aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt197
-rw-r--r--README.md63
-rw-r--r--bin/CMakeLists.txt1
-rw-r--r--cmake/FindDesignerComponents.cmake69
-rw-r--r--cmake/FindGoogleBenchmark.cmake82
-rw-r--r--cmake/FindGoogletest.cmake102
-rw-r--r--cmake/FindQbs.cmake55
-rw-r--r--cmake/QtCreatorIDEBranding.cmake14
-rw-r--r--dist/changes-4.10.0.md229
-rw-r--r--doc/CMakeLists.txt243
-rw-r--r--doc/examples/progressbar/main.cpp1
-rw-r--r--doc/images/creator-compilers-custom.pngbin8324 -> 10140 bytes
-rw-r--r--doc/images/qtcreator-application-output.pngbin10275 -> 10542 bytes
-rw-r--r--doc/images/qtcreator-autotests-options-boost.pngbin0 -> 5636 bytes
-rw-r--r--doc/images/qtcreator-autotests-options-google.pngbin15199 -> 7267 bytes
-rw-r--r--doc/images/qtcreator-autotests-options-qt.pngbin17817 -> 7429 bytes
-rw-r--r--doc/images/qtcreator-autotests-options.pngbin7194 -> 12098 bytes
-rw-r--r--doc/images/qtcreator-autotests.pngbin69724 -> 44003 bytes
-rw-r--r--doc/images/qtcreator-build-issues.pngbin9110 -> 0 bytes
-rw-r--r--doc/images/qtcreator-cmakeexecutable.pngbin28996 -> 11541 bytes
-rw-r--r--doc/images/qtcreator-compile-output.pngbin0 -> 11969 bytes
-rw-r--r--doc/images/qtcreator-compile-pane.pngbin23573 -> 0 bytes
-rw-r--r--doc/images/qtcreator-context-sensitive-help.pngbin57447 -> 65139 bytes
-rw-r--r--doc/images/qtcreator-custom-parser.pngbin13080 -> 11909 bytes
-rw-r--r--doc/images/qtcreator-general-messages.pngbin0 -> 22287 bytes
-rw-r--r--doc/images/qtcreator-help-add-bookmark-dlg.pngbin7064 -> 7964 bytes
-rw-r--r--doc/images/qtcreator-help-filter-attributes.pngbin23049 -> 15403 bytes
-rw-r--r--doc/images/qtcreator-help-filters.pngbin48998 -> 63108 bytes
-rw-r--r--doc/images/qtcreator-help-options.pngbin0 -> 14951 bytes
-rw-r--r--doc/images/qtcreator-help-search.pngbin65662 -> 36520 bytes
-rw-r--r--doc/images/qtcreator-issues.pngbin0 -> 4897 bytes
-rw-r--r--doc/images/qtcreator-kits.pngbin78121 -> 28799 bytes
-rw-r--r--doc/images/qtcreator-language-client-options.pngbin15462 -> 10819 bytes
-rw-r--r--doc/images/qtcreator-parse-build-output.pngbin0 -> 8706 bytes
-rw-r--r--doc/images/qtcreator-qbs-profile-settings.pngbin9918 -> 6708 bytes
-rw-r--r--doc/images/qtcreator-task-pane.pngbin13049 -> 0 bytes
-rw-r--r--doc/images/qtcreator-tests-view.pngbin30506 -> 8796 bytes
-rw-r--r--doc/images/qtcreator-toolchains.pngbin38070 -> 26001 bytes
-rw-r--r--doc/src/cmake/creator-projects-cmake-deploying.qdocinc11
-rw-r--r--doc/src/cmake/creator-projects-cmake.qdoc7
-rw-r--r--doc/src/editors/creator-coding.qdoc10
-rw-r--r--doc/src/editors/creator-locator.qdoc10
-rw-r--r--doc/src/editors/creator-only/creator-code-pasting.qdoc1
-rw-r--r--doc/src/editors/creator-only/creator-language-server.qdoc56
-rw-r--r--doc/src/howto/creator-help.qdoc44
-rw-r--r--doc/src/howto/creator-keyboard-shortcuts.qdoc2
-rw-r--r--doc/src/howto/creator-only/creator-autotest.qdoc108
-rw-r--r--doc/src/howto/creator-sidebar-views.qdoc25
-rw-r--r--doc/src/howto/creator-ui.qdoc141
-rw-r--r--doc/src/overview/creator-acknowledgements.qdoc2
-rw-r--r--doc/src/overview/creator-only/creator-overview.qdoc15
-rw-r--r--doc/src/overview/creator-only/creator-testing.qdoc7
-rw-r--r--doc/src/projects/creator-only/creator-projects-building.qdoc13
-rw-r--r--doc/src/projects/creator-only/creator-projects-compilers.qdoc45
-rw-r--r--doc/src/projects/creator-only/creator-projects-creating.qdoc6
-rw-r--r--doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc42
-rw-r--r--doc/src/projects/creator-only/creator-projects-opening.qdoc4
-rw-r--r--doc/src/projects/creator-only/creator-projects-targets.qdoc41
-rw-r--r--doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc5
-rw-r--r--qbs/imports/QtcProduct.qbs2
-rw-r--r--qbs/modules/libclang/functions.js4
-rw-r--r--qbs/modules/libclang/libclang.qbs7
-rw-r--r--qbs/modules/qtc/qtc.qbs6
-rw-r--r--qtcreator.pri15
-rw-r--r--qtcreator.pro6
-rw-r--r--qtcreator_ide_branding.pri12
-rw-r--r--qtcreatordata.pri5
-rw-r--r--scripts/generateClangFormatChecksUI.py291
-rw-r--r--share/CMakeLists.txt1
-rw-r--r--share/qtcreator/CMakeLists.txt23
-rw-r--r--share/qtcreator/debugger/creatortypes.py32
-rw-r--r--share/qtcreator/debugger/dumper.py16
-rw-r--r--share/qtcreator/debugger/gdbbridge.py37
-rw-r--r--share/qtcreator/debugger/lldbbridge.py2
-rw-r--r--share/qtcreator/debugger/qttypes.py5
-rw-r--r--share/qtcreator/debugger/stdtypes.py37
-rw-r--r--share/qtcreator/indexer_preincludes/QtCore/qconfig.h2
l---------share/qtcreator/indexer_preincludes/QtCore/qglobal.h1
-rw-r--r--share/qtcreator/indexer_preincludes/qglobal.h12
-rw-r--r--share/qtcreator/indexer_preincludes/windows.h6
-rw-r--r--share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp11
-rw-r--r--share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp3
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.cpp1
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp4
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp15
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/ColorEditorTemplate.template3
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/IntEditorTemplate.template18
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/RealEditorTemplate.template21
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/TemplateTypes.qml3
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml9
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml82
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml11
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml21
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml4
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TargetComboBox.qml10
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml75
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml76
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml67
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml41
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml33
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml235
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml55
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml297
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml53
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLogic.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml32
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml70
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml207
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml249
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml58
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml13
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontStyleButtons.qml27
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml25
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml129
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml217
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPropertySpinBox.qml12
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml134
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml108
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml87
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml19
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml120
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml132
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml44
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml51
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml162
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml138
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml256
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml159
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml92
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml31
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml65
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml88
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml46
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml63
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml62
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml32
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml130
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml53
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml34
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml294
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml88
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml338
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml133
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml215
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml144
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml174
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml137
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir29
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml81
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml124
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttfbin0 -> 5280 bytes
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir2
-rw-r--r--share/qtcreator/static.pro3
-rw-r--r--share/qtcreator/templates/qt4project/main.cpp10
-rw-r--r--share/qtcreator/templates/qt4project/mywidget.cpp11
-rw-r--r--share/qtcreator/templates/qt4project/mywidget.h15
-rw-r--r--share/qtcreator/templates/qt4project/mywidget_form.cpp13
-rw-r--r--share/qtcreator/templates/qt4project/mywidget_form.h23
-rw-r--r--share/qtcreator/templates/qt4project/widget.ui20
-rw-r--r--share/qtcreator/templates/wizards/autotest/files/tst.pro20
-rw-r--r--share/qtcreator/templates/wizards/autotest/files/tst.qbs28
-rw-r--r--share/qtcreator/templates/wizards/autotest/files/tst.txt82
-rw-r--r--share/qtcreator/templates/wizards/autotest/files/tst_main.cpp12
-rw-r--r--share/qtcreator/templates/wizards/autotest/files/tst_src.h2
-rw-r--r--share/qtcreator/templates/wizards/autotest/wizard.json83
-rw-r--r--share/qtcreator/templates/wizards/classes/cpp/file.cpp2
-rw-r--r--share/qtcreator/templates/wizards/classes/cpp/wizard.json30
-rw-r--r--share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp2
-rw-r--r--share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp2
-rw-r--r--share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp2
-rw-r--r--share/qtcreator/templates/wizards/classes/itemmodel/wizard.json24
-rw-r--r--share/qtcreator/templates/wizards/classes/python/wizard.json16
-rw-r--r--share/qtcreator/templates/wizards/classes/qtquickui/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/cppheader/wizard.json6
-rw-r--r--share/qtcreator/templates/wizards/files/cppsource/wizard.json6
-rw-r--r--share/qtcreator/templates/wizards/files/form/file.ui2
-rw-r--r--share/qtcreator/templates/wizards/files/form/wizard.json8
-rw-r--r--share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/java/wizard.json6
-rw-r--r--share/qtcreator/templates/wizards/files/js/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/modeling/model/wizard.json12
-rw-r--r--share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/files/nim/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/nimscript/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/python/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/qrc/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/qtquick2/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/files/scratch/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/files/scxml/wizard.json10
-rw-r--r--share/qtcreator/templates/wizards/files/text/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/global/lib.pngbin0 -> 1411 bytes
-rw-r--r--share/qtcreator/templates/wizards/global/lib@2x.pngbin0 -> 2555 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt15
-rw-r--r--share/qtcreator/templates/wizards/projects/consoleapp/wizard.json26
-rw-r--r--share/qtcreator/templates/wizards/projects/cpplibrary/CMakeLists.txt35
-rw-r--r--share/qtcreator/templates/wizards/projects/cpplibrary/lib.cpp17
-rw-r--r--share/qtcreator/templates/wizards/projects/cpplibrary/lib.h46
-rw-r--r--share/qtcreator/templates/wizards/projects/cpplibrary/lib_global.h29
-rw-r--r--share/qtcreator/templates/wizards/projects/cpplibrary/project.json3
-rw-r--r--share/qtcreator/templates/wizards/projects/cpplibrary/project.pro50
-rw-r--r--share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json326
-rw-r--r--share/qtcreator/templates/wizards/projects/nim/wizard.json12
-rw-r--r--share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt7
-rw-r--r--share/qtcreator/templates/wizards/projects/plainc/wizard.json26
-rw-r--r--share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt10
-rw-r--r--share/qtcreator/templates/wizards/projects/plaincpp/wizard.json8
-rw-r--r--share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json8
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json6
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/main.pyproject2
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py28
-rw-r--r--share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json48
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt29
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/app.pro5
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs8
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json116
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json154
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json174
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json174
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json98
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt25
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/main.cpp12
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.pro33
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.qbs29
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.cpp26
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.h38
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.ui24
-rw-r--r--share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json204
-rw-r--r--share/qtcreator/templates/wizards/projects/vcs/bazaar/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/projects/vcs/cvs/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/projects/vcs/git/wizard.json4
-rw-r--r--share/qtcreator/templates/wizards/projects/vcs/mercurial/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/projects/vcs/subversion/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h8
-rw-r--r--share/qtcreator/templates/wizards/qtquick2-extension/object.h4
-rw-r--r--share/qtcreator/translations/extract-mimetypes.xq5
-rw-r--r--share/qtcreator/translations/extract-qmlwizards.xq6
-rw-r--r--share/qtcreator/translations/extract-qtquickwizards.xq6
-rw-r--r--share/qtcreator/translations/qtcreator_ru.ts2
-rw-r--r--share/qtcreator/translations/translations.pro31
-rw-r--r--share/share.qbs3
-rw-r--r--src/CMakeLists.txt556
-rw-r--r--src/app/CMakeLists.txt62
-rw-r--r--src/app/app-Info.plist12
-rw-r--r--src/app/app.pro13
-rw-r--r--src/app/app.qbs8
-rw-r--r--src/app/app_version.h.cmakein53
-rw-r--r--src/app/main.cpp4
-rw-r--r--src/app/qtcreator.rc4
-rw-r--r--src/libs/3rdparty/CMakeLists.txt2
-rw-r--r--src/libs/3rdparty/cplusplus/CMakeLists.txt46
-rw-r--r--src/libs/3rdparty/syntax-highlighting/.gitignore3
-rw-r--r--src/libs/3rdparty/syntax-highlighting/CMakeLists.txt173
-rw-r--r--src/libs/3rdparty/syntax-highlighting/CMakeLists.txt.kde140
-rw-r--r--src/libs/3rdparty/syntax-highlighting/README.md17
-rw-r--r--src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h6
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml27
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml4
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml86
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml2
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml73
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml9
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml52
-rw-r--r--src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml9
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp4
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp88
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt1
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp77
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp83
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h12
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp54
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp45
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h9
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp40
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/repository.h8
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp8
-rw-r--r--src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp8
-rw-r--r--src/libs/3rdparty/variant/variant.hpp9
-rw-r--r--src/libs/CMakeLists.txt21
-rw-r--r--src/libs/aggregation/CMakeLists.txt6
-rw-r--r--src/libs/aggregation/examples/text/main.cpp2
-rw-r--r--src/libs/clangsupport/CMakeLists.txt137
-rw-r--r--src/libs/clangsupport/clangsupport-lib.pri8
-rw-r--r--src/libs/clangsupport/commandlinebuilder.h24
-rw-r--r--src/libs/clangsupport/connectionclient.cpp2
-rw-r--r--src/libs/clangsupport/connectionserver.h8
-rw-r--r--src/libs/clangsupport/environment.h47
-rw-r--r--src/libs/clangsupport/executeinloop.h33
-rw-r--r--src/libs/clangsupport/generatedfiles.cpp28
-rw-r--r--src/libs/clangsupport/ipcserverinterface.cpp31
-rw-r--r--src/libs/clangsupport/modifiedtimechecker.h215
-rw-r--r--src/libs/clangsupport/modifiedtimecheckerinterface.h47
-rw-r--r--src/libs/clangsupport/pchmanagerclientproxy.h3
-rw-r--r--src/libs/clangsupport/pchpaths.h52
-rw-r--r--src/libs/clangsupport/precompiledheadersupdatedmessage.h31
-rw-r--r--src/libs/clangsupport/projectpartartefact.cpp2
-rw-r--r--src/libs/clangsupport/projectpartartefact.h4
-rw-r--r--src/libs/clangsupport/projectpartcontainer.h7
-rw-r--r--src/libs/clangsupport/projectpartid.h2
-rw-r--r--src/libs/clangsupport/projectpartpch.cpp3
-rw-r--r--src/libs/clangsupport/projectpartpch.h3
-rw-r--r--src/libs/clangsupport/projectpartpchproviderinterface.h50
-rw-r--r--src/libs/clangsupport/projectpartsstorage.h35
-rw-r--r--src/libs/clangsupport/projectpartsstorageinterface.h1
-rw-r--r--src/libs/clangsupport/refactoringdatabaseinitializer.h2
-rw-r--r--src/libs/clangsupport/sourceentry.h152
-rw-r--r--src/libs/cplusplus/CMakeLists.txt44
-rw-r--r--src/libs/cplusplus/CppDocument.cpp17
-rw-r--r--src/libs/cplusplus/CppDocument.h28
-rw-r--r--src/libs/cplusplus/DependencyTable.cpp8
-rw-r--r--src/libs/cplusplus/DependencyTable.h6
-rw-r--r--src/libs/cplusplus/FindUsages.cpp2
-rw-r--r--src/libs/cplusplus/FindUsages.h4
-rw-r--r--src/libs/cplusplus/MatchingText.cpp29
-rw-r--r--src/libs/extensionsystem/CMakeLists.txt16
-rw-r--r--src/libs/extensionsystem/iplugin.cpp6
-rw-r--r--src/libs/extensionsystem/iplugin.h2
-rw-r--r--src/libs/extensionsystem/optionsparser.cpp12
-rw-r--r--src/libs/extensionsystem/pluginerroroverview.cpp2
-rw-r--r--src/libs/extensionsystem/pluginmanager.cpp71
-rw-r--r--src/libs/extensionsystem/pluginmanager.h12
-rw-r--r--src/libs/extensionsystem/pluginmanager_p.h28
-rw-r--r--src/libs/extensionsystem/pluginspec.cpp6
-rw-r--r--src/libs/extensionsystem/pluginspec_p.h4
-rw-r--r--src/libs/extensionsystem/pluginview.cpp24
-rw-r--r--src/libs/glsl/CMakeLists.txt19
-rw-r--r--src/libs/glsl/glslparser.h2
-rw-r--r--src/libs/languageserverprotocol/CMakeLists.txt23
-rw-r--r--src/libs/languageserverprotocol/basemessage.cpp16
-rw-r--r--src/libs/languageserverprotocol/basemessage.h3
-rw-r--r--src/libs/languageserverprotocol/clientcapabilities.cpp53
-rw-r--r--src/libs/languageserverprotocol/clientcapabilities.h31
-rw-r--r--src/libs/languageserverprotocol/icontent.h5
-rw-r--r--src/libs/languageserverprotocol/initializemessages.cpp31
-rw-r--r--src/libs/languageserverprotocol/jsonkeys.h1
-rw-r--r--src/libs/languageserverprotocol/jsonobject.cpp4
-rw-r--r--src/libs/languageserverprotocol/jsonrpcmessages.h1
-rw-r--r--src/libs/languageserverprotocol/languagefeatures.cpp55
-rw-r--r--src/libs/languageserverprotocol/languagefeatures.h45
-rw-r--r--src/libs/languageserverprotocol/lsptypes.cpp30
-rw-r--r--src/libs/languageserverprotocol/lsptypes.h34
-rw-r--r--src/libs/languageserverprotocol/lsputils.h2
-rw-r--r--src/libs/languageserverprotocol/servercapabilities.cpp2
-rw-r--r--src/libs/languageserverprotocol/servercapabilities.h4
-rw-r--r--src/libs/languageserverprotocol/textsynchronization.h2
-rw-r--r--src/libs/languageserverprotocol/workspace.cpp10
-rw-r--r--src/libs/languageserverprotocol/workspace.h11
-rw-r--r--src/libs/languageutils/CMakeLists.txt7
-rw-r--r--src/libs/libs.pro4
-rw-r--r--src/libs/modelinglib/CMakeLists.txt196
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp7
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h6
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp16
-rw-r--r--src/libs/qmldebug/CMakeLists.txt18
-rw-r--r--src/libs/qmldebug/baseenginedebugclient.cpp2
-rw-r--r--src/libs/qmldebug/qmldebugcommandlinearguments.h14
-rw-r--r--src/libs/qmldebug/qmldebugconnection.cpp54
-rw-r--r--src/libs/qmldebug/qmldebugconnection.h9
-rw-r--r--src/libs/qmleditorwidgets/CMakeLists.txt22
-rw-r--r--src/libs/qmleditorwidgets/colorbox.cpp6
-rw-r--r--src/libs/qmleditorwidgets/contextpanetextwidget.cpp5
-rw-r--r--src/libs/qmleditorwidgets/customcolordialog.cpp12
-rw-r--r--src/libs/qmljs/CMakeLists.txt53
-rw-r--r--src/libs/qmljs/parser/qmljslexer.cpp67
-rw-r--r--src/libs/qmljs/parser/qmljslexer_p.h3
-rw-r--r--src/libs/qmljs/persistenttrie.cpp1
-rw-r--r--src/libs/qmljs/persistenttrie.h1
-rw-r--r--src/libs/qmljs/qmljs-lib.pri2
-rw-r--r--src/libs/qmljs/qmljs.qbs1
-rw-r--r--src/libs/qmljs/qmljsbundle.cpp5
-rw-r--r--src/libs/qmljs/qmljsbundle.h1
-rw-r--r--src/libs/qmljs/qmljscheck.cpp59
-rw-r--r--src/libs/qmljs/qmljsdialect.cpp7
-rw-r--r--src/libs/qmljs/qmljsdialect.h14
-rw-r--r--src/libs/qmljs/qmljsdocument.cpp8
-rw-r--r--src/libs/qmljs/qmljsdocument.h1
-rw-r--r--src/libs/qmljs/qmljsimportdependencies.cpp6
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp10
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h1
-rw-r--r--src/libs/qmljs/qmljslink.cpp5
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp14
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h6
-rw-r--r--src/libs/qmljs/qmljsqrcparser.cpp556
-rw-r--r--src/libs/qmljs/qmljsqrcparser.h85
-rw-r--r--src/libs/qmljs/qmljsreformatter.cpp76
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp3
-rw-r--r--src/libs/qtcreatorcdbext/CMakeLists.txt46
-rw-r--r--src/libs/qtcreatorcdbext/common.h13
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbext.pro2
-rw-r--r--src/libs/sqlite/CMakeLists.txt27
-rw-r--r--src/libs/sqlite/README.md13
-rw-r--r--src/libs/sqlite/sqlite-lib.pri6
-rw-r--r--src/libs/sqlite/sqlite-source.pri3
-rw-r--r--src/libs/sqlite/sqlitecolumn.cpp31
-rw-r--r--src/libs/sqlite/sqlitedatabase.h24
-rw-r--r--src/libs/sqlite/sqlitedatabasebackend.cpp21
-rw-r--r--src/libs/sqlite/sqlitedatabasebackend.h2
-rw-r--r--src/libs/sqlite/sqlitedatabaseinterface.h37
-rw-r--r--src/libs/sqlite/sqlitetable.cpp32
-rw-r--r--src/libs/sqlite/sqlstatementbuilderexception.cpp34
-rw-r--r--src/libs/ssh/CMakeLists.txt22
-rw-r--r--src/libs/ssh/sftpfilesystemmodel.cpp5
-rw-r--r--src/libs/ssh/sftpsession.cpp9
-rw-r--r--src/libs/ssh/sftptransfer.cpp2
-rw-r--r--src/libs/ssh/ssh.qrc2
-rw-r--r--src/libs/ssh/sshconnection.cpp8
-rw-r--r--src/libs/ssh/sshconnection.h2
-rw-r--r--src/libs/ssh/sshremoteprocess.cpp10
-rw-r--r--src/libs/ssh/sshremoteprocess.h6
-rw-r--r--src/libs/ssh/sshremoteprocessrunner.cpp11
-rw-r--r--src/libs/ssh/sshremoteprocessrunner.h8
-rw-r--r--src/libs/ssh/sshsettings.cpp48
-rw-r--r--src/libs/ssh/sshsettings.h18
-rw-r--r--src/libs/tracing/CMakeLists.txt35
-rw-r--r--src/libs/tracing/timelineabstractrenderer.h1
-rw-r--r--src/libs/tracing/timelinemodel_p.h4
-rw-r--r--src/libs/tracing/timelinerenderer.h1
-rw-r--r--src/libs/tracing/tracestashfile.h2
-rw-r--r--src/libs/utils/CMakeLists.txt204
-rw-r--r--src/libs/utils/algorithm.h409
-rw-r--r--src/libs/utils/basetreeview.cpp9
-rw-r--r--src/libs/utils/buildablehelperlibrary.cpp76
-rw-r--r--src/libs/utils/buildablehelperlibrary.h7
-rw-r--r--src/libs/utils/checkablemessagebox.cpp60
-rw-r--r--src/libs/utils/checkablemessagebox.h7
-rw-r--r--src/libs/utils/completingtextedit.cpp2
-rw-r--r--src/libs/utils/consoleprocess.h4
-rw-r--r--src/libs/utils/consoleprocess_unix.cpp12
-rw-r--r--src/libs/utils/consoleprocess_win.cpp4
-rw-r--r--src/libs/utils/cpplanguage_details.h3
-rw-r--r--src/libs/utils/delegates.cpp2
-rw-r--r--src/libs/utils/detailsbutton.cpp2
-rw-r--r--src/libs/utils/elidinglabel.cpp2
-rw-r--r--src/libs/utils/environment.cpp49
-rw-r--r--src/libs/utils/environment.h13
-rw-r--r--src/libs/utils/filecrumblabel.cpp10
-rw-r--r--src/libs/utils/filecrumblabel.h4
-rw-r--r--src/libs/utils/fileinprojectfinder.cpp193
-rw-r--r--src/libs/utils/fileinprojectfinder.h47
-rw-r--r--src/libs/utils/filesearch.cpp2
-rw-r--r--src/libs/utils/fileutils.cpp424
-rw-r--r--src/libs/utils/fileutils.h137
-rw-r--r--src/libs/utils/genericconstants.h37
-rw-r--r--src/libs/utils/highlightingitemdelegate.cpp3
-rw-r--r--src/libs/utils/images/dir.png (renamed from src/libs/ssh/images/dir.png)bin862 -> 862 bytes
-rw-r--r--src/libs/utils/images/pinned.pngbin0 -> 168 bytes
-rw-r--r--src/libs/utils/images/pinned@2x.pngbin0 -> 267 bytes
-rw-r--r--src/libs/utils/images/settings.pngbin0 -> 177 bytes
-rw-r--r--src/libs/utils/images/settings@2x.pngbin0 -> 316 bytes
-rw-r--r--src/libs/utils/images/sort_alphabetically.png (renamed from src/plugins/autotest/images/sort.png)bin139 -> 139 bytes
-rw-r--r--src/libs/utils/images/sort_alphabetically@2x.png (renamed from src/plugins/autotest/images/sort@2x.png)bin205 -> 205 bytes
-rw-r--r--src/libs/utils/images/toggleprogressdetails.pngbin0 -> 167 bytes
-rw-r--r--src/libs/utils/images/toggleprogressdetails@2x.pngbin0 -> 216 bytes
-rw-r--r--src/libs/utils/images/unknownfile.png (renamed from src/libs/ssh/images/unknownfile.png)bin345 -> 345 bytes
-rw-r--r--src/libs/utils/listmodel.h183
-rw-r--r--src/libs/utils/macroexpander.cpp30
-rw-r--r--src/libs/utils/macroexpander.h3
-rw-r--r--src/libs/utils/mimetypes/mimeprovider.cpp4
-rw-r--r--src/libs/utils/newclasswidget.cpp2
-rw-r--r--src/libs/utils/outputformatter.cpp3
-rw-r--r--src/libs/utils/outputformatter.h3
-rw-r--r--src/libs/utils/pathchooser.cpp20
-rw-r--r--src/libs/utils/pathchooser.h14
-rw-r--r--src/libs/utils/persistentsettings.cpp6
-rw-r--r--src/libs/utils/persistentsettings.h8
-rw-r--r--src/libs/utils/projectintropage.cpp2
-rw-r--r--src/libs/utils/qrcparser.cpp556
-rw-r--r--src/libs/utils/qrcparser.h85
-rw-r--r--src/libs/utils/qtcprocess.cpp11
-rw-r--r--src/libs/utils/qtcprocess.h13
-rw-r--r--src/libs/utils/reloadpromptutils.cpp7
-rw-r--r--src/libs/utils/reloadpromptutils.h4
-rw-r--r--src/libs/utils/runextensions.h57
-rw-r--r--src/libs/utils/savedaction.cpp2
-rw-r--r--src/libs/utils/savefile.cpp2
-rw-r--r--src/libs/utils/settingsaccessor.cpp59
-rw-r--r--src/libs/utils/settingsaccessor.h46
-rw-r--r--src/libs/utils/settingsselector.cpp2
-rw-r--r--src/libs/utils/shellcommand.cpp16
-rw-r--r--src/libs/utils/shellcommand.h14
-rw-r--r--src/libs/utils/smallstringlayout.h7
-rw-r--r--src/libs/utils/stringutils.cpp2
-rw-r--r--src/libs/utils/stylehelper.cpp14
-rw-r--r--src/libs/utils/synchronousprocess.cpp3
-rw-r--r--src/libs/utils/textfieldcombobox.cpp2
-rw-r--r--src/libs/utils/touchbar/touchbar.pri1
-rw-r--r--src/libs/utils/touchbar/touchbar_mac.mm10
-rw-r--r--src/libs/utils/unixutils.cpp2
-rw-r--r--src/libs/utils/utils-lib.pri8
-rw-r--r--src/libs/utils/utils.qbs5
-rw-r--r--src/libs/utils/utils.qrc10
-rw-r--r--src/libs/utils/utilsicons.cpp19
-rw-r--r--src/libs/utils/utilsicons.h7
-rw-r--r--src/libs/utils/variant.h19
-rw-r--r--src/libs/utils/wizardpage.h36
-rw-r--r--src/plugins/CMakeLists.txt84
-rw-r--r--src/plugins/android/CMakeLists.txt52
-rw-r--r--src/plugins/android/android.pro11
-rw-r--r--src/plugins/android/android.qbs7
-rw-r--r--src/plugins/android/androidavdmanager.cpp13
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp130
-rw-r--r--src/plugins/android/androidbuildapkstep.h7
-rw-r--r--src/plugins/android/androidbuildapkwidget.cpp441
-rw-r--r--src/plugins/android/androidbuildapkwidget.h56
-rw-r--r--src/plugins/android/androidbuildapkwidget.ui217
-rw-r--r--src/plugins/android/androidconfigurations.cpp290
-rw-r--r--src/plugins/android/androidconfigurations.h51
-rw-r--r--src/plugins/android/androidconstants.h15
-rw-r--r--src/plugins/android/androidcreatekeystorecertificate.cpp4
-rw-r--r--src/plugins/android/androidcreatekeystorecertificate.h4
-rw-r--r--src/plugins/android/androiddebugsupport.cpp36
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp151
-rw-r--r--src/plugins/android/androiddeployqtstep.h15
-rw-r--r--src/plugins/android/androiddevice.cpp18
-rw-r--r--src/plugins/android/androiddevice.h9
-rw-r--r--src/plugins/android/androiddevicedialog.cpp2
-rw-r--r--src/plugins/android/androiddevicefactory.cpp45
-rw-r--r--src/plugins/android/androiddevicefactory.h41
-rw-r--r--src/plugins/android/androidgdbserverkitinformation.cpp125
-rw-r--r--src/plugins/android/androidgdbserverkitinformation.h51
-rw-r--r--src/plugins/android/androidmanager.cpp111
-rw-r--r--src/plugins/android/androidmanager.h24
-rw-r--r--src/plugins/android/androidmanifesteditorwidget.cpp32
-rw-r--r--src/plugins/android/androidmanifesteditorwidget.h2
-rw-r--r--src/plugins/android/androidpackageinstallationstep.cpp9
-rw-r--r--src/plugins/android/androidplugin.cpp51
-rw-r--r--src/plugins/android/androidplugin.h8
-rw-r--r--src/plugins/android/androidpotentialkit.cpp4
-rw-r--r--src/plugins/android/androidqmltoolingsupport.h2
-rw-r--r--src/plugins/android/androidqtversion.cpp47
-rw-r--r--src/plugins/android/androidqtversion.h15
-rw-r--r--src/plugins/android/androidqtversionfactory.cpp76
-rw-r--r--src/plugins/android/androidqtversionfactory.h47
-rw-r--r--src/plugins/android/androidrunconfiguration.cpp23
-rw-r--r--src/plugins/android/androidrunconfiguration.h1
-rw-r--r--src/plugins/android/androidrunenvironmentaspect.cpp47
-rw-r--r--src/plugins/android/androidrunenvironmentaspect.h42
-rw-r--r--src/plugins/android/androidrunner.cpp2
-rw-r--r--src/plugins/android/androidrunner.h2
-rw-r--r--src/plugins/android/androidrunnerworker.cpp35
-rw-r--r--src/plugins/android/androidsdkmanager.cpp8
-rw-r--r--src/plugins/android/androidsdkpackage.cpp4
-rw-r--r--src/plugins/android/androidsdkpackage.h6
-rw-r--r--src/plugins/android/androidsettingswidget.cpp18
-rw-r--r--src/plugins/android/androidsignaloperation.cpp6
-rw-r--r--src/plugins/android/androidtoolchain.cpp86
-rw-r--r--src/plugins/android/androidtoolchain.h14
-rw-r--r--src/plugins/android/androidtoolmanager.cpp25
-rw-r--r--src/plugins/android/androidtoolmanager.h6
-rw-r--r--src/plugins/android/avddialog.cpp6
-rw-r--r--src/plugins/android/createandroidmanifestwizard.cpp37
-rw-r--r--src/plugins/android/javaparser.cpp13
-rw-r--r--src/plugins/android/javaparser.h8
-rw-r--r--src/plugins/autotest/CMakeLists.txt80
-rw-r--r--src/plugins/autotest/autotest.pro20
-rw-r--r--src/plugins/autotest/autotest.qbs7
-rw-r--r--src/plugins/autotest/autotest.qrc5
-rw-r--r--src/plugins/autotest/autotesticons.h2
-rw-r--r--src/plugins/autotest/autotestplugin.cpp14
-rw-r--r--src/plugins/autotest/autotestplugin.h3
-rw-r--r--src/plugins/autotest/autotestunittests.cpp67
-rw-r--r--src/plugins/autotest/autotestunittests.h9
-rw-r--r--src/plugins/autotest/autotestunittests.qrc17
-rw-r--r--src/plugins/autotest/boost/boostcodeparser.cpp422
-rw-r--r--src/plugins/autotest/boost/boostcodeparser.h82
-rw-r--r--src/plugins/autotest/boost/boosttestconfiguration.cpp154
-rw-r--r--src/plugins/autotest/boost/boosttestconfiguration.h44
-rw-r--r--src/plugins/autotest/boost/boosttestconstants.h41
-rw-r--r--src/plugins/autotest/boost/boosttestframework.cpp76
-rw-r--r--src/plugins/autotest/boost/boosttestframework.h48
-rw-r--r--src/plugins/autotest/boost/boosttestoutputreader.cpp457
-rw-r--r--src/plugins/autotest/boost/boosttestoutputreader.h68
-rw-r--r--src/plugins/autotest/boost/boosttestparser.cpp184
-rw-r--r--src/plugins/autotest/boost/boosttestparser.h51
-rw-r--r--src/plugins/autotest/boost/boosttestresult.cpp76
-rw-r--r--src/plugins/autotest/boost/boosttestresult.h49
-rw-r--r--src/plugins/autotest/boost/boosttestsettings.cpp97
-rw-r--r--src/plugins/autotest/boost/boosttestsettings.h81
-rw-r--r--src/plugins/autotest/boost/boosttestsettingspage.cpp117
-rw-r--r--src/plugins/autotest/boost/boosttestsettingspage.h69
-rw-r--r--src/plugins/autotest/boost/boosttestsettingspage.ui163
-rw-r--r--src/plugins/autotest/boost/boosttesttreeitem.cpp365
-rw-r--r--src/plugins/autotest/boost/boosttesttreeitem.h107
-rw-r--r--src/plugins/autotest/gtest/gtestoutputreader.cpp129
-rw-r--r--src/plugins/autotest/gtest/gtestoutputreader.h8
-rw-r--r--src/plugins/autotest/gtest/gtestparser.cpp12
-rw-r--r--src/plugins/autotest/gtest/gtestresult.cpp45
-rw-r--r--src/plugins/autotest/gtest/gtestresult.h11
-rw-r--r--src/plugins/autotest/gtest/gtesttreeitem.cpp75
-rw-r--r--src/plugins/autotest/gtest/gtesttreeitem.h3
-rw-r--r--src/plugins/autotest/gtest/gtestvisitors.cpp2
-rw-r--r--src/plugins/autotest/images/data@2x.pngbin0 -> 1199 bytes
-rw-r--r--src/plugins/autotest/images/suite.pngbin0 -> 306 bytes
-rw-r--r--src/plugins/autotest/images/suite@2x.pngbin0 -> 501 bytes
-rw-r--r--src/plugins/autotest/itestparser.cpp5
-rw-r--r--src/plugins/autotest/itestparser.h2
-rw-r--r--src/plugins/autotest/qtest/qttestoutputreader.cpp47
-rw-r--r--src/plugins/autotest/qtest/qttestoutputreader.h4
-rw-r--r--src/plugins/autotest/qtest/qttestparser.cpp4
-rw-r--r--src/plugins/autotest/qtest/qttestresult.cpp25
-rw-r--r--src/plugins/autotest/qtest/qttestresult.h1
-rw-r--r--src/plugins/autotest/qtest/qttesttreeitem.cpp20
-rw-r--r--src/plugins/autotest/qtest/qttesttreeitem.h2
-rw-r--r--src/plugins/autotest/qtest/qttestvisitors.cpp2
-rw-r--r--src/plugins/autotest/quick/quicktestparser.cpp4
-rw-r--r--src/plugins/autotest/quick/quicktesttreeitem.cpp24
-rw-r--r--src/plugins/autotest/quick/quicktesttreeitem.h2
-rw-r--r--src/plugins/autotest/quick/quicktestvisitors.cpp2
-rw-r--r--src/plugins/autotest/testcodeparser.cpp27
-rw-r--r--src/plugins/autotest/testconfiguration.cpp18
-rw-r--r--src/plugins/autotest/testconfiguration.h2
-rw-r--r--src/plugins/autotest/testeditormark.cpp2
-rw-r--r--src/plugins/autotest/testeditormark.h2
-rw-r--r--src/plugins/autotest/testnavigationwidget.cpp3
-rw-r--r--src/plugins/autotest/testoutputreader.cpp4
-rw-r--r--src/plugins/autotest/testoutputreader.h7
-rw-r--r--src/plugins/autotest/testresult.cpp141
-rw-r--r--src/plugins/autotest/testresult.h59
-rw-r--r--src/plugins/autotest/testresultdelegate.cpp12
-rw-r--r--src/plugins/autotest/testresultdelegate.h2
-rw-r--r--src/plugins/autotest/testresultmodel.cpp261
-rw-r--r--src/plugins/autotest/testresultmodel.h30
-rw-r--r--src/plugins/autotest/testresultspane.cpp81
-rw-r--r--src/plugins/autotest/testrunner.cpp118
-rw-r--r--src/plugins/autotest/testrunner.h3
-rw-r--r--src/plugins/autotest/testsettings.cpp15
-rw-r--r--src/plugins/autotest/testsettings.h5
-rw-r--r--src/plugins/autotest/testsettingspage.cpp160
-rw-r--r--src/plugins/autotest/testsettingspage.h5
-rw-r--r--src/plugins/autotest/testsettingspage.ui153
-rw-r--r--src/plugins/autotest/testtreeitem.cpp18
-rw-r--r--src/plugins/autotest/testtreeitem.h11
-rw-r--r--src/plugins/autotest/testtreemodel.cpp41
-rw-r--r--src/plugins/autotest/testtreemodel.h4
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/simple_boost.pro2
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/simple_boost.qbs5
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/src/main.cpp6
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/src/src.pro4
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/src/src.qbs6
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.pro8
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.qbs11
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/deco/enab.h23
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/deco/main.cpp21
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.cpp18
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.pro7
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.qbs11
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/params/main.cpp41
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/params/params.pro7
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/params/params.qbs11
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/tests.pro2
-rw-r--r--src/plugins/autotest/unit_test/simple_boost/tests/tests.qbs11
-rw-r--r--src/plugins/autotest/unit_test/simple_gt/tests/common/functions.js26
-rw-r--r--src/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.qbs12
-rw-r--r--src/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.qbs12
-rw-r--r--src/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h1
-rw-r--r--src/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.qbs12
-rw-r--r--src/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp4
-rw-r--r--src/plugins/autotoolsprojectmanager/CMakeLists.txt15
-rw-r--r--src/plugins/autotoolsprojectmanager/autogenstep.cpp10
-rw-r--r--src/plugins/autotoolsprojectmanager/autoreconfstep.cpp10
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp27
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.h5
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.cpp81
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.h64
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsproject.cpp20
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsproject.h5
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro5
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs4
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsprojectnode.cpp44
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsprojectnode.h57
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp6
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h4
-rw-r--r--src/plugins/autotoolsprojectmanager/configurestep.cpp8
-rw-r--r--src/plugins/baremetal/CMakeLists.txt30
-rw-r--r--src/plugins/baremetal/baremetal.pro18
-rw-r--r--src/plugins/baremetal/baremetal.qbs8
-rw-r--r--src/plugins/baremetal/baremetalconstants.h5
-rw-r--r--src/plugins/baremetal/baremetalcustomrunconfiguration.cpp9
-rw-r--r--src/plugins/baremetal/baremetalcustomrunconfiguration.h18
-rw-r--r--src/plugins/baremetal/baremetaldebugsupport.cpp29
-rw-r--r--src/plugins/baremetal/baremetaldebugsupport.h8
-rw-r--r--src/plugins/baremetal/baremetaldevice.cpp33
-rw-r--r--src/plugins/baremetal/baremetaldevice.h40
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationfactory.cpp58
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationfactory.h45
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp10
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwidget.h8
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp8
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwizard.h8
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.cpp6
-rw-r--r--src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.h12
-rw-r--r--src/plugins/baremetal/baremetalgdbcommandsdeploystep.cpp6
-rw-r--r--src/plugins/baremetal/baremetalgdbcommandsdeploystep.h23
-rw-r--r--src/plugins/baremetal/baremetalplugin.cpp34
-rw-r--r--src/plugins/baremetal/baremetalplugin.h20
-rw-r--r--src/plugins/baremetal/baremetalrunconfiguration.cpp7
-rw-r--r--src/plugins/baremetal/baremetalrunconfiguration.h13
-rw-r--r--src/plugins/baremetal/defaultgdbserverprovider.cpp26
-rw-r--r--src/plugins/baremetal/defaultgdbserverprovider.h23
-rw-r--r--src/plugins/baremetal/gdbserverprovider.cpp62
-rw-r--r--src/plugins/baremetal/gdbserverprovider.h37
-rw-r--r--src/plugins/baremetal/gdbserverproviderchooser.cpp16
-rw-r--r--src/plugins/baremetal/gdbserverproviderchooser.h8
-rw-r--r--src/plugins/baremetal/gdbserverprovidermanager.cpp14
-rw-r--r--src/plugins/baremetal/gdbserverprovidermanager.h16
-rw-r--r--src/plugins/baremetal/gdbserverproviderprocess.cpp9
-rw-r--r--src/plugins/baremetal/gdbserverproviderprocess.h28
-rw-r--r--src/plugins/baremetal/gdbserverproviderssettingspage.cpp81
-rw-r--r--src/plugins/baremetal/gdbserverproviderssettingspage.h16
-rw-r--r--src/plugins/baremetal/iarewparser.cpp450
-rw-r--r--src/plugins/baremetal/iarewparser.h64
-rw-r--r--src/plugins/baremetal/iarewtoolchain.cpp594
-rw-r--r--src/plugins/baremetal/iarewtoolchain.h139
-rw-r--r--src/plugins/baremetal/keilparser.cpp516
-rw-r--r--src/plugins/baremetal/keilparser.h57
-rw-r--r--src/plugins/baremetal/keiltoolchain.cpp596
-rw-r--r--src/plugins/baremetal/keiltoolchain.h139
-rw-r--r--src/plugins/baremetal/openocdgdbserverprovider.cpp85
-rw-r--r--src/plugins/baremetal/openocdgdbserverprovider.h35
-rw-r--r--src/plugins/baremetal/sdccparser.cpp339
-rw-r--r--src/plugins/baremetal/sdccparser.h57
-rw-r--r--src/plugins/baremetal/sdcctoolchain.cpp564
-rw-r--r--src/plugins/baremetal/sdcctoolchain.h139
-rw-r--r--src/plugins/baremetal/stlinkutilgdbserverprovider.cpp80
-rw-r--r--src/plugins/baremetal/stlinkutilgdbserverprovider.h46
-rw-r--r--src/plugins/bazaar/CMakeLists.txt19
-rw-r--r--src/plugins/bazaar/bazaarclient.cpp2
-rw-r--r--src/plugins/bazaar/bazaarclient.h2
-rw-r--r--src/plugins/bazaar/bazaarcontrol.cpp6
-rw-r--r--src/plugins/bazaar/bazaarcontrol.h4
-rw-r--r--src/plugins/beautifier/CMakeLists.txt27
-rw-r--r--src/plugins/beautifier/abstractsettings.cpp5
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyle.cpp41
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyle.h8
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp6
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstylesettings.h4
-rw-r--r--src/plugins/beautifier/beautifierabstracttool.h1
-rw-r--r--src/plugins/beautifier/beautifierconstants.h1
-rw-r--r--src/plugins/beautifier/beautifierplugin.cpp4
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.cpp39
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.h11
-rw-r--r--src/plugins/beautifier/configurationeditor.cpp2
-rw-r--r--src/plugins/beautifier/configurationpanel.cpp2
-rw-r--r--src/plugins/beautifier/generalsettings.cpp15
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustify.cpp43
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustify.h9
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifysettings.cpp9
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifysettings.h4
-rw-r--r--src/plugins/bineditor/CMakeLists.txt10
-rw-r--r--src/plugins/bineditor/bineditorplugin.cpp8
-rw-r--r--src/plugins/bineditor/bineditorplugin.h2
-rw-r--r--src/plugins/bineditor/bineditorwidget.cpp34
-rw-r--r--src/plugins/bookmarks/CMakeLists.txt9
-rw-r--r--src/plugins/bookmarks/bookmark.cpp6
-rw-r--r--src/plugins/bookmarks/bookmark.h2
-rw-r--r--src/plugins/bookmarks/bookmarkmanager.cpp23
-rw-r--r--src/plugins/bookmarks/bookmarkmanager.h10
-rw-r--r--src/plugins/bookmarks/bookmarksplugin.cpp30
-rw-r--r--src/plugins/bookmarks/bookmarksplugin.h7
-rw-r--r--src/plugins/clangcodemodel/CMakeLists.txt57
-rw-r--r--src/plugins/clangcodemodel/a.cmd4
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalitem.cpp32
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalitem.h2
-rw-r--r--src/plugins/clangcodemodel/clangcodemodelplugin.cpp24
-rw-r--r--src/plugins/clangcodemodel/clangcodemodelplugin.h7
-rw-r--r--src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp4
-rw-r--r--src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h2
-rw-r--r--src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp2
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticmanager.cpp8
-rw-r--r--src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp4
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp10
-rw-r--r--src/plugins/clangcodemodel/clangfollowsymbol.cpp2
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.cpp2
-rw-r--r--src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp5
-rw-r--r--src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h2
-rw-r--r--src/plugins/clangcodemodel/clangprojectsettingswidget.cpp2
-rw-r--r--src/plugins/clangcodemodel/clangtextmark.cpp2
-rw-r--r--src/plugins/clangcodemodel/clangtextmark.h2
-rw-r--r--src/plugins/clangcodemodel/clangutils.cpp29
-rw-r--r--src/plugins/clangcodemodel/clangutils.h16
-rw-r--r--src/plugins/clangformat/CMakeLists.txt15
-rw-r--r--src/plugins/clangformat/clangformat.pro3
-rw-r--r--src/plugins/clangformat/clangformat.qbs9
-rw-r--r--src/plugins/clangformat/clangformatchecks.ui3299
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.cpp386
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.h19
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.ui44
-rw-r--r--src/plugins/clangformat/clangformatplugin.cpp10
-rw-r--r--src/plugins/clangformat/clangformatplugin.h5
-rw-r--r--src/plugins/clangformat/clangformatutils.cpp66
-rw-r--r--src/plugins/clangformat/clangformatutils.h7
-rw-r--r--src/plugins/clangpchmanager/CMakeLists.txt17
-rw-r--r--src/plugins/clangpchmanager/clangpchmanagerplugin.cpp2
-rw-r--r--src/plugins/clangpchmanager/pchmanagerclient.cpp63
-rw-r--r--src/plugins/clangpchmanager/pchmanagerclient.h21
-rw-r--r--src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp3
-rw-r--r--src/plugins/clangpchmanager/pchmanagernotifierinterface.h5
-rw-r--r--src/plugins/clangpchmanager/projectupdater.cpp19
-rw-r--r--src/plugins/clangpchmanager/qtcreatorprojectupdater.h6
-rw-r--r--src/plugins/clangrefactoring/CMakeLists.txt40
-rw-r--r--src/plugins/clangrefactoring/clangrefactoring.qbs7
-rw-r--r--src/plugins/clangrefactoring/locatorfilter.cpp2
-rw-r--r--src/plugins/clangrefactoring/refactoringconnectionclient.cpp5
-rw-r--r--src/plugins/clangrefactoring/refactoringprojectupdater.cpp4
-rw-r--r--src/plugins/clangrefactoring/refactoringprojectupdater.h4
-rw-r--r--src/plugins/clangtools/CMakeLists.txt41
-rw-r--r--src/plugins/clangtools/clangfileinfo.h4
-rw-r--r--src/plugins/clangtools/clangfixitsrefactoringchanges.cpp2
-rw-r--r--src/plugins/clangtools/clangselectablefilesdialog.cpp27
-rw-r--r--src/plugins/clangtools/clangtidyclazyrunner.cpp8
-rw-r--r--src/plugins/clangtools/clangtidyclazytool.cpp6
-rw-r--r--src/plugins/clangtools/clangtidyclazytool.h2
-rw-r--r--src/plugins/clangtools/clangtool.cpp2
-rw-r--r--src/plugins/clangtools/clangtool.h4
-rw-r--r--src/plugins/clangtools/clangtoolruncontrol.cpp22
-rw-r--r--src/plugins/clangtools/clangtoolruncontrol.h2
-rw-r--r--src/plugins/clangtools/clangtoolrunner.cpp2
-rw-r--r--src/plugins/clangtools/clangtools.qbs1
-rw-r--r--src/plugins/clangtools/clangtoolsconfigwidget.cpp5
-rw-r--r--src/plugins/clangtools/clangtoolsdiagnosticmodel.h2
-rw-r--r--src/plugins/clangtools/clangtoolsdiagnosticview.cpp4
-rw-r--r--src/plugins/clangtools/clangtoolslogfilereader.cpp8
-rw-r--r--src/plugins/clangtools/clangtoolslogfilereader.h4
-rw-r--r--src/plugins/clangtools/clangtoolsplugin.cpp4
-rw-r--r--src/plugins/clangtools/clangtoolsplugin.h2
-rw-r--r--src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp8
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettings.cpp22
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettings.h16
-rw-r--r--src/plugins/clangtools/clangtoolsunittests.cpp6
-rw-r--r--src/plugins/clangtools/clangtoolsutils.cpp23
-rw-r--r--src/plugins/clangtools/clangtoolsutils.h3
-rw-r--r--src/plugins/classview/CMakeLists.txt15
-rw-r--r--src/plugins/classview/classviewparser.cpp8
-rw-r--r--src/plugins/clearcase/CMakeLists.txt18
-rw-r--r--src/plugins/clearcase/ClearCase.mimetypes.xml7
-rw-r--r--src/plugins/clearcase/activityselector.cpp6
-rw-r--r--src/plugins/clearcase/clearcasecontrol.cpp2
-rw-r--r--src/plugins/clearcase/clearcasecontrol.h2
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp8
-rw-r--r--src/plugins/cmakeprojectmanager/CMakeLists.txt42
-rw-r--r--src/plugins/cmakeprojectmanager/builddirmanager.cpp19
-rw-r--r--src/plugins/cmakeprojectmanager/builddirmanager.h6
-rw-r--r--src/plugins/cmakeprojectmanager/builddirparameters.cpp19
-rw-r--r--src/plugins/cmakeprojectmanager/builddirparameters.h9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp92
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp4
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.cpp51
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.h9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp46
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildtarget.h14
-rw-r--r--src/plugins/cmakeprojectmanager/cmakecbpparser.cpp44
-rw-r--r--src/plugins/cmakeprojectmanager/cmakecbpparser.h12
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp8
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeconfigitem.h5
-rw-r--r--src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp5
-rw-r--r--src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp493
-rw-r--r--src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h142
-rw-r--r--src/plugins/cmakeprojectmanager/cmakekitinformation.cpp610
-rw-r--r--src/plugins/cmakeprojectmanager/cmakekitinformation.h45
-rw-r--r--src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeparser.cpp52
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp107
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.h15
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectconstants.h2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp96
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectimporter.h6
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp116
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.h9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro9
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs7
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp121
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectnodes.h31
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp18
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectplugin.h3
-rw-r--r--src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp36
-rw-r--r--src/plugins/cmakeprojectmanager/cmakesettingspage.cpp14
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.cpp11
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.h8
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp6
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketoolmanager.h6
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp28
-rw-r--r--src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp4
-rw-r--r--src/plugins/cmakeprojectmanager/configmodelitemdelegate.h4
-rw-r--r--src/plugins/cmakeprojectmanager/servermode.cpp36
-rw-r--r--src/plugins/cmakeprojectmanager/servermode.h10
-rw-r--r--src/plugins/cmakeprojectmanager/servermodereader.cpp132
-rw-r--r--src/plugins/cmakeprojectmanager/servermodereader.h24
-rw-r--r--src/plugins/cmakeprojectmanager/tealeafreader.cpp82
-rw-r--r--src/plugins/cmakeprojectmanager/tealeafreader.h2
-rw-r--r--src/plugins/cmakeprojectmanager/treescanner.cpp180
-rw-r--r--src/plugins/cmakeprojectmanager/treescanner.h104
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/CMakeLists.txt16
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseconstants.h1
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp405
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h51
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.pro6
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.qbs2
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.cpp50
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.h6
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp1
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp35
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h25
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp228
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h78
-rw-r--r--src/plugins/coreplugin/CMakeLists.txt185
-rw-r--r--src/plugins/coreplugin/corejsextensions.cpp2
-rw-r--r--src/plugins/coreplugin/coreplugin.cpp2
-rw-r--r--src/plugins/coreplugin/coreplugin.qbs2
-rw-r--r--src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp6
-rw-r--r--src/plugins/coreplugin/dialogs/filepropertiesdialog.h2
-rw-r--r--src/plugins/coreplugin/dialogs/newdialog.cpp2
-rw-r--r--src/plugins/coreplugin/dialogs/openwithdialog.cpp2
-rw-r--r--src/plugins/coreplugin/dialogs/openwithdialog.h2
-rw-r--r--src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp102
-rw-r--r--src/plugins/coreplugin/dialogs/readonlyfilesdialog.h6
-rw-r--r--src/plugins/coreplugin/dialogs/saveitemsdialog.cpp2
-rw-r--r--src/plugins/coreplugin/dialogs/saveitemsdialog.h1
-rw-r--r--src/plugins/coreplugin/dialogs/settingsdialog.cpp2
-rw-r--r--src/plugins/coreplugin/dialogs/shortcutsettings.cpp2
-rw-r--r--src/plugins/coreplugin/documentmanager.cpp16
-rw-r--r--src/plugins/coreplugin/documentmanager.h12
-rw-r--r--src/plugins/coreplugin/editormanager/documentmodel.cpp107
-rw-r--r--src/plugins/coreplugin/editormanager/documentmodel.h16
-rw-r--r--src/plugins/coreplugin/editormanager/documentmodel_p.h18
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp123
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.h7
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager_p.h3
-rw-r--r--src/plugins/coreplugin/editormanager/editorview.cpp2
-rw-r--r--src/plugins/coreplugin/editormanager/openeditorsview.cpp6
-rw-r--r--src/plugins/coreplugin/editormanager/openeditorswindow.cpp2
-rw-r--r--src/plugins/coreplugin/editortoolbar.cpp11
-rw-r--r--src/plugins/coreplugin/externaltool.cpp4
-rw-r--r--src/plugins/coreplugin/externaltool.h2
-rw-r--r--src/plugins/coreplugin/fancyactionbar.cpp8
-rw-r--r--src/plugins/coreplugin/fancytabwidget.cpp2
-rw-r--r--src/plugins/coreplugin/fileutils.cpp11
-rw-r--r--src/plugins/coreplugin/fileutils.h3
-rw-r--r--src/plugins/coreplugin/find/find.pri2
-rw-r--r--src/plugins/coreplugin/find/findtoolbar.cpp73
-rw-r--r--src/plugins/coreplugin/find/findtoolbar.h19
-rw-r--r--src/plugins/coreplugin/find/findtoolwindow.cpp7
-rw-r--r--src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp2
-rw-r--r--src/plugins/coreplugin/find/optionspopup.cpp110
-rw-r--r--src/plugins/coreplugin/find/optionspopup.h59
-rw-r--r--src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp150
-rw-r--r--src/plugins/coreplugin/find/searchresulttreeitemdelegate.h15
-rw-r--r--src/plugins/coreplugin/find/searchresulttreemodel.cpp2
-rw-r--r--src/plugins/coreplugin/find/searchresulttreeview.cpp9
-rw-r--r--src/plugins/coreplugin/find/searchresulttreeview.h1
-rw-r--r--src/plugins/coreplugin/find/searchresultwidget.cpp4
-rw-r--r--src/plugins/coreplugin/find/searchresultwindow.cpp5
-rw-r--r--src/plugins/coreplugin/icore.cpp11
-rw-r--r--src/plugins/coreplugin/icore.h11
-rw-r--r--src/plugins/coreplugin/idocument.cpp8
-rw-r--r--src/plugins/coreplugin/idocument.h8
-rw-r--r--src/plugins/coreplugin/infobar.h1
-rw-r--r--src/plugins/coreplugin/ioutputpane.h45
-rw-r--r--src/plugins/coreplugin/iversioncontrol.cpp2
-rw-r--r--src/plugins/coreplugin/iversioncontrol.h10
-rw-r--r--src/plugins/coreplugin/jsexpander.cpp63
-rw-r--r--src/plugins/coreplugin/jsexpander.h35
-rw-r--r--src/plugins/coreplugin/locator/basefilefilter.cpp2
-rw-r--r--src/plugins/coreplugin/locator/directoryfilter.cpp170
-rw-r--r--src/plugins/coreplugin/locator/directoryfilter.h29
-rw-r--r--src/plugins/coreplugin/locator/directoryfilter.ui37
-rw-r--r--src/plugins/coreplugin/locator/executefilter.cpp6
-rw-r--r--src/plugins/coreplugin/locator/filesystemfilter.cpp3
-rw-r--r--src/plugins/coreplugin/locator/locator.cpp25
-rw-r--r--src/plugins/coreplugin/locator/locator.h5
-rw-r--r--src/plugins/coreplugin/locator/locator_test.cpp2
-rw-r--r--src/plugins/coreplugin/locator/locatorwidget.cpp7
-rw-r--r--src/plugins/coreplugin/locator/opendocumentsfilter.cpp2
-rw-r--r--src/plugins/coreplugin/locator/opendocumentsfilter.h2
-rw-r--r--src/plugins/coreplugin/mainwindow.cpp41
-rw-r--r--src/plugins/coreplugin/manhattanstyle.cpp6
-rw-r--r--src/plugins/coreplugin/messagemanager.cpp31
-rw-r--r--src/plugins/coreplugin/messagemanager.h9
-rw-r--r--src/plugins/coreplugin/messageoutputwindow.cpp25
-rw-r--r--src/plugins/coreplugin/messageoutputwindow.h8
-rw-r--r--src/plugins/coreplugin/mimetypemagicdialog.cpp2
-rw-r--r--src/plugins/coreplugin/mimetypesettings.cpp10
-rw-r--r--src/plugins/coreplugin/navigationsubwidget.cpp2
-rw-r--r--src/plugins/coreplugin/navigationwidget.cpp2
-rw-r--r--src/plugins/coreplugin/outputpanemanager.cpp144
-rw-r--r--src/plugins/coreplugin/outputwindow.cpp116
-rw-r--r--src/plugins/coreplugin/outputwindow.h17
-rw-r--r--src/plugins/coreplugin/patchtool.cpp2
-rw-r--r--src/plugins/coreplugin/progressmanager/futureprogress.cpp28
-rw-r--r--src/plugins/coreplugin/progressmanager/futureprogress.h7
-rw-r--r--src/plugins/coreplugin/progressmanager/progressbar.cpp60
-rw-r--r--src/plugins/coreplugin/progressmanager/progressbar.h5
-rw-r--r--src/plugins/coreplugin/progressmanager/progressmanager.cpp56
-rw-r--r--src/plugins/coreplugin/progressmanager/progressmanager_p.h11
-rw-r--r--src/plugins/coreplugin/rightpane.cpp5
-rw-r--r--src/plugins/coreplugin/rightpane.h1
-rw-r--r--src/plugins/coreplugin/shellcommand.cpp9
-rw-r--r--src/plugins/coreplugin/shellcommand.h9
-rw-r--r--src/plugins/coreplugin/sidebarwidget.cpp2
-rw-r--r--src/plugins/coreplugin/systemsettings.cpp4
-rw-r--r--src/plugins/coreplugin/toolsettings.cpp2
-rw-r--r--src/plugins/cpaster/CMakeLists.txt31
-rw-r--r--src/plugins/cpaster/authenticationdialog.cpp64
-rw-r--r--src/plugins/cpaster/authenticationdialog.h53
-rw-r--r--src/plugins/cpaster/columnindicatortextedit.cpp2
-rw-r--r--src/plugins/cpaster/cpaster.pro10
-rw-r--r--src/plugins/cpaster/cpaster.qbs6
-rw-r--r--src/plugins/cpaster/cpasterplugin.cpp2
-rw-r--r--src/plugins/cpaster/frontend/argumentscollector.cpp2
-rw-r--r--src/plugins/cpaster/frontend/frontend.pro2
-rw-r--r--src/plugins/cpaster/frontend/frontend.qbs1
-rw-r--r--src/plugins/cpaster/frontend/main.cpp8
-rw-r--r--src/plugins/cpaster/kdepasteprotocol.cpp394
-rw-r--r--src/plugins/cpaster/kdepasteprotocol.h102
-rw-r--r--src/plugins/cpaster/pasteselectdialog.cpp2
-rw-r--r--src/plugins/cpaster/pasteview.cpp2
-rw-r--r--src/plugins/cpaster/protocol.cpp31
-rw-r--r--src/plugins/cpaster/protocol.h8
-rw-r--r--src/plugins/cpaster/stickynotespasteprotocol.cpp269
-rw-r--r--src/plugins/cpaster/stickynotespasteprotocol.h71
-rw-r--r--src/plugins/cppcheck/CMakeLists.txt14
-rw-r--r--src/plugins/cppcheck/cppcheckdiagnostic.h2
-rw-r--r--src/plugins/cppcheck/cppcheckrunner.cpp22
-rw-r--r--src/plugins/cppcheck/cppcheckrunner.h16
-rw-r--r--src/plugins/cppcheck/cppchecktextmarkmanager.cpp4
-rw-r--r--src/plugins/cppcheck/cppchecktextmarkmanager.h4
-rw-r--r--src/plugins/cppcheck/cppchecktool.cpp18
-rw-r--r--src/plugins/cppcheck/cppchecktool.h10
-rw-r--r--src/plugins/cppcheck/cppchecktrigger.cpp14
-rw-r--r--src/plugins/cppcheck/cppchecktrigger.h10
-rw-r--r--src/plugins/cppeditor/CMakeLists.txt47
-rw-r--r--src/plugins/cppeditor/cppcodemodelinspectordialog.cpp9
-rw-r--r--src/plugins/cppeditor/cppeditordocument.cpp4
-rw-r--r--src/plugins/cppeditor/cppeditordocument.h2
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp7
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.h2
-rw-r--r--src/plugins/cppeditor/cppeditorwidget.cpp4
-rw-r--r--src/plugins/cppeditor/cppoutline.cpp1
-rw-r--r--src/plugins/cppeditor/cppoutline.h1
-rw-r--r--src/plugins/cppeditor/cppparsecontext.cpp8
-rw-r--r--src/plugins/cppeditor/cpppreprocessordialog.cpp2
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp17
-rw-r--r--src/plugins/cppeditor/resourcepreviewhoverhandler.cpp4
-rw-r--r--src/plugins/cpptools/CMakeLists.txt131
-rw-r--r--src/plugins/cpptools/abstracteditorsupport.cpp2
-rw-r--r--src/plugins/cpptools/baseeditordocumentparser.cpp2
-rw-r--r--src/plugins/cpptools/builtineditordocumentparser.cpp16
-rw-r--r--src/plugins/cpptools/builtineditordocumentparser.h4
-rw-r--r--src/plugins/cpptools/builtinindexingsupport.cpp7
-rw-r--r--src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp6
-rw-r--r--src/plugins/cpptools/clangdiagnosticconfigswidget.cpp6
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.cpp14
-rw-r--r--src/plugins/cpptools/cppclassesfilter.cpp2
-rw-r--r--src/plugins/cpptools/cppcodemodelinspectordumper.cpp60
-rw-r--r--src/plugins/cpptools/cppcodemodelinspectordumper.h1
-rw-r--r--src/plugins/cpptools/cppcompletionassist.cpp24
-rw-r--r--src/plugins/cpptools/cppcompletionassist.h1
-rw-r--r--src/plugins/cpptools/cppcurrentdocumentfilter.cpp2
-rw-r--r--src/plugins/cpptools/cppeditoroutline.cpp4
-rw-r--r--src/plugins/cpptools/cppelementevaluator.cpp2
-rw-r--r--src/plugins/cpptools/cppfindreferences.cpp28
-rw-r--r--src/plugins/cpptools/cppfunctionsfilter.cpp4
-rw-r--r--src/plugins/cpptools/cppheadersource_test.cpp2
-rw-r--r--src/plugins/cpptools/cppincludesfilter.cpp4
-rw-r--r--src/plugins/cpptools/cppkitinfo.cpp6
-rw-r--r--src/plugins/cpptools/cpplocatorfilter.cpp2
-rw-r--r--src/plugins/cpptools/cpplocatorfilter_test.cpp4
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp23
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h6
-rw-r--r--src/plugins/cpptools/cppmodelmanager_test.cpp8
-rw-r--r--src/plugins/cpptools/cppprojectinfogenerator.cpp17
-rw-r--r--src/plugins/cpptools/cpptools_clangtidychecks.h85
-rw-r--r--src/plugins/cpptools/cpptoolsconstants.h2
-rw-r--r--src/plugins/cpptools/cpptoolsjsextension.cpp48
-rw-r--r--src/plugins/cpptools/cpptoolsjsextension.h5
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp8
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.h4
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.cpp12
-rw-r--r--src/plugins/cpptools/cpptoolstestcase.cpp4
-rw-r--r--src/plugins/cpptools/cppworkingcopy.h26
-rw-r--r--src/plugins/cpptools/cursorineditor.h6
-rw-r--r--src/plugins/cpptools/doxygengenerator.cpp2
-rw-r--r--src/plugins/cpptools/doxygengenerator.h4
-rw-r--r--src/plugins/cpptools/generatedcodemodelsupport.cpp6
-rw-r--r--src/plugins/cpptools/generatedcodemodelsupport.h6
-rw-r--r--src/plugins/cpptools/headerpathfilter.cpp15
-rw-r--r--src/plugins/cpptools/headerpathfilter.h2
-rw-r--r--src/plugins/cpptools/indexitem.cpp2
-rw-r--r--src/plugins/cpptools/modelmanagertesthelper.cpp2
-rw-r--r--src/plugins/cpptools/symbolsfindfilter.cpp4
-rw-r--r--src/plugins/cpptools/typehierarchybuilder.cpp4
-rw-r--r--src/plugins/cvs/CMakeLists.txt13
-rw-r--r--src/plugins/cvs/cvscontrol.cpp6
-rw-r--r--src/plugins/cvs/cvscontrol.h4
-rw-r--r--src/plugins/cvs/cvsplugin.cpp2
-rw-r--r--src/plugins/debugger/CMakeLists.txt109
-rw-r--r--src/plugins/debugger/analyzer/analyzerrunconfigwidget.cpp2
-rw-r--r--src/plugins/debugger/analyzer/startremotedialog.cpp6
-rw-r--r--src/plugins/debugger/breakhandler.cpp14
-rw-r--r--src/plugins/debugger/breakhandler.h4
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp20
-rw-r--r--src/plugins/debugger/cdb/cdbengine.h9
-rw-r--r--src/plugins/debugger/cdb/cdbparsehelpers.cpp2
-rw-r--r--src/plugins/debugger/console/console.cpp3
-rw-r--r--src/plugins/debugger/console/consoleitemdelegate.cpp4
-rw-r--r--src/plugins/debugger/console/consoleitemmodel.cpp4
-rw-r--r--src/plugins/debugger/console/consoleview.cpp3
-rw-r--r--src/plugins/debugger/debugger.pro2
-rw-r--r--src/plugins/debugger/debugger.qbs1
-rw-r--r--src/plugins/debugger/debugger.qrc2
-rw-r--r--src/plugins/debugger/debuggerconstants.h73
-rw-r--r--src/plugins/debugger/debuggerdialogs.cpp35
-rw-r--r--src/plugins/debugger/debuggerengine.cpp15
-rw-r--r--src/plugins/debugger/debuggerengine.h43
-rw-r--r--src/plugins/debugger/debuggericons.cpp4
-rw-r--r--src/plugins/debugger/debuggericons.h1
-rw-r--r--src/plugins/debugger/debuggerinternalconstants.h50
-rw-r--r--src/plugins/debugger/debuggeritem.cpp19
-rw-r--r--src/plugins/debugger/debuggeritem.h18
-rw-r--r--src/plugins/debugger/debuggeritemmanager.cpp80
-rw-r--r--src/plugins/debugger/debuggeritemmanager.h4
-rw-r--r--src/plugins/debugger/debuggerkitconfigwidget.cpp162
-rw-r--r--src/plugins/debugger/debuggerkitconfigwidget.h81
-rw-r--r--src/plugins/debugger/debuggerkitinformation.cpp180
-rw-r--r--src/plugins/debugger/debuggerkitinformation.h14
-rw-r--r--src/plugins/debugger/debuggermainwindow.cpp41
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp167
-rw-r--r--src/plugins/debugger/debuggerplugin.h2
-rw-r--r--src/plugins/debugger/debuggerrunconfigurationaspect.cpp9
-rw-r--r--src/plugins/debugger/debuggerrunconfigurationaspect.h6
-rw-r--r--src/plugins/debugger/debuggerruncontrol.cpp70
-rw-r--r--src/plugins/debugger/debuggerruncontrol.h10
-rw-r--r--src/plugins/debugger/debuggersourcepathmappingwidget.cpp6
-rw-r--r--src/plugins/debugger/debuggertooltipmanager.cpp9
-rw-r--r--src/plugins/debugger/disassembleragent.cpp4
-rw-r--r--src/plugins/debugger/enginemanager.cpp5
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp32
-rw-r--r--src/plugins/debugger/images/debugger_stop.pngbin0 -> 1304 bytes
-rw-r--r--src/plugins/debugger/images/debugger_stop@2x.pngbin0 -> 4662 bytes
-rw-r--r--src/plugins/debugger/images/debugger_stop_32.pngbin1342 -> 0 bytes
-rw-r--r--src/plugins/debugger/lldb/lldbengine.cpp8
-rw-r--r--src/plugins/debugger/loadcoredialog.cpp10
-rw-r--r--src/plugins/debugger/pdb/pdbengine.cpp2
-rw-r--r--src/plugins/debugger/qml/qmlcppengine.cpp692
-rw-r--r--src/plugins/debugger/qml/qmlcppengine.h129
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp2
-rw-r--r--src/plugins/debugger/qml/qmlinspectoragent.cpp1
-rw-r--r--src/plugins/debugger/registerhandler.cpp2
-rw-r--r--src/plugins/debugger/sourceagent.cpp4
-rw-r--r--src/plugins/debugger/stackhandler.cpp2
-rw-r--r--src/plugins/debugger/terminal.h2
-rw-r--r--src/plugins/debugger/unstartedappwatcherdialog.cpp4
-rw-r--r--src/plugins/debugger/watchdata.cpp7
-rw-r--r--src/plugins/debugger/watchdata.h1
-rw-r--r--src/plugins/debugger/watchhandler.cpp40
-rw-r--r--src/plugins/debugger/watchhandler.h2
-rw-r--r--src/plugins/debugger/watchwindow.cpp11
-rw-r--r--src/plugins/debugger/watchwindow.h1
-rw-r--r--src/plugins/designer/CMakeLists.txt42
-rw-r--r--src/plugins/designer/codemodelhelpers.cpp2
-rw-r--r--src/plugins/designer/formtemplatewizardpage.cpp2
-rw-r--r--src/plugins/designer/formwindowfile.cpp6
-rw-r--r--src/plugins/designer/formwindowfile.h2
-rw-r--r--src/plugins/designer/qtcreatorintegration.cpp13
-rw-r--r--src/plugins/designer/resourcehandler.cpp24
-rw-r--r--src/plugins/diffeditor/CMakeLists.txt22
-rw-r--r--src/plugins/diffeditor/diffeditor.cpp8
-rw-r--r--src/plugins/diffeditor/diffeditordocument.cpp4
-rw-r--r--src/plugins/diffeditor/sidebysidediffeditorwidget.cpp2
-rw-r--r--src/plugins/emacskeys/CMakeLists.txt7
-rw-r--r--src/plugins/fakevim/CMakeLists.txt19
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp25
-rw-r--r--src/plugins/fakevim/fakevimplugin.cpp2
-rw-r--r--src/plugins/genericprojectmanager/CMakeLists.txt22
-rw-r--r--src/plugins/genericprojectmanager/filesselectionwizardpage.cpp8
-rw-r--r--src/plugins/genericprojectmanager/filesselectionwizardpage.h4
-rw-r--r--src/plugins/genericprojectmanager/genericbuildconfiguration.cpp63
-rw-r--r--src/plugins/genericprojectmanager/genericbuildconfiguration.h24
-rw-r--r--src/plugins/genericprojectmanager/genericproject.cpp80
-rw-r--r--src/plugins/genericprojectmanager/genericproject.h5
-rw-r--r--src/plugins/genericprojectmanager/genericprojectplugin.cpp2
-rw-r--r--src/plugins/genericprojectmanager/genericprojectwizard.cpp8
-rw-r--r--src/plugins/genericprojectmanager/genericprojectwizard.h4
-rw-r--r--src/plugins/git/CMakeLists.txt41
-rw-r--r--src/plugins/git/branchadddialog.cpp34
-rw-r--r--src/plugins/git/branchadddialog.h9
-rw-r--r--src/plugins/git/branchadddialog.ui6
-rw-r--r--src/plugins/git/branchmodel.cpp101
-rw-r--r--src/plugins/git/branchmodel.h2
-rw-r--r--src/plugins/git/branchview.cpp22
-rw-r--r--src/plugins/git/branchview.h2
-rw-r--r--src/plugins/git/changeselectiondialog.h2
-rw-r--r--src/plugins/git/gerrit/gerritdialog.cpp2
-rw-r--r--src/plugins/git/gerrit/gerritmodel.cpp8
-rw-r--r--src/plugins/git/gerrit/gerritparameters.cpp7
-rw-r--r--src/plugins/git/gerrit/gerritplugin.cpp14
-rw-r--r--src/plugins/git/gerrit/gerritplugin.h2
-rw-r--r--src/plugins/git/gerrit/gerritpushdialog.cpp4
-rw-r--r--src/plugins/git/gerrit/gerritserver.cpp6
-rw-r--r--src/plugins/git/gitclient.cpp58
-rw-r--r--src/plugins/git/gitclient.h6
-rw-r--r--src/plugins/git/gitconstants.h1
-rw-r--r--src/plugins/git/giteditor.cpp71
-rw-r--r--src/plugins/git/gitgrep.cpp17
-rw-r--r--src/plugins/git/gitgrep.h3
-rw-r--r--src/plugins/git/gitsettings.cpp4
-rw-r--r--src/plugins/git/gitsettings.h2
-rw-r--r--src/plugins/git/gitversioncontrol.cpp4
-rw-r--r--src/plugins/git/gitversioncontrol.h4
-rw-r--r--src/plugins/git/mergetool.cpp2
-rw-r--r--src/plugins/glsleditor/CMakeLists.txt13
-rw-r--r--src/plugins/helloworld/CMakeLists.txt6
-rw-r--r--src/plugins/help/CMakeLists.txt48
-rw-r--r--src/plugins/help/centralwidget.h1
-rw-r--r--src/plugins/help/generalsettingspage.cpp13
-rw-r--r--src/plugins/help/generalsettingspage.h2
-rw-r--r--src/plugins/help/generalsettingspage.ui7
-rw-r--r--src/plugins/help/help.pro1
-rw-r--r--src/plugins/help/helpplugin.cpp5
-rw-r--r--src/plugins/help/helpviewer.cpp20
-rw-r--r--src/plugins/help/helpviewer.h6
-rw-r--r--src/plugins/help/helpwidget.cpp2
-rw-r--r--src/plugins/help/localhelpmanager.cpp12
-rw-r--r--src/plugins/help/localhelpmanager.h4
-rw-r--r--src/plugins/help/macwebkithelpviewer.mm1
-rw-r--r--src/plugins/help/openpagesmanager.cpp2
-rw-r--r--src/plugins/help/textbrowserhelpviewer.cpp10
-rw-r--r--src/plugins/help/textbrowserhelpviewer.h1
-rw-r--r--src/plugins/help/webenginehelpviewer.cpp25
-rw-r--r--src/plugins/help/webenginehelpviewer.h3
-rw-r--r--src/plugins/imageviewer/CMakeLists.txt15
-rw-r--r--src/plugins/imageviewer/exportdialog.cpp8
-rw-r--r--src/plugins/imageviewer/imageview.cpp1
-rw-r--r--src/plugins/imageviewer/imageviewerfile.cpp2
-rw-r--r--src/plugins/imageviewer/multiexportdialog.cpp2
-rw-r--r--src/plugins/ios/CMakeLists.txt32
-rw-r--r--src/plugins/ios/createsimulatordialog.cpp2
-rw-r--r--src/plugins/ios/ios.pro12
-rw-r--r--src/plugins/ios/ios.qbs12
-rw-r--r--src/plugins/ios/iosbuildconfiguration.cpp422
-rw-r--r--src/plugins/ios/iosbuildconfiguration.h10
-rw-r--r--src/plugins/ios/iosbuildsettingswidget.cpp296
-rw-r--r--src/plugins/ios/iosbuildsettingswidget.h78
-rw-r--r--src/plugins/ios/iosbuildsettingswidget.ui137
-rw-r--r--src/plugins/ios/iosbuildstep.cpp16
-rw-r--r--src/plugins/ios/iosconfigurations.cpp95
-rw-r--r--src/plugins/ios/iosconfigurations.h17
-rw-r--r--src/plugins/ios/iosconstants.h3
-rw-r--r--src/plugins/ios/iosdeploystep.cpp34
-rw-r--r--src/plugins/ios/iosdeploystep.h3
-rw-r--r--src/plugins/ios/iosdeploystepwidget.cpp55
-rw-r--r--src/plugins/ios/iosdeploystepwidget.h51
-rw-r--r--src/plugins/ios/iosdeploystepwidget.ui26
-rw-r--r--src/plugins/ios/iosdevice.cpp46
-rw-r--r--src/plugins/ios/iosdevice.h27
-rw-r--r--src/plugins/ios/iosdevicefactory.cpp54
-rw-r--r--src/plugins/ios/iosdevicefactory.h43
-rw-r--r--src/plugins/ios/iosdsymbuildstep.cpp12
-rw-r--r--src/plugins/ios/iosplugin.cpp23
-rw-r--r--src/plugins/ios/iosprobe.cpp8
-rw-r--r--src/plugins/ios/iosprobe.h10
-rw-r--r--src/plugins/ios/iosqtversion.cpp34
-rw-r--r--src/plugins/ios/iosqtversion.h13
-rw-r--r--src/plugins/ios/iosqtversionfactory.cpp73
-rw-r--r--src/plugins/ios/iosqtversionfactory.h48
-rw-r--r--src/plugins/ios/iosrunconfiguration.cpp66
-rw-r--r--src/plugins/ios/iosrunconfiguration.h7
-rw-r--r--src/plugins/ios/iosrunner.cpp25
-rw-r--r--src/plugins/ios/iossettingswidget.cpp2
-rw-r--r--src/plugins/ios/iossimulator.cpp45
-rw-r--r--src/plugins/ios/iossimulator.h25
-rw-r--r--src/plugins/ios/iossimulatorfactory.cpp47
-rw-r--r--src/plugins/ios/iossimulatorfactory.h41
-rw-r--r--src/plugins/ios/iostoolhandler.cpp28
-rw-r--r--src/plugins/ios/simulatorcontrol.cpp20
-rw-r--r--src/plugins/ios/simulatorcontrol.h6
-rw-r--r--src/plugins/languageclient/CMakeLists.txt21
-rw-r--r--src/plugins/languageclient/LanguageClient.json.in1
-rw-r--r--src/plugins/languageclient/client.cpp294
-rw-r--r--src/plugins/languageclient/client.h26
-rw-r--r--src/plugins/languageclient/documentsymbolcache.cpp81
-rw-r--r--src/plugins/languageclient/documentsymbolcache.h58
-rw-r--r--src/plugins/languageclient/images/languageclient.pngbin0 -> 199 bytes
-rw-r--r--src/plugins/languageclient/images/languageclient@2x.pngbin0 -> 360 bytes
-rw-r--r--src/plugins/languageclient/languageclient.pro12
-rw-r--r--src/plugins/languageclient/languageclient.qbs8
-rw-r--r--src/plugins/languageclient/languageclient.qrc2
-rw-r--r--src/plugins/languageclient/languageclient_global.h9
-rw-r--r--src/plugins/languageclient/languageclientcompletionassist.cpp37
-rw-r--r--src/plugins/languageclient/languageclientfunctionhint.cpp144
-rw-r--r--src/plugins/languageclient/languageclientfunctionhint.h53
-rw-r--r--src/plugins/languageclient/languageclienthoverhandler.cpp148
-rw-r--r--src/plugins/languageclient/languageclienthoverhandler.h59
-rw-r--r--src/plugins/languageclient/languageclientinterface.cpp13
-rw-r--r--src/plugins/languageclient/languageclientmanager.cpp270
-rw-r--r--src/plugins/languageclient/languageclientmanager.h26
-rw-r--r--src/plugins/languageclient/languageclientoutline.cpp88
-rw-r--r--src/plugins/languageclient/languageclientplugin.cpp23
-rw-r--r--src/plugins/languageclient/languageclientplugin.h6
-rw-r--r--src/plugins/languageclient/languageclientquickfix.cpp2
-rw-r--r--src/plugins/languageclient/languageclientsettings.cpp253
-rw-r--r--src/plugins/languageclient/languageclientsettings.h52
-rw-r--r--src/plugins/languageclient/languageclientutils.cpp86
-rw-r--r--src/plugins/languageclient/languageclientutils.h4
-rw-r--r--src/plugins/languageclient/locatorfilter.cpp316
-rw-r--r--src/plugins/languageclient/locatorfilter.h119
-rw-r--r--src/plugins/macros/CMakeLists.txt19
-rw-r--r--src/plugins/macros/macrolocatorfilter.cpp4
-rw-r--r--src/plugins/macros/macrolocatorfilter.h2
-rw-r--r--src/plugins/macros/macromanager.cpp33
-rw-r--r--src/plugins/macros/macromanager.h15
-rw-r--r--src/plugins/macros/macrooptionspage.cpp3
-rw-r--r--src/plugins/macros/macrooptionspage.h2
-rw-r--r--src/plugins/macros/macrooptionswidget.h1
-rw-r--r--src/plugins/macros/macrosplugin.cpp32
-rw-r--r--src/plugins/macros/macrosplugin.h10
-rw-r--r--src/plugins/mercurial/CMakeLists.txt18
-rw-r--r--src/plugins/mercurial/mercurialclient.cpp2
-rw-r--r--src/plugins/mercurial/mercurialclient.h2
-rw-r--r--src/plugins/mercurial/mercurialcontrol.cpp6
-rw-r--r--src/plugins/mercurial/mercurialcontrol.h4
-rw-r--r--src/plugins/modeleditor/CMakeLists.txt36
-rw-r--r--src/plugins/modeleditor/jsextension.h2
-rw-r--r--src/plugins/modeleditor/modeldocument.cpp4
-rw-r--r--src/plugins/modeleditor/modeleditor.cpp2
-rw-r--r--src/plugins/modeleditor/modeleditor_plugin.cpp2
-rw-r--r--src/plugins/modeleditor/modelindexer.cpp8
-rw-r--r--src/plugins/modeleditor/modelsmanager.cpp2
-rw-r--r--src/plugins/modeleditor/pxnodeutilities.cpp18
-rw-r--r--src/plugins/nim/CMakeLists.txt35
-rw-r--r--src/plugins/nim/editor/nimcompletionassistprovider.cpp4
-rw-r--r--src/plugins/nim/nim.pro2
-rw-r--r--src/plugins/nim/nim.qbs1
-rw-r--r--src/plugins/nim/nimconstants.h8
-rw-r--r--src/plugins/nim/nimplugin.cpp2
-rw-r--r--src/plugins/nim/project/nimbuildconfiguration.cpp53
-rw-r--r--src/plugins/nim/project/nimbuildconfiguration.h10
-rw-r--r--src/plugins/nim/project/nimbuildconfigurationwidget.cpp85
-rw-r--r--src/plugins/nim/project/nimbuildconfigurationwidget.h58
-rw-r--r--src/plugins/nim/project/nimcompilerbuildstep.cpp39
-rw-r--r--src/plugins/nim/project/nimcompilerbuildstep.h16
-rw-r--r--src/plugins/nim/project/nimcompilerbuildstepconfigwidget.cpp10
-rw-r--r--src/plugins/nim/project/nimcompilercleanstep.cpp2
-rw-r--r--src/plugins/nim/project/nimcompilercleanstep.h2
-rw-r--r--src/plugins/nim/project/nimproject.cpp17
-rw-r--r--src/plugins/nim/project/nimproject.h6
-rw-r--r--src/plugins/nim/project/nimprojectnode.cpp12
-rw-r--r--src/plugins/nim/project/nimprojectnode.h4
-rw-r--r--src/plugins/nim/project/nimrunconfiguration.cpp12
-rw-r--r--src/plugins/nim/project/nimtoolchain.cpp36
-rw-r--r--src/plugins/nim/project/nimtoolchain.h17
-rw-r--r--src/plugins/nim/project/nimtoolchainfactory.cpp49
-rw-r--r--src/plugins/nim/project/nimtoolchainfactory.h7
-rw-r--r--src/plugins/nim/settings/nimtoolssettingspage.cpp10
-rw-r--r--src/plugins/nim/settings/nimtoolssettingspage.h4
-rw-r--r--src/plugins/nim/suggest/nimsuggestcache.cpp2
-rw-r--r--src/plugins/nim/suggest/nimsuggestcache.h4
-rw-r--r--src/plugins/nim/suggest/server.cpp8
-rw-r--r--src/plugins/perforce/CMakeLists.txt17
-rw-r--r--src/plugins/perforce/perforcechecker.cpp2
-rw-r--r--src/plugins/perforce/perforceplugin.cpp2
-rw-r--r--src/plugins/perforce/perforceversioncontrol.cpp2
-rw-r--r--src/plugins/perforce/perforceversioncontrol.h2
-rw-r--r--src/plugins/perfprofiler/CMakeLists.txt41
-rw-r--r--src/plugins/perfprofiler/perfconfigwidget.cpp8
-rw-r--r--src/plugins/perfprofiler/perfdatareader.cpp19
-rw-r--r--src/plugins/perfprofiler/perfdatareader.h9
-rw-r--r--src/plugins/perfprofiler/perfevent.h78
-rw-r--r--src/plugins/perfprofiler/perfeventtype.h23
-rw-r--r--src/plugins/perfprofiler/perfoptionspage.cpp2
-rw-r--r--src/plugins/perfprofiler/perfoptionspage.h2
-rw-r--r--src/plugins/perfprofiler/perfprofilerconstants.h3
-rw-r--r--src/plugins/perfprofiler/perfprofilerflamegraphmodel.cpp8
-rw-r--r--src/plugins/perfprofiler/perfprofilerplugin.cpp47
-rw-r--r--src/plugins/perfprofiler/perfprofilerplugin.h8
-rw-r--r--src/plugins/perfprofiler/perfprofilerruncontrol.cpp5
-rw-r--r--src/plugins/perfprofiler/perfprofilerruncontrol.h2
-rw-r--r--src/plugins/perfprofiler/perfprofilertool.cpp66
-rw-r--r--src/plugins/perfprofiler/perfprofilertool.h5
-rw-r--r--src/plugins/perfprofiler/perfprofilertracefile.cpp186
-rw-r--r--src/plugins/perfprofiler/perfprofilertracefile.h1
-rw-r--r--src/plugins/perfprofiler/perfprofilertracemanager.cpp13
-rw-r--r--src/plugins/perfprofiler/perfprofilertracemanager.h16
-rw-r--r--src/plugins/perfprofiler/perfprofilertraceview.cpp4
-rw-r--r--src/plugins/perfprofiler/perfresourcecounter.cpp1
-rw-r--r--src/plugins/perfprofiler/perfrunconfigurationaspect.cpp2
-rw-r--r--src/plugins/perfprofiler/perfsettings.h6
-rw-r--r--src/plugins/perfprofiler/perftimelinemodel.cpp59
-rw-r--r--src/plugins/perfprofiler/perftimelinemodel.h10
-rw-r--r--src/plugins/perfprofiler/perftracepointdialog.cpp6
-rw-r--r--src/plugins/plugins.pro15
-rw-r--r--src/plugins/projectexplorer/CMakeLists.txt215
-rw-r--r--src/plugins/projectexplorer/abi.cpp50
-rw-r--r--src/plugins/projectexplorer/abi.h10
-rw-r--r--src/plugins/projectexplorer/abiwidget.cpp22
-rw-r--r--src/plugins/projectexplorer/abiwidget.h7
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp103
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.h7
-rw-r--r--src/plugins/projectexplorer/addrunconfigdialog.cpp192
-rw-r--r--src/plugins/projectexplorer/addrunconfigdialog.h55
-rw-r--r--src/plugins/projectexplorer/allprojectsfilter.cpp2
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.cpp2
-rw-r--r--src/plugins/projectexplorer/ansifilterparser.cpp2
-rw-r--r--src/plugins/projectexplorer/applicationlauncher.cpp11
-rw-r--r--src/plugins/projectexplorer/appoutputpane.cpp343
-rw-r--r--src/plugins/projectexplorer/appoutputpane.h43
-rw-r--r--src/plugins/projectexplorer/baseprojectwizarddialog.cpp2
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp114
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.h35
-rw-r--r--src/plugins/projectexplorer/buildenvironmentwidget.cpp3
-rw-r--r--src/plugins/projectexplorer/buildinfo.h2
-rw-r--r--src/plugins/projectexplorer/buildmanager.cpp29
-rw-r--r--src/plugins/projectexplorer/buildmanager.h4
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.cpp2
-rw-r--r--src/plugins/projectexplorer/buildstep.cpp8
-rw-r--r--src/plugins/projectexplorer/buildstep.h7
-rw-r--r--src/plugins/projectexplorer/buildstepspage.cpp15
-rw-r--r--src/plugins/projectexplorer/buildtargetinfo.h29
-rw-r--r--src/plugins/projectexplorer/clangparser.cpp52
-rw-r--r--src/plugins/projectexplorer/codestylesettingspropertiespage.cpp2
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.cpp198
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.h31
-rw-r--r--src/plugins/projectexplorer/currentprojectfilter.cpp2
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.cpp2
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.cpp18
-rw-r--r--src/plugins/projectexplorer/customparser.cpp56
-rw-r--r--src/plugins/projectexplorer/customparser.h2
-rw-r--r--src/plugins/projectexplorer/customparserconfigdialog.cpp12
-rw-r--r--src/plugins/projectexplorer/customtoolchain.cpp95
-rw-r--r--src/plugins/projectexplorer/customtoolchain.h34
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizard.cpp4
-rw-r--r--src/plugins/projectexplorer/deployablefile.cpp4
-rw-r--r--src/plugins/projectexplorer/deployablefile.h6
-rw-r--r--src/plugins/projectexplorer/deployconfiguration.cpp2
-rw-r--r--src/plugins/projectexplorer/deploymentdata.cpp2
-rw-r--r--src/plugins/projectexplorer/deploymentdata.h18
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdevice.cpp14
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdevice.h3
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp6
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicemanager.cpp21
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicemanager.h6
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocess.h1
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp16
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp103
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceprocesslist.h14
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h2
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.cpp34
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.h15
-rw-r--r--src/plugins/projectexplorer/devicesupport/localprocesslist.cpp15
-rw-r--r--src/plugins/projectexplorer/devicesupport/localprocesslist.h3
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp10
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp4
-rw-r--r--src/plugins/projectexplorer/editorconfiguration.cpp2
-rw-r--r--src/plugins/projectexplorer/editorsettingspropertiespage.cpp4
-rw-r--r--src/plugins/projectexplorer/environmentaspect.cpp68
-rw-r--r--src/plugins/projectexplorer/environmentaspect.h43
-rw-r--r--src/plugins/projectexplorer/environmentaspectwidget.cpp38
-rw-r--r--src/plugins/projectexplorer/environmentaspectwidget.h1
-rw-r--r--src/plugins/projectexplorer/environmentwidget.cpp119
-rw-r--r--src/plugins/projectexplorer/environmentwidget.h15
-rw-r--r--src/plugins/projectexplorer/extraabi.cpp2
-rw-r--r--src/plugins/projectexplorer/extracompiler.cpp48
-rw-r--r--src/plugins/projectexplorer/extracompiler.h48
-rw-r--r--src/plugins/projectexplorer/fileinsessionfinder.cpp89
-rw-r--r--src/plugins/projectexplorer/fileinsessionfinder.h36
-rw-r--r--src/plugins/projectexplorer/filterkitaspectsdialog.cpp163
-rw-r--r--src/plugins/projectexplorer/filterkitaspectsdialog.h49
-rw-r--r--src/plugins/projectexplorer/foldernavigationwidget.cpp70
-rw-r--r--src/plugins/projectexplorer/foldernavigationwidget.h12
-rw-r--r--src/plugins/projectexplorer/gccparser.cpp278
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp707
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.h86
-rw-r--r--src/plugins/projectexplorer/gcctoolchainfactories.h57
-rw-r--r--src/plugins/projectexplorer/gnumakeparser.cpp88
-rw-r--r--src/plugins/projectexplorer/images/fileoverlay_py.pngbin0 -> 304 bytes
-rw-r--r--src/plugins/projectexplorer/images/fileoverlay_py@2x.pngbin0 -> 533 bytes
-rw-r--r--src/plugins/projectexplorer/importwidget.cpp18
-rw-r--r--src/plugins/projectexplorer/importwidget.h8
-rw-r--r--src/plugins/projectexplorer/ioutputparser.cpp5
-rw-r--r--src/plugins/projectexplorer/ioutputparser.h1
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp15
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp2
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp2
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp135
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizard.h19
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp58
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h25
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp4
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp2
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp25
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h2
-rw-r--r--src/plugins/projectexplorer/kit.cpp188
-rw-r--r--src/plugins/projectexplorer/kit.h27
-rw-r--r--src/plugins/projectexplorer/kitchooser.cpp19
-rw-r--r--src/plugins/projectexplorer/kitchooser.h3
-rw-r--r--src/plugins/projectexplorer/kitconfigwidget.cpp73
-rw-r--r--src/plugins/projectexplorer/kitconfigwidget.h81
-rw-r--r--src/plugins/projectexplorer/kitinformation.cpp760
-rw-r--r--src/plugins/projectexplorer/kitinformation.h67
-rw-r--r--src/plugins/projectexplorer/kitinformationconfigwidget.cpp529
-rw-r--r--src/plugins/projectexplorer/kitinformationconfigwidget.h196
-rw-r--r--src/plugins/projectexplorer/kitmanager.cpp299
-rw-r--r--src/plugins/projectexplorer/kitmanager.h105
-rw-r--r--src/plugins/projectexplorer/kitmanagerconfigwidget.cpp150
-rw-r--r--src/plugins/projectexplorer/kitmanagerconfigwidget.h12
-rw-r--r--src/plugins/projectexplorer/kitmodel.cpp92
-rw-r--r--src/plugins/projectexplorer/kitmodel.h5
-rw-r--r--src/plugins/projectexplorer/kitoptionspage.cpp34
-rw-r--r--src/plugins/projectexplorer/ldparser.cpp10
-rw-r--r--src/plugins/projectexplorer/linuxiccparser.cpp32
-rw-r--r--src/plugins/projectexplorer/localenvironmentaspect.cpp59
-rw-r--r--src/plugins/projectexplorer/localenvironmentaspect.h9
-rw-r--r--src/plugins/projectexplorer/makestep.cpp46
-rw-r--r--src/plugins/projectexplorer/makestep.h16
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp34
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.h4
-rw-r--r--src/plugins/projectexplorer/msvcparser.cpp126
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp593
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.h83
-rw-r--r--src/plugins/projectexplorer/namedwidget.h4
-rw-r--r--src/plugins/projectexplorer/osparser.cpp4
-rw-r--r--src/plugins/projectexplorer/outputparser_test.cpp4
-rw-r--r--src/plugins/projectexplorer/outputparser_test.h4
-rw-r--r--src/plugins/projectexplorer/parseissuesdialog.cpp171
-rw-r--r--src/plugins/projectexplorer/parseissuesdialog.h48
-rw-r--r--src/plugins/projectexplorer/processparameters.cpp40
-rw-r--r--src/plugins/projectexplorer/processparameters.h28
-rw-r--r--src/plugins/projectexplorer/processstep.cpp206
-rw-r--r--src/plugins/projectexplorer/processstep.h42
-rw-r--r--src/plugins/projectexplorer/processstep.ui62
-rw-r--r--src/plugins/projectexplorer/project.cpp117
-rw-r--r--src/plugins/projectexplorer/project.h28
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.cpp23
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.h27
-rw-r--r--src/plugins/projectexplorer/projectconfigurationaspects.cpp50
-rw-r--r--src/plugins/projectexplorer/projectconfigurationaspects.h12
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp436
-rw-r--r--src/plugins/projectexplorer/projectexplorer.h15
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pro26
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs10
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qrc2
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h4
-rw-r--r--src/plugins/projectexplorer/projectexplorersettings.h43
-rw-r--r--src/plugins/projectexplorer/projectexplorersettingspage.cpp35
-rw-r--r--src/plugins/projectexplorer/projectexplorersettingspage.ui292
-rw-r--r--src/plugins/projectexplorer/projectfilewizardextension.cpp2
-rw-r--r--src/plugins/projectexplorer/projectimporter.cpp68
-rw-r--r--src/plugins/projectexplorer/projectimporter.h17
-rw-r--r--src/plugins/projectexplorer/projectmanager.h8
-rw-r--r--src/plugins/projectexplorer/projectmodels.cpp321
-rw-r--r--src/plugins/projectexplorer/projectmodels.h6
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp143
-rw-r--r--src/plugins/projectexplorer/projectnodes.h115
-rw-r--r--src/plugins/projectexplorer/projecttree.cpp56
-rw-r--r--src/plugins/projectexplorer/projecttree.h10
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp33
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.h6
-rw-r--r--src/plugins/projectexplorer/projectwelcomepage.cpp7
-rw-r--r--src/plugins/projectexplorer/projectwindow.cpp4
-rw-r--r--src/plugins/projectexplorer/projectwizardpage.cpp10
-rw-r--r--src/plugins/projectexplorer/runconfiguration.cpp1493
-rw-r--r--src/plugins/projectexplorer/runconfiguration.h271
-rw-r--r--src/plugins/projectexplorer/runconfigurationaspects.cpp66
-rw-r--r--src/plugins/projectexplorer/runconfigurationaspects.h26
-rw-r--r--src/plugins/projectexplorer/runcontrol.cpp1563
-rw-r--r--src/plugins/projectexplorer/runcontrol.h346
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.cpp47
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.h3
-rw-r--r--src/plugins/projectexplorer/selectablefilesmodel.cpp61
-rw-r--r--src/plugins/projectexplorer/selectablefilesmodel.h45
-rw-r--r--src/plugins/projectexplorer/session.cpp105
-rw-r--r--src/plugins/projectexplorer/session.h7
-rw-r--r--src/plugins/projectexplorer/sessiondialog.cpp24
-rw-r--r--src/plugins/projectexplorer/sessiondialog.h2
-rw-r--r--src/plugins/projectexplorer/sessionmodel.cpp8
-rw-r--r--src/plugins/projectexplorer/sessionmodel.h4
-rw-r--r--src/plugins/projectexplorer/sessionview.cpp41
-rw-r--r--src/plugins/projectexplorer/sessionview.h13
-rw-r--r--src/plugins/projectexplorer/target.cpp24
-rw-r--r--src/plugins/projectexplorer/target.h15
-rw-r--r--src/plugins/projectexplorer/targetsettingspanel.cpp89
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp15
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.h5
-rw-r--r--src/plugins/projectexplorer/targetsetupwidget.cpp5
-rw-r--r--src/plugins/projectexplorer/task.cpp29
-rw-r--r--src/plugins/projectexplorer/task.h12
-rw-r--r--src/plugins/projectexplorer/taskhub.cpp10
-rw-r--r--src/plugins/projectexplorer/taskhub.h2
-rw-r--r--src/plugins/projectexplorer/taskmodel.cpp212
-rw-r--r--src/plugins/projectexplorer/taskmodel.h50
-rw-r--r--src/plugins/projectexplorer/taskwindow.cpp32
-rw-r--r--src/plugins/projectexplorer/taskwindow.h2
-rw-r--r--src/plugins/projectexplorer/toolchain.cpp151
-rw-r--r--src/plugins/projectexplorer/toolchain.h81
-rw-r--r--src/plugins/projectexplorer/toolchainmanager.cpp22
-rw-r--r--src/plugins/projectexplorer/toolchainmanager.h13
-rw-r--r--src/plugins/projectexplorer/toolchainoptionspage.cpp165
-rw-r--r--src/plugins/projectexplorer/toolchainsettingsaccessor.cpp123
-rw-r--r--src/plugins/projectexplorer/treescanner.cpp176
-rw-r--r--src/plugins/projectexplorer/treescanner.h101
-rw-r--r--src/plugins/projectexplorer/userfileaccessor.cpp67
-rw-r--r--src/plugins/projectexplorer/userfileaccessor.h6
-rw-r--r--src/plugins/projectexplorer/waitforstopdialog.h2
-rw-r--r--src/plugins/projectexplorer/xcodebuildparser.cpp38
-rw-r--r--src/plugins/pythoneditor/CMakeLists.txt11
-rw-r--r--src/plugins/pythoneditor/pythoneditorplugin.cpp157
-rw-r--r--src/plugins/qbsprojectmanager/CMakeLists.txt38
-rw-r--r--src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp233
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp134
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfiguration.h12
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.cpp109
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.h66
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.cpp43
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.h2
-rw-r--r--src/plugins/qbsprojectmanager/qbscleanstep.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsinstallstep.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbskitinformation.cpp49
-rw-r--r--src/plugins/qbsprojectmanager/qbskitinformation.h10
-rw-r--r--src/plugins/qbsprojectmanager/qbslogsink.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.cpp103
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.h51
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp135
-rw-r--r--src/plugins/qbsprojectmanager/qbsparser.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp57
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.h8
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectimporter.cpp43
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectimporter.h4
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.pro2
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.qbs2
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h1
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp131
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h7
-rw-r--r--src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp66
-rw-r--r--src/plugins/qbsprojectmanager/qbsrunconfiguration.h8
-rw-r--r--src/plugins/qmakeprojectmanager/CMakeLists.txt53
-rw-r--r--src/plugins/qmakeprojectmanager/addlibrarywizard.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/addlibrarywizard.h4
-rw-r--r--src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp44
-rw-r--r--src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h6
-rw-r--r--src/plugins/qmakeprojectmanager/externaleditors.cpp13
-rw-r--r--src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp8
-rw-r--r--src/plugins/qmakeprojectmanager/makefileparse.cpp10
-rw-r--r--src/plugins/qmakeprojectmanager/makefileparse.h4
-rw-r--r--src/plugins/qmakeprojectmanager/profileeditor.cpp46
-rw-r--r--src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp117
-rw-r--r--src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h6
-rw-r--r--src/plugins/qmakeprojectmanager/qmakekitconfigwidget.cpp86
-rw-r--r--src/plugins/qmakeprojectmanager/qmakekitconfigwidget.h61
-rw-r--r--src/plugins/qmakeprojectmanager/qmakekitinformation.cpp119
-rw-r--r--src/plugins/qmakeprojectmanager/qmakekitinformation.h23
-rw-r--r--src/plugins/qmakeprojectmanager/qmakemakestep.cpp47
-rw-r--r--src/plugins/qmakeprojectmanager/qmakemakestep.h10
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.cpp52
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.h10
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp55
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodetreebuilder.h2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeparser.cpp38
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp204
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeparsernodes.h71
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp154
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.h16
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp165
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h16
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.ui105
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp36
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectimporter.h6
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp25
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager.h4
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro15
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs9
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp22
-rw-r--r--src/plugins/qmakeprojectmanager/qmakesettings.cpp159
-rw-r--r--src/plugins/qmakeprojectmanager/qmakesettings.h78
-rw-r--r--src/plugins/qmakeprojectmanager/qmakestep.cpp52
-rw-r--r--src/plugins/qmakeprojectmanager/qmakestep.h15
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/guiappwizard.cpp270
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/guiappwizard.h54
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.cpp108
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.h72
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp193
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/libraryparameters.h64
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/librarywizard.cpp161
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/librarywizard.h48
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp347
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.h78
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp10
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp16
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt611
-rw-r--r--src/plugins/qmldesigner/components/colortool/colortool.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/colortool/colortool.h (renamed from src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.h)0
-rw-r--r--src/plugins/qmldesigner/components/colortool/colortool.pri (renamed from src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.pri)0
-rw-r--r--src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp10
-rw-r--r--src/plugins/qmldesigner/components/componentcore/componentcore_constants.h1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/crumblebar.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/crumblebar.h4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp7
-rw-r--r--src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp11
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp160
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/zoomaction.cpp3
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.ui (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.ui)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp333
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/backendmodel.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/backendmodel.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp446
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectioneditor.pri (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectioneditor.pri)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectioneditor.qrc (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectioneditor.qrc)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp357
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionview.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionview.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.ui (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.ui)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/delegates.cpp361
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/delegates.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/delegates.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp677
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.h)0
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/stylesheet.css (renamed from src/plugins/qmldesigner/qmldesignerextension/connectioneditor/stylesheet.css)0
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp187
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/animationcurve.h69
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp64
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditor.h53
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditor.pri46
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp70
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h72
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h125
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp101
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.h63
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp267
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.h127
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp226
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h98
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.cpp277
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.h65
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp225
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h89
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp523
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h157
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/handleitem.cpp104
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/handleitem.h56
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp251
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h98
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/playhead.cpp187
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/playhead.h72
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.cpp112
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.h85
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp221
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/selector.h86
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/shortcut.cpp81
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/shortcut.h61
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.cpp146
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.h63
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp156
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treemodel.h75
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp127
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treeview.h61
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/utils.cpp107
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/utils.h52
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/keyframe.cpp88
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/keyframe.h65
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/treeitem.cpp227
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/treeitem.h137
-rw-r--r--src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/dragtool.cpp1
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp5
-rw-r--r--src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp2
-rw-r--r--src/plugins/qmldesigner/components/importmanager/importswidget.cpp2
-rw-r--r--src/plugins/qmldesigner/components/integration/componentaction.cpp2
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.cpp52
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.h4
-rw-r--r--src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp2
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp59
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreeview.h1
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp16
-rw-r--r--src/plugins/qmldesigner/components/pathtool/controlpoint.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/controlpoint.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/controlpoint.h (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/controlpoint.h)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/cubicsegment.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/cubicsegment.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/cubicsegment.h126
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathitem.cpp971
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathitem.h (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.h)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathselectionmanipulator.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.h (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathselectionmanipulator.h)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathtool.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathtool.h (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.h)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathtool.pri (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.pri)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtoolview.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathtoolview.h (renamed from src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtoolview.h)0
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp13
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.h4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp178
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h15
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.cpp161
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.h62
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.cpp61
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.h48
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.cpp206
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.h92
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp113
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.h60
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri18
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp29
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp119
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h7
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp119
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h3
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp284
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp31
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h9
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp6
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp113
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h75
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp146
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h77
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp185
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h71
-rw-r--r--src/plugins/qmldesigner/components/sourcetool/sourcetool.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/sourcetool/sourcetool.h (renamed from src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.h)0
-rw-r--r--src/plugins/qmldesigner/components/sourcetool/sourcetool.pri (renamed from src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.pri)0
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp1
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.h1
-rw-r--r--src/plugins/qmldesigner/components/texttool/textedititem.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/texttool/textedititem.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/texttool/textedititem.h (renamed from src/plugins/qmldesigner/qmldesignerextension/texttool/textedititem.h)0
-rw-r--r--src/plugins/qmldesigner/components/texttool/textedititemwidget.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/texttool/textedititemwidget.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/texttool/textedititemwidget.h (renamed from src/plugins/qmldesigner/qmldesignerextension/texttool/textedititemwidget.h)0
-rw-r--r--src/plugins/qmldesigner/components/texttool/texttool.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/texttool/texttool.h (renamed from src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.h)0
-rw-r--r--src/plugins/qmldesigner/components/texttool/texttool.pri (renamed from src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.pri)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/canvas.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvas.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/canvas.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvas.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.cpp124
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvasstyledialog.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp502
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/easingcurve.h157
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/easingcurvedialog.cpp298
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/easingcurvedialog.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurvedialog.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/add_timeline.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/add_timeline.png)bin164 -> 164 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/add_timeline@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/add_timeline@2x.png)bin162 -> 162 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/animation.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/animation.png)bin200 -> 200 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/animation@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/animation@2x.png)bin235 -> 235 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/back_one_frame.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/back_one_frame.png)bin153 -> 153 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/back_one_frame@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/back_one_frame@2x.png)bin231 -> 231 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/curve_editor.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_editor.png)bin190 -> 190 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/curve_editor@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_editor@2x.png)bin239 -> 239 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/curve_picker.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_picker.png)bin163 -> 163 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/curve_picker@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_picker@2x.png)bin295 -> 295 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/forward_one_frame.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/forward_one_frame.png)bin147 -> 147 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/forward_one_frame@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/forward_one_frame@2x.png)bin231 -> 231 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/global_record_keyframes.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/global_record_keyframes.png)bin162 -> 162 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/global_record_keyframes@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/global_record_keyframes@2x.png)bin281 -> 281 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/is_keyframe.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/is_keyframe.png)bin237 -> 237 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/is_keyframe@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/is_keyframe@2x.png)bin236 -> 236 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe-16px.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe-16px.png)bin190 -> 190 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe.png)bin185 -> 185 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe@2x.png)bin185 -> 185 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_active.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_active.png)bin268 -> 268 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_active@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_active@2x.png)bin489 -> 489 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_inactive.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_inactive.png)bin241 -> 241 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_inactive@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_inactive@2x.png)bin414 -> 414 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_selected.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_selected.png)bin273 -> 273 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_selected@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_selected@2x.png)bin493 -> 493 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_active.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_active.png)bin327 -> 327 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_active@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_active@2x.png)bin550 -> 550 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_inactive.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_inactive.png)bin371 -> 371 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_inactive@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_inactive@2x.png)bin580 -> 580 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_selected.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_selected.png)bin328 -> 328 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_selected@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_selected@2x.png)bin557 -> 557 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_active.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_active.png)bin204 -> 204 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_active@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_active@2x.png)bin299 -> 299 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_inactive.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_inactive.png)bin201 -> 201 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_inactive@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_inactive@2x.png)bin292 -> 292 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_selected.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_selected.png)bin204 -> 204 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_selected@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_selected@2x.png)bin299 -> 299 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_active.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_active.png)bin336 -> 336 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_active@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_active@2x.png)bin542 -> 542 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_inactive.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_inactive.png)bin286 -> 286 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_inactive@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_inactive@2x.png)bin457 -> 457 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_selected.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_selected.png)bin407 -> 407 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_selected@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_selected@2x.png)bin706 -> 706 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/local_record_keyframes.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/local_record_keyframes.png)bin186 -> 186 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/local_record_keyframes@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/local_record_keyframes@2x.png)bin192 -> 192 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/loop_playback.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/loop_playback.png)bin171 -> 171 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/loop_playback@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/loop_playback@2x.png)bin291 -> 291 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/next_keyframe.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/next_keyframe.png)bin133 -> 133 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/next_keyframe@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/next_keyframe@2x.png)bin150 -> 150 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/pause_playback.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/pause_playback.png)bin150 -> 150 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/pause_playback@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/pause_playback@2x.png)bin152 -> 152 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/playhead.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/playhead.png)bin289 -> 289 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/playhead@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/playhead@2x.png)bin478 -> 478 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/previous_keyframe.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/previous_keyframe.png)bin132 -> 132 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/previous_keyframe@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/previous_keyframe@2x.png)bin152 -> 152 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/remove_timeline.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/remove_timeline.png)bin190 -> 190 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/remove_timeline@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/remove_timeline@2x.png)bin179 -> 179 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/start_playback.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/start_playback.png)bin143 -> 143 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/start_playback@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/start_playback@2x.png)bin169 -> 169 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/timeline-16px.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/timeline-16px.png)bin389 -> 389 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/to_first_frame.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_first_frame.png)bin135 -> 135 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/to_first_frame@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_first_frame@2x.png)bin193 -> 193 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/to_last_frame.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_last_frame.png)bin132 -> 132 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/to_last_frame@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_last_frame@2x.png)bin191 -> 191 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_left.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_left.png)bin186 -> 186 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_left@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_left@2x.png)bin309 -> 309 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_right.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_right.png)bin177 -> 177 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_right@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_right@2x.png)bin282 -> 282 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/zoom_big.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_big.png)bin202 -> 202 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/zoom_big@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_big@2x.png)bin357 -> 357 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/zoom_small.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_small.png)bin191 -> 191 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/images/zoom_small@2x.png (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_small@2x.png)bin370 -> 370 bytes
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/preseteditor.cpp560
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/preseteditor.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/preseteditor.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.ui)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/splineeditor.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/splineeditor.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/splineeditor.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/splineeditor.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timeline.metainfo (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timeline.metainfo)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timeline.qrc (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timeline.qrc)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineabstracttool.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineabstracttool.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineabstracttool.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineabstracttool.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineactions.cpp322
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineactions.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineactions.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp262
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.ui (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.ui)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineconstants.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinecontext.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontext.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinecontext.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontext.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontrols.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontrols.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineeditor.pri (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineeditor.pri)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineform.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineform.ui (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.ui)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicslayout.cpp162
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicslayout.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicslayout.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp720
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicsscene.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineicons.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineicons.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineitem.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineitem.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineitem.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineitem.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovableabstractitem.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovableabstractitem.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp173
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovetool.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineplaceholder.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineplaceholder.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp641
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinepropertyitem.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp1062
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesectionitem.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineselectiontool.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineselectiontool.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.ui (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.ui)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesettingsmodel.cpp484
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesettingsmodel.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsmodel.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbar.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbar.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinetoolbutton.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbutton.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinetoolbutton.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbutton.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetooldelegate.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetooldelegate.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineutils.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineutils.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineutils.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineutils.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp610
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineview.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineview.h)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinewidget.cpp)0
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinewidget.h (renamed from src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinewidget.h)0
-rw-r--r--src/plugins/qmldesigner/componentsplugin/componentsplugin.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/qmlrefactoring.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractview.h5
-rw-r--r--src/plugins/qmldesigner/designercore/include/metainforeader.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodehints.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlitemnode.h7
-rw-r--r--src/plugins/qmldesigner/designercore/include/subcomponentmanager.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/viewmanager.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp6
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h4
-rw-r--r--src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp27
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp24
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp15
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelmerger.cpp40
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlanchors.cpp119
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp55
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp6
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp13
-rw-r--r--src/plugins/qmldesigner/designercore/model/viewmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.h2
-rw-r--r--src/plugins/qmldesigner/designercore/rewritertransaction.cpp2
-rw-r--r--src/plugins/qmldesigner/designersettings.cpp1
-rw-r--r--src/plugins/qmldesigner/designersettings.h1
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp2
-rw-r--r--src/plugins/qmldesigner/designmodewidget.h2
-rw-r--r--src/plugins/qmldesigner/documentmanager.cpp29
-rw-r--r--src/plugins/qmldesigner/documentmanager.h4
-rw-r--r--src/plugins/qmldesigner/qmldesigner.pro2
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/connectioneditor/backendmodel.cpp348
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.cpp453
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp372
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/connectioneditor/delegates.cpp361
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp692
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/pathtool/cubicsegment.h127
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp980
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension.pri12
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension_global.h34
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/qmldesignerextensionconstants.h35
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvasstyledialog.cpp124
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.cpp500
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.h155
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurvedialog.cpp307
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/preseteditor.cpp560
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineactions.cpp345
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.cpp262
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicslayout.cpp160
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicsscene.cpp733
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovetool.cpp181
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinepropertyitem.cpp647
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesectionitem.cpp1067
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsmodel.cpp502
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineview.cpp625
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp8
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.pro9
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.qbs71
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.pngbin0 -> 198 bytes
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.pngbin0 -> 424 bytes
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo2
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp303
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h135
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp173
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h69
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json6
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri10
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro18
-rw-r--r--src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc7
-rw-r--r--src/plugins/qmldesigner/shortcutmanager.cpp2
-rw-r--r--src/plugins/qmljseditor/CMakeLists.txt33
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.cpp1
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.h3
-rw-r--r--src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp2
-rw-r--r--src/plugins/qmljseditor/qmljscomponentfromobjectdef.h1
-rw-r--r--src/plugins/qmljseditor/qmljseditor.cpp8
-rw-r--r--src/plugins/qmljseditor/qmljseditordocument.cpp4
-rw-r--r--src/plugins/qmljseditor/qmljshoverhandler.cpp4
-rw-r--r--src/plugins/qmljseditor/qmljsoutline.cpp1
-rw-r--r--src/plugins/qmljseditor/qmljsoutline.h3
-rw-r--r--src/plugins/qmljseditor/qmljsquickfix.h2
-rw-r--r--src/plugins/qmljseditor/qmljsquickfixassist.cpp1
-rw-r--r--src/plugins/qmljseditor/qmljsquickfixassist.h5
-rw-r--r--src/plugins/qmljseditor/qmljssemanticinfoupdater.h3
-rw-r--r--src/plugins/qmljseditor/qmljstextmark.cpp4
-rw-r--r--src/plugins/qmljseditor/qmljstextmark.h4
-rw-r--r--src/plugins/qmljseditor/qmltaskmanager.cpp16
-rw-r--r--src/plugins/qmljseditor/qmltaskmanager.h4
-rw-r--r--src/plugins/qmljstools/CMakeLists.txt26
-rw-r--r--src/plugins/qmljstools/qmljsbundleprovider.cpp2
-rw-r--r--src/plugins/qmljstools/qmljsfunctionfilter.cpp2
-rw-r--r--src/plugins/qmljstools/qmljsinterpreter.cpp83
-rw-r--r--src/plugins/qmljstools/qmljsinterpreter.h56
-rw-r--r--src/plugins/qmljstools/qmljslocatordata.cpp4
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp5
-rw-r--r--src/plugins/qmlpreview/CMakeLists.txt18
-rw-r--r--src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp2
-rw-r--r--src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp4
-rw-r--r--src/plugins/qmlpreview/qmlpreviewplugin.cpp14
-rw-r--r--src/plugins/qmlpreview/qmlpreviewplugin.h5
-rw-r--r--src/plugins/qmlpreview/qmlpreviewruncontrol.cpp36
-rw-r--r--src/plugins/qmlpreview/qmlpreviewruncontrol.h2
-rw-r--r--src/plugins/qmlpreview/tests/qmlpreviewplugin_test.cpp2
-rw-r--r--src/plugins/qmlprofiler/CMakeLists.txt75
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerconfigwidget.cpp2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerplugin.cpp38
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerplugin.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp5
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerruncontrol.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertextmark.cpp4
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertextmark.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.cpp27
-rw-r--r--src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp12
-rw-r--r--src/plugins/qmlprofiler/tests/qmlnote_test.h1
-rw-r--r--src/plugins/qmlprofiler/tests/qmlprofilerattachdialog_test.cpp9
-rw-r--r--src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp29
-rw-r--r--src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp9
-rw-r--r--src/plugins/qmlprojectmanager/CMakeLists.txt16
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp2
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp6
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h2
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp6
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h4
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp59
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.h20
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectconstants.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp66
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.h45
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.pro9
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.qbs1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectnodes.cpp7
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectnodes.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.cpp15
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.h2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp78
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp43
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.h40
-rw-r--r--src/plugins/qnx/CMakeLists.txt29
-rw-r--r--src/plugins/qnx/qnx.pro4
-rw-r--r--src/plugins/qnx/qnx.qbs4
-rw-r--r--src/plugins/qnx/qnxconfiguration.cpp105
-rw-r--r--src/plugins/qnx/qnxconfiguration.h36
-rw-r--r--src/plugins/qnx/qnxconfigurationmanager.cpp6
-rw-r--r--src/plugins/qnx/qnxconfigurationmanager.h2
-rw-r--r--src/plugins/qnx/qnxconstants.h2
-rw-r--r--src/plugins/qnx/qnxdebugsupport.cpp22
-rw-r--r--src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp19
-rw-r--r--src/plugins/qnx/qnxdevice.cpp33
-rw-r--r--src/plugins/qnx/qnxdevice.h15
-rw-r--r--src/plugins/qnx/qnxdevicefactory.cpp61
-rw-r--r--src/plugins/qnx/qnxdevicefactory.h46
-rw-r--r--src/plugins/qnx/qnxdeviceprocess.cpp1
-rw-r--r--src/plugins/qnx/qnxdeviceprocesssignaloperation.h4
-rw-r--r--src/plugins/qnx/qnxdevicetester.cpp5
-rw-r--r--src/plugins/qnx/qnxplugin.cpp43
-rw-r--r--src/plugins/qnx/qnxqtversion.cpp38
-rw-r--r--src/plugins/qnx/qnxqtversion.h17
-rw-r--r--src/plugins/qnx/qnxqtversionfactory.cpp79
-rw-r--r--src/plugins/qnx/qnxqtversionfactory.h51
-rw-r--r--src/plugins/qnx/qnxrunconfiguration.cpp2
-rw-r--r--src/plugins/qnx/qnxsettingswidget.cpp4
-rw-r--r--src/plugins/qnx/qnxtoolchain.cpp80
-rw-r--r--src/plugins/qnx/qnxtoolchain.h13
-rw-r--r--src/plugins/qnx/qnxutils.cpp8
-rw-r--r--src/plugins/qnx/qnxutils.h8
-rw-r--r--src/plugins/qnx/slog2inforunner.cpp2
-rw-r--r--src/plugins/qnx/slog2inforunner.h2
-rw-r--r--src/plugins/qtsupport/CMakeLists.txt35
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp307
-rw-r--r--src/plugins/qtsupport/baseqtversion.h105
-rw-r--r--src/plugins/qtsupport/codegensettingspage.cpp2
-rw-r--r--src/plugins/qtsupport/desktopqtversion.cpp61
-rw-r--r--src/plugins/qtsupport/desktopqtversion.h22
-rw-r--r--src/plugins/qtsupport/desktopqtversionfactory.cpp71
-rw-r--r--src/plugins/qtsupport/desktopqtversionfactory.h48
-rw-r--r--src/plugins/qtsupport/exampleslistmodel.cpp2
-rw-r--r--src/plugins/qtsupport/gettingstartedwelcomepage.cpp14
-rw-r--r--src/plugins/qtsupport/qmldumptool.cpp2
-rw-r--r--src/plugins/qtsupport/qscxmlcgenerator.cpp43
-rw-r--r--src/plugins/qtsupport/qscxmlcgenerator.h16
-rw-r--r--src/plugins/qtsupport/qtcppkitinfo.cpp2
-rw-r--r--src/plugins/qtsupport/qtkitconfigwidget.cpp156
-rw-r--r--src/plugins/qtsupport/qtkitconfigwidget.h66
-rw-r--r--src/plugins/qtsupport/qtkitinformation.cpp241
-rw-r--r--src/plugins/qtsupport/qtkitinformation.h12
-rw-r--r--src/plugins/qtsupport/qtoptionspage.cpp38
-rw-r--r--src/plugins/qtsupport/qtoptionspage.h1
-rw-r--r--src/plugins/qtsupport/qtoutputformatter.cpp64
-rw-r--r--src/plugins/qtsupport/qtoutputformatter.h6
-rw-r--r--src/plugins/qtsupport/qtparser.cpp38
-rw-r--r--src/plugins/qtsupport/qtprojectimporter.cpp80
-rw-r--r--src/plugins/qtsupport/qtprojectimporter.h4
-rw-r--r--src/plugins/qtsupport/qtsupport.pro6
-rw-r--r--src/plugins/qtsupport/qtsupport.qbs8
-rw-r--r--src/plugins/qtsupport/qtsupportconstants.h3
-rw-r--r--src/plugins/qtsupport/qtsupportplugin.cpp13
-rw-r--r--src/plugins/qtsupport/qtsupportplugin.h1
-rw-r--r--src/plugins/qtsupport/qttestparser.cpp132
-rw-r--r--src/plugins/qtsupport/qttestparser.h47
-rw-r--r--src/plugins/qtsupport/qtversionfactory.cpp97
-rw-r--r--src/plugins/qtsupport/qtversionfactory.h53
-rw-r--r--src/plugins/qtsupport/qtversionmanager.cpp45
-rw-r--r--src/plugins/qtsupport/qtversionmanager.h6
-rw-r--r--src/plugins/qtsupport/screenshotcropper.cpp2
-rw-r--r--src/plugins/qtsupport/uicgenerator.cpp25
-rw-r--r--src/plugins/qtsupport/uicgenerator.h12
-rw-r--r--src/plugins/remotelinux/CMakeLists.txt49
-rw-r--r--src/plugins/remotelinux/abstractpackagingstep.cpp8
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp19
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeployservice.h18
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp13
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeploystep.h7
-rw-r--r--src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp4
-rw-r--r--src/plugins/remotelinux/deploymenttimeinfo.cpp4
-rw-r--r--src/plugins/remotelinux/embeddedlinuxqtversion.cpp38
-rw-r--r--src/plugins/remotelinux/embeddedlinuxqtversion.h14
-rw-r--r--src/plugins/remotelinux/embeddedlinuxqtversionfactory.cpp87
-rw-r--r--src/plugins/remotelinux/embeddedlinuxqtversionfactory.h49
-rw-r--r--src/plugins/remotelinux/genericdirectuploadservice.cpp5
-rw-r--r--src/plugins/remotelinux/genericdirectuploadstep.cpp11
-rw-r--r--src/plugins/remotelinux/genericdirectuploadstep.h3
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp57
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h45
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp4
-rw-r--r--src/plugins/remotelinux/linuxdevice.cpp83
-rw-r--r--src/plugins/remotelinux/linuxdevice.h15
-rw-r--r--src/plugins/remotelinux/linuxdeviceprocess.cpp55
-rw-r--r--src/plugins/remotelinux/linuxdeviceprocess.h2
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.cpp7
-rw-r--r--src/plugins/remotelinux/makeinstallstep.cpp226
-rw-r--r--src/plugins/remotelinux/makeinstallstep.h65
-rw-r--r--src/plugins/remotelinux/remotelinux.pro9
-rw-r--r--src/plugins/remotelinux/remotelinux.qbs9
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp17
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h2
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp125
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h12
-rw-r--r--src/plugins/remotelinux/remotelinuxcheckforfreediskspacestepwidget.ui51
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp4
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h2
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp19
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h2
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp1
-rw-r--r--src/plugins/remotelinux/remotelinuxdebugsupport.cpp2
-rw-r--r--src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp10
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp26
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentaspect.h3
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp22
-rw-r--r--src/plugins/remotelinux/remotelinuxenvironmentreader.cpp2
-rw-r--r--src/plugins/remotelinux/remotelinuxkillappstep.cpp9
-rw-r--r--src/plugins/remotelinux/remotelinuxkillappstep.h2
-rw-r--r--src/plugins/remotelinux/remotelinuxpackageinstaller.cpp4
-rw-r--r--src/plugins/remotelinux/remotelinuxplugin.cpp10
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfiguration.cpp3
-rw-r--r--src/plugins/remotelinux/remotelinuxsignaloperation.cpp2
-rw-r--r--src/plugins/remotelinux/rsyncdeploystep.cpp37
-rw-r--r--src/plugins/remotelinux/rsyncdeploystep.h7
-rw-r--r--src/plugins/remotelinux/sshkeydeployer.cpp5
-rw-r--r--src/plugins/remotelinux/tarpackagecreationstep.cpp2
-rw-r--r--src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp2
-rw-r--r--src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp12
-rw-r--r--src/plugins/remotelinux/uploadandinstalltarpackagestep.h2
-rw-r--r--src/plugins/resourceeditor/CMakeLists.txt16
-rw-r--r--src/plugins/resourceeditor/qrceditor/resourcefile.cpp2
-rw-r--r--src/plugins/resourceeditor/resourceeditorplugin.cpp25
-rw-r--r--src/plugins/resourceeditor/resourceeditorw.cpp8
-rw-r--r--src/plugins/resourceeditor/resourceeditorw.h2
-rw-r--r--src/plugins/resourceeditor/resourcenode.cpp109
-rw-r--r--src/plugins/resourceeditor/resourcenode.h10
-rw-r--r--src/plugins/scxmleditor/CMakeLists.txt94
-rw-r--r--src/plugins/scxmleditor/common/colorsettings.cpp3
-rw-r--r--src/plugins/scxmleditor/common/stateproperties.cpp2
-rw-r--r--src/plugins/scxmleditor/scxmleditordocument.cpp8
-rw-r--r--src/plugins/scxmleditor/scxmleditordocument.h2
-rw-r--r--src/plugins/scxmleditor/scxmltexteditor.cpp2
-rw-r--r--src/plugins/serialterminal/CMakeLists.txt13
-rw-r--r--src/plugins/serialterminal/serialoutputpane.cpp12
-rw-r--r--src/plugins/silversearcher/CMakeLists.txt12
-rw-r--r--src/plugins/silversearcher/findinfilessilversearcher.cpp4
-rw-r--r--src/plugins/silversearcher/findinfilessilversearcher.h2
-rw-r--r--src/plugins/silversearcher/silversearcherplugin.cpp2
-rw-r--r--src/plugins/silversearcher/silversearcherplugin.h2
-rw-r--r--src/plugins/studiowelcome/CMakeLists.txt10
-rw-r--r--src/plugins/studiowelcome/StudioWelcome.json.in21
-rw-r--r--src/plugins/studiowelcome/images/mode_welcome_mask.pngbin0 -> 101 bytes
-rw-r--r--src/plugins/studiowelcome/images/mode_welcome_mask@2x.pngbin0 -> 107 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Arc.qml97
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/ArcAnimation.qml148
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Dof_Effect.qml93
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Image1.qml32
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Image2.qml152
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml47
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/RectangleMask.qml86
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Sequencer.qml629
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Sequencer_Bars.qml643
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/SlidersTogether.qml104
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Splash_Image25d.qml80
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Splash_Image2d_png.qml96
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml253
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/main.qml46
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_screens.qmlproject47
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/close.pngbin0 -> 273 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/hand.pngbin0 -> 122318 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/highlight.pngbin0 -> 10633 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/logo.pngbin0 -> 30814 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/blue_seq.pngbin0 -> 130 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/peach_seq.pngbin0 -> 145 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/pink_seq.pngbin0 -> 130 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_1.pngbin0 -> 182 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_2.pngbin0 -> 199 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_3.pngbin0 -> 153 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_4.pngbin0 -> 200 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_5.pngbin0 -> 191 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_6.pngbin0 -> 196 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_7.pngbin0 -> 186 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_8.pngbin0 -> 201 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Audio_Waves.pngbin0 -> 2731 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Slider_on.pngbin0 -> 1198 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Sliders_together.pngbin0 -> 482 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Step_sequencer.pngbin0 -> 2632 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/UI_Background.pngbin0 -> 31484 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_in.pngbin0 -> 276 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_out.pngbin0 -> 577 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_2.pngbin0 -> 1182 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_3.pngbin0 -> 1108 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_1.pngbin0 -> 532 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_2.pngbin0 -> 593 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/sliders_off.pngbin0 -> 835 bytes
-rw-r--r--src/plugins/studiowelcome/qml/splashscreen/welcome_windows/welcome_1.pngbin0 -> 732 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/AccountImage.qml55
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml70
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml189
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/MyButton.qml51
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/MyTabButton.qml33
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml70
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/SaturationEffect.qml37
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/TutorialsModel.qml88
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/coffeemachinedemo_thumbnail.pngbin0 -> 41491 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/designer_and_developers.pngbin0 -> 92433 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/ebike_demo_thumbnail.pngbin0 -> 17612 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/icon_default.pngbin0 -> 289 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/icon_hover.pngbin0 -> 289 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/progressbar_demo.pngbin0 -> 6012 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/qtws_video_thumbnail.pngbin0 -> 60216 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/ready_to_go.pngbin0 -> 37363 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/sidemenu_demo.pngbin0 -> 45862 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/thumbnail_test.pngbin0 -> 32580 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/tutorial1.pngbin0 -> 28717 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/tutorial2.pngbin0 -> 20299 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/tutorial3.pngbin0 -> 28298 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/tutorial4.pngbin0 -> 44785 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/tutorial5.pngbin0 -> 40981 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/tutorialclusterdemo_thumbnail.pngbin0 -> 50213 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/webinar1.pngbin0 -> 54944 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/webinar2.pngbin0 -> 32635 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/images/webinardemo_thumbnail.pngbin0 -> 52855 bytes
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/imports/welcome/Constants.qml37
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/imports/welcome/qmldir1
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/main.qml204
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml138
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/qmldir1
-rw-r--r--src/plugins/studiowelcome/qml/welcomepage/welcomepage.qmlproject47
-rw-r--r--src/plugins/studiowelcome/studiowelcome.pro27
-rw-r--r--src/plugins/studiowelcome/studiowelcome.qrc6
-rw-r--r--src/plugins/studiowelcome/studiowelcome_dependencies.pri10
-rw-r--r--src/plugins/studiowelcome/studiowelcome_global.h34
-rw-r--r--src/plugins/studiowelcome/studiowelcomeplugin.cpp325
-rw-r--r--src/plugins/studiowelcome/studiowelcomeplugin.h53
-rw-r--r--src/plugins/subversion/CMakeLists.txt13
-rw-r--r--src/plugins/subversion/subversionclient.cpp2
-rw-r--r--src/plugins/subversion/subversionclient.h2
-rw-r--r--src/plugins/subversion/subversioncontrol.cpp6
-rw-r--r--src/plugins/subversion/subversioncontrol.h4
-rw-r--r--src/plugins/subversion/subversionplugin.cpp2
-rw-r--r--src/plugins/subversion/subversionplugin.h2
-rw-r--r--src/plugins/tasklist/CMakeLists.txt8
-rw-r--r--src/plugins/tasklist/taskfile.cpp2
-rw-r--r--src/plugins/tasklist/taskfile.h2
-rw-r--r--src/plugins/tasklist/tasklistplugin.cpp16
-rw-r--r--src/plugins/tasklist/tasklistplugin.h6
-rw-r--r--src/plugins/texteditor/CMakeLists.txt108
-rw-r--r--src/plugins/texteditor/autocompleter.cpp6
-rw-r--r--src/plugins/texteditor/autocompleter.h4
-rw-r--r--src/plugins/texteditor/basefilefind.cpp39
-rw-r--r--src/plugins/texteditor/basehoverhandler.cpp2
-rw-r--r--src/plugins/texteditor/behaviorsettingswidget.cpp2
-rw-r--r--src/plugins/texteditor/codeassist/assistproposalitem.h1
-rw-r--r--src/plugins/texteditor/codeassist/assistproposaliteminterface.h3
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.cpp39
-rw-r--r--src/plugins/texteditor/codeassist/documentcontentcompletion.h2
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalmodel.cpp14
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalmodel.h1
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalwidget.cpp19
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposalmodel.h1
-rw-r--r--src/plugins/texteditor/codeassist/keywordscompletionassist.cpp99
-rw-r--r--src/plugins/texteditor/codeassist/keywordscompletionassist.h13
-rw-r--r--src/plugins/texteditor/codestylepool.cpp14
-rw-r--r--src/plugins/texteditor/codestylepool.h10
-rw-r--r--src/plugins/texteditor/codestyleselectorwidget.cpp8
-rw-r--r--src/plugins/texteditor/colorschemeedit.cpp10
-rw-r--r--src/plugins/texteditor/completionsettings.cpp5
-rw-r--r--src/plugins/texteditor/completionsettings.h1
-rw-r--r--src/plugins/texteditor/completionsettingspage.cpp5
-rw-r--r--src/plugins/texteditor/completionsettingspage.ui12
-rw-r--r--src/plugins/texteditor/findincurrentfile.cpp2
-rw-r--r--src/plugins/texteditor/findinfiles.cpp14
-rw-r--r--src/plugins/texteditor/findinfiles.h8
-rw-r--r--src/plugins/texteditor/fontsettingspage.cpp9
-rw-r--r--src/plugins/texteditor/highlighter.cpp34
-rw-r--r--src/plugins/texteditor/highlighter.h6
-rw-r--r--src/plugins/texteditor/indenter.h6
-rw-r--r--src/plugins/texteditor/refactoringchanges.cpp3
-rw-r--r--src/plugins/texteditor/refactoroverlay.cpp5
-rw-r--r--src/plugins/texteditor/snippets/snippetssettingspage.cpp2
-rw-r--r--src/plugins/texteditor/tabsettingswidget.cpp4
-rw-r--r--src/plugins/texteditor/textdocument.cpp23
-rw-r--r--src/plugins/texteditor/textdocument.h8
-rw-r--r--src/plugins/texteditor/texteditor.cpp72
-rw-r--r--src/plugins/texteditor/texteditor.h5
-rw-r--r--src/plugins/texteditor/texteditor.pro2
-rw-r--r--src/plugins/texteditor/texteditorsettings.cpp14
-rw-r--r--src/plugins/texteditor/textmark.cpp18
-rw-r--r--src/plugins/texteditor/textmark.h8
-rw-r--r--src/plugins/todo/CMakeLists.txt25
-rw-r--r--src/plugins/todo/cpptodoitemsscanner.cpp2
-rw-r--r--src/plugins/todo/todoitem.h2
-rw-r--r--src/plugins/todo/todoitemsprovider.cpp32
-rw-r--r--src/plugins/todo/todoitemsprovider.h2
-rw-r--r--src/plugins/todo/todoitemsscanner.cpp2
-rw-r--r--src/plugins/todo/todooutputpane.cpp14
-rw-r--r--src/plugins/todo/todooutputpane.h4
-rw-r--r--src/plugins/updateinfo/CMakeLists.txt8
-rw-r--r--src/plugins/updateinfo/settingspage.cpp2
-rw-r--r--src/plugins/updateinfo/updateinfoplugin.cpp11
-rw-r--r--src/plugins/valgrind/CMakeLists.txt63
-rw-r--r--src/plugins/valgrind/callgrind/callgrindcontroller.h2
-rw-r--r--src/plugins/valgrind/callgrind/callgrindparser.cpp7
-rw-r--r--src/plugins/valgrind/callgrindcostdelegate.cpp2
-rw-r--r--src/plugins/valgrind/callgrindtextmark.cpp2
-rw-r--r--src/plugins/valgrind/callgrindtextmark.h2
-rw-r--r--src/plugins/valgrind/callgrindtool.cpp255
-rw-r--r--src/plugins/valgrind/callgrindtool.h14
-rw-r--r--src/plugins/valgrind/callgrindvisualisation.cpp2
-rw-r--r--src/plugins/valgrind/memchecktool.cpp237
-rw-r--r--src/plugins/valgrind/memchecktool.h17
-rw-r--r--src/plugins/valgrind/suppressiondialog.cpp2
-rw-r--r--src/plugins/valgrind/valgrindconfigwidget.cpp12
-rw-r--r--src/plugins/valgrind/valgrindengine.cpp8
-rw-r--r--src/plugins/valgrind/valgrindengine.h2
-rw-r--r--src/plugins/valgrind/valgrindmemcheckparsertest.cpp46
-rw-r--r--src/plugins/valgrind/valgrindplugin.cpp44
-rw-r--r--src/plugins/valgrind/valgrindplugin.h14
-rw-r--r--src/plugins/valgrind/valgrindrunner.cpp91
-rw-r--r--src/plugins/valgrind/valgrindrunner.h2
-rw-r--r--src/plugins/valgrind/valgrindsettings.cpp20
-rw-r--r--src/plugins/valgrind/valgrindsettings.h2
-rw-r--r--src/plugins/vcsbase/CMakeLists.txt39
-rw-r--r--src/plugins/vcsbase/submiteditorfile.cpp6
-rw-r--r--src/plugins/vcsbase/submitfieldwidget.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.cpp6
-rw-r--r--src/plugins/vcsbase/vcsbaseclient.h4
-rw-r--r--src/plugins/vcsbase/vcsbaseclientsettings.cpp8
-rw-r--r--src/plugins/vcsbase/vcsbaseclientsettings.h4
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp10
-rw-r--r--src/plugins/vcsbase/vcsbaseeditorconfig.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.h4
-rw-r--r--src/plugins/vcsbase/vcsbasesubmiteditor.cpp4
-rw-r--r--src/plugins/vcsbase/vcscommand.cpp2
-rw-r--r--src/plugins/vcsbase/vcscommand.h2
-rw-r--r--src/plugins/vcsbase/vcsoutputwindow.cpp103
-rw-r--r--src/plugins/vcsbase/vcsoutputwindow.h9
-rw-r--r--src/plugins/vcsbase/vcsplugin.cpp2
-rw-r--r--src/plugins/vcsbase/wizard/vcscommandpage.cpp4
-rw-r--r--src/plugins/welcome/CMakeLists.txt8
-rw-r--r--src/plugins/welcome/introductionwidget.cpp6
-rw-r--r--src/plugins/winrt/CMakeLists.txt16
-rw-r--r--src/plugins/winrt/winrt.pro4
-rw-r--r--src/plugins/winrt/winrt.qbs5
-rw-r--r--src/plugins/winrt/winrtdebugsupport.cpp2
-rw-r--r--src/plugins/winrt/winrtdevice.cpp273
-rw-r--r--src/plugins/winrt/winrtdevice.h25
-rw-r--r--src/plugins/winrt/winrtdevicefactory.cpp304
-rw-r--r--src/plugins/winrt/winrtdevicefactory.h56
-rw-r--r--src/plugins/winrt/winrtpackagedeploymentstep.cpp12
-rw-r--r--src/plugins/winrt/winrtphoneqtversion.cpp28
-rw-r--r--src/plugins/winrt/winrtphoneqtversion.h18
-rw-r--r--src/plugins/winrt/winrtplugin.cpp20
-rw-r--r--src/plugins/winrt/winrtplugin.h5
-rw-r--r--src/plugins/winrt/winrtqtversion.cpp31
-rw-r--r--src/plugins/winrt/winrtqtversion.h18
-rw-r--r--src/plugins/winrt/winrtqtversionfactory.cpp99
-rw-r--r--src/plugins/winrt/winrtqtversionfactory.h48
-rw-r--r--src/plugins/winrt/winrtrunconfiguration.cpp2
-rw-r--r--src/plugins/winrt/winrtruncontrol.cpp2
-rw-r--r--src/plugins/winrt/winrtruncontrol.h2
-rw-r--r--src/plugins/winrt/winrtrunnerhelper.cpp58
-rw-r--r--src/share/3rdparty/CMakeLists.txt13
-rw-r--r--src/share/3rdparty/studiofonts/StudioFonts/StudioFonts.qml44
-rw-r--r--src/share/3rdparty/studiofonts/StudioFonts/qmldir1
-rw-r--r--src/share/3rdparty/studiofonts/TitilliumWeb-Light.ttfbin0 -> 64004 bytes
-rw-r--r--src/share/3rdparty/studiofonts/TitilliumWeb-Regular.ttfbin0 -> 63660 bytes
-rw-r--r--src/share/3rdparty/studiofonts/TitilliumWeb.txt8
-rw-r--r--src/share/3rdparty/studiofonts/studiofonts.qrc8
-rw-r--r--src/share/CMakeLists.txt2
-rw-r--r--src/share/qtcreator/CMakeLists.txt1
-rw-r--r--src/share/qtcreator/externaltools/CMakeLists.txt13
-rw-r--r--src/shared/CMakeLists.txt6
-rw-r--r--src/shared/clang/clang_installation.pri37
-rw-r--r--src/shared/designerintegrationv2/CMakeLists.txt8
-rw-r--r--src/shared/help/CMakeLists.txt24
-rw-r--r--src/shared/help/bookmarkmanager.cpp2
-rw-r--r--src/shared/proparser/CMakeLists.txt29
-rw-r--r--src/shared/proparser/profileevaluator.cpp5
-rw-r--r--src/shared/proparser/profileevaluator.h1
-rw-r--r--src/shared/proparser/proitems.cpp5
-rw-r--r--src/shared/proparser/proitems.h1
-rw-r--r--src/shared/proparser/prowriter.cpp64
-rw-r--r--src/shared/proparser/prowriter.h4
-rw-r--r--src/shared/proparser/qmakebuiltins.cpp3
-rw-r--r--src/shared/proparser/qmakeevaluator.cpp2
-rw-r--r--src/shared/proparser/qmakeparser.h1
m---------src/shared/qbs0
-rw-r--r--src/shared/qtlockedfile/CMakeLists.txt13
-rw-r--r--src/shared/qtsingleapplication/CMakeLists.txt9
-rw-r--r--src/shared/registryaccess/CMakeLists.txt8
-rw-r--r--src/shared/registryaccess/registryaccess.h1
-rw-r--r--src/tools/3rdparty/CMakeLists.txt1
-rw-r--r--src/tools/3rdparty/cplusplus-keywordgen/CMakeLists.txt5
-rw-r--r--src/tools/CMakeLists.txt48
-rw-r--r--src/tools/buildoutputparser/CMakeLists.txt6
-rw-r--r--src/tools/clangbackend/CMakeLists.txt8
-rw-r--r--src/tools/clangbackend/source/CMakeLists.txt66
-rw-r--r--src/tools/clangbackend/source/clangbackend_global.h20
-rw-r--r--src/tools/clangbackend/source/clangtooltipinfocollector.cpp12
-rw-r--r--src/tools/clangbackend/source/clangtranslationunitupdater.cpp2
-rw-r--r--src/tools/clangbackend/source/codecompleter.cpp4
-rw-r--r--src/tools/clangbackend/source/codecompleter.h1
-rw-r--r--src/tools/clangbackend/source/codecompletionsextractor.cpp6
-rw-r--r--src/tools/clangbackend/source/cursor.cpp4
-rw-r--r--src/tools/clangpchmanagerbackend/CMakeLists.txt9
-rw-r--r--src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp39
-rw-r--r--src/tools/clangpchmanagerbackend/source/CMakeLists.txt49
-rw-r--r--src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp6
-rw-r--r--src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h13
-rw-r--r--src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h8
-rw-r--r--src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h1
-rw-r--r--src/tools/clangpchmanagerbackend/source/builddependencycollector.cpp31
-rw-r--r--src/tools/clangpchmanagerbackend/source/builddependencycollector.h1
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri6
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectbuilddependencyaction.h18
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h7
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectbuilddependencytoolaction.h16
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectusedmacroactionfactory.h4
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectusedmacrosaction.h4
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectusedmacrosandsourcespreprocessorcallbacks.h15
-rw-r--r--src/tools/clangpchmanagerbackend/source/environment.h46
-rw-r--r--src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h3
-rw-r--r--src/tools/clangpchmanagerbackend/source/modifiedtimechecker.h214
-rw-r--r--src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h46
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreator.cpp36
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp18
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchtask.h5
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp56
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchtaskqueue.h6
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp12
-rw-r--r--src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h63
-rw-r--r--src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h8
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp30
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectpartsmanager.h13
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h9
-rw-r--r--src/tools/clangpchmanagerbackend/source/sourceentry.h151
-rw-r--r--src/tools/clangpchmanagerbackend/source/toolchainargumentscache.h12
-rw-r--r--src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.cpp1
-rw-r--r--src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.h1
-rw-r--r--src/tools/clangrefactoringbackend/CMakeLists.txt8
-rw-r--r--src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp35
-rw-r--r--src/tools/clangrefactoringbackend/source/CMakeLists.txt54
-rw-r--r--src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri2
-rw-r--r--src/tools/clangrefactoringbackend/source/collectmacrospreprocessorcallbacks.h19
-rw-r--r--src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp19
-rw-r--r--src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h11
-rw-r--r--src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp3
-rw-r--r--src/tools/clangrefactoringbackend/source/collectsymbolsaction.h67
-rw-r--r--src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.cpp59
-rw-r--r--src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.h59
-rw-r--r--src/tools/clangrefactoringbackend/source/findcursorusr.h4
-rw-r--r--src/tools/clangrefactoringbackend/source/indexdataconsumer.cpp101
-rw-r--r--src/tools/clangrefactoringbackend/source/indexdataconsumer.h29
-rw-r--r--src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h1
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexer.cpp142
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexer.h8
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h25
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexing.h38
-rw-r--r--src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp2
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolscollector.cpp109
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolscollector.h8
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h3
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorage.h108
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorageinterface.h8
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolsvisitorbase.h43
-rw-r--r--src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp5
-rw-r--r--src/tools/cplusplus-shared/utils.cpp2
-rw-r--r--src/tools/iconlister/iconlister.cpp2
-rw-r--r--src/tools/icons/qtcreatoricons.svg261
-rw-r--r--src/tools/iostool/CMakeLists.txt24
-rw-r--r--src/tools/iostool/main.cpp2
m---------src/tools/perfparser0
-rw-r--r--src/tools/qml2puppet/CMakeLists.txt136
-rw-r--r--src/tools/qtcdebugger/CMakeLists.txt18
-rw-r--r--src/tools/qtcdebugger/main.cpp9
-rw-r--r--src/tools/qtcrashhandler/CMakeLists.txt7
-rw-r--r--src/tools/qtcreatorcrashhandler/CMakeLists.txt11
-rw-r--r--src/tools/qtcreatorcrashhandler/backtracecollector.cpp6
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandler.cpp2
-rw-r--r--src/tools/qtcreatorwidgets/CMakeLists.txt20
-rw-r--r--src/tools/qtpromaker/CMakeLists.txt1
-rw-r--r--src/tools/screenshotcropper/CMakeLists.txt22
-rw-r--r--src/tools/sdktool/CMakeLists.txt59
-rw-r--r--src/tools/sdktool/addcmakeoperation.cpp4
-rw-r--r--src/tools/sdktool/addkitoperation.cpp2
-rw-r--r--src/tools/sdktool/addqtoperation.cpp4
-rw-r--r--src/tools/sdktool/addtoolchainoperation.cpp4
-rw-r--r--src/tools/sdktool/main.cpp4
-rw-r--r--src/tools/sdktool/operation.cpp6
-rw-r--r--src/tools/sdktool/sdktool.pro5
-rw-r--r--src/tools/sdktool/sdktool.qbs5
-rw-r--r--src/tools/sdktool/settings.cpp26
-rw-r--r--src/tools/sdktool/settings.h4
-rw-r--r--src/tools/tools.pro14
-rw-r--r--src/tools/valgrindfake/CMakeLists.txt5
-rw-r--r--src/tools/wininterrupt/CMakeLists.txt12
-rw-r--r--src/tools/winrtdebughelper/CMakeLists.txt13
-rw-r--r--tests/CMakeLists.txt4
-rw-r--r--tests/auto/CMakeLists.txt25
-rw-r--r--tests/auto/aggregation/CMakeLists.txt4
-rw-r--r--tests/auto/algorithm/CMakeLists.txt4
-rw-r--r--tests/auto/changeset/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/CMakeLists.txt15
-rw-r--r--tests/auto/cplusplus/ast/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/ast/tst_ast.cpp2
-rw-r--r--tests/auto/cplusplus/c99/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/c99/tst_c99.cpp5
-rw-r--r--tests/auto/cplusplus/checksymbols/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/codeformatter/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/cxx11/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/cxx11/tst_cxx11.cpp5
-rw-r--r--tests/auto/cplusplus/fileiterationorder/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/findusages/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/lexer/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/lookup/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/misc/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/preprocessor/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/semantic/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/semantic/tst_semantic.cpp2
-rw-r--r--tests/auto/cplusplus/translationunit/CMakeLists.txt4
-rw-r--r--tests/auto/cplusplus/translationunit/tst_translationunit.cpp2
-rw-r--r--tests/auto/cplusplus/typeprettyprinter/CMakeLists.txt4
-rw-r--r--tests/auto/debugger/CMakeLists.txt53
-rw-r--r--tests/auto/debugger/tst_dumpers.cpp7
-rw-r--r--tests/auto/diff/CMakeLists.txt1
-rw-r--r--tests/auto/diff/differ/CMakeLists.txt4
-rw-r--r--tests/auto/environment/CMakeLists.txt4
-rw-r--r--tests/auto/extensionsystem/CMakeLists.txt2
-rw-r--r--tests/auto/extensionsystem/pluginmanager/CMakeLists.txt9
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/CMakeLists.txt4
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/CMakeLists.txt7
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/CMakeLists.txt7
-rw-r--r--tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/CMakeLists.txt7
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/CMakeLists.txt4
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/CMakeLists.txt8
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/CMakeLists.txt8
-rw-r--r--tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/CMakeLists.txt8
-rw-r--r--tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp2
-rw-r--r--tests/auto/extensionsystem/pluginspec/CMakeLists.txt10
-rw-r--r--tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt22
-rw-r--r--tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp8
-rw-r--r--tests/auto/externaltool/CMakeLists.txt7
-rw-r--r--tests/auto/filesearch/CMakeLists.txt6
-rw-r--r--tests/auto/json/CMakeLists.txt7
-rw-r--r--tests/auto/languageserverprotocol/CMakeLists.txt4
-rw-r--r--tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp16
-rw-r--r--tests/auto/mapreduce/CMakeLists.txt4
-rw-r--r--tests/auto/pointeralgorithm/CMakeLists.txt4
-rw-r--r--tests/auto/profilewriter/CMakeLists.txt5
-rw-r--r--tests/auto/qml/CMakeLists.txt8
-rw-r--r--tests/auto/qml/codemodel/CMakeLists.txt4
-rw-r--r--tests/auto/qml/codemodel/check/CMakeLists.txt8
-rw-r--r--tests/auto/qml/codemodel/dependencies/CMakeLists.txt9
-rw-r--r--tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp4
-rw-r--r--tests/auto/qml/codemodel/ecmascript7/CMakeLists.txt9
-rw-r--r--tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp8
-rw-r--r--tests/auto/qml/codemodel/importscheck/CMakeLists.txt9
-rw-r--r--tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp4
-rw-r--r--tests/auto/qml/persistenttrie/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qml.pro6
-rw-r--r--tests/auto/qml/qmldesigner/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmldesigner/coretests/CMakeLists.txt20
-rw-r--r--tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp40
-rw-r--r--tests/auto/qml/qmldesigner/coretests/tst_testcore.h1
-rw-r--r--tests/auto/qml/qmleditor/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmleditor/qmlcodeformatter/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qmljssimplereader/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qmlprojectmanager/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmlprojectmanager/fileformat/CMakeLists.txt15
-rw-r--r--tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp2
-rw-r--r--tests/auto/qml/qrcparser/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qrcparser/qrcparser.pro2
-rw-r--r--tests/auto/qml/qrcparser/qrcparser.qbs5
-rw-r--r--tests/auto/qml/qrcparser/tst_qrcparser.cpp4
-rw-r--r--tests/auto/qml/reformatter/CMakeLists.txt8
-rw-r--r--tests/auto/qml/reformatter/comments.qml8
-rw-r--r--tests/auto/qml/reformatter/enum.qml14
-rw-r--r--tests/auto/qml/reformatter/jssyntax.js10
-rw-r--r--tests/auto/qml/reformatter/objectliteral.js2
-rw-r--r--tests/auto/qml/reformatter/qmlsingleton.qml3
-rw-r--r--tests/auto/qml/reformatter/qmlsyntax.qml4
-rw-r--r--tests/auto/qtcprocess/CMakeLists.txt4
-rw-r--r--tests/auto/runextensions/CMakeLists.txt4
-rw-r--r--tests/auto/sdktool/CMakeLists.txt5
-rw-r--r--tests/auto/sdktool/tst_sdktool.cpp4
-rw-r--r--tests/auto/ssh/CMakeLists.txt4
-rw-r--r--tests/auto/ssh/tst_ssh.cpp19
-rw-r--r--tests/auto/toolchaincache/CMakeLists.txt5
-rw-r--r--tests/auto/toolchaincache/toolchaincache.pro2
-rw-r--r--tests/auto/toolchaincache/toolchaincache.qbs1
-rw-r--r--tests/auto/tracing/CMakeLists.txt14
-rw-r--r--tests/auto/tracing/flamegraph/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/flamegraphview/CMakeLists.txt6
-rw-r--r--tests/auto/tracing/timelineabstractrenderer/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelineitemsrenderpass/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinemodel/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinemodelaggregator/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinenotesmodel/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinenotesrenderpass/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelineoverviewrenderer/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinerenderer/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinerenderpass/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinerenderstate/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelineselectionrenderpass/CMakeLists.txt4
-rw-r--r--tests/auto/tracing/timelinezoomcontrol/CMakeLists.txt4
-rw-r--r--tests/auto/treeviewfind/CMakeLists.txt4
-rw-r--r--tests/auto/utils/CMakeLists.txt7
-rw-r--r--tests/auto/utils/ansiescapecodehandler/CMakeLists.txt4
-rw-r--r--tests/auto/utils/fileutils/CMakeLists.txt4
-rw-r--r--tests/auto/utils/fileutils/tst_fileutils.cpp6
-rw-r--r--tests/auto/utils/fuzzymatcher/CMakeLists.txt4
-rw-r--r--tests/auto/utils/settings/CMakeLists.txt4
-rw-r--r--tests/auto/utils/settings/tst_settings.cpp44
-rw-r--r--tests/auto/utils/stringutils/CMakeLists.txt4
-rw-r--r--tests/auto/utils/stringutils/tst_stringutils.cpp12
-rw-r--r--tests/auto/utils/templateengine/CMakeLists.txt4
-rw-r--r--tests/auto/utils/treemodel/CMakeLists.txt4
-rw-r--r--tests/auto/valgrind/callgrind/modeltest.cpp2
-rw-r--r--tests/auto/valgrind/memcheck/memcheck.qbs1
-rw-r--r--tests/auto/valgrind/valgrind.qbs1
-rw-r--r--tests/manual/debugger/simple/simple_test_app.cpp7
-rw-r--r--tests/manual/proparser/testreader.pro8
-rw-r--r--tests/system/objects.map28
-rw-r--r--tests/system/shared/build_utils.py5
-rw-r--r--tests/system/shared/debugger.py2
-rw-r--r--tests/system/shared/project.py11
-rw-r--r--tests/system/shared/qtcreator.py2
-rwxr-xr-xtests/system/suite_HELP/tst_HELP02/test.py2
-rw-r--r--tests/system/suite_debugger/tst_qml_locals/test.py3
-rw-r--r--tests/system/suite_editors/tst_edit_externally/test.py3
-rw-r--r--tests/system/suite_general/tst_create_proj_wizard/test.py2
-rw-r--r--tests/system/suite_general/tst_default_settings/test.py10
-rw-r--r--tests/system/suite_general/tst_rename_file/test.py6
-rw-r--r--tests/system/suite_tools/tst_git_clone/test.py2
-rw-r--r--tests/unit/CMakeLists.txt2
-rw-r--r--tests/unit/echoserver/CMakeLists.txt8
-rw-r--r--tests/unit/mockup/coreplugin/icore.h5
-rw-r--r--tests/unit/mockup/projectexplorer/project.h8
-rw-r--r--tests/unit/mockup/projectexplorer/toolchain.h13
-rw-r--r--tests/unit/unittest/CMakeLists.txt413
-rw-r--r--tests/unit/unittest/builddependenciesprovider-test.cpp17
-rw-r--r--tests/unit/unittest/builddependenciesstorage-test.cpp11
-rw-r--r--tests/unit/unittest/builddependencycollector-test.cpp99
-rw-r--r--tests/unit/unittest/clangdocument-test.cpp4
-rw-r--r--tests/unit/unittest/clangfollowsymbol-test.cpp4
-rw-r--r--tests/unit/unittest/clangformat-test.cpp4
-rw-r--r--tests/unit/unittest/clangqueryprojectfindfilter-test.cpp113
-rw-r--r--tests/unit/unittest/clangreferencescollector-test.cpp4
-rw-r--r--tests/unit/unittest/clangtooltipinfo-test.cpp14
-rw-r--r--tests/unit/unittest/clangupdateannotationsjob-test.cpp6
-rw-r--r--tests/unit/unittest/codecompletionsextractor-test.cpp4
-rw-r--r--tests/unit/unittest/commandlinebuilder-test.cpp39
-rw-r--r--tests/unit/unittest/compilationdatabaseutils-test.cpp188
-rw-r--r--tests/unit/unittest/conditionally-disabled-tests.h12
-rw-r--r--tests/unit/unittest/cppprojectinfogenerator-test.cpp3
-rw-r--r--tests/unit/unittest/cursor-test.cpp4
-rw-r--r--tests/unit/unittest/data/preincludes/system1.h1
-rw-r--r--tests/unit/unittest/diagnostic-test.cpp6
-rw-r--r--tests/unit/unittest/diagnosticset-test.cpp6
-rw-r--r--tests/unit/unittest/filesystem-utilities.h9
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp41
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h10
-rw-r--r--tests/unit/unittest/headerpathfilter-test.cpp17
-rw-r--r--tests/unit/unittest/highlightingresultreporter-test.cpp4
-rw-r--r--tests/unit/unittest/matchingtext-test.cpp35
-rw-r--r--tests/unit/unittest/mockbuilddependenciesstorage.h2
-rw-r--r--tests/unit/unittest/mockmodifiedtimechecker.h10
-rw-r--r--tests/unit/unittest/mockpchmanagernotifier.h5
-rw-r--r--tests/unit/unittest/mockprecompiledheaderstorage.h9
-rw-r--r--tests/unit/unittest/mockprojectpartsmanager.h5
-rw-r--r--tests/unit/unittest/mockprojectpartsstorage.h2
-rw-r--r--tests/unit/unittest/mocksqlitedatabase.h5
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.cpp25
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.h25
-rw-r--r--tests/unit/unittest/mocksymbolstorage.h7
-rw-r--r--tests/unit/unittest/modifiedtimechecker-test.cpp2
-rw-r--r--tests/unit/unittest/pchcreator-test.cpp55
-rw-r--r--tests/unit/unittest/pchmanagerclient-test.cpp61
-rw-r--r--tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp2
-rw-r--r--tests/unit/unittest/pchmanagerserver-test.cpp28
-rw-r--r--tests/unit/unittest/pchtaskqueue-test.cpp16
-rw-r--r--tests/unit/unittest/precompiledheaderstorage-test.cpp108
-rw-r--r--tests/unit/unittest/projectpartsmanager-test.cpp134
-rw-r--r--tests/unit/unittest/projectpartsstorage-test.cpp102
-rw-r--r--tests/unit/unittest/projectupdater-test.cpp156
-rw-r--r--tests/unit/unittest/refactoringclient-test.cpp46
-rw-r--r--tests/unit/unittest/refactoringdatabaseinitializer-test.cpp107
-rw-r--r--tests/unit/unittest/refactoringengine-test.cpp28
-rw-r--r--tests/unit/unittest/refactoringprojectupdater-test.cpp8
-rw-r--r--tests/unit/unittest/skippedsourceranges-test.cpp4
-rw-r--r--tests/unit/unittest/sourcerange-test.cpp4
-rw-r--r--tests/unit/unittest/symbolindexer-test.cpp994
-rw-r--r--tests/unit/unittest/symbolindexertaskqueue-test.cpp35
-rw-r--r--tests/unit/unittest/symbolindexing-test.cpp8
-rw-r--r--tests/unit/unittest/symbolscollector-test.cpp219
-rw-r--r--tests/unit/unittest/symbolstorage-test.cpp153
-rw-r--r--tests/unit/unittest/testenvironment.h28
-rw-r--r--tests/unit/unittest/token-test.cpp4
-rw-r--r--tests/unit/unittest/tokenprocessor-test.cpp8
-rw-r--r--tests/unit/unittest/translationunitupdater-test.cpp2
-rw-r--r--tests/unit/unittest/unittest-utility-functions.h12
-rw-r--r--tests/unit/unittest/unittest.pro5
2835 files changed, 82315 insertions, 41263 deletions
diff --git a/.gitignore b/.gitignore
index 5dbedd7022..9a6c349f80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,6 +45,7 @@ wrapper.sh
*.pyqtc.user*
*.qbs.user*
*.qmlproject.user*
+CMakeLists.txt.user
/share/qtcreator/externaltools
/share/qtcreator/fonts/
/share/qtcreator/generic-highlighter/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000..46ab6b8da7
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,197 @@
+cmake_minimum_required(VERSION 3.9)
+
+## Add paths to check for cmake modules:
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+include(FeatureSummary)
+include(QtCreatorIDEBranding)
+
+set(IDE_REVISION FALSE CACHE BOOL "Marks the presence of IDE revision string.")
+set(IDE_REVISION_STR "" CACHE STRING "The IDE revision string.")
+
+mark_as_advanced(IDE_REVISION IDE_REVISION_STR)
+
+project(QtCreator VERSION ${IDE_VERSION})
+
+# Force C++ standard, do not fall back, do not use compiler extensions
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+option(WITH_TESTS "Build Tests" OFF)
+option(WITH_DEBUG_CMAKE "Enabled CMake project debugging functionality (e.g. source file disk checking)" OFF)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+# Set up Qt stuff:
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTOUIC ON)
+
+if (WITH_TESTS)
+ set(_TEST_QT_COMPONENT Test)
+ set(_TEST_DEPENDS Qt5::Test)
+endif()
+
+find_package(Qt5
+ COMPONENTS Concurrent Core Network PrintSupport Qml Quick QuickWidgets
+ Sql ${_TEST_QT_COMPONENT}
+ REQUIRED
+)
+
+find_package(Threads)
+
+# Get information on directories from qmake
+# as this is not yet exported by cmake.
+function(qt5_query_qmake)
+ if (NOT TARGET Qt5::qmake)
+ message(FATAL_ERROR "Qmake was not found.")
+ endif()
+
+ get_target_property(_qmake_binary Qt5::qmake IMPORTED_LOCATION)
+ execute_process(COMMAND "${_qmake_binary}" "-query"
+ TIMEOUT 10
+ RESULT_VARIABLE _qmake_result
+ OUTPUT_VARIABLE _qmake_stdout
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ if (NOT "${_qmake_result}" STREQUAL "0")
+ message(FATAL_ERROR "Qmake did not execute successfully: ${_qmake_result}.")
+ endif()
+
+ # split into lines:
+ string(REPLACE "\n" ";" _lines "${_qmake_stdout}")
+
+ foreach(_line ${_lines})
+ # split line into key/value pairs
+ string(REPLACE ":" ";" _parts "${_line}")
+ list(GET _parts 0 _key)
+ list(REMOVE_AT _parts 0)
+ string(REPLACE ";" ":" _value "${_parts}")
+
+ set("${_key}" "${_value}" CACHE PATH "qmake import of ${_key}" FORCE)
+ endforeach()
+endfunction()
+
+qt5_query_qmake()
+
+find_package(Qt5 COMPONENTS Designer Help Script SerialPort Svg QUIET)
+function (set_if_target var target)
+ if (TARGET "${target}")
+ set(_result ON)
+ else()
+ set(_result OFF)
+ endif()
+ set(${var} "${_result}" PARENT_SCOPE)
+endfunction()
+
+set_if_target(_has_svg_target Qt5::Svg)
+option(ENABLE_SVG_SUPPORT "Enable SVG support" "${_has_svg_target}")
+
+add_library(OptionalSvg INTERFACE)
+if (TARGET Qt5::Svg AND ENABLE_SVG_SUPPORT)
+ target_link_libraries(OptionalSvg INTERFACE Qt5::Svg)
+else()
+ target_compile_definitions(OptionalSvg INTERFACE QT_NO_SVG)
+endif()
+
+find_package(LLVM QUIET)
+find_package(Clang COMPONENTS libclang QUIET)
+
+if (APPLE)
+ find_library(FWCoreFoundation CoreFoundation)
+ find_library(FWCoreServices CoreServices)
+ find_library(FWFoundation Foundation)
+ find_library(FWAppKit AppKit)
+ find_library(FWIOKit IOKit)
+ find_library(FWSecurity Security)
+ find_library(FWSystemConfiguration SystemConfiguration)
+ find_library(FWWebKit WebKit)
+endif()
+
+set(_IDE_APP_PATH "bin")
+
+if (APPLE)
+ set(_IDE_APP_TARGET "${IDE_DISPLAY_NAME}")
+
+ set(_IDE_OUTPUT_PATH "${_IDE_APP_PATH}/${_IDE_APP_TARGET}.app/Contents")
+
+ set(_IDE_PLUGIN_PATH "${_IDE_OUTPUT_PATH}/PlugIns")
+ set(_IDE_LIBRARY_BASE_PATH "Frameworks")
+ set(_IDE_LIBRARY_PATH "${_IDE_OUTPUT_PATH}/Frameworks")
+ set(_IDE_LIBEXEC_PATH "${_IDE_OUTPUT_PATH}/Resources")
+ set(_IDE_DATA_PATH "${_IDE_OUTPUT_PATH}/Resources")
+ set(_IDE_DOC_PATH "${_IDE_OUTPUT_PATH}/Resources/doc")
+ set(_IDE_BIN_PATH "${_IDE_OUTPUT_PATH}/MacOS")
+else ()
+ set(_IDE_APP_TARGET "${IDE_ID}")
+
+ set(_IDE_LIBRARY_BASE_PATH "lib")
+ set(_IDE_LIBRARY_PATH "lib/qtcreator")
+ set(_IDE_PLUGIN_PATH "lib/qtcreator/plugins")
+ if (WIN32)
+ set(_IDE_LIBEXEC_PATH "bin")
+ else ()
+ set(_IDE_LIBEXEC_PATH "libexec/qtcreator/bin")
+ endif ()
+ set(_IDE_DATA_PATH "share/qtcreator")
+ set(_IDE_DOC_PATH "share/doc/qtcreator")
+ set(_IDE_BIN_PATH "bin")
+endif ()
+
+set(IDE_APP_PATH "${_IDE_APP_PATH}") # The target path of the IDE application (relative to CMAKE_INSTALL_PREFIX).
+set(IDE_APP_TARGET "${_IDE_APP_TARGET}") # The IDE application name.
+set(IDE_PLUGIN_PATH "${_IDE_PLUGIN_PATH}") # The IDE plugin path (relative to CMAKE_INSTALL_PREFIX).
+set(IDE_LIBRARY_BASE_PATH "${_IDE_LIBRARY_BASE_PATH}") # The IDE library base path (relative to CMAKE_INSTALL_PREFIX).
+set(IDE_LIBRARY_PATH "${_IDE_LIBRARY_PATH}") # The IDE library path (relative to CMAKE_INSTALL_PREFIX).
+set(IDE_LIBEXEC_PATH "${_IDE_LIBEXEC_PATH}") # The IDE libexec path (relative to CMAKE_INSTALL_PREFIX).
+set(IDE_DATA_PATH "${_IDE_DATA_PATH}") # The IDE data path (relative to CMAKE_INSTALL_PREFIX).
+set(IDE_DOC_PATH "${_IDE_DOC_PATH}") # The IDE documentation path (relative to CMAKE_INSTALL_PREFIX).
+set(IDE_BIN_PATH "${_IDE_BIN_PATH}") # The IDE bin path (relative to CMAKE_INSTALL_PREFIX).
+
+file(RELATIVE_PATH RELATIVE_PLUGIN_PATH "/${IDE_BIN_PATH}" "/${IDE_PLUGIN_PATH}")
+file(RELATIVE_PATH RELATIVE_LIBEXEC_PATH "/${IDE_BIN_PATH}" "/${IDE_LIBEXEC_PATH}")
+file(RELATIVE_PATH RELATIVE_DATA_PATH "/${IDE_BIN_PATH}" "/${IDE_DATA_PATH}")
+file(RELATIVE_PATH RELATIVE_DOC_PATH "/${IDE_BIN_PATH}" "/${IDE_DOC_PATH}")
+
+list(APPEND DEFAULT_DEFINES
+ RELATIVE_PLUGIN_PATH="${RELATIVE_PLUGIN_PATH}"
+ RELATIVE_LIBEXEC_PATH="${RELATIVE_LIBEXEC_PATH}"
+ RELATIVE_DATA_PATH="${RELATIVE_DATA_PATH}"
+ RELATIVE_DOC_PATH="${RELATIVE_DOC_PATH}"
+)
+
+file(RELATIVE_PATH _PLUGIN_TO_LIB "/${IDE_PLUGIN_PATH}" "/${IDE_LIBRARY_PATH}")
+
+if (APPLE)
+ set(_RPATH_BASE "@executable_path")
+ set(_LIB_RPATH "@loader_path")
+ set(_PLUGIN_RPATH "@loader_path;@loader_path/${_PLUGIN_TO_LIB}")
+elseif (WIN32)
+ set(_RPATH_BASE "")
+ set(_LIB_RPATH "")
+ set(_PLUGIN_RPATH "")
+else()
+ set(_RPATH_BASE "\$ORIGIN")
+ set(_LIB_RPATH "\$ORIGIN")
+ set(_PLUGIN_RPATH "\$ORIGIN;\$ORIGIN/${_PLUGIN_TO_LIB}")
+endif ()
+
+if (UNIX)
+ add_subdirectory(bin)
+endif()
+
+add_subdirectory(src)
+add_subdirectory(share)
+
+if (WITH_TESTS)
+ enable_testing()
+ add_subdirectory(tests)
+endif()
+
+add_subdirectory(doc)
+
+feature_summary(INCLUDE_QUIET_PACKAGES WHAT
+ PACKAGES_FOUND PACKAGES_NOT_FOUND
+ ENABLED_FEATURES DISABLED_FEATURES
+)
diff --git a/README.md b/README.md
index 34bdf6a50b..2293ae8015 100644
--- a/README.md
+++ b/README.md
@@ -25,18 +25,19 @@ https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html
Prerequisites:
-* Qt 5.9.0 or later
+* Qt 5.11.0 or later
* Qt WebEngine module for QtWebEngine based help viewer
* On Windows:
* ActiveState Active Perl
- * MinGW with g++ 5.3 or Visual Studio 2015 or later
+ * MinGW with g++ 5.3 or Visual Studio 2017 or later
* jom
* Python 3.5 or later (optional, needed for the python enabled debug helper)
* On Mac OS X: latest Xcode
* On Linux: g++ 5.3 or later
-* LLVM/Clang 7.0.0 or later (optional, needed for the Clang Code Model, Clang Tools, ClangFormat,
+* LLVM/Clang 8.0.0 or later (optional, needed for the Clang Code Model, Clang Tools, ClangFormat,
Clang PCH Manager and Clang Refactoring plugins, see the section
- "Get LLVM/Clang for the Clang Code Model")
+ "Get LLVM/Clang for the Clang Code Model". The LLVM C++ API provides no compatibility garantee,
+ so if later versions don't compile we don't support that version.)
* CMake (only for manual builds of LLVM/Clang)
* Qbs 1.7.x (optional, sources also contain Qbs itself)
@@ -46,6 +47,8 @@ You can build Qt Creator with
# Optional, needed for the Clang Code Model if llvm-config is not in PATH:
export LLVM_INSTALL_DIR=/path/to/llvm (or "set" on Windows)
+ # Optional, disable Clang Refactoring
+ export QTC_DISABLE_CLANG_REFACTORING=1
# Optional, needed to let the QbsProjectManager plugin use system Qbs:
export QBS_INSTALL_DIR=/path/to/qbs
# Optional, needed for the Python enabled dumper on Windows
@@ -68,7 +71,7 @@ Installation ("make install") is not needed. It is however possible, using
This section provides step by step instructions for compiling the latest
versions of Qt and Qt Creator on Windows. Alternatively, to avoid having to
compile Qt yourself, you can use one of the versions of Qt shipped with the Qt
-SDK (release builds of Qt using MinGW and Visual C++ 2015 or later).
+SDK (release builds of Qt using MinGW and Visual C++ 2017 or later).
For detailed information on the supported compilers, see
<https://wiki.qt.io/Building_Qt_5_from_Git> .
@@ -85,7 +88,7 @@ For detailed information on the supported compilers, see
for example, `c:\work`. If you plan to use MinGW and Microsoft Visual
Studio simultaneously or mix different Qt versions, we recommend
creating a directory structure which reflects that. For example:
- `C:\work\qt5.9.0-vs12, C:\work\qt5.9.0-mingw`.
+ `C:\work\qt5.11.0-vs15, C:\work\qt5.11.0-mingw`.
4. Download and install Perl from <https://www.activestate.com/activeperl>
and check that perl.exe is added to the path. Run `perl -v` to verify
@@ -152,8 +155,6 @@ For detailed information on the supported compilers, see
* Before you launch Qt Creator you may prepend the PATH with
the location of libclang.dll/.so that you want to be used.
See more info in the section "Prebuilt LLVM/Clang packages".
- * When you launch Qt Creator, activate the Clang Code Model plugin as
- described in doc/src/editors/creator-only/creator-clang-codemodel.qdoc.
11. You are now ready to configure and build Qt and Qt Creator.
Please see <https://wiki.qt.io/Building_Qt_5_from_Git> for
@@ -225,7 +226,7 @@ or using shadow builds.
## Get LLVM/Clang for the Clang Code Model
The Clang Code Model depends on the LLVM/Clang libraries. The currently
-supported LLVM/Clang version is 7.0.
+supported LLVM/Clang version is 8.0.
### Prebuilt LLVM/Clang packages
@@ -234,9 +235,10 @@ Prebuilt packages of LLVM/Clang can be downloaded from
https://download.qt.io/development_releases/prebuilt/libclang/
This should be your preferred option because you will use the version that is
-shipped together with Qt Creator. In addition, MinGW packages for Windows are
-faster due to profile-guided optimization. If the prebuilt packages do not
-match your configuration, you need to build LLVM/Clang manually.
+shipped together with Qt Creator (with backported/additional patches). In
+addition, MinGW packages for Windows are faster due to profile-guided
+optimization. If the prebuilt packages do not match your configuration, you
+need to build LLVM/Clang manually.
If you use the MSVC compiler to build Qt Creator the suggested way is:
1. Download both MSVC and MinGW packages of libclang.
@@ -244,23 +246,6 @@ If you use the MSVC compiler to build Qt Creator the suggested way is:
3. Prepend PATH variable used for the run time with the location of MinGW version of libclang.dll.
4. Launch Qt Creator.
-If you use GCC 5 or higher on Linux, please do not use our LLVM package, but get
-the package for your distribution. Our LLVM package is compiled with GCC 4, so
-you get linking errors, because GCC 5 is using a C++ 11 conforming string
-implementation, which is not used by GCC 4. To sum it up, do not mix GCC 5 and
-GCC 4 binaries. On Ubuntu, you can download the package from
-http://apt.llvm.org/ with:
-
- wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
- sudo apt-add-repository "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-7.0 main"
- sudo apt-get update
- sudo apt-get install llvm-7.0 libclang-7.0-dev
-
-There is a workaround to set _GLIBCXX_USE_CXX11_ABI to 1 or 0, but we recommend
-to download the package from http://apt.llvm.org/.
-
- https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
-
### Building LLVM/Clang manually
You need to install CMake in order to build LLVM/Clang.
@@ -268,9 +253,9 @@ You need to install CMake in order to build LLVM/Clang.
Build LLVM/Clang by roughly following the instructions at
http://llvm.org/docs/GettingStarted.html#git-mirror:
- 1. Clone LLVM and checkout a suitable branch
+ 1. Clone LLVM/Clang and checkout a suitable branch
- git clone -b release_70-based --recursive https://code.qt.io/clang/llvm
+ git clone -b release_80-based --recursive https://code.qt.io/clang/llvm-project.git
2. Build and install LLVM/Clang
@@ -279,12 +264,12 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
For Linux/macOS:
- cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<installation location> -DLLVM_ENABLE_RTTI=ON ../llvm
+ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_INSTALL_PREFIX=<installation location> ../llvm-project/llvm
make install
For Windows:
- cmake -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<installation location> -DLLVM_ENABLE_RTTI=ON ..\llvm
+ cmake -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_INSTALL_PREFIX=<installation location> ..\llvm-project\llvm
jom install
## Third-party Components
@@ -343,18 +328,14 @@ we thank the authors who made this possible:
### LLVM/Clang
- http://llvm.org/svn/llvm-project/llvm
- http://llvm.org/svn/llvm-project/cfe/trunk
- http://llvm.org/svn/llvm-project/clang-tools-extra/trunk
+ https://github.com/llvm/llvm-project.git
- Copyright (C) 2003-2018 LLVM Team
+ Copyright (C) 2003-2019 LLVM Team
Distributed under the University of Illinois/NCSA Open Source License (NCSA),
- see https://github.com/llvm-mirror/llvm/blob/master/LICENSE.TXT
+ see https://github.com/llvm/llvm-project/blob/master/llvm/LICENSE.TXT
- With backported/additional patches from
- http://code.qt.io/cgit/clang/llvm.git/
- http://code.qt.io/cgit/clang/clang.git/
+ With backported/additional patches from https://code.qt.io/clang/llvm-project.git
### Reference implementation for std::experimental::optional
diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt
new file mode 100644
index 0000000000..60b1bb7d35
--- /dev/null
+++ b/bin/CMakeLists.txt
@@ -0,0 +1 @@
+install(PROGRAMS qtcreator.sh DESTINATION bin)
diff --git a/cmake/FindDesignerComponents.cmake b/cmake/FindDesignerComponents.cmake
new file mode 100644
index 0000000000..58f957b468
--- /dev/null
+++ b/cmake/FindDesignerComponents.cmake
@@ -0,0 +1,69 @@
+#.rst:
+# FindDesignerComponents
+# ---------
+#
+# Try to locate the DesignerComponents library.
+# If found, this will define the following variables:
+#
+# ``DesignerComponents_FOUND``
+# True if the DesignerComponents library is available
+# ``DesignerComponents_INCLUDE_DIRS``
+# The DesignerComponents include directories
+# ``DesignerComponents_LIBRARIES``
+# The DesignerComponentscore library for linking
+# ``DesignerComponents_INSTALL_DIR``
+# Top level DesignerComponents installation directory
+#
+# If ``DesignerComponents_FOUND`` is TRUE, it will also define the following
+# imported target:
+#
+# ``Qt5::DesignerComponents``
+# The DesignerComponents library
+
+find_package(Qt5Designer QUIET)
+if (NOT Qt5Designer_FOUND)
+ set(DesignerComponents_FOUND OFF)
+ return()
+endif()
+
+get_target_property(_designer_location Qt5::Designer IMPORTED_LOCATION_DEBUG)
+if (NOT _designer_location)
+ get_target_property(_designer_location Qt5::Designer IMPORTED_LOCATION_RELEASE)
+endif()
+if (NOT _designer_location)
+ get_target_property(_designer_location Qt5::Designer IMPORTED_LOCATION)
+endif()
+get_target_property(_designer_is_framework Qt5::Designer FRAMEWORK)
+find_library(DesignerComponents_LIBRARIES NAMES Qt5DesignerComponents QtDesignerComponents
+ NO_DEFAULT_PATH PATHS "${_designer_location}/.." "${_designer_location}/../..")
+
+if (_designer_is_framework)
+ if (DesignerComponents_LIBRARIES)
+ set(DesignerComponents_LIBRARIES "${DesignerComponents_LIBRARIES}/QtDesignerComponents")
+ endif()
+else()
+ find_path(DesignerComponents_INCLUDE_DIRS NAMES qtdesignercomponentsversion.h PATH_SUFFIXES QtDesignerComponents HINTS ${Qt5Designer_INCLUDE_DIRS})
+ set(_required_vars Qt5Designer_INCLUDE_DIRS)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(DesignerComponents DEFAULT_MSG
+ DesignerComponents_LIBRARIES ${_required_vars})
+
+if(DesignerComponents_FOUND AND NOT TARGET DesignerComponents::DesignerComponents)
+ add_library(Qt5::DesignerComponents UNKNOWN IMPORTED)
+ set_target_properties(Qt5::DesignerComponents PROPERTIES
+ IMPORTED_LOCATION "${DesignerComponents_LIBRARIES}")
+ if (NOT _designer_is_framework)
+ set_target_properties(Qt5::DesignerComponents PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${DesignerComponents_INCLUDE_DIRS}")
+ endif()
+endif()
+
+mark_as_advanced(DesignerComponents_INCLUDE_DIRS DesignerComponents_LIBRARIES)
+
+include(FeatureSummary)
+set_package_properties(DesignerComponents PROPERTIES
+ URL "https://qt.io/"
+ DESCRIPTION "Qt5 (Widget) DesignerComponents library")
+
diff --git a/cmake/FindGoogleBenchmark.cmake b/cmake/FindGoogleBenchmark.cmake
new file mode 100644
index 0000000000..ce2cf3f66d
--- /dev/null
+++ b/cmake/FindGoogleBenchmark.cmake
@@ -0,0 +1,82 @@
+#.rst:
+# FindGoogleBenchmark
+# -----------------
+#
+# Try to locate the GoogleBenchmark source files, and then build them as a
+# static library.
+#
+# The ``GOOGLEBENCHMARK_DIR`` (CMake or Environment) variable should be used
+# to pinpoint the GoogleBenchmark source files.
+#
+# If found, this will define the following variables:
+#
+# ``GoogleBenchmark_FOUND``
+# True if the GoogleBenchmark source package has been found.
+#
+# ``GoogleBenchmark``
+# Target compiled as static library.
+#
+
+find_path(GOOGLE_BENCHMARK_INCLUDE_DIR
+ NAMES benchmark/benchmark.h
+ PATH_SUFFIXES include
+ HINTS
+ "${GOOGLEBENCHMARK_DIR}" ENV GOOGLEBENCHMARK_DIR
+ "${CMAKE_SOURCE_DIR}/../benchmark"
+ "${CMAKE_SOURCE_DIR}/../../benchmark"
+)
+
+find_path(GOOGLE_BENCHMARK_SRC_DIR
+ NAMES benchmark.cc
+ PATH_SUFFIXES src
+ HINTS
+ "${GOOGLEBENCHMARK_DIR}" ENV GOOGLEBENCHMARK_DIR
+ "${CMAKE_SOURCE_DIR}/../benchmark"
+ "${CMAKE_SOURCE_DIR}/../../benchmark"
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GoogleBenchmark
+ DEFAULT_MSG
+ GOOGLE_BENCHMARK_INCLUDE_DIR GOOGLE_BENCHMARK_SRC_DIR
+)
+
+if(GoogleBenchmark_FOUND AND NOT TARGET GoogleBenchmark)
+ add_library(GoogleBenchmark STATIC
+ "${GOOGLE_BENCHMARK_SRC_DIR}/benchmark.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/benchmark_api_internal.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/benchmark_name.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/benchmark_register.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/benchmark_runner.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/colorprint.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/commandlineflags.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/complexity.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/console_reporter.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/counter.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/csv_reporter.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/json_reporter.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/reporter.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/sleep.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/statistics.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/string_util.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/sysinfo.cc"
+ "${GOOGLE_BENCHMARK_SRC_DIR}/timers.cc"
+ )
+ target_include_directories(GoogleBenchmark
+ PUBLIC
+ "${GOOGLE_BENCHMARK_INCLUDE_DIR}"
+ PRIVATE
+ "${GOOGLE_BENCHMARK_SRC_DIR}"
+ )
+ target_compile_definitions(GoogleBenchmark PRIVATE HAVE_STD_REGEX WITH_BENCHMARKS)
+ if (WIN32)
+ target_link_libraries(GoogleBenchmark PRIVATE shlwapi)
+ endif()
+endif()
+
+mark_as_advanced(GOOGLE_BENCHMARK_INCLUDE_DIR GOOGLE_BENCHMARK_SRC_DIR)
+
+include(FeatureSummary)
+set_package_properties(GoogleBenchmark PROPERTIES
+ URL "https://github.com/google/benchmark"
+ DESCRIPTION "A microbenchmark support library")
diff --git a/cmake/FindGoogletest.cmake b/cmake/FindGoogletest.cmake
new file mode 100644
index 0000000000..b73f7680fc
--- /dev/null
+++ b/cmake/FindGoogletest.cmake
@@ -0,0 +1,102 @@
+#.rst:
+# FindGoogletest
+# -----------------
+#
+# Try to locate the Googletest source files, and then build them as a
+# static library.
+#
+# The ``GOOGLETEST_DIR`` (CMake or Environment) variable should be used
+# to pinpoint the Googletest source files.
+#
+# If found, this will define the following variables:
+#
+# ``Googletest_FOUND``
+# True if the Googletest source package has been found.
+#
+# ``Googletest``
+# Target compiled as static library.
+#
+
+find_path(GOOGLE_TEST_INCLUDE_DIR
+ NAMES gtest/gtest.h
+ PATH_SUFFIXES googletest/include
+ HINTS
+ "${GOOGLETEST_DIR}" ENV GOOGLETEST_DIR
+ "${CMAKE_SOURCE_DIR}/../googletest"
+ "${CMAKE_SOURCE_DIR}/../../googletest"
+)
+
+find_path(GOOGLE_TEST_SRC_ALL
+ NAMES gtest-all.cc
+ PATH_SUFFIXES googletest/src
+ HINTS
+ "${GOOGLETEST_DIR}" ENV GOOGLETEST_DIR
+ "${CMAKE_SOURCE_DIR}/../googletest"
+ "${CMAKE_SOURCE_DIR}/../../googletest"
+)
+
+
+find_path(GOOGLE_MOCK_INCLUDE_DIR
+ NAMES gmock/gmock.h
+ PATH_SUFFIXES googlemock/include
+ HINTS
+ "${GOOGLETEST_DIR}" ENV GOOGLETEST_DIR
+ "${CMAKE_SOURCE_DIR}/../googletest"
+ "${CMAKE_SOURCE_DIR}/../../googletest"
+)
+
+find_path(GOOGLE_MOCK_SRC_ALL
+ NAMES gmock-all.cc
+ PATH_SUFFIXES googlemock/src
+ HINTS
+ "${GOOGLETEST_DIR}" ENV GOOGLETEST_DIR
+ "${CMAKE_SOURCE_DIR}/../googletest"
+ "${CMAKE_SOURCE_DIR}/../../googletest"
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Googletest
+ DEFAULT_MSG
+ GOOGLE_TEST_INCLUDE_DIR GOOGLE_MOCK_INCLUDE_DIR
+ GOOGLE_TEST_SRC_ALL GOOGLE_MOCK_SRC_ALL
+)
+
+if(Googletest_FOUND AND NOT TARGET Googletest)
+ add_library(Googletest STATIC
+ "${GOOGLE_TEST_SRC_ALL}/gtest-all.cc"
+ "${GOOGLE_MOCK_SRC_ALL}/gmock-all.cc"
+ )
+ target_include_directories(Googletest
+ PUBLIC
+ "${GOOGLE_TEST_INCLUDE_DIR}"
+ "${GOOGLE_MOCK_INCLUDE_DIR}"
+ PRIVATE
+ "${GOOGLE_TEST_SRC_ALL}/.."
+ "${GOOGLE_MOCK_SRC_ALL}/.."
+ )
+ target_compile_definitions(Googletest
+ PRIVATE
+ GTEST_HAS_STD_INITIALIZER_LIST_
+ GTEST_LANG_CXX11
+ GTEST_HAS_STD_TUPLE_
+ GTEST_HAS_STD_TYPE_TRAITS_
+ GTEST_HAS_STD_FUNCTION_
+ GTEST_HAS_RTTI
+ GTEST_HAS_STD_BEGIN_AND_END_
+ GTEST_HAS_STD_UNIQUE_PTR_
+ GTEST_HAS_EXCEPTIONS
+ GTEST_HAS_STREAM_REDIRECTION
+ GTEST_HAS_TYPED_TEST
+ GTEST_HAS_TYPED_TEST_P
+ GTEST_HAS_PARAM_TEST
+ GTEST_HAS_DEATH_TEST
+ )
+endif()
+
+mark_as_advanced(GOOGLE_TEST_INCLUDE_DIR GOOGLE_MOCK_INCLUDE_DIR
+ GOOGLE_TEST_SRC_ALL GOOGLE_MOCK_SRC_ALL)
+
+include(FeatureSummary)
+set_package_properties(Googletest PROPERTIES
+ URL "https://github.com/google/googletest"
+ DESCRIPTION "Google Testing and Mocking Framework")
diff --git a/cmake/FindQbs.cmake b/cmake/FindQbs.cmake
new file mode 100644
index 0000000000..f89252cf86
--- /dev/null
+++ b/cmake/FindQbs.cmake
@@ -0,0 +1,55 @@
+#.rst:
+# FindQbs
+# ---------
+#
+# Try to locate the Qbs library.
+# If found, this will define the following variables:
+#
+# ``QBS_FOUND``
+# True if the qbs library is available
+# ``QBS_INCLUDE_DIRS``
+# The qbs include directories
+# ``QBSCORE_LIBRARIES``
+# The qbscore library for linking
+# ``QBS_INSTALL_DIR``
+# Top level qbs installation directory
+#
+# If ``QBS_FOUND`` is TRUE, it will also define the following
+# imported target:
+#
+# ``QBS::QBS``
+# The qbs library
+
+find_program(QBS_BINARY NAMES qbs)
+if(QBS_BINARY STREQUAL "QBS_BINARY-NOTFOUND")
+ set(_QBS_INSTALL_DIR "QBS_INSTALL_DIR-NOTFOUND")
+else()
+ get_filename_component(_QBS_BIN_DIR "${QBS_BINARY}" DIRECTORY)
+ get_filename_component(_QBS_INSTALL_DIR "${_QBS_BIN_DIR}" DIRECTORY)
+endif()
+
+set(QBS_INSTALL_DIR "${_QBS_INSTALL_DIR}" CACHE PATH "Qbs install directory")
+
+find_path(QBS_INCLUDE_DIRS NAMES qbs.h PATH_SUFFIXES qbs HINTS "${QBS_INSTALL_DIR}/include")
+
+find_library(QBSCORE_LIBRARIES NAMES qbscore HINTS "${QBS_INSTALL_DIR}/lib")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(QBS DEFAULT_MSG QBSCORE_LIBRARIES QBS_INCLUDE_DIRS)
+
+if(QBS_FOUND AND NOT TARGET Qbs::QbsCore)
+ add_library(Qbs::QbsCore UNKNOWN IMPORTED)
+ # FIXME: Detect whether QBS_ENABLE_PROJECT_FILE_UPDATES is set in qbscore!
+ set_target_properties(Qbs::QbsCore PROPERTIES
+ IMPORTED_LOCATION "${QBSCORE_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${QBS_INCLUDE_DIRS}"
+ INTERFACE_COMPILE_DEFINITIONS "QBS_ENABLE_PROJECT_FILE_UPDATES")
+endif()
+
+mark_as_advanced(QBS_INCLUDE_DIRS QBSCORE_LIBRARIES QBS_INSTALL_DIR)
+
+include(FeatureSummary)
+set_package_properties(QBS PROPERTIES
+ URL "https://qt.io/qbs"
+ DESCRIPTION "QBS build system")
+
diff --git a/cmake/QtCreatorIDEBranding.cmake b/cmake/QtCreatorIDEBranding.cmake
new file mode 100644
index 0000000000..f7327d19fa
--- /dev/null
+++ b/cmake/QtCreatorIDEBranding.cmake
@@ -0,0 +1,14 @@
+#BINARY_ARTIFACTS_BRANCH = master
+#PROJECT_USER_FILE_EXTENSION = .user
+
+set(IDE_VERSION "4.9.83") # The IDE version.
+set(IDE_VERSION_COMPAT "4.9.83") # The IDE Compatibility version.
+set(IDE_VERSION_DISPLAY "4.10.0-beta2") # The IDE display version.
+set(IDE_COPYRIGHT_YEAR "2019") # The IDE copyright year.
+
+set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation.
+set(IDE_COPY_SETTINGSVARIANT "Nokia") # The IDE settings to initially import.
+set(IDE_DISPLAY_NAME "Qt Creator") # The IDE display name.
+set(IDE_ID "qtcreator") # The IDE id (no spaces, lowercase!)
+set(IDE_CASED_ID "QtCreator") # The cased IDE id (no spaces!)
+set(IDE_BUNDLE_IDENTIFIER "org.qt-project.${IDE_ID}") # The macOS application bundle identifier.
diff --git a/dist/changes-4.10.0.md b/dist/changes-4.10.0.md
new file mode 100644
index 0000000000..baece64d4f
--- /dev/null
+++ b/dist/changes-4.10.0.md
@@ -0,0 +1,229 @@
+# Qt Creator 4.10
+
+Qt Creator version 4.10 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/4.9..v4.10.0
+
+## Editing
+
+* Removed support for KDE code paster after removal of official API
+* Added option for pinning files so they stay open when closing all files (QTCREATORBUG-21899)
+
+### Language Client
+
+* Removed `Experimental` flag
+* Added option for starting server when needed
+* Added option for starting one server per project
+* Added support for `workspace/workspaceFolders` server request
+* Added Locator filter for current document (`.`)
+* Added Locator filters for symbols in workspace (`:`, `c`, and `m`) (QTCREATORBUG-21915)
+* Added support for showing tooltip information from server
+* Made client settings expand variables for executable and arguments
+* Improved completion item tooltip (QTCREATORBUG-22429)
+
+## Help
+
+* Added option for scroll wheel zooming (QTCREATORBUG-14154)
+
+## All Projects
+
+* Added option for hiding kit settings (QTCREATORBUG-9134)
+* Added support for drag & drop in Projects tree (QTCREATORBUG-6446)
+* Added option for closing files of project when closing project (QTCREATORBUG-22198)
+* Added filtering to `Issues`, `Application Output`, `Compile Output`, and `General Messages`
+ (QTCREATORBUG-16356)
+* Added `Re-detect` and `Remove All` to compiler settings
+* Added Locator filter for all files in all project directory trees (`a`) (QTCREATORBUG-19122)
+* Added `CurrentRun:WorkingDir` Qt Creator variable
+* Added `Tools` > `Parse Build Output` (QTCREATORBUG-16017)
+* Added option for not clearing `Issues` pane on build (QTCREATORBUG-22478)
+* Moved `Application Output` and `Build Output` options to separate tabs in the
+ `Build & Run` options
+* Improved search for files from `Issues` pane (QTCREATORBUG-13623)
+
+### Wizards
+
+* Added build system choice to `Qt Widgets Application` and `C++ Library` wizards
+* Added `value('variablename')` to JavaScript context in JSON wizards, adding support for
+ lists and dictionaries as values
+* Fixed that file names were always lower-cased by file wizards (QTCREATORBUG-14711)
+
+## QMake Projects
+
+* Added option for adding existing project as sub-project (QTCREATORBUG-5837)
+* Added option for running `qmake` on every build (QTCREATORBUG-20888)
+* Added completion of paths in project files (QTCREATORBUG-5915)
+* Added forced `qmake` run on rebuild
+* Fixed building sub-project in case of additional custom make steps (QTCREATORBUG-15794)
+* Fixed missing items from `OBJECTIVE_HEADERS` (QTCREATORBUG-17569)
+
+## CMake Projects
+
+* Removed `Default` from build types (QTCREATORBUG-22013)
+* Added support for Android targets
+* Added support for building single file (QTCREATORBUG-18898)
+* Added completion of paths in project files (QTCREATORBUG-5915)
+* Improved text in `Configuration has changed on disk` dialog (QTCREATORBUG-22059)
+
+## Qbs Projects
+
+* Added support for Android targets
+* Fixed `Build product` for files in groups
+
+## Python Projects
+
+* Added support for adding and removing files from project
+* Improved wizards
+
+## Compilation Database Projects
+
+* Added setting for project header path (QTCREATORBUG-22031)
+* Added custom build steps and run configuration (QTCREATORBUG-21727)
+* Added option for specifying additional files in `compile_database.json.files`
+* Fixed handling of relative paths (QTCREATORBUG-22338)
+* Fixed handling of `--sysroot` (QTCREATORBUG-22339)
+
+## Qt Support
+
+* Added handling of QtTest messages in compile output (QTCREATORBUG-8091)
+
+## C++ Support
+
+* Improved auto-insertion of closing curly brace (QTCREATORBUG-18872)
+* Fixed that snippet completion could get in the way (QTCREATORBUG-21767)
+
+### Clang Format
+
+* Improved configuration UI
+* Fixed that clang format was triggered on save when Beautifier already was as well
+
+## QML Support
+
+* Fixed various formatting issues
+
+## Debugging
+
+* Added pretty printer for `QMargin`
+* Fixed issues with restoring layout (QTCREATORBUG-21669)
+
+### CDB
+
+* Fixed loading of custom debugging helpers (QTCREATORBUG-20481)
+
+## Perf Profiler
+
+* Changed format of saved traces
+* Added support for multiple attributes per sample
+* Added CPU ID for events
+
+## Qt Quick Designer
+
+* Added support for `ShapeGradient` (QDS-359)
+* Added gradient picker that allows loading and saving of presets
+* Added support for changing properties for multiple items at once (QDS-324)
+* Added missing properties for `LineEdit` and `ComboBox`
+* Updated properties of `Flickable`
+* Improved handling of errors in state editor (QDS-695)
+
+## Version Control Systems
+
+* Added zoom buttons to `Version Control` output pane
+
+### Git
+
+* Added support for different reset types in `Branches` view
+* Added choice of build system to `Git Clone` wizard if cloned project supports multiple
+ build systems (QTCREATORBUG-17828)
+
+## Test Integration
+
+* Added basic support for Boost tests
+* Added wizard for Boost tests (QTCREATORBUG-21169)
+* Added option for automatically opening test results pane
+* Improved handling of unexpected test output (QTCREATORBUG-22354)
+
+## Platform Specific
+
+### Windows
+
+* Added `Clone` for MSVC toolchains (QTCREATORBUG-22163)
+* Fixed that `mingw32-make`'s warnings were categorized as errors (QTCREATORBUG-22171)
+* Fixed bitness detection for MinGW (QTCREATORBUG-22160)
+
+### Linux
+
+* Improved auto-detection of toolchains (QTCREATORBUG-19179, QTCREATORBUG-20044, QTCREATORBUG-22081)
+
+### macOS
+
+### Android
+
+* Removed support for MIPS64
+
+### Remote Linux
+
+* Added deployment method that deploys everything that is installed by the build system
+ in its install step (QTCREATORBUG-21855)
+* Added support for opening remote terminal with run environment
+* Added option for `rsync` flags for deployment (QTCREATORBUG-22352)
+
+### Boot to Qt
+
+### Bare Metal
+
+* Added include path detection and output parsers for `IAR`, `KEIL` and `SDCC` toolchains
+
+## Credits for these changes go to:
+Aleksei German
+Alessandro Ambrosano
+Alessandro Portale
+Andre Hartmann
+André Pönitz
+Anton Danielsson
+Antonio Di Monaco
+Asit Dhal
+BogDan Vatra
+Christian Gagneraud
+Christian Kandeler
+Christian Stenger
+Cristian Adam
+Cristián Maureira-Fredes
+Daniel Teske
+David Schulz
+Denis Shienkov
+Denis Vygovskiy
+Eike Ziller
+Friedemann Kleint
+Giuseppe D'Angelo
+Haxor Leet
+Henning Gruendl
+illiteratecoder
+Ivan Donchevskii
+Ivan Komissarov
+Joel Smith
+Jörg Bornemann
+Kavindra Palaraja
+Leena Miettinen
+Luca Carlon
+Marco Bubke
+Martin Haase
+Mitch Curtis
+Nikolai Kosjar
+Oliver Wolff
+Orgad Shaneh
+Przemyslaw Gorszkowski
+Robert Löhning
+Thomas Hartmann
+Thomas Otto
+Tim Henning
+Tim Jenssen
+Tobias Hunger
+Tor Arne Vestbø
+Uladzislau Paulovich
+Ulf Hermann
+Ville Nummela
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
new file mode 100644
index 0000000000..0a750d44a4
--- /dev/null
+++ b/doc/CMakeLists.txt
@@ -0,0 +1,243 @@
+# Generate documentation
+
+# Options:
+option(WITH_DOCS "Build documentation" OFF)
+add_feature_info("Build documentation" WITH_DOCS "")
+
+option(WITH_ONLINE_DOCS "Build online documentation" OFF)
+add_feature_info("Build online documentation" WITH_ONLINE_DOCS "")
+
+option(BUILD_DEVELOPER_DOCS "Include developer documentation" OFF)
+add_feature_info("Include developer documentation" BUILD_DEVELOPER_DOCS "")
+
+
+# Find programs:
+function(_doc_find_program result_var)
+ if (NOT TARGET Qt5::qmake)
+ message(FATAL_ERROR "QDoc is only available in Qt5 projects")
+ endif()
+
+ get_target_property(_qmake_binary Qt5::qmake IMPORTED_LOCATION)
+ get_filename_component(_qmake_dir "${_qmake_binary}" DIRECTORY)
+ find_program("_prg_${result_var}" ${ARGN} HINTS "${_qmake_dir}")
+ if ("_prg_${result_var}" STREQUAL "_prg_${result_var}-NOTFOUND")
+ set("_prg_${result_var}" "${result_var}-NOTFOUND")
+ message(WARNING "Could not find binary for ${result_var}")
+ endif()
+
+ set(${result_var} "${_prg_${result_var}}" PARENT_SCOPE)
+endfunction()
+
+function(_setup_doc_targets)
+ # Set up important targets:
+ if (NOT TARGET html_docs)
+ add_custom_target(html_docs COMMENT "Build HTML documentation")
+ endif()
+ if (NOT TARGET qch_docs)
+ add_custom_target(qch_docs COMMENT "Build QCH documentation")
+ endif()
+ if (NOT TARGET docs)
+ add_custom_target(docs COMMENT "Build documentation")
+ add_dependencies(docs html_docs qch_docs)
+ endif()
+ if (NOT TARGET install_docs)
+ add_custom_target(install_docs COMMENT "Install documentation")
+ add_dependencies(install_docs docs)
+ endif()
+ if (NOT TARGET clean_docs)
+ add_custom_target(clean_docs COMMENT "Clean documentation files from build directory")
+ endif()
+endfunction()
+
+function(_setup_qdoc_targets _qdocconf_file _retval)
+ cmake_parse_arguments(_arg "" "HTML_DIR;INSTALL_DIR;POSTFIX"
+ "INDEXES;ENVIRONMENT_EXPORTS" ${ARGN})
+
+ foreach(_index ${_arg_INDEXES})
+ list(APPEND _qdoc_index_args "-indexdir;${_index}")
+ endforeach()
+
+ set(_env "")
+ foreach(_export ${_arg_ENVIRONMENT_EXPORTS})
+ if (NOT DEFINED "${_export}")
+ message(FATAL_ERROR "${_export} is not known when trying to export it to qdoc.")
+ endif()
+ list(APPEND _env "${_export}=${${_export}}")
+ endforeach()
+
+ set(_full_qdoc_command "${_qdoc}")
+ if (_env)
+ set(_full_qdoc_command "${CMAKE_COMMAND}" "-E" "env" ${_env} "${_qdoc}")
+ endif()
+
+ if (_arg_HTML_DIR STREQUAL "")
+ set(_arg_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc")
+ endif()
+
+ get_filename_component(_target "${_qdocconf_file}" NAME_WE)
+
+ set(_html_outputdir "${_arg_HTML_DIR}/${_target}${_arg_POSTFIX}")
+ file(MAKE_DIRECTORY "${_html_outputdir}")
+
+ set(_html_target "html_docs_${_target}")
+ add_custom_target("${_html_target}"
+ ${_full_qdoc_command} "-outputdir" "${_html_outputdir}" "${_qdocconf_file}" ${_qdoc_index_args}
+ COMMENT "Build HTML documentation from ${_qdocconf_file}"
+ DEPENDS "${_qdocconf_file}"
+ SOURCES "${_qdocconf_file}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM
+ )
+ add_dependencies(html_docs "${_html_target}")
+
+ # Install HTML files as a special component
+ install(DIRECTORY "${_html_outputdir}" DESTINATION "${_arg_INSTALL_DIR}"
+ COMPONENT ${_html_target} EXCLUDE_FROM_ALL)
+
+ add_custom_target("install_${_html_target}"
+ "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=${_html_target}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
+ COMMENT "Install HTML documentation from ${_qdocconf_file}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM
+ )
+ add_dependencies(install_docs "install_${_html_target}")
+
+ add_custom_target("clean_${_html_target}"
+ "${CMAKE_COMMAND}" -E remove_directory "${_html_outputdir}"
+ COMMENT "Clean HTML documentation from ${_qdocconf_file}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM
+ )
+ add_dependencies(clean_docs "clean_${_html_target}")
+
+ set("${_retval}" "${_html_outputdir}" PARENT_SCOPE)
+endfunction()
+
+function(_setup_qhelpgenerator_targets _qdocconf_file _html_outputdir)
+ cmake_parse_arguments(_arg "" "QCH_DIR;INSTALL_DIR" "" ${ARGN})
+ if (_arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "qdoc_build_qdocconf_file has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.")
+ endif()
+
+ if (NOT _arg_QCH_DIR)
+ set(_arg_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc")
+ endif()
+
+ if (NOT TARGET Qt5::qhelpgenerator)
+ message(WARNING "qhelpgenerator missing: No QCH documentation targets were generated")
+ return()
+ endif()
+
+ get_filename_component(_target "${_qdocconf_file}" NAME_WE)
+
+ set(_qch_outputdir "${_arg_QCH_DIR}")
+ file(MAKE_DIRECTORY "${_qch_outputdir}")
+
+ set(_qch_target "qch_docs_${_target}")
+ set(_html_target "html_docs_${_target}")
+ add_custom_target("${_qch_target}"
+ Qt5::qhelpgenerator "${_html_outputdir}/${_target}.qhp" -o "${_qch_outputdir}/${_target}.qch"
+ COMMENT "Build QCH documentation from ${_qdocconf_file}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM
+ )
+ add_dependencies("${_qch_target}" "${_html_target}")
+ add_dependencies(qch_docs "${_qch_target}")
+
+ install(FILES "${_qch_outputdir}/${_target}.qch" DESTINATION "${_arg_INSTALL_DIR}"
+ COMPONENT ${_qch_target} EXCLUDE_FROM_ALL)
+
+ add_custom_target("install_${_qch_target}"
+ "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=${_qch_target}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM
+ )
+ add_dependencies(install_docs "install_${_qch_target}")
+
+ add_custom_target("clean_${_qch_target}"
+ "${CMAKE_COMMAND}" -E remove -f "${_qch_outputdir}/${_target}.qch"
+ COMMENT "Clean QCH documentation generated from ${_qdocconf_file}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM
+ )
+ add_dependencies(clean_docs "clean_${_qch_target}")
+endfunction()
+
+# Helper functions:
+function(qdoc_build_qdocconf_file _qdocconf_file)
+ _setup_doc_targets()
+
+ _doc_find_program(_qdoc NAMES qdoc qdoc-qt5)
+ if (_qdoc STREQUAL "_qdoc-NOTFOUND")
+ message(WARNING "No qdoc binary found: No documentation targets were generated")
+ return()
+ endif()
+
+ cmake_parse_arguments(_arg "QCH" "HTML_DIR;QCH_DIR;INSTALL_DIR;POSTFIX"
+ "INDEXES;ENVIRONMENT_EXPORTS" ${ARGN})
+ if (_arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "qdoc_build_qdocconf_file has unknown arguments: ${_arg_UNPARSED_ARGUMENTS}.")
+ endif()
+
+ if (NOT _arg_INSTALL_DIR)
+ message(FATAL_ERROR "No INSTALL_DIR set when calling qdoc_build_qdocconf_file")
+ endif()
+
+ _setup_qdoc_targets("${_qdocconf_file}" _html_outputdir
+ HTML_DIR "${_arg_HTML_DIR}" INSTALL_DIR "${_arg_INSTALL_DIR}"
+ INDEXES ${_arg_INDEXES} ENVIRONMENT_EXPORTS ${_arg_ENVIRONMENT_EXPORTS}
+ POSTFIX "${_arg_POSTFIX}")
+
+ if (_arg_QCH)
+ _setup_qhelpgenerator_targets("${_qdocconf_file}" "${_html_outputdir}"
+ QCH_DIR "${_arg_QCH_DIR}" INSTALL_DIR "${_arg_INSTALL_DIR}")
+ endif()
+endfunction()
+
+### Skip docs setup if that is not needed!
+if (WITH_ONLINE_DOCS OR WITH_DOCS)
+ if (WITH_DOCS)
+ set(_qch_params "QCH;QCH_DIR;${PROJECT_BINARY_DIR}/doc")
+ endif()
+
+ set(_qdoc_params HTML_DIR "${PROJECT_BINARY_DIR}/doc")
+ list(APPEND _qdoc_params INDEXES "${QT_INSTALL_DOCS}" "${PROJECT_BINARY_DIR}/doc")
+ list(APPEND _qdoc_params INSTALL_DIR "${IDE_DOC_PATH}")
+
+ # Set up environment for qdoc:
+ set(QTC_VERSION "${IDE_VERSION_DISPLAY}")
+ set(QTCREATOR_COPYRIGHT_YEAR "${IDE_COPYRIGHT_YEAR}")
+ set(IDE_SOURCE_TREE "${PROJECT_SOURCE_DIR}")
+ string(REPLACE "." "" QTC_VERSION_TAG "${IDE_VERSION}")
+ set(QTC_DOCS_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+ set(QDOC_INDEX_DIR "${QT_INSTALL_DOCS}")
+ if (QT_INSTALL_DOCS_src)
+ set(QT_INSTALL_DOCS "${QT_INSTALL_DOCS_src}")
+ endif()
+
+ list(APPEND _qdoc_params ENVIRONMENT_EXPORTS
+ IDE_ID IDE_CASED_ID IDE_DISPLAY_NAME
+
+ IDE_SOURCE_TREE
+
+ QTC_DOCS_DIR QTC_VERSION QTC_VERSION_TAG
+
+ QTCREATOR_COPYRIGHT_YEAR
+
+ QT_INSTALL_DOCS QDOC_INDEX_DIR)
+
+ if (WITH_DOCS)
+ qdoc_build_qdocconf_file("qtcreator.qdocconf" ${_qch_params} ${_qdoc_params})
+ if (BUILD_DEVELOPER_DOCS)
+ qdoc_build_qdocconf_file("api/qtcreator-dev.qdocconf" ${_qch_params} ${_qdoc_params})
+ endif()
+ endif()
+ if(WITH_ONLINE_DOCS)
+ qdoc_build_qdocconf_file("qtcreator-online.qdocconf" ${_qdoc_params})
+ if (BUILD_DEVELOPER_DOCS)
+ qdoc_build_qdocconf_file("api/qtcreator-dev-online.qdocconf" ${_qdoc_params})
+ endif()
+ endif()
+endif()
diff --git a/doc/examples/progressbar/main.cpp b/doc/examples/progressbar/main.cpp
index f8f4c584aa..d8275e35c2 100644
--- a/doc/examples/progressbar/main.cpp
+++ b/doc/examples/progressbar/main.cpp
@@ -9,6 +9,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QQuickView view;
+ view.engine->addImportPath("qrc:/qml/imports");
view.setSource(QUrl("qrc:/qml/ProgressBar.ui.qml"));
if (!view.errors().isEmpty())
return -1;
diff --git a/doc/images/creator-compilers-custom.png b/doc/images/creator-compilers-custom.png
index cadbe17afd..d090b83259 100644
--- a/doc/images/creator-compilers-custom.png
+++ b/doc/images/creator-compilers-custom.png
Binary files differ
diff --git a/doc/images/qtcreator-application-output.png b/doc/images/qtcreator-application-output.png
index 05f76b380d..23250da485 100644
--- a/doc/images/qtcreator-application-output.png
+++ b/doc/images/qtcreator-application-output.png
Binary files differ
diff --git a/doc/images/qtcreator-autotests-options-boost.png b/doc/images/qtcreator-autotests-options-boost.png
new file mode 100644
index 0000000000..4e1f8c4361
--- /dev/null
+++ b/doc/images/qtcreator-autotests-options-boost.png
Binary files differ
diff --git a/doc/images/qtcreator-autotests-options-google.png b/doc/images/qtcreator-autotests-options-google.png
index ce5898e162..a32b5fcabb 100644
--- a/doc/images/qtcreator-autotests-options-google.png
+++ b/doc/images/qtcreator-autotests-options-google.png
Binary files differ
diff --git a/doc/images/qtcreator-autotests-options-qt.png b/doc/images/qtcreator-autotests-options-qt.png
index 84a2501717..ed93ac1280 100644
--- a/doc/images/qtcreator-autotests-options-qt.png
+++ b/doc/images/qtcreator-autotests-options-qt.png
Binary files differ
diff --git a/doc/images/qtcreator-autotests-options.png b/doc/images/qtcreator-autotests-options.png
index e880c8d616..3fd226939d 100644
--- a/doc/images/qtcreator-autotests-options.png
+++ b/doc/images/qtcreator-autotests-options.png
Binary files differ
diff --git a/doc/images/qtcreator-autotests.png b/doc/images/qtcreator-autotests.png
index a7e14d5292..48380a10eb 100644
--- a/doc/images/qtcreator-autotests.png
+++ b/doc/images/qtcreator-autotests.png
Binary files differ
diff --git a/doc/images/qtcreator-build-issues.png b/doc/images/qtcreator-build-issues.png
deleted file mode 100644
index 85c42782b3..0000000000
--- a/doc/images/qtcreator-build-issues.png
+++ /dev/null
Binary files differ
diff --git a/doc/images/qtcreator-cmakeexecutable.png b/doc/images/qtcreator-cmakeexecutable.png
index 8b328b0fb9..a0475e0c04 100644
--- a/doc/images/qtcreator-cmakeexecutable.png
+++ b/doc/images/qtcreator-cmakeexecutable.png
Binary files differ
diff --git a/doc/images/qtcreator-compile-output.png b/doc/images/qtcreator-compile-output.png
new file mode 100644
index 0000000000..3807bf345d
--- /dev/null
+++ b/doc/images/qtcreator-compile-output.png
Binary files differ
diff --git a/doc/images/qtcreator-compile-pane.png b/doc/images/qtcreator-compile-pane.png
deleted file mode 100644
index e7af4fe5e8..0000000000
--- a/doc/images/qtcreator-compile-pane.png
+++ /dev/null
Binary files differ
diff --git a/doc/images/qtcreator-context-sensitive-help.png b/doc/images/qtcreator-context-sensitive-help.png
index d26b14469d..fb5720bb4a 100644
--- a/doc/images/qtcreator-context-sensitive-help.png
+++ b/doc/images/qtcreator-context-sensitive-help.png
Binary files differ
diff --git a/doc/images/qtcreator-custom-parser.png b/doc/images/qtcreator-custom-parser.png
index 25e38a79af..ea300583aa 100644
--- a/doc/images/qtcreator-custom-parser.png
+++ b/doc/images/qtcreator-custom-parser.png
Binary files differ
diff --git a/doc/images/qtcreator-general-messages.png b/doc/images/qtcreator-general-messages.png
new file mode 100644
index 0000000000..143a28c876
--- /dev/null
+++ b/doc/images/qtcreator-general-messages.png
Binary files differ
diff --git a/doc/images/qtcreator-help-add-bookmark-dlg.png b/doc/images/qtcreator-help-add-bookmark-dlg.png
index 998060a81f..bec770fe98 100644
--- a/doc/images/qtcreator-help-add-bookmark-dlg.png
+++ b/doc/images/qtcreator-help-add-bookmark-dlg.png
Binary files differ
diff --git a/doc/images/qtcreator-help-filter-attributes.png b/doc/images/qtcreator-help-filter-attributes.png
index 2ca849a600..9c290d9dd0 100644
--- a/doc/images/qtcreator-help-filter-attributes.png
+++ b/doc/images/qtcreator-help-filter-attributes.png
Binary files differ
diff --git a/doc/images/qtcreator-help-filters.png b/doc/images/qtcreator-help-filters.png
index 38fd932e9a..2763f736c8 100644
--- a/doc/images/qtcreator-help-filters.png
+++ b/doc/images/qtcreator-help-filters.png
Binary files differ
diff --git a/doc/images/qtcreator-help-options.png b/doc/images/qtcreator-help-options.png
new file mode 100644
index 0000000000..63c34700b5
--- /dev/null
+++ b/doc/images/qtcreator-help-options.png
Binary files differ
diff --git a/doc/images/qtcreator-help-search.png b/doc/images/qtcreator-help-search.png
index 14ece95700..ca29bd6593 100644
--- a/doc/images/qtcreator-help-search.png
+++ b/doc/images/qtcreator-help-search.png
Binary files differ
diff --git a/doc/images/qtcreator-issues.png b/doc/images/qtcreator-issues.png
new file mode 100644
index 0000000000..b0bde84e45
--- /dev/null
+++ b/doc/images/qtcreator-issues.png
Binary files differ
diff --git a/doc/images/qtcreator-kits.png b/doc/images/qtcreator-kits.png
index 82dd2df34c..05e8cc0df3 100644
--- a/doc/images/qtcreator-kits.png
+++ b/doc/images/qtcreator-kits.png
Binary files differ
diff --git a/doc/images/qtcreator-language-client-options.png b/doc/images/qtcreator-language-client-options.png
index fef9889748..ab1a0e09d3 100644
--- a/doc/images/qtcreator-language-client-options.png
+++ b/doc/images/qtcreator-language-client-options.png
Binary files differ
diff --git a/doc/images/qtcreator-parse-build-output.png b/doc/images/qtcreator-parse-build-output.png
new file mode 100644
index 0000000000..56d9724ea6
--- /dev/null
+++ b/doc/images/qtcreator-parse-build-output.png
Binary files differ
diff --git a/doc/images/qtcreator-qbs-profile-settings.png b/doc/images/qtcreator-qbs-profile-settings.png
index e100701bd0..8710ff9ecd 100644
--- a/doc/images/qtcreator-qbs-profile-settings.png
+++ b/doc/images/qtcreator-qbs-profile-settings.png
Binary files differ
diff --git a/doc/images/qtcreator-task-pane.png b/doc/images/qtcreator-task-pane.png
deleted file mode 100644
index b220751400..0000000000
--- a/doc/images/qtcreator-task-pane.png
+++ /dev/null
Binary files differ
diff --git a/doc/images/qtcreator-tests-view.png b/doc/images/qtcreator-tests-view.png
index cb771e06cf..0faf49a5a4 100644
--- a/doc/images/qtcreator-tests-view.png
+++ b/doc/images/qtcreator-tests-view.png
Binary files differ
diff --git a/doc/images/qtcreator-toolchains.png b/doc/images/qtcreator-toolchains.png
index 91a6dbc7d7..1e54fe3333 100644
--- a/doc/images/qtcreator-toolchains.png
+++ b/doc/images/qtcreator-toolchains.png
Binary files differ
diff --git a/doc/src/cmake/creator-projects-cmake-deploying.qdocinc b/doc/src/cmake/creator-projects-cmake-deploying.qdocinc
index a5adb5e19e..a9c53ea4e2 100644
--- a/doc/src/cmake/creator-projects-cmake-deploying.qdocinc
+++ b/doc/src/cmake/creator-projects-cmake-deploying.qdocinc
@@ -34,10 +34,13 @@
\section1 Deploying CMake Projects to Embedded Linux Devices
- \QC cannot extract files to be installed from a CMake project, and
- therefore, only executable targets are automatically added to deployment
- files. You must specify all other files in the \c {QtCreatorDeployment.txt}
- file that you create and place in either the root directory of the CMake
+ \QC cannot directly extract files to be installed from a CMake project.
+ Therefore, a special deploy step is created that installs the project into
+ a local directory. The files in that directory are then deployed to the
+ remote device.
+ Alternatively, you can provide a \c {QtCreatorDeployment.txt} file in which
+ you must specify all files to be deployed which are not executables or
+ libraries. You place this file in either the root directory of the CMake
project or the build directory of the active build configuration.
Currently, \QC first checks the root directory and only if no
\c {QtCreatorDeployment.txt} exists it checks the active build directory.
diff --git a/doc/src/cmake/creator-projects-cmake.qdoc b/doc/src/cmake/creator-projects-cmake.qdoc
index 2a29cac9c1..585031ded7 100644
--- a/doc/src/cmake/creator-projects-cmake.qdoc
+++ b/doc/src/cmake/creator-projects-cmake.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -43,6 +43,9 @@
native build configurations and workspaces that you can use in the compiler
environment of your choice.
+ You can use CMake from \QC to build applications for the desktop and
+ Android devices. You can also build single files to test your changes.
+
\QC automatically detects the CMake executable specified in the \c PATH.
You can add paths to other CMake executables and use them in different
build and run \l{glossary-buildandrun-kit}{kits}.
@@ -109,6 +112,8 @@
\li Code completion
+ \li Path completion
+
\li Auto-indentation
\li Matching parentheses and quotes
diff --git a/doc/src/editors/creator-coding.qdoc b/doc/src/editors/creator-coding.qdoc
index b897961996..11990f4618 100644
--- a/doc/src/editors/creator-coding.qdoc
+++ b/doc/src/editors/creator-coding.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -93,10 +93,10 @@
\li \l{Using Language Servers}
- The experimental language client provides code completion,
- highlighting of the symbol under cursor, and jumping to the symbol
- definition for other programming languages besides C++. In addition,
- it integrates diagnostics from the language server.
+ The language client provides code completion, highlighting of the
+ symbol under cursor, and jumping to the symbol definition for other
+ programming languages besides C++. In addition, it integrates
+ diagnostics from the language server.
\li \l{Editing MIME Types}
diff --git a/doc/src/editors/creator-locator.qdoc b/doc/src/editors/creator-locator.qdoc
index 7d8f25dd07..e7c048f6d2 100644
--- a/doc/src/editors/creator-locator.qdoc
+++ b/doc/src/editors/creator-locator.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -99,7 +99,7 @@
\section1 Using Locator Filters
The locator enables you to browse not only files, but any items defined by
- \b{locator filters}. By default, the locator contains filters for:
+ \b{locator filters}. The filters that are available depend on the file type:
\list
@@ -114,11 +114,11 @@
\li Locating bookmarks (\c {b}).
For more information, see \l{Using Bookmarks}.
- \li Locating class (\c {c}), enum, and function (m) definitions in your
- project or anywhere referenced from your project (\c {:})
+ \li Locating class (\c {c}), enum, and function (\c {m}) definitions in
+ your project or anywhere referenced from your project (\c {:})
\endif
- \li Locating QML methods (m)
+ \li Locating QML methods (\c {m})
\li Locating symbols in the current document (\c {.})
diff --git a/doc/src/editors/creator-only/creator-code-pasting.qdoc b/doc/src/editors/creator-only/creator-code-pasting.qdoc
index 803a15e64a..b518c8ca3f 100644
--- a/doc/src/editors/creator-only/creator-code-pasting.qdoc
+++ b/doc/src/editors/creator-only/creator-code-pasting.qdoc
@@ -38,7 +38,6 @@
\list
\li \uicontrol {Pastebin.Com}
\li \uicontrol {Pastecode.Xyz}
- \li \uicontrol {Paste.KDE.Org}
\li \uicontrol {Shared network drives}
\endlist
diff --git a/doc/src/editors/creator-only/creator-language-server.qdoc b/doc/src/editors/creator-only/creator-language-server.qdoc
index 4b75aae16e..9dc5d1e84f 100644
--- a/doc/src/editors/creator-only/creator-language-server.qdoc
+++ b/doc/src/editors/creator-only/creator-language-server.qdoc
@@ -39,8 +39,9 @@
\list
\li \l{Completing Code}{Code completion}
\li Highlighting the symbol under cursor
- \li \l{Moving to Symbol Definition or Declaration}
- {Moving to the symbol definition}
+ \li Navigating in the code by using the \l{Searching with the Locator}
+ {locator} or \l{Moving to Symbol Definition or Declaration}
+ {moving to the symbol definition}
\li Inspecting code by viewing the document
\l{Viewing Defined Types and Symbols}{outline}
\li \l{Finding Symbols}{Finding references to symbols}
@@ -50,8 +51,10 @@
By providing a client for the language server protocol, \QC can support
the above features for several other programming languages besides C++.
- However, the experimental client does not support language servers that
- require special handling.
+ However, the client does not support language servers that require special
+ handling.
+
+ \section1 Adding MIME Types for Language Servers
\QC uses the \l{https://www.iana.org/assignments/media-types/media-types.xhtml}
{MIME type} of the file to determine which language server to request
@@ -62,21 +65,11 @@
only sent to the languge server if they are known to be handled by it. For
more information about how \QC uses MIME types, see \l {Editing MIME Types}.
- The experimental language service client has been mostly tested with Python.
- If problems arise when you try some other language, please select
- \uicontrol Help > \uicontrol {Report Bug} to report them in the Qt Bug
- Tracker. The reports should include \QC console output with the environment
- variable \c {QT_LOGGING_RULES=qtc.languageclient.*=true} set.
+ \section1 Specifying Settings for Language Clients
To use a language server:
\list 1
- \li Enable the language server client by selecting \uicontrol Help >
- \uicontrol {About Plugins} > \uicontrol {Other Languages} >
- \uicontrol {Language Client} (or \uicontrol {Qt Creator} >
- \uicontrol {About Plugins} > \uicontrol {Other Languages} >
- \uicontrol {Language Client} on \macos).
- \li Restart \QC to load the language client plugin.
\li Select \uicontrol Tools > \uicontrol Options >
\uicontrol {Language Client} (or \uicontrol {Qt Creator} >
\uicontrol Preferences > \uicontrol {Language Client} > on
@@ -86,15 +79,48 @@
language server.
\li Select \uicontrol Add to add language servers.
\li In the \uicontrol Name field, enter a name for the language server.
+ Select the \inlineimage replace.png
+ (\uicontrol {Variables}) button to use a variable for the server
+ name. For more information, see \l{Using Qt Creator Variables}.
\li In the \uicontrol {Language} field, select
\uicontrol {Set MIME Types} to select the MIME types of the files to
send to the language server. In the field below, you can enter file
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 Capabilities field, you can see the features
+ that are supported by the language server. Only some of them are
+ implemented by \QC.
\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
+ arguments. Select \uicontrol Variables to use variables as
arguments.
\endlist
To remove language servers from the list, select \uicontrol Delete.
+
+ \section1 Supported Locator Filters
+
+ The locator enables you to browse not only files, but any items defined by
+ \e {locator filters}. The language client plugin supports the following
+ locator filters:
+
+ \list
+ \li Locating symbols in the current project (\c {:})
+ \li Locating symbols in the current document (\c {.})
+ \li Locating class (\c {c}), enum, and function (\c {m})
+ definitions in your project
+ \endlist
+
+ \section1 Reporting Issues
+
+ The language service client has been mostly tested with Python.
+ If problems arise when you try it or some other language, please select
+ \uicontrol Help > \uicontrol {Report Bug} to report them in the Qt Bug
+ Tracker. The reports should include \QC console output with the environment
+ variable \c {QT_LOGGING_RULES=qtc.languageclient.*=true} set.
*/
diff --git a/doc/src/howto/creator-help.qdoc b/doc/src/howto/creator-help.qdoc
index 51bf69b810..7d8e7908bc 100644
--- a/doc/src/howto/creator-help.qdoc
+++ b/doc/src/howto/creator-help.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -23,12 +23,6 @@
**
****************************************************************************/
-// **********************************************************************
-// NOTE: the sections are not ordered by their logical order to avoid
-// reshuffling the file each time the index order changes (i.e., often).
-// Run the fixnavi.pl script to adjust the links to the index order.
-// **********************************************************************
-
/*!
\contentspage index.html
\page creator-help.html
@@ -62,7 +56,6 @@
\li To select and configure how the documentation is displayed in the
\uicontrol Help mode, select \uicontrol Tools > \uicontrol Options > \uicontrol Help.
-
\endlist
The following image displays the context sensitive help in the \uicontrol Edit
@@ -70,6 +63,19 @@
\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 >
+ \uicontrol Help > \uicontrol General.
+
+ \image qtcreator-help-options.png
+
+ By default, you can use the mouse scroll wheel to zoom help pages. To
+ disable this feature, deselect the \uicontrol {Enable scroll wheel zooming}
+ check box.
+
+ To switch to the editor context when you close the last help page, select
+ the \uicontrol {Return to editor on closing the last page} check box.
+
\section1 Viewing Function Tooltips
To hide function tooltips by default, select \uicontrol {Tools > Options >
@@ -127,17 +133,19 @@
\endlist
- To import and export bookmarks, select \uicontrol {Tools > Options > Help >
- General Settings > Import} or \uicontrol Export.
+ To import and export bookmarks, select \uicontrol Tools > \uicontrol Options
+ > \uicontrol Help > \uicontrol General > \uicontrol {Import Bookmarks} or
+ \uicontrol {Export Bookmarks}.
\section2 Full-text Search
In the \uicontrol Search pane, you can use full-text search for finding a
- particular word in all the installed documents. In the \uicontrol {Search for}
- field, enter the term you are looking for, and select the \uicontrol Search
- button. All documents that contain the specified term are listed. The list
- is sorted by the number of search hits that the documents contain. Select a
- document in the list to open it.
+ particular word in all the installed documents. Enter the term you are
+ looking for, and select the \uicontrol Search button. All documents that
+ contain the specified term are listed. The list is sorted by document
+ version (if you have installed several Qt versions, for example) and
+ the number of search hits that the documents contain. Select a document in
+ the list to open it.
\image qtcreator-help-search.png "Search pane"
@@ -159,12 +167,6 @@
\endlist
- For more flexibility, use the \uicontrol {Advanced search}. Specify words to
- exclude from the search hits, or search for an exact phrase or for similar
- words. For example, searching for \c{QStin}, \c{QSting}, or \c{QStrin} lists
- all the documents with titles that are similar, such as \c{QString}.
- Combine options to improve the search results.
-
Full-text search is based on indexing all the installed documents the first
time when you open the \uicontrol Search pane. If you add or remove documents,
\QC recreates the index.
diff --git a/doc/src/howto/creator-keyboard-shortcuts.qdoc b/doc/src/howto/creator-keyboard-shortcuts.qdoc
index bf47b2dabf..0d2045b7f4 100644
--- a/doc/src/howto/creator-keyboard-shortcuts.qdoc
+++ b/doc/src/howto/creator-keyboard-shortcuts.qdoc
@@ -33,7 +33,7 @@
\contentspage index.html
\page creator-keyboard-shortcuts.html
\if defined(qtdesignstudio)
- \previouspage studio-advanced.html
+ \previouspage studio-platforms.html
\nextpage creator-coding.html
\else
\previouspage creator-cli.html
diff --git a/doc/src/howto/creator-only/creator-autotest.qdoc b/doc/src/howto/creator-only/creator-autotest.qdoc
index 2058581308..05edde5027 100644
--- a/doc/src/howto/creator-only/creator-autotest.qdoc
+++ b/doc/src/howto/creator-only/creator-autotest.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -31,27 +31,28 @@
\title Running Autotests
- \QC integrates the \l{Qt Test} framework and
- \l{https://github.com/google/googletest}{Google C++ Testing Framework} for
- unit testing applications and libraries. You can use \QC to build and run
- Qt tests, Qt Quick tests (QML-based Qt tests), and Google tests for your
- projects.
+ \QC integrates the \l{Qt Test} framework,
+ \l{https://github.com/google/googletest}{Google C++ Testing Framework}, and
+ \l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
+ {Boost.Test} for unit testing applications and libraries. You can use \QC to
+ create, build, and run Qt tests, Qt Quick tests (QML-based Qt tests), Google
+ tests, and Boost tests for your projects.
\image qtcreator-autotests.png
\section1 Creating Tests
- You can use a wizard to create projects that contain Qt or Google tests.
+ You can use a wizard to create projects that contain tests.
- \section2 Creating Qt Tests
+ \section2 Creating Qt and Qt Quick Tests
- To create a Qt test:
+ To create a Qt or Qt Quick test:
\list 1
\li Select \uicontrol File > \uicontrol {New File or Project} >
\uicontrol {Other Project} > \uicontrol {Auto Test Project} >
\uicontrol Choose to create a project with boilerplate code for a
- Qt test.
+ Qt test or a Qt Quick test.
\li In the \uicontrol {Project and Test Information} dialog, specify
settings for the project and test:
@@ -59,17 +60,17 @@
\list 1
\li In the \uicontrol {Test framework} field, select
- \uicontrol {Qt Test}.
+ \uicontrol {Qt Test} or \uicontrol {Qt Quick Test}.
- \li Select the \uicontrol {GUI Application} check box to create
- a Qt application.
+ \li For a Qt test, select the \uicontrol {GUI Application} check
+ box to create a Qt application.
\li In the \uicontrol {Test case name} field, enter a name for
the test case.
- \li Select the \uicontrol {Requires QApplication} check box to
- add the include statement for QApplication to the main.cpp
- file of the project.
+ \li For a Qt test, select the \uicontrol {Requires \QApplication}
+ check box to add the include statement for QApplication to
+ the main.cpp file of the project.
\li Select the \uicontrol {Generate initialization and cleanup
code} checkbox to add functions to your test that are
@@ -106,12 +107,12 @@
\li In the \uicontrol {Test framework} field, select
\uicontrol {Google Test}.
+ \li In the \uicontrol {Test suite name} field, enter a name for
+ the test suite.
+
\li In the \uicontrol {Test case name} field, enter a name for
the test case.
- \li In the \uicontrol {Test set name} field, enter a name for
- the test set.
-
\li Select the \uicontrol {Enable C++ 11} check box to
support C++ 11 features in the test.
@@ -135,6 +136,46 @@
\l{https://github.com/google/googletest/blob/master/googletest/docs/primer.md}
{Google Test Primer}.
+ \section2 Creating Boost Tests
+
+ To build and run Boost tests, you must have the Boost.Test installed on the
+ development host. Typically, it is installed when you install Boost. You can
+ download Boost from \l{https://www.boost.org/}{Boost.org}.
+
+ If Boost libraries can be found by the used compiler and build system, you
+ do not need to specify the include directory when creating the test.
+
+ To create a Boost test:
+
+ \list 1
+ \li Select \uicontrol File > \uicontrol {New File or Project} >
+ \uicontrol {Other Project} > \uicontrol {Auto Test Project} >
+ \uicontrol Choose to create a project with boilerplate code for a
+ Boost test.
+ \li In the \uicontrol {Project and Test Information} dialog, specify
+ settings for the project and test:
+ \list 1
+ \li In the \uicontrol {Test framework} field, select
+ \uicontrol {Boost Test}.
+ \li In the \uicontrol {Test suite name} field, enter a name for
+ the test suite.
+ \li In the \uicontrol {Test case name} field, enter a name for
+ the test case.
+ \li In the \uicontrol {Boost include dir (optional)} field,
+ enter the path to the directory that contains files needed
+ by Boost.Test, such as \e version.hpp and a subfolder called
+ \e test that contains the test header files.
+ \li In the \uicontrol {Build system} field, select the build
+ system to use for building the project: qmake, CMake, or
+ Qbs.
+ \endlist
+ \endlist
+
+ \QC creates the test in the specified project directory.
+ For more information about creating Boost tests, see
+ \l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
+ {Boost.Test}.
+
\section1 Setting Up the Google C++ Testing Framework
To build and run Google tests, you must have the Google C++ Testing
@@ -240,11 +281,6 @@
\image qtcreator-autotests-options.png
- You can add filters to specify the directories within the current project
- to scan for tests. Select the \uicontrol {Global Filters} check box, and
- then select \uicontrol Add to specify paths to the directories to scan for
- tests. Wildcards are not supported in the filter expressions.
-
In some special setups, \QC cannot deduce which executable or run
configuration it should use. If \QC repeatedly asks you to select the
tests to run when trying to execute tests, you can enable it to cache
@@ -315,6 +351,30 @@
failures into C++ exceptions, select the \uicontrol {Throw on failure} check
box.
+ \section2 Specifying Settings for Running Boost Tests
+
+ \list 1
+ \li To specify settings for running Boost tests, select \uicontrol Tools
+ > \uicontrol Options > \uicontrol {Testing} >
+ \uicontrol {Boost Test}.
+ \image qtcreator-autotests-options-boost.png
+ \li In the \uicontrol {Log format} field, select the error report
+ format to specify the type of events you want recorded in the
+ test report.
+ \li In the \uicontrol {Report level} field, select the verbosity level
+ of the test result report. Select \uicontrol No if you do not want
+ a report.
+ \li Select the \uicontrol Randomize check box to execute the tests in
+ a random order, using the seed specified in the \uicontrol Seed
+ field for initializing the randomizer.
+ \li Select the \uicontrol {Catch system errors} check box to catch
+ system errors.
+ \li Select the \uicontrol {Floating point exceptions} check box to
+ detect floating point exceptions.
+ \li Select the \uicontrol {Detect memory leaks} check box to detect
+ memory leaks.
+ \endlist
+
\section1 Viewing Test Output
The test results are displayed in the \uicontrol {Test Results} output pane
diff --git a/doc/src/howto/creator-sidebar-views.qdoc b/doc/src/howto/creator-sidebar-views.qdoc
index bda32acb6a..9140af5f35 100644
--- a/doc/src/howto/creator-sidebar-views.qdoc
+++ b/doc/src/howto/creator-sidebar-views.qdoc
@@ -159,6 +159,10 @@
\li To see the absolute path of a file, move the mouse pointer over the
file name.
+ \li To move files from one project to another, drag-and-drop them
+ in the project tree. \QC makes the necessary changes to project
+ configuration files.
+
\endlist
\if defined(qtcreator)
@@ -188,7 +192,10 @@
\li Expand or collapse the tree view to show or hide all files and
folders.
\li Close all files in a project.
- \li Close projects.
+ \li Close projects. By default, all files in the project are also
+ closed. To keep them open, deselect the \uicontrol Tools >
+ \uicontrol Options > \uicontrol {Build & Run} > \uicontrol General
+ > \uicontrol {Close source files along with project} check box.
\endlist
For managing files and directories, the same functions are available as in
@@ -264,6 +271,22 @@
\endlist
+ \section1 Viewing Open Documents
+
+ To see a list of open documents, switch to the \uicontrol {Open Documents}
+ view. You can use the context-menu to perform some of the functions also
+ available in the \uicontrol File menu and in the context menu in the
+ \uicontrol {File System} view.
+
+ In addition, you can:
+
+ \list
+ \li Copy the full path of the file or just the filename to the
+ clipboard.
+ \li Pin files to ensure they stay at the top of the list and are not
+ closed when \uicontrol {Close All} is used.
+ \endlist
+
\section1 Viewing Defined Types and Symbols
The \uicontrol Outline view shows an overview of defined types and other
diff --git a/doc/src/howto/creator-ui.qdoc b/doc/src/howto/creator-ui.qdoc
index f91302ad0c..314abee874 100644
--- a/doc/src/howto/creator-ui.qdoc
+++ b/doc/src/howto/creator-ui.qdoc
@@ -110,6 +110,46 @@
documentation, see \l{Tips and Tricks}.
\endif
+ \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 >
+ \uicontrol Environment and select a language in the \uicontrol Language
+ field. The change takes effect after you restart \QC.
+
+ \section1 Viewing Images
+
+ \QC opens image files in the image viewer.
+
+ \image qtcreator-image-viewer.png "Image viewer"
+
+ Use the toolbar buttons (1) or \l{Keyboard Shortcuts}{keyboard shortcuts}
+ to:
+
+ \list
+
+ \li Export SVG images to pixmaps
+
+ \li Switch between background and outline modes
+
+ \li Zoom in and out
+
+ \li Fit images to screen
+
+ \li Return to original size
+
+ \li Play and pause animated GIF and MNG images
+
+ \endlist
+
+ \section2 Exporting SVG Images
+
+ If you receive a freely scalable icon in the SVG format from an UI designer,
+ you can export it to several images of different sizes to create a set of
+ pixmaps. You can then use QIcon::addPixmap() to add the pixmaps to icons in
+ different modes and states.
+
\section1 Platform Notes
This section describes the cases where the behavior of \QC depends on the
@@ -296,7 +336,7 @@
\title Viewing Output
- \image qtcreator-task-pane.png
+ \image qtcreator-general-messages.png "General Messages output pane"
The task pane in \QC can display one of the following panes:
@@ -334,6 +374,9 @@
up in the pane. In these panes, you can also use the zoom buttons to increase and
decrease the text size of the output.
+ To filter the output, enter a string in the \uicontrol Filter field.
+ Filtering is not supported in all output panes.
+
To open the \uicontrol{General Messages} and
\if defined(qtcreator)
\l{Using Version Control Systems}{Version Control}
@@ -404,7 +447,7 @@
\uicontrol {Filter Tree}
and then select a filter.
- \image qtcreator-build-issues.png
+ \image qtcreator-issues.png "Issues output pane"
Right-clicking on a line brings up a context menu with actions that you can
apply to the contents of the line. You can remove a line, copy its contents
@@ -422,6 +465,11 @@
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 >
+ \uicontrol {Clear issues list on new build}.
+
\section1 Search Results
In the \uicontrol{Search Results} pane, you can search through projects, files on
@@ -459,10 +507,10 @@
To specify settings for displaying application output, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
- \uicontrol General. You can select whether to open the
- \uicontrol{Application Output} pane 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.
+ \uicontrol Application Output, or click the \uicontrol {Open Settings Page}
+ button. You can select whether to open the \uicontrol{Application Output} pane
+ 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
@@ -470,7 +518,7 @@
The \uicontrol{Compile Output} is a more detailed version of information
displayed in the \uicontrol{Issues} pane.
- \image qtcreator-compile-pane.png
+ \image qtcreator-compile-output.png "Compile Output pane"
Double-click on a file name in an error message to open the file in the
code editor.
@@ -479,11 +527,46 @@
To specify whether to open the \uicontrol {Compile Output} pane on output
when building applications, select \uicontrol Tools > \uicontrol Options >
- \uicontrol {Build & Run} > \uicontrol General, and then select the
- \uicontrol {Open Compile Output pane when building} check box.
- In the \uicontrol {Limit build output to} field, you can specify the maximum
+ \uicontrol {Build & Run} > \uicontrol Compile Output, and then select the
+ \uicontrol {Open pane 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.
+ You can also reach the options page by clicking the \uicontrol {Open Settings Page}
+ button.
+
+ 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.
+ This is useful for large projects that take a long time to build.
+
+ \section2 Parsing Existing Compile Output
+
+ You can use \QC's output parsers to parse output from builds done outside
+ of \QC or stored from previous build runs. By default, the parsers from the
+ kit selected for the active project are used, but you can select another
+ kit.
+
+ To parse compile output:
+
+ \list 1
+ \li Select \uicontrol Tools > \uicontrol {Parse Build Output}.
+ \image qtcreator-parse-build-output.png
+ \li Paste the build output in the \uicontrol {Build Output} field, or
+ select \uicontrol {Load from File} to load it from a file.
+ \li Deselect the \uicontrol {Output went to stderr} check box if the
+ parser expects issues on \c stdout.
+ \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.
+ Deselect the \uicontrol {Clear existing tasks} check box to append
+ the new output to the old output.
+ \li Select \uicontrol OK to start parsing.
+ \endlist
+
\if defined(qtcreator)
\section1 To-Do Entries
@@ -528,42 +611,4 @@
\l{Showing Task List Files in Issues Pane}.
\endif
- \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 > Options > Environment} and select a language
- in the \uicontrol Language field. The change takes effect after you restart \QC.
-
- \section1 Viewing Images
-
- \QC opens image files in the image viewer.
-
- \image qtcreator-image-viewer.png "Image viewer"
-
- Use the toolbar buttons (1) or \l{Keyboard Shortcuts}{keyboard shortcuts}
- to:
-
- \list
-
- \li Export SVG images to pixmaps
-
- \li Switch between background and outline modes
-
- \li Zoom in and out
-
- \li Fit images to screen
-
- \li Return to original size
-
- \li Play and pause animated GIF and MNG images
-
- \endlist
-
- \section1 Exporting SVG Images
-
- If you receive a freely scalable icon in the SVG format from an UI designer,
- you can export it to several images of different sizes to create a set of
- pixmaps. You can then use QIcon::addPixmap() to add the pixmaps to icons in
- different modes and states.
*/
diff --git a/doc/src/overview/creator-acknowledgements.qdoc b/doc/src/overview/creator-acknowledgements.qdoc
index e7fdc6765e..43bac0ad4c 100644
--- a/doc/src/overview/creator-acknowledgements.qdoc
+++ b/doc/src/overview/creator-acknowledgements.qdoc
@@ -168,7 +168,7 @@
The source code of ANGLE is part of the Qt libraries. For more
information about the licenses used in Qt GUI, see
- \l{https://doc.qt.io/qt-5.9/licenses-used-in-qt.html#qt-gui}{Qt GUI}.
+ \l{https://doc.qt.io/qt-5.11/licenses-used-in-qt.html#qt-gui}{Qt GUI}.
\l{https://spdx.org/licenses/BSD-3-Clause.html}
{BSD 3-clause "New" or "Revised" License}
diff --git a/doc/src/overview/creator-only/creator-overview.qdoc b/doc/src/overview/creator-only/creator-overview.qdoc
index 1f6f31936d..09ef2766e4 100644
--- a/doc/src/overview/creator-only/creator-overview.qdoc
+++ b/doc/src/overview/creator-only/creator-overview.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -79,10 +79,9 @@
languages as code, not just as plain text. This enables it to
provide you with useful features, such as semantic highlighting,
checking code syntax, code completion, and refactoring actions.
- In addition, the experimental language server plugin provides
- some of these services for other programming languages, such as
- Python, for which a \e {language server} is available that
- provides information about the code to IDEs.
+ \QC supports some of these services also for other programming
+ languages, such as Python, for which a \e {language server} is
+ available that provides information about the code to IDEs.
For more information, see \l{Coding}.
\row
\li \inlineimage creator_buildingrunning.png
@@ -117,9 +116,9 @@
execution. In addition, the QML Profiler enables you to profile
Qt Quick applications.
- \QC is integrated to the \l{Qt Test} and Google C++ Testing
- frameworks for unit testing applications and libraries. You can
- use \QC to build and run autotests.
+ \QC is integrated to the \l{Qt Test}, Google C++ Testing, and
+ Boost.Test frameworks for unit testing applications and
+ libraries. You can use \QC to create, build, and run autotests.
For more information, see \l{Testing}.
\li \b {Publishing}
diff --git a/doc/src/overview/creator-only/creator-testing.qdoc b/doc/src/overview/creator-only/creator-testing.qdoc
index 39bae4ba17..10df1d7f31 100644
--- a/doc/src/overview/creator-only/creator-testing.qdoc
+++ b/doc/src/overview/creator-only/creator-testing.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -60,9 +60,8 @@
\li \l{Running Autotests}
- You can build and run Qt tests, Qt Quick tests, and Google tests
- using \QC. In addition, you can use a wizard to create projects that
- contain Qt or Google tests.
+ You can create, build and run Qt tests, Qt Quick tests, Google
+ tests, and Boost tests using \QC.
\endlist
diff --git a/doc/src/projects/creator-only/creator-projects-building.qdoc b/doc/src/projects/creator-only/creator-projects-building.qdoc
index c5a9ae001e..740096f0cf 100644
--- a/doc/src/projects/creator-only/creator-projects-building.qdoc
+++ b/doc/src/projects/creator-only/creator-projects-building.qdoc
@@ -79,8 +79,9 @@
subproject.
To remove all build artifacts, select \uicontrol Build > \uicontrol {Clean All} or
- \uicontrol {Clean Project}. To clean the build directory and then build the
- project, select \uicontrol Build > \uicontrol {Rebuild All} or \uicontrol {Rebuild Project}.
+ \uicontrol {Clean Project}. To clean the build directory, run qmake, and
+ then build the project, select \uicontrol Build > \uicontrol {Rebuild All}
+ or \uicontrol {Rebuild Project}.
To build and clean projects without dependencies, select the
\uicontrol {Build Without Dependencies},
@@ -88,6 +89,10 @@
\uicontrol {Clean Without Dependencies} options in the context menu in the
\uicontrol Projects view.
- To run qmake to generate new Makefiles, select \uicontrol Build > \uicontrol qmake.
-
+ To run qmake to generate new Makefiles, select \uicontrol Build >
+ \uicontrol qmake. 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 >
+ \uicontrol {Run qmake on every build}.
*/
diff --git a/doc/src/projects/creator-only/creator-projects-compilers.qdoc b/doc/src/projects/creator-only/creator-projects-compilers.qdoc
index 5387e4c680..b91d5b7d9e 100644
--- a/doc/src/projects/creator-only/creator-projects-compilers.qdoc
+++ b/doc/src/projects/creator-only/creator-projects-compilers.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -44,7 +44,12 @@
for and running it on a particular platform.
\QC automatically detects the compilers that are registered by your system
- or by an installer. You can add compilers to build applications by using other
+ or by an installer and lists them in \uicontrol Tools > \uicontrol Options >
+ \uicontrol Kits > \uicontrol Compilers:
+
+ \image qtcreator-toolchains.png
+
+ You can add the following compilers to build applications by using other
compilers or by using additional versions of the automatically detected
compilers:
@@ -74,6 +79,40 @@
\endlist
+ In addition, the \QC Bare Metal Device plugin provides support for the
+ following compilers:
+
+ \list
+
+ \li \l{https://www.iar.com/iar-embedded-workbench/}{IAREW} is a group of
+ C and C++ bare-metal compilers from the various IAR Embedded Workbench
+ development environments.
+ \note Currently supported architectures are \c 8051, \c AVR, and \c ARM.
+
+ \li \l{https://www.keil.com}{KEIL} is a group of C and C++ bare-metal
+ compilers from the various KEIL development environments.
+ \note Currently supported architectures are \c 8051 and \c ARM.
+
+ \li \l{https://sdcc.sourceforge.net}{SDCC} is a retargetable, optimizing
+ C bare-metal compiler for various architectures.
+ \note Currently supported architecture is \c 8051.
+
+ \endlist
+
+ \section1 Redetecting Compilers
+
+ When \QC finds an x86_64 GCC compiler, it sets up an instance for the native
+ x86_64 target. If you plan to create also 32-bit x86 binaries without using
+ a dedicated cross-compiler, select \uicontrol {Auto-detection Settings} >
+ \uicontrol {Detect x86_64 GCC compilers as x86_64 and x86}. Then select
+ \uicontrol Re-detect to refresh the list of automatically detected
+ compilers.
+
+ To remove manually added compilers, select \uicontrol Remove or
+ \uicontrol {Remove All}.
+
+ \section1 Specifying Compiler Settings
+
To build an application using GCC, MinGW, Clang, or QCC, specify the path
to the directory where the compiler is located and select
the application binary interface (ABI) version from the list of available
@@ -98,8 +137,6 @@
then select a compiler in the list, and then select \uicontrol C or
\uicontrol C++ to add a C or C++ compiler.
- \image qtcreator-toolchains.png
-
To clone the selected compiler, select \uicontrol Clone.
\li In the \uicontrol Name field, enter a name for the compiler to
diff --git a/doc/src/projects/creator-only/creator-projects-creating.qdoc b/doc/src/projects/creator-only/creator-projects-creating.qdoc
index 43b2e39f70..37b3224cd6 100644
--- a/doc/src/projects/creator-only/creator-projects-creating.qdoc
+++ b/doc/src/projects/creator-only/creator-projects-creating.qdoc
@@ -472,8 +472,10 @@
and the subproject that you add as a value of the \l{Variables#subdirs}
{SUBDIRS variable}. It also adds all the necessary files for the subproject.
- To add more subprojects, right-click the project name in the \uicontrol Projects
- pane, and select \uicontrol {New Subproject} in the context menu.
+ To create more subprojects, right-click the project name in the
+ \uicontrol Projects pane, and select \uicontrol {New Subproject} in the
+ context menu. To add an existing project as a subproject, select
+ \uicontrol {Add Existing Projects}.
To remove subprojects, right-click the project name in the \uicontrol Projects
pane, and select \uicontrol {Remove Subproject} in the context menu.
diff --git a/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc b/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc
index c6dc6a24b4..80fcdaa832 100644
--- a/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc
+++ b/doc/src/projects/creator-only/creator-projects-custom-wizards-json.qdoc
@@ -98,15 +98,22 @@
\section1 Using Variables in Wizards
- You can use variables (\c {%\{<variableName>\}}) in the configuration and
- template source files. A set of variables is predefined by the wizards and
- their pages. You can introduce new variables as shortcuts to be used later.
- Define the variable key names and values in the \c options section in the
+ You can use variables (\c {%\{<variableName>\}}) in strings in the JSON configuration
+ file and in template source files.
+ A set of variables is predefined by the wizards and their pages.
+ You can introduce new variables as shortcuts to be used later by
+ defining the variable key names and values in the \c options section in the
\c {wizard.json} file.
- The variables always return strings. In places where a boolean value is
- expected and a string is given, an empty string as well as the string
- \c {"false"} is treated as \c false and anything else as \c true.
+ There is a special variable \c {%\{JS:<JavaScript expression>\}} which evaluates the given
+ JavaScript expression and converts the resulting JavaScript value to a string.
+ In the JavaScript expression you can refer to variables defined by the wizard with
+ \c {value('<variableName>')}. The returned JavaScript object has the type that the value
+ of the variable has, which can be a string, list, dictionary or boolean.
+
+ In places where a boolean value is expected and a string is given,
+ an empty string as well as the string \c {"false"} is treated as
+ \c false and anything else as \c true.
\section1 Localizing Wizards
@@ -221,7 +228,7 @@
"trDisplayName": "C++ Class",
"trDisplayCategory": "C++",
"icon": "../../global/genericfilewizard.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",
\endcode
\list
@@ -295,11 +302,11 @@
{ "key": "TargetPath", "value": "%{Path}" },
{ "key": "HdrPath", "value": "%{Path}/%{HdrFileName}" },
{ "key": "SrcPath", "value": "%{Path}/%{SrcFileName}" },
- { "key": "CN", "value": "%{JS: Cpp.className('%{Class}')}" },
- { "key": "Base", "value": "%{JS: ( '%{BaseCB}' === '' ) ? '%{BaseEdit}' : '%{BaseCB}'}" },
- { "key": "isQObject", "value": "%{JS: ('%{Base}' === 'QObject' || '%{Base}' === 'QWidget' || '%{Base}' === 'QMainWindow' || '%{Base}' === 'QDeclarativeItem' || '%{Base}' === 'QQuickItem' ) ? 'yes' : ''}" },
- { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" },
- { "key": "SharedDataInit", "value": "%{JS: ('%{IncludeQSharedData}') ? 'data(new %{CN}Data)' : '' }" }
+ { "key": "CN", "value": "%{JS: Cpp.className(value('Class'))}" },
+ { "key": "Base", "value": "%{JS: value('BaseCB') === '' ? value('BaseEdit') : value('BaseCB')}" },
+ { "key": "isQObject", "value": "%{JS: (value('Base') === 'QObject' || value('Base') === 'QWidget' || value('Base') === 'QMainWindow' || value('Base') === 'QDeclarativeItem' || value('Base') === 'QQuickItem' ) ? 'true' : 'false'}" },
+ { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('Class'), Util.suffix(value('HdrFileName'))}" },
+ { "key": "SharedDataInit", "value": "%{JS: value('IncludeQSharedData') ? 'data(new %{CN}Data)' : '' }" }
],
\endcode
@@ -712,7 +719,7 @@
{
"checkedValue": "QObject",
"uncheckedValue": "",
- "checked": "%{JS: ('%{BaseCB}' === 'QObject' ) ? 'yes' : ''}"
+ "checked": "%{JS: value('BaseCB') === 'QObject' ? 'true' : 'false'}"
}
},
\endcode
@@ -788,7 +795,7 @@
"name": "LabelQQC_2_0",
"type": "Label",
"span": true,
- "visible": "%{( '%{CS}' === 'QQC_2_0' )}",
+ "visible": "%{JS: value('CS') === 'QQC_2_0'}",
"data":
{
"wordWrap": true,
@@ -819,7 +826,7 @@
{
"name": "BaseEdit",
"type": "LineEdit",
- "enabled": "%{JS: ( '%{BaseCB}' === '' ) ? 'yes' : ''}",
+ "enabled": "%{JS: value('BaseCB') === '' ? 'true' : 'false'}",
"mandatory": false,
"data":
{
@@ -981,9 +988,6 @@
as the top level directory. This setting defaults to an empty list
and no subdirectories will be scanned.
- \li \c firstProjectOnly is a boolean value, which will determine whether
- all project files that were found will be opened as a project or
- only the first one. This setting defaults to \c true.
\endlist
*/
diff --git a/doc/src/projects/creator-only/creator-projects-opening.qdoc b/doc/src/projects/creator-only/creator-projects-opening.qdoc
index 6298c896b5..3848979150 100644
--- a/doc/src/projects/creator-only/creator-projects-opening.qdoc
+++ b/doc/src/projects/creator-only/creator-projects-opening.qdoc
@@ -59,8 +59,8 @@
\uicontrol Options > \uicontrol Kits.
Qt for Python projects rely on the \l{Using Language Servers}
- {experimental language server client} for code completion,
- highlighting, and other useful features.
+ {language server client} for code completion, highlighting, and
+ other useful features.
If \QC cannot find an existing build for a particular \l{glossary-buildandrun-kit}{kit},
it starts out
diff --git a/doc/src/projects/creator-only/creator-projects-targets.qdoc b/doc/src/projects/creator-only/creator-projects-targets.qdoc
index 1d6101b02f..6438abc42b 100644
--- a/doc/src/projects/creator-only/creator-projects-targets.qdoc
+++ b/doc/src/projects/creator-only/creator-projects-targets.qdoc
@@ -73,6 +73,21 @@
\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 >
+ \uicontrol Kits >. For example, if you use CMake to build all your projects,
+ you can hide Qbs and qmake settings by default.
+
+ To hide and show settings in the \uicontrol Kits tab for the
+ current kit, select \uicontrol {Settings Filter}. To view and
+ modify the settings displayed when you add a new kit, select
+ \uicontrol {Default Settings Filter}.
+
+ \section1 Specifying Kit Settings
+
To add kits:
\list 1
@@ -105,13 +120,13 @@
\li In the \uicontrol Device field, select a device.
- \li In the \uicontrol {Emulator skin} field, select the skin to use for
- the \l {Emulator}{Boot2Qt Emulator 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
@@ -153,6 +168,10 @@
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 tool to use
for building the project. Select \uicontrol Manage to add installed
CMake tools to the list. For more information, see
@@ -169,10 +188,6 @@
\uicontrol Change to edit the variables of the CMake configuration
for the kit.
- \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}.
-
\endlist
\QC uses the \e {default kit} if it does not have enough information to
@@ -194,16 +209,18 @@
\list 1
\li Select \uicontrol Change next to the
- \uicontrol {Additional Qbs Profile Settings} field.
+ \uicontrol {Additional Qbs Profile Settings} field to open the
+ \uicontrol {Custom Properties} dialog.
\image qtcreator-qbs-profile-settings.
- \li Select \uicontrol Add.
+ \li Double-click an empty cell in the \uicontrol Key column to specify
+ the key to add or modify as: \c <module_name>.<property_name>.
- \li In the \uicontrol Key column, spefify the key to add or modify as:
- \c <module_name>.<property_name>.
+ \li Double-click the cell on the same row in the \uicontrol Value column
+ to specify a value as a JSON literal.
- \li In the \uicontrol Value column, specify a value as a JSON literal.
+ \li Select \uicontrol Add to add the key-value pair.
\li Click \uicontrol OK.
diff --git a/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc b/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
index 174b6c3c93..9e1fe9919e 100644
--- a/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
+++ b/doc/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
@@ -99,8 +99,9 @@
\quotefromfile progressbar/main.cpp
\skipto QQuickView view;
\printuntil view.show()
- Where \c {qml\main.qml} is the path to and the name of the main QML
- file in the Qt Quick UI project.
+ Where \c {qrc:/qml/imports} is the import path and
+ \c {qrc:qml/ProgressBar.ui.qml} is the path to and the
+ name of the main QML file in the Qt Quick UI project.
\li Select \uicontrol Build > \uicontrol Run to build and run your
project.
\endlist
diff --git a/qbs/imports/QtcProduct.qbs b/qbs/imports/QtcProduct.qbs
index 1caf073e98..a031474c29 100644
--- a/qbs/imports/QtcProduct.qbs
+++ b/qbs/imports/QtcProduct.qbs
@@ -27,7 +27,7 @@ Product {
enableFallback: false
}
}
- Depends { name: "Qt.core"; versionAtLeast: "5.9.0" }
+ Depends { name: "Qt.core"; versionAtLeast: "5.11.0" }
// TODO: Should fall back to what came from Qt.core for Qt < 5.7, but we cannot express that
// atm. Conditionally pulling in a module that sets the property is also not possible,
diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js
index 3a75fe1ead..d1bd2dd2ea 100644
--- a/qbs/modules/libclang/functions.js
+++ b/qbs/modules/libclang/functions.js
@@ -1,7 +1,7 @@
var Environment = require("qbs.Environment")
var File = require("qbs.File")
var FileInfo = require("qbs.FileInfo")
-var MinimumLLVMVersion = "6.0.0" // CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
+var MinimumLLVMVersion = "8.0.0" // CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
var Process = require("qbs.Process")
function readOutput(executable, args)
@@ -110,7 +110,7 @@ function formattingLibs(llvmConfig, qtcFunctions, targetOS)
var clangVersion = version(llvmConfig)
var libs = []
if (qtcFunctions.versionIsAtLeast(clangVersion, MinimumLLVMVersion)) {
- if (qtcFunctions.versionIsAtLeast(clangVersion, "7.0.0")) {
+ if (qtcFunctions.versionIsAtLeast(clangVersion, "8.0.0")) {
libs.push(
"clangFormat",
"clangToolingInclusions",
diff --git a/qbs/modules/libclang/libclang.qbs b/qbs/modules/libclang/libclang.qbs
index fc50b4f7c1..9c2cfae23d 100644
--- a/qbs/modules/libclang/libclang.qbs
+++ b/qbs/modules/libclang/libclang.qbs
@@ -39,8 +39,11 @@ Module {
llvmToolingDefines = toolingParams.defines;
llvmToolingIncludes = toolingParams.includes;
llvmToolingCxxFlags = toolingParams.cxxFlags;
- if (toolchain.contains("gcc"))
+ if (toolchain.contains("gcc")) {
llvmToolingCxxFlags.push("-Wno-unused-parameter");
+ // clang/Format/Format.h has intentional multiline comments
+ llvmToolingCxxFlags.push("-Wno-comment");
+ }
llvmFormattingLibs = ClangFunctions.formattingLibs(llvmConfig, QtcFunctions, targetOS);
found = llvmConfig && File.exists(llvmIncludeDir.concat("/clang-c/Index.h"));
}
@@ -61,7 +64,7 @@ Module {
return incl != llvmIncludeDir;
})
property stringList llvmToolingCxxFlags: clangProbe.llvmToolingCxxFlags
- property bool toolingEnabled: Environment.getEnv("QTC_ENABLE_CLANG_LIBTOOLING")
+ property bool toolingEnabled: !Environment.getEnv("QTC_DISABLE_CLANG_REFACTORING")
validate: {
if (!clangProbe.found) {
diff --git a/qbs/modules/qtc/qtc.qbs b/qbs/modules/qtc/qtc.qbs
index 11c1c8f099..d51dfacf38 100644
--- a/qbs/modules/qtc/qtc.qbs
+++ b/qbs/modules/qtc/qtc.qbs
@@ -4,16 +4,16 @@ import qbs.FileInfo
import "qtc.js" as HelperFunctions
Module {
- property string qtcreator_display_version: '4.9.2'
+ property string qtcreator_display_version: '4.10.0-beta2'
property string ide_version_major: '4'
property string ide_version_minor: '9'
- property string ide_version_release: '2'
+ property string ide_version_release: '83'
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.'
+ ide_version_release
property string ide_compat_version_major: '4'
property string ide_compat_version_minor: '9'
- property string ide_compat_version_release: '0'
+ property string ide_compat_version_release: '83'
property string qtcreator_compat_version: ide_compat_version_major + '.'
+ ide_compat_version_minor + '.' + ide_compat_version_release
diff --git a/qtcreator.pri b/qtcreator.pri
index 9cc64fac27..9ed1bf1c8f 100644
--- a/qtcreator.pri
+++ b/qtcreator.pri
@@ -1,18 +1,11 @@
!isEmpty(QTCREATOR_PRI_INCLUDED):error("qtcreator.pri already included")
QTCREATOR_PRI_INCLUDED = 1
-QTCREATOR_VERSION = 4.9.2
-QTCREATOR_COMPAT_VERSION = 4.9.0
-VERSION = $$QTCREATOR_VERSION
-QTCREATOR_DISPLAY_VERSION = 4.9.2
-QTCREATOR_COPYRIGHT_YEAR = 2019
-BINARY_ARTIFACTS_BRANCH = master
-
-isEmpty(IDE_DISPLAY_NAME): IDE_DISPLAY_NAME = Qt Creator
-isEmpty(IDE_ID): IDE_ID = qtcreator
-isEmpty(IDE_CASED_ID): IDE_CASED_ID = QtCreator
+include($$PWD/qtcreator_ide_branding.pri)
+!isEmpty(IDE_BRANDING_PRI): include($$IDE_BRANDING_PRI)
-isEmpty(PRODUCT_BUNDLE_IDENTIFIER): PRODUCT_BUNDLE_IDENTIFIER = org.qt-project.$$IDE_ID
+PRODUCT_BUNDLE_IDENTIFIER=$${PRODUCT_BUNDLE_ORGANIZATION}.$${IDE_ID}
+VERSION = $$QTCREATOR_VERSION
CONFIG += c++14
diff --git a/qtcreator.pro b/qtcreator.pro
index 2578649905..e22433d420 100644
--- a/qtcreator.pro
+++ b/qtcreator.pro
@@ -1,9 +1,9 @@
include(qtcreator.pri)
#version check qt
-!minQtVersion(5, 9, 0) {
+!minQtVersion(5, 11, 0) {
message("Cannot build $$IDE_DISPLAY_NAME with Qt version $${QT_VERSION}.")
- error("Use at least Qt 5.9.0.")
+ error("Use at least Qt 5.11.0.")
}
include(doc/doc.pri)
@@ -124,7 +124,7 @@ macx {
BINDIST_EXCLUDE_ARG.debug = $${BINDIST_EXCLUDE_ARG.release}
deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX/bin/$${IDE_APP_TARGET}\" \"$(QMAKE)\"
deployqt.depends = install
- win32 {
+ win32:!isEmpty(BINARY_ARTIFACTS_BRANCH) {
deployartifacts.depends = install
deployartifacts.commands = git clone --depth 1 -b $$BINARY_ARTIFACTS_BRANCH \
"http://code.qt.io/qt-creator/binary-artifacts.git" \
diff --git a/qtcreator_ide_branding.pri b/qtcreator_ide_branding.pri
new file mode 100644
index 0000000000..2555c59351
--- /dev/null
+++ b/qtcreator_ide_branding.pri
@@ -0,0 +1,12 @@
+QTCREATOR_VERSION = 4.9.83
+QTCREATOR_COMPAT_VERSION = 4.9.83
+QTCREATOR_DISPLAY_VERSION = 4.10.0-beta2
+QTCREATOR_COPYRIGHT_YEAR = 2019
+BINARY_ARTIFACTS_BRANCH = 4.10
+
+IDE_DISPLAY_NAME = Qt Creator
+IDE_ID = qtcreator
+IDE_CASED_ID = QtCreator
+
+PRODUCT_BUNDLE_ORGANIZATION = org.qt-project
+PROJECT_USER_FILE_EXTENSION = .user
diff --git a/qtcreatordata.pri b/qtcreatordata.pri
index 7d723e3170..e34e541269 100644
--- a/qtcreatordata.pri
+++ b/qtcreatordata.pri
@@ -30,8 +30,11 @@ defineReplace(stripStaticBase) {
win32:copy2build.commands = $$QMAKE_COPY \"${QMAKE_FILE_IN}\" \"${QMAKE_FILE_OUT}\"
unix:copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
copy2build.name = COPY ${QMAKE_FILE_IN}
- copy2build.config += no_link
+ copy2build.CONFIG += no_link no_clean
QMAKE_EXTRA_COMPILERS += copy2build
+ for(static_file, STATIC_FILES) {
+ QMAKE_DISTCLEAN += $$STATIC_OUTPUT_BASE/$$stripStaticBase($$static_file)
+ }
}
static.files = $$STATIC_FILES
diff --git a/scripts/generateClangFormatChecksUI.py b/scripts/generateClangFormatChecksUI.py
new file mode 100644
index 0000000000..cf38d44d92
--- /dev/null
+++ b/scripts/generateClangFormatChecksUI.py
@@ -0,0 +1,291 @@
+#!/usr/bin/env python
+############################################################################
+#
+# 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.
+#
+############################################################################
+
+import argparse
+import json
+import os
+import docutils.nodes
+import docutils.parsers.rst
+import docutils.utils
+
+def full_ui_content(checks):
+ return '''<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClangFormat::ClangFormatChecksWidget</class>
+ <widget class="QWidget" name="ClangFormat::ClangFormatChecksWidget">
+ <property name="maximumSize">
+ <size>
+ <width>480</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <layout class="QGridLayout" name="checksLayout">
+''' + checks + ''' </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
+'''
+
+def parse_arguments():
+ parser = argparse.ArgumentParser(description='Clazy checks header file generator')
+ parser.add_argument('--clang-format-options-rst', help='path to ClangFormatStyleOptions.rst',
+ default=None, dest='options_rst')
+ return parser.parse_args()
+
+def parse_rst(text):
+ parser = docutils.parsers.rst.Parser()
+ components = (docutils.parsers.rst.Parser,)
+ settings = docutils.frontend.OptionParser(components=components).get_default_values()
+ document = docutils.utils.new_document('<rst-doc>', settings=settings)
+ parser.parse(text, document)
+ return document
+
+def createItem(key, value, index):
+ label = ''' <item row="''' + str(index) + '''" column="0">
+ <widget class="QLabel" name="label''' + key + '''">
+ <property name="text">
+ <string notr="true">''' + key + '''</string>
+ </property>
+ </widget>
+ </item>
+'''
+ value_item = ''
+ if value[0] == 'bool':
+ value_item = ''' <item row="''' + str(index) + '''" column="1">
+ <widget class="QComboBox" name="''' + key + '''">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+'''
+ elif value[0].startswith('std::string') or value[0] == 'unsigned' or value[0] == 'int':
+ value_item = ''' <item row="''' + str(index) + '''" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="''' + key + '''">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="set''' + key + '''">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+'''
+ elif value[0].startswith('std::vector'):
+ value_item = ''' <item row="''' + str(index) + '''" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPlainTextEdit" name="''' + key + '''">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="set''' + key + '''">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+'''
+ else:
+ if ' ' in value[1]:
+ value_item = ''
+ for i, val in enumerate(value):
+ if i == 0:
+ continue
+ index += 1
+ space_index = val.find(' ')
+ val = val[space_index + 1:]
+ value_item += ''' <item row="''' + str(index) + '''" column="0">
+ <widget class="QLabel" name="label''' + val + '''">
+ <property name="text">
+ <string notr="true"> ''' + val + '''</string>
+ </property>
+ </widget>
+ </item>
+'''
+ value_item += ''' <item row="''' + str(index) + '''" column="1">
+ <widget class="QComboBox" name="''' + val + '''">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+'''
+ else:
+ value_item = ''' <item row="''' + str(index) + '''" column="1">
+ <widget class="QComboBox" name="''' + key + '''">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+'''
+ if key == 'Language':
+ value_item += ''' <property name="enabled">
+ <bool>false</bool>
+ </property>
+'''
+ if index > 0:
+ value_item += ''' <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+'''
+ for i, val in enumerate(value):
+ if i == 0:
+ continue
+ underline_index = val.find('_')
+ val = val[underline_index + 1:]
+ value_item += ''' <item>
+ <property name="text">
+ <string notr="true">''' + val + '''</string>
+ </property>
+ </item>
+'''
+ value_item += ''' </widget>
+ </item>
+'''
+
+ return label + value_item, index
+
+class MyVisitor(docutils.nodes.NodeVisitor):
+ in_bullet_list = False
+ in_bullet_list_paragraph = False
+ tree = {}
+ last_key = ''
+ def visit_term(self, node):
+ node_values = node.traverse(condition=docutils.nodes.Text)
+ name = node_values[0].astext()
+ self.last_key = name
+ self.tree[name] = [node_values[2].astext()]
+ def visit_bullet_list(self, node):
+ self.in_bullet_list = True
+ def depart_bullet_list(self, node):
+ self.in_bullet_list = False
+ def visit_paragraph(self, node):
+ if self.in_bullet_list:
+ self.in_bullet_list_paragraph = True
+ def depart_paragraph(self, node):
+ self.in_bullet_list_paragraph = False
+ def visit_literal(self, node):
+ if self.in_bullet_list_paragraph:
+ value = node.traverse(condition=docutils.nodes.Text)[0].astext()
+ self.tree[self.last_key].append(value)
+ self.in_bullet_list_paragraph = False
+ def unknown_visit(self, node):
+ """Called for all other node types."""
+ #print(node)
+ pass
+ def unknown_departure(self, node):
+ pass
+
+def main():
+ arguments = parse_arguments()
+
+ content = file(arguments.options_rst).read()
+ document = parse_rst(content)
+ visitor = MyVisitor(document)
+ document.walkabout(visitor)
+ keys = visitor.tree.keys()
+ basedOnStyleKey = 'BasedOnStyle'
+ keys.remove(basedOnStyleKey)
+ keys.sort()
+
+ text = ''
+ line, index = createItem(basedOnStyleKey, visitor.tree[basedOnStyleKey], 0)
+ text += line
+ index = 1
+ for key in keys:
+ line, index = createItem(key, visitor.tree[key], index)
+ text += line
+ index += 1
+
+ current_path = os.path.dirname(os.path.abspath(__file__))
+ ui_path = os.path.abspath(os.path.join(current_path, '..', 'src',
+ 'plugins', 'clangformat', 'clangformatchecks.ui'))
+ with open(ui_path, 'w') as f:
+ f.write(full_ui_content(text))
+
+if __name__ == "__main__":
+ main()
diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt
new file mode 100644
index 0000000000..471053adec
--- /dev/null
+++ b/share/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(qtcreator)
diff --git a/share/qtcreator/CMakeLists.txt b/share/qtcreator/CMakeLists.txt
new file mode 100644
index 0000000000..3fe6c60b4b
--- /dev/null
+++ b/share/qtcreator/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(template_directories cplusplus debugger glsl modeleditor qml qmldesigner
+ qmlicons qml-type-descriptions schemes snippets styles templates themes welcomescreen)
+
+add_custom_target(copy_share_to_builddir ALL
+ COMMENT Copy files into build directory
+ VERBATIM
+)
+
+foreach(dir IN ITEMS ${template_directories})
+ add_custom_command(TARGET copy_share_to_builddir POST_BUILD
+ COMMAND "${CMAKE_COMMAND}" -E copy_directory "${dir}"
+ "${PROJECT_BINARY_DIR}/${IDE_DATA_PATH}/${dir}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ COMMENT Copy files into build directory
+ VERBATIM
+ )
+endforeach()
+
+install(DIRECTORY ${template_directories} DESTINATION "${IDE_DATA_PATH}")
+install(
+ FILES indexer_preincludes/qglobal.h indexer_preincludes/windows.h
+ DESTINATION "${IDE_DATA_PATH}/indexer_preincludes"
+)
diff --git a/share/qtcreator/debugger/creatortypes.py b/share/qtcreator/debugger/creatortypes.py
index c93646a31d..087619eb4a 100644
--- a/share/qtcreator/debugger/creatortypes.py
+++ b/share/qtcreator/debugger/creatortypes.py
@@ -250,21 +250,23 @@ def qdump__Core__GeneratedFile(d, value):
d.putStringValue(value["m_d"]["d"]["path"])
d.putPlainChildren(value)
-def qdump__ProjectExplorer__Node(d, value):
- d.putStringValue(value["m_filePath"])
- d.putPlainChildren(value)
-
-def qdump__ProjectExplorer__FolderNode(d, value):
- d.putStringValue(value["m_displayName"])
- d.putPlainChildren(value)
-
-def qdump__ProjectExplorer__ToolChain(d, value):
- d.putStringValue(value["d"]["m_displayName"])
- d.putPlainChildren(value)
-
-def qdump__ProjectExplorer__Kit(d, value):
- d.putStringValue(value["d"]["m_unexpandedDisplayName"])
- d.putPlainChildren(value)
+#def qdump__ProjectExplorer__Node(d, value):
+# d.putStringValue(value["m_filePath"])
+# d.putPlainChildren(value)
+#
+#def qdump__ProjectExplorer__FolderNode(d, value):
+# d.putStringValue(value["m_displayName"])
+# d.putPlainChildren(value)
+
+# Broke when moving to unique_ptr
+#def qdump__ProjectExplorer__ToolChain(d, value):
+# d.putStringValue(value["d"]["m_displayName"])
+# d.putPlainChildren(value)
+
+# Broke when moving to unique_ptr
+#def qdump__ProjectExplorer__Kit(d, value):
+# d.putStringValue(value["d"]["m_unexpandedDisplayName"])
+# d.putPlainChildren(value)
def qdump__ProjectExplorer__ProjectNode(d, value):
qdump__ProjectExplorer__FolderNode(d, value)
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index e1d04a03f7..586df832c0 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -270,6 +270,7 @@ class DumperBase:
# Later set, or not set:
self.stringCutOff = 10000
self.displayStringLimit = 100
+ self.useTimeStamps = False
self.typesReported = {}
self.typesToReport = {}
@@ -329,6 +330,7 @@ class DumperBase:
self.showQObjectNames = int(args.get('qobjectnames', '1'))
self.nativeMixed = int(args.get('nativemixed', '0'))
self.autoDerefPointers = int(args.get('autoderef', '0'))
+ self.useTimeStamps = int(args.get('timestamps', '0'))
self.partialVariable = args.get('partialvar', '')
self.uninitialized = args.get('uninitialized', [])
self.uninitialized = list(map(lambda x: self.hexdecode(x), self.uninitialized))
@@ -422,6 +424,8 @@ class DumperBase:
self.currentIName = item.iname
self.currentValue = ReportItem();
self.currentType = ReportItem();
+ if self.useTimeStamps:
+ item.startTime = time.time()
def exitSubItem(self, item, exType, exValue, exTraceBack):
#warn('CURRENT VALUE: %s: %s %s' %
@@ -431,6 +435,8 @@ class DumperBase:
showException('SUBITEM', exType, exValue, exTraceBack)
self.putSpecialValue('notaccessible')
self.putNumChild(0)
+ if self.useTimeStamps:
+ self.put('time="%s",' % (time.time() - item.startTime))
if not self.isCli:
try:
if self.currentType.value:
@@ -1072,7 +1078,7 @@ class DumperBase:
reslist = []
for item in res.get('variables', {}):
- if not 'iname' in item:
+ if 'iname' not in item:
item['iname'] = '.' + item.get('name')
reslist.append(self.variablesToMi(item, 'local'))
@@ -1889,10 +1895,14 @@ class DumperBase:
if qobjectPtr:
qobjectType = self.createType('QObject')
- qobjectPtrType = self.createType('QObject') # FIXME.
with SubItem(self, '[parent]'):
self.putField('sortgroup', 9)
- self.putItem(self.createValue(parentPtr, qobjectPtrType))
+ if parentPtr:
+ self.putItem(self.createValue(parentPtr, qobjectType))
+ else:
+ self.putValue('0x0')
+ self.putType('QObject *')
+ self.putNumChild(0)
with SubItem(self, '[children]'):
self.putField('sortgroup', 8)
base = self.extractPointer(dd + 3 * ptrSize) # It's a QList<QObject *>
diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py
index f9e1eb138c..2f056c7a93 100644
--- a/share/qtcreator/debugger/gdbbridge.py
+++ b/share/qtcreator/debugger/gdbbridge.py
@@ -79,16 +79,16 @@ def registerCommand(name, func):
#
#######################################################################
-# Just convienience for 'python print ...'
+# For CLI dumper use, see README.txt
class PPCommand(gdb.Command):
def __init__(self):
super(PPCommand, self).__init__('pp', gdb.COMMAND_OBSCURE)
def invoke(self, args, from_tty):
- print(eval(args))
+ print(theCliDumper.fetchVariable(args))
PPCommand()
-# Just convienience for 'python print gdb.parse_and_eval(...)'
+# Just convenience for 'python print gdb.parse_and_eval(...)'
class PPPCommand(gdb.Command):
def __init__(self):
super(PPPCommand, self).__init__('ppp', gdb.COMMAND_OBSCURE)
@@ -153,7 +153,7 @@ class PlainDumper:
if d.isExpanded():
with Children(d):
for child in children:
- d.putSubItem(child[0], d.fromNativeValue(child[1]))
+ d.putSubItem(child[0], d.fromNativeValue(gdb.Value(child[1])))
def importPlainDumpers(args):
if args == 'off':
@@ -169,7 +169,7 @@ registerCommand('importPlainDumpers', importPlainDumpers)
-class OutputSafer:
+class OutputSaver:
def __init__(self, d):
self.d = d
@@ -179,7 +179,7 @@ class OutputSafer:
def __exit__(self, exType, exValue, exTraceBack):
if self.d.passExceptions and not exType is None:
- showException('OUTPUTSAFER', exType, exValue, exTraceBack)
+ showException('OUTPUTSAVER', exType, exValue, exTraceBack)
self.d.output = self.savedOutput
else:
self.savedOutput += self.d.output
@@ -1296,7 +1296,7 @@ class Dumper(DumperBase):
frame = gdb.newest_frame()
ns = self.qtNamespace()
needle = self.qtNamespace() + 'QV4::ExecutionEngine'
- pat = '%sqt_v4StackTrace(((%sQV4::ExecutionEngine *)0x%x)->currentContext())'
+ pat = '%sqt_v4StackTraceForEngine((void*)0x%x)'
done = False
while i < limit and frame and not done:
block = None
@@ -1313,7 +1313,7 @@ class Dumper(DumperBase):
dereftype = typeobj.target().unqualified()
if dereftype.name == needle:
addr = toInteger(value)
- expr = pat % (ns, ns, addr)
+ expr = pat % (ns, addr)
res = str(gdb.parse_and_eval(expr))
pos = res.find('"stack=[')
if pos != -1:
@@ -1329,7 +1329,7 @@ class Dumper(DumperBase):
frame = gdb.newest_frame()
self.currentCallContext = None
while i < limit and frame:
- with OutputSafer(self):
+ with OutputSaver(self):
name = frame.name()
functionName = '??' if name is None else name
fileName = ''
@@ -1425,7 +1425,7 @@ class CliDumper(Dumper):
self.chidrenSuffix = '] '
self.indent = 0
self.isCli = True
-
+ self.setupDumpers({})
def put(self, line):
if self.output.endswith('\n'):
@@ -1438,26 +1438,25 @@ class CliDumper(Dumper):
def putOriginalAddress(self, address):
pass
- def fetchVariables(self, args):
+ def fetchVariable(self, name):
+ args = {}
args['fancy'] = 1
args['passexception'] = 1
args['autoderef'] = 1
args['qobjectnames'] = 1
- name = args['varlist']
+ args['varlist'] = name
self.prepare(args)
self.output = name + ' = '
- frame = gdb.selected_frame()
- value = frame.read_var(name)
+ value = self.parseAndEvaluate(name)
with TopLevelItem(self, name):
self.putItem(value)
return self.output
-# Global instance.
-#if gdb.parameter('height') is None:
+
+# Global instances.
theDumper = Dumper()
-#else:
-# import codecs
-# theDumper = CliDumper()
+theCliDumper = CliDumper()
+
######################################################################
#
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py
index cf19c1eac8..0c53a1c26f 100644
--- a/share/qtcreator/debugger/lldbbridge.py
+++ b/share/qtcreator/debugger/lldbbridge.py
@@ -2216,7 +2216,7 @@ class SyntheticChildrenProvider(SummaryProvider):
SummaryProvider.update(self)
self.synthetic_children = []
- if not 'children' in self.summary:
+ if 'children' not in self.summary:
return
dereference_child = None
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index 80d5634b52..77cb2fa512 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -1234,6 +1234,11 @@ def qdump__QPixmap(d, value):
d.putPlainChildren(value)
+def qdump__QMargins(d, value):
+ d.putValue('left:%s, top:%s, right:%s, bottom:%s' % (value.split('iiii')))
+ d.putPlainChildren(value)
+
+
def qdump__QPoint(d, value):
d.putValue('(%s, %s)' % (value.split('ii')))
d.putPlainChildren(value)
diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py
index cca73b7717..b0b6899563 100644
--- a/share/qtcreator/debugger/stdtypes.py
+++ b/share/qtcreator/debugger/stdtypes.py
@@ -952,15 +952,44 @@ def qdump__std__vector(d, value):
def qdumpHelper__std__vector(d, value, isLibCpp):
innerType = value.type[0]
isBool = innerType.name == 'bool'
+
+ try:
+ allocator = value.type[1].name
+ except:
+ allocator = ''
+
+ isStdAllocator = allocator == 'std::allocator<%s>' % innerType.name
+
if isBool:
if isLibCpp:
- (start, size) = value.split("pp") # start is 'unsigned long *'
+ if isStdAllocator:
+ (start, size) = value.split("pp") # start is 'unsigned long *'
+ else:
+ start = value["__begin_"].pointer()
+ size = value["__size_"]
alloc = size
else:
- (start, soffset, pad, finish, foffset, pad, alloc) = value.split("pI@pI@p")
+ if isStdAllocator:
+ (start, soffset, pad, finish, foffset, pad, alloc) = value.split("pI@pI@p")
+ else:
+ start = value["_M_start"]["_M_p"].pointer()
+ soffset = value["_M_start"]["_M_offset"].integer()
+ finish = value["_M_finish"]["_M_p"].pointer()
+ foffset = value["_M_finish"]["_M_offset"].integer()
+ alloc = value["_M_end_of_storage"].pointer()
size = (finish - start) * 8 + foffset - soffset # 8 is CHAR_BIT.
else:
- (start, finish, alloc) = value.split("ppp")
+ if isStdAllocator:
+ (start, finish, alloc) = value.split("ppp")
+ else:
+ if isLibCpp:
+ start = value["__begin_"].pointer()
+ finish = value["__end_"].pointer()
+ alloc = value["__end_cap_"].pointer()
+ else:
+ start = value["_M_start"].pointer()
+ finish = value["_M_finish"].pointer()
+ alloc = value["_M_end_of_storage"].pointer()
size = int((finish - start) / innerType.size())
d.check(finish <= alloc)
if size > 0:
@@ -1066,7 +1095,7 @@ def qdump__std____cxx11__basic_string(d, value):
(data, size) = value.split("pI")
else:
try:
- data = value["_M_dataplus"]["_M_p"]
+ data = value["_M_dataplus"]["_M_p"].pointer()
size = int(value["_M_string_length"])
except:
d.putEmptyValue()
diff --git a/share/qtcreator/indexer_preincludes/QtCore/qconfig.h b/share/qtcreator/indexer_preincludes/QtCore/qconfig.h
new file mode 100644
index 0000000000..9534d0d8bf
--- /dev/null
+++ b/share/qtcreator/indexer_preincludes/QtCore/qconfig.h
@@ -0,0 +1,2 @@
+#include_next <QtCore/qconfig.h>
+#undef QT_REDUCE_RELOCATIONS
diff --git a/share/qtcreator/indexer_preincludes/QtCore/qglobal.h b/share/qtcreator/indexer_preincludes/QtCore/qglobal.h
new file mode 120000
index 0000000000..1ff1b44512
--- /dev/null
+++ b/share/qtcreator/indexer_preincludes/QtCore/qglobal.h
@@ -0,0 +1 @@
+../qglobal.h \ No newline at end of file
diff --git a/share/qtcreator/indexer_preincludes/qglobal.h b/share/qtcreator/indexer_preincludes/qglobal.h
new file mode 100644
index 0000000000..f41cee00e2
--- /dev/null
+++ b/share/qtcreator/indexer_preincludes/qglobal.h
@@ -0,0 +1,12 @@
+#include_next <qglobal.h>
+
+#ifdef Q_DECL_IMPORT
+#undef Q_DECL_IMPORT
+#endif
+
+#ifdef Q_DECL_EXPORT
+#undef Q_DECL_EXPORT
+#endif
+
+#define Q_DECL_IMPORT
+#define Q_DECL_EXPORT
diff --git a/share/qtcreator/indexer_preincludes/windows.h b/share/qtcreator/indexer_preincludes/windows.h
new file mode 100644
index 0000000000..631b0477f9
--- /dev/null
+++ b/share/qtcreator/indexer_preincludes/windows.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include_next <windows.h>
+
+// add here all dangerous defines
+#undef small
diff --git a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp
index f36a1d5efb..91b77e27a6 100644
--- a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp
+++ b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp
@@ -129,14 +129,14 @@ static void writeSharedMemory(SharedMemory *sharedMemory, const QImage &image)
sharedMemory->lock();
qint32 headerData[5];
- headerData[0] = image.byteCount();
+ headerData[0] = qint32(image.sizeInBytes());
headerData[1] = image.bytesPerLine();
headerData[2] = image.size().width();
headerData[3] = image.size().height();
headerData[4] = image.format();
std::memcpy(sharedMemory->data(), headerData, 20);
- std::memcpy(reinterpret_cast<char*>(sharedMemory->data()) + 20, image.constBits(), image.byteCount());
+ std::memcpy(reinterpret_cast<char*>(sharedMemory->data()) + 20, image.constBits(), image.sizeInBytes());
sharedMemory->unlock();
}
@@ -145,8 +145,8 @@ static void writeStream(QDataStream &out, const QImage &image)
out << qint32(image.bytesPerLine());
out << image.size();
out << qint32(image.format());
- out << qint32(image.byteCount());
- out.writeRawData(reinterpret_cast<const char*>(image.constBits()), image.byteCount());
+ out << qint32(image.sizeInBytes());
+ out.writeRawData(reinterpret_cast<const char*>(image.constBits()), image.sizeInBytes());
}
QDataStream &operator<<(QDataStream &out, const ImageContainer &container)
@@ -163,7 +163,8 @@ QDataStream &operator<<(QDataStream &out, const ImageContainer &container)
out << qint32(0);
writeStream(out, image);
} else {
- SharedMemory *sharedMemory = createSharedMemory(container.keyNumber(), image.byteCount() + extraDataSize);
+ const qint32 totalSize = qint32(image.sizeInBytes()) + extraDataSize;
+ SharedMemory *sharedMemory = createSharedMemory(container.keyNumber(), totalSize);
out << qint32(sharedMemory != nullptr); // send if shared memory is used
diff --git a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp b/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp
index 06a16f01c2..ca4792e7a0 100644
--- a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp
+++ b/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp
@@ -87,8 +87,7 @@ void NodeInstanceClientProxy::initializeSocket()
{
QLocalSocket *localSocket = new QLocalSocket(this);
connect(localSocket, &QIODevice::readyRead, this, &NodeInstanceClientProxy::readDataStream);
- connect(localSocket,
- static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
+ connect(localSocket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
QCoreApplication::instance(), &QCoreApplication::quit);
connect(localSocket, &QLocalSocket::disconnected, QCoreApplication::instance(), &QCoreApplication::quit);
localSocket->connectToServer(QCoreApplication::arguments().at(1), QIODevice::ReadWrite | QIODevice::Unbuffered);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.cpp
index ef8143884d..f546548b41 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.cpp
@@ -33,7 +33,6 @@
namespace QmlDesigner {
namespace Internal {
-
ComponentNodeInstance::ComponentNodeInstance(QQmlComponent *component)
: ObjectNodeInstance(component)
{
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
index fb1bad0603..a9a8111afd 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
@@ -1278,7 +1278,7 @@ void NodeInstanceServer::loadDummyContextObjectFile(const QFileInfo& qmlFileInfo
void NodeInstanceServer::loadDummyDataFiles(const QString& directory)
{
QDir dir(directory, "*.qml");
- QList<QFileInfo> filePathList = dir.entryInfoList();
+ QFileInfoList filePathList = dir.entryInfoList();
foreach (const QFileInfo &qmlFileInfo, filePathList) {
loadDummyDataFile(qmlFileInfo);
}
@@ -1287,7 +1287,7 @@ void NodeInstanceServer::loadDummyDataFiles(const QString& directory)
void NodeInstanceServer::loadDummyDataContext(const QString& directory)
{
QDir dir(directory+"/context", "*.qml");
- QList<QFileInfo> filePathList = dir.entryInfoList();
+ QFileInfoList filePathList = dir.entryInfoList();
QString baseName = QFileInfo(fileUrl().toLocalFile()).completeBaseName();
foreach (const QFileInfo &qmlFileInfo, filePathList) {
if (qmlFileInfo.completeBaseName() == baseName)
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
index 18ce40580f..2a9118625c 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
@@ -25,6 +25,9 @@
#include "qt5nodeinstanceserver.h"
+#include <QSurfaceFormat>
+
+#include <QQmlFileSelector>
#include <QQuickItem>
#include <QQuickView>
@@ -57,7 +60,19 @@ void Qt5NodeInstanceServer::initializeView()
Q_ASSERT(!quickView());
m_quickView = new QQuickView;
+
+ QSurfaceFormat surfaceFormat = m_quickView->requestedFormat();
+ surfaceFormat.setVersion(4, 1);
+ surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
+ m_quickView->setFormat(surfaceFormat);
+
DesignerSupport::createOpenGLContext(m_quickView.data());
+
+ if (qEnvironmentVariableIsSet("QML_FILE_SELECTORS")) {
+ QQmlFileSelector *fileSelector = new QQmlFileSelector(engine(), engine());
+ QStringList customSelectors = QString::fromUtf8(qgetenv("QML_FILE_SELECTORS")).split(",");
+ fileSelector->setExtraSelectors(customSelectors);
+ }
}
QQmlView *Qt5NodeInstanceServer::declarativeView() const
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/ColorEditorTemplate.template b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/ColorEditorTemplate.template
index 4ae345c678..ad6e541ce9 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/ColorEditorTemplate.template
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/ColorEditorTemplate.template
@@ -1,8 +1,5 @@
-Item {
-}
ColorEditor {
- caption: "%1"
backendValue: backendValues.%2
supportGradient: false
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/IntEditorTemplate.template b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/IntEditorTemplate.template
index bd5a899d95..981340e4cd 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/IntEditorTemplate.template
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/IntEditorTemplate.template
@@ -2,10 +2,16 @@ Label {
text: "%1"
tooltip: "%1"
}
-SpinBox {
- maximumValue: 9999999
- minimumValue: -9999999
- backendValue: backendValues.%2
- Layout.fillWidth: true
- Layout.maximumWidth: 100
+
+SecondColumnLayout {
+ SpinBox {
+ maximumValue: 9999999
+ minimumValue: -9999999
+ backendValue: backendValues.%2
+ Layout.fillWidth: true
+ Layout.maximumWidth: 100
+ }
+
+ ExpandingSpacer {
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/RealEditorTemplate.template b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/RealEditorTemplate.template
index d2a259c80e..fbc24990c8 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/RealEditorTemplate.template
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/RealEditorTemplate.template
@@ -2,12 +2,17 @@ Label {
text: "%1"
tooltip: "%1"
}
-SpinBox {
- maximumValue: 9999999
- minimumValue: -9999999
- decimals: 2
- stepSize: 0.1
- backendValue: backendValues.%2
- Layout.fillWidth: true
- Layout.maximumWidth: 100
+
+SecondColumnLayout {
+ SpinBox {
+ maximumValue: 9999999
+ minimumValue: -9999999
+ decimals: 2
+ stepSize: 0.1
+ backendValue: backendValues.%2
+ Layout.fillWidth: true
+ Layout.maximumWidth: 100
+ }
+ ExpandingSpacer {
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/TemplateTypes.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/TemplateTypes.qml
index f6a94e021b..fd3fbfaee3 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/TemplateTypes.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/PropertyTemplates/TemplateTypes.qml
@@ -49,6 +49,7 @@ AutoTypes {
Type {
typeNames: ["color", "QColor"]
- sourceFile: "StringEditorTemplate.template"
+ sourceFile: "ColorEditorTemplate.template"
+ separateSection: true
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
index d68e021d7f..6d9c073c77 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
@@ -49,13 +49,14 @@ Section {
SecondColumnLayout {
SpinBox {
+ sliderIndicatorVisible: true
backendValue: backendValues.scale
hasSlider: true
decimals: 2
minimumValue: 0.01
stepSize: 0.1
maximumValue: 10
- Layout.preferredWidth: 80
+ Layout.preferredWidth: 140
}
ExpandingSpacer {
}
@@ -65,12 +66,13 @@ Section {
}
SecondColumnLayout {
SpinBox {
+ sliderIndicatorVisible: true
backendValue: backendValues.rotation
hasSlider: true
decimals: 2
minimumValue: -360
maximumValue: 360
- Layout.preferredWidth: 80
+ Layout.preferredWidth: 140
}
ExpandingSpacer {
}
@@ -80,11 +82,12 @@ Section {
}
SecondColumnLayout {
SpinBox {
+ sliderIndicatorVisible: true
backendValue: backendValues.z
hasSlider: true
minimumValue: -100
maximumValue: 100
- Layout.preferredWidth: 80
+ Layout.preferredWidth: 140
}
ExpandingSpacer {
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml
index 567093359c..2800f89539 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml
@@ -29,6 +29,9 @@ import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls
import QtQuickDesignerTheme 1.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
RowLayout {
id: anchorRow
@@ -71,7 +74,7 @@ RowLayout {
rows: 2
columns: 2
- Controls.Label {
+ Label {
text: qsTr("Target")
color: __defaultTextColor
elide: Text.ElideRight
@@ -85,7 +88,7 @@ RowLayout {
}
}
- Controls.Label {
+ Label {
text: "Margin"
color: __defaultTextColor
elide: Text.ElideRight
@@ -99,6 +102,80 @@ RowLayout {
backendValue: anchorMargin
}
+ StudioControls.ButtonRow {
+ id: buttonRow
+ actionIndicatorVisible: false
+
+ property variant relativeTarget: anchorBackend.relativeAnchorTargetTop
+
+ onRelativeTargetChanged: {
+
+ buttonSameEdge.checked = false
+ buttonCenter.checked = false
+ buttonOppositeEdge.checked = false
+
+ if (relativeTarget == AnchorBindingProxy.SameEdge) {
+ if (!invertRelativeTargets) {
+ buttonSameEdge.checked = true
+ } else {
+ buttonOppositeEdge.checked = true
+ }
+ } else if (relativeTarget == AnchorBindingProxy.OppositeEdge) {
+ if (!invertRelativeTargets) {
+ buttonOppositeEdge.checked = true
+ } else {
+ buttonSameEdge.checked = true
+ }
+ } else if (relativeTarget == AnchorBindingProxy.Center) {
+ buttonCenter.checked = true
+ }
+ }
+
+ StudioControls.ButtonGroup {
+ id: group
+ }
+
+ StudioControls.AbstractButton {
+ id: buttonSameEdge
+ buttonIcon: verticalAnchor ? StudioTheme.Constants.anchorTop : StudioTheme.Constants.anchorLeft
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ //tooltip: verticalAnchor ? qsTr("Anchor to the top of the target.") : qsTr("Anchor to the left of the target.")
+ onClicked: {
+ if (!invertRelativeTargets)
+ sameEdgeButtonClicked();
+ else
+ oppositeEdgeButtonClicked();
+ }
+ }
+ StudioControls.AbstractButton {
+ id: buttonCenter
+ buttonIcon: verticalAnchor ? StudioTheme.Constants.centerVertical : StudioTheme.Constants.centerHorizontal
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ //tooltip: verticalAnchor ? qsTr("Anchor to the vertical center of the target.") : qsTr("Anchor to the horizontal center of the target.")
+ onClicked: centerButtonClicked();
+ }
+ StudioControls.AbstractButton {
+ id: buttonOppositeEdge
+ buttonIcon: verticalAnchor ? StudioTheme.Constants.anchorBottom : StudioTheme.Constants.anchorRight
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ //tooltip: verticalAnchor ? qsTr("Anchor to the bottom of the target.") : qsTr("Anchor to the right of the target.")
+ onClicked: {
+ if (!invertRelativeTargets)
+ oppositeEdgeButtonClicked();
+ else
+ sameEdgeButtonClicked();
+ }
+ }
+ }
+
+
+/*
ButtonRow {
id: buttonRow
@@ -157,6 +234,7 @@ RowLayout {
}
}
}
+*/
}
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
index 5c7f0302a3..a74fc94f1e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
@@ -33,9 +33,14 @@ Rectangle {
width: 320
height: 400
color: Theme.qmlDesignerBackgroundColorDarkAlternate()
+ MouseArea {
+ anchors.fill: parent
+ onClicked: forceActiveFocus()
+ }
ScrollView {
anchors.fill: parent
+ horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
Column {
y: -1
@@ -76,6 +81,7 @@ Rectangle {
typeLineEdit.forceActiveFocus()
}
tooltip: qsTr("Change the type of this item.")
+ enabled: !modelNodeBackend.multiSelection
}
ExpressionTextField {
@@ -116,17 +122,21 @@ Rectangle {
placeholderText: qsTr("id")
text: backendValues.id.value
Layout.fillWidth: true
+ width: 240
showTranslateCheckBox: false
showExtendedFunctionButton: false
+ enabled: !modelNodeBackend.multiSelection
}
// workaround: without this item the lineedit does not shrink to the
// right size after resizing to a wider width
Image {
+ visible: !modelNodeBackend.multiSelection
Layout.preferredWidth: 16
Layout.preferredHeight: 16
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked"
ToolTipArea {
+ enabled: !modelNodeBackend.multiSelection
anchors.fill: parent
onClicked: toogleExportAlias()
tooltip: qsTr("Toggles whether this item is exported as an alias property of the root item.")
@@ -179,6 +189,7 @@ Rectangle {
SecondColumnLayout {
SpinBox {
+ sliderIndicatorVisible: true
backendValue: backendValues.opacity
decimals: 2
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml
index c7e978a53f..67e0cff45a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml
@@ -67,19 +67,28 @@ Rectangle {
SecondColumnLayout {
LineEdit {
id: lineEdit
- enabled: isBaseState
+
backendValue: backendValues.id
placeholderText: qsTr("id")
text: backendValues.id.value
Layout.fillWidth: true
+ width: 240
showTranslateCheckBox: false
showExtendedFunctionButton: false
+ enabled: !modelNodeBackend.multiSelection
}
- // workaround: without this item the lineedit does not shrink to the
- // right size after resizing to a wider width
- Item {
- width: 0
- height: 1
+
+ Image {
+ visible: !modelNodeBackend.multiSelection
+ Layout.preferredWidth: 16
+ Layout.preferredHeight: 16
+ source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked"
+ ToolTipArea {
+ enabled: !modelNodeBackend.multiSelection
+ anchors.fill: parent
+ onClicked: toogleExportAlias()
+ tooltip: qsTr("Toggles whether this item is exported as an alias property of the root item.")
+ }
}
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml
index 143f950b38..6570497297 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml
@@ -73,7 +73,7 @@ Column {
SpinBox {
backendValue: backendValues.border_width
hasSlider: true
- Layout.preferredWidth: 80
+ Layout.preferredWidth: 120
}
ExpandingSpacer {
@@ -86,7 +86,7 @@ Column {
SpinBox {
backendValue: backendValues.radius
hasSlider: true
- Layout.preferredWidth: 80
+ Layout.preferredWidth: 120
minimumValue: 0
maximumValue: Math.min(backendValues.height.value, backendValues.width.value) / 2
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TargetComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TargetComboBox.qml
index 1e823bdeb0..b500f8c6a7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TargetComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/TargetComboBox.qml
@@ -26,14 +26,16 @@
import QtQuick 2.0
import HelperWidgets 2.0
import QtQuick.Layouts 1.0
-import QtQuick.Controls 1.0 as Controls
+import StudioControls 1.0 as StudioControls
import QtQuickDesignerTheme 1.0
-Controls.ComboBox {
+StudioControls.ComboBox {
property string targetName: anchorBackend.topTarget
property color textColor: Theme.color(Theme.PanelTextColorLight)
+ actionIndicatorVisible: false
+
id: targetComboBox
Connections {
@@ -50,8 +52,4 @@ Controls.ComboBox {
}
model: anchorBackend.possibleTargetItems
-
- style: CustomComboBoxStyle {
- textColor: targetComboBox.textColor
- }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml
index af29773ce2..bb545d2369 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml
@@ -25,21 +25,12 @@
import QtQuick 2.1
import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
Row {
id: alignmentHorizontalButtons
- RoundedPanel {
- width: 16
- height: parent.height
- roundLeft: true
- ExtendedFunctionButton {
- x: 2
- anchors.verticalCenter: parent.verticalCenter
- backendValue: alignmentHorizontalButtons.backendValue
- }
- }
-
property bool blueHighlight: false
property variant backendValue: backendValues.horizontalAlignment;
@@ -48,19 +39,20 @@ Row {
property bool baseStateFlag: isBaseState;
+ property color __currentColor: blueHighlight ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor
+
onValueChanged: {
- buttonRow.initalChecked = 0
- buttonRow.checkedIndex = 0
+ buttonAlignLeft.checked = true
+ buttonAlignHCenter.checked = false
+ buttonAlignRight.checked = false
+
if (value !== undefined) {
if (value === "AlignLeft") {
- buttonRow.initalChecked = 0
- buttonRow.checkedIndex = 0
+ buttonAlignLeft.checked = true
} else if (value === "AlignHCenter") {
- buttonRow.initalChecked = 1
- buttonRow.checkedIndex = 1
+ buttonAlignHCenter.checked = true
} else if (value === "AlignRight") {
- buttonRow.initalChecked = 2
- buttonRow.checkedIndex = 2
+ buttonAlignRight.checked = true
}
}
evaluate()
@@ -89,27 +81,54 @@ Row {
}
}
- ButtonRow {
+ ExtendedFunctionLogic {
+ id: extFuncLogic
+ backendValue: alignmentHorizontalButtons.backendValue
+ }
+
+ StudioControls.ButtonRow {
id: buttonRow
- exclusive: true
+ actionIndicatorVisible: true
+
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
+ StudioControls.ButtonGroup {
+ id: group
+ }
- ButtonRowButton {
- roundLeftButton: false
- iconSource: "image://icons/alignment-left" + (blueHighlight ? "-h" : "")
+ StudioControls.AbstractButton {
+ id: buttonAlignLeft
+ buttonIcon: StudioTheme.Constants.textAlignLeft
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignLeft")
}
}
- ButtonRowButton {
- iconSource: "image://icons/alignment-center" + (blueHighlight ? "-h" : "")
+ StudioControls.AbstractButton {
+ id: buttonAlignHCenter
+ buttonIcon: StudioTheme.Constants.textAlignCenter
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignHCenter")
}
}
- ButtonRowButton {
- iconSource: "image://icons/alignment-right" + (blueHighlight ? "-h" : "")
+ StudioControls.AbstractButton {
+ id: buttonAlignRight
+ buttonIcon: StudioTheme.Constants.textAlignRight
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignRight")
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml
index ac3bd20f35..d74fa5d66e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml
@@ -25,22 +25,12 @@
import QtQuick 2.1
import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
Row {
id: alignmentVerticalButtons
- RoundedPanel {
- width: 16
- height: parent.height
- roundLeft: true
-
- ExtendedFunctionButton {
- x: 2
- anchors.verticalCenter: parent.verticalCenter
- backendValue: alignmentVerticalButtons.backendValue
- }
- }
-
property bool blueHighlight: false
property variant backendValue: backendValues.verticalAlignment;
@@ -49,19 +39,20 @@ Row {
property bool baseStateFlag: isBaseState;
+ property color __currentColor: blueHighlight ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor
+
onValueChanged: {
- buttonRow.initalChecked = 0
- buttonRow.checkedIndex = 0
+ buttonAlignTop.checked = true
+ buttonAlignVCenter.checked = false
+ buttonAlignBottom.checked = false
+
if (value !== undefined) {
if (value === "AlignTop") {
- buttonRow.initalChecked = 0
- buttonRow.checkedIndex = 0
+ buttonAlignTop.checked = true
} else if (value === "AlignVCenter") {
- buttonRow.initalChecked = 1
- buttonRow.checkedIndex = 1
+ buttonAlignVCenter.checked = true
} else if (value === "AlignBottom") {
- buttonRow.initalChecked = 2
- buttonRow.checkedIndex = 2
+ buttonAlignBottom.checked = true
}
}
evaluate()
@@ -90,27 +81,54 @@ Row {
}
}
- ButtonRow {
+ ExtendedFunctionLogic {
+ id: extFuncLogic
+ backendValue: alignmentVerticalButtons.backendValue
+ }
+
+ StudioControls.ButtonRow {
id: buttonRow
- exclusive: true
+ actionIndicatorVisible: true
+
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
+ StudioControls.ButtonGroup {
+ id: group
+ }
- ButtonRowButton {
- roundLeftButton: false
- iconSource: "image://icons/alignment-top" + (blueHighlight ? "-h" : "")
+ StudioControls.AbstractButton {
+ id: buttonAlignTop
+ buttonIcon: StudioTheme.Constants.textAlignTop
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignTop")
}
}
- ButtonRowButton {
- iconSource: "image://icons/alignment-middle" + (blueHighlight ? "-h" : "")
+ StudioControls.AbstractButton {
+ id: buttonAlignVCenter
+ buttonIcon: StudioTheme.Constants.textAlignMiddle
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignVCenter")
}
}
- ButtonRowButton {
- iconSource: "image://icons/alignment-bottom" + (blueHighlight ? "-h" : "")
+ StudioControls.AbstractButton {
+ id: buttonAlignBottom
+ buttonIcon: StudioTheme.Constants.textAlignBottom
+ checkable: true
+ autoExclusive: true
+ StudioControls.ButtonGroup.group: group
+ iconColor: __currentColor
onClicked: {
if (checked)
backendValue.setEnumeration("Text", "AlignBottom")
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml
index e7f9859ee4..963f578221 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AnchorButtons.qml
@@ -25,23 +25,32 @@
import QtQuick 2.1
import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+
+StudioControls.ButtonRow {
+ id: buttonRow
-ButtonRow {
enabled: anchorBackend.hasParent
opacity: enabled ? 1 : 0.5
- id: buttonRow
+ actionIndicatorVisible: false
- ButtonRowButton {
- iconSource: "image://icons/anchor-top"
- tooltip: qsTr("Anchor item to the top.")
+ StudioControls.ButtonGroup {
+ id: group
+ }
+
+ StudioControls.AbstractButton {
+ checkable: true
+ buttonIcon: StudioTheme.Constants.anchorTop
+ //tooltip: qsTr("Anchor item to the top.")
property bool topAnchored: anchorBackend.topAnchored
onTopAnchoredChanged: {
checked = topAnchored
}
- onClicked: {
+ onClicked: {
if (checked) {
if (anchorBackend.bottomAnchored)
anchorBackend.verticalCentered = false;
@@ -52,9 +61,10 @@ ButtonRow {
}
}
- ButtonRowButton {
- iconSource: "image://icons/anchor-bottom"
- tooltip: qsTr("Anchor item to the bottom.")
+ StudioControls.AbstractButton {
+ checkable: true
+ buttonIcon: StudioTheme.Constants.anchorBottom
+ //tooltip: qsTr("Anchor item to the bottom.")
property bool bottomAnchored: anchorBackend.bottomAnchored
onBottomAnchoredChanged: {
@@ -73,9 +83,10 @@ ButtonRow {
}
- ButtonRowButton {
- iconSource: "image://icons/anchor-left"
- tooltip: qsTr("Anchor item to the left.")
+ StudioControls.AbstractButton {
+ checkable: true
+ buttonIcon: StudioTheme.Constants.anchorLeft
+ //tooltip: qsTr("Anchor item to the left.")
property bool leftAnchored: anchorBackend.leftAnchored
onLeftAnchoredChanged: {
@@ -93,9 +104,10 @@ ButtonRow {
}
}
- ButtonRowButton {
- iconSource: "image://icons/anchor-right"
- tooltip: qsTr("Anchor item to the right.")
+ StudioControls.AbstractButton {
+ checkable: true
+ buttonIcon: StudioTheme.Constants.anchorRight
+ //tooltip: qsTr("Anchor item to the right.")
property bool rightAnchored: anchorBackend.rightAnchored
onRightAnchoredChanged: {
@@ -113,14 +125,15 @@ ButtonRow {
}
}
- ButtonRowButton {
+ StudioControls.AbstractButton {
enabled: false
}
- ButtonRowButton {
- iconSource: "image://icons/anchor-fill"
- tooltip: qsTr("Fill parent item.")
+ StudioControls.AbstractButton {
+ checkable: true
+ buttonIcon: StudioTheme.Constants.anchorFill
+ //tooltip: qsTr("Fill parent item.")
property bool isFilled: anchorBackend.isFilled
onIsFilledChanged: {
@@ -136,13 +149,14 @@ ButtonRow {
}
}
- ButtonRowButton {
+ StudioControls.AbstractButton {
enabled: false
}
- ButtonRowButton {
- iconSource: "image://icons/anchor-vertical"
- tooltip: qsTr("Anchor item vertically.")
+ StudioControls.AbstractButton {
+ checkable: true
+ buttonIcon: StudioTheme.Constants.centerVertical
+ //tooltip: qsTr("Anchor item vertically.")
property bool verticalCentered: anchorBackend.verticalCentered;
onVerticalCenteredChanged: {
@@ -162,9 +176,10 @@ ButtonRow {
}
}
- ButtonRowButton {
- iconSource: "image://icons/anchor-horizontal"
- tooltip: qsTr("Anchor item horizontally.")
+ StudioControls.AbstractButton {
+ checkable: true
+ buttonIcon: StudioTheme.Constants.centerHorizontal
+ //tooltip: qsTr("Anchor item horizontally.")
property bool horizontalCentered: anchorBackend.horizontalCentered;
onHorizontalCenteredChanged: {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml
index 2b413caaef..45ff261928 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/BoolButtonRowButton.qml
@@ -25,33 +25,31 @@
import QtQuick 2.1
import HelperWidgets 2.0
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
-ButtonRowButton {
- id: boolButtonRowButton
+StudioControls.Button {
+ id: button
property variant backendValue
-
property bool isHighlighted: false
- property string standardIconSource
- property string highlightedIconSource
-
- leftPadding: 18
-
- iconSource: isHighlighted ? highlightedIconSource : standardIconSource
+ iconColor: isHighlighted ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor
+ actionIndicatorVisible: true
+ checkable: true
QtObject {
id: innerObject
function evaluate() {
if (innerObject.baseStateFlag) {
- if (boolButtonRowButton.backendValue !== null
+ if (button.backendValue !== null
&& innerObject.isInModel) {
isHighlighted = true
} else {
isHighlighted = false
}
} else {
- if (boolButtonRowButton.backendValue !== null
+ if (button.backendValue !== null
&& innerObject.isInSubState) {
isHighlighted = true
} else {
@@ -63,27 +61,30 @@ ButtonRowButton {
property bool baseStateFlag: isBaseState
onBaseStateFlagChanged: evaluate()
- property bool isInModel: boolButtonRowButton.backendValue.isInModel
+ property bool isInModel: button.backendValue.isInModel
onIsInModelChanged: evaluate()
- property bool isInSubState: boolButtonRowButton.backendValue.isInSubState
+ property bool isInSubState: button.backendValue.isInSubState
onIsInSubStateChanged: evaluate()
- property variant theValue: boolButtonRowButton.backendValue.value
+ property variant theValue: button.backendValue.value
onTheValueChanged: {
evaluate()
- boolButtonRowButton.checked = innerObject.theValue
+ button.checked = innerObject.theValue
}
}
onCheckedChanged: {
- boolButtonRowButton.backendValue.value = checked
+ button.backendValue.value = button.checked
}
- ExtendedFunctionButton {
- backendValue: boolButtonRowButton.backendValue
- x: 2
- anchors.verticalCenter: parent.verticalCenter
+ ExtendedFunctionLogic {
+ id: extFuncLogic
+ backendValue: button.backendValue
}
+
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
index 8557552b53..6ba9957cd5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
@@ -39,6 +39,8 @@ Item {
signal clicked()
+ signal doubleClicked()
+
property alias tooltip: toolTipArea.tooltip
width: 24 + leftPadding
@@ -100,7 +102,8 @@ Item {
buttonRowButton.parent.__checkButton(index())
}
buttonRowButton.clicked()
- }
+ }
+ onDoubleClicked: buttonRowButton.doubleClicked()
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml
index d69490d53a..e599088e42 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml
@@ -24,42 +24,37 @@
****************************************************************************/
import QtQuick 2.1
-import QtQuick.Controls 1.1 as Controls
+import StudioControls 1.0 as StudioControls
import QtQuick.Controls.Styles 1.1
-Controls.CheckBox {
-
+StudioControls.CheckBox {
id: checkBox
- property color textColor: colorLogic.textColor
-
- opacity: enabled ? 1 : 0.5
-
property variant backendValue
+ property string tooltip
- ExtendedFunctionButton {
- x: 22
- anchors.verticalCenter: parent.verticalCenter
+ ExtendedFunctionLogic {
+ id: extFuncLogic
backendValue: checkBox.backendValue
- visible: checkBox.enabled
}
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
+ labelColor: colorLogic.textColor
ColorLogic {
id: colorLogic
backendValue: checkBox.backendValue
onValueFromBackendChanged: {
- if (checkBox.checked !== valueFromBackend)
- checkBox.checked = valueFromBackend;
+ if (colorLogic.valueFromBackend !== undefined
+ && checkBox.checked !== colorLogic.valueFromBackend)
+ checkBox.checked = colorLogic.valueFromBackend
}
}
onCheckedChanged: {
if (backendValue.value !== checkBox.checked)
- backendValue.value = checkBox.checked;
+ backendValue.value = checkBox.checked
}
-
- style: CustomCheckBoxStyle {
- }
-
-
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml
index 203e692a82..5449f85eb6 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorButton.qml
@@ -82,6 +82,9 @@ Item {
lightnessSlider.value = lightness
alphaSlider.value = alpha
+ redSlider.value = (color.r * 255)
+ greenSlider.value = (color.g * 255)
+ blueSlider.value = (color.b * 255)
block = false
}
@@ -242,7 +245,6 @@ Item {
anchors.margins: 6
y: 4
height: parent.height - 8
- //value: colorButton.hue
onValueChanged: {
if (colorButton.hue !== value)
colorButton.hue = value
@@ -250,101 +252,194 @@ Item {
onClicked: colorButton.clicked()
}
- Column {
+ Row {
anchors.left: hueSlider.right
anchors.margins: colorButton.sliderMargins
spacing: 10
- Row {
- z: 3
- spacing: 4
- Label {
- text: "H:"
- width: 16
- color: "#eee"
- elide: Text.ElideRight
- anchors.verticalCenter: parent.verticalCenter
+ Column {
+
+ spacing: 10
+
+ Row {
+ z: 3
+ spacing: 1
+ Label {
+ text: "R"
+ width: 16
+ color: "#eee"
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ DoubleSpinBox {
+ id: redSlider
+ width: 64
+
+ stepSize: 1
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+
+ onCompressedValueModified: {
+ if (color.r !== value && !colorButton.block) {
+ color.r = (value / 255.0)
+ colorButton.clicked()
+ }
+ }
+ }
}
- DoubleSpinBox {
- id: hueSlider2
- //value: colorButton.hue
- onValueChanged: {
- if (colorButton.hue !== value && !colorButton.block) {
- colorButton.hue = value
- colorButton.clicked()
+
+ Row {
+ z: 2
+ spacing: 1
+ Label {
+ text: "G"
+ width: 16
+ color: "#eee"
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ DoubleSpinBox {
+ id: greenSlider
+ width: 64
+
+ stepSize: 1
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+
+ onCompressedValueModified: {
+ if (color.g !== value && !colorButton.block) {
+ color.g = (value / 255.0)
+ colorButton.clicked()
+ }
}
}
}
- }
- Row {
- z: 2
- spacing: 4
- Controls.Label {
- text: "S:"
- width: 16
- color: "#eee"
- elide: Text.ElideRight
- anchors.verticalCenter: parent.verticalCenter
+ Row {
+ z: 1
+ spacing: 1
+ Label {
+ text: "B"
+ width: 16
+ color: "#eee"
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ DoubleSpinBox {
+ id: blueSlider
+ width: 64
+
+ stepSize: 1
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+
+ onCompressedValueModified: {
+ if (color.b !== value && !colorButton.block) {
+ color.b = (value / 255.0)
+ colorButton.clicked()
+ }
+ }
+ }
}
- DoubleSpinBox {
- id: saturationSlider
- //value: colorButton.saturation
- onValueChanged: {
- if (colorButton.saturation !== value && !colorButton.block) {
- colorButton.saturation = value
- colorButton.clicked()
+ Row {
+ z: 0
+ spacing: 1
+ Label {
+ text: "A"
+ width: 16
+ color: "#eee"
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ DoubleSpinBox {
+ id: alphaSlider
+ width: 64
+ onCompressedValueModified: {
+ if (colorButton.alpha !== value && !colorButton.block) {
+ colorButton.alpha = value
+ colorButton.clicked()
+ }
}
}
}
}
- Row {
- z: 1
- spacing: 4
- Controls.Label {
- text: "L:"
- width: 16
- color: "#eee"
- elide: Text.ElideRight
- anchors.verticalCenter: parent.verticalCenter
- }
- DoubleSpinBox {
- id: lightnessSlider
- //value: colorButton.lightness
- onValueChanged: {
- if (colorButton.lightness !== value && !colorButton.block) {
- colorButton.lightness = value
- colorButton.clicked()
+ Column {
+
+ spacing: 10
+ Row {
+ z: 3
+ spacing: 1
+ Label {
+ text: "H"
+ width: 16
+ color: "#eee"
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ DoubleSpinBox {
+ id: hueSlider2
+ width: 64
+ onCompressedValueModified: {
+ if (colorButton.hue !== value && !colorButton.block) {
+ colorButton.hue = value
+ colorButton.clicked()
+ }
}
}
}
- }
- Row {
- z: 0
- spacing: 4
- Controls.Label {
- text: "A:"
- width: 16
- color: "#eee"
- elide: Text.ElideRight
- anchors.verticalCenter: parent.verticalCenter
+ Row {
+ z: 2
+ spacing: 1
+ Label {
+ text: "S"
+ width: 16
+ color: "#eee"
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ DoubleSpinBox {
+ id: saturationSlider
+ width: 64
+ onCompressedValueModified: {
+ if (colorButton.saturation !== value && !colorButton.block) {
+ colorButton.saturation = value
+ colorButton.clicked()
+ }
+ }
+ }
}
- DoubleSpinBox {
- id: alphaSlider
- //value: colorButton.alpha
- onValueChanged: {
- if (colorButton.alpha !== value && !colorButton.block) {
- colorButton.alpha = value
- colorButton.clicked()
+ Row {
+ z: 1
+ spacing: 1
+ Label {
+ text: "L"
+ width: 16
+ color: "#eee"
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ DoubleSpinBox {
+ id: lightnessSlider
+ width: 64
+ onCompressedValueModified: {
+ if (colorButton.lightness !== value && !colorButton.block) {
+ colorButton.lightness = value
+ colorButton.clicked()
+ }
}
}
}
}
-
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml
index 941d705abd..5f094dc00d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorCheckButton.qml
@@ -25,19 +25,54 @@
import QtQuick 2.1
-Rectangle {
- id: checkBox
- width: 18
- height: 18
+Item {
+ id: colorCheckButtonRoot
+ property bool checked: false
+ property alias buttonColor: checkBox.color
+ width: 30
+ height: 24
- border.color: "black"
- border.width: 1
- property bool checked: false
+ Rectangle {
+ id: backgroundBox
+ width: 24
+ height: 24
+ anchors.right: parent.right
- MouseArea {
- anchors.fill: parent
- onClicked: checkBox.checked = !checkBox.checked
+ color: "white"
+ border.color: "white"
+ border.width: 1
+
+ Rectangle {
+ id: checkBox
+ width: 22
+ height: 22
+ anchors.centerIn: parent
+
+ border.color: "black"
+ border.width: 1
+ }
}
+ Image {
+ id: arrowImage
+ width: 8
+ height: 4
+ source: "image://icons/down-arrow"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: backgroundBox.left
+ anchors.rightMargin: 2
+ opacity: colorToolTip.containsMouse ? 1 : 0.8
+ rotation: colorCheckButtonRoot.checked ? 0.0 : 270.0
+ }
+
+ ToolTipArea {
+ id: colorToolTip
+
+ onClicked: checked = !checked
+ hoverEnabled: true
+ anchors.fill: parent
+ anchors.leftMargin: -arrowImage.width
+ tooltip: qsTr("Toggle color picker view")
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
index e39bd8e88d..39fb95fce1 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
@@ -25,9 +25,7 @@
import QtQuick 2.1
import QtQuick.Layouts 1.0
-import QtQuick.Controls 1.0 as Controls
import QtQuickDesignerTheme 1.0
-import QtQuick.Controls.Styles 1.1
Column {
id: colorEditor
@@ -38,7 +36,7 @@ Column {
property bool supportGradient: false
- property alias caption: label.text
+ property string caption: "Color"
property variant backendValue
@@ -50,8 +48,14 @@ Column {
property alias transparent: transparentButton.checked
+ property color originalColor
+
function isNotInGradientMode() {
- return (buttonRow.checkedIndex !== 1)
+ return (buttonRow.checkedIndex === 0 || transparent)
+ }
+
+ function resetShapeColor() {
+ colorEditor.backendValue.resetValue()
}
onValueChanged: colorEditor.color = colorEditor.value
@@ -73,7 +77,7 @@ Column {
if (!gradientLine.isInValidState)
return;
- if (supportGradient && gradientLine.hasGradient) {
+ if (colorEditor.supportGradient && gradientLine.hasGradient) {
textField.text = convertColorToString(color)
gradientLine.currentColor = color
}
@@ -84,22 +88,27 @@ Column {
}
}
+ ColorLine {
+ visible: {
+ return (colorEditor.supportGradient && isNotInGradientMode())
+ }
+ currentColor: colorEditor.color
+ width: parent.width
+ }
+
GradientLine {
property bool isInValidState: false
visible: {
- if (colorEditor.shapeGradients) {
- return buttonRow.checkedIndex > 0 && buttonRow.checkedIndex < 4
- } else {
- return buttonRow.checkedIndex === 1
- }
+ return !(isNotInGradientMode())
}
id: gradientLine
width: parent.width
onCurrentColorChanged: {
- if (supportGradient && gradientLine.hasGradient)
+ if (colorEditor.supportGradient && gradientLine.hasGradient) {
colorEditor.color = gradientLine.currentColor
+ }
}
onHasGradientChanged: {
@@ -125,11 +134,21 @@ Column {
buttonRow.initalChecked = 1
}
colorEditor.color = gradientLine.currentColor
+ } else if (colorEditor.transparent) {
+ buttonRow.initalChecked = 4
} else {
buttonRow.initalChecked = 0
colorEditor.color = colorEditor.value
}
+
buttonRow.checkedIndex = buttonRow.initalChecked
+ colorEditor.originalColor = colorEditor.color
+ }
+
+ onSelectedNodeChanged: {
+ if (colorEditor.supportGradient && gradientLine.hasGradient) {
+ colorEditor.originalColor = gradientLine.currentColor
+ }
}
Connections {
@@ -137,18 +156,26 @@ Column {
onSelectionToBeChanged: {
colorEditorTimer.stop()
gradientLine.isInValidState = false
+ if (colorEditor.originalColor !== colorEditor.color) {
+ if (colorEditor.color != "#ffffff"
+ && colorEditor.color != "#000000"
+ && colorEditor.color != "#00000000") {
+ colorPalette.addColorToPalette(colorEditor.color)
+ }
+ }
}
}
Connections {
target: modelNodeBackend
onSelectionChanged: {
- if (supportGradient && gradientLine.hasGradient) {
+ if (colorEditor.supportGradient && gradientLine.hasGradient) {
colorEditor.color = gradientLine.currentColor
gradientLine.currentColor = color
textField.text = colorEditor.color
}
gradientLine.isInValidState = true
+ colorEditor.originalColor = colorEditor.color
}
}
@@ -156,29 +183,21 @@ Column {
SectionLayout {
width: parent.width
+ columnSpacing: 0
+ rowSpacing: checkButton.checked ? 8 : 2
rows: 5
+ //spacer 1
Item {
- height: 0
- width: 2
- }
-
- Item {
- height: 0
- width: 2
- }
-
- Label {
- id: label
- text: "Color"
+ height: 6
}
SecondColumnLayout {
ColorCheckButton {
id: checkButton
- color: colorEditor.color
+ buttonColor: colorEditor.color
}
LineEdit {
@@ -217,24 +236,30 @@ Column {
iconSource: "images/icon_color_solid.png"
onClicked: {
- if (colorEditor.supportGradient)
- gradientLine.deleteGradient()
+ gradientLine.deleteGradient()
textField.text = colorEditor.color
- colorEditor.backendValue.resetValue()
+ colorEditor.resetShapeColor()
}
tooltip: qsTr("Solid Color")
}
ButtonRowButton {
- visible: supportGradient
+ visible: colorEditor.supportGradient
iconSource: "images/icon_color_gradient.png"
onClicked: {
- colorEditor.backendValue.resetValue()
- if (colorEditor.shapeGradients) {
- gradientLine.deleteGradient()
+ colorEditor.resetShapeColor()
+
+ if (colorEditor.shapeGradients)
gradientLine.gradientTypeName = "LinearGradient"
+ else
+ gradientLine.gradientTypeName = "Gradient"
+
+ if (gradientLine.hasGradient)
+ gradientLine.updateGradient()
+ else {
+ gradientLine.deleteGradient()
+ gradientLine.addGradient()
}
- gradientLine.addGradient()
}
tooltip: qsTr("Linear Gradient")
@@ -305,15 +330,18 @@ Column {
}
}
ButtonRowButton {
- visible: supportGradient && colorEditor.shapeGradients
+ visible: colorEditor.supportGradient && colorEditor.shapeGradients
iconSource: "images/icon_color_radial_gradient.png"
onClicked: {
- colorEditor.backendValue.resetValue()
- if (colorEditor.shapeGradients) {
+ colorEditor.resetShapeColor()
+ gradientLine.gradientTypeName = "RadialGradient"
+
+ if (gradientLine.hasGradient)
+ gradientLine.updateGradient()
+ else {
gradientLine.deleteGradient()
- gradientLine.gradientTypeName = "RadialGradient"
+ gradientLine.addGradient()
}
- gradientLine.addGradient()
}
tooltip: qsTr("Radial Gradient")
@@ -402,18 +430,21 @@ Column {
}
}
ButtonRowButton {
- visible: supportGradient && colorEditor.shapeGradients
+ visible: colorEditor.supportGradient && colorEditor.shapeGradients
iconSource: "images/icon_color_conical_gradient.png"
onClicked: {
- colorEditor.backendValue.resetValue()
- if (colorEditor.shapeGradients) {
+ colorEditor.resetShapeColor()
+ gradientLine.gradientTypeName = "ConicalGradient"
+
+ if (gradientLine.hasGradient)
+ gradientLine.updateGradient()
+ else {
gradientLine.deleteGradient()
- gradientLine.gradientTypeName = "ConicalGradient"
+ gradientLine.addGradient()
}
- gradientLine.addGradient()
}
- tooltip: qsTr("Concial Gradient")
+ tooltip: qsTr("Conical Gradient")
GradientPopupIndicator {
@@ -473,18 +504,94 @@ Column {
id: transparentButton
iconSource: "images/icon_color_none.png"
onClicked: {
+ gradientLine.deleteGradient()
+ colorEditor.resetShapeColor()
colorEditor.color = "#00000000"
- if (colorEditor.supportGradient)
- gradientLine.deleteGradient()
}
tooltip: qsTr("Transparent")
}
}
+ Rectangle {
+ id: gradientPickerButton
+ width: 20
+ height: 20
+ visible: colorEditor.supportGradient
+
+ color: "white"
+ border.color: "white"
+ border.width: 1
+
+ ToolTipArea {
+ anchors.fill: parent
+ id: toolTipArea
+ tooltip: qsTr("Gradient Picker Dialog")
+ }
+
+ GradientPresetList {
+ id: presetList
+ visible: false
+
+ function applyPreset() {
+ 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);
+ }
+ }
+
+ onApply: {
+ if (presetList.gradientData.stopsCount > 0) {
+ applyPreset();
+ }
+ }
+
+ onSaved: {
+ gradientLine.savePreset();
+ presetList.updatePresets();
+ }
+
+ onAccepted: { //return key
+ if (presetList.gradientData.stopsCount > 0) {
+ applyPreset();
+ }
+ }
+ }
+
+ Rectangle {
+ width: 18
+ height: 18
+ anchors.centerIn: parent
+ color: "steelblue"
+
+ border.color: "black"
+ border.width: 1
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ presetList.open()
+ }
+ }
+ }
+ }
+
ExpandingSpacer {
}
}
+ Item {
+ height: 8
+ }
+
ColorButton {
property color bindedColor: colorEditor.color
@@ -496,24 +603,106 @@ Column {
enabled: !colorEditor.transparent
opacity: checkButton.checked ? 1 : 0
id: colorButton
- width: 116
- height: checkButton.checked ? 116 : 0
- Layout.preferredWidth: 116
- Layout.preferredHeight: checkButton.checked ? 116 : 0
+ Layout.preferredWidth: 124
+ Layout.preferredHeight: checkButton.checked ? 124 : 0
- sliderMargins: Math.max(0, label.width - colorButton.width) + 4
+ sliderMargins: 4
onClicked: colorEditor.color = colorButton.color
}
- SecondColumnLayout {
+ Item {
+ height: 1
}
Item {
- height: 4
- width :4
+ height: 2
+ visible: checkButton.checked
}
+ Item {
+ height: 1
+ }
+
+ Item {
+ id: colorBoxes
+
+ Layout.preferredWidth: 134
+ Layout.preferredHeight: checkButton.checked ? 70 : 0
+ visible: checkButton.checked
+
+
+ SecondColumnLayout {
+ spacing: 16
+ RowLayout {
+ spacing: 2
+ Column {
+ spacing: 5
+ Label {
+ width: parent.width
+ text: qsTr("Original")
+ color: "#eee"
+ }
+ Rectangle {
+ id: originalColorRectangle
+ color: colorEditor.originalColor
+ height: 40
+ width: 67
+
+ border.width: 1
+ border.color: "#555555"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!colorEditor.transparent)
+ colorEditor.color = colorEditor.originalColor
+ }
+ }
+ }
+ }
+
+ Column {
+ spacing: 5
+ Label {
+ width: parent.width
+ text: qsTr("New")
+ color: "#eee"
+ }
+ Rectangle {
+ id: newColorRectangle
+ color: colorEditor.color
+ height: 40
+ width: 67
+
+ border.width: 1
+ border.color: "#555555"
+ }
+ }
+ }
+
+ Column {
+ spacing: 5
+ Label {
+ width: parent.width
+ text: qsTr("Recent")
+ color: "#eee"
+ elide: Text.ElideRight
+ }
+
+ SimpleColorPalette {
+ id: colorPalette
+
+ clickable: !colorEditor.transparent
+
+ onSelectedColorChanged: {
+ colorEditor.color = colorPalette.selectedColor;
+ }
+ }
+ }
+
+ }
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml
new file mode 100644
index 0000000000..c7256ba892
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLine.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import HelperWidgets 2.0
+import QtQuick.Controls.Private 1.0 // showing a ToolTip
+
+Item {
+ width: 300
+ height: 60
+
+ property alias currentColor : colorLine.color
+
+ Column {
+ anchors.fill: parent
+
+ Item {
+ width: 1
+ height: 40
+ }
+ Rectangle {
+ height: 16
+ width: parent.width
+ border.color: "#555555"
+ border.width: 1
+
+ id: colorLine
+ color: "white"
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLogic.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLogic.qml
index 97c03ea921..4426e95cde 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLogic.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorLogic.qml
@@ -28,20 +28,21 @@ import QtQuick.Controls 1.1 as Controls
import QtQuick.Controls.Styles 1.0
import QtQuickDesignerTheme 1.0
import "Constants.js" as Constants
+import StudioTheme 1.0 as StudioTheme
QtObject {
id: innerObject
property variant backendValue
- property color textColor: Theme.color(Theme.PanelTextColorLight)
+ property color textColor: StudioTheme.Values.themeTextColor//Theme.color(Theme.PanelTextColorLight)
property variant valueFromBackend: backendValue.value;
property bool baseStateFlag: isBaseState;
property bool isInModel: backendValue.isInModel;
property bool isInSubState: backendValue.isInSubState;
property bool highlight: textColor === __changedTextColor
- property color __defaultTextColor: Theme.color(Theme.PanelTextColorLight)
- readonly property color __changedTextColor: Theme.color(Theme.QmlDesigner_HighlightColor)
+ property color __defaultTextColor: StudioTheme.Values.themeTextColor//Theme.color(Theme.PanelTextColorLight)
+ readonly property color __changedTextColor: StudioTheme.Values.themeInteraction//Theme.color(Theme.QmlDesigner_HighlightColor)
onBackendValueChanged: {
evaluate();
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml
index 08f76b4f25..62a285a52b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml
@@ -24,15 +24,16 @@
****************************************************************************/
import QtQuick 2.1
-import QtQuick.Controls 1.1 as Controls
import QtQuick.Controls.Styles 1.1
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
-Controls.ComboBox {
+StudioControls.ComboBox {
id: comboBox
property variant backendValue
- property color textColor: colorLogic.textColor
+ labelColor: edit ? StudioTheme.Values.themeTextColor : colorLogic.textColor
property string scope: "Qt"
property bool useInteger: false
@@ -45,6 +46,19 @@ Controls.ComboBox {
property bool block: false
+ property bool showExtendedFunctionButton: true
+
+ ExtendedFunctionLogic {
+ id: extFuncLogic
+ backendValue: comboBox.backendValue
+ }
+
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
+ actionIndicator.visible: showExtendedFunctionButton
+
ColorLogic {
id: colorLogic
backendValue: comboBox.backendValue
@@ -84,7 +98,7 @@ Controls.ComboBox {
}
}
- onCurrentTextChanged: {
+ onActivated: {
if (!__isCompleted)
return;
@@ -106,14 +120,4 @@ Controls.ComboBox {
__isCompleted = true;
}
- style: CustomComboBoxStyle {
- textColor: comboBox.textColor
- }
-
- ExtendedFunctionButton {
- x: 2
- anchors.verticalCenter: parent.verticalCenter
- backendValue: comboBox.backendValue
- visible: comboBox.enabled
- }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml
index ca789fab43..5b368565ae 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml
@@ -24,20 +24,70 @@
****************************************************************************/
import QtQuick 2.1
-import QtQuick.Controls 1.0
import QtQuickDesignerTheme 1.0
+import StudioControls 1.0 as StudioControls
-SpinBox {
- id: spinBox
- width: 76
- decimals: 2
- stepSize: 0.1
- minimumValue: 0
- maximumValue: 1
+Item {
+ id: wrapper
- property color textColor: Theme.color(Theme.PanelTextColorLight)
+ property alias decimals: spinBox.decimals
+ property alias hasSlider: spinBox.hasSlider
- style: CustomSpinBoxStyle {
+ property real minimumValue: 0.0
+ property real maximumValue: 1.0
+ property real stepSize: 0.1
+
+ property alias sliderIndicatorVisible: spinBox.sliderIndicatorVisible
+
+ property real value
+
+ onValueChanged: spinBox.value = wrapper.value * spinBox.factor
+
+ signal compressedValueModified
+ signal valueModified
+
+ width: 90
+ implicitHeight: spinBox.height
+
+ onStepSizeChanged: spinBox.convert("stepSize", wrapper.stepSize)
+ onMinimumValueChanged: spinBox.convert("from", wrapper.minimumValue)
+ onMaximumValueChanged: spinBox.convert("to", wrapper.maximumValue)
+
+ StudioControls.SpinBox {
+ id: spinBox
+
+ onValueModified: wrapper.valueModified()
+ onCompressedValueModified: wrapper.compressedValueModified()
+
+ onValueChanged: {
+ if (spinBox.__initialized)
+ wrapper.value = spinBox.value / spinBox.factor
+ }
+
+ width: wrapper.width
+ decimals: 2
+
+ actionIndicatorVisible: false
+
+ property bool __initialized: false
+
+ property bool hasSlider: spinBox.sliderIndicatorVisible
+
+ Component.onCompleted: {
+ spinBox.__initialized = true
+
+ spinBox.convert("stepSize", wrapper.stepSize)
+ spinBox.convert("from", wrapper.minimumValue)
+ spinBox.convert("to", wrapper.maximumValue)
+
+ spinBox.value = wrapper.value * spinBox.factor
+ }
+
+ function convert(target, value) {
+ if (!spinBox.__initialized)
+ return
+ spinBox[target] = Math.round(value * spinBox.factor)
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
new file mode 100644
index 0000000000..f64dd62220
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please 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.1
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
+import QtQuickDesignerTheme 1.0
+
+Item {
+ id: extendedFunctionButton
+
+ property variant backendValue
+ property bool isBoundBackend: backendValue.isBound
+ property string backendExpression: backendValue.expression
+
+ property string glyph: StudioTheme.Constants.actionIcon
+ property string color: StudioTheme.Constants.themeTextColor
+ property alias menuLoader: menuLoader
+
+ signal reseted
+
+ function show() {
+ menuLoader.show()
+ }
+
+ function setIcon() {
+ extendedFunctionButton.color = StudioTheme.Values.themeTextColor
+ if (backendValue === null) {
+ extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon
+ } else if (backendValue.isBound) {
+ if (backendValue.isTranslated) {
+ // translations are a special case
+ extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon
+ } else {
+ extendedFunctionButton.glyph = StudioTheme.Constants.actionIconBinding
+ extendedFunctionButton.color = StudioTheme.Values.themeInteraction
+ }
+ } else {
+ if (backendValue.complexNode !== null
+ && backendValue.complexNode.exists) {
+
+ } else {
+ extendedFunctionButton.glyph = StudioTheme.Constants.actionIcon
+ }
+ }
+ }
+
+ onBackendValueChanged: {
+ setIcon()
+ }
+
+ onIsBoundBackendChanged: {
+ setIcon()
+ }
+
+ onBackendExpressionChanged: {
+ setIcon()
+ }
+
+ Loader {
+ id: menuLoader
+
+ active: false
+
+ function show() {
+ active = true
+ item.popup()
+ }
+
+ sourceComponent: Component {
+ StudioControls.Menu {
+ id: menu
+
+ onAboutToShow: {
+ exportMenuItem.checked = backendValue.hasPropertyAlias()
+ exportMenuItem.enabled = !backendValue.isAttachedProperty()
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Reset")
+ onTriggered: {
+ transaction.start()
+ backendValue.resetValue()
+ backendValue.resetValue()
+ transaction.end()
+ extendedFunctionButton.reseted()
+ }
+ }
+ StudioControls.MenuItem {
+ text: qsTr("Set Binding")
+ onTriggered: expressionDialogLoader.show()
+ }
+ StudioControls.MenuItem {
+ id: exportMenuItem
+ text: qsTr("Export Property as Alias")
+ onTriggered: {
+ if (checked)
+ backendValue.exportPopertyAsAlias()
+ else
+ backendValue.removeAliasExport()
+ }
+ checkable: true
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Insert Keyframe")
+ enabled: hasActiveTimeline
+ onTriggered: insertKeyframe(backendValue.name)
+ }
+ }
+ }
+ }
+
+ Loader {
+ id: expressionDialogLoader
+ parent: itemPane
+ anchors.fill: parent
+
+ visible: false
+ active: visible
+
+ function show() {
+ expressionDialogLoader.visible = true
+ }
+
+ sourceComponent: Component {
+ Item {
+ id: expressionDialog
+ anchors.fill: parent
+
+ Component.onCompleted: {
+ textField.text = backendValue.expression
+ textField.forceActiveFocus()
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: Theme.qmlDesignerBackgroundColorDarker()
+ opacity: 0.6
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onDoubleClicked: expressionDialog.visible = false
+ }
+
+ Rectangle {
+ x: 4
+ Component.onCompleted: {
+ var pos = itemPane.mapFromItem(
+ extendedFunctionButton.parent, 0, 0)
+ y = pos.y + 2
+ }
+
+ width: parent.width - 8
+ height: 260
+
+ radius: 2
+ color: Theme.qmlDesignerBackgroundColorDarkAlternate()
+ border.color: Theme.qmlDesignerBorderColor()
+
+ Label {
+ x: 8
+ y: 6
+ font.bold: true
+ text: qsTr("Binding Editor")
+ }
+ ExpressionTextField {
+ id: textField
+ onRejected: expressionDialogLoader.visible = false
+ onAccepted: {
+ backendValue.expression = textField.text.trim()
+ expressionDialogLoader.visible = false
+ }
+ anchors.fill: parent
+ anchors.leftMargin: 8
+ anchors.rightMargin: 8
+ anchors.topMargin: 24
+ anchors.bottomMargin: 32
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml
index 7a90e89413..50590efc1f 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlickableSection.qml
@@ -32,40 +32,12 @@ Section {
anchors.right: parent.right
caption: qsTr("Flickable")
- SectionLayout {
- Label {
- text: qsTr("Content size")
- }
-
- SecondColumnLayout {
-
- Label {
- text: "W"
- width: 12
- }
-
- SpinBox {
- backendValue: backendValues.contentWidth
- minimumValue: 0
- maximumValue: 8000
- }
-
- Label {
- text: "H"
- width: 12
- }
-
- SpinBox {
- backendValue: backendValues.contentHeight
- minimumValue: 0
- maximumValue: 8000
+ id: root
- }
+ property int spinBoxWidth: 62
- ExpandingSpacer {
+ SectionLayout {
- }
- }
Label {
text: qsTr("Flick direction")
@@ -83,7 +55,7 @@ Section {
Label {
text: qsTr("Behavior")
- tooltip: qsTr("Bounds behavior")
+ tooltip: qsTr("Determines whether the surface may be dragged beyond the Flickable's boundaries, or overshoot the Flickable's boundaries when flicked.")
}
SecondColumnLayout {
@@ -96,6 +68,22 @@ Section {
}
+
+ Label {
+ text: qsTr("Movement")
+ tooltip: qsTr("Determines whether the flickable will give a feeling that the edges of the view are soft, rather than a hard physical boundary.")
+ }
+
+ SecondColumnLayout {
+ ComboBox {
+ backendValue: backendValues.boundsMovement
+ model: ["FollowBoundsBehavior", "StopAtBounds"]
+ Layout.fillWidth: true
+ scope: "Flickable"
+ }
+
+ }
+
Label {
text:qsTr("Interactive")
}
@@ -143,5 +131,202 @@ Section {
}
}
+ Label {
+ text: qsTr("Press delay")
+ tooltip: qsTr("Holds the time to delay (ms) delivering a press to children of the Flickable.")
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ backendValue: backendValues.pressDelay
+ minimumValue: 0
+ maximumValue: 2000
+ decimals: 0
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text:qsTr("Pixel aligned")
+ }
+
+ SecondColumnLayout {
+ CheckBox {
+ backendValue: backendValues.pixelAligned
+ tooltip: qsTr("Sets the alignment of contentX and contentY to pixels (true) or subpixels (false).")
+ }
+
+ ExpandingSpacer {
+ }
+ }
+
+ Label {
+ text: qsTr("Content size")
+ }
+
+ SecondColumnLayout {
+
+ Label {
+ text: "W"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.contentWidth
+ minimumValue: 0
+ maximumValue: 8000
+ implicitWidth: root.spinBoxWidth
+ }
+
+ Item {
+ width: 4
+ height: 4
+ }
+
+ Label {
+ text: "H"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.contentHeight
+ minimumValue: 0
+ maximumValue: 8000
+ implicitWidth: root.spinBoxWidth
+
+ }
+
+ ExpandingSpacer {
+
+ }
+ }
+
+ Label {
+ text: qsTr("Content")
+ }
+
+ SecondColumnLayout {
+
+ Label {
+ text: "X"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.contentX
+ minimumValue: 0
+ maximumValue: 8000
+ implicitWidth: root.spinBoxWidth
+ }
+
+ Item {
+ width: 4
+ height: 4
+ }
+
+ Label {
+ text: "Y"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.contentY
+ minimumValue: 0
+ maximumValue: 8000
+ implicitWidth: root.spinBoxWidth
+
+ }
+
+ ExpandingSpacer {
+
+ }
+ }
+
+ Label {
+ text: qsTr("Margins")
+ }
+
+ SecondColumnLayout {
+ Layout.fillWidth: true
+
+ Label {
+ text: "Top"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.topMargin
+ maximumValue: 0xffff
+ minimumValue: 0
+ decimals: 0
+ implicitWidth: root.spinBoxWidth
+ }
+
+ Item {
+ width: 4
+ height: 4
+ }
+
+ Label {
+ text: "Bottom"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.bottomMargin
+ maximumValue: 0xffff
+ minimumValue: 0
+ decimals: 0
+ implicitWidth: root.spinBoxWidth
+ }
+ ExpandingSpacer {
+
+ }
+ }
+
+ Label {
+ text: ("")
+ }
+
+ SecondColumnLayout {
+ Layout.fillWidth: true
+
+ Label {
+ text: "Left"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.leftMargin
+ maximumValue: 0xffff
+ minimumValue: 0
+ decimals: 0
+ implicitWidth: root.spinBoxWidth
+ }
+
+ Item {
+ width: 4
+ height: 4
+ }
+
+ Label {
+ text: "Right"
+ width: 28
+ }
+
+ SpinBox {
+ backendValue: backendValues.rightMargin
+ maximumValue: 0xffff
+ minimumValue: 0
+ decimals: 0
+ implicitWidth: root.spinBoxWidth
+ }
+ ExpandingSpacer {
+
+ }
+ }
+
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml
index 6cca085da7..5d9ae328d2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml
@@ -26,27 +26,66 @@
import QtQuick 2.1
import HelperWidgets 2.0
import QtQuick.Layouts 1.0
-import QtQuick.Controls 1.0 as Controls
+import StudioControls 1.0 as StudioControls
-Controls.ComboBox {
+StudioControls.ComboBox {
id: comboBox
property variant backendValue
property color textColor: colorLogic.textColor
+ labelColor: colorLogic.textColor
+
onTextColorChanged: setColor()
editable: true
- model: ["Arial", "Times New Roman", "Courier", "Verdana", "Tahoma"]
+
+ property string fontFilter: "*.ttf *.otf"
+
+
+ FileResourcesModel {
+ modelNodeBackendProperty: modelNodeBackend
+ filter: comboBox.fontFilter
+ id: fileModel
+ }
+
+ function fontUrlToName(url) {
+ var fontLoader = Qt.createQmlObject('import QtQuick 2.0; FontLoader { source: \"' + url + '\"; }',
+ comboBox,
+ "dynamicFontLoader");
+ return fontLoader.name
+ }
+
+ function setupModel() {
+ var files = fileModel.fileModel
+ var familyNames = ["Arial", "Times New Roman", "Courier", "Verdana", "Tahoma"]
+
+ files.forEach(function (item, index) {
+ var name = fontUrlToName(fileModel.dirPath + "/" + item)
+ familyNames.push(name)
+ });
+
+ familyNames.sort()
+ comboBox.model = familyNames
+ }
onModelChanged: {
editText = comboBox.backendValue.valueToString
}
- style: CustomComboBoxStyle {
- textColor: comboBox.textColor
+ ExtendedFunctionLogic {
+ id: extFuncLogic
+ backendValue: comboBox.backendValue
}
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
+ property bool showExtendedFunctionButton: true
+
+ actionIndicator.visible: showExtendedFunctionButton
+
ColorLogic {
id: colorLogic
backendValue: comboBox.backendValue
@@ -82,21 +121,16 @@ Controls.ComboBox {
backendValue.value = indexText;
}
- ExtendedFunctionButton {
- x: 2
- anchors.verticalCenter: parent.verticalCenter
- backendValue: comboBox.backendValue
- visible: comboBox.enabled
- }
-
Connections {
target: modelNodeBackend
onSelectionChanged: {
comboBox.editText = backendValue.value
+ setupModel()
}
}
Component.onCompleted: {
+ setupModel()
//Hack to style the text input
for (var i = 0; i < comboBox.children.length; i++) {
if (comboBox.children[i].text !== undefined) {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml
index 10d562da15..28621e4be6 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontSection.qml
@@ -26,7 +26,7 @@
import QtQuick 2.1
import HelperWidgets 2.0
import QtQuick.Layouts 1.0
-import QtQuick.Controls 1.0 as Controls
+import StudioControls 1.0 as StudioControls
import QtQuickDesignerTheme 1.0
Section {
@@ -63,6 +63,7 @@ Section {
FontComboBox {
backendValue: fontSection.fontFamily
Layout.fillWidth: true
+ width: 160
}
Label {
@@ -111,11 +112,13 @@ Section {
}
}
- Controls.ComboBox {
+ StudioControls.ComboBox {
id: sizeType
model: ["pixels", "points"]
property color textColor: Theme.color(Theme.PanelTextColorLight)
- onCurrentIndexChanged: {
+ actionIndicatorVisible: false
+
+ onActivated: {
if (sizeWidget.isSetup)
return;
if (currentText == "pixels") {
@@ -128,10 +131,6 @@ Section {
}
Layout.fillWidth: true
-
- style: CustomComboBoxStyle {
- }
-
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontStyleButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontStyleButtons.qml
index 23e5db53e5..ff06c1e1bd 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontStyleButtons.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontStyleButtons.qml
@@ -25,6 +25,7 @@
import QtQuick 2.1
import HelperWidgets 2.0
+import StudioTheme 1.0 as StudioTheme
ButtonRow {
@@ -34,25 +35,31 @@ ButtonRow {
property variant strikeout: backendValues.font_strikeout
BoolButtonRowButton {
- standardIconSource: "image://icons/style-bold"
- highlightedIconSource: "image://icons/style-bold-h"
+ buttonIcon: StudioTheme.Constants.fontStyleBold
backendValue: bold
}
+ Item {
+ width: 4
+ height: 4
+ }
BoolButtonRowButton {
- standardIconSource: "image://icons/style-italic"
- highlightedIconSource: "image://icons/style-italic-h"
+ buttonIcon: StudioTheme.Constants.fontStyleItalic
backendValue: italic
}
+ Item {
+ width: 4
+ height: 4
+ }
BoolButtonRowButton {
- standardIconSource: "image://icons/style-underline"
- highlightedIconSource: "image://icons/style-underline-h"
+ buttonIcon: StudioTheme.Constants.fontStyleUnderline
backendValue: underline
}
-
+ Item {
+ width: 4
+ height: 4
+ }
BoolButtonRowButton {
- standardIconSource: "image://icons/style-strikeout"
- highlightedIconSource: "image://icons/style-strikeout-h"
+ buttonIcon: StudioTheme.Constants.fontStyleStrikethrough
backendValue: strikeout
}
-
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml
index 0f0c8b8586..f1886ada43 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientLine.qml
@@ -40,6 +40,8 @@ Item {
property alias gradientPropertyName: gradientModel.gradientPropertyName
property alias gradientTypeName: gradientModel.gradientTypeName
+ signal selectedNodeChanged
+
onHasGradientChanged: {
colorLine.invalidate()
}
@@ -59,6 +61,26 @@ Item {
gradientModel.deleteGradient()
}
+ function setPresetByID(presetID) {
+ gradientModel.setPresetByID(presetID)
+ colorLine.invalidate()
+ colorLine.select(0)
+ }
+
+ function setPresetByStops(stopsPositions, stopsColors, stopsCount) {
+ gradientModel.setPresetByStops(stopsPositions, stopsColors, stopsCount)
+ colorLine.invalidate()
+ colorLine.select(0)
+ }
+
+ function savePreset() {
+ gradientModel.savePreset()
+ }
+
+ function updateGradient() {
+ gradientModel.updateGradient()
+ }
+
Connections {
target: modelNodeBackend
onSelectionChanged: {
@@ -89,6 +111,7 @@ Item {
gradientModel.lock()
currentColor = repeater.itemAt(index).item.color
gradientModel.unlock()
+ selectedNodeChanged()
}
function invalidate() {
@@ -118,6 +141,7 @@ Item {
height: 40
anchors.left: parent.left
anchors.right: parent.right
+ cursorShape: Qt.PointingHandCursor
onClicked: {
var currentPosition = mouseX / colorLine.effectiveWidth
@@ -305,6 +329,7 @@ Item {
drag.maximumX: colorLine.effectiveWidth
drag.minimumY: !readOnly ? 0 : 20
drag.maximumY: 20
+ cursorShape: Qt.PointingHandCursor
// using pressed property instead of drag.active which was not working
onExited: {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
new file mode 100644
index 0000000000..b96d858ba4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please 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.11
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.5
+import QtQuick.Dialogs 1.3
+
+import HelperWidgets 2.0
+import QtQuickDesignerTheme 1.0
+
+Dialog {
+ id: dialogWindow
+ width: 1200
+ height: 650
+ title: "Gradient Picker"
+
+ signal saved;
+ property alias gradientData: gradientPickerData;
+
+
+ QtObject {
+ id: gradientPickerData
+ property var stops;
+ property var colors;
+ property int stopsCount;
+ property int presetID;
+ property int presetType; //default(0) or custom(1)
+ }
+
+ function addGradient(stopsPositions, stopsColors, stopsCount) {
+ customPresetListModel.addGradient(stopsPositions, stopsColors, stopsCount);
+ }
+
+ function updatePresets() {
+ customPresetListModel.readPresets();
+ }
+
+ GradientPresetDefaultListModel { id: defaultPresetListModel; }
+ GradientPresetCustomListModel { id: customPresetListModel; }
+
+ standardButtons: Dialog.NoButton
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: -12
+ anchors.bottomMargin: -70
+ color: "#363636"
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.margins: 13
+ anchors.bottomMargin: 71
+ TabView {
+ id: presetTabView
+ Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Tab {
+ title: qsTr("System Presets")
+ anchors.fill:parent
+
+ GradientPresetTabContent {
+ id: defaultTabContent
+ viewModel: defaultPresetListModel
+ editableName: false
+ }
+
+ } //tab default
+ Tab {
+ title: qsTr("User Presets")
+ anchors.fill: parent
+
+ GradientPresetTabContent {
+ id: customTabContent
+ viewModel: customPresetListModel
+ editableName: true
+ onPresetNameChanged: customPresetListModel.changePresetName(id, name);
+ property int deleteId;
+
+ onDeleteButtonClicked: {
+ deleteId = id;
+ deleteDialog.open()
+ }
+
+ MessageDialog {
+ id: deleteDialog
+ visible: false
+ modality: Qt.WindowModal
+ standardButtons: Dialog.No | Dialog.Yes
+ title: qsTr("Delete preset?")
+ text: qsTr("Are you sure you want to delete this preset?")
+ onAccepted: customPresetListModel.deletePreset(customTabContent.deleteId);
+ }
+ }
+ } //tab custom
+ } //tabview
+ RowLayout {
+ Layout.alignment: Qt.AlignBottom | Qt.AlignRight
+ Layout.topMargin: 5
+
+ Button { id: buttonClose; text: qsTr("Close"); onClicked: { dialogWindow.reject(); } }
+ Button { id: buttonSave; text: qsTr("Save"); onClicked: { dialogWindow.saved(); } }
+ Button { id: buttonApply; text: qsTr("Apply"); onClicked: { dialogWindow.apply(); } }
+ } //RowLayout
+ } //ColumnLayout
+ } //rectangle
+} //dialog
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
new file mode 100644
index 0000000000..fa59794b14
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please 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.11
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.5
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Dialogs 1.3
+
+import HelperWidgets 2.0
+import QtQuickDesignerTheme 1.0
+
+
+Rectangle {
+ id: tabBackground
+ width: parent.width
+ height: parent.height
+ color: "#242424"
+ anchors.fill: parent
+
+ property alias viewModel : gradientTable.model;
+ property bool editableName : false;
+ signal presetNameChanged(int id, string name)
+ signal deleteButtonClicked(int id)
+
+ property int delegateWidth: 153;
+ property int delegateHeight: 173;
+ property int gridCellWidth: 160;
+
+
+ ScrollView {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ anchors.fill: parent
+
+ GridView {
+ id: gradientTable
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ anchors.fill: parent
+ anchors.leftMargin: 10
+ clip: true
+ delegate: gradientDelegate
+
+
+ property int gridColumns: width / tabBackground.gridCellWidth;
+ cellWidth: width / gridColumns
+ cellHeight: 180
+
+ Component {
+ id: gradientDelegate
+
+ Rectangle {
+ id: backgroundCard
+ color: "#404040"
+ clip: false
+
+ property real flexibleWidth: (gradientTable.width - gradientTable.cellWidth * gradientTable.gridColumns) / gradientTable.gridColumns
+ width: gradientTable.cellWidth + flexibleWidth - 8; height: tabBackground.delegateHeight
+ radius: 16
+
+ MouseArea {
+ id: rectMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: {
+ gradientTable.currentIndex = index;
+ gradientData.stops = stopsPosList;
+ gradientData.colors = stopsColorList;
+ gradientData.stopsCount = stopListSize;
+ gradientData.presetID = presetID;
+ gradientData.presetType = presetTabView.currentIndex
+
+// console.log( "#" + preset + " " + presetName + " Stops: " + stopsPosList + " Colors: " + stopsColorList);
+ }
+ onEntered: {
+ if (backgroundCard.state != "CLICKED") {
+ backgroundCard.state = "HOVER";
+ }
+ }
+ onExited: {
+ if (backgroundCard.state != "CLICKED") {
+ backgroundCard.state = "USUAL";
+ }
+ }
+ } //mouseArea
+
+ states: [
+ State {
+ name: "HOVER"
+ PropertyChanges {
+ target: backgroundCard
+ color: "#606060"
+ z: 5
+ clip: true
+ border.width: 1
+ border.color: "#029de0"
+ }
+ },
+ State {
+ name: "USUAL"
+ PropertyChanges
+ {
+ target: backgroundCard
+ color: "#404040"
+ scale: 1.0
+ border.width: 0
+ }
+ }
+ ] //states
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ Rectangle {
+ width: 150; height: 150
+ id: gradientRect
+ radius: 16
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+ Layout.topMargin: 2
+ gradient: Gradient {
+ id: showGr
+ }
+
+ Component {
+ id: stopComponent
+ GradientStop {}
+ }
+
+ Component.onCompleted: {
+ var stopsAmount = stopListSize;
+ var newStops = [];
+ for (var i = 0; i < stopsAmount; i++ ) {
+ newStops.push( stopComponent.createObject(showGr, { "position": stopsPosList[i], "color": stopsColorList[i] }) );
+ }
+ showGr.stops = newStops;
+ }
+
+ Rectangle {
+ id: removeItemRect
+ anchors.right: parent.right
+ anchors.rightMargin: 2
+ anchors.top: parent.top
+ anchors.topMargin: 2
+ height: 16
+ width: 16
+ visible: editableName && rectMouseArea.containsMouse
+ color: "#804682b4"
+
+
+ MouseArea {
+ anchors.fill: parent;
+ onClicked: tabBackground.deleteButtonClicked(index);
+ }
+
+ Image {
+ id: remoreItemImg
+ source: "image://icons/close"
+ fillMode: Image.PreserveAspectFit
+ anchors.fill: parent;
+ Layout.alignment: Qt.AlignCenter
+ }
+ }
+ } //rectangle gradient
+
+ TextInput {
+ id: presetNameBox
+ readOnly: !editableName
+ text: (presetName)
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
+ Layout.preferredWidth: backgroundCard.width
+ Layout.topMargin: -5
+ padding: 5.0
+ topPadding: -2.0
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.Wrap
+ color: "#ffffff"
+ activeFocusOnPress: true
+
+ onEditingFinished: tabBackground.presetNameChanged(index, text);
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
+ event.accepted = true;
+ editingFinished();
+ focus = false;
+ }
+ } //Keys.onPressed
+ } //textInput
+ } //columnLayout
+ } //rectangle background
+ } //component delegate
+ } //gridview
+ } //scrollView
+} //rectangle
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPropertySpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPropertySpinBox.qml
index 4ca86b097d..54483e1598 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPropertySpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPropertySpinBox.qml
@@ -25,20 +25,20 @@
import QtQuick 2.1
import QtQuick.Layouts 1.0
-import QtQuick.Controls 1.0 as Controls
import QtQuickDesignerTheme 1.0
-import QtQuick.Controls.Styles 1.1
+import StudioControls 1.0 as StudioControls
-DoubleSpinBox {
+StudioControls.SpinBox {
id: spinBox
width: 82
Layout.minimumWidth: 82
property string propertyName
+ actionIndicatorVisible: false
- minimumValue: -9999
- maximumValue: 9999
+ from: -9999
+ to: 9999
Component.onCompleted: spinBox.value = gradientLine.model.readGradientProperty(propertyName)
- onValueChanged: gradientLine.model.setGradientProperty(propertyName, spinBox.value)
+ onCompressedValueModified: gradientLine.model.setGradientProperty(propertyName, spinBox.value)
stepSize: 1
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml
index 8498f838ac..e4129c6dcf 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml
@@ -28,6 +28,7 @@ import QtQuick.Controls 1.1 as Controls
import QtQuick.Layouts 1.0
import QtQuick.Controls.Private 1.0
import QtQuickDesignerTheme 1.0
+import StudioTheme 1.0 as StudioTheme
Controls.Label {
id: label
@@ -36,10 +37,12 @@ Controls.Label {
// workaround because PictureSpecifics.qml still use this
property alias toolTip: toolTipArea.tooltip
- width: Math.max(Math.min(240, parent.width - 220), 80)
+ width: Math.max(Math.min(240, parent.width - 280), 50)
color: Theme.color(Theme.PanelTextColorLight)
elide: Text.ElideRight
+ font.pixelSize: StudioTheme.Values.myFontSize
+
Layout.preferredWidth: width
Layout.minimumWidth: width
Layout.maximumWidth: width
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
index c4ff04b7f1..90e222bead 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
@@ -24,24 +24,21 @@
****************************************************************************/
import QtQuick 2.2
-import QtQuick.Controls 1.1 as Controls
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
import QtQuick.Controls.Styles 1.0
import QtQuickDesignerTheme 1.0
-Controls.TextField {
-
- Controls.Action {
- //Workaround to avoid that "Delete" deletes the item.
- shortcut: "Delete"
- }
-
+StudioControls.TextField {
id: lineEdit
+
property variant backendValue
property color borderColor: "#222"
property color highlightColor: "orange"
- property color textColor: colorLogic.textColor
+ color: lineEdit.edit ? StudioTheme.Values.themeTextColor : colorLogic.textColor
property bool showTranslateCheckBox: true
+ translationIndicatorVisible: showTranslateCheckBox
property bool writeValueManually: false
@@ -49,6 +46,8 @@ Controls.TextField {
property bool showExtendedFunctionButton: true
+ actionIndicator.visible: showExtendedFunctionButton
+
signal commitData
property string context
@@ -58,19 +57,21 @@ Controls.TextField {
if (translateFunction() === "qsTranslate") {
backendValue.expression = translateFunction()
+ "(\"" + backendValue.getTranslationContext()
- + "\", " + "\"" + trCheckbox.escapeString(text) + "\")"
+ + "\", " + "\"" + escapeString(text) + "\")"
} else {
- backendValue.expression = translateFunction() + "(\"" + trCheckbox.escapeString(text) + "\")"
+ backendValue.expression = translateFunction() + "(\"" + escapeString(text) + "\")"
}
}
- ExtendedFunctionButton {
- x: 4
- anchors.verticalCenter: parent.verticalCenter
+ ExtendedFunctionLogic {
+ id: extFuncLogic
backendValue: lineEdit.backendValue
- visible: lineEdit.enabled && showExtendedFunctionButton
}
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
ColorLogic {
id: colorLogic
backendValue: lineEdit.backendValue
@@ -102,7 +103,6 @@ Controls.TextField {
}
onEditingFinished: {
-
if (writeValueManually)
return
@@ -118,87 +118,35 @@ Controls.TextField {
__dirty = false
}
- style: TextFieldStyle {
-
- selectionColor: Theme.color(Theme.PanelTextColorLight)
- selectedTextColor: Theme.color(Theme.PanelTextColorMid)
- textColor: lineEdit.textColor
- placeholderTextColor: Theme.color(Theme.PanelTextColorMid)
-
- padding.top: 2
- padding.bottom: 2
- padding.left: 18
- padding.right: lineEdit.showTranslateCheckBox ? 16 : 1
- background: Rectangle {
- implicitWidth: 100
- implicitHeight: 24
- color: Theme.qmlDesignerBackgroundColorDarker()
- border.color: Theme.qmlDesignerBorderColor()
- }
- }
-
- Controls.CheckBox {
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- id: trCheckbox
+ property bool isTranslated: colorLogic.backendValue.isTranslated
-
- property bool isTranslated: colorLogic.backendValue.isTranslated
- property bool backendValueValue: colorLogic.backendValue.value
-
- onIsTranslatedChanged: {
- checked = lineEdit.backendValue.isTranslated
- }
-
- onBackendValueValueChanged: {
- checked = lineEdit.backendValue.isTranslated
+ translationIndicator.onClicked: {
+ if (translationIndicator.checked) {
+ setTranslateExpression()
+ } else {
+ var textValue = lineEdit.text
+ lineEdit.backendValue.value = textValue
}
+ colorLogic.evaluate();
+ }
- onClicked: {
- if (trCheckbox.checked) {
- setTranslateExpression()
- } else {
- var textValue = lineEdit.text
- lineEdit.backendValue.value = textValue
- }
- colorLogic.evaluate();
- }
+ property variant backendValueValueInternal: backendValue.value
+ onBackendValueValueInternalChanged: {
+ lineEdit.translationIndicator.checked = lineEdit.backendValue.isTranslated
+ }
- function escapeString(string) {
- var str = string;
- str = str.replace(/\\/g, "\\\\");
- str.replace(/\"/g, "\\\"");
- str = str.replace(/\t/g, "\\t");
- str = str.replace(/\r/g, "\\r");
- str = str.replace(/\n/g, '\\n');
- return str;
- }
+ onIsTranslatedChanged: {
+ lineEdit.translationIndicator.checked = lineEdit.backendValue.isTranslated
+ }
- visible: showTranslateCheckBox
-
-
- style: CheckBoxStyle {
- spacing: 8
- indicator: Item {
- implicitWidth: 15
- implicitHeight: 15
- x: 7
- y: 1
- Rectangle {
- anchors.fill: parent
- border.color: Theme.qmlDesignerBorderColor()
- color: Theme.qmlDesignerBackgroundColorDarker()
- opacity: control.hovered || control.pressed ? 1 : 0.75
- }
- Image {
- x: 1
- y: 1
- width: 13
- height: 13
- source: "image://icons/tr"
- opacity: control.checked ? 1 : 0.3;
- }
- }
- }
+ function escapeString(string) {
+ var str = string;
+ str = str.replace(/\\/g, "\\\\");
+ str.replace(/\"/g, "\\\"");
+ str = str.replace(/\t/g, "\\t");
+ str = str.replace(/\r/g, "\\r");
+ str = str.replace(/\n/g, '\\n');
+ return str;
}
+
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
index b7c2664bdc..10b09287b7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
@@ -27,6 +27,7 @@ import QtQuick 2.1
import QtQuick.Controls 1.1 as Controls
import QtQuick.Layouts 1.0
import QtQuickDesignerTheme 1.0
+import StudioTheme 1.0 as StudioTheme
Item {
id: section
@@ -54,6 +55,7 @@ Item {
color: Theme.color(Theme.PanelTextColorLight)
x: 22
font.bold: true
+ font.pixelSize: StudioTheme.Values.myFontSize
}
Image {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml
new file mode 100644
index 0000000000..9cc787bd23
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Controls 2.5
+import StudioControls 1.0 as StudioControls
+import HelperWidgets 2.0
+import QtQuick.Controls.Private 1.0 // showing a ToolTip
+
+Item {
+ property color selectedColor
+ property bool clickable : true
+
+
+ width: 200
+ height: 40
+ enabled: clickable
+
+ function addColorToPalette(colorCode)
+ {
+ paletteModel.addItem(colorCode)
+ }
+
+ Component {
+ id: colorItemDelegate
+
+
+ Rectangle {
+ id: backgroundColor
+ property var favorite : isFavorite
+ height: 27
+ width: 27
+ border.color: (backgroundColor.favorite ? "#ffd700" : "#555555")
+ border.width: (backgroundColor.favorite ? 2 : 1)
+ color: "white"
+ radius: 0
+
+ Rectangle {
+ id: colorRectangle
+ width: 25
+ height: 25
+ anchors.centerIn: parent
+ color: colorCode
+
+ border.color: "black"
+ border.width: 1
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onClicked: {
+ if ((mouse.button === Qt.LeftButton) && clickable)
+ selectedColor = colorRectangle.color
+ }
+ onPressed: {
+ if (mouse.button === Qt.RightButton)
+ contextMenu.popup()
+ }
+ }
+ StudioControls.Menu {
+ id: contextMenu
+ StudioControls.MenuItem {
+ text: (backgroundColor.favorite
+ ? qsTr("Remove from Favorites")
+ : qsTr("Add to Favorites"))
+ onTriggered: {
+ paletteModel.toggleFavorite(index)
+ }
+ }
+ }
+ }
+ }
+
+ SimpleColorPaletteModel { id: paletteModel }
+ ListView {
+ id: colorPaletteView
+ model: paletteModel
+ delegate: colorItemDelegate
+ orientation: Qt.Horizontal
+ anchors.fill: parent
+ clip: true
+ interactive: false
+ spacing: 2
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml
index cc50509cc0..02665fc77a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml
@@ -24,42 +24,79 @@
****************************************************************************/
import QtQuick 2.1
-import QtQuick.Controls 1.1 as Controls
import QtQuick.Controls.Styles 1.1
+import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
-Controls.SpinBox {
- id: spinBox
+Item {
+ id: wrapper
- property color textColor: colorLogic.textColor
- property variant backendValue;
+ property alias decimals: spinBox.decimals
+ property alias hasSlider: spinBox.hasSlider
- implicitWidth: 74
+ property real minimumValue: 0.0
+ property real maximumValue: 99
+ property real stepSize: 1.0
- ExtendedFunctionButton {
- x: 4
- anchors.verticalCenter: parent.verticalCenter
- backendValue: spinBox.backendValue
- visible: spinBox.enabled
- }
+ property alias backendValue: spinBox.backendValue
+ property alias sliderIndicatorVisible: spinBox.sliderIndicatorVisible
- ColorLogic {
- id: colorLogic
- backendValue: spinBox.backendValue
- onValueFromBackendChanged: {
- spinBox.value = valueFromBackend;
- }
- }
+ width: 96
+ implicitHeight: spinBox.height
- property bool hasSlider: false
+ property bool __initialized: false
- height: hasSlider ? 32 : implicitHeight
+ Component.onCompleted: {
+ wrapper.__initialized = true
- onValueChanged: {
- if (backendValue.value !== value)
- backendValue.value = value;
+ convert("stepSize", stepSize)
+ convert("from", minimumValue)
+ convert("to", maximumValue)
}
- style: CustomSpinBoxStyle {
+ onStepSizeChanged: convert("stepSize", stepSize)
+ onMinimumValueChanged: convert("from", minimumValue)
+ onMaximumValueChanged: convert("to", maximumValue)
+
+ function convert(target, value) {
+ if (!wrapper.__initialized)
+ return
+ spinBox[target] = Math.round(value * spinBox.factor)
}
+ StudioControls.SpinBox {
+ id: spinBox
+
+ property real realValue: value / factor
+ property variant backendValue
+ property bool hasSlider: wrapper.sliderIndicatorVisible
+
+ from: minimumValue * factor
+ to: maximumValue * factor
+ width: wrapper.width
+
+ ExtendedFunctionLogic {
+ id: extFuncLogic
+ backendValue: spinBox.backendValue
+ }
+
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
+ ColorLogic {
+ id: colorLogic
+ backendValue: spinBox.backendValue
+ onValueFromBackendChanged: {
+ spinBox.value = valueFromBackend * spinBox.factor;
+ }
+ }
+
+ labelColor: edit ? StudioTheme.Values.themeTextColor : colorLogic.textColor
+
+ onCompressedValueModified: {
+ if (backendValue.value !== realValue)
+ backendValue.value = realValue;
+ }
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml
index 22c1923fad..b5e0ac0221 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/TabView.qml
@@ -27,6 +27,7 @@ import QtQuick 2.1
import QtQuick.Controls 1.0 as Controls
import QtQuick.Controls.Styles 1.1
import QtQuickDesignerTheme 1.0
+import StudioTheme 1.0 as StudioTheme
Controls.TabView {
id: root
@@ -42,6 +43,7 @@ Controls.TabView {
Text {
id: text
font.bold: true
+ font.pixelSize: StudioTheme.Values.myFontSize
anchors.centerIn: parent
anchors.verticalCenterOffset: -1
text: styleData.title
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml
index 9b51f1f4d3..df39546d93 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml
@@ -34,6 +34,8 @@ MouseArea {
onExited: Tooltip.hideText()
onCanceled: Tooltip.hideText()
+ onClicked: forceActiveFocus()
+
hoverEnabled: true
property string tooltip
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
index 0c89aa119e..d4b59a32d9 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
@@ -25,7 +25,7 @@
import QtQuick 2.1
import HelperWidgets 2.0
-import QtQuick.Controls 1.1 as Controls
+import StudioControls 1.0 as StudioControls
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
@@ -49,14 +49,16 @@ RowLayout {
backendValue: urlChooser.backendValue
}
- Controls.ComboBox {
+ StudioControls.ComboBox {
id: comboBox
- ExtendedFunctionButton {
- x: 2
- anchors.verticalCenter: parent.verticalCenter
- backendValue: urlChooser.backendValue
- visible: urlChooser.enabled
+ actionIndicator.icon.color: extFuncLogic.color
+ actionIndicator.icon.text: extFuncLogic.glyph
+ actionIndicator.onClicked: extFuncLogic.show()
+
+ ExtendedFunctionLogic {
+ id: extFuncLogic
+ backendValue: comboBox.backendValue
}
property bool isComplete: false
@@ -86,9 +88,6 @@ RowLayout {
Layout.fillWidth: true
editable: true
- style: CustomComboBoxStyle {
- textColor: urlChooser.textColor
- }
model: fileModel.fileModel
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
index 2bb87380c3..007fb08d49 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
@@ -9,6 +9,7 @@ CheckBox 2.0 CheckBox.qml
ColorButton 2.0 ColorButton.qml
ColorCheckButton 2.0 ColorCheckButton.qml
ColorEditor 2.0 ColorEditor.qml
+ColorLine 2.0 ColorLine.qml
ColorLogic 2.0 ColorLogic.qml
ComboBox 2.0 ComboBox.qml
CustomCheckBoxStyle 2.0 CustomCheckBoxStyle.qml
@@ -16,11 +17,14 @@ CustomComboBoxStyle 2.0 CustomComboBoxStyle.qml
CustomSpinBoxStyle 2.0 CustomSpinBoxStyle.qml
ExpandingSpacer 2.0 ExpandingSpacer.qml
ExtendedFunctionButton 2.0 ExtendedFunctionButton.qml
+ExtendedFunctionLogic 2.0 ExtendedFunctionLogic.qml
FlickableSection 2.0 FlickableSection.qml
FontComboBox 2.0 FontComboBox.qml
FontSection 2.0 FontSection.qml
FontStyleButtons 2.0 FontStyleButtons.qml
GradientLine 2.0 GradientLine.qml
+GradientPresetList 2.0 GradientPresetList.qml
+GradientPresetTabContent 2.0 GradientPresetTabContent.qml
GroupBox 2.0 GroupBox.qml
HueSlider 2.0 HueSlider.qml
IconLabel 2.0 IconLabel.qml
@@ -31,6 +35,7 @@ ScrollView 2.0 ScrollView.qml
SecondColumnLayout 2.0 SecondColumnLayout.qml
Section 2.0 Section.qml
SectionLayout 2.0 SectionLayout.qml
+SimpleColorPalette 2.0 SimpleColorPalette.qml
DoubleSpinBox 2.0 DoubleSpinBox.qml
SpinBox 2.0 SpinBox.qml
StandardTextSection 2.0 StandardTextSection.qml
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml
new file mode 100644
index 0000000000..4dec58d4b6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.AbstractButton {
+ id: myButton
+
+ property alias buttonIcon: buttonIcon.text
+ property alias iconColor: buttonIcon.color
+ property alias backgroundVisible: buttonBackground.visible
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+ height: StudioTheme.Values.height
+ width: StudioTheme.Values.height
+ z: myButton.checked ? 10 : 3
+ activeFocusOnTab: false
+
+ background: Rectangle {
+ id: buttonBackground
+ color: myButton.checked ? StudioTheme.Values.themeControlBackgroundChecked : StudioTheme.Values.themeControlBackground
+ border.color: myButton.checked ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+ }
+
+ indicator: Item {
+ x: 0
+ y: 0
+ implicitWidth: myButton.width
+ implicitHeight: myButton.height
+
+ T.Label {
+ id: buttonIcon
+ color: StudioTheme.Values.themeTextColor
+ font.family: StudioTheme.Constants.iconFont.family
+ font.pixelSize: StudioTheme.Values.myIconFontSize
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.fill: parent
+ renderType: Text.QtRendering
+ }
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myButton.enabled && !myButton.hovered && !myButton.pressed
+ && !myButton.checked
+ PropertyChanges {
+ target: buttonBackground
+ color: StudioTheme.Values.themeControlBackground
+ }
+ PropertyChanges {
+ target: myButton
+ z: 3
+ }
+ },
+ State {
+ name: "hovered"
+ when: myButton.hovered && !myButton.pressed
+ PropertyChanges {
+ target: buttonBackground
+ color: StudioTheme.Values.themeHoverHighlight
+ }
+ },
+ State {
+ name: "pressed"
+ when: myButton.hovered && myButton.pressed
+ PropertyChanges {
+ target: buttonBackground
+ color: StudioTheme.Values.themeControlBackgroundPressed
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ PropertyChanges {
+ target: myButton
+ z: 10
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myButton.enabled
+ PropertyChanges {
+ target: buttonBackground
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ PropertyChanges {
+ target: buttonIcon
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml
new file mode 100644
index 0000000000..c2a660228d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ActionIndicator.qml
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+Rectangle {
+ id: actionIndicator
+
+ property Item myControl
+
+ property alias icon: actionIndicatorIcon
+
+ property bool hover: false
+ property bool pressed: false
+
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ state: "default"
+
+ implicitWidth: StudioTheme.Values.height
+ implicitHeight: StudioTheme.Values.height
+
+ signal clicked
+
+ T.Label {
+ id: actionIndicatorIcon
+ anchors.fill: parent
+ text: StudioTheme.Constants.actionIcon
+ color: StudioTheme.Values.themeTextColor
+ font.family: StudioTheme.Constants.iconFont.family
+ font.pixelSize: StudioTheme.Values.myIconFontSize
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ MouseArea {
+ id: actionIndicatorMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onContainsMouseChanged: actionIndicator.hover = containsMouse
+ onClicked: actionIndicator.clicked()
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myControl.enabled && !actionIndicator.hover
+ && !actionIndicator.pressed && !myControl.hover
+ && !myControl.edit && !myControl.drag
+ PropertyChanges {
+ target: actionIndicator
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "hovered"
+ when: actionIndicator.hover && !actionIndicator.pressed
+ && !myControl.edit && !myControl.drag
+ PropertyChanges {
+ target: actionIndicatorIcon
+ scale: 1.2
+ }
+ },
+ State {
+ name: "globalHover"
+ when: myControl.hover && !actionIndicator.hover
+ && !actionIndicator.pressed && !myControl.edit
+ && !myControl.drag
+ PropertyChanges {
+ target: actionIndicator
+ color: StudioTheme.Values.themeHoverHighlight
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "edit"
+ when: myControl.edit
+ PropertyChanges {
+ target: actionIndicator
+ color: StudioTheme.Values.themeFocusEdit
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "drag"
+ when: myControl.drag
+ PropertyChanges {
+ target: actionIndicator
+ color: StudioTheme.Values.themeFocusDrag
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myControl.enabled
+ PropertyChanges {
+ target: actionIndicator
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ PropertyChanges {
+ target: actionIndicatorIcon
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml
new file mode 100644
index 0000000000..42d7b3eda8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Button.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+ButtonRow {
+ id: myButtonRow
+
+ property alias buttonIcon: myAbstractButton.buttonIcon
+ property alias iconColor: myAbstractButton.iconColor
+ property alias checkable: myAbstractButton.checkable
+ property alias checked: myAbstractButton.checked
+
+ signal onCheckedChanged()
+
+ AbstractButton {
+ id: myAbstractButton
+ onCheckedChanged: myButtonRow.onCheckedChanged()
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml
new file mode 100644
index 0000000000..1b233c590b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonGroup.qml
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+
+T.ButtonGroup {
+
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml
new file mode 100644
index 0000000000..059c38ad2c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+Row {
+ // TODO When using Item as root it won't react to outer layout
+ id: myButtonGroup
+
+ property alias actionIndicator: actionIndicator
+
+ property alias actionIndicatorVisible: actionIndicator.visible
+ property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __actionIndicatorHeight: StudioTheme.Values.height
+
+ ActionIndicator {
+ id: actionIndicator
+ myControl: myButtonGroup // TODO global hover issue. Can be solved with extra property in ActionIndicator
+ x: 0
+ y: 0
+ width: actionIndicator.visible ? __actionIndicatorWidth : 0
+ height: actionIndicator.visible ? __actionIndicatorHeight : 0
+ }
+
+ spacing: -StudioTheme.Values.border // TODO Which one is better? Spacing vs. layout function. ALso depends on root item
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml
new file mode 100644
index 0000000000..142421ee99
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.CheckBox {
+ id: myCheckBox
+
+ property alias actionIndicator: actionIndicator
+
+ property bool hover: myCheckBox.hovered
+ property bool edit: false
+
+ property alias actionIndicatorVisible: actionIndicator.visible
+ property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __actionIndicatorHeight: StudioTheme.Values.height
+
+ property alias labelVisible: checkBoxLabel.visible
+ property alias labelColor: checkBoxLabel.color
+
+ font.pixelSize: StudioTheme.Values.myFontSize
+
+ implicitWidth: Math.max(
+ implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding
+ + implicitIndicatorWidth + spacing + actionIndicator.width)
+ implicitHeight: Math.max(
+ implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: StudioTheme.Values.checkBoxSpacing
+ hoverEnabled: true
+ activeFocusOnTab: false
+
+ contentItem: T.Label {
+ id: checkBoxLabel
+ leftPadding: 0
+ rightPadding: 0
+ verticalAlignment: Text.AlignVCenter
+ text: myCheckBox.text
+ font: myCheckBox.font
+ color: StudioTheme.Values.themeTextColor
+ }
+
+ ActionIndicator {
+ id: actionIndicator
+ myControl: myCheckBox // TODO global hover issue. Can be solved with extra property in ActionIndicator
+
+ x: checkBoxLabel.visible ? checkBoxLabel.contentWidth + myCheckBox.spacing : 0
+ y: 0
+ width: actionIndicator.visible ? __actionIndicatorWidth : 0
+ height: actionIndicator.visible ? __actionIndicatorHeight : 0
+ }
+
+ indicator: Rectangle {
+ id: checkBoxBackground
+ x: actionIndicator.x + actionIndicator.width
+ - (actionIndicator.visible ? StudioTheme.Values.border : 0)
+ y: 0
+ z: 5
+ implicitWidth: StudioTheme.Values.height
+ implicitHeight: StudioTheme.Values.height
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+
+ T.Label {
+ id: checkBoxIcon
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ text: StudioTheme.Constants.tickIcon
+ visible: myCheckBox.checkState === Qt.Checked
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.sliderControlSizeMulti
+ font.family: StudioTheme.Constants.iconFont.family
+ }
+
+ /*
+ // Tristate only
+ Rectangle {
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: 16
+ height: 3
+ color: myCheckBox.palette.text
+ visible: myCheckBox.checkState === Qt.PartiallyChecked
+ }
+*/
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myCheckBox.enabled && !myCheckBox.hovered
+ && !myCheckBox.pressed
+ PropertyChanges {
+ target: checkBoxBackground
+ color: StudioTheme.Values.themeControlBackground
+ }
+ },
+ State {
+ name: "hovered"
+ when: myCheckBox.hovered && !myCheckBox.pressed
+ && !actionIndicator.hover
+ PropertyChanges {
+ target: checkBoxBackground
+ color: StudioTheme.Values.themeHoverHighlight
+ }
+ },
+ State {
+ name: "pressed"
+ when: myCheckBox.hovered && myCheckBox.pressed
+ PropertyChanges {
+ target: checkBoxBackground
+ color: StudioTheme.Values.themeFocusEdit
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myCheckBox.enabled
+ PropertyChanges {
+ target: checkBoxBackground
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ PropertyChanges {
+ target: checkBoxIcon
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ PropertyChanges {
+ target: checkBoxLabel
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml
new file mode 100644
index 0000000000..4c314b9101
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+Rectangle {
+ id: checkIndicator
+
+ property T.Control myControl
+ property T.Popup myPopup
+
+ property bool hover: false
+ property bool checked: false
+
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ state: "default"
+
+ Connections {
+ target: myPopup
+ onClosed: checkIndicator.checked = false
+ onOpened: checkIndicator.checked = true
+ }
+
+ MouseArea {
+ id: checkIndicatorMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onContainsMouseChanged: checkIndicator.hover = checkIndicatorMouseArea.containsMouse
+ onPressed: {
+ myControl.forceActiveFocus() // TODO
+ myPopup.opened ? myPopup.close() : myPopup.open()
+ }
+ }
+
+ T.Label {
+ id: checkIndicatorIcon
+ anchors.fill: parent
+ color: StudioTheme.Values.themeTextColor
+ text: StudioTheme.Constants.upDownSquare2
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: StudioTheme.Values.sliderControlSizeMulti
+ font.family: StudioTheme.Constants.iconFont.family
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myControl.enabled && !(checkIndicator.hover
+ || myControl.hover)
+ && !checkIndicator.checked && !myControl.edit
+ && !myControl.drag
+ PropertyChanges {
+ target: checkIndicator
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "hovered"
+ when: (checkIndicator.hover || myControl.hover)
+ && !checkIndicator.checked && !myControl.edit
+ && !myControl.drag
+ PropertyChanges {
+ target: checkIndicator
+ color: StudioTheme.Values.themeHoverHighlight
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "checked"
+ when: checkIndicator.checked
+ PropertyChanges {
+ target: checkIndicator
+ color: StudioTheme.Values.themeInteraction
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "edit"
+ when: myControl.edit && !checkIndicator.checked
+ && !(checkIndicator.hover && myControl.hover)
+ PropertyChanges {
+ target: checkIndicator
+ color: StudioTheme.Values.themeFocusEdit
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "drag"
+ when: myControl.drag && !checkIndicator.checked
+ && !(checkIndicator.hover && myControl.hover)
+ PropertyChanges {
+ target: checkIndicator
+ color: StudioTheme.Values.themeFocusDrag
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myControl.enabled
+ PropertyChanges {
+ target: checkIndicator
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ PropertyChanges {
+ target: checkIndicatorIcon
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml
new file mode 100644
index 0000000000..c61e7e0dbf
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.ComboBox {
+ id: myComboBox
+
+ property alias actionIndicator: actionIndicator
+ property alias labelColor: comboBoxInput.color
+
+ property bool hover: false // This property is used to indicate the global hover state
+ property bool edit: myComboBox.activeFocus
+
+ property alias actionIndicatorVisible: actionIndicator.visible
+ property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __actionIndicatorHeight: StudioTheme.Values.height
+
+ property string __lastAcceptedText: ""
+ signal compressedActivated
+
+ width: StudioTheme.Values.squareComponentWidth * 5
+ height: StudioTheme.Values.height
+
+ leftPadding: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0)
+ rightPadding: popupIndicator.width - StudioTheme.Values.border
+ font.pixelSize: StudioTheme.Values.myFontSize
+ wheelEnabled: false
+
+ onFocusChanged: {
+ if (!focus)
+ comboBoxPopup.close()
+ }
+
+ ActionIndicator {
+ id: actionIndicator
+ myControl: myComboBox
+ x: 0
+ y: 0
+ width: actionIndicator.visible ? __actionIndicatorWidth : 0
+ height: actionIndicator.visible ? __actionIndicatorHeight : 0
+ }
+
+ contentItem: ComboBoxInput {
+ id: comboBoxInput
+ myControl: myComboBox
+ text: myComboBox.editText
+ }
+
+ indicator: CheckIndicator {
+ id: popupIndicator
+ myControl: myComboBox
+ myPopup: myComboBox.popup
+ x: comboBoxInput.x + comboBoxInput.width - StudioTheme.Values.border
+ y: 0
+ width: StudioTheme.Values.squareComponentWidth
+ height: StudioTheme.Values.height
+ }
+
+ background: Rectangle {
+ id: comboBoxBackground
+ color: StudioTheme.Values.themeControlOutline
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+ width: myComboBox.width
+ height: myComboBox.height
+ }
+
+ // Set the initial value for __lastAcceptedText
+ Component.onCompleted: __lastAcceptedText = myComboBox.editText
+
+ onAccepted: {
+ if (myComboBox.editText != __lastAcceptedText) {
+ var pos = find(myComboBox.editText)
+ activated(pos)
+ }
+ __lastAcceptedText = myComboBox.editText
+ }
+
+ Timer {
+ id: myTimer
+ repeat: false
+ running: false
+ interval: 100
+ onTriggered: myComboBox.compressedActivated()
+ }
+
+ onActivated: myTimer.restart()
+
+ delegate: ItemDelegate {
+ id: myItemDelegate
+
+ width: comboBoxPopup.width - comboBoxPopup.leftPadding - comboBoxPopup.rightPadding
+ - (comboBoxPopupScrollBar.visible ? comboBoxPopupScrollBar.contentItem.implicitWidth
+ + 2 : 0) // TODO Magic number
+ height: StudioTheme.Values.height - 2 * StudioTheme.Values.border
+ padding: 0
+
+ contentItem: Text {
+ leftPadding: itemDelegateIconArea.width
+ text: modelData
+ color: StudioTheme.Values.themeTextColor
+ font: myComboBox.font
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ Item {
+ id: itemDelegateIconArea
+ width: myItemDelegate.height
+ height: myItemDelegate.height
+
+ T.Label {
+ id: itemDelegateIcon
+ text: StudioTheme.Constants.tickIcon
+ color: myItemDelegate.highlighted ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeInteraction
+ font.family: StudioTheme.Constants.iconFont.family
+ font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti
+ visible: myComboBox.currentIndex === index ? true : false
+ anchors.fill: parent
+ renderType: Text.NativeRendering
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+
+ highlighted: myComboBox.highlightedIndex === index
+
+ background: Rectangle {
+ id: itemDelegateBackground
+ x: 0
+ y: 0
+ width: myItemDelegate.width
+ height: myItemDelegate.height
+ color: myItemDelegate.highlighted ? StudioTheme.Values.themeInteraction : "transparent"
+ }
+ }
+
+ popup: T.Popup {
+ id: comboBoxPopup
+ x: comboBoxInput.x
+ y: myComboBox.height - StudioTheme.Values.border
+ width: comboBoxInput.width + popupIndicator.width - StudioTheme.Values.border
+ // TODO Setting the height on the popup solved the problem with the popup of height 0,
+ // but it has the problem that it sometimes extend over the border of the actual window
+ // and is then cut off.
+ height: Math.min(contentItem.implicitHeight + comboBoxPopup.topPadding
+ + comboBoxPopup.bottomPadding,
+ myComboBox.Window.height - topMargin - bottomMargin,
+ StudioTheme.Values.maxComboBoxPopupHeight)
+ padding: StudioTheme.Values.border
+ margins: 0 // If not defined margin will be -1
+ closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent
+
+ contentItem: ListView {
+ clip: true
+ implicitHeight: contentHeight
+ model: myComboBox.popup.visible ? myComboBox.delegateModel : null
+ currentIndex: myComboBox.highlightedIndex
+ boundsBehavior: Flickable.StopAtBounds
+ ScrollBar.vertical: ScrollBar {
+ id: comboBoxPopupScrollBar
+ }
+ }
+
+ background: Rectangle {
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeInteraction
+ border.width: StudioTheme.Values.border
+ }
+
+ enter: Transition {
+ }
+ exit: Transition {
+ }
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: !myComboBox.hover && !myComboBox.edit
+ PropertyChanges {
+ target: myComboBox
+ wheelEnabled: false
+ }
+ PropertyChanges {
+ target: comboBoxInput
+ selectByMouse: false
+ }
+ PropertyChanges {
+ target: comboBoxBackground
+ color: StudioTheme.Values.themeControlOutline
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "focus"
+ when: myComboBox.edit && !myComboBox.editable
+ PropertyChanges {
+ target: myComboBox
+ wheelEnabled: true
+ }
+ PropertyChanges {
+ target: comboBoxInput
+ focus: true
+ }
+ },
+ State {
+ name: "edit"
+ when: myComboBox.edit && myComboBox.editable
+ PropertyChanges {
+ target: myComboBox
+ wheelEnabled: true
+ }
+ PropertyChanges {
+ target: comboBoxInput
+ selectByMouse: true
+ }
+ PropertyChanges {
+ target: comboBoxBackground
+ color: StudioTheme.Values.themeInteraction
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ }
+ ]
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_Escape)
+ myComboBox.focus = false
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml
new file mode 100644
index 0000000000..2ea123f90d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+TextInput {
+ id: textInput
+
+ property T.Control myControl
+
+ property bool edit: textInput.activeFocus
+ property bool drag: false
+
+ z: 2
+ font: myControl.font
+ color: StudioTheme.Values.themeTextColor
+ selectionColor: StudioTheme.Values.themeTextSelectionColor
+ selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor
+
+ horizontalAlignment: Qt.AlignLeft
+ verticalAlignment: Qt.AlignVCenter
+ leftPadding: StudioTheme.Values.inputHorizontalPadding
+ rightPadding: StudioTheme.Values.inputHorizontalPadding
+
+ readOnly: !myControl.editable
+ validator: myControl.validator
+ inputMethodHints: myControl.inputMethodHints
+ selectByMouse: false
+ activeFocusOnPress: false
+ clip: true
+
+ Rectangle {
+ id: textInputArea
+ x: 0
+ y: 0
+ z: -1
+ width: textInput.width
+ height: StudioTheme.Values.height
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+ }
+
+ TapHandler {
+ id: tapHandler
+ acceptedDevices: PointerDevice.Mouse
+ enabled: true
+ onTapped: {
+ if (textInput.readOnly) {
+ if (myControl.popup.opened) {
+ myControl.popup.close()
+ } else {
+ myControl.popup.open()
+ myControl.forceActiveFocus()
+ }
+ } else {
+ textInput.forceActiveFocus()
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ enabled: true
+ hoverEnabled: true
+ propagateComposedEvents: true
+ acceptedButtons: Qt.LeftButton
+ cursorShape: Qt.PointingHandCursor
+ // Sets the global hover
+ onContainsMouseChanged: myControl.hover = containsMouse
+ onPressed: mouse.accepted = false
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myControl.enabled && !textInput.edit
+ && !mouseArea.containsMouse && !myControl.drag
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ PropertyChanges {
+ target: mouseArea
+ cursorShape: Qt.PointingHandCursor
+ }
+ },
+ State {
+ name: "hovered"
+ when: myControl.hover && !textInput.edit && !myControl.drag
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeHoverHighlight
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "focus"
+ when: textInput.edit && !myControl.editable
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeFocusEdit
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "edit"
+ when: textInput.edit && myControl.editable
+ extend: "focus"
+ PropertyChanges {
+ target: tapHandler
+ enabled: false
+ }
+ PropertyChanges {
+ target: mouseArea
+ cursorShape: Qt.IBeamCursor
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myControl.enabled
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ PropertyChanges {
+ target: textInput
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml
new file mode 100644
index 0000000000..8589d8129f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ContextMenu.qml
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Controls 2.12 as Controls2
+
+Menu {
+ id: contextMenu
+
+ property Item myTextEdit
+
+ Controls2.MenuItem {
+ text: "Undo"
+ enabled: myTextEdit.canUndo
+ onTriggered: myTextEdit.undo()
+ /* shortcut: StandardKey.Undo Shortcuts in QQC2 seem to override global shortcuts */
+ }
+ Controls2.MenuItem {
+ text: "Redo"
+ enabled: myTextEdit.canRedo
+ onTriggered: myTextEdit.redo()
+ /* shortcut: StandardKey.Redo Shortcuts in QQC2 seem to override global shortcuts */
+ }
+
+ MenuSeparator {
+ }
+
+ Controls2.MenuItem {
+ text: "Copy"
+ enabled: myTextEdit.selectedText !== ""
+ onTriggered: myTextEdit.copy()
+ /* shortcut: StandardKey.Copy Shortcuts in QQC2 seem to override global shortcuts */
+ }
+ Controls2.MenuItem {
+ text: "Cut"
+ enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly
+ onTriggered: myTextEdit.cut()
+ /* shortcut: StandardKey.Cut Shortcuts in QQC2 seem to override global shortcuts */
+ }
+ Controls2.MenuItem {
+ text: "Paste"
+ enabled: myTextEdit.canPaste
+ onTriggered: myTextEdit.paste()
+ /* shortcut: StandardKey.Paste Shortcuts in QQC2 seem to override global shortcuts */
+ }
+ Controls2.MenuItem {
+ text: "Delete"
+ enabled: myTextEdit.selectedText !== ""
+ onTriggered: myTextEdit.remove(myTextEdit.selectionStart,
+ myTextEdit.selectionEnd)
+ /* shortcut: StandardKey.Delete Shortcuts in QQC2 seem to override global shortcuts */
+ }
+ Controls2.MenuItem {
+ text: "Clear"
+ enabled: myTextEdit.text !== ""
+ onTriggered: myTextEdit.clear()
+ /* shortcut: StandardKey.DeleteCompleteLine Shortcuts in QQC2 seem to override global shortcuts */
+ }
+
+ MenuSeparator {
+ }
+
+ Controls2.MenuItem {
+ text: "Select All"
+ enabled: myTextEdit.text !== ""
+ && myTextEdit.selectedText !== myTextEdit.text
+ onTriggered: myTextEdit.selectAll()
+ /* shortcut: StandardKey.SelectAll Shortcuts in QQC2 seem to override global shortcuts */
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml
new file mode 100644
index 0000000000..9e48128c49
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ExpandingSpacer.qml
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+
+Item {
+ Layout.fillWidth: true
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml
new file mode 100644
index 0000000000..c2190c5d83
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ItemDelegate.qml
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+
+T.ItemDelegate {
+
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml
new file mode 100644
index 0000000000..01a86847fc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.Menu {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ font.family: StudioTheme.Constants.font.family
+ font.pixelSize: StudioTheme.Values.myFontSize
+
+ margins: 0
+ overlap: 1
+ padding: 0
+
+ closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnEscape
+
+ delegate: MenuItem {
+ }
+
+ contentItem: ListView {
+ model: control.contentModel
+ interactive: Window.window ? contentHeight > Window.window.height : false
+ clip: false
+ currentIndex: control.currentIndex
+ }
+
+ background: Rectangle {
+ implicitWidth: contentItem.childrenRect.width
+ implicitHeight: contentItem.childrenRect.height
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml
new file mode 100644
index 0000000000..ff3c139679
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuItem.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+import QtQuick.Controls 2.12
+
+T.MenuItem {
+ id: control
+
+ property int labelSpacing: StudioTheme.Values.contextMenuLabelSpacing
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(
+ implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ padding: 0
+ spacing: 0
+ horizontalPadding: StudioTheme.Values.contextMenuHorizontalPadding
+ action: Action {}
+
+ contentItem: Item {
+ id: menuItem
+
+ width: control.menu.width
+ height: StudioTheme.Values.height
+
+ Text {
+ id: textLabel
+ text: control.text
+ font: control.font
+ color: control.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Text {
+ id: shortcutLabel
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ text: shortcut.nativeText
+ font: control.font
+ color: textLabel.color
+
+ Shortcut {
+ id: shortcut
+ property int shortcutWorkaround: control.action.shortcut ? control.action.shortcut : 0
+ sequence: shortcutWorkaround
+ }
+ }
+ }
+
+ background: Rectangle {
+ implicitWidth: textLabel.implicitWidth + control.labelSpacing + shortcutLabel.implicitWidth
+ + control.leftPadding + control.rightPadding // TODO
+ implicitHeight: StudioTheme.Values.height
+ x: StudioTheme.Values.border
+ y: StudioTheme.Values.border
+ width: control.width - (StudioTheme.Values.border * 2)
+ height: control.height - (StudioTheme.Values.border * 2)
+ color: control.down ? control.palette.midlight : control.highlighted ? StudioTheme.Values.themeInteraction : "transparent"
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml
new file mode 100644
index 0000000000..4e226f5c58
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/MenuSeparator.qml
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.MenuSeparator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 0
+ verticalPadding: padding
+
+ contentItem: Rectangle {
+ implicitWidth: 10
+ implicitHeight: StudioTheme.Values.border
+ color: StudioTheme.Values.themeControlOutline
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml
new file mode 100644
index 0000000000..886e92206b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollBar.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.ScrollBar {
+ id: control
+
+ // This needs to be set, when using T.ScrollBar
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ active: true
+ interactive: true
+ visible: control.size < 1.0 || T.ScrollBar.AlwaysOn
+
+ snapMode: T.ScrollBar.SnapAlways // TODO
+ policy: T.ScrollBar.AsNeeded
+
+ padding: 1 // TODO 0
+ size: 1.0
+ position: 1.0
+ //orientation: Qt.Vertical
+
+ contentItem: Rectangle {
+ id: controlHandle
+ implicitWidth: 4
+ implicitHeight: 4
+ radius: width / 2 // TODO 0
+ color: StudioTheme.Values.themeScrollBarHandle
+ }
+
+ background: Rectangle {
+ id: controlTrack
+ color: StudioTheme.Values.themeScrollBarTrack
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml
new file mode 100644
index 0000000000..bf1b3937b9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ScrollView.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.ScrollView {
+ id: control
+
+ property alias horizontalThickness: horizontalScrollBar.height
+ property alias verticalThickness: verticalScrollBar.width
+ property bool bothVisible: verticalScrollBar.visible
+ && horizontalScrollBar.visible
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ ScrollBar.vertical: ScrollBar {
+ id: verticalScrollBar
+ parent: control
+ x: control.width - width - StudioTheme.Values.border
+ y: StudioTheme.Values.border
+ height: control.availableHeight - 2 * StudioTheme.Values.border
+ - (bothVisible ? horizontalThickness : 0)
+ active: control.ScrollBar.horizontal.active
+ }
+
+ ScrollBar.horizontal: ScrollBar {
+ id: horizontalScrollBar
+ parent: control
+ x: StudioTheme.Values.border
+ y: control.height - height - StudioTheme.Values.border
+ width: control.availableWidth - 2 * StudioTheme.Values.border
+ - (bothVisible ? verticalThickness : 0)
+ active: control.ScrollBar.vertical.active
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml
new file mode 100644
index 0000000000..d5c917f5ce
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SecondColumnLayout.qml
@@ -0,0 +1,32 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+
+RowLayout {
+ Layout.fillWidth: true
+ spacing: 4
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml
new file mode 100644
index 0000000000..98a163a322
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import StudioTheme 1.0 as StudioTheme
+
+Item {
+ id: section
+ property alias caption: label.text
+ property int leftPadding: 8
+ property int topPadding: 4
+ property int rightPadding: 0
+
+ property int animationDuration: 0
+
+ property bool expanded: true
+
+ clip: true
+
+ Rectangle {
+ id: header
+ height: StudioTheme.Values.height
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ color: StudioTheme.Values.themeControlBackground
+
+ SectionLabel {
+ id: label
+ anchors.verticalCenter: parent.verticalCenter
+ color: StudioTheme.Values.themeTextColor
+ x: 22
+ //font.bold: true
+ font.pixelSize: StudioTheme.Values.myFontSize
+ // TODO font size?
+ }
+
+ SectionLabel {
+ id: arrow
+ width: StudioTheme.Values.spinControlIconSizeMulti
+ height: StudioTheme.Values.spinControlIconSizeMulti
+ text: StudioTheme.Constants.upDownSquare2
+ color: StudioTheme.Values.themeTextColor
+ renderType: Text.NativeRendering
+ anchors.left: parent.left
+ anchors.leftMargin: 4
+ anchors.verticalCenter: parent.verticalCenter
+ font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti
+ font.family: StudioTheme.Constants.iconFont.family
+ Behavior on rotation {
+ NumberAnimation {
+ easing.type: Easing.OutCubic
+ duration: animationDuration
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ section.animationDuration = 120
+ section.expanded = !section.expanded
+ if (!section.expanded) // TODO
+ section.forceActiveFocus()
+ }
+ }
+ }
+
+ default property alias __content: row.children
+
+ readonly property alias contentItem: row
+
+ implicitHeight: Math.round(row.height + header.height)
+
+ Row {
+ id: row
+ anchors.left: parent.left
+ anchors.leftMargin: leftPadding
+ anchors.right: parent.right
+ anchors.rightMargin: rightPadding
+ anchors.top: header.bottom
+ anchors.topMargin: topPadding
+ }
+
+ Behavior on implicitHeight {
+ NumberAnimation {
+ easing.type: Easing.OutCubic
+ duration: animationDuration
+ }
+ }
+
+ states: [
+ State {
+ name: "Collapsed"
+ when: !section.expanded
+ PropertyChanges {
+ target: section
+ implicitHeight: header.height
+ }
+ PropertyChanges {
+ target: arrow
+ rotation: -90
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml
new file mode 100644
index 0000000000..73fec21ce0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLabel.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.Label {
+ id: label
+
+ //property alias tooltip: toolTipArea.tooltip
+ // workaround because PictureSpecifics.qml still use this
+ //property alias toolTip: toolTipArea.tooltip
+
+ width: Math.max(Math.min(240, parent.width - 220), 80)
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.myFontSize // TODO
+ elide: Text.ElideRight
+
+ Layout.preferredWidth: width
+ Layout.minimumWidth: width
+ Layout.maximumWidth: width
+/*
+ ToolTipArea {
+ id: toolTipArea
+ anchors.fill: parent
+ tooltip: label.text
+ }
+*/
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml
new file mode 100644
index 0000000000..22054feebb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SectionLayout.qml
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+
+GridLayout {
+ columns: 2
+ columnSpacing: 12
+ rowSpacing: 4
+ width: parent.width - 16
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml
new file mode 100644
index 0000000000..7e111b6851
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Shapes 1.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.Slider {
+ id: slider
+
+ property int decimals: 0
+ property bool labels: true
+ property bool tickMarks: false
+ property real tickMarkStepSize: 0.0 // StepSize bug QTBUG-76136
+ property real tickMarkWidth: 1.0
+ property real tickMarkHeight: 4.0
+ readonly property int tickMarkCount: tickMarkStepSize
+ !== 0.0 ? (to - from) / tickMarkStepSize + 1 : 0
+ readonly property real tickMarkSpacing: tickMarkCount
+ !== 0 ? (sliderTrack.width - tickMarkWidth
+ * tickMarkCount) / (tickMarkCount - 1) : 0.0
+
+ property string __activeColor: StudioTheme.Values.themeSliderActiveTrack
+ property string __inactiveColor: StudioTheme.Values.themeSliderInactiveTrack
+
+ property bool hover: false // This property is used to indicate the global hover state
+ property bool edit: slider.activeFocus
+
+ property alias actionIndicatorVisible: actionIndicator.visible
+ property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __actionIndicatorHeight: StudioTheme.Values.height
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitHandleWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitHandleHeight + topPadding + bottomPadding,
+ StudioTheme.Values.height)
+ padding: 0
+ leftPadding: actionIndicator.width
+ - (actionIndicatorVisible ? StudioTheme.Values.border
+ - StudioTheme.Values.sliderPadding : 0)
+
+ wheelEnabled: false
+
+ ActionIndicator {
+ id: actionIndicator
+ myControl: slider
+ x: 0
+ y: 0
+ width: actionIndicator.visible ? __actionIndicatorWidth : 0
+ height: actionIndicator.visible ? __actionIndicatorHeight : 0
+ }
+
+ handle: Rectangle {
+ id: sliderHandle
+ x: slider.leftPadding + (slider.visualPosition * slider.availableWidth)
+ - sliderHandle.width / 2
+ y: slider.topPadding + slider.availableHeight / 2 - sliderHandle.height / 2
+ z: 20
+ implicitWidth: StudioTheme.Values.sliderHandleWidth
+ implicitHeight: StudioTheme.Values.sliderHandleHeight
+ color: StudioTheme.Values.themeSliderHandle
+
+ Shape {
+ id: sliderHandleLabelPointer
+
+ property real __width: StudioTheme.Values.sliderPointerWidth
+ property real __height: StudioTheme.Values.sliderPointerHeight
+ property bool antiAlias: true
+
+ layer.enabled: antiAlias
+ layer.smooth: antiAlias
+ layer.textureSize: Qt.size(width * 2, height * 2)
+
+ implicitWidth: __width
+ implicitHeight: __height
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: sliderHandleLabelBackground.bottom
+
+ ShapePath {
+ id: sliderHandleLabelPointerPath
+ strokeColor: "transparent"
+ strokeWidth: 0
+ fillColor: StudioTheme.Values.themeInteraction
+
+ startX: 0
+ startY: 0
+
+ PathLine {
+ x: sliderHandleLabelPointer.__width
+ y: 0
+ }
+ PathLine {
+ x: sliderHandleLabelPointer.__width / 2
+ y: sliderHandleLabelPointer.__height
+ }
+ }
+ }
+
+ Rectangle {
+ id: sliderHandleLabelBackground
+ x: -(sliderHandleLabelBackground.width / 2) + (sliderHandle.width / 2)
+ width: makeEven(
+ sliderHandleLabel.width + StudioTheme.Values.inputHorizontalPadding)
+ height: sliderHandleLabel.height
+ anchors.bottom: parent.top
+ anchors.bottomMargin: StudioTheme.Values.sliderMargin
+ color: StudioTheme.Values.themeInteraction
+
+ Text {
+ id: sliderHandleLabel
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ text: Number.parseFloat(slider.value).toFixed(slider.decimals)
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.sliderFontSize
+ }
+ }
+ }
+
+ function makeEven(value) {
+ var v = Math.round(value)
+ return (v % 2 === 0) ? v : v + 1
+ }
+
+ background: Rectangle {
+ id: sliderTrack
+ x: slider.leftPadding
+ y: slider.topPadding + slider.availableHeight / 2 - height / 2
+ width: slider.availableWidth
+ height: StudioTheme.Values.sliderTrackHeight
+ color: __inactiveColor
+
+ Rectangle {
+ width: slider.visualPosition * parent.width
+ height: parent.height
+ color: __activeColor
+ }
+ }
+
+ Item {
+ id: tickmarkBounds
+ x: sliderTrack.x
+ y: sliderTrack.y
+
+ Text {
+ id: tickmarkFromLabel
+ x: 0
+ y: StudioTheme.Values.sliderPadding
+ text: Number.parseFloat(slider.from).toFixed(slider.decimals)
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.sliderFontSize
+ visible: slider.labels
+ }
+
+ Text {
+ id: tickmarkToLabel
+ x: slider.availableWidth - width
+ y: StudioTheme.Values.sliderPadding
+ text: Number.parseFloat(slider.to).toFixed(slider.decimals)
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.sliderFontSize
+ visible: slider.labels
+ }
+
+ Row {
+ id: tickmarkRow
+ spacing: tickMarkSpacing
+ visible: slider.tickMarks
+
+ Repeater {
+ id: tickmarkRepeater
+ model: tickMarkCount
+ delegate: Rectangle {
+ implicitWidth: tickMarkWidth
+ implicitHeight: StudioTheme.Values.sliderTrackHeight
+ color: x < (slider.visualPosition
+ * slider.availableWidth) ? __inactiveColor : __activeColor
+ }
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ x: actionIndicator.width
+ y: 0
+ width: slider.width - actionIndicator.width
+ height: slider.height
+ enabled: true
+ hoverEnabled: true
+ propagateComposedEvents: true
+ acceptedButtons: Qt.LeftButton
+ cursorShape: Qt.PointingHandCursor
+ // Sets the global hover
+ onContainsMouseChanged: slider.hover = containsMouse
+ onPressed: mouse.accepted = false
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: slider.enabled && !slider.hover && !slider.edit
+ PropertyChanges {
+ target: slider
+ wheelEnabled: false
+ }
+ },
+ State {
+ name: "hovered"
+ when: slider.enabled && slider.hover && !slider.edit
+ PropertyChanges {
+ target: slider
+ __activeColor: StudioTheme.Values.themeSliderActiveTrackHover
+ __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackHover
+ }
+ PropertyChanges {
+ target: sliderHandle
+ color: StudioTheme.Values.themeSliderHandleHover
+ }
+ },
+ State {
+ name: "focus"
+ when: slider.enabled && slider.edit
+ PropertyChanges {
+ target: slider
+ wheelEnabled: true
+ __activeColor: StudioTheme.Values.themeSliderActiveTrackFocus
+ __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackFocus
+ }
+ PropertyChanges {
+ target: sliderHandle
+ color: StudioTheme.Values.themeSliderHandleFocus
+ }
+ },
+ State {
+ name: "disabled"
+ when: !slider.enabled
+ PropertyChanges {
+ target: tickmarkFromLabel
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ PropertyChanges {
+ target: tickmarkToLabel
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ PropertyChanges {
+ target: sliderHandleLabel
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ PropertyChanges {
+ target: slider
+ __activeColor: StudioTheme.Values.themeControlBackgroundDisabled
+ __inactiveColor: StudioTheme.Values.themeControlBackgroundDisabled
+ }
+ PropertyChanges {
+ target: sliderHandleLabelBackground
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ }
+ PropertyChanges {
+ target: sliderHandleLabelPointerPath
+ fillColor: StudioTheme.Values.themeControlBackgroundDisabled
+ }
+ PropertyChanges {
+ target: sliderHandle
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml
new file mode 100644
index 0000000000..beb6da4a8f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SliderPopup.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.Popup {
+ id: sliderPopup
+
+ property T.Control myControl
+
+ dim: false
+ closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent
+
+ background: Rectangle {
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeInteraction
+ }
+
+ contentItem: T.Slider {
+ id: slider
+ anchors.fill: parent
+
+ bottomPadding: 0
+ topPadding: 0
+ rightPadding: 3
+ leftPadding: 3
+
+ from: myControl.from
+ value: myControl.value
+ to: myControl.to
+
+ focusPolicy: Qt.NoFocus
+
+ handle: Rectangle {
+ x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
+ y: slider.topPadding + slider.availableHeight / 2 - height / 2
+ width: StudioTheme.Values.sliderHandleWidth
+ height: StudioTheme.Values.sliderHandleHeight
+ radius: 0
+ color: slider.pressed ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline
+ }
+
+ background: Rectangle {
+ x: slider.leftPadding
+ y: slider.topPadding + slider.availableHeight / 2 - height / 2
+ width: slider.availableWidth
+ height: StudioTheme.Values.sliderTrackHeight
+ radius: 0
+ color: StudioTheme.Values.themeSliderInactiveTrack
+
+ Rectangle {
+ width: slider.visualPosition * parent.width
+ height: parent.height
+ color: StudioTheme.Values.themeSliderActiveTrack
+ radius: 0
+ }
+ }
+
+ onMoved: {
+ myControl.value = value
+ myControl.valueModified()
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml
new file mode 100644
index 0000000000..e10a334bd6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml
@@ -0,0 +1,338 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.SpinBox {
+ id: mySpinBox
+
+ property alias labelColor: spinBoxInput.color
+ property alias actionIndicator: actionIndicator
+
+ property int decimals: 0
+ property int factor: Math.pow(10, decimals)
+
+ property real defaultStepSize: 1
+ property real minStepSize: 1
+ property real maxStepSize: 10
+
+ property bool edit: spinBoxInput.activeFocus
+ property bool hover: false // This property is used to indicate the global hover state
+ property bool drag: false
+
+ property alias actionIndicatorVisible: actionIndicator.visible
+ property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __actionIndicatorHeight: StudioTheme.Values.height
+
+ property bool spinBoxIndicatorVisible: true
+ property real __spinBoxIndicatorWidth: StudioTheme.Values.smallRectWidth - 2
+ * StudioTheme.Values.border
+ property real __spinBoxIndicatorHeight: StudioTheme.Values.height / 2
+ - StudioTheme.Values.border
+
+ property alias sliderIndicatorVisible: sliderIndicator.visible
+ property real __sliderIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __sliderIndicatorHeight: StudioTheme.Values.height
+
+ signal compressedValueModified
+
+ // Use custom wheel handling due to bugs
+ property bool __wheelEnabled: false
+ wheelEnabled: false
+
+ width: StudioTheme.Values.squareComponentWidth * 5
+ height: StudioTheme.Values.height
+
+ leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width
+ - (spinBoxIndicatorVisible ? 0 : StudioTheme.Values.border)
+ rightPadding: sliderIndicator.width - (sliderIndicatorVisible ? StudioTheme.Values.border : 0)
+
+ font.pixelSize: StudioTheme.Values.myFontSize
+ editable: true
+ validator: mySpinBox.decimals ? doubleValidator : intValidator
+
+ DoubleValidator {
+ id: doubleValidator
+ locale: mySpinBox.locale.name
+ notation: DoubleValidator.StandardNotation
+ decimals: mySpinBox.decimals
+ bottom: Math.min(mySpinBox.from, mySpinBox.to) / factor
+ top: Math.max(mySpinBox.from, mySpinBox.to) / factor
+ }
+
+ IntValidator {
+ id: intValidator
+ locale: mySpinBox.locale.name
+ bottom: Math.min(mySpinBox.from, mySpinBox.to)
+ top: Math.max(mySpinBox.from, mySpinBox.to)
+ }
+
+ ActionIndicator {
+ id: actionIndicator
+ myControl: mySpinBox
+
+ x: 0
+ y: 0
+ width: actionIndicator.visible ? __actionIndicatorWidth : 0
+ height: actionIndicator.visible ? __actionIndicatorHeight : 0
+ }
+
+ up.indicator: SpinBoxIndicator {
+ id: spinBoxIndicatorUp
+ myControl: mySpinBox
+
+ visible: spinBoxIndicatorVisible
+ //hover: mySpinBox.up.hovered // TODO QTBUG-74688
+ pressed: mySpinBox.up.pressed
+ iconFlip: -1
+
+ x: actionIndicator.width + (actionIndicator.visible ? 0 : StudioTheme.Values.border)
+ y: StudioTheme.Values.border
+ width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0
+ height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0
+ }
+
+ down.indicator: SpinBoxIndicator {
+ id: spinBoxIndicatorDown
+ myControl: mySpinBox
+
+ visible: spinBoxIndicatorVisible
+ //hover: mySpinBox.down.hovered // TODO QTBUG-74688
+ pressed: mySpinBox.down.pressed
+
+ x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border)
+ y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height
+ width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0
+ height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0
+ }
+
+ contentItem: SpinBoxInput {
+ id: spinBoxInput
+ myControl: mySpinBox
+ }
+
+ background: Rectangle {
+ id: spinBoxBackground
+ color: StudioTheme.Values.themeControlOutline
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+ width: mySpinBox.width
+ height: mySpinBox.height
+ }
+
+ CheckIndicator {
+ id: sliderIndicator
+ myControl: mySpinBox
+ myPopup: sliderPopup
+
+ x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border
+ width: sliderIndicator.visible ? __sliderIndicatorWidth : 0
+ height: sliderIndicator.visible ? __sliderIndicatorHeight : 0
+ visible: false // reasonable default
+ }
+
+ SliderPopup {
+ id: sliderPopup
+ myControl: mySpinBox
+
+ x: spinBoxInput.x
+ y: StudioTheme.Values.height - StudioTheme.Values.border
+ width: spinBoxInput.width + sliderIndicator.width - StudioTheme.Values.border
+ height: StudioTheme.Values.sliderHeight
+
+ enter: Transition {
+ }
+ exit: Transition {
+ }
+ }
+
+ textFromValue: function (value, locale) {
+ return Number(value / factor).toLocaleString(locale, 'f',
+ mySpinBox.decimals)
+ }
+
+ valueFromText: function (text, locale) {
+ return Number.fromLocaleString(locale, text) * factor
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: mySpinBox.enabled && !mySpinBox.hover
+ && !mySpinBox.edit && !mySpinBox.drag
+ PropertyChanges {
+ target: mySpinBox
+ __wheelEnabled: false
+ }
+ PropertyChanges {
+ target: spinBoxInput
+ selectByMouse: false
+ }
+ PropertyChanges {
+ target: spinBoxBackground
+ color: StudioTheme.Values.themeControlOutline
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "edit"
+ when: mySpinBox.edit
+ PropertyChanges {
+ target: mySpinBox
+ __wheelEnabled: true
+ }
+ PropertyChanges {
+ target: spinBoxInput
+ selectByMouse: true
+ }
+ PropertyChanges {
+ target: spinBoxBackground
+ color: StudioTheme.Values.themeInteraction
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "drag"
+ when: mySpinBox.drag
+ PropertyChanges {
+ target: spinBoxBackground
+ color: StudioTheme.Values.themeInteraction
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "disabled"
+ when: !mySpinBox.enabled
+ PropertyChanges {
+ target: spinBoxBackground
+ color: StudioTheme.Values.themeControlOutlineDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ }
+ ]
+
+ onActiveFocusChanged: {
+ if (mySpinBox.activeFocus)
+ // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason)
+ spinBoxInput.selectAll()
+
+ if (sliderPopup.opened && !mySpinBox.activeFocus)
+ sliderPopup.close()
+ }
+
+ onFocusChanged: {
+ // FIX: This is a temporary fix for QTBUG-74239
+ var currValue = mySpinBox.value
+
+ if (!spinBoxInput.acceptableInput)
+ mySpinBox.value = clamp(valueFromText(spinBoxInput.text,
+ mySpinBox.locale),
+ mySpinBox.validator.bottom * factor,
+ mySpinBox.validator.top * factor)
+ else
+ mySpinBox.value = valueFromText(spinBoxInput.text, mySpinBox.locale)
+
+ if (spinBoxInput.text !== mySpinBox.displayText)
+ spinBoxInput.text = mySpinBox.displayText
+
+ if (mySpinBox.value !== currValue)
+ mySpinBox.valueModified()
+ }
+
+ onDisplayTextChanged: {
+ spinBoxInput.text = mySpinBox.displayText
+ }
+
+ Timer {
+ id: myTimer
+ repeat: false
+ running: false
+ interval: 100
+ onTriggered: mySpinBox.compressedValueModified()
+ }
+
+ onValueModified: myTimer.restart()
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) {
+ event.accepted = true
+
+ mySpinBox.stepSize = defaultStepSize
+
+ if (event.modifiers & Qt.ControlModifier)
+ mySpinBox.stepSize = minStepSize
+
+ if (event.modifiers & Qt.ShiftModifier)
+ mySpinBox.stepSize = maxStepSize
+
+ var val = mySpinBox.valueFromText(spinBoxInput.text,
+ mySpinBox.locale)
+ if (mySpinBox.value !== val)
+ mySpinBox.value = val
+
+ var curValue = mySpinBox.value
+
+ if (event.key === Qt.Key_Up)
+ mySpinBox.increase()
+ else
+ mySpinBox.decrease()
+
+ if (curValue !== mySpinBox.value)
+ mySpinBox.valueModified()
+ }
+
+ if (event.key === Qt.Key_Escape)
+ mySpinBox.focus = false
+
+ // FIX: This is a temporary fix for QTBUG-74239
+ if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
+ var currValue = mySpinBox.value
+
+ if (!spinBoxInput.spinBoxInput)
+ mySpinBox.value = clamp(valueFromText(spinBoxInput.text,
+ mySpinBox.locale),
+ mySpinBox.validator.bottom * factor,
+ mySpinBox.validator.top * factor)
+ else
+ mySpinBox.value = valueFromText(spinBoxInput.text,
+ mySpinBox.locale)
+
+ if (spinBoxInput.text !== mySpinBox.displayText)
+ spinBoxInput.text = mySpinBox.displayText
+
+ if (mySpinBox.value !== currValue)
+ mySpinBox.valueModified()
+ }
+ }
+
+ function clamp(v, lo, hi) {
+ if (v < lo || v > hi)
+ return Math.min(Math.max(lo, v), hi)
+
+ return v
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml
new file mode 100644
index 0000000000..f75b8b47fd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+Rectangle {
+ id: spinBoxIndicator
+
+ property T.Control myControl
+
+ property bool hover: false
+ property bool pressed: false
+
+ property alias iconFlip: spinBoxIndicatorIconScale.yScale
+
+ color: StudioTheme.Values.themeControlBackground
+ border.width: 0
+
+ // This MouseArea is a workaround to avoid some hover state related bugs
+ // when using the actual signal 'up.hovered'. QTBUG-74688
+ MouseArea {
+ id: spinBoxIndicatorMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onContainsMouseChanged: spinBoxIndicator.hover = containsMouse
+ onPressed: {
+ myControl.forceActiveFocus()
+ mouse.accepted = false
+ }
+ }
+
+ T.Label {
+ id: spinBoxIndicatorIcon
+ text: StudioTheme.Constants.upDownSquare2
+ color: StudioTheme.Values.themeTextColor
+ renderType: Text.NativeRendering
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti
+ font.family: StudioTheme.Constants.iconFont.family
+ anchors.fill: parent
+ transform: Scale {
+ id: spinBoxIndicatorIconScale
+ origin.x: 0
+ origin.y: spinBoxIndicatorIcon.height / 2
+ yScale: 1
+ }
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myControl.enabled && !(spinBoxIndicator.hover
+ || myControl.hover)
+ && !spinBoxIndicator.pressed && !myControl.edit
+ && !myControl.drag
+ PropertyChanges {
+ target: spinBoxIndicator
+ color: StudioTheme.Values.themeControlBackground
+ }
+ },
+ State {
+ name: "hovered"
+ when: (spinBoxIndicator.hover || myControl.hover)
+ && !spinBoxIndicator.pressed && !myControl.edit
+ && !myControl.drag
+ PropertyChanges {
+ target: spinBoxIndicator
+ color: StudioTheme.Values.themeHoverHighlight
+ }
+ },
+ State {
+ name: "pressed"
+ when: spinBoxIndicator.pressed
+ PropertyChanges {
+ target: spinBoxIndicator
+ color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "edit"
+ when: myControl.edit
+ PropertyChanges {
+ target: spinBoxIndicator
+ color: StudioTheme.Values.themeFocusEdit
+ }
+ },
+ State {
+ name: "drag"
+ when: myControl.drag
+ PropertyChanges {
+ target: spinBoxIndicator
+ color: StudioTheme.Values.themeFocusDrag
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myControl.enabled
+ PropertyChanges {
+ target: spinBoxIndicator
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ }
+ PropertyChanges {
+ target: spinBoxIndicatorIcon
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml
new file mode 100644
index 0000000000..e2f718176e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+TextInput {
+ id: textInput
+
+ property T.Control myControl
+
+ property bool edit: textInput.activeFocus
+ property bool drag: false
+
+ z: 2
+ font: myControl.font
+ color: StudioTheme.Values.themeTextColor
+ selectionColor: StudioTheme.Values.themeTextSelectionColor
+ selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor
+
+ horizontalAlignment: Qt.AlignRight
+ verticalAlignment: Qt.AlignVCenter
+ leftPadding: StudioTheme.Values.inputHorizontalPadding
+ rightPadding: StudioTheme.Values.inputHorizontalPadding
+
+ readOnly: !myControl.editable
+ validator: myControl.validator
+ inputMethodHints: myControl.inputMethodHints
+ selectByMouse: false
+ activeFocusOnPress: false
+ clip: true
+
+ // TextInput focus needs to be set to activeFocus whenever it changes,
+ // otherwise TextInput will get activeFocus whenever the parent SpinBox gets
+ // activeFocus. This will lead to weird side effects.
+ onActiveFocusChanged: textInput.focus = activeFocus
+
+ Rectangle {
+ id: textInputArea
+
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+
+ x: 0
+ y: 0
+ z: -1
+ width: textInput.width
+ height: StudioTheme.Values.height
+ }
+
+ DragHandler {
+ id: dragHandler
+ target: null
+ acceptedDevices: PointerDevice.Mouse
+ enabled: true
+
+ property int initialValue: 0
+
+ onActiveChanged: {
+ if (active) {
+ initialValue = myControl.value
+ mouseArea.cursorShape = Qt.ClosedHandCursor
+ myControl.drag = true
+ } else {
+ mouseArea.cursorShape = Qt.PointingHandCursor
+ myControl.drag = false
+ }
+ }
+ onTranslationChanged: {
+ var curValue = myControl.value
+ myControl.value = initialValue + translation.x
+
+ if (curValue !== myControl.value)
+ myControl.valueModified()
+ }
+ }
+
+ TapHandler {
+ id: tapHandler
+ acceptedDevices: PointerDevice.Mouse
+ enabled: true
+ onTapped: {
+ textInput.forceActiveFocus()
+ textInput.deselect() // QTBUG-75862
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ enabled: true
+ hoverEnabled: true
+ propagateComposedEvents: true
+ acceptedButtons: Qt.LeftButton
+ cursorShape: Qt.PointingHandCursor
+ // Sets the global hover
+ onContainsMouseChanged: myControl.hover = containsMouse
+ onPressed: mouse.accepted = false
+ onWheel: {
+ if (!myControl.__wheelEnabled)
+ return
+
+ var val = myControl.valueFromText(textInput.text, myControl.locale)
+ if (myControl.value !== val)
+ myControl.value = val
+
+ var curValue = myControl.value
+ myControl.value += wheel.angleDelta.y / 120
+
+ if (curValue !== myControl.value)
+ myControl.valueModified()
+ }
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myControl.enabled && !textInput.edit
+ && !mouseArea.containsMouse && !myControl.drag
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ PropertyChanges {
+ target: dragHandler
+ enabled: true
+ }
+ PropertyChanges {
+ target: tapHandler
+ enabled: true
+ }
+ PropertyChanges {
+ target: mouseArea
+ cursorShape: Qt.PointingHandCursor
+ }
+ },
+ State {
+ name: "hovered"
+ when: myControl.hover && !textInput.edit && !myControl.drag
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeHoverHighlight
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "edit"
+ when: textInput.edit
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeFocusEdit
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ PropertyChanges {
+ target: dragHandler
+ enabled: false
+ }
+ PropertyChanges {
+ target: tapHandler
+ enabled: false
+ }
+ PropertyChanges {
+ target: mouseArea
+ cursorShape: Qt.IBeamCursor
+ }
+ },
+ State {
+ name: "drag"
+ when: myControl.drag
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeFocusDrag
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myControl.enabled
+ PropertyChanges {
+ target: textInputArea
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ PropertyChanges {
+ target: textInput
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml
new file mode 100644
index 0000000000..7432d00bb0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+TextField {
+ id: myTextField
+
+ property real relativePopupX: 0 // TODO Maybe call it leftPadding
+ property real popupWidth: myTextField.width
+ property string txtStorage
+
+ property int temp: 0
+
+ T.Popup {
+ id: popup
+ x: relativePopupX
+ y: myTextField.height - StudioTheme.Values.border
+ width: popupWidth
+ height: scrollView.height
+ background: Rectangle {
+ color: StudioTheme.Values.themeFocusEdit
+ border.color: StudioTheme.Values.themeInteraction
+ border.width: StudioTheme.Values.border
+ }
+
+ contentItem: ScrollView {
+ id: scrollView
+ padding: 0
+ height: Math.min(textAreaPopup.contentHeight + scrollView.topPadding
+ + scrollView.bottomPadding,
+ StudioTheme.Values.maxTextAreaPopupHeight)
+ ScrollBar.horizontal.policy: ScrollBar.AlwaysOn
+ ScrollBar.vertical.policy: ScrollBar.AlwaysOn
+
+ T.TextArea {
+ id: textAreaPopup
+ padding: 10
+ width: textAreaPopup.contentWidth + textAreaPopup.leftPadding
+ + textAreaPopup.rightPadding
+ anchors.fill: parent
+ font.pixelSize: StudioTheme.Values.myFontSize
+ color: StudioTheme.Values.themeTextColor
+ selectionColor: StudioTheme.Values.themeTextSelectionColor
+ selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor
+ selectByMouse: true
+ persistentSelection: textAreaPopup.focus
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ enabled: true
+ cursorShape: Qt.IBeamCursor
+ acceptedButtons: Qt.RightButton
+ onPressed: contextMenu.popup(textAreaPopup)
+ }
+ }
+ }
+
+ ContextMenu {
+ id: contextMenu
+ myTextEdit: textAreaPopup
+ }
+
+ AbstractButton {
+ id: acceptButton
+ x: popup.width - acceptButton.width
+ y: popup.height - StudioTheme.Values.border
+ width: Math.round(StudioTheme.Values.smallRectWidth)
+ height: Math.round(StudioTheme.Values.smallRectWidth)
+ buttonIcon: StudioTheme.Constants.tickIcon
+ }
+
+ AbstractButton {
+ id: discardButton
+ x: popup.width - acceptButton.width - discardButton.width + StudioTheme.Values.border
+ y: popup.height - StudioTheme.Values.border
+ width: Math.round(StudioTheme.Values.smallRectWidth)
+ height: Math.round(StudioTheme.Values.smallRectWidth)
+ buttonIcon: StudioTheme.Constants.closeCross
+ }
+
+ Component.onCompleted: {
+ storeAndFormatTextInput(myTextField.text)
+ }
+
+ onOpened: {
+ textAreaPopup.text = txtStorage
+ myTextField.clear()
+ }
+
+ onClosed: {
+ storeAndFormatTextInput(textAreaPopup.text)
+ myTextField.forceActiveFocus()
+ textAreaPopup.deselect()
+ }
+ }
+
+ function storeAndFormatTextInput(inputText) {
+ txtStorage = inputText
+ var pos = txtStorage.search(/\n/g)
+ var sliceAt = Math.min(pos, 15)
+ myTextField.text = txtStorage.slice(0, sliceAt).padEnd(sliceAt + 3, '.')
+ }
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_Escape) {
+ if (popup.opened)
+ popup.close()
+ else
+ myTextField.focus = false
+ }
+
+ if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter)
+ && !popup.opened) {
+ popup.open()
+ textAreaPopup.forceActiveFocus()
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml
new file mode 100644
index 0000000000..80ca6fd1c7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+T.TextField {
+ id: myTextField
+
+ property alias actionIndicator: actionIndicator
+ property alias translationIndicator: translationIndicator
+
+ property bool edit: myTextField.activeFocus
+ property bool hover: false // This property is used to indicate the global hover state
+
+ property alias actionIndicatorVisible: actionIndicator.visible
+ property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __actionIndicatorHeight: StudioTheme.Values.height
+
+ property alias translationIndicatorVisible: translationIndicator.visible
+ property real __translationIndicatorWidth: StudioTheme.Values.squareComponentWidth
+ property real __translationIndicatorHeight: StudioTheme.Values.height
+
+ horizontalAlignment: Qt.AlignLeft
+ verticalAlignment: Qt.AlignVCenter
+
+ font.pixelSize: StudioTheme.Values.myFontSize
+
+ color: StudioTheme.Values.themeTextColor
+ selectionColor: StudioTheme.Values.themeTextSelectionColor
+ selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor
+
+ readOnly: false
+ selectByMouse: true
+ persistentSelection: focus // QTBUG-73807
+ clip: true
+
+ height: StudioTheme.Values.height
+ implicitHeight: StudioTheme.Values.height
+ width: StudioTheme.Values.height * 5
+
+ leftPadding: StudioTheme.Values.inputHorizontalPadding + actionIndicator.width
+ - (actionIndicatorVisible ? StudioTheme.Values.border : 0)
+ rightPadding: StudioTheme.Values.inputHorizontalPadding + translationIndicator.width
+ - (translationIndicatorVisible ? StudioTheme.Values.border : 0)
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ enabled: true
+ hoverEnabled: true
+ propagateComposedEvents: true
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ cursorShape: Qt.PointingHandCursor
+ onContainsMouseChanged: myTextField.hover = containsMouse // Sets the global hover
+ onPressed: {
+ if (mouse.button === Qt.RightButton)
+ contextMenu.popup(myTextField)
+
+ mouse.accepted = false
+ }
+ }
+
+ onPersistentSelectionChanged: {
+ if (!persistentSelection)
+ myTextField.deselect()
+ }
+
+ ContextMenu {
+ id: contextMenu
+ myTextEdit: myTextField
+ }
+
+ ActionIndicator {
+ id: actionIndicator
+ myControl: myTextField
+ x: 0
+ y: 0
+ width: actionIndicator.visible ? __actionIndicatorWidth : 0
+ height: actionIndicator.visible ? __actionIndicatorHeight : 0
+ }
+
+ background: Rectangle {
+ id: textFieldBackground
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+ anchors.fill: parent
+ }
+
+ TranslationIndicator {
+ id: translationIndicator
+ myControl: myTextField
+ x: myTextField.width - translationIndicator.width
+ width: translationIndicator.visible ? __translationIndicatorWidth : 0
+ height: translationIndicator.visible ? __translationIndicatorHeight : 0
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myTextField.enabled && !myTextField.hover
+ && !myTextField.edit
+ PropertyChanges {
+ target: textFieldBackground
+ color: StudioTheme.Values.themeControlBackground
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ PropertyChanges {
+ target: mouseArea
+ cursorShape: Qt.PointingHandCursor
+ }
+ },
+ State {
+ name: "hovered"
+ when: myTextField.hover && !myTextField.edit
+ PropertyChanges {
+ target: textFieldBackground
+ color: StudioTheme.Values.themeHoverHighlight
+ border.color: StudioTheme.Values.themeControlOutline
+ }
+ },
+ State {
+ name: "edit"
+ when: myTextField.edit
+ PropertyChanges {
+ target: textFieldBackground
+ color: StudioTheme.Values.themeFocusEdit
+ border.color: StudioTheme.Values.themeInteraction
+ }
+ PropertyChanges {
+ target: mouseArea
+ cursorShape: Qt.IBeamCursor
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myTextField.enabled
+ PropertyChanges {
+ target: textFieldBackground
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ }
+ ]
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_Escape)
+ myTextField.focus = false
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml
new file mode 100644
index 0000000000..7c4e0c90ce
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Templates 2.12 as T
+import StudioTheme 1.0 as StudioTheme
+
+Item {
+ id: translationIndicator
+
+ property Item myControl
+
+ property bool hover: false
+ property bool pressed: false
+ property bool checked: false
+
+ signal clicked
+
+ state: "default"
+
+ Rectangle {
+ id: translationIndicatorBackground
+ color: StudioTheme.Values.themeColumnBackground // TODO create extra variable, this one is used
+ border.color: StudioTheme.Values.themeTranslationIndicatorBorder
+
+ anchors.centerIn: parent
+
+ width: matchParity(translationIndicator.height,
+ StudioTheme.Values.smallRectWidth)
+ height: matchParity(translationIndicator.height,
+ StudioTheme.Values.smallRectWidth)
+
+ function matchParity(root, value) {
+ // TODO maybe not necessary
+ var v = Math.round(value)
+
+ if (root % 2 == 0)
+ // even
+ return (v % 2 == 0) ? v : v - 1
+ else
+ // odd
+ return (v % 2 == 0) ? v - 1 : v
+ }
+
+ MouseArea {
+ id: translationIndicatorMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onContainsMouseChanged: translationIndicator.hover = containsMouse
+ onPressed: mouse.accepted = true // TODO
+ onClicked: {
+ translationIndicator.checked = !translationIndicator.checked
+ translationIndicator.clicked()
+ }
+ }
+ }
+
+ T.Label {
+ id: translationIndicatorIcon
+ text: "tr"
+ color: StudioTheme.Values.themeTextColor
+ font.family: StudioTheme.Constants.font.family
+ font.pixelSize: StudioTheme.Values.myIconFontSize
+ font.italic: true
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.fill: parent
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: myControl.enabled && !translationIndicator.hover
+ && !translationIndicator.pressed && !myControl.hover
+ && !myControl.edit && !myControl.drag
+ && !translationIndicator.checked
+ PropertyChanges {
+ target: translationIndicatorBackground
+ color: StudioTheme.Values.themeColumnBackground
+ border.color: StudioTheme.Values.themeTranslationIndicatorBorder
+ }
+ },
+ State {
+ name: "checked"
+ when: translationIndicator.checked
+
+ PropertyChanges {
+ target: translationIndicatorBackground
+ color: StudioTheme.Values.themeInteraction // TODO
+ }
+ },
+ State {
+ name: "hovered"
+ when: translationIndicator.hover && !translationIndicator.pressed
+ && !myControl.edit && !myControl.drag && !myControl.drag
+ PropertyChanges {
+ target: translationIndicatorBackground
+ color: StudioTheme.Values.themeFocusDrag // TODO
+ }
+ },
+ State {
+ name: "disabled"
+ when: !myControl.enabled
+ PropertyChanges {
+ target: translationIndicatorBackground
+ color: StudioTheme.Values.themeControlBackgroundDisabled
+ border.color: StudioTheme.Values.themeControlOutlineDisabled
+ }
+ PropertyChanges {
+ target: translationIndicatorIcon
+ color: StudioTheme.Values.themeTextColorDisabled
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir
new file mode 100644
index 0000000000..02acf99dff
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/qmldir
@@ -0,0 +1,29 @@
+AbstractButton 1.0 AbstractButton.qml
+ActionIndicator 1.0 ActionIndicator.qml
+Button 1.0 Button.qml
+ButtonGroup 1.0 ButtonGroup.qml
+ButtonRow 1.0 ButtonRow.qml
+CheckBox 1.0 CheckBox.qml
+CheckIndicator 1.0 CheckIndicator.qml
+ComboBox 1.0 ComboBox.qml
+ComboBoxInput 1.0 ComboBoxInput.qml
+ContextMenu 1.0 ContextMenu.qml
+ExpandingSpacer 1.0 ExpandingSpacer.qml
+ItemDelegate 1.0 ItemDelegate.qml
+Menu 1.0 Menu.qml
+MenuItem 1.0 MenuItem.qml
+MenuSeparator 1.0 MenuSeparator.qml
+ScrollBar 1.0 ScrollBar.qml
+ScrollView 1.0 ScrollView.qml
+SecondColumnLayout 1.0 SecondColumnLayout.qml
+Section 1.0 Section.qml
+SectionLabel 1.0 SectionLabel.qml
+SectionLayout 1.0 SectionLayout.qml
+Slider 1.0 Slider.qml
+SliderPopup 1.0 SliderPopup.qml
+SpinBox 1.0 SpinBox.qml
+SpinBoxIndicator 1.0 SpinBoxIndicator.qml
+SpinBoxInput 1.0 SpinBoxInput.qml
+TextArea 1.0 TextArea.qml
+TextField 1.0 TextField.qml
+TranslationIndicator 1.0 TranslationIndicator.qml
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml
new file mode 100644
index 0000000000..207a154719
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Constants.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 Singleton
+import QtQuick 2.10
+
+QtObject {
+ readonly property int width: 1920
+ readonly property int height: 1080
+ readonly property FontLoader mySystemFont: FontLoader {
+ name: "Arial"
+ }
+ readonly property FontLoader controlIcons: FontLoader {
+ source: "icons.ttf"
+ }
+
+ readonly property string actionIcon: "\u0021"
+ readonly property string actionIconBinding: "\u0022"
+ readonly property string anchorBaseline: "\u0023"
+ readonly property string anchorBottom: "\u0024"
+ readonly property string anchorFill: "\u0025"
+ readonly property string anchorLeft: "\u0026"
+ readonly property string anchorRight: "\u0027"
+ readonly property string anchorTop: "\u0028"
+ readonly property string centerHorizontal: "\u0029"
+ readonly property string centerVertical: "\u002A"
+ readonly property string closeCross: "\u002B"
+ readonly property string fontStyleBold: "\u002C"
+ readonly property string fontStyleItalic: "\u002D"
+ readonly property string fontStyleStrikethrough: "\u002E"
+ readonly property string fontStyleUnderline: "\u002F"
+ readonly property string textAlignBottom: "\u0030"
+ readonly property string textAlignCenter: "\u0031"
+ readonly property string textAlignLeft: "\u0032"
+ readonly property string textAlignMiddle: "\u0033"
+ readonly property string textAlignRight: "\u0034"
+ readonly property string textAlignTop: "\u0035"
+ readonly property string tickIcon: "\u0036"
+ readonly property string triState: "\u0037"
+ readonly property string upDownIcon: "\u0038"
+ readonly property string upDownSquare2: "\u0039"
+
+ readonly property font iconFont: Qt.font({
+ "family": controlIcons.name,
+ "pixelSize": 12
+ })
+
+ readonly property font font: Qt.font({
+ "family": mySystemFont.name,
+ "pointSize": Qt.application.font.pixelSize
+ })
+
+ readonly property font largeFont: Qt.font({
+ "family": mySystemFont.name,
+ "pointSize": Qt.application.font.pixelSize * 1.6
+ })
+
+ readonly property color backgroundColor: "#c2c2c2"
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
new file mode 100644
index 0000000000..2055572e44
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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 Singleton
+import QtQuick 2.12
+
+QtObject {
+ id: values
+
+ property real baseHeight: 20
+ property real baseFont: 12
+ property real baseIconFont: 10
+
+ property real scaleFactor: 1
+
+ property real height: Math.round(values.baseHeight * values.scaleFactor)
+ property real myFontSize: Math.round(values.baseFont * values.scaleFactor)
+ property real myIconFontSize: Math.round(values.baseIconFont * values.scaleFactor)
+
+ property real squareComponentWidth: values.height
+ property real smallRectWidth: values.height / 2 * 1.5
+
+ property real inputWidth: values.height * 4
+
+ property real sliderHeight: values.height / 2 * 1.5 // TODO:Have a look at -> sliderAreaHeight: Data.Values.height/2*1.5
+
+ property real sliderControlSize: 12
+ property real sliderControlSizeMulti: sliderControlSize * scaleFactor
+
+ property real spinControlIconSize: 8
+ property real spinControlIconSizeMulti: spinControlIconSize * scaleFactor
+
+ property real sliderTrackHeight: values.height / 4
+ property real sliderHandleHeight: values.sliderTrackHeight * 2
+ property real sliderHandleWidth: values.sliderTrackHeight
+ property real sliderFontSize: Math.round(8 * values.scaleFactor)
+ property real sliderPadding: Math.round(6 * values.scaleFactor)
+ property real sliderMargin: Math.round(3 * values.scaleFactor)
+
+ property real sliderPointerWidth: Math.round(7 * values.scaleFactor)
+ property real sliderPointerHeight: Math.round(2 * values.scaleFactor)
+
+ property real checkBoxSpacing: 6 // TODO Does look strange with scale factor applied
+
+ property real columnWidth: 225 + (175 * (values.scaleFactor * 2))
+
+ property real marginTopBottom: 4
+ property real border: 1
+
+ property real maxComboBoxPopupHeight: 300
+ property real maxTextAreaPopupHeight: 150
+
+ property real contextMenuLabelSpacing: 30
+ property real contextMenuHorizontalPadding: 6
+
+ property real inputHorizontalPadding: Math.round(4 * values.scaleFactor)
+
+ // Theme Colors
+
+ // Dark Theme Defaults
+ property string themeControlBackground: "#242424"
+ property string themeControlOutline: "#404040"
+ property string themeTextColor: "#ffffff"
+
+ property string themePanelBackground: "#2a2a2a"
+ property string themeHoverHighlight: "#313131"
+ property string themeColumnBackground: "#363636"
+ property string themeFocusEdit: "#606060"
+ property string themeFocusDrag: "#565656"
+
+ property string themeControlBackgroundPressed: "#606060"
+ property string themeControlBackgroundChecked: "#565656"
+
+ property string themeInteraction: "#029de0"
+
+ property string themeSliderActiveTrack: "#606060"
+ property string themeSliderInactiveTrack: "#404040"
+ property string themeSliderHandle: "#505050"
+
+ property string themeSliderActiveTrackHover: "#7f7f7f"
+ property string themeSliderInactiveTrackHover: "#505050"
+ property string themeSliderHandleHover: "#606060"
+
+ property string themeSliderActiveTrackFocus: "#aaaaaa"
+ property string themeSliderInactiveTrackFocus: "#606060"
+ property string themeSliderHandleFocus: values.themeInteraction
+
+ // NEW NEW NEW NEW NEW
+ property string themeControlBackgroundDisabled: "#363636"
+ property string themeControlOutlineDisabled: "#404040"
+ property string themeTextColorDisabled: "#606060"
+
+ property string themeTextSelectionColor: "#029de0"
+ property string themeTextSelectedTextColor: "#ffffff"
+
+ property string themeScrollBarTrack: "#404040"
+ property string themeScrollBarHandle: "#505050"
+
+ property string themeControlBackgroundInteraction: "#404040" // TODO Name. Right now themeFocusEdit is used for all 'edit' states. Is that correct? Different color!
+
+ property string themeTranslationIndicatorBorder: "#7f7f7f"
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
new file mode 100644
index 0000000000..9658c01782
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
Binary files differ
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir
new file mode 100644
index 0000000000..b768fe63a2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/qmldir
@@ -0,0 +1,2 @@
+singleton Values 1.0 Values.qml
+singleton Constants 1.0 Constants.qml
diff --git a/share/qtcreator/static.pro b/share/qtcreator/static.pro
index cda672829a..7f39ae2fae 100644
--- a/share/qtcreator/static.pro
+++ b/share/qtcreator/static.pro
@@ -22,7 +22,8 @@ DATA_DIRS = \
qml-type-descriptions \
modeleditor \
glsl \
- cplusplus
+ cplusplus \
+ indexer_preincludes
macx: DATA_DIRS += scripts
for(data_dir, DATA_DIRS) {
diff --git a/share/qtcreator/templates/qt4project/main.cpp b/share/qtcreator/templates/qt4project/main.cpp
deleted file mode 100644
index cc228553ac..0000000000
--- a/share/qtcreator/templates/qt4project/main.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "%INCLUDE%"
-#include <%QAPP_INCLUDE%>
-
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
- %CLASS% w;
-%SHOWMETHOD%
- return a.exec();
-}
diff --git a/share/qtcreator/templates/qt4project/mywidget.cpp b/share/qtcreator/templates/qt4project/mywidget.cpp
deleted file mode 100644
index ae355e98dd..0000000000
--- a/share/qtcreator/templates/qt4project/mywidget.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "%INCLUDE%"
-
-%CLASS%::%CLASS%(QWidget *parent)
- : %BASECLASS%(parent)
-{
-}
-
-%CLASS%::~%CLASS%()
-{
-
-}
diff --git a/share/qtcreator/templates/qt4project/mywidget.h b/share/qtcreator/templates/qt4project/mywidget.h
deleted file mode 100644
index 993914c8cc..0000000000
--- a/share/qtcreator/templates/qt4project/mywidget.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef %PRE_DEF%
-#define %PRE_DEF%
-
-#include <%BASECLASS%>
-
-class %CLASS% : public %BASECLASS%
-{
- Q_OBJECT
-
-public:
- %CLASS%(QWidget *parent = 0);
- ~%CLASS%();
-};
-
-#endif // %PRE_DEF%
diff --git a/share/qtcreator/templates/qt4project/mywidget_form.cpp b/share/qtcreator/templates/qt4project/mywidget_form.cpp
deleted file mode 100644
index b7e3ae6200..0000000000
--- a/share/qtcreator/templates/qt4project/mywidget_form.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "%INCLUDE%"
-#include "%UI_HDR%"
-
-%CLASS%::%CLASS%(QWidget *parent)
- : %BASECLASS%(parent), ui(new Ui::%CLASS%)
-{
- ui->setupUi(this);
-}
-
-%CLASS%::~%CLASS%()
-{
- delete ui;
-}
diff --git a/share/qtcreator/templates/qt4project/mywidget_form.h b/share/qtcreator/templates/qt4project/mywidget_form.h
deleted file mode 100644
index f519708a52..0000000000
--- a/share/qtcreator/templates/qt4project/mywidget_form.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef %PRE_DEF%
-#define %PRE_DEF%
-
-#include <%BASECLASS%>
-
-namespace Ui
-{
- class %CLASS%;
-}
-
-class %CLASS% : public %BASECLASS%
-{
- Q_OBJECT
-
-public:
- %CLASS%(QWidget *parent = 0);
- ~%CLASS%();
-
-private:
- Ui::%CLASS% *ui;
-};
-
-#endif // %PRE_DEF%
diff --git a/share/qtcreator/templates/qt4project/widget.ui b/share/qtcreator/templates/qt4project/widget.ui
deleted file mode 100644
index 2ac9f1d7c7..0000000000
--- a/share/qtcreator/templates/qt4project/widget.ui
+++ /dev/null
@@ -1,20 +0,0 @@
-<ui version="4.0">
- <class>%CLASS%</class>
- <widget class="%BASECLASS%" name="%CLASS%" >
- <property name="geometry" >
- <rect>
- <x>0</x>
- <y>0</y>
- <width>%WIDGET_WIDTH%</width>
- <height>%WIDGET_HEIGHT%</height>
- </rect>
- </property>
- <property name="windowTitle" >
- <string>%CLASS%</string>
- </property>%CENTRAL_WIDGET%
- </widget>
- <layoutDefault spacing="6" margin="11" />
- <pixmapfunction></pixmapfunction>
- <resources/>
- <connections/>
-</ui>
diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.pro b/share/qtcreator/templates/wizards/autotest/files/tst.pro
index a973d1a9cb..1d59f9c05f 100644
--- a/share/qtcreator/templates/wizards/autotest/files/tst.pro
+++ b/share/qtcreator/templates/wizards/autotest/files/tst.pro
@@ -44,3 +44,23 @@ HEADERS += \\
SOURCES += \\
%{MainCppName}
@endif
+@if "%{TestFrameWork}" == "BoostTest"
+TEMPLATE = app
+CONFIG -= qt
+CONFIG -= app_bundle
+CONFIG += console
+
+isEmpty(BOOST_INCLUDE_DIR): BOOST_INCLUDE_DIR=$$(BOOST_INCLUDE_DIR)
+@if "%{BoostIncDir}" != ""
+# set by Qt Creator wizard
+isEmpty(BOOST_INCLUDE_DIR): BOOST_INCLUDE_DIR="%{BoostIncDir}"
+@endif
+!isEmpty(BOOST_INCLUDE_DIR): INCLUDEPATH *= $${BOOST_INCLUDE_DIR}
+
+isEmpty(BOOST_INCLUDE_DIR): {
+ message("BOOST_INCLUDE_DIR is not set, assuming Boost can be found automatically in your system")
+}
+
+SOURCES += \\
+ %{MainCppName}
+@endif
diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.qbs b/share/qtcreator/templates/wizards/autotest/files/tst.qbs
index 14d277a429..92a0656d65 100644
--- a/share/qtcreator/templates/wizards/autotest/files/tst.qbs
+++ b/share/qtcreator/templates/wizards/autotest/files/tst.qbs
@@ -3,6 +3,10 @@ import qbs
import qbs.Environment
import "googlecommon.js" as googleCommon
@endif
+@if "%{TestFrameWork}" == "BoostTest"
+import qbs.Environment
+import qbs.File
+@endif
CppApplication {
@if "%{TestFrameWork}" == "QtTest"
@@ -72,4 +76,28 @@ CppApplication {
cpp.defines: base.concat("QUICK_TEST_SOURCE_DIR=\\"" + path + "\\"")
@endif
+@if "%{TestFrameWork}" == "BoostTest"
+ type: "application"
+
+ property string boostIncDir: {
+ if (typeof Environment.getEnv("BOOST_INCLUDE_DIR") !== 'undefined')
+ return Environment.getEnv("BOOST_INCLUDE_DIR");
+ return "%{BoostIncDir}"; // set by Qt Creator wizard
+ }
+
+ Properties {
+ condition: boostIncDir && File.exists(boostIncDir)
+ cpp.includePaths: [boostIncDir];
+ }
+
+ condition: {
+ if (!boostIncDir)
+ console.log("BOOST_INCLUDE_DIR is not set, assuming Boost can be "
+ + "found automatically in your system");
+ return true;
+ }
+
+ files: [ "%{MainCppName}" ]
+
+@endif
}
diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.txt b/share/qtcreator/templates/wizards/autotest/files/tst.txt
index 239e7087f8..bf5e75ff16 100644
--- a/share/qtcreator/templates/wizards/autotest/files/tst.txt
+++ b/share/qtcreator/templates/wizards/autotest/files/tst.txt
@@ -1,7 +1,6 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
+cmake_minimum_required(VERSION 3.5)
-PROJECT(%{TestCaseName}
- LANGUAGES CXX)
+project(%{TestCaseName} LANGUAGES CXX)
@if "%{TestFrameWork}" == "QtTest"
@@ -10,38 +9,46 @@ find_package(Qt5Test REQUIRED)
find_package(Qt5Gui REQUIRED)
@endif
-SET(CMAKE_AUTOMOC ON)
-SET(CMAKE_INCLUDE_CURRENT_DIR ON)
-SET(CMAKE_CXX_STANDARD 11)
-SET(CMAKE_CXX_STANDARD_REQUIRED ON)
-ENABLE_TESTING()
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
-add_executable(${PROJECT_NAME} %{TestCaseFileWithCppSuffix})
-add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME})
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+enable_testing()
+
+add_executable(%{TestCaseName} %{TestCaseFileWithCppSuffix})
+add_test(%{TestCaseName} COMMAND %{TestCaseName})
@if "%{RequireGUI}" == "true"
-target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Gui Qt5::Test)
+target_link_libraries(%{TestCaseName} PRIVATE Qt5::Gui Qt5::Test)
@else
-target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Test)
+target_link_libraries(%{TestCaseName} PRIVATE Qt5::Test)
@endif
@endif
@if "%{TestFrameWork}" == "QtQuickTest"
find_package(Qt5QuickTest REQUIRED)
-SET(CMAKE_AUTOMOC ON)
-SET(CMAKE_INCLUDE_CURRENT_DIR ON)
-SET(CMAKE_CXX_STANDARD 11)
-SET(CMAKE_CXX_STANDARD_REQUIRED ON)
-ENABLE_TESTING()
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+enable_testing()
# no need to copy around qml test files for shadow builds - just set the respective define
add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
-add_executable(${PROJECT_NAME} %{MainCppName})
-add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME})
+add_executable(%{TestCaseName} %{MainCppName})
+add_test(%{TestCaseName} COMMAND %{TestCaseName})
-target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::QuickTest)
+target_link_libraries(%{TestCaseName} PRIVATE Qt5::QuickTest)
@endif
@if "%{TestFrameWork}" == "GTest"
@@ -53,14 +60,14 @@ add_definitions(-DGTEST_LANGUAGE_CXX11)
find_package(Threads REQUIRED)
if ($ENV{GOOGLETEST_DIR})
- SET(GOOGLETEST_DIR $ENV{GOOGLETEST_DIR})
+ set(GOOGLETEST_DIR $ENV{GOOGLETEST_DIR})
else ()
message(WARNING "Using googletest src dir specified at Qt Creator wizard")
- SET(GOOGLETEST_DIR "%{GTestRepository}")
+ set(GOOGLETEST_DIR "%{GTestRepository}")
endif ()
if (EXISTS ${GOOGLETEST_DIR})
- SET(GTestSrc ${GOOGLETEST_DIR}/googletest)
- SET(GMockSrc ${GOOGLETEST_DIR}/googlemock)
+ set(GTestSrc ${GOOGLETEST_DIR}/googletest)
+ set(GMockSrc ${GOOGLETEST_DIR}/googlemock)
else ()
message( FATAL_ERROR "No googletest src dir found - set GOOGLETEST_DIR to enable!")
endif ()
@@ -68,10 +75,31 @@ endif ()
include_directories(${GTestSrc} ${GTestSrc}/include ${GMockSrc} ${GMockSrc}/include)
-add_executable(${PROJECT_NAME} %{MainCppName} %{TestCaseFileWithHeaderSuffix}
+add_executable(%{TestCaseName} %{MainCppName} %{TestCaseFileWithHeaderSuffix}
${GTestSrc}/src/gtest-all.cc
${GMockSrc}/src/gmock-all.cc)
-add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME})
-target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
+add_test(%{TestCaseName} COMMAND %{TestCaseName})
+target_link_libraries(%{TestCaseName} PRIVATE Threads::Threads)
+
+@endif
+@if "%{TestFrameWork}" == "BoostTest"
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+enable_testing()
+
+add_executable(%{TestCaseName} %{MainCppName})
+add_test(%{TestCaseName} COMMAND %{TestCaseName})
+
+if (DEFINED ENV{BOOST_INCLUDE_DIR})
+ set(BOOST_INCLUDE_DIR $ENV{BOOST_INCLUDE_DIR})
+else ()
+ set(BOOST_INCLUDE_DIR "%{BoostIncDir}") # set by Qt Creator wizard
+endif ()
+if (BOOST_INCLUDE_DIR STREQUAL "")
+ message("BOOST_INCLUDE_DIR is not set, assuming Boost can be found automatically in your system")
+elseif (EXISTS ${BOOST_INCLUDE_DIR})
+ include_directories(${BOOST_INCLUDE_DIR})
+endif ()
@endif
diff --git a/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp b/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp
index d918350551..923fad9f9b 100644
--- a/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp
+++ b/share/qtcreator/templates/wizards/autotest/files/tst_main.cpp
@@ -2,7 +2,8 @@
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(example)
-@else
+@endif
+@if "%{TestFrameWork}" == "GTest"
%{Cpp:LicenseTemplate}\
#include "%{TestCaseFileWithHeaderSuffix}"
@@ -14,3 +15,12 @@ int main(int argc, char *argv[])
return RUN_ALL_TESTS();
}
@endif
+@if "%{TestFrameWork}" == "BoostTest"
+#define BOOST_TEST_MODULE %{TestSuiteName}
+#include <boost/test/included/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( %{TestCaseName} )
+{
+ BOOST_TEST( true /* test assertion */ );
+}
+@endif
diff --git a/share/qtcreator/templates/wizards/autotest/files/tst_src.h b/share/qtcreator/templates/wizards/autotest/files/tst_src.h
index 9e6c619c5f..ef29240cd5 100644
--- a/share/qtcreator/templates/wizards/autotest/files/tst_src.h
+++ b/share/qtcreator/templates/wizards/autotest/files/tst_src.h
@@ -11,7 +11,7 @@
using namespace testing;
-TEST(%{TestCaseName}, %{TestSetName})
+TEST(%{TestSuiteName}, %{TestCaseName})
{
EXPECT_EQ(1, 1);
ASSERT_THAT(0, Eq(0));
diff --git a/share/qtcreator/templates/wizards/autotest/wizard.json b/share/qtcreator/templates/wizards/autotest/wizard.json
index 64e8b8d6af..83a4be09a4 100644
--- a/share/qtcreator/templates/wizards/autotest/wizard.json
+++ b/share/qtcreator/templates/wizards/autotest/wizard.json
@@ -8,19 +8,19 @@
"trDisplayCategory": "Other Project",
"icon": "autotest.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureDesktop" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('AutoTest') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('AutoTest') >= 0}",
"options":
[
{ "key": "ProjectFilePath",
- "value": "%{JS: '%{BuildSystem}' == 'qmake' ? '%{ProFileName}' : ('%{BuildSystem}' == 'qbs' ? '%{QbsFileName}' : '%{CMakeFileName}') }"
+ "value": "%{JS: value('BuildSystem') == 'qmake' ? value('ProFileName') : (value('BuildSystem') == 'qbs' ? value('QbsFileName') : value('CMakeFileName')) }"
},
{ "key": "ProFileName",
- "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}"
+ "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}"
},
{
"key": "QbsFileName",
- "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}"
+ "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}"
},
{
"key": "CMakeFileName",
@@ -34,19 +34,19 @@
},
{
"key": "TestCaseFileWithHeaderSuffix",
- "value": "%{JS: 'tst_%{TestCaseName}.'.toLowerCase() + Util.preferredSuffix('text/x-c++hdr') }"
+ "value": "%{JS: 'tst_' + value('TestCaseName').toLowerCase() + '.' + Util.preferredSuffix('text/x-c++hdr') }"
},
{
"key": "GUARD",
- "value": "%{JS: '%{TestCaseFileWithHeaderSuffix}'.toUpperCase().replace('.', '_') }"
+ "value": "%{JS: value('TestCaseFileWithHeaderSuffix').toUpperCase().replace('.', '_') }"
},
{
"key": "TestCaseFileWithCppSuffix",
- "value": "%{JS: 'tst_%{TestCaseName}.'.toLowerCase() + Util.preferredSuffix('text/x-c++src') }"
+ "value": "%{JS: 'tst_' + value('TestCaseName').toLowerCase() + '.' + Util.preferredSuffix('text/x-c++src') }"
},
{
"key": "TestCaseFileWithQmlSuffix",
- "value": "%{JS: 'tst_%{TestCaseName}.qml'.toLowerCase() }"
+ "value": "%{JS: 'tst_' + value('TestCaseName').toLowerCase() + '.qml' }"
}
],
@@ -87,6 +87,10 @@
{
"trKey": "Qt Quick Test",
"value": "QtQuickTest"
+ },
+ {
+ "trKey": "Boost Test",
+ "value": "BoostTest"
}
]
@@ -95,13 +99,21 @@
{
"name": "RequireGUI",
"trDisplayName": "GUI Application",
- "visible": "%{JS: '%{TestFrameWork}' === 'QtTest'}",
+ "visible": "%{JS: value('TestFrameWork') === 'QtTest'}",
"type": "CheckBox",
"data": {
"checked": false
}
},
{
+ "name": "TestSuiteName",
+ "trDisplayName": "Test suite name:",
+ "visible": "%{JS: ['BoostTest', 'GTest'].indexOf(value('TestFrameWork')) >= 0}",
+ "mandatory": true,
+ "type": "LineEdit",
+ "data": { "validator": "^[a-zA-Z_0-9]+$" }
+ },
+ {
"name": "TestCaseName",
"trDisplayName": "Test case name:",
"mandatory": true,
@@ -111,7 +123,7 @@
{
"name": "RequireApplication",
"trDisplayName": "Requires QApplication",
- "visible": "%{JS: '%{TestFrameWork}' === 'QtTest'}",
+ "visible": "%{JS: value('TestFrameWork') === 'QtTest'}",
"type": "CheckBox",
"data": {
"checked": false
@@ -120,23 +132,16 @@
{
"name": "GenerateInitAndCleanup",
"trDisplayName": "Generate initialization and cleanup code",
- "visible": "%{JS: [ 'QtTest', 'QtQuickTest' ].indexOf('%{TestFrameWork}') >= 0 }",
+ "visible": "%{JS: [ 'QtTest', 'QtQuickTest' ].indexOf(value('TestFrameWork')) >= 0 }",
"type": "CheckBox",
"data": {
"checked": false
}
},
{
- "name": "TestSetName",
- "trDisplayName": "Test set name:",
- "visible": "%{JS: '%{TestFrameWork}' === 'GTest'}",
- "type": "LineEdit",
- "data": { "validator": "^[a-zA-Z0-9]+$" }
- },
- {
"name": "GTestCXX11",
"trDisplayName": "Enable C++11",
- "visible": "%{JS: '%{TestFrameWork}' === 'GTest'}",
+ "visible": "%{JS: value('TestFrameWork') === 'GTest'}",
"type": "CheckBox",
"data": {
"checked": false
@@ -145,7 +150,17 @@
{
"name": "GTestRepository",
"trDisplayName": "Googletest repository:",
- "visible": "%{JS: '%{TestFrameWork}' === 'GTest'}",
+ "visible": "%{JS: value('TestFrameWork') === 'GTest'}",
+ "type": "PathChooser",
+ "data": {
+ "kind": "existingDirectory"
+ }
+ },
+ {
+ "name": "BoostIncDir",
+ "trDisplayName": "Boost include dir (optional):",
+ "visible": "%{JS: value('TestFrameWork') == 'BoostTest'}",
+ "mandatory": false,
"type": "PathChooser",
"data": {
"kind": "existingDirectory"
@@ -163,17 +178,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
@@ -187,7 +202,7 @@
"enabled": "%{IsTopLevelProject}",
"data": {
"projectFilePath": "%{ProjectFilePath}",
- "requiredFeatures": [ "%{JS: ('%{TestFrameWork}' === 'QtQuickTest' ? 'QtSupport.Wizards.FeatureQt.5' : (('%{BuildSystem}' === 'qmake' || '%{TestFrameWork}' === 'QtTest') ? 'QtSupport.Wizards.FeatureQt' : 'DeviceType.Desktop' )) }" ]
+ "requiredFeatures": [ "%{JS: (value('TestFrameWork') === 'QtQuickTest' ? 'QtSupport.Wizards.FeatureQt.5' : ((value('BuildSystem') === 'qmake' || value('TestFrameWork') === 'QtTest') ? 'QtSupport.Wizards.FeatureQt' : 'DeviceType.Desktop' )) }" ]
}
},
{
@@ -205,64 +220,64 @@
{
"source": "files/gtest_dependency.pri",
"target": "gtest_dependency.pri",
- "condition": "%{JS: '%{TestFrameWork}' == 'GTest' && '%{BuildSystem}' == 'qmake'}",
+ "condition": "%{JS: value('TestFrameWork') == 'GTest' && value('BuildSystem') == 'qmake'}",
"openInEditor": false
},
{
"source": "files/googlecommon.js",
"target": "googlecommon.js",
- "condition": "%{JS: '%{TestFrameWork}' == 'GTest' && '%{BuildSystem}' == 'qbs'}",
+ "condition": "%{JS: value('TestFrameWork') == 'GTest' && value('BuildSystem') == 'qbs'}",
"openInEditor": false
},
{
"source": "files/tst.pro",
"target": "%{ProjectFilePath}",
- "condition": "%{JS: '%{BuildSystem}' == 'qmake'}",
+ "condition": "%{JS: value('BuildSystem') == 'qmake'}",
"openInEditor": false,
"openAsProject": true
},
{
"source": "files/tst.qbs",
"target": "%{ProjectFilePath}",
- "condition": "%{JS: '%{BuildSystem}' == 'qbs'}",
+ "condition": "%{JS: value('BuildSystem') == 'qbs'}",
"openInEditor": false,
"openAsProject": true
},
{
"source": "files/tst.txt",
"target": "CMakeLists.txt",
- "condition": "%{JS: '%{BuildSystem}' == 'cmake'}",
+ "condition": "%{JS: value('BuildSystem') == 'cmake'}",
"openInEditor": false,
"openAsProject": true
},
{
"source": "files/tst_src.h",
"target": "%{TestCaseFileWithHeaderSuffix}",
- "condition": "%{JS: '%{TestFrameWork}' == 'GTest'}",
+ "condition": "%{JS: value('TestFrameWork') == 'GTest'}",
"openInEditor": true
},
{
"source": "files/tst_src.cpp",
"target": "%{TestCaseFileWithCppSuffix}",
- "condition": "%{JS: '%{TestFrameWork}' == 'QtTest'}",
+ "condition": "%{JS: value('TestFrameWork') == 'QtTest'}",
"openInEditor": true
},
{
"source": "files/tst_main.cpp",
"target": "%{MainCppName}",
- "condition": "%{JS: ['GTest', 'QtQuickTest'].indexOf('%{TestFrameWork}') >= 0}",
+ "condition": "%{JS: ['GTest', 'QtQuickTest', 'BoostTest'].indexOf(value('TestFrameWork')) >= 0}",
"openInEditor": true
},
{
"source": "files/tst_qml.tmpl",
"target": "%{TestCaseFileWithQmlSuffix}",
- "condition": "%{JS: '%{TestFrameWork}' === 'QtQuickTest'}",
+ "condition": "%{JS: value('TestFrameWork') === 'QtQuickTest'}",
"openInEditor": true
},
{
"source": "../projects/git.ignore",
"target": ".gitignore",
- "condition": "%{JS: ( %{IsTopLevelProject} && '%{VersionControl}' === 'G.Git' )}"
+ "condition": "%{JS: ( %{IsTopLevelProject} && value('VersionControl') === 'G.Git' )}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/classes/cpp/file.cpp b/share/qtcreator/templates/wizards/classes/cpp/file.cpp
index d102ecf4a1..6bf6885858 100644
--- a/share/qtcreator/templates/wizards/classes/cpp/file.cpp
+++ b/share/qtcreator/templates/wizards/classes/cpp/file.cpp
@@ -1,5 +1,5 @@
%{Cpp:LicenseTemplate}\
-#include "%{HdrFileName}"
+#include "%{JS: Util.relativeFilePath('%{Path}/%{HdrFileName}', '%{Path}' + '/' + Util.path('%{SrcFileName}'))}"
%{JS: Cpp.openNamespaces('%{Class}')}
@if '%{IncludeQSharedData}'
class %{CN}Data : public QSharedData
diff --git a/share/qtcreator/templates/wizards/classes/cpp/wizard.json b/share/qtcreator/templates/wizards/classes/cpp/wizard.json
index 24b1f79b61..ae466ba7ed 100644
--- a/share/qtcreator/templates/wizards/classes/cpp/wizard.json
+++ b/share/qtcreator/templates/wizards/classes/cpp/wizard.json
@@ -7,18 +7,18 @@
"trDisplayName": "C++ Class",
"trDisplayCategory": "C++",
"iconText": "h/cpp",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",
"options":
[
{ "key": "TargetPath", "value": "%{Path}" },
{ "key": "HdrPath", "value": "%{Path}/%{HdrFileName}" },
{ "key": "SrcPath", "value": "%{Path}/%{SrcFileName}" },
- { "key": "CN", "value": "%{JS: Cpp.className('%{Class}')}" },
- { "key": "Base", "value": "%{JS: ( '%{BaseCB}' === '' ) ? '%{BaseEdit}' : '%{BaseCB}'}" },
- { "key": "isQObject", "value": "%{JS: [ 'QObject', 'QWidget', 'QMainWindow', 'QDeclarativeItem', 'QQuickItem'].indexOf('%{Base}') >= 0 }" },
- { "key": "GUARD", "value": "%{JS: Cpp.headerGuard('%{HdrFileName}')}" },
- { "key": "SharedDataInit", "value": "%{JS: ('%{IncludeQSharedData}') ? 'data(new %{CN}Data)' : '' }" }
+ { "key": "CN", "value": "%{JS: Cpp.className(value('Class'))}" },
+ { "key": "Base", "value": "%{JS: value('BaseCB') === '' ? value('BaseEdit') : value('BaseCB')}" },
+ { "key": "isQObject", "value": "%{JS: [ 'QObject', 'QWidget', 'QMainWindow', 'QDeclarativeItem', 'QQuickItem'].indexOf(value('Base')) >= 0 }" },
+ { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('Class'), Util.suffix(value('HdrFileName')))}" },
+ { "key": "SharedDataInit", "value": "%{JS: (value('IncludeQSharedData')) ? 'data(new %{CN}Data)' : '' }" }
],
"pages":
@@ -49,7 +49,7 @@
{
"name": "BaseEdit",
"type": "LineEdit",
- "enabled": "%{JS: '%{BaseCB}' === ''}",
+ "enabled": "%{JS: value('BaseCB') === ''}",
"mandatory": false,
"data":
{
@@ -71,7 +71,7 @@
{
"checkedValue": "QObject",
"uncheckedValue": "",
- "checked": "%{JS: '%{BaseCB}' === 'QObject'}"
+ "checked": "%{JS: value('BaseCB') === 'QObject'}"
}
},
{
@@ -82,7 +82,7 @@
{
"checkedValue": "QWidget",
"uncheckedValue": "",
- "checked": "%{JS: '%{BaseCB}' === 'QWidget'}"
+ "checked": "%{JS: value('BaseCB') === 'QWidget'}"
}
},
{
@@ -93,7 +93,7 @@
{
"checkedValue": "QMainWindow",
"uncheckedValue": "",
- "checked": "%{JS: '%{BaseCB}' === 'QMainWindow'}"
+ "checked": "%{JS: value('BaseCB') === 'QMainWindow'}"
}
},
{
@@ -104,7 +104,7 @@
{
"checkedValue": "QDeclarativeItem",
"uncheckedValue": "",
- "checked": "%{JS: '%{BaseCB}' === 'QDeclarativeItem'}"
+ "checked": "%{JS: value('BaseCB') === 'QDeclarativeItem'}"
}
},
{
@@ -115,7 +115,7 @@
{
"checkedValue": "QQuickItem",
"uncheckedValue": "",
- "checked": "%{JS: '%{BaseCB}' === 'QQuickItem'}"
+ "checked": "%{JS: value('BaseCB') === 'QQuickItem'}"
}
},
{
@@ -139,14 +139,14 @@
"type": "LineEdit",
"trDisplayName": "Header file:",
"mandatory": true,
- "data": { "trText": "%{JS: Cpp.classToFileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" }
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++hdr'))}" }
},
{
"name": "SrcFileName",
"type": "LineEdit",
"trDisplayName": "Source file:",
"mandatory": true,
- "data": { "trText": "%{JS: Cpp.classToFileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++src')}')}" }
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++src'))}" }
},
{
"name": "Path",
@@ -155,7 +155,7 @@
"mandatory": true,
"data":
{
- "kind": "existingDirectory",
+ "kind": "directory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
diff --git a/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp b/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp
index a8cdf3164a..4a438f48e4 100644
--- a/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp
+++ b/share/qtcreator/templates/wizards/classes/itemmodel/itemmodel.cpp
@@ -1,5 +1,5 @@
%{Cpp:LicenseTemplate}\
-#include "%{HdrFileName}"
+#include "%{JS: Util.relativeFilePath('%{Path}/%{HdrFileName}', '%{Path}' + '/' + Util.path('%{SrcFileName}'))}"
%{JS: Cpp.openNamespaces('%{Class}')}\
%{CN}::%{CN}(QObject *parent)
diff --git a/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp b/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp
index 5d25d88609..b6c9c4b430 100644
--- a/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp
+++ b/share/qtcreator/templates/wizards/classes/itemmodel/listmodel.cpp
@@ -1,5 +1,5 @@
%{Cpp:LicenseTemplate}\
-#include "%{HdrFileName}"
+#include "%{JS: Util.relativeFilePath('%{Path}/%{HdrFileName}', '%{Path}' + '/' + Util.path('%{SrcFileName}'))}"
%{JS: Cpp.openNamespaces('%{Class}')}\
%{CN}::%{CN}(QObject *parent)
diff --git a/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp b/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp
index 80bedf5899..cda910e6f7 100644
--- a/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp
+++ b/share/qtcreator/templates/wizards/classes/itemmodel/tablemodel.cpp
@@ -1,5 +1,5 @@
%{Cpp:LicenseTemplate}\
-#include "%{HdrFileName}"
+#include "%{JS: Util.relativeFilePath('%{Path}/%{HdrFileName}', '%{Path}' + '/' + Util.path('%{SrcFileName}'))}"
%{JS: Cpp.openNamespaces('%{Class}')}\
%{CN}::%{CN}(QObject *parent)
diff --git a/share/qtcreator/templates/wizards/classes/itemmodel/wizard.json b/share/qtcreator/templates/wizards/classes/itemmodel/wizard.json
index b6b70ba245..1e0cd06e19 100644
--- a/share/qtcreator/templates/wizards/classes/itemmodel/wizard.json
+++ b/share/qtcreator/templates/wizards/classes/itemmodel/wizard.json
@@ -6,15 +6,15 @@
"trDescription": "Creates a Qt item model.",
"trDisplayName": "Qt Item Model",
"trDisplayCategory": "Qt",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",
"options":
[
{ "key": "TargetPath", "value": "%{Path}" },
{ "key": "HdrPath", "value": "%{Path}/%{HdrFileName}" },
{ "key": "SrcPath", "value": "%{Path}/%{SrcFileName}" },
- { "key": "CN", "value": "%{JS: Cpp.className('%{Class}')}" },
- { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" }
+ { "key": "CN", "value": "%{JS: Cpp.className(value('Class'))}" },
+ { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('Class'), Util.preferredSuffix('text/x-c++hdr'))}" }
],
"pages":
@@ -92,14 +92,14 @@
"type": "LineEdit",
"trDisplayName": "Header file:",
"mandatory": true,
- "data": { "trText": "%{JS: Cpp.classToFileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" }
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++hdr'))}" }
},
{
"name": "SrcFileName",
"type": "LineEdit",
"trDisplayName": "Source file:",
"mandatory": true,
- "data": { "trText": "%{JS: Cpp.classToFileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++src')}')}" }
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++src'))}" }
},
{
"name": "Path",
@@ -108,7 +108,7 @@
"mandatory": true,
"data":
{
- "kind": "existingDirectory",
+ "kind": "directory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
@@ -131,7 +131,7 @@
{
"source": "itemmodel.h",
"target": "%{HdrPath}",
- "condition": "%{JS: '%{Base}' === 'QAbstractItemModel'}",
+ "condition": "%{JS: value('Base') === 'QAbstractItemModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
@@ -141,7 +141,7 @@
"source": "itemmodel.cpp",
"target": "%{SrcPath}",
"openInEditor": true,
- "condition": "%{JS: '%{Base}' === 'QAbstractItemModel'}",
+ "condition": "%{JS: value('Base') === 'QAbstractItemModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
@@ -150,7 +150,7 @@
{
"source": "tablemodel.h",
"target": "%{HdrPath}",
- "condition": "%{JS: '%{Base}' === 'QAbstractTableModel'}",
+ "condition": "%{JS: value('Base') === 'QAbstractTableModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
@@ -160,7 +160,7 @@
"source": "tablemodel.cpp",
"target": "%{SrcPath}",
"openInEditor": true,
- "condition": "%{JS: '%{Base}' === 'QAbstractTableModel'}",
+ "condition": "%{JS: value('Base') === 'QAbstractTableModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
@@ -169,7 +169,7 @@
{
"source": "listmodel.h",
"target": "%{HdrPath}",
- "condition": "%{JS: '%{Base}' === 'QAbstractListModel'}",
+ "condition": "%{JS: value('Base') === 'QAbstractListModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
@@ -179,7 +179,7 @@
"source": "listmodel.cpp",
"target": "%{SrcPath}",
"openInEditor": true,
- "condition": "%{JS: '%{Base}' === 'QAbstractListModel'}",
+ "condition": "%{JS: value('Base') === 'QAbstractListModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
diff --git a/share/qtcreator/templates/wizards/classes/python/wizard.json b/share/qtcreator/templates/wizards/classes/python/wizard.json
index 6d1d72c63b..233a8bac7a 100644
--- a/share/qtcreator/templates/wizards/classes/python/wizard.json
+++ b/share/qtcreator/templates/wizards/classes/python/wizard.json
@@ -7,11 +7,11 @@
"trDisplayName": "Python Class",
"trDisplayCategory": "Python",
"icon": "../../files/python/icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('PythonEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('PythonEditor') >= 0}",
"options":
[
- { "key": "Base", "value":"%{JS: ( '%{BaseCB}' === '' ) ? '%{BaseEdit}' : '%{BaseCB}'}" },
+ { "key": "Base", "value":"%{JS: value('BaseCB') === '' ? value('BaseEdit') : value('BaseCB')}" },
{ "key": "Imports", "value": "%{ImportQtCore}%{ImportQtWidgets}%{ImportQtDeclarative}"}
],
@@ -52,7 +52,7 @@
{
"name": "BaseEdit",
"type": "LineEdit",
- "enabled": "%{JS: '%{BaseCB}' === ''}",
+ "enabled": "%{JS: value('BaseCB') === ''}",
"mandatory": false,
"data": { "trText": "%{BaseCB}" }
},
@@ -71,7 +71,7 @@
{
"checkedValue": "QtCore",
"uncheckedValue": "",
- "checked": "%{JS: '%{Base}' !== ''}"
+ "checked": "%{JS: value('Base') !== ''}"
}
},
{
@@ -82,7 +82,7 @@
{
"checkedValue": "QtWidgets",
"uncheckedValue": "",
- "checked": "%{JS: '%{Base}' === 'QWidget'}"
+ "checked": "%{JS: value('Base') === 'QWidget'}"
}
},
{
@@ -93,7 +93,7 @@
{
"checkedValue": "QtQuick",
"uncheckedValue": "",
- "checked": "%{JS: '%{Base}' === 'QQuickItem'}"
+ "checked": "%{JS: value('Base') === 'QQuickItem'}"
}
},
{
@@ -108,7 +108,7 @@
"type": "LineEdit",
"trDisplayName": "Source file:",
"mandatory": true,
- "data": { "trText": "%{JS: Util.fileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-python')}')}" }
+ "data": { "trText": "%{JS: Util.fileName(value('Class'), Util.preferredSuffix('text/x-python'))}" }
},
{
"name": "TargetPath",
@@ -117,7 +117,7 @@
"mandatory": true,
"data":
{
- "kind": "existingDirectory",
+ "kind": "directory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
diff --git a/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json b/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json
index a1d4338994..e8bd200d75 100644
--- a/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json
+++ b/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "Qt",
"iconText": "ui.qml",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.UiFiles" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlJSEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}",
"options" : [
{ "key": "QmlFile", "value": "%{Class}.%{JS: Util.preferredSuffix('text/x-qml')}" },
@@ -57,7 +57,7 @@
"mandatory": true,
"data":
{
- "kind": "existingDirectory",
+ "kind": "directory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
diff --git a/share/qtcreator/templates/wizards/files/cppheader/wizard.json b/share/qtcreator/templates/wizards/files/cppheader/wizard.json
index bda6770d09..efb0ea8119 100644
--- a/share/qtcreator/templates/wizards/files/cppheader/wizard.json
+++ b/share/qtcreator/templates/wizards/files/cppheader/wizard.json
@@ -7,9 +7,9 @@
"trDisplayName": "C++ Header File",
"trDisplayCategory": "C++",
"iconText": "h",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",
- "options": { "key": "FileName", "value": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" },
+ "options": { "key": "FileName", "value": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-c++hdr'))}" },
"pages" :
[
@@ -33,7 +33,7 @@
"source": "file.h",
"target": "%{FileName}",
"openInEditor": true,
- "options": { "key": "Cpp:License:FileName", "value": "%{JS: Util.fileName('%{FileName}')}" }
+ "options": { "key": "Cpp:License:FileName", "value": "%{JS: Util.fileName(value('FileName'))}" }
}
}
]
diff --git a/share/qtcreator/templates/wizards/files/cppsource/wizard.json b/share/qtcreator/templates/wizards/files/cppsource/wizard.json
index 7eebc282b5..775cd892ab 100644
--- a/share/qtcreator/templates/wizards/files/cppsource/wizard.json
+++ b/share/qtcreator/templates/wizards/files/cppsource/wizard.json
@@ -7,9 +7,9 @@
"trDisplayName": "C++ Source File",
"trDisplayCategory": "C++",
"iconText": "cpp",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",
- "options": { "key": "FileName", "value": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-c++src')}')}" },
+ "options": { "key": "FileName", "value": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-c++src'))}" },
"pages" :
[
@@ -33,7 +33,7 @@
"source": "file.cpp",
"target": "%{FileName}",
"openInEditor": true,
- "options": { "key": "Cpp:License:FileName", "value": "%{JS: Util.fileName('%{FileName}')}" }
+ "options": { "key": "Cpp:License:FileName", "value": "%{JS: Util.fileName(value('FileName'))}" }
}
}
]
diff --git a/share/qtcreator/templates/wizards/files/form/file.ui b/share/qtcreator/templates/wizards/files/form/file.ui
index d83113033f..1ee54204a8 100644
--- a/share/qtcreator/templates/wizards/files/form/file.ui
+++ b/share/qtcreator/templates/wizards/files/form/file.ui
@@ -1 +1 @@
-%{JS: [ %{FormContents} ].join('\n')}\
+%{FormContents}
diff --git a/share/qtcreator/templates/wizards/files/form/wizard.json b/share/qtcreator/templates/wizards/files/form/wizard.json
index 26d15d2b59..ec5fd422a3 100644
--- a/share/qtcreator/templates/wizards/files/form/wizard.json
+++ b/share/qtcreator/templates/wizards/files/form/wizard.json
@@ -7,12 +7,12 @@
"trDisplayName": "Qt Designer Form",
"trDisplayCategory": "Qt",
"iconText": "ui",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Designer') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Designer') >= 0}",
"options": [
- { "key": "UiClass", "value": "%{JS: QtSupport.uiClassName([ %{FormContents} ].join('\\n'))}" },
+ { "key": "UiClass", "value": "%{JS: QtSupport.uiClassName(value('FormContents'))}" },
{ "key": "Extension", "value": "%{JS: Util.preferredSuffix('application/x-designer')}"},
- { "key": "InitialFileName", "value": "%{JS: Cpp.classToFileName('%{UiClass}', '%{Extension}') }" }
+ { "key": "InitialFileName", "value": "%{JS: Cpp.classToFileName(value('UiClass'), value('Extension')) }" }
],
"pages":
@@ -41,7 +41,7 @@
"data":
{
"source": "file.ui",
- "target": "%{JS: Cpp.fileName('%{TargetPath}', '%{Extension}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), value('Extension'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json
index eb5e994782..900e4f8f68 100644
--- a/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json
+++ b/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "GLSL",
"iconText": "frag",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('GLSLEditor') >= 0}",
"pages" :
[
@@ -30,7 +30,7 @@
"data":
{
"source": "file.frag",
- "target": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-glsl-frag')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-glsl-frag'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json
index bd76a76d6b..38d2df2947 100644
--- a/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json
+++ b/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "GLSL",
"iconText": "vert",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('GLSLEditor') >= 0}",
"pages" :
[
@@ -30,7 +30,7 @@
"data":
{
"source": "file.vert",
- "target": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-glsl-vert')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-glsl-vert'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json
index c95b336aea..a993a3cfce 100644
--- a/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json
+++ b/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "GLSL",
"iconText": "fsh",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('GLSLEditor') >= 0}",
"pages" :
[
@@ -30,7 +30,7 @@
"data":
{
"source": "file.fsh",
- "target": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-glsl-es-frag')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-glsl-es-frag'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json
index 68d430d29d..54231aadd5 100644
--- a/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json
+++ b/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "GLSL",
"iconText": "vsh",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('GLSLEditor') >= 0}",
"pages" :
[
@@ -30,7 +30,7 @@
"data":
{
"source": "file.vsh",
- "target": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-glsl-es-vert')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-glsl-es-vert'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/java/wizard.json b/share/qtcreator/templates/wizards/files/java/wizard.json
index 427dc84e16..6341319c6b 100644
--- a/share/qtcreator/templates/wizards/files/java/wizard.json
+++ b/share/qtcreator/templates/wizards/files/java/wizard.json
@@ -7,9 +7,9 @@
"trDisplayName": "Java File",
"trDisplayCategory": "Java",
"iconText": "java",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Android') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Android') >= 0}",
- "options": [ { "key": "ClassName", "value": "%{JS: '%{FileName}'.charAt(0).toUpperCase() + '%{FileName}'.substr(1)}" } ],
+ "options": [ { "key": "ClassName", "value": "%{JS: value('FileName').charAt(0).toUpperCase() + value('FileName').substr(1).replace(/\\.java$/,'')}" } ],
"pages" :
[
@@ -31,7 +31,7 @@
"data":
{
"source": "source.java",
- "target": "%{JS: Util.fileName('%{Path}/%{ClassName}', '%{JS: Util.preferredSuffix('text/x-java')}')}",
+ "target": "%{JS: Util.fileName(value('Path') + '/' + value('ClassName'), Util.preferredSuffix('text/x-java'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/js/wizard.json b/share/qtcreator/templates/wizards/files/js/wizard.json
index 62d3211cda..d47721bb46 100644
--- a/share/qtcreator/templates/wizards/files/js/wizard.json
+++ b/share/qtcreator/templates/wizards/files/js/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "JS File",
"trDisplayCategory": "Qt",
"iconText": "js",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlJSEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}",
"pages" :
[
@@ -47,7 +47,7 @@
"data":
{
"source": "file.js",
- "target": "%{JS: Util.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('application/javascript')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('application/javascript'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/modeling/model/wizard.json b/share/qtcreator/templates/wizards/files/modeling/model/wizard.json
index 2f8cff689a..c971c8bf9d 100644
--- a/share/qtcreator/templates/wizards/files/modeling/model/wizard.json
+++ b/share/qtcreator/templates/wizards/files/modeling/model/wizard.json
@@ -8,12 +8,12 @@
"trDisplayCategory": "Modeling",
"iconText": "qmodel",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('ModelEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('ModelEditor') >= 0}",
"options":
[
- { "key": "TargetPath", "value": "%{JS: Util.fileName('%{Location}/%{FileName}', '%{JS: Util.preferredSuffix('text/vnd.qtcreator.model')}')}" },
- { "key": "FileName", "value": "%{JS: Modeling.elementNameToFileName('%{Name}')}" }
+ { "key": "TargetPath", "value": "%{JS: Util.fileName(value('Location') + '/' + value('FileName'), Util.preferredSuffix('text/vnd.qtcreator.model'))}" },
+ { "key": "FileName", "value": "%{JS: Modeling.elementNameToFileName(value('Name'))}" }
],
"pages" :
@@ -34,11 +34,11 @@
"name": "Location",
"trDisplayName": "Location:",
"type": "PathChooser",
- "isComplete": "%{JS: '%{Location}' === '' || !Util.exists('%{TargetPath}')}",
- "trIncompleteMessage": "\"%{JS: Util.toNativeSeparators('%{TargetPath}')}\" exists in the filesystem.",
+ "isComplete": "%{JS: value('Location') === '' || !Util.exists(value('TargetPath'))}",
+ "trIncompleteMessage": "\"%{JS: Util.toNativeSeparators(value('TargetPath'))}\" exists in the filesystem.",
"data":
{
- "kind": "existingDirectory",
+ "kind": "directory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
diff --git a/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json b/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json
index 71bad75ddf..8092ba6021 100644
--- a/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json
+++ b/share/qtcreator/templates/wizards/files/modeling/scratch/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "Modeling",
"iconText": "qmodel",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('ModelEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('ModelEditor') >= 0}",
"options": [ { "key": "TargetPath", "value": "%{JS: Util.mktemp('model-XXXXXX.qmodel')}" } ],
diff --git a/share/qtcreator/templates/wizards/files/nim/wizard.json b/share/qtcreator/templates/wizards/files/nim/wizard.json
index 953df6a847..723531ced5 100644
--- a/share/qtcreator/templates/wizards/files/nim/wizard.json
+++ b/share/qtcreator/templates/wizards/files/nim/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Nim File",
"trDisplayCategory": "Nim",
"icon": "../../projects/nim/icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}",
"pages" :
[
@@ -29,7 +29,7 @@
"data":
{
"source": "file.nim",
- "target": "%{JS: Util.fileName('%{TargetPath}', 'nim')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), 'nim')}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/nimscript/wizard.json b/share/qtcreator/templates/wizards/files/nimscript/wizard.json
index 62aba314cd..15f366773b 100644
--- a/share/qtcreator/templates/wizards/files/nimscript/wizard.json
+++ b/share/qtcreator/templates/wizards/files/nimscript/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Nim Script File",
"trDisplayCategory": "Nim",
"icon": "../../projects/nim/icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}",
"pages" :
[
@@ -29,7 +29,7 @@
"data":
{
"source": "file.nims",
- "target": "%{JS: Util.fileName('%{TargetPath}', 'nims')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), 'nims')}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/python/wizard.json b/share/qtcreator/templates/wizards/files/python/wizard.json
index d4a6cfd012..262de2d37b 100644
--- a/share/qtcreator/templates/wizards/files/python/wizard.json
+++ b/share/qtcreator/templates/wizards/files/python/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Python File",
"trDisplayCategory": "Python",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('PythonEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('PythonEditor') >= 0}",
"pages" :
[
@@ -29,7 +29,7 @@
"data":
{
"source": "file.py",
- "target": "%{JS: Util.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-python')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-python'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/qrc/wizard.json b/share/qtcreator/templates/wizards/files/qrc/wizard.json
index bbbd8e98f9..578eed58a1 100644
--- a/share/qtcreator/templates/wizards/files/qrc/wizard.json
+++ b/share/qtcreator/templates/wizards/files/qrc/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Qt Resource File",
"trDisplayCategory": "Qt",
"iconText": "qrc",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('ResourceEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('ResourceEditor') >= 0}",
"pages" :
[
@@ -29,7 +29,7 @@
"data":
{
"source": "file.qrc",
- "target": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('application/vnd.qt.xml.resource')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('application/vnd.qt.xml.resource'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json
index 544368b173..ead52b1687 100644
--- a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json
+++ b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "QML File (Qt Quick 2)",
"trDisplayCategory": "Qt",
"iconText": "qml",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlJSEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}",
"pages" :
[
@@ -29,7 +29,7 @@
"data":
{
"source": "file.qml.tpl",
- "target": "%{JS: Util.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-qml')}')}",
+ "target": "%{JS: Util.fileName(value('TargetPath'), Util.preferredSuffix('text/x-qml'))}",
"openInEditor": true
}
}
diff --git a/share/qtcreator/templates/wizards/files/scratch/wizard.json b/share/qtcreator/templates/wizards/files/scratch/wizard.json
index 6508db6aa3..aa0efb0e10 100644
--- a/share/qtcreator/templates/wizards/files/scratch/wizard.json
+++ b/share/qtcreator/templates/wizards/files/scratch/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Scratch Buffer",
"trDisplayCategory": "General",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('TextEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('TextEditor') >= 0}",
"options": [ { "key": "TargetPath", "value": "%{JS: Util.mktemp('scratch-XXXXXX.txt')}" } ],
diff --git a/share/qtcreator/templates/wizards/files/scxml/wizard.json b/share/qtcreator/templates/wizards/files/scxml/wizard.json
index 4e9e870637..36bbda7b71 100644
--- a/share/qtcreator/templates/wizards/files/scxml/wizard.json
+++ b/share/qtcreator/templates/wizards/files/scxml/wizard.json
@@ -8,11 +8,11 @@
"trDisplayCategory": "Modeling",
"iconText": "scxml",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('ScxmlEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('ScxmlEditor') >= 0}",
"options":
[
- { "key": "TargetPath", "value": "%{JS: Util.fileName('%{Location}/%{FileName}', '%{JS: Util.preferredSuffix('application/scxml+xml')}')}" },
+ { "key": "TargetPath", "value": "%{JS: Util.fileName(value('Location') + '/' + value('FileName'), Util.preferredSuffix('application/scxml+xml'))}" },
{ "key": "FileName", "value": "%{Name}" }
],
@@ -34,11 +34,11 @@
"name": "Location",
"trDisplayName": "Location:",
"type": "PathChooser",
- "isComplete": "%{JS: '%{Location}' === '' || !Util.exists('%{TargetPath}')}",
- "trIncompleteMessage": "\"%{JS: Util.toNativeSeparators('%{TargetPath}')}\" exists in the filesystem.",
+ "isComplete": "%{JS: value('Location') === '' || !Util.exists(value('TargetPath'))}",
+ "trIncompleteMessage": "\"%{JS: Util.toNativeSeparators(value('TargetPath'))}\" exists in the filesystem.",
"data":
{
- "kind": "existingDirectory",
+ "kind": "directory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
diff --git a/share/qtcreator/templates/wizards/files/text/wizard.json b/share/qtcreator/templates/wizards/files/text/wizard.json
index 11e0577a2d..b983401ef3 100644
--- a/share/qtcreator/templates/wizards/files/text/wizard.json
+++ b/share/qtcreator/templates/wizards/files/text/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "General",
"iconText": "txt",
"platformIndependent": true,
- "enabled": "%{JS: [ %{Plugins} ].indexOf('TextEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('TextEditor') >= 0}",
"pages" :
[
diff --git a/share/qtcreator/templates/wizards/global/lib.png b/share/qtcreator/templates/wizards/global/lib.png
new file mode 100644
index 0000000000..52cb73e382
--- /dev/null
+++ b/share/qtcreator/templates/wizards/global/lib.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/global/lib@2x.png b/share/qtcreator/templates/wizards/global/lib@2x.png
new file mode 100644
index 0000000000..c959779b02
--- /dev/null
+++ b/share/qtcreator/templates/wizards/global/lib@2x.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt
index 4beef640b7..ce63061d75 100644
--- a/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/consoleapp/CMakeLists.txt
@@ -1,12 +1,17 @@
-cmake_minimum_required(VERSION 3.0.0)
+cmake_minimum_required(VERSION 3.5)
-project(%{ProjectName} VERSION 0.1 LANGUAGES CXX)
+project(%{ProjectName} LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
-find_package(Qt5Core)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
-add_executable(${PROJECT_NAME} "%{CppFileName}")
+find_package(Qt5Core)
-target_link_libraries(${PROJECT_NAME} Qt5::Core)
+add_executable(%{ProjectName} %{CppFileName})
+target_link_libraries(%{ProjectName} Qt5::Core)
diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json b/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json
index b40d529169..bee602c87d 100644
--- a/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json
@@ -8,13 +8,13 @@
"trDisplayCategory": "Application",
"icon": "../../global/consoleapplication.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}",
"options":
[
- { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
- { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : (value('BuildSystem') === 'cmake' ? value('CMakeFile') : value('QbsFile'))}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "CppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" }
],
@@ -31,7 +31,7 @@
"trDisplayName": "Define Build System",
"trShortTitle": "Build System",
"typeId": "Fields",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data":
[
{
@@ -46,17 +46,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
@@ -67,7 +67,7 @@
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data": { "projectFilePath": "%{ProjectFile}" }
},
{
@@ -86,18 +86,18 @@
"source": "file.pro",
"target": "%{ProFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "CMakeLists.txt",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
},
{
"source": "file.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ "condition": "%{JS: value('BuildSystem') === 'qbs'}"
},
{
"source": "main.cpp",
@@ -107,7 +107,7 @@
{
"source": "../git.ignore",
"target": ".gitignore",
- "condition": "%{JS: ! %{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/cpplibrary/CMakeLists.txt
new file mode 100644
index 0000000000..243280b657
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/cpplibrary/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(%{ProjectName} LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+@if '%{QtModule}' != 'none'
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+@endif
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+@if '%{QtModule}' != 'none'
+
+find_package(Qt5 COMPONENTS %{QtModuleUpperCase} REQUIRED)
+@endif
+
+add_library(%{ProjectName} %{JS: %{IsStatic} ? 'STATIC' : 'SHARED'}
+@if '%{Type}' === 'shared'
+ %{GlobalHdrFileName}
+@endif
+ %{SrcFileName}
+ %{HdrFileName}
+@if %{IsQtPlugin}
+ %{PluginJsonFile}
+@endif
+)
+@if '%{QtModule}' != 'none'
+
+target_link_libraries(%{ProjectName} PRIVATE Qt5::%{QtModuleUpperCase})
+@endif
+@if '%{IsShared}'
+
+target_compile_definitions(%{ProjectName} PRIVATE %{LibraryDefine})
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/lib.cpp b/share/qtcreator/templates/wizards/projects/cpplibrary/lib.cpp
new file mode 100644
index 0000000000..6eb6c86faa
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/cpplibrary/lib.cpp
@@ -0,0 +1,17 @@
+%{Cpp:LicenseTemplate}\
+#include "%{JS: Util.relativeFilePath('%{Path}/%{HdrFileName}', '%{Path}' + '/' + Util.path('%{SrcFileName}'))}"
+%{JS: Cpp.openNamespaces('%{Class}')}\
+
+@if ! %{IsQtPlugin}
+%{CN}::%{CN}()
+{
+}
+@else
+%{CN}::%{CN}(QObject *parent)
+ : %{BaseClassName}(parent)
+{
+}
+%{JS: '%{PluginMethods}'.split('|').map(function(s) { return '\\n' + s.replace(/([a-zA-Z0-9]+\\()/, '%{CN}::$1') + '\\n\{\\n static_assert(false, "You need to implement this function");\\n\}'; \}).join('\\n')}\
+
+@endif
+%{JS: Cpp.closeNamespaces('%{Class}')}\
diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/lib.h b/share/qtcreator/templates/wizards/projects/cpplibrary/lib.h
new file mode 100644
index 0000000000..ae2c90a313
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/cpplibrary/lib.h
@@ -0,0 +1,46 @@
+%{Cpp:LicenseTemplate}\
+@if '%{Cpp:PragmaOnce}'
+#pragma once
+@else
+#ifndef %{GUARD}
+#define %{GUARD}
+@endif
+@if %{IsShared}
+
+#include "%{GlobalHdrFileName}"
+@elsif %{IsQtPlugin}
+
+#include <%{BaseClassName}>
+@endif
+%{JS: Cpp.openNamespaces('%{Class}')}\
+
+@if %{IsShared}
+class %{LibraryExport} %{CN}
+{
+public:
+ %{CN}();
+};
+@elsif %{IsStatic}
+class %{CN}
+{
+public:
+ %{CN}();
+};
+@else
+class %{CN} : public %{BaseClassName}
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.%{PluginInterface}" FILE "%{PluginJsonFile}")
+
+public:
+ explicit %{CN}(QObject *parent = nullptr);
+
+private:
+%{JS: '%{PluginMethods}'.split('|').map(function(s) { return ' ' + s + ' override;'; \}).join('\\n')}
+};
+@endif
+%{JS: Cpp.closeNamespaces('%{Class}')}\
+@if ! '%{Cpp:PragmaOnce}'
+
+#endif // %{GUARD}
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/lib_global.h b/share/qtcreator/templates/wizards/projects/cpplibrary/lib_global.h
new file mode 100644
index 0000000000..c665cf911c
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/cpplibrary/lib_global.h
@@ -0,0 +1,29 @@
+%{Cpp:LicenseTemplate}\
+@if '%{Cpp:PragmaOnce}'
+#pragma once
+@else
+#ifndef %{GLOBAL_GUARD}
+#define %{GLOBAL_GUARD}
+@endif
+
+@if '%{QtModule}' != 'none'
+#include <QtCore/qglobal.h>
+@else
+#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
+# define Q_DECL_EXPORT __declspec(dllexport)
+# define Q_DECL_IMPORT __declspec(dllimport)
+#else
+# define Q_DECL_EXPORT __attribute__((visibility("default")))
+# define Q_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+@endif
+
+#if defined(%{LibraryDefine})
+# define %{LibraryExport} Q_DECL_EXPORT
+#else
+# define %{LibraryExport} Q_DECL_IMPORT
+#endif
+@if ! '%{Cpp:PragmaOnce}'
+
+#endif // %{GLOBAL_GUARD}
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/project.json b/share/qtcreator/templates/wizards/projects/cpplibrary/project.json
new file mode 100644
index 0000000000..1e811388e4
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/cpplibrary/project.json
@@ -0,0 +1,3 @@
+{
+ "Keys" : [ ]
+}
diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/project.pro b/share/qtcreator/templates/wizards/projects/cpplibrary/project.pro
new file mode 100644
index 0000000000..431667ada5
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/cpplibrary/project.pro
@@ -0,0 +1,50 @@
+@if '%{QtModule}' === 'none'
+CONFIG -= qt
+@elsif '%{QtModule}' === 'core'
+QT -= gui
+@else
+QT += %{QtModule}
+@endif
+
+TEMPLATE = lib
+@if %{IsStatic}
+CONFIG += staticlib
+@elsif %{IsQtPlugin}
+CONFIG += plugin
+@elsif %{IsShared}
+DEFINES += %{LibraryDefine}
+@endif
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \\
+ %{SrcFileName}
+
+HEADERS += \\
+@if %{IsShared}
+ %{GlobalHdrFileName} \\
+@endif
+ %{HdrFileName}
+@if %{IsQtPlugin}
+
+DISTFILES += %{PluginJsonFile}
+@endif
+
+@if '%{TargetInstallPath}' != ''
+# Default rules for deployment.
+unix {
+ target.path = %{TargetInstallPath}
+}
+!isEmpty(target.path): INSTALLS += target
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json b/share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json
new file mode 100644
index 0000000000..af209105bf
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json
@@ -0,0 +1,326 @@
+{
+ "version": 1,
+ "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qt4ProjectManager.Qt4Project" ],
+ "id": "H.CppLibrary",
+ "category": "G.Library",
+ "trDescription": "Creates a C++ library. This can be used to create:<ul><li>a shared C++ library for use with <tt>QPluginLoader</tt> and runtime (Plugins)</li><li>a shared or static C++ library for use with another project at linktime</li></ul>",
+ "trDisplayName": "C++ Library",
+ "trDisplayCategory": "Library",
+ "icon": "../../global/lib.png",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0)}",
+
+ "options":
+ [
+ { "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": "PluginJsonFile", "value": "%{JS: Util.fileName(value('ProjectName'), 'json')}" },
+ { "key": "IsShared", "value": "%{JS: value('Type') === 'shared'}" },
+ { "key": "IsStatic", "value": "%{JS: value('Type') === 'static'}" },
+ { "key": "IsQtPlugin", "value": "%{JS: value('Type') === 'qtplugin'}" },
+ { "key": "BaseClassName", "value": "%{JS: value('BaseClassInfo').BaseClassName }" },
+ { "key": "PluginTargetPath", "value": "%{JS: value('BaseClassInfo').PluginTargetPath }" },
+ { "key": "PluginInterface", "value": "%{JS: value('BaseClassInfo').PluginInterface }" },
+ { "key": "PluginModule", "value": "%{JS: value('BaseClassInfo').PluginModule }" },
+ { "key": "PluginMethods", "value": "%{JS: value('BaseClassInfo').PluginMethods }" },
+ { "key": "QtModule", "value": "%{JS: value('IsQtPlugin') === 'true' ? value('PluginModule') : value('LibraryQtModule')}" },
+ { "key": "QtModuleUpperCase", "value": "%{JS: value('QtModule').charAt(0).toUpperCase() + value('QtModule').slice(1)}" },
+ { "key": "LibraryDefine", "value": "%{JS: Cpp.headerGuard(value('ProjectName')) + '_LIBRARY'}" },
+ { "key": "LibraryExport", "value": "%{JS: Cpp.headerGuard(value('ProjectName')) + '_EXPORT'}" },
+ { "key": "GlobalHdrFileName", "value": "%{JS: Util.fileName(value('ProjectName') + '_global', Util.preferredSuffix('text/x-c++hdr'))}" },
+ { "key": "TargetInstallPath", "value": "%{JS: value('IsShared') === 'true' ? '/usr/lib' : (value('IsQtPlugin') && value('PluginTargetPath') ? '$$[QT_INSTALL_PLUGINS]/' + value('PluginTargetPath') : '')}" },
+ { "key": "CN", "value": "%{JS: Cpp.className(value('Class'))}" },
+ { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('Class'), Util.suffix(value('HdrFileName')))}" },
+ { "key": "GLOBAL_GUARD", "value": "%{JS: Cpp.headerGuard(value('GlobalHdrFileName'))}" }
+ ],
+
+ "pages":
+ [
+ {
+ "trDisplayName": "Project Location",
+ "trShortTitle": "Location",
+ "typeId": "Project",
+ "data": { "trDescription": "This wizard creates a C++ library project." }
+ },
+ {
+ "trDisplayName": "Define Build System",
+ "trShortTitle": "Build System",
+ "typeId": "Fields",
+ "enabled": "%{JS: !value('IsSubproject')}",
+ "data":
+ [
+ {
+ "name": "BuildSystem",
+ "trDisplayName": "Build system:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Qmake",
+ "value": "qmake",
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "CMake",
+ "value": "cmake",
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Define Project Details",
+ "trShortTitle": "Details",
+ "typeId": "Fields",
+ "data":
+ [
+ {
+ "name": "ClassPageDescription",
+ "type": "Label",
+ "data":
+ {
+ "trText": "Specify basic information about the classes for which you want to generate skeleton source code files.",
+ "wordWrap": true
+ }
+ },
+ {
+ "name": "Type",
+ "trDisplayName": "Type:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Shared Library",
+ "value": "shared"
+ },
+ {
+ "trKey": "Statically Linked Library",
+ "value": "static"
+ },
+ {
+ "trKey": "Qt Plugin",
+ "value": "qtplugin"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Sp0",
+ "type": "Spacer"
+ },
+ {
+ "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('Type') === 'qtplugin' ? value('BaseClassName').slice(1) : (value('ProjectName').charAt(0).toUpperCase() + value('ProjectName').slice(1))}"
+ }
+ },
+ {
+ "name": "BaseClassInfo",
+ "trDisplayName": "Base class:",
+ "type": "ComboBox",
+ "visible": "%{JS: value('Type') === 'qtplugin'}",
+ "data":
+ {
+ "index": 1,
+ "items":
+ [
+ {
+ "trKey": "QAccessiblePlugin",
+ "value":
+ {
+ "BaseClassName": "QAccessiblePlugin",
+ "PluginTargetPath": "accessible",
+ "PluginInterface": "QAccessibleFactoryInterface",
+ "PluginModule": "gui",
+ "PluginMethods": "QAccessibleInterface *create(const QString &key, QObject *object)"
+ }
+ },
+ {
+ "trKey": "QGenericPlugin",
+ "value":
+ {
+ "BaseClassName": "QGenericPlugin",
+ "PluginTargetPath": "generic",
+ "PluginInterface": "QGenericPluginFactoryInterface",
+ "PluginModule": "gui",
+ "PluginMethods": "QObject *create(const QString &name, const QString &spec)"
+ }
+ },
+ {
+ "trKey": "QIconEnginePlugin",
+ "value":
+ {
+ "BaseClassName": "QIconEnginePlugin",
+ "PluginTargetPath": "imageformats",
+ "PluginInterface": "QIconEngineFactoryInterface",
+ "PluginModule": "gui",
+ "PluginMethods": "QIconEngine *create(const QString &filename)"
+ }
+ },
+ {
+ "trKey": "QImageIOPlugin",
+ "value":
+ {
+ "BaseClassName": "QImageIOPlugin",
+ "PluginTargetPath": "imageformats",
+ "PluginInterface": "QImageIOHandlerFactoryInterface",
+ "PluginModule": "gui",
+ "PluginMethods": "QImageIOPlugin::Capabilities capabilities(QIODevice *device, const QByteArray &format) const|QImageIOHandler *create(QIODevice *device, const QByteArray &format) const"
+ }
+ },
+ {
+ "trKey": "QScriptExtensionPlugin",
+ "value":
+ {
+ "BaseClassName": "QScriptExtensionPlugin",
+ "PluginTargetPath": "",
+ "PluginInterface": "QScriptExtensionInterface",
+ "PluginModule": "script",
+ "PluginMethods": "void initialize(const QString &key, QScriptEngine *engine)|QStringList keys() const"
+ }
+ },
+ {
+ "trKey": "QSqlDriverPlugin",
+ "value":
+ {
+ "BaseClassName": "QSqlDriverPlugin",
+ "PluginTargetPath": "sqldrivers",
+ "PluginInterface": "QSqlDriverFactoryInterface",
+ "PluginModule": "sql",
+ "PluginMethods": "QSqlDriver *create(const QString &key)"
+ }
+ },
+ {
+ "trKey": "QStylePlugin",
+ "value":
+ {
+ "BaseClassName": "QStylePlugin",
+ "PluginTargetPath": "styles",
+ "PluginInterface": "QStyleFactoryInterface",
+ "PluginModule": "widgets",
+ "PluginMethods": "QStyle *create(const QString &key)"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "LibraryQtModule",
+ "trDisplayName": "Qt module:",
+ "type": "ComboBox",
+ "visible": "%{JS: value('Type') != 'qtplugin'}",
+ "data":
+ {
+ "index": 1,
+ "items":
+ [
+ {
+ "trKey": "None",
+ "value": "none"
+ },
+ {
+ "trKey": "Core",
+ "value": "core"
+ },
+ {
+ "trKey": "Gui",
+ "value": "gui"
+ },
+ {
+ "trKey": "Widgets",
+ "value": "widgets"
+ }
+ ]
+ }
+ },
+ {
+ "name": "Sp1",
+ "type": "Spacer"
+ },
+ {
+ "name": "HdrFileName",
+ "type": "LineEdit",
+ "trDisplayName": "Header file:",
+ "mandatory": true,
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++hdr'))}" }
+ },
+ {
+ "name": "SrcFileName",
+ "type": "LineEdit",
+ "trDisplayName": "Source file:",
+ "mandatory": true,
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++src'))}" }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Kit Selection",
+ "trShortTitle": "Kits",
+ "typeId": "Kits",
+ "enabled": "%{JS: !value('IsSubproject')}",
+ "data": { "projectFilePath": "%{ProjectFile}" }
+ },
+ {
+ "trDisplayName": "Project Management",
+ "trShortTitle": "Summary",
+ "typeId": "Summary"
+ }
+ ],
+ "generators":
+ [
+ {
+ "typeId": "File",
+ "data":
+ [
+ {
+ "source": "project.pro",
+ "target": "%{ProFile}",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
+ },
+ {
+ "source": "CMakeLists.txt",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
+ },
+ {
+ "source": "lib.cpp",
+ "target": "%{SrcFileName}",
+ "openInEditor": true
+ },
+ {
+ "source": "lib.h",
+ "target": "%{HdrFileName}"
+ },
+ {
+ "source": "lib_global.h",
+ "target": "%{GlobalHdrFileName}",
+ "condition": "%{JS: value('Type') === 'shared'}"
+ },
+ {
+ "source": "project.json",
+ "target": "%{PluginJsonFile}",
+ "condition": "%{JS: value('Type') === 'qtplugin'}"
+ },
+ {
+ "source": "../git.ignore",
+ "target": ".gitignore",
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
+ }
+ ]
+ }
+ ]
+}
diff --git a/share/qtcreator/templates/wizards/projects/nim/wizard.json b/share/qtcreator/templates/wizards/projects/nim/wizard.json
index bd30370cd5..1239e444e9 100644
--- a/share/qtcreator/templates/wizards/projects/nim/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/nim/wizard.json
@@ -8,13 +8,13 @@
"trDisplayCategory": "Non-Qt Project",
"featuresRequired": [ "ToolChain.Nim.NimToolChain" ],
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0 }",
+ "enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0 }",
"options":
[
- { "key": "ProjectFile", "value": "%{JS: '%{NimProjectFile}'}" },
- { "key": "NimProjectFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'nimproject')}" },
- { "key": "NimFileName", "value": "%{JS: 'main.nim'}" }
+ { "key": "ProjectFile", "value": "%{NimProjectFile}" },
+ { "key": "NimProjectFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'nimproject')}" },
+ { "key": "NimFileName", "value": "main.nim" }
],
"pages":
@@ -28,7 +28,7 @@
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data": { "projectFilePath": "%{ProjectFile}" }
},
{
@@ -56,7 +56,7 @@
{
"source": "../git.ignore",
"target": "%{ProjectDirectory}/.gitignore",
- "condition": "%{JS: ! %{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt
index f4783c4195..5af2f09fb6 100644
--- a/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/plainc/CMakeLists.txt
@@ -1,4 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.5)
-project(%{ProjectName})
-add_executable(${PROJECT_NAME} "%{CFileName}")
+project(%{ProjectName} LANGUAGES C)
+
+add_executable(%{ProjectName} %{CFileName})
diff --git a/share/qtcreator/templates/wizards/projects/plainc/wizard.json b/share/qtcreator/templates/wizards/projects/plainc/wizard.json
index 56361be81d..66514cb9a7 100644
--- a/share/qtcreator/templates/wizards/projects/plainc/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/plainc/wizard.json
@@ -7,13 +7,13 @@
"trDisplayName": "Plain C Application",
"trDisplayCategory": "Non-Qt Project",
"icon": "../../global/consoleapplication.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0 && ([ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0)}",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0)}",
"options":
[
- { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
- { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : (value('BuildSystem') === 'cmake' ? value('CMakeFile') : value('QbsFile'))}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "CFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-csrc')}" }
],
@@ -29,7 +29,7 @@
"trDisplayName": "Define Build System",
"trShortTitle": "Build System",
"typeId": "Fields",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data":
[
{
@@ -44,17 +44,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
@@ -65,7 +65,7 @@
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data": { "projectFilePath": "%{ProjectFile}" }
},
{
@@ -84,18 +84,18 @@
"source": "file.pro",
"target": "%{ProFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "CMakeLists.txt",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
},
{
"source": "file.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ "condition": "%{JS: value('BuildSystem') === 'qbs'}"
},
{
"source": "main.c",
@@ -105,7 +105,7 @@
{
"source": "../git.ignore",
"target": ".gitignore",
- "condition": "%{JS: ! %{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt
index 6393118931..cdea69420e 100644
--- a/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/plaincpp/CMakeLists.txt
@@ -1,4 +1,8 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.5)
-project(%{ProjectName})
-add_executable(${PROJECT_NAME} "%{CppFileName}")
+project(%{ProjectName} LANGUAGES CXX)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+add_executable(%{ProjectName} %{CppFileName})
diff --git a/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json b/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json
index bf48c26108..af7e84362d 100644
--- a/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Plain C++ Application",
"trDisplayCategory": "Non-Qt Project",
"icon": "../../global/consoleapplication.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0 && ([ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0)}",
+ "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0)}",
"options":
[
@@ -44,17 +44,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins).indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json b/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json
index 3ae9c3ff55..84f019c222 100644
--- a/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json
@@ -8,11 +8,11 @@
"trDisplayCategory": "Other Project",
"icon": "../../../global/guiapplication.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}",
"options":
[
- { "key": "ProFileName", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "IsTopLevelProject", "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}'}" }
+ { "key": "ProFileName", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "IsTopLevelProject", "value": "%{JS: !value('Exists:ProjectExplorer.Profile.Ids')}" }
],
"pages":
@@ -51,7 +51,7 @@
{
"source": "../../git.ignore",
"target": "%{ProjectDirectory}/.gitignore",
- "condition": "%{JS: %{IsTopLevelProject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: value('IsTopLevelProject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json
index 16c2646ce5..6d734cb0e8 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/empty/wizard.json
@@ -7,12 +7,12 @@
"trDisplayName": "Qt for Python - Empty",
"trDisplayCategory": "Application",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('PythonEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('PythonEditor') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.6" ],
"options":
[
- { "key": "MainPyFileName", "value": "main.py" },
+ { "key": "SrcFileName", "value": "main.py" },
{ "key": "PyProjectFile", "value": "main.pyproject" }
],
@@ -42,7 +42,7 @@
},
{
"source": "../main_empty.py",
- "target": "%{MainPyFileName}",
+ "target": "%{SrcFileName}",
"openInEditor": true
}
]
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main.pyproject b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main.pyproject
index cc7a74a346..5c790aa745 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main.pyproject
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main.pyproject
@@ -1,3 +1,3 @@
{
- "files": ["main.py"]
+ "files": ["%{SrcFileName}"]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py
index fa1f92c747..9ec8b5d4e5 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/main_mainwindow.py
@@ -1,15 +1,39 @@
# This Python file uses the following encoding: utf-8
import sys
+@if '%{BaseCB}' === 'QWidget'
+from PySide2.QtWidgets import QApplication, QWidget
+@endif
+@if '%{BaseCB}' === 'QMainWindow'
from PySide2.QtWidgets import QApplication, QMainWindow
+@endif
+@if '%{BaseCB}' === ''
+from PySide2.QtWidgets import QApplication
+@endif
-class MainWindow(QMainWindow):
+@if '%{BaseCB}'
+class %{Class}(%{BaseCB}):
+@else
+class %{Class}:
+@endif
def __init__(self):
+@if '%{BaseCB}' === 'QWidget'
+ QWidget.__init__(self)
+@endif
+@if '%{BaseCB}' === 'QMainWindow'
QMainWindow.__init__(self)
+@endif
+@if '%{BaseCB}' === ''
+ pass # call __init__(self) of the custom base class here
+@endif
if __name__ == "__main__":
app = QApplication([])
- window = MainWindow()
+ window = %{Class}()
+@if '%{BaseCB}' === ''
+ # window.show()
+@else
window.show()
+@endif
sys.exit(app.exec_())
diff --git a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json
index c98ebb3ed4..c8e397d0d8 100644
--- a/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtforpythonapplication/mainwindow/wizard.json
@@ -7,13 +7,13 @@
"trDisplayName": "Qt for Python - Window",
"trDisplayCategory": "Application",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('PythonEditor') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('PythonEditor') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.6" ],
"options":
[
- { "key": "MainPyFileName", "value": "main.py" },
- { "key": "PyProjectFile", "value": "main.pyproject" }
+ { "key": "MainPyFileName", "value": "%{ProjectDirectory}/%{SrcFileName}" },
+ { "key": "PyProjectFile", "value": "%{ProjectDirectory}/%{ProjectFileName}" }
],
"pages":
@@ -21,7 +21,47 @@
{
"trDisplayName": "Project Location",
"trShortTitle": "Location",
- "typeId": "Project"
+ "typeId": "Project",
+ "name": "ProjectPath"
+ },
+ {
+ "trDisplayName": "Define Class",
+ "trShortTitle": "Details",
+ "typeId": "Fields",
+ "data" :
+ [
+ {
+ "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]*|)" }
+ },
+ {
+ "name": "BaseCB",
+ "trDisplayName": "Base class:",
+ "type": "ComboBox",
+ "data":
+ {
+ "items": [ { "trKey": "<Custom>", "value": "" },
+ "QWidget", "QMainWindow"]
+ }
+ },
+ {
+ "name": "SrcFileName",
+ "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: Cpp.classToFileName(value('Class'), 'pyproject')}" }
+ }
+ ]
},
{
"trDisplayName": "Project Management",
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
index f28d772a1a..165a32be3d 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/CMakeLists.txt
@@ -1,15 +1,36 @@
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.5)
project(%{ProjectName} LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
+
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Core Quick REQUIRED)
-add_executable(${PROJECT_NAME} "%{MainCppFileName}" "qml.qrc")
-target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
-target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick)
+if(ANDROID)
+ add_library(%{ProjectName} SHARED %{MainCppFileName} qml.qrc)
+else()
+ add_executable(%{ProjectName} %{MainCppFileName} qml.qrc)
+endif()
+
+target_compile_definitions(%{ProjectName}
+ PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
+target_link_libraries(%{ProjectName}
+ PRIVATE Qt5::Core Qt5::Quick)
+
+# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
+# Check http://doc.qt.io/qt-5/deployment-android.html for more information.
+# These variables must use CACHE, otherwise QtCreator won't see them.
+
+#if(ANDROID)
+# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android" CACHE INTERNAL "")
+# if (ANDROID_ABI STREQUAL "armeabi-v7a")
+# set(ANDROID_EXTRA_LIBS ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so CACHE INTERNAL "")
+# endif()
+#endif()
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/app.pro b/share/qtcreator/templates/wizards/projects/qtquickapplication/app.pro
index c979910fdd..0ac5682b11 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/app.pro
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/app.pro
@@ -1,4 +1,9 @@
+@if "%{UseVirtualKeyboard}" == "true"
+QT += quick virtualkeyboard
+@else
QT += quick
+@endif
+
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs b/share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs
index 76257178c6..d86ee9b454 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs
@@ -1,12 +1,16 @@
import qbs
-CppApplication {
+Application {
+@if "%{UseVirtualKeyboard}" == "true"
+ Depends { name: "Qt"; submodules: "quick", "virtualkeyboard" }
+@else
Depends { name: "Qt.quick" }
+@endif
// Additional import path used to resolve QML modules in Qt Creator's code model
property pathList qmlImportPaths: []
- cpp.cxxLanguageVersion: "c++11"
+ cpp.cxxLanguageVersion: "c++14"
cpp.defines: [
// The following define makes your compiler emit warnings if you use
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
index d26bec5ec6..329fc6c14a 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
@@ -8,20 +8,20 @@
"trDisplayCategory": "Application",
"icon": "icon.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.6" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}",
"options":
[
- { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
- { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : (value('BuildSystem') === 'cmake' ? value('CMakeFile') : value('QbsFile'))}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
- { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.QtQuickWindowVersion}" },
- { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
+ { "key": "QtQuickWindowVersion", "value": "%{JS: value('QtVersion').QtQuickWindowVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: value('QtVersion').QtQuickVirtualKeyboardImport}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
- { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0}" },
{ "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
],
@@ -36,7 +36,7 @@
"trDisplayName": "Define Build System",
"trShortTitle": "Build System",
"typeId": "Fields",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data":
[
{
@@ -51,17 +51,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
@@ -86,74 +86,74 @@
{
"trKey": "Qt 5.13",
"value":
- "({
- 'QtQuickVersion': '2.13',
- 'QtQuickWindowVersion': '2.13',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.13",
+ "QtQuickWindowVersion": "2.13",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.12",
"value":
- "({
- 'QtQuickVersion': '2.12',
- 'QtQuickWindowVersion': '2.12',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.12",
+ "QtQuickWindowVersion": "2.12",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.11",
"value":
- "({
- 'QtQuickVersion': '2.11',
- 'QtQuickWindowVersion': '2.11',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.11",
+ "QtQuickWindowVersion": "2.11",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.10",
"value":
- "({
- 'QtQuickVersion': '2.10',
- 'QtQuickWindowVersion': '2.10',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.10",
+ "QtQuickWindowVersion": "2.10",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.9",
"value":
- "({
- 'QtQuickVersion': '2.9',
- 'QtQuickWindowVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.2'
- })"
+ {
+ "QtQuickVersion": "2.9",
+ "QtQuickWindowVersion": "2.9",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.2"
+ }
},
{
"trKey": "Qt 5.8",
"value":
- "({
- 'QtQuickVersion': '2.8',
- 'QtQuickWindowVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.8",
+ "QtQuickWindowVersion": "2.8",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
},
{
"trKey": "Qt 5.7",
"value":
- "({
- 'QtQuickVersion': '2.7',
- 'QtQuickWindowVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.7",
+ "QtQuickWindowVersion": "2.7",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
},
{
"trKey": "Qt 5.6",
"value":
- "({
- 'QtQuickVersion': '2.6',
- 'QtQuickWindowVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 2.0'
- })"
+ {
+ "QtQuickVersion": "2.6",
+ "QtQuickWindowVersion": "2.6",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.0"
+ }
}
]
}
@@ -164,7 +164,7 @@
"type": "CheckBox",
"data":
{
- "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ "checked": "%{UseVirtualKeyboardByDefault}"
}
}
]
@@ -173,7 +173,7 @@
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data": {
"projectFilePath": "%{ProjectFile}",
"requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
@@ -195,19 +195,19 @@
"source": "../app.pro",
"target": "%{ProFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "../CMakeLists.txt",
"target": "CMakeLists.txt",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
},
{
"source": "../app.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ "condition": "%{JS: value('BuildSystem') === 'qbs'}"
},
{
"source": "../main.cpp",
@@ -224,7 +224,7 @@
{
"source": "../../git.ignore",
"target": ".gitignore",
- "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json
index 098456a431..f03b62635a 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json
@@ -8,22 +8,22 @@
"trDisplayCategory": "Application",
"icon": "icon.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.9" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}",
"options":
[
- { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
- { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : (value('BuildSystem') === 'cmake' ? value('CMakeFile') : value('QbsFile'))}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
- { "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.QtQuickControlsVersion}" },
- { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
- { "key": "QtQuickControlsStyle", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyle}" },
- { "key": "QtQuickControlsStyleTheme", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyleTheme}" },
+ { "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
+ { "key": "QtQuickControlsVersion", "value": "%{JS: value('QtVersion').QtQuickControlsVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: value('QtVersion').QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickControlsStyle", "value": "%{JS: value('ControlsStyle').QtQuickControlsStyle}" },
+ { "key": "QtQuickControlsStyleTheme", "value": "%{JS: value('ControlsStyle').QtQuickControlsStyleTheme}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
- { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0}" },
{ "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
],
@@ -38,7 +38,7 @@
"trDisplayName": "Define Build System",
"trShortTitle": "Build System",
"typeId": "Fields",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data":
[
{
@@ -53,17 +53,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
@@ -88,47 +88,47 @@
{
"trKey": "Qt 5.13",
"value":
- "({
- 'QtQuickVersion': '2.13',
- 'QtQuickControlsVersion': '2.13',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.13",
+ "QtQuickControlsVersion": "2.13",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.12",
"value":
- "({
- 'QtQuickVersion': '2.12',
- 'QtQuickControlsVersion': '2.5',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.12",
+ "QtQuickControlsVersion": "2.5",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.11",
"value":
- "({
- 'QtQuickVersion': '2.11',
- 'QtQuickControlsVersion': '2.4',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.11",
+ "QtQuickControlsVersion": "2.4",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.10",
"value":
- "({
- 'QtQuickVersion': '2.10',
- 'QtQuickControlsVersion': '2.3',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.10",
+ "QtQuickControlsVersion": "2.3",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.9",
"value":
- "({
- 'QtQuickVersion': '2.9',
- 'QtQuickControlsVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.2'
- })"
+ {
+ "QtQuickVersion": "2.9",
+ "QtQuickControlsVersion": "2.2",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.2"
+ }
}
]
}
@@ -145,66 +145,66 @@
{
"trKey": "Default",
"value":
- "({
- 'QtQuickControlsStyle': 'Default',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Default",
+ "QtQuickControlsStyleTheme": ""
+ }
},
{
"trKey": "Material Light",
"value":
- "({
- 'QtQuickControlsStyle': 'Material',
- 'QtQuickControlsStyleTheme': 'Light'
- })"
+ {
+ "QtQuickControlsStyle": "Material",
+ "QtQuickControlsStyleTheme": "Light"
+ }
},
{
"trKey": "Material Dark",
"value":
- "({
- 'QtQuickControlsStyle': 'Material',
- 'QtQuickControlsStyleTheme': 'Dark'
- })"
+ {
+ "QtQuickControlsStyle": "Material",
+ "QtQuickControlsStyleTheme": "Dark"
+ }
},
{
"trKey": "Universal Light",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'Light'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "Light"
+ }
},
{
"trKey": "Universal Dark",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'Dark'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "Dark"
+ }
},
{
"trKey": "Universal System",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'System'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "System"
+ }
},
{
"trKey": "Fusion (Qt 5.10+)",
"value":
- "({
- 'QtQuickControlsStyle': 'Fusion',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Fusion",
+ "QtQuickControlsStyleTheme": ""
+ }
},
{
"trKey": "Imagine (Qt 5.10+)",
"value":
- "({
- 'QtQuickControlsStyle': 'Imagine',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Imagine",
+ "QtQuickControlsStyleTheme": ""
+ }
}
]
}
@@ -215,7 +215,7 @@
"type": "CheckBox",
"data":
{
- "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ "checked": "%{UseVirtualKeyboardByDefault}"
}
}
]
@@ -224,7 +224,7 @@
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data": {
"projectFilePath": "%{ProjectFile}",
"requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
@@ -246,19 +246,19 @@
"source": "../app.pro",
"target": "%{ProFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "../CMakeLists.txt",
"target": "CMakeLists.txt",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
},
{
"source": "../app.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ "condition": "%{JS: value('BuildSystem') === 'qbs'}"
},
{
"source": "../main.cpp",
@@ -279,7 +279,7 @@
{
"source": "../../git.ignore",
"target": ".gitignore",
- "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
index 0b0f8558ac..6640901abe 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
@@ -8,22 +8,22 @@
"trDisplayCategory": "Application",
"icon": "icon.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.7" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}",
"options":
[
- { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
- { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : (value('BuildSystem') === 'cmake' ? value('CMakeFile') : value('QbsFile'))}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
- { "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.QtQuickControlsVersion}" },
- { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
- { "key": "QtQuickControlsStyle", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyle}" },
- { "key": "QtQuickControlsStyleTheme", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyleTheme}" },
+ { "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
+ { "key": "QtQuickControlsVersion", "value": "%{JS: value('QtVersion').QtQuickControlsVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: value('QtVersion').QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickControlsStyle", "value": "%{JS: value('ControlsStyle').QtQuickControlsStyle}" },
+ { "key": "QtQuickControlsStyleTheme", "value": "%{JS: value('ControlsStyle').QtQuickControlsStyleTheme}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
- { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0}" },
{ "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
],
@@ -38,7 +38,7 @@
"trDisplayName": "Define Build System",
"trShortTitle": "Build System",
"typeId": "Fields",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data":
[
{
@@ -53,17 +53,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
@@ -88,65 +88,65 @@
{
"trKey": "Qt 5.13",
"value":
- "({
- 'QtQuickVersion': '2.13',
- 'QtQuickControlsVersion': '2.13',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.13",
+ "QtQuickControlsVersion": "2.13",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.12",
"value":
- "({
- 'QtQuickVersion': '2.12',
- 'QtQuickControlsVersion': '2.5',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.12",
+ "QtQuickControlsVersion": "2.5",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.11",
"value":
- "({
- 'QtQuickVersion': '2.11',
- 'QtQuickControlsVersion': '2.4',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.11",
+ "QtQuickControlsVersion": "2.4",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.10",
"value":
- "({
- 'QtQuickVersion': '2.10',
- 'QtQuickControlsVersion': '2.3',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.10",
+ "QtQuickControlsVersion": "2.3",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.9",
"value":
- "({
- 'QtQuickVersion': '2.9',
- 'QtQuickControlsVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.2'
- })"
+ {
+ "QtQuickVersion": "2.9",
+ "QtQuickControlsVersion": "2.2",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.2"
+ }
},
{
"trKey": "Qt 5.8",
"value":
- "({
- 'QtQuickVersion': '2.8',
- 'QtQuickControlsVersion': '2.1',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.8",
+ "QtQuickControlsVersion": "2.1",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
},
{
"trKey": "Qt 5.7",
"value":
- "({
- 'QtQuickVersion': '2.7',
- 'QtQuickControlsVersion': '2.0',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.7",
+ "QtQuickControlsVersion": "2.0",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
}
]
}
@@ -163,66 +163,66 @@
{
"trKey": "Default",
"value":
- "({
- 'QtQuickControlsStyle': 'Default',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Default",
+ "QtQuickControlsStyleTheme": ""
+ }
},
{
"trKey": "Material Light",
"value":
- "({
- 'QtQuickControlsStyle': 'Material',
- 'QtQuickControlsStyleTheme': 'Light'
- })"
+ {
+ "QtQuickControlsStyle": "Material",
+ "QtQuickControlsStyleTheme": "Light"
+ }
},
{
"trKey": "Material Dark",
"value":
- "({
- 'QtQuickControlsStyle': 'Material',
- 'QtQuickControlsStyleTheme': 'Dark'
- })"
+ {
+ "QtQuickControlsStyle": "Material",
+ "QtQuickControlsStyleTheme": "Dark"
+ }
},
{
"trKey": "Universal Light",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'Light'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "Light"
+ }
},
{
"trKey": "Universal Dark",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'Dark'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "Dark"
+ }
},
{
"trKey": "Universal System",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'System'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "System"
+ }
},
{
"trKey": "Fusion (Qt 5.10+)",
"value":
- "({
- 'QtQuickControlsStyle': 'Fusion',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Fusion",
+ "QtQuickControlsStyleTheme": ""
+ }
},
{
"trKey": "Imagine (Qt 5.10+)",
"value":
- "({
- 'QtQuickControlsStyle': 'Imagine',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Imagine",
+ "QtQuickControlsStyleTheme": ""
+ }
}
]
}
@@ -233,7 +233,7 @@
"type": "CheckBox",
"data":
{
- "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ "checked": "%{UseVirtualKeyboardByDefault}"
}
}
]
@@ -242,7 +242,7 @@
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data": {
"projectFilePath": "%{ProjectFile}",
"requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
@@ -264,19 +264,19 @@
"source": "../app.pro",
"target": "%{ProFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "../CMakeLists.txt",
"target": "CMakeLists.txt",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
},
{
"source": "../app.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ "condition": "%{JS: value('BuildSystem') === 'qbs'}"
},
{
"source": "../main.cpp",
@@ -309,7 +309,7 @@
{
"source": "../../git.ignore",
"target": ".gitignore",
- "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json
index a89e6cce26..2b6ac53030 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json
@@ -8,22 +8,22 @@
"trDisplayCategory": "Application",
"icon": "icon.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.7" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}",
"options":
[
- { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
- { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : (value('BuildSystem') === 'cmake' ? value('CMakeFile') : value('QbsFile'))}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
- { "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.QtQuickControlsVersion}" },
- { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
- { "key": "QtQuickControlsStyle", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyle}" },
- { "key": "QtQuickControlsStyleTheme", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyleTheme}" },
+ { "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
+ { "key": "QtQuickControlsVersion", "value": "%{JS: value('QtVersion').QtQuickControlsVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: value('QtVersion').QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickControlsStyle", "value": "%{JS: value('ControlsStyle').QtQuickControlsStyle}" },
+ { "key": "QtQuickControlsStyleTheme", "value": "%{JS: value('ControlsStyle').QtQuickControlsStyleTheme}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
- { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0}" },
{ "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
],
@@ -38,7 +38,7 @@
"trDisplayName": "Define Build System",
"trShortTitle": "Build System",
"typeId": "Fields",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data":
[
{
@@ -53,17 +53,17 @@
{
"trKey": "qmake",
"value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "Qbs",
"value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
}
]
}
@@ -88,65 +88,65 @@
{
"trKey": "Qt 5.13",
"value":
- "({
- 'QtQuickVersion': '2.13',
- 'QtQuickControlsVersion': '2.13',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.13",
+ "QtQuickControlsVersion": "2.13",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.12",
"value":
- "({
- 'QtQuickVersion': '2.12',
- 'QtQuickControlsVersion': '2.5',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.12",
+ "QtQuickControlsVersion": "2.5",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.11",
"value":
- "({
- 'QtQuickVersion': '2.11',
- 'QtQuickControlsVersion': '2.4',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.11",
+ "QtQuickControlsVersion": "2.4",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.10",
"value":
- "({
- 'QtQuickVersion': '2.10',
- 'QtQuickControlsVersion': '2.3',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.10",
+ "QtQuickControlsVersion": "2.3",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.9",
"value":
- "({
- 'QtQuickVersion': '2.9',
- 'QtQuickControlsVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.2'
- })"
+ {
+ "QtQuickVersion": "2.9",
+ "QtQuickControlsVersion": "2.2",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.2"
+ }
},
{
"trKey": "Qt 5.8",
"value":
- "({
- 'QtQuickVersion': '2.8',
- 'QtQuickControlsVersion': '2.1',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.8",
+ "QtQuickControlsVersion": "2.1",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
},
{
"trKey": "Qt 5.7",
"value":
- "({
- 'QtQuickVersion': '2.7',
- 'QtQuickControlsVersion': '2.0',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.7",
+ "QtQuickControlsVersion": "2.0",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
}
]
}
@@ -163,66 +163,66 @@
{
"trKey": "Default",
"value":
- "({
- 'QtQuickControlsStyle': 'Default',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Default",
+ "QtQuickControlsStyleTheme": ""
+ }
},
{
"trKey": "Material Light",
"value":
- "({
- 'QtQuickControlsStyle': 'Material',
- 'QtQuickControlsStyleTheme': 'Light'
- })"
+ {
+ "QtQuickControlsStyle": "Material",
+ "QtQuickControlsStyleTheme": "Light"
+ }
},
{
"trKey": "Material Dark",
"value":
- "({
- 'QtQuickControlsStyle': 'Material',
- 'QtQuickControlsStyleTheme': 'Dark'
- })"
+ {
+ "QtQuickControlsStyle": "Material",
+ "QtQuickControlsStyleTheme": "Dark"
+ }
},
{
"trKey": "Universal Light",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'Light'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "Light"
+ }
},
{
"trKey": "Universal Dark",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'Dark'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "Dark"
+ }
},
{
"trKey": "Universal System",
"value":
- "({
- 'QtQuickControlsStyle': 'Universal',
- 'QtQuickControlsStyleTheme': 'System'
- })"
+ {
+ "QtQuickControlsStyle": "Universal",
+ "QtQuickControlsStyleTheme": "System"
+ }
},
{
"trKey": "Fusion (Qt 5.10+)",
"value":
- "({
- 'QtQuickControlsStyle': 'Fusion',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Fusion",
+ "QtQuickControlsStyleTheme": ""
+ }
},
{
"trKey": "Imagine (Qt 5.10+)",
"value":
- "({
- 'QtQuickControlsStyle': 'Imagine',
- 'QtQuickControlsStyleTheme': ''
- })"
+ {
+ "QtQuickControlsStyle": "Imagine",
+ "QtQuickControlsStyleTheme": ""
+ }
}
]
}
@@ -233,7 +233,7 @@
"type": "CheckBox",
"data":
{
- "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ "checked": "%{UseVirtualKeyboardByDefault}"
}
}
]
@@ -242,7 +242,7 @@
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
+ "enabled": "%{JS: !value('IsSubproject')}",
"data": {
"projectFilePath": "%{ProjectFile}",
"requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
@@ -264,19 +264,19 @@
"source": "../app.pro",
"target": "%{ProFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "../CMakeLists.txt",
"target": "CMakeLists.txt",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
},
{
"source": "../app.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ "condition": "%{JS: value('BuildSystem') === 'qbs'}"
},
{
"source": "../main.cpp",
@@ -305,7 +305,7 @@
{
"source": "../../git.ignore",
"target": ".gitignore",
- "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
index 8a726cc09c..79900ca557 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
@@ -7,18 +7,18 @@
"trDisplayName": "Qt Quick UI Prototype",
"trDisplayCategory": "Other Project",
"icon": "qtquickuiprototype.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],
"options":
[
- { "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qmlproject')}" },
- { "key": "MainQmlFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qml')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
- { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.QtQuickWindowVersion}" },
- { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
+ { "key": "QmlProjectFileName", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qmlproject')}" },
+ { "key": "MainQmlFileName", "value": "%{JS: Util.fileName(value('ProjectName'), 'qml')}" },
+ { "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
+ { "key": "QtQuickWindowVersion", "value": "%{JS: value('QtVersion').QtQuickWindowVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: value('QtVersion').QtQuickVirtualKeyboardImport}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
- { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" }
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: value('Plugins').indexOf('Boot2Qt') >= 0 || value('Plugins').indexOf('Boot2QtQdb') >= 0}" }
],
"pages":
@@ -46,74 +46,74 @@
{
"trKey": "Qt 5.13",
"value":
- "({
- 'QtQuickVersion': '2.13',
- 'QtQuickWindowVersion': '2.13',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.13",
+ "QtQuickWindowVersion": "2.13",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.12",
"value":
- "({
- 'QtQuickVersion': '2.12',
- 'QtQuickWindowVersion': '2.12',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.4'
- })"
+ {
+ "QtQuickVersion": "2.12",
+ "QtQuickWindowVersion": "2.12",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
+ }
},
{
"trKey": "Qt 5.11",
"value":
- "({
- 'QtQuickVersion': '2.11',
- 'QtQuickWindowVersion': '2.11',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.11",
+ "QtQuickWindowVersion": "2.11",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.10",
"value":
- "({
- 'QtQuickVersion': '2.10',
- 'QtQuickWindowVersion': '2.10',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.3'
- })"
+ {
+ "QtQuickVersion": "2.10",
+ "QtQuickWindowVersion": "2.10",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.3"
+ }
},
{
"trKey": "Qt 5.9",
"value":
- "({
- 'QtQuickVersion': '2.9',
- 'QtQuickWindowVersion': '2.3',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.2'
- })"
+ {
+ "QtQuickVersion": "2.9",
+ "QtQuickWindowVersion": "2.9",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.2"
+ }
},
{
"trKey": "Qt 5.8",
"value":
- "({
- 'QtQuickVersion': '2.8',
- 'QtQuickWindowVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.8",
+ "QtQuickWindowVersion": "2.8",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
},
{
"trKey": "Qt 5.7",
"value":
- "({
- 'QtQuickVersion': '2.7',
- 'QtQuickWindowVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
- })"
+ {
+ "QtQuickVersion": "2.7",
+ "QtQuickWindowVersion": "2.7",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.1"
+ }
},
{
"trKey": "Qt 5.6",
"value":
- "({
- 'QtQuickVersion': '2.6',
- 'QtQuickWindowVersion': '2.2',
- 'QtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 2.0'
- })"
+ {
+ "QtQuickVersion": "2.6",
+ "QtQuickWindowVersion": "2.6",
+ "QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.0"
+ }
}
]
}
@@ -124,7 +124,7 @@
"type": "CheckBox",
"data":
{
- "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ "checked": "%{UseVirtualKeyboardByDefault}"
}
}
]
@@ -164,7 +164,7 @@
{
"source": "../git.ignore",
"target": "%{ProjectDirectory}/.gitignore",
- "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
new file mode 100644
index 0000000000..5fd51e9014
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(%{ProjectName} LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(Qt5 COMPONENTS Widgets REQUIRED)
+
+add_executable(%{ProjectName}
+ %{MainFileName}
+ %{SrcFileName}
+ %{HdrFileName}
+@if %{GenerateForm}
+ %{FormFileName}
+@endif
+)
+
+target_link_libraries(%{ProjectName} PRIVATE Qt5::Widgets)
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/main.cpp
new file mode 100644
index 0000000000..5c64f1d05e
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/main.cpp
@@ -0,0 +1,12 @@
+%{Cpp:LicenseTemplate}\
+#include "%{HdrFileName}"
+
+%{JS: QtSupport.qtIncludes([ 'QtGui/QApplication' ], [ 'QtWidgets/QApplication' ]) }\
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ %{Class} w;
+ w.show();
+ return a.exec();
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.pro b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.pro
new file mode 100644
index 0000000000..a5362aa9bc
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.pro
@@ -0,0 +1,33 @@
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \\
+ %{MainFileName} \\
+ %{SrcFileName}
+
+HEADERS += \\
+ %{HdrFileName}
+@if %{GenerateForm}
+
+FORMS += \\
+ %{FormFileName}
+@endif
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.qbs b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.qbs
new file mode 100644
index 0000000000..4a54380d6b
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/project.qbs
@@ -0,0 +1,29 @@
+import qbs.FileInfo
+
+QtApplication {
+ Depends { name: "Qt.widgets" }
+
+ // The following define makes your compiler emit warnings if you use
+ // any Qt feature that has been marked deprecated (the exact warnings
+ // depend on your compiler). Please consult the documentation of the
+ // deprecated API in order to know how to port your code away from it.
+ // You can also make your code fail to compile if it uses deprecated APIs.
+ // In order to do so, uncomment the second entry in the list.
+ // You can also select to disable deprecated APIs only up to a certain version of Qt.
+ cpp.defines: [
+ "QT_DEPRECATED_WARNINGS",
+ /* "QT_DISABLE_DEPRECATED_BEFORE=0x060000" */ // disables all the APIs deprecated before Qt 6.0.0
+ ]
+
+ files: [
+ "%{MainFileName}",
+ "%{SrcFileName}",
+ "%{HdrFileName}",
+ @if %{GenerateForm}
+ "%{FormFileName}",
+ @endif
+ ]
+
+ install: true
+ installDir: qbs.targetOS.contains("qnx") ? FileInfo.joinPaths("/tmp", name, "bin") : base
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.cpp b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.cpp
new file mode 100644
index 0000000000..356e2444f6
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.cpp
@@ -0,0 +1,26 @@
+%{Cpp:LicenseTemplate}\
+#include "%{JS: Util.relativeFilePath('%{Path}/%{HdrFileName}', '%{Path}' + '/' + Util.path('%{SrcFileName}'))}"
+@if %{GenerateForm}
+#include "%{UiHdrFileName}"
+@endif
+%{JS: Cpp.openNamespaces('%{Class}')}\
+
+%{CN}::%{CN}(QWidget *parent)
+ : %{BaseClass}(parent)
+@if %{GenerateForm}
+ , ui(new Ui::%{CN})
+@endif
+{
+@if %{GenerateForm}
+ ui->setupUi(this);
+@endif
+}
+
+%{CN}::~%{CN}()
+{
+@if %{GenerateForm}
+ delete ui;
+@endif
+}
+
+%{JS: Cpp.closeNamespaces('%{Class}')}\
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.h b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.h
new file mode 100644
index 0000000000..dca6171267
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.h
@@ -0,0 +1,38 @@
+%{Cpp:LicenseTemplate}\
+@if '%{Cpp:PragmaOnce}'
+#pragma once
+@else
+#ifndef %{GUARD}
+#define %{GUARD}
+@endif
+
+%{JS: QtSupport.qtIncludes([ 'QtGui/%{BaseClass}' ], [ 'QtWidgets/%{BaseClass}' ]) }\
+%{JS: Cpp.openNamespaces('%{Class}')}\
+@if %{GenerateForm}
+
+@if ! %{JS: Cpp.hasNamespaces('%{Class}')}
+QT_BEGIN_NAMESPACE
+@endif
+namespace Ui { class %{CN}; }
+@if ! %{JS: Cpp.hasNamespaces('%{Class}')}
+QT_END_NAMESPACE
+@endif
+@endif
+
+class %{CN} : public %{BaseClass}
+{
+ Q_OBJECT
+
+public:
+ %{CN}(QWidget *parent = nullptr);
+ ~%{CN}();
+@if %{GenerateForm}
+
+private:
+ Ui::%{CN} *ui;
+@endif
+};
+%{JS: Cpp.closeNamespaces('%{Class}')}\
+@if ! '%{Cpp:PragmaOnce}'
+#endif // %{GUARD}
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.ui b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.ui
new file mode 100644
index 0000000000..1b21b83109
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/widget.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>%{Class}</class>
+ <widget class="%{BaseClass}" name="%{Class}">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>%{CN}</string>
+ </property>
+@if '%{BaseClass}' === 'QMainWindow'
+ <widget class="QWidget" name="centralwidget"/>
+ <widget class="QMenuBar" name="menubar"/>
+ <widget class="QStatusBar" name="statusbar"/>
+@endif
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json
new file mode 100644
index 0000000000..9cce84a413
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json
@@ -0,0 +1,204 @@
+{
+ "version": 1,
+ "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qt4ProjectManager.Qt4Project", "Qbs.QbsProject" ],
+ "id": "C.QtWidgets",
+ "category": "F.Application",
+ "trDescription": "Creates a Qt application for the desktop. Includes a Qt Designer-based main window.\n\nPreselects a desktop Qt for building the application if available.",
+ "trDisplayName": "Qt Widgets Application",
+ "trDisplayCategory": "Application",
+ "icon": "../../global/guiapplication.png",
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
+ "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0}",
+
+ "options":
+ [
+ { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : value('BuildSystem') === 'cmake' ? value('CMakeFile') : value('QbsFile')}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
+ { "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'qbs')}" },
+ { "key": "MainFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
+ { "key": "UiHdrFileName", "value": "%{JS: (value('BuildSystem') === 'cmake' ? (Util.path(value('FormFileName')) + '/') : '') + 'ui_' + Util.completeBaseName(value('FormFileName')) + '.h'}" },
+ { "key": "CN", "value": "%{JS: Cpp.className(value('Class'))}" },
+ { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('Class'), Util.suffix(value('HdrFileName')))}" }
+ ],
+
+ "pages":
+ [
+ {
+ "trDisplayName": "Project Location",
+ "trShortTitle": "Location",
+ "typeId": "Project",
+ "data": { "trDescription": "This wizard generates a Qt Widgets Application project. The application derives by default from QApplication and includes an empty widget." }
+ },
+ {
+ "trDisplayName": "Define Build System",
+ "trShortTitle": "Build System",
+ "typeId": "Fields",
+ "enabled": "%{JS: !value('IsSubproject')}",
+ "data":
+ [
+ {
+ "name": "BuildSystem",
+ "trDisplayName": "Build system:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "qmake",
+ "value": "qmake",
+ "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "CMake",
+ "value": "cmake",
+ "condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "Qbs",
+ "value": "qbs",
+ "condition": "%{JS: value('Plugins').indexOf('QbsProjectManager') >= 0}"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Class Information",
+ "trShortTitle": "Details",
+ "typeId": "Fields",
+ "data":
+ [
+ {
+ "name": "ClassPageDescription",
+ "type": "Label",
+ "data":
+ {
+ "trText": "Specify basic information about the classes for which you want to generate skeleton source code files.",
+ "wordWrap": true
+ }
+ },
+ {
+ "name": "Sp0",
+ "type": "Spacer"
+ },
+ {
+ "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('BaseClass') ? value('BaseClass').slice(1) : 'MyClass'}"
+ }
+ },
+ {
+ "name": "BaseClass",
+ "trDisplayName": "Base class:",
+ "type": "ComboBox",
+ "data":
+ {
+ "items": [ "QMainWindow", "QWidget", "QDialog" ]
+ }
+ },
+ {
+ "name": "Sp1",
+ "type": "Spacer"
+ },
+ {
+ "name": "HdrFileName",
+ "type": "LineEdit",
+ "trDisplayName": "Header file:",
+ "mandatory": true,
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++hdr'))}" }
+ },
+ {
+ "name": "SrcFileName",
+ "type": "LineEdit",
+ "trDisplayName": "Source file:",
+ "mandatory": true,
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++src'))}" }
+ },
+ {
+ "name": "GenerateForm",
+ "type": "CheckBox",
+ "trDisplayName": "Generate form",
+ "data": { "checked": true }
+ },
+ {
+ "name": "FormFileName",
+ "type": "LineEdit",
+ "trDisplayName": "Form file:",
+ "enabled": "%{GenerateForm}",
+ "mandatory": true,
+ "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), 'ui')}" }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Kit Selection",
+ "trShortTitle": "Kits",
+ "typeId": "Kits",
+ "enabled": "%{JS: !value('IsSubproject')}",
+ "data": { "projectFilePath": "%{ProjectFile}" }
+ },
+ {
+ "trDisplayName": "Project Management",
+ "trShortTitle": "Summary",
+ "typeId": "Summary"
+ }
+ ],
+ "generators":
+ [
+ {
+ "typeId": "File",
+ "data":
+ [
+ {
+ "source": "project.pro",
+ "target": "%{ProFile}",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'qmake'}"
+ },
+ {
+ "source": "CMakeLists.txt",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'cmake'}"
+ },
+ {
+ "source": "project.qbs",
+ "target": "%{QbsFile}",
+ "openAsProject": true,
+ "condition": "%{JS: value('BuildSystem') === 'qbs'}"
+ },
+ {
+ "source": "main.cpp",
+ "target": "%{MainFileName}",
+ "openInEditor": true
+ },
+ {
+ "source": "widget.cpp",
+ "target": "%{SrcFileName}"
+ },
+ {
+ "source": "widget.h",
+ "target": "%{HdrFileName}"
+ },
+ {
+ "source": "widget.ui",
+ "target": "%{FormFileName}",
+ "condition": "%{GenerateForm}"
+ },
+ {
+ "source": "../git.ignore",
+ "target": ".gitignore",
+ "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
+ }
+ ]
+ }
+ ]
+}
diff --git a/share/qtcreator/templates/wizards/projects/vcs/bazaar/wizard.json b/share/qtcreator/templates/wizards/projects/vcs/bazaar/wizard.json
index 9e4d494f45..a8b4d041e7 100644
--- a/share/qtcreator/templates/wizards/projects/vcs/bazaar/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/vcs/bazaar/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Bazaar Clone (Or Branch)",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Bazaar') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Bazaar') >= 0}",
"options":
[
diff --git a/share/qtcreator/templates/wizards/projects/vcs/cvs/wizard.json b/share/qtcreator/templates/wizards/projects/vcs/cvs/wizard.json
index 15dc344567..10969e3da8 100644
--- a/share/qtcreator/templates/wizards/projects/vcs/cvs/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/vcs/cvs/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "CVS Checkout",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('CVS') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('CVS') >= 0}",
"options":
[
diff --git a/share/qtcreator/templates/wizards/projects/vcs/git/wizard.json b/share/qtcreator/templates/wizards/projects/vcs/git/wizard.json
index be1cd42904..c97698612b 100644
--- a/share/qtcreator/templates/wizards/projects/vcs/git/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/vcs/git/wizard.json
@@ -7,13 +7,13 @@
"trDisplayName": "Git Clone",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Git') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Git') >= 0}",
"options":
[
{ "key": "vcsId", "value": "G.Git" },
{ "key": "vcsName", "value": "%{JS: Vcs.displayName('%{vcsId}')}" },
- { "key": "SR", "value": "%{JS: '%{Repo}'.replace(/\.git$/, '') }"},
+ { "key": "SR", "value": "%{JS: '%{Repo}'.replace(/\\.git$/, '') }"},
{ "key": "defaultDir", "value": "%{JS: '%{SR}'.substr('%{SR}'.lastIndexOf('/') + 1).replace(/\\./, '-') }"},
{ "key": "branchArg", "value": "%{JS: '%{Branch}' ? '--branch' : '' }" },
{ "key": "TargetPath", "value": "%{Path}/%{Dir}" }
diff --git a/share/qtcreator/templates/wizards/projects/vcs/mercurial/wizard.json b/share/qtcreator/templates/wizards/projects/vcs/mercurial/wizard.json
index 9fe95ba049..75bd410861 100644
--- a/share/qtcreator/templates/wizards/projects/vcs/mercurial/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/vcs/mercurial/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Mercurial Clone",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Mercurial') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Mercurial') >= 0}",
"options":
[
diff --git a/share/qtcreator/templates/wizards/projects/vcs/subversion/wizard.json b/share/qtcreator/templates/wizards/projects/vcs/subversion/wizard.json
index 7048c37dd6..aef8a28b9a 100644
--- a/share/qtcreator/templates/wizards/projects/vcs/subversion/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/vcs/subversion/wizard.json
@@ -7,7 +7,7 @@
"trDisplayName": "Subversion Checkout",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
- "enabled": "%{JS: [ %{Plugins} ].indexOf('Subversion') >= 0}",
+ "enabled": "%{JS: value('Plugins').indexOf('Subversion') >= 0}",
"options":
[
diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h
index 47a7b2e743..1342090ac7 100644
--- a/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h
+++ b/share/qtcreator/templates/wizards/qtcreatorplugin/myplugin.h
@@ -19,11 +19,11 @@ class %PluginName%Plugin : public ExtensionSystem::IPlugin
public:
%PluginName%Plugin();
- ~%PluginName%Plugin();
+ ~%PluginName%Plugin() override;
- bool initialize(const QStringList &arguments, QString *errorString);
- void extensionsInitialized();
- ShutdownFlag aboutToShutdown();
+ bool initialize(const QStringList &arguments, QString *errorString) override;
+ void extensionsInitialized() override;
+ ShutdownFlag aboutToShutdown() override;
private:
void triggerAction();
diff --git a/share/qtcreator/templates/wizards/qtquick2-extension/object.h b/share/qtcreator/templates/wizards/qtquick2-extension/object.h
index 72b47b9bf3..cabd5229db 100644
--- a/share/qtcreator/templates/wizards/qtquick2-extension/object.h
+++ b/share/qtcreator/templates/wizards/qtquick2-extension/object.h
@@ -13,8 +13,8 @@ class %ObjectName% : public QQuickItem
Q_DISABLE_COPY(%ObjectName%)
public:
- %ObjectName%(QQuickItem *parent = nullptr);
- ~%ObjectName%();
+ explicit %ObjectName%(QQuickItem *parent = nullptr);
+ ~%ObjectName%() override;
};
@if ! '%{Cpp:PragmaOnce}'
diff --git a/share/qtcreator/translations/extract-mimetypes.xq b/share/qtcreator/translations/extract-mimetypes.xq
deleted file mode 100644
index 181d99d499..0000000000
--- a/share/qtcreator/translations/extract-mimetypes.xq
+++ /dev/null
@@ -1,5 +0,0 @@
-let $prefix := string("QT_TRANSLATE_NOOP(&quot;MimeType&quot;, &quot;")
-let $suffix := concat("&quot;)", codepoints-to-string(10))
-for $file in tokenize($files, string("\|"))
- for $comment in doc($file)/*:mime-info/*:mime-type/*:comment
- return fn:concat($prefix, data($comment), $suffix)
diff --git a/share/qtcreator/translations/extract-qmlwizards.xq b/share/qtcreator/translations/extract-qmlwizards.xq
deleted file mode 100644
index 9d6d8c0abe..0000000000
--- a/share/qtcreator/translations/extract-qmlwizards.xq
+++ /dev/null
@@ -1,6 +0,0 @@
-let $prefix := string("QT_TRANSLATE_NOOP(&quot;QmlProjectManager::QmlApplicationWizard&quot;, &quot;")
-let $suffix := concat("&quot;)", codepoints-to-string(10))
-for $file in tokenize($files, string("\|"))
- let $doc := doc($file)
- for $text in ($doc/*:template/*:description, $doc/*:template/*:displayname)
- return fn:concat($prefix, data($text), $suffix)
diff --git a/share/qtcreator/translations/extract-qtquickwizards.xq b/share/qtcreator/translations/extract-qtquickwizards.xq
deleted file mode 100644
index cbe3a3be74..0000000000
--- a/share/qtcreator/translations/extract-qtquickwizards.xq
+++ /dev/null
@@ -1,6 +0,0 @@
-let $prefix := string("QT_TRANSLATE_NOOP(&quot;QmakeProjectManager::QtQuickAppWizard&quot;, &quot;")
-let $suffix := concat("&quot;)", codepoints-to-string(10))
-for $file in tokenize($files, string("\|"))
- let $doc := doc($file)
- for $text in ($doc/*:template/*:description, $doc/*:template/*:displayname)
- return fn:concat($prefix, data($text), $suffix)
diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts
index 62cb96a0b5..3983269a68 100644
--- a/share/qtcreator/translations/qtcreator_ru.ts
+++ b/share/qtcreator/translations/qtcreator_ru.ts
@@ -8669,7 +8669,7 @@ Do you want to kill it?</source>
</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; Файл &gt; Открыть файл или проект (%1)&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; Файл &gt; Недавние файлы&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; Инструменты &gt; Найти (%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;space&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; Перетащите файлы сюда&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</translation>
+ <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; Файл &gt; Открыть файл или проект (%1)&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; Файл &gt; Недавние файлы&lt;/div&gt;&lt;div style=&quot;margin-top: 5px&quot;&gt;&amp;bull; Инструменты &gt; Найти (%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; Перетащите файлы сюда&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<source>&lt;div style=&quot;margin-left: 1em&quot;&gt;- type &lt;code&gt;%1&amp;lt;space&amp;gt;&amp;lt;pattern&amp;gt;&lt;/code&gt; to jump to a class definition&lt;/div&gt;</source>
diff --git a/share/qtcreator/translations/translations.pro b/share/qtcreator/translations/translations.pro
index 0df2d53ad4..fff62c3f3d 100644
--- a/share/qtcreator/translations/translations.pro
+++ b/share/qtcreator/translations/translations.pro
@@ -3,7 +3,7 @@ TEMPLATE = aux
include(../../../qtcreator.pri)
LANGUAGES = cs da de fr ja pl ru sl uk zh_CN zh_TW
-# *don't* re-enable these without a prior rework
+# *do not* re-enable these without a prior rework
BAD_LANGUAGES = hu
# var, prepend, append
@@ -21,11 +21,8 @@ wd = $$replace(IDE_SOURCE_TREE, /, $$QMAKE_DIR_SEP)
TRANSLATIONS = $$prependAll(LANGUAGES, $$PWD/qtcreator_,.ts)
-MIME_TR_H = $$OUT_PWD/mime_tr.h
CUSTOMWIZARD_TR_H = $$OUT_PWD/customwizard_tr.h
JSONWIZARD_TR_H = $$OUT_PWD/jsonwizard_tr.h
-QMLWIZARD_TR_H = $$OUT_PWD/qmlwizard_tr.h
-QTQUICKWIZARD_TR_H = $$OUT_PWD/qtquickwizard_tr.h
EXTERNALTOOLS_TR_H = $$OUT_PWD/externaltools_tr.h
SNIPPETS_TR_H = $$OUT_PWD/snippets_tr.h
@@ -34,29 +31,17 @@ win32: \
else: \
PREFIX = "file://"
-for(dir, $$list($$files($$IDE_SOURCE_TREE/src/plugins/*))):MIMETYPES_FILES += $$files($$dir/*.mimetypes.xml)
-MIMETYPES_FILES = \"$$join(MIMETYPES_FILES, "|$$PREFIX", "$$PREFIX")\"
-
for(dir, $$list($$files($$IDE_SOURCE_TREE/share/qtcreator/templates/wizards/*, true))):CUSTOMWIZARD_FILES += $$files($$dir/wizard.xml)
CUSTOMWIZARD_FILES = \"$$join(CUSTOMWIZARD_FILES, "|$$PREFIX", "$$PREFIX")\"
-for(dir, $$list($$files($$IDE_SOURCE_TREE/share/qtcreator/templates/qml/*))):QMLWIZARD_FILES += $$files($$dir/template.xml)
-QMLWIZARD_FILES = \"$$join(QMLWIZARD_FILES, "|$$PREFIX", "$$PREFIX")\"
-
-for(dir, $$list($$files($$IDE_SOURCE_TREE/share/qtcreator/templates/qtquick/*))):QTQUICKWIZARD_FILES += $$files($$dir/template.xml)
-QTQUICKWIZARD_FILES = \"$$join(QTQUICKWIZARD_FILES, "|$$PREFIX", "$$PREFIX")\"
-
-for(file, $$list($$files($$IDE_SOURCE_TREE/src/share/qtcreator/externaltools/*))):EXTERNALTOOLS_FILES += $$files($$file)
+for(file, $$list($$files($$IDE_SOURCE_TREE/src/share/qtcreator/externaltools/*.xml))):EXTERNALTOOLS_FILES += $$files($$file)
EXTERNALTOOLS_FILES = \"$$join(EXTERNALTOOLS_FILES, "|$$PREFIX", "$$PREFIX")\"
for(file, $$list($$files($$IDE_SOURCE_TREE/share/qtcreator/snippets/*))):SNIPPETS_FILES += $$files($$file)
SNIPPETS_FILES = \"$$join(SNIPPETS_FILES, "|$$PREFIX", "$$PREFIX")\"
extract.commands += \
- $$XMLPATTERNS -output $$MIME_TR_H -param files=$$MIMETYPES_FILES $$PWD/extract-mimetypes.xq $$escape_expand(\\n\\t) \
$$XMLPATTERNS -output $$CUSTOMWIZARD_TR_H -param files=$$CUSTOMWIZARD_FILES $$PWD/extract-customwizards.xq $$escape_expand(\\n\\t) \
- $$XMLPATTERNS -output $$QMLWIZARD_TR_H -param files=$$QMLWIZARD_FILES $$PWD/extract-qmlwizards.xq $$escape_expand(\\n\\t) \
- $$XMLPATTERNS -output $$QTQUICKWIZARD_TR_H -param files=$$QTQUICKWIZARD_FILES $$PWD/extract-qtquickwizards.xq $$escape_expand(\\n\\t) \
$$XMLPATTERNS -output $$EXTERNALTOOLS_TR_H -param files=$$EXTERNALTOOLS_FILES $$PWD/extract-externaltools.xq $$escape_expand(\\n\\t) \
$$XMLPATTERNS -output $$SNIPPETS_TR_H -param files=$$SNIPPETS_FILES $$PWD/extract-snippets.xq $$escape_expand(\\n\\t) \
$(QMAKE) -o Makefile.jsonwizard JSONWIZARD_TR_H=\"$$JSONWIZARD_TR_H\" TOP_LEVEL=\"$$IDE_SOURCE_TREE/share/qtcreator/templates/wizards\" $$PWD/jsonwizard_tr.pro
@@ -65,14 +50,12 @@ QMAKE_EXTRA_TARGETS += extract
plugin_sources = $$files($$IDE_SOURCE_TREE/src/plugins/*)
plugin_sources ~= s,^$$re_escape($$IDE_SOURCE_TREE/),,g$$i_flag
plugin_sources -= src/plugins/plugins.pro \
- src/plugins/helloworld \ # just an example
- # the following ones are dead
- src/plugins/qtestlib \
- src/plugins/snippets \
- src/plugins/regexp
+ src/CMakeLists.txt \
+ src/plugins/helloworld
shared_sources = $$files($$IDE_SOURCE_TREE/src/shared/*)
shared_sources ~= s,^$$re_escape($$IDE_SOURCE_TREE/),,g$$i_flag
shared_sources -= \
+ src/CMakeLists.txt \
src/shared/qbs \
src/shared/shared.pro
sources = src/app src/libs $$plugin_sources $$shared_sources share/qtcreator/qmldesigner
@@ -83,12 +66,12 @@ files = $$files($$PWD/*_??.ts) $$PWD/qtcreator_untranslated.ts
for(file, files) {
lang = $$replace(file, .*_([^/]*)\\.ts, \\1)
v = ts-$${lang}.commands
- $$v = cd $$wd && $$LUPDATE $$include_options $$sources $$MIME_TR_H $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$QMLWIZARD_TR_H $$QTQUICKWIZARD_TR_H $$EXTERNALTOOLS_TR_H $$SNIPPETS_TR_H -ts $$file
+ $$v = cd $$wd && $$LUPDATE $$include_options $$sources $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$EXTERNALTOOLS_TR_H $$SNIPPETS_TR_H -ts $$file
v = ts-$${lang}.depends
$$v = extract
QMAKE_EXTRA_TARGETS += ts-$$lang
}
-ts-all.commands = cd $$wd && $$LUPDATE $$include_options $$sources $$MIME_TR_H $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$QMLWIZARD_TR_H $$QTQUICKWIZARD_TR_H $$EXTERNALTOOLS_TR_H $$SNIPPETS_TR_H -ts $$files
+ts-all.commands = cd $$wd && $$LUPDATE $$include_options $$sources $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$EXTERNALTOOLS_TR_H $$SNIPPETS_TR_H -ts $$files
ts-all.depends = extract
QMAKE_EXTRA_TARGETS += ts-all
diff --git a/share/share.qbs b/share/share.qbs
index c929391115..ba7b2a453f 100644
--- a/share/share.qbs
+++ b/share/share.qbs
@@ -21,6 +21,7 @@ Product {
"qmlicons/**/*",
"qml-type-descriptions/**/*",
"schemes/**/*",
+ "scripts/**/*",
"snippets/**/*",
"styles/**/*",
"templates/**/*",
@@ -40,7 +41,7 @@ Product {
qbs.installSourceBase: project.ide_source_tree + "/src/share/3rdparty"
prefix: project.ide_source_tree + "/src/share/3rdparty/"
files: [
- "generic-highlighter/**/*"
+ "fonts/**/*"
]
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000000..cf807a680e
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,556 @@
+# Not in the main CMakeLists.txt file because some tests fail if we have the flags set as default
+list(APPEND DEFAULT_DEFINES
+ QT_CREATOR QT_NO_CAST_TO_ASCII QT_RESTRICTED_CAST_FROM_ASCII
+ QT_DISABLE_DEPRECATED_BEFORE=0x050900
+ QT_USE_FAST_OPERATOR_PLUS
+ QT_USE_FAST_CONCATENATION
+)
+
+set(__QTC_PLUGINS "" CACHE INTERNAL "*** Internal ***" FORCE)
+set(__QTC_LIBRARIES "" CACHE INTERNAL "*** Internal ***" FORCE)
+set(__QTC_EXECUTABLES "" CACHE INTERNAL "*** Internal ***" FORCE)
+set(__QTC_TESTS "" CACHE INTERNAL "*** Internal ***" FORCE)
+
+function(update_cached_list name value)
+ set(_tmp_list "${${name}}")
+ list(APPEND _tmp_list "${value}")
+ set("${name}" "${_tmp_list}" CACHE INTERNAL "*** Internal ***" FORCE)
+endfunction()
+
+function(compare_sources_with_existing_disk_files target_name sources)
+ if(NOT WITH_DEBUG_CMAKE)
+ return()
+ endif()
+
+ file(GLOB_RECURSE existing_files RELATIVE ${CMAKE_CURRENT_LIST_DIR} "*.cpp" "*.hpp" "*.c" "*.h" "*.ui" "*.qrc")
+ foreach(file IN LISTS existing_files)
+ if(NOT ${file} IN_LIST sources)
+ if (NOT WITH_TESTS AND ${file} MATCHES "test")
+ continue()
+ endif()
+ message(STATUS "${target_name} doesn't include ${file}")
+ endif()
+ endforeach()
+
+ foreach(source IN LISTS "${sources}")
+ if(NOT ${source} IN_LIST existing_files)
+ if (NOT WITH_TESTS AND ${file} MATCHES "test")
+ continue()
+ endif()
+ message(STATUS "${target_name} contains non existing ${source}")
+ endif()
+ endforeach()
+endfunction(compare_sources_with_existing_disk_files)
+
+function(separate_object_libraries libraries REGULAR_LIBS OBJECT_LIBS OBJECT_LIB_OBJECTS)
+ if (CMAKE_VERSION VERSION_LESS 3.14)
+ foreach(lib IN LISTS libraries)
+ if (TARGET ${lib})
+ get_target_property(lib_type ${lib} TYPE)
+ if (lib_type STREQUAL "OBJECT_LIBRARY")
+ list(APPEND object_libs ${lib})
+ list(APPEND object_libs_objects $<TARGET_OBJECTS:${lib}>)
+ else()
+ list(APPEND regular_libs ${lib})
+ endif()
+ else()
+ list(APPEND regular_libs ${lib})
+ endif()
+ set(${REGULAR_LIBS} ${regular_libs} PARENT_SCOPE)
+ set(${OBJECT_LIBS} ${object_libs} PARENT_SCOPE)
+ set(${OBJECT_LIB_OBJECTS} ${object_libs_objects} PARENT_SCOPE)
+ endforeach()
+ else()
+ set(${REGULAR_LIBS} ${libraries} PARENT_SCOPE)
+ unset(${OBJECT_LIBS} PARENT_SCOPE)
+ unset(${OBJECT_LIB_OBJECTS} PARENT_SCOPE)
+ endif()
+endfunction(separate_object_libraries)
+
+function(set_explicit_moc target_name file)
+ set_property(SOURCE "${file}" PROPERTY SKIP_AUTOMOC ON)
+ qt5_wrap_cpp(file_moc "${file}")
+ target_sources(${target_name} PRIVATE "${file_moc}")
+endfunction()
+
+function(add_qtc_depends target_name)
+ cmake_parse_arguments(_arg "" "" "PRIVATE;PUBLIC" ${ARGN})
+ if (${_arg_UNPARSED_ARGUMENTS})
+ message(FATAL_ERROR "add_qtc_depends had unparsed arguments")
+ endif()
+
+ separate_object_libraries("${_arg_PRIVATE}"
+ depends object_lib_depends object_lib_depends_objects)
+ separate_object_libraries("${_arg_PUBLIC}"
+ public_depends object_public_depends object_public_depends_objects)
+
+ target_sources(${target_name} PRIVATE ${object_lib_depends_objects} ${object_public_depends_objects})
+
+ get_target_property(target_type ${target_name} TYPE)
+ if (NOT target_type STREQUAL "OBJECT_LIBRARY")
+ target_link_libraries(${target_name} PRIVATE ${depends} PUBLIC ${public_depends})
+ else()
+ list(APPEND object_lib_depends ${depends})
+ list(APPEND object_public_depends ${public_depends})
+ endif()
+
+ foreach(obj_lib IN LISTS object_lib_depends)
+ target_compile_definitions(${target_name} PRIVATE $<TARGET_PROPERTY:${obj_lib},INTERFACE_COMPILE_DEFINITIONS>)
+ target_include_directories(${target_name} PRIVATE $<TARGET_PROPERTY:${obj_lib},INTERFACE_INCLUDE_DIRECTORIES>)
+ endforeach()
+ foreach(obj_lib IN LISTS object_public_depends)
+ target_compile_definitions(${target_name} PUBLIC $<TARGET_PROPERTY:${obj_lib},INTERFACE_COMPILE_DEFINITIONS>)
+ target_include_directories(${target_name} PUBLIC $<TARGET_PROPERTY:${obj_lib},INTERFACE_INCLUDE_DIRECTORIES>)
+ endforeach()
+
+endfunction()
+
+function(add_qtc_library name)
+ cmake_parse_arguments(_arg "STATIC;OBJECT" ""
+ "DEFINES;DEPENDS;INCLUDES;PUBLIC_DEFINES;PUBLIC_DEPENDS;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;PROPERTIES" ${ARGN}
+ )
+
+ if (${_arg_UNPARSED_ARGUMENTS})
+ message(FATAL_ERROR "add_qtc_library had unparsed arguments")
+ endif()
+
+ update_cached_list(__QTC_LIBRARIES "${name}")
+
+ compare_sources_with_existing_disk_files(${name} "${_arg_SOURCES}")
+
+ set(library_type SHARED)
+ if (_arg_STATIC)
+ set(library_type STATIC)
+ endif()
+ if (_arg_OBJECT)
+ set(library_type OBJECT)
+ endif()
+
+ # Do not just build libraries...
+ add_library(${name} ${library_type} EXCLUDE_FROM_ALL ${_arg_SOURCES})
+
+ if (${name} MATCHES "^[^0-9]+")
+ string(TOUPPER "${name}_LIBRARY" EXPORT_SYMBOL)
+ endif()
+
+ if (WITH_TESTS)
+ set(TEST_DEFINES WITH_TESTS SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
+ endif()
+
+ target_include_directories(${name}
+ PRIVATE ${_arg_INCLUDES}
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/.." ${_arg_PUBLIC_INCLUDES}
+ )
+ target_compile_definitions(${name}
+ PRIVATE ${EXPORT_SYMBOL} ${DEFAULT_DEFINES} ${_arg_DEFINES} ${TEST_DEFINES}
+ PUBLIC ${_arg_PUBLIC_DEFINES}
+ )
+
+ add_qtc_depends(${name}
+ PRIVATE ${_arg_DEPENDS} ${_TEST_DEPENDS}
+ PUBLIC ${_arg_PUBLIC_DEPENDS}
+ )
+
+ foreach(file IN LISTS _arg_EXPLICIT_MOC)
+ set_explicit_moc(${name} "${file}")
+ endforeach()
+
+ foreach(file IN LISTS _arg_SKIP_AUTOMOC)
+ set_property(SOURCE ${file} PROPERTY SKIP_AUTOMOC ON)
+ endforeach()
+
+ set_target_properties(${name} PROPERTIES
+ SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERSION "${PROJECT_VERSION}"
+ CXX_VISIBILITY_PRESET hidden
+ VISIBILITY_INLINES_HIDDEN ON
+ BUILD_RPATH "${_LIB_RPATH}"
+ INSTALL_RPATH "${_LIB_RPATH}"
+ RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${IDE_BIN_PATH}"
+ LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${IDE_LIBRARY_PATH}"
+ ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${IDE_LIBRARY_PATH}"
+ ${_arg_PROPERTIES}
+ )
+
+ if (NOT (${library_type} STREQUAL "OBJECT" AND CMAKE_VERSION VERSION_LESS 3.14))
+ install(TARGETS ${name}
+ RUNTIME DESTINATION "${IDE_BIN_PATH}"
+ LIBRARY DESTINATION "${IDE_LIBRARY_PATH}"
+ ARCHIVE DESTINATION "${IDE_LIBRARY_PATH}"
+ )
+ endif()
+
+endfunction(add_qtc_library)
+
+function(find_dependent_plugins varName)
+ set(_RESULT ${ARGN})
+
+ foreach(i ${ARGN})
+ get_property(_dep TARGET "${i}" PROPERTY _arg_DEPENDS)
+ if (_dep)
+ find_dependent_plugins(_REC ${_dep})
+ list(APPEND _RESULT ${_REC})
+ endif()
+ endforeach()
+
+ if (_RESULT)
+ list(REMOVE_DUPLICATES _RESULT)
+ list(SORT _RESULT)
+ endif()
+
+ set("${varName}" ${_RESULT} PARENT_SCOPE)
+endfunction()
+
+function(qtc_plugin_enabled varName name)
+ if (NOT (name IN_LIST __QTC_PLUGINS))
+ message(FATAL_ERROR "extend_qtc_plugin: Unknown plugin target \"${name}\"")
+ endif()
+ if (TARGET ${name})
+ set(${varName} ON PARENT_SCOPE)
+ else()
+ set(${varName} OFF PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(add_qtc_plugin target_name)
+ cmake_parse_arguments(_arg
+ "EXPERIMENTAL;SKIP_DEBUG_CMAKE_FILE_CHECK;SKIP_INSTALL"
+ "VERSION;COMPAT_VERSION;PLUGIN_JSON_IN;PLUGIN_PATH;PLUGIN_NAME;OUTPUT_NAME"
+ "CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;INCLUDES;PUBLIC_INCLUDES;PLUGIN_DEPENDS;PLUGIN_RECOMMENDS;SOURCES;EXPLICIT_MOC"
+ ${ARGN}
+ )
+
+ if (${_arg_UNPARSED_ARGUMENTS})
+ message(FATAL_ERROR "add_qtc_plugin had unparsed arguments")
+ endif()
+
+ update_cached_list(__QTC_PLUGINS "${target_name}")
+
+ set(name ${target_name})
+ if (_arg_PLUGIN_NAME)
+ set(name ${_arg_PLUGIN_NAME})
+ endif()
+
+ if (NOT _arg_CONDITION)
+ set(_arg_CONDITION ON)
+ set(_extra_text "")
+ else()
+ string(REPLACE ";" " " _contents "${_arg_CONDITION}")
+ set(_extra_text "with CONDITION ${_contents}")
+ endif()
+
+ string(TOUPPER "BUILD_PLUGIN_${target_name}" _build_plugin_var)
+ set(_build_plugin_default "ON")
+ if (DEFINED ENV{QTC_${_build_plugin_var}})
+ set(_build_plugin_default "$ENV{QTC_${_build_plugin_var}}")
+ endif()
+ set(${_build_plugin_var} "${_build_plugin_default}" CACHE BOOL "Build plugin ${name}.")
+
+ if ((${_arg_CONDITION}) AND ${_build_plugin_var})
+ set(_plugin_enabled ON)
+ else()
+ set(_plugin_enabled OFF)
+ endif()
+
+ add_feature_info("Plugin ${name}" _plugin_enabled "${_extra_text}")
+ if (NOT _plugin_enabled)
+ return()
+ endif()
+
+ ### Generate plugin.json file:
+ if (NOT _arg_VERSION)
+ set(_arg_VERSION ${PROJECT_VERSION})
+ endif()
+ if (NOT _arg_COMPAT_VERSION)
+ set(_arg_COMPAT_VERSION ${_arg_VERSION})
+ endif()
+
+ if (NOT _arg_SKIP_DEBUG_CMAKE_FILE_CHECK)
+ compare_sources_with_existing_disk_files(${target_name} "${_arg_SOURCES}")
+ endif()
+
+ # Generate dependency list:
+ find_dependent_plugins(_DEP_PLUGINS ${_arg_PLUGIN_DEPENDS})
+
+ set(_arg_DEPENDENCY_STRING "\"Dependencies\" : [\n")
+ foreach(i IN LISTS _DEP_PLUGINS)
+ get_property(_v TARGET "${i}" PROPERTY _arg_VERSION)
+ string(APPEND _arg_DEPENDENCY_STRING
+ " { \"Name\" : \"${i}\", \"Version\" : \"${_v}\" }"
+ )
+ endforeach(i)
+ string(REPLACE "} {" "},\n {"
+ _arg_DEPENDENCY_STRING "${_arg_DEPENDENCY_STRING}"
+ )
+ foreach(i IN LISTS ${_arg_RECOMMENDS})
+ get_property(_v TARGET "${i}" PROPERTY _arg_VERSION)
+ string(APPEND _arg_DEPENDENCY_STRING
+ " { \"Name\" : \"${i}\", \"Version\" : \"${_v}\", \"Type\" : \"optional\" }"
+ )
+ endforeach(i)
+ string(APPEND _arg_DEPENDENCY_STRING "\n ]")
+ if (_arg_EXPERIMENTAL)
+ string(APPEND _arg_DEPENDENCY_STRING ",\n \"Experimental\" : true")
+ endif()
+
+ set(IDE_PLUGIN_DEPENDENCY_STRING ${_arg_DEPENDENCY_STRING})
+
+ ### Configure plugin.json file:
+ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.json.in")
+ file(READ "${name}.json.in" plugin_json_in)
+ string(REPLACE "\\\"" "\"" plugin_json_in ${plugin_json_in})
+ string(REPLACE "\\'" "'" plugin_json_in ${plugin_json_in})
+ string(REPLACE "$$QTCREATOR_VERSION" "\${IDE_VERSION}" plugin_json_in ${plugin_json_in})
+ string(REPLACE "$$QTCREATOR_COMPAT_VERSION" "\${IDE_VERSION_COMPAT}" plugin_json_in ${plugin_json_in})
+ string(REPLACE "$$QTCREATOR_COPYRIGHT_YEAR" "\${IDE_COPYRIGHT_YEAR}" plugin_json_in ${plugin_json_in})
+ string(REPLACE "$$dependencyList" "\${IDE_PLUGIN_DEPENDENCY_STRING}" plugin_json_in ${plugin_json_in})
+ if(_arg_PLUGIN_JSON_IN)
+ #e.g. UPDATEINFO_EXPERIMENTAL_STR=true
+ string(REGEX REPLACE "=.*$" "" json_key ${_arg_PLUGIN_JSON_IN})
+ string(REGEX REPLACE "^.*=" "" json_value ${_arg_PLUGIN_JSON_IN})
+ string(REPLACE "$$${json_key}" "${json_value}" plugin_json_in ${plugin_json_in})
+ endif()
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${name}.json.cmakein" ${plugin_json_in})
+
+ configure_file("${CMAKE_CURRENT_BINARY_DIR}/${name}.json.cmakein" "${name}.json")
+ endif()
+
+ add_library(${target_name} SHARED ${_arg_SOURCES})
+
+ ### Generate EXPORT_SYMBOL
+ string(TOUPPER "${name}_LIBRARY" EXPORT_SYMBOL)
+
+ if (WITH_TESTS)
+ set(TEST_DEFINES WITH_TESTS SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
+ endif()
+
+ target_include_directories(${target_name}
+ PRIVATE ${_arg_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/.." "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_BINARY_DIR}/src"
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/.." ${_arg_PUBLIC_INCLUDES}
+ )
+ target_compile_definitions(${target_name}
+ PRIVATE ${EXPORT_SYMBOL} ${DEFAULT_DEFINES} ${_arg_DEFINES} ${TEST_DEFINES}
+ )
+
+ add_qtc_depends(${target_name}
+ PRIVATE ${_arg_DEPENDS} ${_DEP_PLUGINS} ${_TEST_DEPENDS}
+ PUBLIC ${_arg_PUBLIC_DEPENDS}
+ )
+
+ set(plugin_dir "${IDE_PLUGIN_PATH}")
+ if (_arg_PLUGIN_PATH)
+ set(plugin_dir "${_arg_PLUGIN_PATH}")
+ endif()
+
+ set_target_properties(${target_name} PROPERTIES
+ SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
+ CXX_VISIBILITY_PRESET hidden
+ VISIBILITY_INLINES_HIDDEN ON
+ _arg_DEPENDS "${_arg_PLUGIN_DEPENDS}"
+ _arg_VERSION "${_arg_VERSION}"
+ BUILD_RPATH "${_PLUGIN_RPATH}"
+ INSTALL_RPATH "${_PLUGIN_RPATH}"
+ LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${plugin_dir}"
+ ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${plugin_dir}"
+ RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${plugin_dir}"
+ OUTPUT_NAME "${name}"
+ ${_arg_PROPERTIES}
+ )
+
+ foreach(file IN LISTS _arg_EXPLICIT_MOC)
+ set_explicit_moc(${target_name} "${file}")
+ endforeach()
+
+ if (NOT _arg_SKIP_INSTALL)
+ install(TARGETS ${target_name}
+ LIBRARY DESTINATION "${plugin_dir}"
+ ARCHIVE DESTINATION "${plugin_dir}"
+ RUNTIME DESTINATION "${plugin_dir}"
+ )
+ endif()
+endfunction()
+
+function(extend_qtc_target target_name)
+ cmake_parse_arguments(_arg
+ ""
+ "SOURCES_PREFIX"
+ "CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC"
+ ${ARGN}
+ )
+
+ if (${_arg_UNPARSED_ARGUMENTS})
+ message(FATAL_ERROR "extend_qtc_target had unparsed arguments")
+ endif()
+
+ if (NOT _arg_CONDITION)
+ set(_arg_CONDITION ON)
+ endif()
+ if (NOT (${_arg_CONDITION}))
+ return()
+ endif()
+
+ add_qtc_depends(${target_name}
+ PRIVATE ${_arg_DEPENDS}
+ PUBLIC ${_arg_PUBLIC_DEPENDS}
+ )
+ target_compile_definitions(${target_name} PRIVATE ${_arg_DEFINES})
+ target_include_directories(${target_name} PRIVATE ${_arg_INCLUDES} PUBLIC ${_arg_PUBLIC_INCLUDES})
+
+ if (_arg_SOURCES_PREFIX)
+ foreach(source IN LISTS _arg_SOURCES)
+ list(APPEND prefixed_sources "${_arg_SOURCES_PREFIX}/${source}")
+ endforeach()
+ target_include_directories(${target_name} PUBLIC "${_arg_SOURCES_PREFIX}")
+ set(_arg_SOURCES ${prefixed_sources})
+ endif()
+ target_sources(${target_name} PRIVATE ${_arg_SOURCES})
+
+ foreach(file IN LISTS _arg_EXPLICIT_MOC)
+ set_explicit_moc(${target_name} "${file}")
+ endforeach()
+
+endfunction()
+
+function(extend_qtc_plugin target_name)
+ qtc_plugin_enabled(_plugin_enabled ${target_name})
+ if (NOT _plugin_enabled)
+ return()
+ endif()
+
+ extend_qtc_target(${target_name} ${ARGN})
+endfunction()
+
+function(add_qtc_executable name)
+ cmake_parse_arguments(_arg "SKIP_INSTALL" "DESTINATION" "DEFINES;DEPENDS;INCLUDES;SOURCES;PROPERTIES" ${ARGN})
+
+ if ($_arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "add_qtc_executable had unparsed arguments!")
+ endif()
+
+ update_cached_list(__QTC_EXECUTABLES "${name}")
+
+ string(TOUPPER "BUILD_EXECUTABLE_${name}" _build_executable_var)
+ set(_build_executable_default "ON")
+ if (DEFINED ENV{QTC_${_build_executable_var}})
+ set(_build_executable_default "$ENV{QTC_${_build_executable_var}}")
+ endif()
+ set(${_build_executable_var} "${_build_executable_default}" CACHE BOOL "Build executable ${name}.")
+
+ if (NOT ${_build_executable_var})
+ return()
+ endif()
+
+ set(_DESTINATION "${IDE_LIBEXEC_PATH}")
+ if (_arg_DESTINATION)
+ set(_DESTINATION "${_arg_DESTINATION}")
+ endif()
+
+ set(_EXECUTABLE_PATH "${_DESTINATION}")
+ if (APPLE)
+ # path of executable might be inside app bundle instead of DESTINATION directly
+ cmake_parse_arguments(_prop "" "MACOSX_BUNDLE;OUTPUT_NAME" "" "${_arg_PROPERTIES}")
+ if (_prop_MACOSX_BUNDLE)
+ set(_BUNDLE_NAME "${name}")
+ if (_prop_OUTPUT_NAME)
+ set(_BUNDLE_NAME "${_prop_OUTPUT_NAME}")
+ endif()
+ set(_EXECUTABLE_PATH "${_DESTINATION}/${_BUNDLE_NAME}.app/Contents/MacOS")
+ endif()
+ endif()
+
+ file(RELATIVE_PATH _RELATIVE_LIB_PATH "/${_EXECUTABLE_PATH}" "/${IDE_LIBRARY_PATH}")
+
+ add_executable("${name}" ${_arg_SOURCES})
+ target_include_directories("${name}" PRIVATE "${CMAKE_BINARY_DIR}/src" ${_arg_INCLUDES})
+ target_compile_definitions("${name}" PRIVATE ${_arg_DEFINES} ${TEST_DEFINES} ${DEFAULT_DEFINES})
+ target_link_libraries("${name}" PRIVATE ${_arg_DEPENDS} ${_TEST_DEPENDS})
+ set_target_properties("${name}" PROPERTIES
+ BUILD_RPATH "${_RPATH_BASE}/${_RELATIVE_LIB_PATH}"
+ INSTALL_RPATH "${_RPATH_BASE}/${_RELATIVE_LIB_PATH}"
+ RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${_DESTINATION}"
+ ${_arg_PROPERTIES}
+ )
+
+ if (NOT _arg_SKIP_INSTALL)
+ install(TARGETS ${name} DESTINATION "${_DESTINATION}")
+ endif()
+endfunction()
+
+function(extend_qtc_executable name)
+ if (NOT (name IN_LIST __QTC_EXECUTABLES))
+ message(FATAL_ERROR "extend_qtc_executable: Unknown executable target \"${name}\"")
+ endif()
+ if (TARGET ${name})
+ extend_qtc_target(${name} ${ARGN})
+ endif()
+endfunction()
+
+function(fix_test_environment test_name)
+ if (WIN32)
+ list(APPEND env_path $ENV{PATH})
+ list(APPEND env_path ${CMAKE_BINARY_DIR}/${IDE_PLUGIN_PATH})
+ list(APPEND env_path ${CMAKE_BINARY_DIR}/${IDE_BIN_PATH})
+ list(APPEND env_path $<TARGET_FILE_DIR:Qt5::Test>)
+ if (TARGET libclang)
+ list(APPEND env_path $<TARGET_FILE_DIR:libclang>)
+ endif()
+
+ string(REPLACE "/" "\\" env_path "${env_path}")
+ string(REPLACE ";" "\\;" env_path "${env_path}")
+
+ set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "PATH=${env_path}")
+ endif()
+endfunction()
+
+function(add_qtc_test name)
+ cmake_parse_arguments(_arg "GTEST" "" "DEFINES;DEPENDS;INCLUDES;SOURCES" ${ARGN})
+
+ if ($_arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "add_qtc_test had unparsed arguments!")
+ endif()
+
+ update_cached_list(__QTC_TESTS "${name}")
+
+ set(TEST_DEFINES SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
+ file(RELATIVE_PATH _RPATH "/${IDE_BIN_PATH}" "/${IDE_LIBRARY_PATH}")
+
+ add_executable(${name} ${_arg_SOURCES})
+
+ add_qtc_depends(${name}
+ PRIVATE ${_arg_DEPENDS} ${_TEST_DEPENDS}
+ )
+
+ target_include_directories(${name} PRIVATE "${CMAKE_BINARY_DIR}/src" ${_arg_INCLUDES})
+ target_compile_definitions(${name} PRIVATE ${_arg_DEFINES} ${TEST_DEFINES} ${DEFAULT_DEFINES})
+
+ set_target_properties(${name} PROPERTIES
+ BUILD_RPATH "${_RPATH_BASE}/${_RPATH}"
+ INSTALL_RPATH "${_RPATH_BASE}/${_RPATH}"
+ )
+
+ if (NOT _arg_GTEST)
+ add_test(NAME ${name} COMMAND ${name})
+ fix_test_environment(${name})
+ endif()
+endfunction()
+
+function(finalize_qtc_gtest test_name)
+ get_target_property(test_sources ${test_name} SOURCES)
+ include(GoogleTest)
+ gtest_add_tests(TARGET ${test_name} SOURCES ${test_sources} TEST_LIST test_list)
+
+ foreach(test IN LISTS test_list)
+ fix_test_environment(${test})
+ endforeach()
+endfunction()
+
+add_library(app_version INTERFACE)
+target_include_directories(app_version INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
+
+add_subdirectory(libs)
+add_subdirectory(share)
+add_subdirectory(shared)
+add_subdirectory(app)
+add_subdirectory(plugins)
+add_subdirectory(tools)
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
new file mode 100644
index 0000000000..0ef67b2943
--- /dev/null
+++ b/src/app/CMakeLists.txt
@@ -0,0 +1,62 @@
+configure_file(app_version.h.cmakein app_version.h ESCAPE_QUOTES)
+
+add_qtc_executable(qtcreator
+ DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
+ DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils shared_qtsingleapplication app_version
+ SOURCES
+ main.cpp
+ ../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h
+ PROPERTIES
+ WIN32_EXECUTABLE ON
+ MACOSX_BUNDLE ON
+ OUTPUT_NAME "${IDE_APP_TARGET}"
+ DESTINATION "${IDE_APP_PATH}"
+)
+
+if (WIN32)
+ set(RC_APPLICATION_NAME "${IDE_DISPLAY_NAME}")
+ set(RC_VERSION "${IDE_VERSION}.0")
+ set(RC_VERSION_STRING "${IDE_VERSION_DISPLAY}")
+ set(RC_COPYRIGHT "2008-${IDE_COPYRIGHT_YEAR} The Qt Company Ltd")
+
+ string(REPLACE " " "\\x20" RC_APPLICATION_NAME "${RC_APPLICATION_NAME}")
+ string(REPLACE " " "\\x20" RC_COPYRIGHT "${RC_COPYRIGHT}")
+ string(REPLACE "." "," RC_VERSION "${RC_VERSION}")
+
+ target_compile_definitions(qtcreator PRIVATE
+ RC_APPLICATION_NAME=${RC_APPLICATION_NAME}
+ RC_VERSION=${RC_VERSION}
+ RC_VERSION_STRING=${RC_VERSION_STRING}
+ RC_COPYRIGHT=${RC_COPYRIGHT}
+ )
+
+ target_sources(qtcreator PRIVATE qtcreator.rc)
+endif()
+
+if (APPLE)
+ set_target_properties(qtcreator PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/app-Info.plist"
+ )
+ # icon
+ add_custom_command(
+ OUTPUT qtcreator.icns qtcreator-project.icns
+ COMMAND
+ xcrun actool --app-icon qtcreator --output-partial-info-plist "${CMAKE_CURRENT_BINARY_DIR}/qtcreator.Info.plist"
+ --platform macosx --minimum-deployment-target 10.7 --compile "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/qtcreator.xcassets"
+ > /dev/null
+ BYPRODUCTS qtcreator.Info.plist
+ VERBATIM
+ )
+ target_sources(qtcreator
+ PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/qtcreator.icns"
+ "${CMAKE_CURRENT_BINARY_DIR}/qtcreator-project.icns"
+ )
+ set_source_files_properties(
+ "${CMAKE_CURRENT_BINARY_DIR}/qtcreator.icns"
+ "${CMAKE_CURRENT_BINARY_DIR}/qtcreator-project.icns"
+ PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources"
+ )
+endif()
diff --git a/src/app/app-Info.plist b/src/app/app-Info.plist
index 5893f062a8..95863741ac 100644
--- a/src/app/app-Info.plist
+++ b/src/app/app-Info.plist
@@ -237,7 +237,7 @@
</dict>
</array>
<key>NSHumanReadableCopyright</key>
- <string>(C) @QTCREATOR_COPYRIGHT_YEAR@ The Qt Company Ltd</string>
+ <string>(C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd</string>
<key>CFBundleIconFile</key>
<string>qtcreator</string>
<key>CFBundlePackageType</key>
@@ -245,15 +245,15 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleExecutable</key>
- <string>@EXECUTABLE@</string>
+ <string>${IDE_APP_TARGET}</string>
<key>CFBundleIdentifier</key>
- <string>@PRODUCT_BUNDLE_IDENTIFIER@</string>
+ <string>${IDE_BUNDLE_IDENTIFIER}</string>
<key>CFBundleVersion</key>
- <string>@FULL_VERSION@</string>
+ <string>${IDE_VERSION}</string>
<key>CFBundleShortVersionString</key>
- <string>@SHORT_VERSION@</string>
+ <string>${IDE_VERSION}</string>
<key>LSMinimumSystemVersion</key>
- <string>@MACOSX_DEPLOYMENT_TARGET@</string>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSAppleEventsUsageDescription</key>
<string>This application wants to run AppleScript.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
diff --git a/src/app/app.pro b/src/app/app.pro
index 712563419e..8621a63f02 100644
--- a/src/app/app.pro
+++ b/src/app/app.pro
@@ -23,7 +23,10 @@ win32 {
# RC_VERSION_STRING="4.4.0-beta1" (free text)
# Also, we need to replace space with \x20 to be able to work with both rc and windres
COPYRIGHT = "2008-$${QTCREATOR_COPYRIGHT_YEAR} The Qt Company Ltd"
- DEFINES += RC_VERSION=$$replace(QTCREATOR_VERSION, "\\.", ","),0 \
+ APPLICATION_NAME = "$${IDE_DISPLAY_NAME}"
+ DEFINES += \
+ RC_APPLICATION_NAME=\"$$replace(APPLICATION_NAME, " ", "\\x20")\" \
+ RC_VERSION=$$replace(QTCREATOR_VERSION, "\\.", ","),0 \
RC_VERSION_STRING=\"$${QTCREATOR_DISPLAY_VERSION}\" \
RC_COPYRIGHT=\"$$replace(COPYRIGHT, " ", "\\x20")\"
RC_FILE = qtcreator.rc
@@ -35,9 +38,11 @@ win32 {
QMAKE_ASSET_CATALOGS_APP_ICON = qtcreator
infoplist = $$cat($$PWD/app-Info.plist, blob)
- infoplist = $$replace(infoplist, @MACOSX_DEPLOYMENT_TARGET@, $$QMAKE_MACOSX_DEPLOYMENT_TARGET)
- infoplist = $$replace(infoplist, @QTCREATOR_COPYRIGHT_YEAR@, $$QTCREATOR_COPYRIGHT_YEAR)
- infoplist = $$replace(infoplist, @PRODUCT_BUNDLE_IDENTIFIER@, $$PRODUCT_BUNDLE_IDENTIFIER)
+ infoplist = $$replace(infoplist, \\$\\{MACOSX_DEPLOYMENT_TARGET\\}, $$QMAKE_MACOSX_DEPLOYMENT_TARGET)
+ infoplist = $$replace(infoplist, \\$\\{IDE_COPYRIGHT_YEAR\\}, $$QTCREATOR_COPYRIGHT_YEAR)
+ infoplist = $$replace(infoplist, \\$\\{IDE_APP_TARGET\\}, $$IDE_APP_TARGET)
+ infoplist = $$replace(infoplist, \\$\\{IDE_BUNDLE_IDENTIFIER\\}, $$PRODUCT_BUNDLE_IDENTIFIER)
+ infoplist = $$replace(infoplist, \\$\\{IDE_VERSION\\}, $$QTCREATOR_VERSION)
write_file($$OUT_PWD/Info.plist, infoplist)
QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist
diff --git a/src/app/app.qbs b/src/app/app.qbs
index 3ed4eb8fde..a866a2ecdb 100644
--- a/src/app/app.qbs
+++ b/src/app/app.qbs
@@ -26,8 +26,14 @@ QtcProduct {
property bool qtcRunnable: true
bundle.identifier: qtc.ide_bundle_identifier
+
+ // Some of these are in here only to override the entries added to app-Info.plist with other
+ // build systems in mind.
bundle.infoPlist: ({
- "NSHumanReadableCopyright": qtc.qtcreator_copyright_string
+ "NSHumanReadableCopyright": qtc.qtcreator_copyright_string,
+ "CFBundleExecutable": qtc.ide_app_target,
+ "CFBundleIdentifier": qtc.ide_bundle_identifier,
+ "CFBundleVersion": version
})
cpp.rpaths: qbs.targetOS.contains("macos") ? ["@executable_path/../Frameworks"]
diff --git a/src/app/app_version.h.cmakein b/src/app/app_version.h.cmakein
new file mode 100644
index 0000000000..86074a22e9
--- /dev/null
+++ b/src/app/app_version.h.cmakein
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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
+
+#define IDE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}
+#define IDE_VERSION_MINOR ${PROJECT_VERSION_MINOR}
+#define IDE_VERSION_RELEASE ${PROJECT_VERSION_PATCH}
+
+#cmakedefine IDE_REVISION
+
+namespace Core {
+namespace Constants {
+
+const char IDE_VERSION_LONG[] = "${PROJECT_VERSION}";
+const char IDE_AUTHOR[] = "The Qt Company Ltd";
+const char IDE_YEAR[] = "${IDE_COPYRIGHT_YEAR}";
+
+const char IDE_DISPLAY_NAME[] = "${IDE_DISPLAY_NAME}";
+const char IDE_ID[] = "${IDE_ID}";
+const char IDE_CASED_ID[] = "${IDE_CASED_ID}";
+
+const char IDE_VERSION_DISPLAY[] = "${IDE_VERSION_DISPLAY}";
+const char IDE_REVISION_STR[] = "${IDE_REVISION_STR}";
+
+// changes the path where the settings are saved to
+const char IDE_SETTINGSVARIANT_STR[] = "${IDE_SETTINGSVARIANT}";
+const char IDE_COPY_SETTINGS_FROM_VARIANT_STR[] = "${IDE_COPY_SETTINGSVARIANT}";
+
+} // Constants
+} // Core
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 17e2d3bf29..e1756b2b95 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -102,7 +102,7 @@ const char BLOCK_OPTION[] = "-block";
const char PLUGINPATH_OPTION[] = "-pluginpath";
const char USER_LIBRARY_PATH_OPTION[] = "-user-library-path"; // hidden option for qtcreator.sh
-typedef QList<PluginSpec *> PluginSpecSet;
+using PluginSpecSet = QVector<PluginSpec *>;
// Helpers for displaying messages. Note that there is no console on Windows.
@@ -196,7 +196,7 @@ static bool copyRecursively(const QString &srcFilePath,
if (srcFileInfo.isDir()) {
QDir targetDir(tgtFilePath);
targetDir.cdUp();
- if (!targetDir.mkdir(Utils::FileName::fromString(tgtFilePath).fileName()))
+ if (!targetDir.mkdir(Utils::FilePath::fromString(tgtFilePath).fileName()))
return false;
QDir sourceDir(srcFilePath);
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
diff --git a/src/app/qtcreator.rc b/src/app/qtcreator.rc
index bcc6e7f8ab..ac57dc6d5b 100644
--- a/src/app/qtcreator.rc
+++ b/src/app/qtcreator.rc
@@ -21,9 +21,9 @@ VS_VERSION_INFO VERSIONINFO
// U.S. English - Windows, Multilingual
BLOCK "040904E4"
{
- VALUE "FileDescription", "Qt Creator"
+ VALUE "FileDescription", STRINGIFY(RC_APPLICATION_NAME)
VALUE "FileVersion", STRINGIFY(RC_VERSION_STRING)
- VALUE "ProductName", "Qt Creator"
+ VALUE "ProductName", STRINGIFY(RC_APPLICATION_NAME)
VALUE "ProductVersion", STRINGIFY(RC_VERSION_STRING)
VALUE "LegalCopyright", STRINGIFY(RC_COPYRIGHT)
}
diff --git a/src/libs/3rdparty/CMakeLists.txt b/src/libs/3rdparty/CMakeLists.txt
new file mode 100644
index 0000000000..7cf97ab87f
--- /dev/null
+++ b/src/libs/3rdparty/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(cplusplus)
+add_subdirectory(syntax-highlighting)
diff --git a/src/libs/3rdparty/cplusplus/CMakeLists.txt b/src/libs/3rdparty/cplusplus/CMakeLists.txt
new file mode 100644
index 0000000000..a33e96a197
--- /dev/null
+++ b/src/libs/3rdparty/cplusplus/CMakeLists.txt
@@ -0,0 +1,46 @@
+add_qtc_library(3rd_cplusplus OBJECT
+ PUBLIC_DEPENDS Qt5::Core Utils
+ DEFINES CPLUSPLUS_BUILD_LIB
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/libs"
+ SOURCES
+ AST.cpp AST.h
+ ASTClone.cpp
+ ASTMatch0.cpp
+ ASTMatcher.cpp ASTMatcher.h
+ ASTPatternBuilder.h
+ ASTVisit.cpp
+ ASTVisitor.cpp ASTVisitor.h
+ ASTfwd.h
+ Bind.cpp Bind.h
+ CPlusPlus.h
+ CPlusPlusForwardDeclarations.h
+ Control.cpp Control.h
+ CoreTypes.cpp CoreTypes.h
+ DiagnosticClient.cpp DiagnosticClient.h
+ FullySpecifiedType.cpp FullySpecifiedType.h
+ Keywords.cpp
+ Lexer.cpp Lexer.h
+ LiteralTable.h
+ Literals.cpp Literals.h
+ Matcher.cpp Matcher.h
+ MemoryPool.cpp MemoryPool.h
+ Name.cpp Name.h
+ NameVisitor.cpp NameVisitor.h
+ Names.cpp Names.h
+ ObjectiveCAtKeywords.cpp
+ ObjectiveCTypeQualifiers.cpp ObjectiveCTypeQualifiers.h
+ Parser.cpp Parser.h
+ QtContextKeywords.cpp QtContextKeywords.h
+ SafeMatcher.cpp SafeMatcher.h
+ Scope.cpp Scope.h
+ Symbol.cpp Symbol.h
+ SymbolVisitor.h
+ Symbols.cpp Symbols.h
+ Templates.cpp Templates.h
+ Token.cpp Token.h
+ TranslationUnit.cpp TranslationUnit.h
+ Type.cpp Type.h
+ TypeVisitor.cpp TypeVisitor.h
+ cppassert.h
+ PROPERTIES POSITION_INDEPENDENT_CODE ON
+)
diff --git a/src/libs/3rdparty/syntax-highlighting/.gitignore b/src/libs/3rdparty/syntax-highlighting/.gitignore
index 02ba11c78a..52f10e28a5 100644
--- a/src/libs/3rdparty/syntax-highlighting/.gitignore
+++ b/src/libs/3rdparty/syntax-highlighting/.gitignore
@@ -7,3 +7,6 @@
CMakeLists.txt.user
callgrind.*
heaptrack.*
+/build*/
+*.unc-backup*
+
diff --git a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt
index 49923fb26e..27cc408223 100644
--- a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt
@@ -1,134 +1,47 @@
-cmake_minimum_required(VERSION 3.0)
-
-set(KF5_VERSION "5.52.0")
-project(KSyntaxHighlighting VERSION ${KF5_VERSION})
-
-find_package(ECM 5.51.0 REQUIRED NO_MODULE)
-set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
-if(POLICY CMP0063)
- cmake_policy(SET CMP0063 NEW)
-endif()
-
-include(FeatureSummary)
-include(GenerateExportHeader)
-include(ECMSetupVersion)
-include(ECMGenerateHeaders)
-include(ECMGeneratePriFile)
-include(CMakePackageConfigHelpers)
-include(ECMPoQmTools)
-include(ECMQtDeclareLoggingCategory)
-include(KDEInstallDirs)
-include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
-include(KDECMakeSettings)
-include(ECMMarkNonGuiExecutable)
-include(ECMAddQch)
-
-
-ecm_setup_version(PROJECT
- VARIABLE_PREFIX SyntaxHighlighting
- VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h"
- PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake"
+add_qtc_library(KSyntaxHighlighting STATIC
+ PUBLIC_INCLUDES autogenerated/ autogenerated/src/lib src/lib
+ PUBLIC_DEFINES KSYNTAXHIGHLIGHTING_LIBRARY
+ DEPENDS Qt5::Network Qt5::Gui
+ SOURCES
+ autogenerated/src/lib/ksyntaxhighlighting_logging.cpp autogenerated/src/lib/ksyntaxhighlighting_logging.h
+ autogenerated/ksyntaxhighlighting_version.h
+
+ data/themes/theme-data.qrc
+
+ src/lib/abstracthighlighter.cpp src/lib/abstracthighlighter.h src/lib/abstracthighlighter_p.h
+ src/lib/context.cpp src/lib/context_p.h
+ src/lib/contextswitch.cpp src/lib/contextswitch_p.h
+ src/lib/definition.cpp src/lib/definition.h
+ src/lib/definitiondownloader.cpp src/lib/definitiondownloader.h
+ src/lib/definitionref_p.h
+ src/lib/definition_p.h
+ src/lib/foldingregion.cpp src/lib/foldingregion.h
+ src/lib/format.cpp src/lib/format.h src/lib/format_p.h
+ src/lib/htmlhighlighter.cpp src/lib/htmlhighlighter.h
+ src/lib/keywordlist.cpp src/lib/keywordlist_p.h
+ src/lib/ksyntaxhighlighting_export.h
+ src/lib/matchresult_p.h
+ src/lib/repository.cpp src/lib/repository.h src/lib/repository_p.h
+ src/lib/rule.cpp src/lib/rule_p.h
+ src/lib/state.cpp src/lib/state.h src/lib/state_p.h
+ src/lib/syntaxhighlighter.cpp src/lib/syntaxhighlighter.h
+ src/lib/textstyledata_p.h
+ src/lib/theme.cpp src/lib/theme.h
+ src/lib/themedata.cpp src/lib/themedata_p.h
+ src/lib/wildcardmatcher.cpp src/lib/wildcardmatcher_p.h
+ src/lib/xml_p.h
)
-#
-# Dependencies
-#
-set(REQUIRED_QT_VERSION 5.8.0)
-find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Core Network Test)
-option(KSYNTAXHIGHLIGHTING_USE_GUI "Build components depending on Qt5Gui" ON)
-if(KSYNTAXHIGHLIGHTING_USE_GUI)
- find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Gui)
-endif()
-find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE QUIET OPTIONAL_COMPONENTS Widgets XmlPatterns)
-set_package_properties(Qt5 PROPERTIES URL "http://qt-project.org/")
-set_package_properties(Qt5Widgets PROPERTIES PURPOSE "Example application.")
-set_package_properties(Qt5XmlPatterns PROPERTIES PURPOSE "Compile-time validation of syntax definition files.")
-
-find_package(Perl REQUIRED)
-set_package_properties(Perl PROPERTIES PURPOSE "Auto-generate PHP syntax definition files.")
-
-#
-# allow to install the "differently" licensed syntax xml files instead of putting them in a QRC and link them in
-#
-option(QRC_SYNTAX "Bundle the syntax definition files inside the library as resources" ON)
-add_feature_info(SYNTAX_RESOURCE ${QRC_SYNTAX} "Bundle the syntax definition files inside the library as resources")
-
-#
-# allow to turn of lookup for syntax files and themes via QStandardPaths
-#
-option(NO_STANDARD_PATHS "Skip lookup of syntax and theme definitions in QStandardPaths locations" OFF)
-add_feature_info(FEATURE_NO_STANDARD_PATHS ${NO_STANDARD_PATHS} "Skip lookup of syntax and theme definitions in QStandardPaths locations")
-
-#
-# API documentation
-#
-option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF)
-add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)")
-
-#
-# Translations
-#
-if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po")
- ecm_install_po_files_as_qm(po)
-endif()
-
-# tell the framework if it shall use the syntax files from the resource
-if (QRC_SYNTAX)
- add_definitions(-DHAS_SYNTAX_RESOURCE)
-endif()
-
-# skip standard paths?
-if (NO_STANDARD_PATHS)
- add_definitions(-DNO_STANDARD_PATHS)
-endif()
-
-#
-# Actually build the stuff
-#
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-add_subdirectory(data)
-add_subdirectory(src)
-if(TARGET Qt5::Gui)
- add_subdirectory(examples)
-endif()
-
-#
-# CMake package config file generation
-#
-set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KF5SyntaxHighlighting")
-
-if (BUILD_QCH)
- ecm_install_qch_export(
- TARGETS KF5SyntaxHighlighting_QCH
- FILE KF5SyntaxHighlightingQchTargets.cmake
- DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
- COMPONENT Devel
- )
- set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5SyntaxHighlightingQchTargets.cmake\")")
-endif()
-
-configure_package_config_file(
- "${CMAKE_CURRENT_SOURCE_DIR}/KF5SyntaxHighlightingConfig.cmake.in"
- "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake"
- INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+install(
+ DIRECTORY data/syntax
+ DESTINATION "${IDE_DATA_PATH}/generic-highlighter/"
)
-install(FILES
- "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake"
- "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake"
- DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
- COMPONENT Devel)
-
-if(TARGET KF5SyntaxHighlighting)
- install(EXPORT KF5SyntaxHighlightingTargets
- DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
- FILE KF5SyntaxHighlightingTargets.cmake
- NAMESPACE KF5::)
-endif()
-
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h"
- DESTINATION "${KDE_INSTALL_INCLUDEDIR_KF5}"
- COMPONENT Devel)
-install(FILES org_kde_ksyntaxhighlighting.categories DESTINATION ${KDE_INSTALL_CONFDIR})
-
-feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
+add_custom_target(copy_generic_highligher_to_builddir ALL VERBATIM)
+add_custom_command(TARGET copy_generic_highligher_to_builddir POST_BUILD
+ COMMAND "${CMAKE_COMMAND}" -E copy_directory data/syntax
+ "${PROJECT_BINARY_DIR}/${IDE_DATA_PATH}/generic-highlighter/syntax"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ COMMENT Copy files into build directory
+ VERBATIM
+)
diff --git a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt.kde b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt.kde
new file mode 100644
index 0000000000..4f88fcf84a
--- /dev/null
+++ b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt.kde
@@ -0,0 +1,140 @@
+cmake_minimum_required(VERSION 3.5)
+
+set(KF5_VERSION "5.59.0")
+project(KSyntaxHighlighting VERSION ${KF5_VERSION})
+
+find_package(ECM 5.59.0 REQUIRED NO_MODULE)
+set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
+if(POLICY CMP0063)
+ cmake_policy(SET CMP0063 NEW)
+endif()
+
+include(FeatureSummary)
+include(GenerateExportHeader)
+include(ECMSetupVersion)
+include(ECMGenerateHeaders)
+include(ECMGeneratePriFile)
+include(CMakePackageConfigHelpers)
+include(ECMPoQmTools)
+include(ECMQtDeclareLoggingCategory)
+include(KDEInstallDirs)
+include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
+include(KDECMakeSettings)
+include(ECMMarkNonGuiExecutable)
+include(ECMAddQch)
+include(ECMOptionalAddSubdirectory)
+
+
+ecm_setup_version(PROJECT
+ VARIABLE_PREFIX SyntaxHighlighting
+ VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h"
+ PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake"
+)
+
+#
+# Dependencies
+#
+set(REQUIRED_QT_VERSION 5.10.0)
+find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Core Network Test)
+option(KSYNTAXHIGHLIGHTING_USE_GUI "Build components depending on Qt5Gui" ON)
+if(KSYNTAXHIGHLIGHTING_USE_GUI)
+ find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Gui)
+endif()
+find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE QUIET OPTIONAL_COMPONENTS PrintSupport Widgets XmlPatterns)
+set_package_properties(Qt5 PROPERTIES URL "http://qt-project.org/")
+set_package_properties(Qt5Widgets PROPERTIES PURPOSE "Example application.")
+set_package_properties(Qt5PrintSupport PROPERTIES PURPOSE "Example application.")
+set_package_properties(Qt5XmlPatterns PROPERTIES PURPOSE "Compile-time validation of syntax definition files.")
+
+find_package(Perl REQUIRED)
+set_package_properties(Perl PROPERTIES PURPOSE "Auto-generate PHP syntax definition files.")
+
+#
+# allow to install the "differently" licensed syntax xml files instead of putting them in a QRC and link them in
+#
+option(QRC_SYNTAX "Bundle the syntax definition files inside the library as resources" ON)
+add_feature_info(SYNTAX_RESOURCE ${QRC_SYNTAX} "Bundle the syntax definition files inside the library as resources")
+
+#
+# allow to turn of lookup for syntax files and themes via QStandardPaths
+#
+option(NO_STANDARD_PATHS "Skip lookup of syntax and theme definitions in QStandardPaths locations" OFF)
+add_feature_info(FEATURE_NO_STANDARD_PATHS ${NO_STANDARD_PATHS} "Skip lookup of syntax and theme definitions in QStandardPaths locations")
+
+#
+# API documentation
+#
+option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF)
+add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)")
+
+#
+# Translations
+#
+if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po")
+ ecm_install_po_files_as_qm(po)
+endif()
+
+# tell the framework if it shall use the syntax files from the resource
+if (QRC_SYNTAX)
+ add_definitions(-DHAS_SYNTAX_RESOURCE)
+endif()
+
+# skip standard paths?
+if (NO_STANDARD_PATHS)
+ add_definitions(-DNO_STANDARD_PATHS)
+endif()
+add_definitions(-DQT_NO_FOREACH)
+
+#
+# Actually build the stuff
+#
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+add_subdirectory(data)
+add_subdirectory(src)
+if(TARGET Qt5::Gui)
+ add_subdirectory(examples)
+ if (BUILD_TESTING)
+ add_subdirectory(autotests)
+ endif()
+endif()
+
+#
+# CMake package config file generation
+#
+set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KF5SyntaxHighlighting")
+
+if (BUILD_QCH)
+ ecm_install_qch_export(
+ TARGETS KF5SyntaxHighlighting_QCH
+ FILE KF5SyntaxHighlightingQchTargets.cmake
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ COMPONENT Devel
+ )
+ set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5SyntaxHighlightingQchTargets.cmake\")")
+endif()
+
+configure_package_config_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/KF5SyntaxHighlightingConfig.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake"
+ INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+)
+
+install(FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake"
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ COMPONENT Devel)
+
+if(TARGET KF5SyntaxHighlighting)
+ install(EXPORT KF5SyntaxHighlightingTargets
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ FILE KF5SyntaxHighlightingTargets.cmake
+ NAMESPACE KF5::)
+endif()
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h"
+ DESTINATION "${KDE_INSTALL_INCLUDEDIR_KF5}"
+ COMPONENT Devel)
+install(FILES org_kde_ksyntaxhighlighting.categories DESTINATION ${KDE_INSTALL_CONFDIR})
+
+feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
diff --git a/src/libs/3rdparty/syntax-highlighting/README.md b/src/libs/3rdparty/syntax-highlighting/README.md
index 1eedc0af7f..c1b82c63d1 100644
--- a/src/libs/3rdparty/syntax-highlighting/README.md
+++ b/src/libs/3rdparty/syntax-highlighting/README.md
@@ -30,3 +30,20 @@ out of scope:
* management of text buffers or documents
If you need any of this, check out [KTextEditor](https://api.kde.org/frameworks/ktexteditor/html/).
+
+## Adding unit tests for a syntax definition
+
+* add an input file into the autotests/input/ folder, lets call it test.<language-extension>
+
+* if the file extension is not sufficient to trigger the right syntax definition, you can add an
+ second file testname.<language-extension>.syntax that contains the syntax definition name
+ to enforce the use of the right extension
+
+* do "make && make test"
+
+* inspect the outputs found in your binary directory autotests/folding.out, autotests/html.output and autotests/output
+
+* if ok, run in the binary folder "./autotests/update-reference-data.sh" to copy the results to the right location
+
+* add the result references after the copying to the git
+
diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h b/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h
index bd31a4d407..70795908d6 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.52.0"
+#define SyntaxHighlighting_VERSION_STRING "5.59.0"
#define SyntaxHighlighting_VERSION_MAJOR 5
-#define SyntaxHighlighting_VERSION_MINOR 52
+#define SyntaxHighlighting_VERSION_MINOR 59
#define SyntaxHighlighting_VERSION_PATCH 0
-#define SyntaxHighlighting_VERSION ((5<<16)|(52<<8)|(0))
+#define SyntaxHighlighting_VERSION ((5<<16)|(59<<8)|(0))
#endif
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml
index 2a9088b46c..6d170e4eaa 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml
@@ -31,7 +31,7 @@
<language
name="CMake"
- version="11"
+ version="12"
kateversion="2.4"
section="Other"
extensions="CMakeLists.txt;*.cmake;*.cmake.in"
@@ -317,6 +317,7 @@
<item>PATTERN</item>
<item>PERMISSIONS</item>
<item>READ</item>
+ <item>READ_SYMLINK</item>
<item>REGEX</item>
<item>RELATIVE</item>
<item>RELATIVE_PATH</item>
@@ -335,6 +336,7 @@
<item>SHA3_512</item>
<item>SHA512</item>
<item>SHOW_PROGRESS</item>
+ <item>SIZE</item>
<item>STATUS</item>
<item>STRINGS</item>
<item>TIMEOUT</item>
@@ -484,8 +486,10 @@
<item>CACHE</item>
<item>DIRECTORY</item>
<item>EXT</item>
+ <item>LAST_EXT</item>
<item>NAME</item>
<item>NAME_WE</item>
+ <item>NAME_WLE</item>
<item>PATH</item>
<item>PROGRAM</item>
<item>PROGRAM_ARGS</item>
@@ -1054,6 +1058,7 @@
<item>COPY_FILE</item>
<item>COPY_FILE_ERROR</item>
<item>LINK_LIBRARIES</item>
+ <item>LINK_OPTIONS</item>
<item>OUTPUT_VARIABLE</item>
<item>RESULT_VAR</item>
<item>SOURCES</item>
@@ -1065,6 +1070,7 @@
<item>COMPILE_OUTPUT_VARIABLE</item>
<item>COMPILE_RESULT_VAR</item>
<item>LINK_LIBRARIES</item>
+ <item>LINK_OPTIONS</item>
<item>OUTPUT_VARIABLE</item>
<item>RUN_OUTPUT_VARIABLE</item>
<item>RUN_RESULT_VAR</item>
@@ -1209,6 +1215,7 @@
<item>CMAKE_ARCHIVE_OUTPUT_DIRECTORY</item>
<item>CMAKE_ARGC</item>
<item>CMAKE_ARGV0</item>
+ <item>CMAKE_AUTOGEN_ORIGIN_DEPENDS</item>
<item>CMAKE_AUTOGEN_PARALLEL</item>
<item>CMAKE_AUTOGEN_VERBOSE</item>
<item>CMAKE_AUTOMOC</item>
@@ -1223,6 +1230,7 @@
<item>CMAKE_BACKWARDS_COMPATIBILITY</item>
<item>CMAKE_BINARY_DIR</item>
<item>CMAKE_BUILD_RPATH</item>
+ <item>CMAKE_BUILD_RPATH_USE_ORIGIN</item>
<item>CMAKE_BUILD_TOOL</item>
<item>CMAKE_BUILD_TYPE</item>
<item>CMAKE_BUILD_WITH_INSTALL_NAME_DIR</item>
@@ -1297,6 +1305,7 @@
<item>CMAKE_FIND_PACKAGE_NAME</item>
<item>CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY</item>
<item>CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY</item>
+ <item>CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS</item>
<item>CMAKE_FIND_PACKAGE_SORT_DIRECTION</item>
<item>CMAKE_FIND_PACKAGE_SORT_ORDER</item>
<item>CMAKE_FIND_PACKAGE_WARN_NO_MODULE</item>
@@ -1316,6 +1325,10 @@
<item>CMAKE_GENERATOR_INSTANCE</item>
<item>CMAKE_GENERATOR_PLATFORM</item>
<item>CMAKE_GENERATOR_TOOLSET</item>
+ <item>CMAKE_GLOBAL_AUTOGEN_TARGET</item>
+ <item>CMAKE_GLOBAL_AUTOGEN_TARGET_NAME</item>
+ <item>CMAKE_GLOBAL_AUTORCC_TARGET</item>
+ <item>CMAKE_GLOBAL_AUTORCC_TARGET_NAME</item>
<item>CMAKE_GNUtoMS</item>
<item>CMAKE_HAS_ANSI_STRING_STREAM</item>
<item>CMAKE_HOME_DIRECTORY</item>
@@ -1412,6 +1425,7 @@
<item>CMAKE_MAJOR_VERSION</item>
<item>CMAKE_MAKE_PROGRAM</item>
<item>CMAKE_MATCH_COUNT</item>
+ <item>CMAKE_MAXIMUM_RECURSION_DEPTH</item>
<item>CMAKE_MFC_FLAG</item>
<item>CMAKE_MINIMUM_REQUIRED_VERSION</item>
<item>CMAKE_MINOR_VERSION</item>
@@ -1884,6 +1898,7 @@
<item>CTEST_SCP_COMMAND</item>
<item>CTEST_SITE</item>
<item>CTEST_SOURCE_DIRECTORY</item>
+ <item>CTEST_SUBMIT_URL</item>
<item>CTEST_SVN_COMMAND</item>
<item>CTEST_SVN_OPTIONS</item>
<item>CTEST_SVN_UPDATE_OPTIONS</item>
@@ -1964,6 +1979,8 @@
<item>PROJECT_VERSION_PATCH</item>
<item>PROJECT_VERSION_TWEAK</item>
<item>QTIFWDIR</item>
+ <item>SWIG_OUTFILE_DIR</item>
+ <item>SWIG_SOURCE_FILE_EXTENSIONS</item>
<item>THREADS_PREFER_PTHREAD_FLAG</item>
<item>UNIX</item>
<item>WIN32</item>
@@ -1982,6 +1999,7 @@
<item>AUTORCC_SOURCE_GROUP</item>
<item>CMAKE_CXX_KNOWN_FEATURES</item>
<item>CMAKE_C_KNOWN_FEATURES</item>
+ <item>CMAKE_ROLE</item>
<item>DEBUG_CONFIGURATIONS</item>
<item>DISABLED_FEATURES</item>
<item>ECLIPSE_EXTRA_NATURES</item>
@@ -2067,17 +2085,24 @@
<item>ARCHIVE_OUTPUT_DIRECTORY</item>
<item>ARCHIVE_OUTPUT_NAME</item>
<item>AUTOGEN_BUILD_DIR</item>
+ <item>AUTOGEN_ORIGIN_DEPENDS</item>
<item>AUTOGEN_TARGET_DEPENDS</item>
<item>AUTOMOC</item>
+ <item>AUTOMOC_COMPILER_PREDEFINES</item>
<item>AUTOMOC_DEPEND_FILTERS</item>
+ <item>AUTOMOC_EXECUTABLE</item>
+ <item>AUTOMOC_MACRO_NAMES</item>
<item>AUTOMOC_MOC_OPTIONS</item>
<item>AUTORCC</item>
+ <item>AUTORCC_EXECUTABLE</item>
<item>AUTORCC_OPTIONS</item>
<item>AUTOUIC</item>
+ <item>AUTOUIC_EXECUTABLE</item>
<item>AUTOUIC_OPTIONS</item>
<item>AUTOUIC_SEARCH_PATHS</item>
<item>BINARY_DIR</item>
<item>BUILD_RPATH</item>
+ <item>BUILD_RPATH_USE_ORIGIN</item>
<item>BUILD_WITH_INSTALL_NAME_DIR</item>
<item>BUILD_WITH_INSTALL_RPATH</item>
<item>BUNDLE</item>
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml
index 99b1d79c02..a6abda9204 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml
@@ -4,7 +4,7 @@
<!ENTITY wordsep "([][,?;()]|\.$|\.?\s)"> <!-- things that end a TagWord -->
]>
<language name="Doxygen"
- version="5"
+ version="6"
kateversion="5.0"
section="Markup"
extensions="*.dox;*.doxygen"
@@ -463,7 +463,7 @@
<itemData name="Tags" defStyleNum="dsAnnotation" bold="1" />
<itemData name="Custom Tags" defStyleNum="dsAnnotation" />
<itemData name="Word" defStyleNum="dsCommentVar" bold="1" italic="0" />
- <itemData name="HTML Tag" defStyleNum="dsKeyword" color="#000000" bold="1" italic="0" />
+ <itemData name="HTML Tag" defStyleNum="dsKeyword" bold="1" italic="0" />
<itemData name="Entities" defStyleNum="dsOthers" color="#4086C0" bold="1" italic="1" />
<itemData name="Description" defStyleNum="dsDocumentation" />
<itemData name="Comment" defStyleNum="dsComment" />
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml
index 4f9eb962d7..107e1067da 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml
@@ -5,7 +5,7 @@
<!ENTITY attributeName "[A-Za-z_:*#\(\[][\)\]\w.:_-]*">
<!ENTITY entref "&amp;(#[0-9]+|#[xX][0-9A-Fa-f]+|&name;);">
]>
-<language name="HTML" version="5" kateversion="3.4" section="Markup" extensions="*.htm;*.html;*.shtml;*.shtm" mimetype="text/html" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10">
+<language name="HTML" version="7" kateversion="3.4" section="Markup" extensions="*.htm;*.html;*.shtml;*.shtm" mimetype="text/html" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10">
<highlighting>
<contexts>
@@ -163,16 +163,23 @@
</context>
<context name="JS" attribute="Other Text" lineEndContext="#stay">
- <Detect2Chars attribute="Element" context="#pop" char="/" char1="&gt;" endRegion="script" />
+ <RegExpr attribute="Attribute" context="Script-Type" String="(\s+|^)type(?=\=|\s|$)" insensitive="true"/>
<DetectChar attribute="Element" context="JS content" char="&gt;" />
+ <IncludeRules context="DefaultJS" />
+ </context>
+ <context name="DefaultJS" attribute="Other Text" lineEndContext="#stay">
+ <Detect2Chars attribute="Element" context="#pop" char="/" char1="&gt;" endRegion="script" />
<IncludeRules context="FindAttributes" />
<RegExpr attribute="Error" context="#stay" String="\S" />
</context>
<context name="JS content" attribute="Other Text" lineEndContext="#stay">
+ <IncludeRules context="Default JS content"/>
+ <IncludeRules context="Normal##JavaScript" includeAttrib="true"/>
+ </context>
+ <context name="Default JS content" attribute="Other Text" lineEndContext="#stay">
<RegExpr attribute="Element" context="El Close 2" String="&lt;/script\b" insensitive="true" endRegion="script" />
<RegExpr attribute="Comment" context="JS comment close" String="//(?=.*&lt;/script\b)" insensitive="true" />
- <IncludeRules context="Normal##JavaScript" includeAttrib="true"/>
</context>
<context name="JS comment close" attribute="Comment" lineEndContext="#pop">
@@ -202,6 +209,79 @@
<IncludeRules context="FindEntityRefs" />
</context>
+ <!-- Read content from the "type" attribute to change the language to
+ highlight in the <script> tag. The default language is JavaScript. -->
+
+ <context name="Script-Type" attribute="Other Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop">
+ <DetectSpaces />
+ <DetectChar attribute="Attribute" context="#pop!Script-Type Value" char="=" />
+ </context>
+ <context name="Script-Type Value" attribute="Other Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop!Value">
+ <DetectSpaces />
+ <!-- TypeScript -->
+ <StringDetect attribute="Value" context="#pop#pop!TypeScript" String="&quot;text/typescript&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!TypeScript" String="&apos;text/typescript&apos;"/>
+ <!-- JSX (JavaScript React) -->
+ <StringDetect attribute="Value" context="#pop#pop!JSX" String="&quot;text/jsx&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!JSX" String="&apos;text/jsx&apos;"/>
+ <StringDetect attribute="Value" context="#pop#pop!JSX" String="&quot;text/babel&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!JSX" String="&apos;text/babel&apos;"/>
+ <!-- MustacheJS / HandlebarsJS / RactiveJS -->
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&quot;x-tmpl-mustache&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&apos;x-tmpl-mustache&apos;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&quot;text/mustache&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&apos;text/mustache&apos;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&quot;text/x-mustache-template&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&apos;text/x-mustache-template&apos;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&quot;text/x-handlebars-template&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&apos;text/x-handlebars-template&apos;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&quot;text/ractive&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="&apos;text/ractive&apos;"/>
+ <!-- HTML templates -->
+ <StringDetect attribute="Value" context="#pop#pop!Script HTML template" String="&quot;text/html&quot;"/>
+ <StringDetect attribute="Value" context="#pop#pop!Script HTML template" String="&apos;text/html&apos;"/>
+ </context>
+
+ <context name="JSX" attribute="Other Text" lineEndContext="#stay">
+ <DetectChar attribute="Element" context="JSX content" char="&gt;" />
+ <IncludeRules context="DefaultJS" />
+ </context>
+ <context name="JSX content" attribute="Other Text" lineEndContext="#stay">
+ <IncludeRules context="Default JS content"/>
+ <IncludeRules context="Normal##JavaScript React" includeAttrib="true"/>
+ </context>
+
+ <context name="TypeScript" attribute="Other Text" lineEndContext="#stay">
+ <DetectChar attribute="Element" context="TypeScript content" char="&gt;" />
+ <IncludeRules context="DefaultJS" />
+ </context>
+ <context name="TypeScript content" attribute="Other Text" lineEndContext="#stay">
+ <IncludeRules context="Default JS content"/>
+ <IncludeRules context="Normal##TypeScript" includeAttrib="true"/>
+ </context>
+
+ <context name="MustacheJS" attribute="Other Text" lineEndContext="#stay">
+ <DetectChar attribute="Element" context="MustacheJS content" char="&gt;" />
+ <IncludeRules context="DefaultJS" />
+ </context>
+ <context name="MustacheJS content" attribute="Other Text" lineEndContext="#stay">
+ <RegExpr attribute="Element" context="El Close 2" String="&lt;/script\b" insensitive="true" endRegion="script" />
+ <StringDetect attribute="Error" context="#stay" String="&lt;script&gt;" insensitive="true" />
+ <RegExpr attribute="Error" context="#stay" String="&lt;script\b" insensitive="true" />
+ <IncludeRules context="Base##Mustache/Handlebars (HTML)" includeAttrib="true"/>
+ </context>
+
+ <context name="Script HTML template" attribute="Other Text" lineEndContext="#stay">
+ <DetectChar attribute="Element" context="Script HTML template content" char="&gt;" />
+ <IncludeRules context="DefaultJS" />
+ </context>
+ <context name="Script HTML template content" attribute="Other Text" lineEndContext="#stay">
+ <RegExpr attribute="Element" context="El Close 2" String="&lt;/script\b" insensitive="true" endRegion="script" />
+ <StringDetect attribute="Error" context="#stay" String="&lt;script&gt;" insensitive="true" />
+ <RegExpr attribute="Error" context="#stay" String="&lt;script\b" insensitive="true" />
+ <IncludeRules context="FindHTML" />
+ </context>
+
</contexts>
<itemDatas>
<itemData name="Normal Text" defStyleNum="dsNormal" />
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml
index 465422f0b0..ce300fff47 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
-<language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc;*.conf" mimetype="" version="4" kateversion="2.4" author="Jan Janssen (medhefgo@web.de)" license="LGPL">
+<language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc" mimetype="" version="5" kateversion="2.4" author="Jan Janssen (medhefgo@web.de)" license="LGPL">
<highlighting>
<list name="keywords">
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml
index 39ffaf77af..f88848729f 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml
@@ -35,7 +35,7 @@
<!ENTITY strikeoutregex "[~]{2}[^~].*[^~][~]{2}">
<!-- pandoc style -->
]>
-<language name="Markdown" version="3" kateversion="3.8" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD">
+<language name="Markdown" version="6" kateversion="5.0" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD">
<highlighting>
<contexts>
<context attribute="Normal Text" lineEndContext="#stay" name="Normal Text">
@@ -74,13 +74,57 @@
<context attribute="comment" lineEndContext="#stay" name="comment">
<RegExpr String="--&gt;" attribute="comment" context="#pop" endRegion="comment"/>
</context>
+ <context attribute="code" lineEndContext="#stay" name="bash-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##Bash" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="cmake-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##CMake" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="cpp-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##C++" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="css-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##CSS" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="email-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##Email" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="haskell-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##Haskell" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="html-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##HTML" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="json-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##JSON" includeAttrib="true"/>
+ </context>
<context attribute="code" lineEndContext="#stay" name="php-code">
<WordDetect attribute="code" context="#pop" String="```"/>
- <IncludeRules context="phpsource##PHP/PHP"/>
+ <IncludeRules context="phpsource##PHP/PHP" includeAttrib="true"/>
</context>
<context attribute="code" lineEndContext="#stay" name="python-code">
<WordDetect attribute="code" context="#pop" String="```"/>
- <IncludeRules context="##Python"/>
+ <IncludeRules context="##Python" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="qml-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##QML" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="rust-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##Rust" includeAttrib="true"/>
+ </context>
+ <context attribute="code" lineEndContext="#stay" name="xml-code">
+ <WordDetect attribute="code" context="#pop" String="```"/>
+ <IncludeRules context="##XML" includeAttrib="true"/>
</context>
<context attribute="code" lineEndContext="#stay" name="code">
<WordDetect attribute="code" context="#pop" String="```"/>
@@ -98,8 +142,19 @@
<RegExpr attribute="mailtolink" String="&mailtolinkregex;"/>
<RegExpr attribute="strikeout" minimal="true" String="&strikeoutregex;"/>
<RegExpr attribute="linebreak" minimal="true" String="&linebreakregex;"/>
+ <WordDetect attribute="code" context="bash-code" String="```bash"/>
+ <WordDetect attribute="code" context="cmake-code" String="```cmake"/>
+ <WordDetect attribute="code" context="cpp-code" String="```cpp"/>
+ <WordDetect attribute="code" context="css-code" String="```css"/>
+ <WordDetect attribute="code" context="email-code" String="```email"/>
+ <WordDetect attribute="code" context="haskell-code" String="```haskell"/>
+ <WordDetect attribute="code" context="html-code" String="```html"/>
+ <WordDetect attribute="code" context="json-code" String="```json"/>
<WordDetect attribute="code" context="php-code" String="```php"/>
<WordDetect attribute="code" context="python-code" String="```python"/>
+ <WordDetect attribute="code" context="qml-code" String="```qml"/>
+ <WordDetect attribute="code" context="rust-code" String="```rust"/>
+ <WordDetect attribute="code" context="xml-code" String="```xml"/>
<StringDetect attribute="code" context="code" String="```"/>
</context>
</contexts>
@@ -121,12 +176,12 @@
<itemData name="blockquote" defStyleNum="dsDataType"/>
<itemData name="bq-emphasis" defStyleNum="dsDataType" italic="true"/>
<itemData name="bq-strong" defStyleNum="dsDataType" bold="true"/>
- <itemData name="bullet" defStyleNum="dsFloat"/>
- <itemData name="bl-emphasis" defStyleNum="dsFloat" italic="true"/>
- <itemData name="bl-strong" defStyleNum="dsFloat" bold="true"/>
- <itemData name="numlist" defStyleNum="dsFloat"/>
- <itemData name="nl-emphasis" defStyleNum="dsFloat" italic="true"/>
- <itemData name="nl-strong" defStyleNum="dsFloat" bold="true"/>
+ <itemData name="bullet" defStyleNum="dsString"/>
+ <itemData name="bl-emphasis" defStyleNum="dsString" italic="true"/>
+ <itemData name="bl-strong" defStyleNum="dsString" bold="true"/>
+ <itemData name="numlist" defStyleNum="dsString"/>
+ <itemData name="nl-emphasis" defStyleNum="dsString" italic="true"/>
+ <itemData name="nl-strong" defStyleNum="dsString" bold="true"/>
<itemData name="comment" defStyleNum="dsComment"/>
<itemData name="code" defStyleNum="dsBaseN"/>
<itemData name="reflink" defStyleNum="dsOthers" underline="true"/>
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml
index cd3d3ce65c..0d1931649c 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml
@@ -39,7 +39,7 @@
Enhance tr/// and y/// support.
-->
-<language name="Perl" version="7" kateversion="2.4" section="Scripts" extensions="*.pl;*.PL;*.pm;*.pl6;*.PL6;*.p6;*.pm6;" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2">
+<language name="Perl" version="8" kateversion="2.4" section="Scripts" extensions="*.pl;*.PL;*.pm;*.pl6;*.PL6;*.p6;*.pm6;" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2">
<highlighting>
<list name="keywords">
<item>if</item>
@@ -383,8 +383,11 @@
<RegExpr attribute="Operator" context="find_pattern" String="\b(?:m|qr)(?=\s*[^\w\s\]})])" />
- <RegExpr attribute="Normal Text" context="#stay" String="[\w_]+\s*/" />
- <RegExpr attribute="Normal Text" context="#stay" String="[&lt;&gt;&quot;':]/" />
+ <RegExpr attribute="Normal Text" context="#stay" String="[\w_]+\s*//?\=?" />
+ <RegExpr attribute="Normal Text" context="#stay" String="[&lt;&gt;&quot;':]//?\=?" />
+ <!-- Avoid conflicts between operators / and // -->
+ <StringDetect attribute="Normal Text" context="#stay" String="//=" />
+ <Detect2Chars attribute="Normal Text" context="#stay" char="/" char1="/" />
<DetectChar attribute="Operator" context="pattern_slash" char="/" beginRegion="Pattern" />
<RegExpr attribute="Operator" context="#stay" String="-[rwxoRWXOeszfdlpSbctugkTBMAC]\b" />
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml
index 754dfdc5fe..a451e1442f 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml
@@ -31,7 +31,7 @@
<!-- Hold the "language" opening tag on a single line, as mentioned in "language.dtd". -->
<language name="Ruby" section="Scripts"
- version="9" kateversion="3.3"
+ version="10" kateversion="3.3"
extensions="*.rb;*.rjs;*.rxml;*.xml.erb;*.js.erb;*.rake;Rakefile;Gemfile;*.gemspec;Vagrantfile"
mimetype="application/x-ruby"
style="ruby" indenter="ruby"
@@ -179,11 +179,11 @@
<item>warn</item>
</list>
- <list name="mixin-methods">
- <item>extend</item>
- <item>include</item>
- <item>prepend</item>
- </list>
+ <list name="mixin-methods">
+ <item>extend</item>
+ <item>include</item>
+ <item>prepend</item>
+ </list>
<contexts>
<context name="Normal" attribute="Normal Text" lineEndContext="#stay">
@@ -204,7 +204,7 @@
<RegExpr attribute="Keyword" String="\;\s*(while|until)\b(?!.*\bdo\b)" context="#stay" beginRegion="def block"/>
<RegExpr attribute="Keyword" String="(if|unless)\b" context="#stay" beginRegion="def block" firstNonSpace="true"/>
<RegExpr attribute="Keyword" String="\;\s*(if|unless)\b" context="#stay" beginRegion="def block"/>
- <WordDetect attribute="Keyword" String="class" context="#stay" beginRegion="def block"/>
+ <WordDetect attribute="Keyword" String="class" context="no_heredoc" beginRegion="def block"/>
<WordDetect attribute="Keyword" String="module" context="#stay" beginRegion="def block"/>
<WordDetect attribute="Keyword" String="begin" context="#stay" beginRegion="def block"/>
<RegExpr attribute="Keyword" String="\bfor\b(?!.*\bdo\b)" context="#stay" beginRegion="def block"/>
@@ -231,7 +231,7 @@
<keyword attribute="Pseudo variable" String="pseudo-variables" context="check_div_1"/>
<keyword attribute="Default globals" String="default-globals" context="check_div_2"/>
<keyword attribute="Kernel methods" String="kernel-methods" context="check_div_2"/>
- <keyword attribute="Module mixin methods" String="mixin-methods" context="check_div_2"/>
+ <keyword attribute="Module mixin methods" String="mixin-methods" context="check_div_2"/>
<!-- (global) vars starting with $
Match them before $_.
@@ -263,8 +263,8 @@
push operator '<<' than requiring to put space between the operator
and the string.
-->
- <RegExpr attribute="Operator" context="find_indented_heredoc" String="\s*&lt;&lt;-(?=\w+|[&quot;'])" beginRegion="HereDocument" />
- <RegExpr attribute="Operator" context="find_heredoc" String="\s*&lt;&lt;(?=\w+|[&quot;'])" beginRegion="HereDocument" />
+ <RegExpr attribute="Operator" context="find_indented_heredoc" String="\s*&lt;&lt;[-~](?=\w+|[&quot;'`])" beginRegion="HereDocument" />
+ <RegExpr attribute="Operator" context="find_heredoc" String="\s*&lt;&lt;(?=\w+|[&quot;'`])" beginRegion="HereDocument" />
<DetectChar attribute="Operator" char="." context="#stay"/>
<Detect2Chars attribute="Operator" char="&amp;" char1="&amp;" context="#stay"/>
@@ -280,8 +280,10 @@
<RegExpr attribute="Symbol" String=":(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?" context="check_div_1"/>
<RegExpr attribute="Symbol" String=":\[\]=?" context="check_div_1"/>
- <RegExpr attribute="Symbol" String="(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?: " context="check_div_1"/>
- <RegExpr attribute="Symbol" String="\[\]=?: " context="check_div_1"/>
+ <!-- Do not send to "check_div_1" context!:
+ after detecting these rules (": ") there can be a regular expression (see bug: #361875) -->
+ <RegExpr attribute="Symbol" String="(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?: " context="#stay"/>
+ <RegExpr attribute="Symbol" String="\[\]=?: " context="#stay"/>
<DetectChar attribute="String" char="&quot;" context="Quoted String"/>
<DetectChar attribute="Raw String" char="'" context="Apostrophed String"/>
@@ -436,13 +438,17 @@
The contexts below support both normal and indented heredocs
-->
<!-- here we markup the heredoc markers -->
- <context name="find_heredoc" attribute="Normal Text" lineEndContext="#pop" >
+ <context name="find_heredoc" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
<RegExpr attribute="Keyword" context="apostrophed_normal_heredoc" String="'(\w+)'" />
- <RegExpr attribute="Keyword" context="normal_heredoc" String="&quot;?(\w+)&quot;?" />
+ <RegExpr attribute="Keyword" context="normal_heredoc" String="(\w+)" />
+ <RegExpr attribute="Keyword" context="normal_heredoc" String="&quot;(\w+)&quot;" />
+ <RegExpr attribute="Keyword" context="normal_heredoc" String="`(\w+)`" />
</context>
- <context name="find_indented_heredoc" attribute="Normal Text" lineEndContext="#pop" >
+ <context name="find_indented_heredoc" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
<RegExpr attribute="Keyword" context="apostrophed_indented_heredoc" String="'(\w+)'" />
- <RegExpr attribute="Keyword" context="indented_heredoc" String="&quot;?(\w+)&quot;?" />
+ <RegExpr attribute="Keyword" context="indented_heredoc" String="(\w+)" />
+ <RegExpr attribute="Keyword" context="indented_heredoc" String="&quot;(\w+)&quot;" />
+ <RegExpr attribute="Keyword" context="indented_heredoc" String="`(\w+)`" />
</context>
<!-- these are the real heredoc contexts -->
<context name="indented_heredoc" attribute="Here Document" lineEndContext="#stay" dynamic="true">
@@ -467,6 +473,16 @@
<Detect2Chars attribute="Substitution" char="#" char1="{" context="Subst"/>
</context>
+ <!-- avoid highlighting heredoc markers, for example, in singleton class definition (see bug: #358273) -->
+ <context name="no_heredoc" attribute="Normal Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop">
+ <DetectSpaces />
+ <Detect2Chars attribute="Operator" char="&lt;" char1="&lt;" context="#pop"/>
+ <!-- comments -->
+ <RegExpr attribute="Comment" String="#\s*BEGIN.*$" context="#stay" beginRegion="marker" column="0"/>
+ <RegExpr attribute="Comment" String="#\s*END.*$" context="#stay" endRegion="marker" column="0"/>
+ <DetectChar attribute="Comment" char="#" context="General Comment"/>
+ </context>
+
<!-- General delimited input support
The contexts below handle the various gdl formats
-->
@@ -892,7 +908,7 @@
<itemData name="Constant" defStyleNum="dsDataType"/>
<itemData name="Constant Value" defStyleNum="dsDataType" color="#bb1188"/>
<itemData name="Kernel methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 -->
- <itemData name="Module mixin methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 -->
+ <itemData name="Module mixin methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 -->
<itemData name="Member" defStyleNum="dsNormal"/>
<itemData name="Instance Variable" defStyleNum="dsOthers"/>
<itemData name="Class Variable" defStyleNum="dsOthers"/>
@@ -913,3 +929,5 @@
<keywords casesensitive="1" weakDeliminator="!?"/>
</general>
</language>
+
+<!-- kate: replace-tabs off; -->
diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml
index 6936c7a2de..06d6492ff1 100644
--- a/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml
+++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml
@@ -32,7 +32,7 @@ This code is released under the LGPL as part of kdelibs/kate.
========================================================================
-->
-<language name="Yacc/Bison" version="4" kateversion="2.4" section="Sources" extensions="*.y;*.yy;*.ypp;*.y++" mimetype="text/x-yacc;text/x-bison" priority="5" author="Jan Villat (jan.villat@net2000.ch)" license="LGPL">
+<language name="Yacc/Bison" version="5" kateversion="5.0" section="Sources" extensions="*.y;*.yy;*.ypp;*.y++" mimetype="text/x-yacc;text/x-bison" priority="5" author="Jan Villat (jan.villat@net2000.ch)" license="LGPL">
<highlighting>
<contexts>
@@ -200,9 +200,12 @@ This code is released under the LGPL as part of kdelibs/kate.
</context>
<context name="CommentStar" attribute="Comment" lineEndContext="#stay">
<Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
+ <IncludeRules context="##Alerts" />
+ <IncludeRules context="##Modelines" />
</context>
- <context name="CommentSlash" attribute="Comment" lineEndContext="#stay">
- <RegExpr attribute="Comment" context="#pop" String="[^\\]$" />
+ <context name="CommentSlash" attribute="Comment" lineEndContext="#pop">
+ <IncludeRules context="##Alerts" />
+ <IncludeRules context="##Modelines" />
</context>
<context name="StringOrChar" attribute="Normal Text" lineEndContext="#stay">
diff --git a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp
index 80a15d2589..8334dd32e9 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp
@@ -92,14 +92,14 @@ int main(int argc, char **argv)
Repository repo;
if (parser.isSet(listDefs)) {
- foreach (const auto &def, repo.definitions()) {
+ for (const auto &def : repo.definitions()) {
std::cout << qPrintable(def.name()) << std::endl;
}
return 0;
}
if (parser.isSet(listThemes)) {
- foreach (const auto &theme, repo.themes())
+ for (const auto &theme : repo.themes())
std::cout << qPrintable(theme.name()) << std::endl;
return 0;
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp
index 489fbec160..3534cfde90 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp
@@ -194,6 +194,82 @@ bool checkLookAhead(const QString &hlFilename, QXmlStreamReader &xml)
}
/**
+ * Helper class to search for non-existing keyword include.
+ */
+class KeywordIncludeChecker
+{
+public:
+ void processElement(const QString &hlFilename, const QString &hlName, QXmlStreamReader &xml)
+ {
+ if (xml.name() == QLatin1String("list")) {
+ auto &keywords = m_keywordMap[hlName];
+ keywords.filename = hlFilename;
+ auto name = xml.attributes().value(QLatin1String("name")).toString();
+ m_currentIncludes = &keywords.includes[name];
+ }
+ else if (xml.name() == QLatin1String("include")) {
+ if (!m_currentIncludes) {
+ qWarning() << hlFilename << "line" << xml.lineNumber() << "<include> tag ouside <list>";
+ m_success = false;
+ } else {
+ m_currentIncludes->push_back({xml.lineNumber(), xml.readElementText()});
+ }
+ }
+ }
+
+ bool check() const
+ {
+ bool success = m_success;
+ for (auto &keywords : m_keywordMap) {
+ QMapIterator<QString, QVector<Keywords::Include>> includes(keywords.includes);
+ while (includes.hasNext()) {
+ includes.next();
+ for (auto &include : includes.value()) {
+ bool containsKeywordName = true;
+ int const idx = include.name.indexOf(QStringLiteral("##"));
+ if (idx == -1) {
+ auto &keywordName = includes.key();
+ containsKeywordName = keywords.includes.contains(keywordName);
+ }
+ else {
+ auto defName = include.name.mid(idx + 2);
+ auto listName = include.name.left(idx);
+ auto it = m_keywordMap.find(defName);
+ if (it == m_keywordMap.end()) {
+ qWarning() << keywords.filename << "line" << include.line << "unknown definition in" << include.name;
+ success = false;
+ } else {
+ containsKeywordName = it->includes.contains(listName);
+ }
+ }
+
+ if (!containsKeywordName) {
+ qWarning() << keywords.filename << "line" << include.line << "unknown keyword name in" << include.name;
+ success = false;
+ }
+ }
+ }
+ }
+ return success;
+ }
+
+private:
+ struct Keywords
+ {
+ QString filename;
+ struct Include
+ {
+ qint64 line;
+ QString name;
+ };
+ QMap<QString, QVector<Include>> includes;
+ };
+ QHash<QString, Keywords> m_keywordMap;
+ QVector<Keywords::Include> *m_currentIncludes = nullptr;
+ bool m_success = true;
+};
+
+/**
* Helper class to search for non-existing or unreferenced keyword lists.
*/
class KeywordChecker
@@ -296,6 +372,7 @@ public:
const auto unusedNames = language.existingContextNames - language.usedContextNames;
if (!unusedNames.isEmpty()) {
qWarning() << language.hlFilename << "Unused contexts:" << unusedNames;
+ success = false;
}
}
@@ -457,9 +534,10 @@ int main(int argc, char *argv[])
// index all given highlightings
ContextChecker contextChecker;
+ KeywordIncludeChecker keywordIncludeChecker;
QVariantMap hls;
int anyError = 0;
- foreach (const QString &hlFilename, hlFilenames) {
+ for (const QString &hlFilename : qAsConst(hlFilenames)) {
QFile hlFile(hlFilename);
if (!hlFile.open(QIODevice::ReadOnly)) {
qWarning ("Failed to open %s", qPrintable(hlFilename));
@@ -493,7 +571,7 @@ int main(int argc, char *argv[])
QVariantMap hl;
// transfer text attributes
- Q_FOREACH (const QString &attribute, textAttributes) {
+ for (const QString &attribute : qAsConst(textAttributes)) {
hl[attribute] = xml.attributes().value(attribute).toString();
}
@@ -528,6 +606,9 @@ int main(int argc, char *argv[])
// search for used/existing contexts if applicable
contextChecker.processElement(hlFilename, hlName, xml);
+ // search for existing keyword includes
+ keywordIncludeChecker.processElement(hlFilename, hlName, xml);
+
// search for used/existing attributes if applicable
attributeChecker.processElement(xml);
@@ -571,6 +652,9 @@ int main(int argc, char *argv[])
if (!contextChecker.check())
anyError = 7;
+ if (!keywordIncludeChecker.check())
+ anyError = 7;
+
// bail out if any problem was seen
if (anyError)
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
index bf729fca71..95bf4c349e 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt
@@ -40,6 +40,7 @@ ecm_generate_headers(SyntaxHighlighting_HEADERS
HEADER_NAMES
AbstractHighlighter
Definition
+ DefinitionDownloader
FoldingRegion
Format
Repository
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp
index f69944debd..c4ef86a771 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp
@@ -53,7 +53,7 @@ void AbstractHighlighterPrivate::ensureDefinitionLoaded()
defData = DefinitionData::get(m_definition);
}
- if (Q_UNLIKELY(!defData->repo && !defData->name.isEmpty()))
+ if (Q_UNLIKELY(!defData->repo && !defData->fileName.isEmpty()))
qCCritical(Log) << "Repository got deleted while a highlighter is still active!";
if (m_definition.isValid())
@@ -118,13 +118,13 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
// verify definition, deal with no highlighting being enabled
d->ensureDefinitionLoaded();
- if (!d->m_definition.isValid()) {
+ const auto defData = DefinitionData::get(d->m_definition);
+ if (!d->m_definition.isValid() || !defData->isLoaded()) {
applyFormat(0, text.size(), Format());
return State();
}
// verify/initialize state
- auto defData = DefinitionData::get(d->m_definition);
auto newState = state;
auto stateData = StateData::get(newState);
const DefinitionRef currentDefRef(d->m_definition);
@@ -139,9 +139,37 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
// process empty lines
if (text.isEmpty()) {
- while (!stateData->topContext()->lineEmptyContext().isStay()) {
- if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList()))
+ /**
+ * handle line empty context switches
+ * guard against endless loops
+ * see https://phabricator.kde.org/D18509
+ */
+ int endlessLoopingCounter = 0;
+ while (!stateData->topContext()->lineEmptyContext().isStay() || (stateData->topContext()->lineEmptyContext().isStay() && !stateData->topContext()->lineEndContext().isStay())) {
+ /**
+ * line empty context switches
+ */
+ if (!stateData->topContext()->lineEmptyContext().isStay()) {
+ if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList())) {
+ /**
+ * end when trying to #pop the main context
+ */
+ break;
+ }
+ /**
+ * line end context switches only when lineEmptyContext is #stay. This avoids
+ * skipping empty lines after a line continuation character (see bug 405903)
+ */
+ } else if (!stateData->topContext()->lineEndContext().isStay() &&
+ !d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList()))
break;
+
+ // guard against endless loops
+ ++endlessLoopingCounter;
+ if (endlessLoopingCounter > 1024) {
+ qCDebug(Log) << "Endless switch context transitions for line empty context, aborting highlighting of line.";
+ break;
+ }
}
auto context = stateData->topContext();
applyFormat(0, 0, context->attributeFormat());
@@ -238,11 +266,18 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
if (newOffset <= offset)
continue;
- // apply folding
- if (rule->endRegion().isValid())
- applyFolding(offset, newOffset - offset, rule->endRegion());
+ /**
+ * apply folding.
+ * special cases:
+ * - rule with endRegion + beginRegion: in endRegion, the length is 0
+ * - rule with lookAhead: length is 0
+ */
+ if (rule->endRegion().isValid() && rule->beginRegion().isValid())
+ applyFolding(offset, 0, rule->endRegion());
+ else if (rule->endRegion().isValid())
+ applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->endRegion());
if (rule->beginRegion().isValid())
- applyFolding(offset, newOffset - offset, rule->beginRegion());
+ applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->beginRegion());
if (rule->isLookAhead()) {
Q_ASSERT(!rule->context().isStay());
@@ -293,12 +328,30 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
} while (offset < text.size());
+ /**
+ * apply format for remaining text, if any
+ */
if (beginOffset < offset)
applyFormat(beginOffset, text.size() - beginOffset, *currentFormat);
- while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) {
- if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList()))
- break;
+ /**
+ * handle line end context switches
+ * guard against endless loops
+ * see https://phabricator.kde.org/D18509
+ */
+ {
+ int endlessLoopingCounter = 0;
+ while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) {
+ if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList()))
+ break;
+
+ // guard against endless loops
+ ++endlessLoopingCounter;
+ if (endlessLoopingCounter > 1024) {
+ qCDebug(Log) << "Endless switch context transitions for line end context, aborting highlighting of line.";
+ break;
+ }
+ }
}
return newState;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
index c03d23dc48..ae95a6b235 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp
@@ -31,6 +31,7 @@
#include "context_p.h"
#include "format.h"
#include "format_p.h"
+#include "repository.h"
#include "repository_p.h"
#include "rule_p.h"
#include "ksyntaxhighlighting_logging.h"
@@ -222,13 +223,13 @@ QStringList Definition::foldingIgnoreList() const
QStringList Definition::keywordLists() const
{
- d->load();
+ d->load(DefinitionData::OnlyKeywords(true));
return d->keywordLists.keys();
}
QStringList Definition::keywordList(const QString& name) const
{
- d->load();
+ d->load(DefinitionData::OnlyKeywords(true));
const auto list = d->keywordList(name);
return list ? list->keywords() : QStringList();
}
@@ -323,18 +324,18 @@ Context* DefinitionData::initialContext() const
return contexts.first();
}
-Context* DefinitionData::contextByName(const QString& name) const
+Context* DefinitionData::contextByName(const QString& wantedName) const
{
- foreach (auto context, contexts) {
- if (context->name() == name)
+ for (const auto context : contexts) {
+ if (context->name() == wantedName)
return context;
}
return nullptr;
}
-KeywordList *DefinitionData::keywordList(const QString& name)
+KeywordList *DefinitionData::keywordList(const QString& wantedName)
{
- auto it = keywordLists.find(name);
+ auto it = keywordLists.find(wantedName);
return (it == keywordLists.end()) ? nullptr : &it.value();
}
@@ -343,9 +344,9 @@ bool DefinitionData::isWordDelimiter(QChar c) const
return std::binary_search(wordDelimiters.constBegin(), wordDelimiters.constEnd(), c);
}
-Format DefinitionData::formatByName(const QString& name) const
+Format DefinitionData::formatByName(const QString& wantedName) const
{
- const auto it = formats.constFind(name);
+ const auto it = formats.constFind(wantedName);
if (it != formats.constEnd())
return it.value();
@@ -357,7 +358,7 @@ bool DefinitionData::isLoaded() const
return !contexts.isEmpty();
}
-bool DefinitionData::load()
+bool DefinitionData::load(OnlyKeywords onlyKeywords)
{
if (fileName.isEmpty())
return false;
@@ -365,6 +366,9 @@ bool DefinitionData::load()
if (isLoaded())
return true;
+ if (bool(onlyKeywords) && keywordIsLoaded)
+ return true;
+
QFile file(fileName);
if (!file.open(QFile::ReadOnly))
return false;
@@ -375,17 +379,22 @@ bool DefinitionData::load()
if (token != QXmlStreamReader::StartElement)
continue;
- if (reader.name() == QLatin1String("highlighting"))
- loadHighlighting(reader);
+ if (reader.name() == QLatin1String("highlighting")) {
+ loadHighlighting(reader, onlyKeywords);
+ if (bool(onlyKeywords)) {
+ return true;
+ }
+ }
else if (reader.name() == QLatin1String("general"))
loadGeneral(reader);
}
- for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it)
- (*it).setCaseSensitivity(caseSensitive);
+ for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) {
+ it->setCaseSensitivity(caseSensitive);
+ }
- foreach (auto context, contexts) {
+ for (const auto context : qAsConst(contexts)) {
context->resolveContexts();
context->resolveIncludes();
context->resolveAttributeFormat();
@@ -454,10 +463,10 @@ bool DefinitionData::loadMetaData(const QString &file, const QJsonObject &obj)
fileName = file;
const auto exts = obj.value(QLatin1String("extensions")).toString();
- foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ for (const auto &ext : exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
extensions.push_back(ext);
const auto mts = obj.value(QLatin1String("mimetype")).toString();
- foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ for (const auto &mt : mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
mimetypes.push_back(mt);
return true;
@@ -482,29 +491,42 @@ bool DefinitionData::loadLanguage(QXmlStreamReader &reader)
author = reader.attributes().value(QStringLiteral("author")).toString();
license = reader.attributes().value(QStringLiteral("license")).toString();
const auto exts = reader.attributes().value(QStringLiteral("extensions")).toString();
- foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ for (const auto &ext : exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
extensions.push_back(ext);
const auto mts = reader.attributes().value(QStringLiteral("mimetype")).toString();
- foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
+ for (const auto &mt : mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
mimetypes.push_back(mt);
if (reader.attributes().hasAttribute(QStringLiteral("casesensitive")))
caseSensitive = Xml::attrToBool(reader.attributes().value(QStringLiteral("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
return true;
}
-void DefinitionData::loadHighlighting(QXmlStreamReader& reader)
+void DefinitionData::loadHighlighting(QXmlStreamReader& reader, OnlyKeywords onlyKeywords)
{
Q_ASSERT(reader.name() == QLatin1String("highlighting"));
Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
+ // skip highlighting
+ reader.readNext();
+
while (!reader.atEnd()) {
switch (reader.tokenType()) {
case QXmlStreamReader::StartElement:
if (reader.name() == QLatin1String("list")) {
- KeywordList keywords;
- keywords.load(reader);
- keywordLists.insert(keywords.name(), keywords);
+ if (!keywordIsLoaded) {
+ KeywordList keywords;
+ keywords.load(reader);
+ keywordLists.insert(keywords.name(), keywords);
+ }
+ else {
+ reader.skipCurrentElement();
+ reader.readNext(); // Skip </list>
+ }
+ } else if (bool(onlyKeywords)) {
+ resolveIncludeKeywords();
+ return;
} else if (reader.name() == QLatin1String("contexts")) {
+ resolveIncludeKeywords();
loadContexts(reader);
reader.readNext();
} else if (reader.name() == QLatin1String("itemDatas")) {
@@ -522,6 +544,19 @@ void DefinitionData::loadHighlighting(QXmlStreamReader& reader)
}
}
+void DefinitionData::resolveIncludeKeywords()
+{
+ if (keywordIsLoaded) {
+ return;
+ }
+
+ keywordIsLoaded = true;
+
+ for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) {
+ it->resolveIncludeKeywords(*this);
+ }
+}
+
void DefinitionData::loadContexts(QXmlStreamReader& reader)
{
Q_ASSERT(reader.name() == QLatin1String("contexts"));
@@ -598,7 +633,7 @@ void DefinitionData::loadGeneral(QXmlStreamReader& reader)
std::sort(wordDelimiters.begin(), wordDelimiters.end());
auto it = std::unique(wordDelimiters.begin(), wordDelimiters.end());
wordDelimiters.truncate(std::distance(wordDelimiters.begin(), it));
- foreach (const auto c, reader.attributes().value(QLatin1String("weakDeliminator")))
+ for (const auto c : reader.attributes().value(QLatin1String("weakDeliminator")))
wordDelimiters.remove(c);
// adaptWordWrapDelimiters, and sort
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h
index ab95a9552c..9bbf59691c 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h
@@ -46,6 +46,9 @@ public:
DefinitionData();
~DefinitionData();
+ DefinitionData(const DefinitionData &) = delete;
+ DefinitionData &operator=(const DefinitionData &) = delete;
+
static DefinitionData* get(const Definition &def);
bool isLoaded() const;
@@ -54,9 +57,11 @@ public:
void clear();
- bool load();
+ enum class OnlyKeywords : bool;
+
+ bool load(OnlyKeywords onlyKeywords = OnlyKeywords(false));
bool loadLanguage(QXmlStreamReader &reader);
- void loadHighlighting(QXmlStreamReader &reader);
+ void loadHighlighting(QXmlStreamReader &reader, OnlyKeywords onlyKeywords);
void loadContexts(QXmlStreamReader &reader);
void loadItemData(QXmlStreamReader &reader);
void loadGeneral(QXmlStreamReader &reader);
@@ -65,6 +70,8 @@ public:
void loadSpellchecking(QXmlStreamReader &reader);
bool checkKateVersion(const QStringRef &verStr);
+ void resolveIncludeKeywords();
+
KeywordList *keywordList(const QString &name);
bool isWordDelimiter(QChar c) const;
@@ -83,6 +90,7 @@ public:
QHash<QString, Format> formats;
QString wordDelimiters;
QString wordWrapDelimiters;
+ bool keywordIsLoaded = false;
bool hasFoldingRegions = false;
bool indentationBasedFolding = false;
QStringList foldingIgnoreList;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp
index 397da6d700..d1808cafef 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp
@@ -213,52 +213,52 @@ void FormatPrivate::load(QXmlStreamReader& reader)
name = reader.attributes().value(QStringLiteral("name")).toString();
defaultStyle = stringToDefaultFormat(reader.attributes().value(QStringLiteral("defStyleNum")));
- QStringRef ref = reader.attributes().value(QStringLiteral("color"));
- if (!ref.isEmpty()) {
- style.textColor = QColor(ref.toString()).rgba();
+ QStringRef attribute = reader.attributes().value(QStringLiteral("color"));
+ if (!attribute.isEmpty()) {
+ style.textColor = QColor(attribute.toString()).rgba();
}
- ref = reader.attributes().value(QStringLiteral("selColor"));
- if (!ref.isEmpty()) {
- style.selectedTextColor = QColor(ref.toString()).rgba();
+ attribute = reader.attributes().value(QStringLiteral("selColor"));
+ if (!attribute.isEmpty()) {
+ style.selectedTextColor = QColor(attribute.toString()).rgba();
}
- ref = reader.attributes().value(QStringLiteral("backgroundColor"));
- if (!ref.isEmpty()) {
- style.backgroundColor = QColor(ref.toString()).rgba();
+ attribute = reader.attributes().value(QStringLiteral("backgroundColor"));
+ if (!attribute.isEmpty()) {
+ style.backgroundColor = QColor(attribute.toString()).rgba();
}
- ref = reader.attributes().value(QStringLiteral("selBackgroundColor"));
- if (!ref.isEmpty()) {
- style.selectedBackgroundColor = QColor(ref.toString()).rgba();
+ attribute = reader.attributes().value(QStringLiteral("selBackgroundColor"));
+ if (!attribute.isEmpty()) {
+ style.selectedBackgroundColor = QColor(attribute.toString()).rgba();
}
- ref = reader.attributes().value(QStringLiteral("italic"));
- if (!ref.isEmpty()) {
+ attribute = reader.attributes().value(QStringLiteral("italic"));
+ if (!attribute.isEmpty()) {
style.hasItalic = true;
- style.italic = Xml::attrToBool(ref);
+ style.italic = Xml::attrToBool(attribute);
}
- ref = reader.attributes().value(QStringLiteral("bold"));
- if (!ref.isEmpty()) {
+ attribute = reader.attributes().value(QStringLiteral("bold"));
+ if (!attribute.isEmpty()) {
style.hasBold = true;
- style.bold = Xml::attrToBool(ref);
+ style.bold = Xml::attrToBool(attribute);
}
- ref = reader.attributes().value(QStringLiteral("underline"));
- if (!ref.isEmpty()) {
+ attribute = reader.attributes().value(QStringLiteral("underline"));
+ if (!attribute.isEmpty()) {
style.hasUnderline = true;
- style.underline = Xml::attrToBool(ref);
+ style.underline = Xml::attrToBool(attribute);
}
- ref = reader.attributes().value(QStringLiteral("strikeOut"));
- if (!ref.isEmpty()) {
+ attribute = reader.attributes().value(QStringLiteral("strikeOut"));
+ if (!attribute.isEmpty()) {
style.hasStrikeThrough = true;
- style.strikeThrough = Xml::attrToBool(ref);
+ style.strikeThrough = Xml::attrToBool(attribute);
}
- ref = reader.attributes().value(QStringLiteral("spellChecking"));
- if (!ref.isEmpty()) {
- spellCheck = Xml::attrToBool(ref);
+ attribute = reader.attributes().value(QStringLiteral("spellChecking"));
+ if (!attribute.isEmpty()) {
+ spellCheck = Xml::attrToBool(attribute);
}
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
index fe5f77586a..f042baac27 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp
@@ -22,6 +22,9 @@
*/
#include "keywordlist_p.h"
+#include "repository.h"
+#include "definition_p.h"
+#include "ksyntaxhighlighting_logging.h"
#include <QDebug>
#include <QXmlStreamReader>
@@ -58,6 +61,11 @@ void KeywordList::load(QXmlStreamReader& reader)
reader.readNextStartElement();
break;
}
+ else if (reader.name() == QLatin1String("include")) {
+ m_includes.append(reader.readElementText().trimmed());
+ reader.readNextStartElement();
+ break;
+ }
reader.readNext();
break;
case QXmlStreamReader::EndElement:
@@ -102,3 +110,40 @@ void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive
*/
std::sort(vectorToSort.begin(), vectorToSort.end(), [caseSensitive] (const QStringRef &a, const QStringRef &b) { return a.compare(b, caseSensitive) < 0; });
}
+
+void KeywordList::resolveIncludeKeywords(DefinitionData &def)
+{
+ while (!m_includes.isEmpty()) {
+ const auto kw_include = std::move(m_includes.back());
+ m_includes.pop_back();
+
+ const auto idx = kw_include.indexOf(QLatin1String("##"));
+ KeywordList *keywords = nullptr;
+
+ if (idx >= 0) {
+ auto listName = kw_include.left(idx);
+ auto defName = kw_include.mid(idx + 2);
+ auto includeDef = def.repo->definitionForName(defName);
+ if (includeDef.isValid()) {
+ auto defData = DefinitionData::get(includeDef);
+ defData->load(DefinitionData::OnlyKeywords(true));
+ keywords = defData->keywordList(listName);
+ }
+ else {
+ qCWarning(Log) << "Unable to resolve external include keyword for definition" << defName << "in" << def.name;
+ }
+ } else {
+ keywords = def.keywordList(kw_include);
+ }
+
+ if (keywords) {
+ if (this != keywords) {
+ keywords->resolveIncludeKeywords(def);
+ }
+ m_keywords += keywords->m_keywords;
+ }
+ else {
+ qCWarning(Log) << "Unresolved include keyword" << kw_include << "in" << def.name;
+ }
+ }
+}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h
index 8c41aabe0c..25d0022dbe 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h
@@ -36,6 +36,9 @@ QT_END_NAMESPACE
namespace KSyntaxHighlighting {
+class Repository;
+class DefinitionData;
+
class KeywordList
{
public:
@@ -69,6 +72,7 @@ public:
void load(QXmlStreamReader &reader);
void setCaseSensitivity(Qt::CaseSensitivity caseSensitive);
void initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive);
+ void resolveIncludeKeywords(DefinitionData &def);
private:
/**
@@ -82,6 +86,11 @@ private:
QStringList m_keywords;
/**
+ * raw list of include keywords, as seen in XML (but trimmed)
+ */
+ QStringList m_includes;
+
+ /**
* default case-sensitivity setting
*/
Qt::CaseSensitivity m_caseSensitive = Qt::CaseSensitive;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
index 922225a7e1..aaba9616dc 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp
@@ -69,7 +69,7 @@ Repository::~Repository()
{
// reset repo so we can detect in still alive definition instances
// that the repo was deleted
- foreach (const auto &def, d->m_sortedDefs)
+ for (const auto &def : qAsConst(d->m_sortedDefs))
DefinitionData::get(def)->repo = nullptr;
}
@@ -78,21 +78,16 @@ Definition Repository::definitionForName(const QString& defName) const
return d->m_defs.value(defName);
}
-static Definition bestCandidate(QVector<Definition> &&candidates)
+static void sortDefinitions(QVector<Definition> &definitions)
{
- if (candidates.isEmpty())
- return Definition();
-
- std::partial_sort(candidates.begin(), candidates.begin() + 1, candidates.end(), [](const Definition &lhs, const Definition &rhs) {
+ std::stable_sort(definitions.begin(), definitions.end(), [](const Definition &lhs, const Definition &rhs) {
return lhs.priority() > rhs.priority();
});
-
- return candidates.at(0);
}
Definition Repository::definitionForFileName(const QString& fileName) const
{
- return bestCandidate(definitionsForFileName(fileName));
+ return definitionsForFileName(fileName).value(0);
}
QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const
@@ -101,9 +96,8 @@ QVector<Definition> Repository::definitionsForFileName(const QString &fileName)
const auto name = fi.fileName();
QVector<Definition> candidates;
- for (auto it = d->m_defs.constBegin(); it != d->m_defs.constEnd(); ++it) {
- auto def = it.value();
- foreach (const auto &pattern, def.extensions()) {
+ for (const Definition &def : qAsConst(d->m_sortedDefs)) {
+ for (const auto &pattern : def.extensions()) {
if (WildcardMatcher::exactMatch(name, pattern)) {
candidates.push_back(def);
break;
@@ -111,26 +105,28 @@ QVector<Definition> Repository::definitionsForFileName(const QString &fileName)
}
}
+ sortDefinitions(candidates);
return candidates;
}
Definition Repository::definitionForMimeType(const QString& mimeType) const
{
- return bestCandidate(definitionsForMimeType(mimeType));
+ return definitionsForMimeType(mimeType).value(0);
}
QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const
{
QVector<Definition> candidates;
- for (auto it = d->m_defs.constBegin(); it != d->m_defs.constEnd(); ++it) {
- auto def = it.value();
- foreach (const auto &matchType, def.mimeTypes()) {
+ for (const Definition &def : qAsConst(d->m_sortedDefs)) {
+ for (const auto &matchType : def.mimeTypes()) {
if (mimeType == matchType) {
candidates.push_back(def);
break;
}
}
}
+
+ sortDefinitions(candidates);
return candidates;
}
@@ -169,11 +165,11 @@ void RepositoryPrivate::load(Repository *repo)
// do lookup in standard paths, if not disabled
#ifndef NO_STANDARD_PATHS
- foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory))
+ for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory))
loadSyntaxFolder(repo, dir);
// backward compatibility with Kate
- foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory))
+ for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory))
loadSyntaxFolder(repo, dir);
#endif
@@ -181,7 +177,7 @@ void RepositoryPrivate::load(Repository *repo)
loadSyntaxFolder(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax"));
// user given extra paths
- foreach (const auto &path, m_customSearchPaths)
+ for (const auto &path : qAsConst(m_customSearchPaths))
loadSyntaxFolder(repo, path + QStringLiteral("/syntax"));
m_sortedDefs.reserve(m_defs.size());
@@ -198,7 +194,7 @@ void RepositoryPrivate::load(Repository *repo)
// do lookup in standard paths, if not disabled
#ifndef NO_STANDARD_PATHS
- foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory))
+ for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory))
loadThemeFolder(dir);
#endif
@@ -206,7 +202,7 @@ void RepositoryPrivate::load(Repository *repo)
loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes"));
// user given extra paths
- foreach (const auto &path, m_customSearchPaths)
+ for (const auto &path : qAsConst(m_customSearchPaths))
loadThemeFolder(path + QStringLiteral("/themes"));
}
@@ -307,7 +303,7 @@ quint16 RepositoryPrivate::nextFormatId()
void Repository::reload()
{
qCDebug(Log) << "Reloading syntax definitions!";
- foreach (const auto &def, d->m_sortedDefs)
+ for (const auto &def : qAsConst(d->m_sortedDefs))
DefinitionData::get(def)->clear();
d->m_defs.clear();
d->m_sortedDefs.clear();
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
index e4e9bed69f..2bc66965cf 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h
@@ -167,9 +167,11 @@ public:
Definition definitionForFileName(const QString &fileName) const;
/**
- * Returns all Definition%s for the file named @p fileName.
+ * Returns all Definition%s for the file named @p fileName sorted by priority.
* The match is performed based on the \e extensions and @e mimetype of
* the definition files.
+ *
+ * @since 5.56
*/
QVector<Definition> definitionsForFileName(const QString &fileName) const;
@@ -184,7 +186,9 @@ public:
Definition definitionForMimeType(const QString &mimeType) const;
/**
- * Returns all Definition%s to the type named @p mimeType
+ * Returns all Definition%s to the type named @p mimeType sorted by priority
+ *
+ * @since 5.56
*/
QVector<Definition> definitionsForMimeType(const QString &mimeType) const;
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
index c48753bf0c..d9cf5eb211 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp
@@ -59,7 +59,8 @@ static int matchEscapedChar(const QString &text, int offset)
if (controlChars.contains(c))
return offset + 2;
- if (c == QLatin1Char('x')) { // hex encoded character
+ // hex encoded character
+ if (c == QLatin1Char('x')) {
auto newOffset = offset + 2;
for (int i = 0; i < 2 && newOffset + i < text.size(); ++i, ++newOffset) {
if (!isHexChar(text.at(newOffset)))
@@ -70,14 +71,13 @@ static int matchEscapedChar(const QString &text, int offset)
return newOffset;
}
- if (isOctalChar(c)) { // octal encoding
+ // octal encoding, simple \0 is OK, too, unlike simple \x above
+ if (isOctalChar(c)) {
auto newOffset = offset + 2;
for (int i = 0; i < 2 && newOffset + i < text.size(); ++i, ++newOffset) {
if (!isOctalChar(text.at(newOffset)))
break;
}
- if (newOffset == offset + 2)
- return offset;
return newOffset;
}
diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
index 2bb61a7ae6..4987dc95f0 100644
--- a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
+++ b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp
@@ -156,15 +156,15 @@ void SyntaxHighlighter::highlightBlock(const QString& text)
void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format& format)
{
- if (format.isDefaultTextStyle(theme()) || length == 0)
+ if (length == 0)
return;
QTextCharFormat tf;
- if (format.hasTextColor(theme()))
- tf.setForeground(format.textColor(theme()));
+ // always set the foreground color to avoid palette issues
+ tf.setForeground(format.textColor(theme()));
+
if (format.hasBackgroundColor(theme()))
tf.setBackground(format.backgroundColor(theme()));
-
if (format.isBold(theme()))
tf.setFontWeight(QFont::Bold);
if (format.isItalic(theme()))
diff --git a/src/libs/3rdparty/variant/variant.hpp b/src/libs/3rdparty/variant/variant.hpp
index 29d7feb29f..dca26986c9 100644
--- a/src/libs/3rdparty/variant/variant.hpp
+++ b/src/libs/3rdparty/variant/variant.hpp
@@ -8,6 +8,11 @@
#ifndef MPARK_VARIANT_HPP
#define MPARK_VARIANT_HPP
+#if defined(__GNUC__) && __GNUC__ >= 9
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-copy"
+#endif
+
/*
variant synopsis
@@ -2453,4 +2458,8 @@ namespace std {
} // namespace std
+#if defined(__GNUC__) && __GNUC__ >= 9
+#pragma GCC diagnostic pop
+#endif
+
#endif // MPARK_VARIANT_HPP
diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt
new file mode 100644
index 0000000000..52cc1d35a9
--- /dev/null
+++ b/src/libs/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_subdirectory(3rdparty)
+
+add_subdirectory(aggregation)
+add_subdirectory(extensionsystem)
+add_subdirectory(utils)
+add_subdirectory(languageutils)
+add_subdirectory(cplusplus)
+add_subdirectory(modelinglib)
+add_subdirectory(qmljs)
+add_subdirectory(qmldebug)
+add_subdirectory(qmleditorwidgets)
+add_subdirectory(glsl)
+add_subdirectory(languageserverprotocol)
+add_subdirectory(ssh)
+add_subdirectory(sqlite)
+add_subdirectory(clangsupport)
+add_subdirectory(tracing)
+
+if (WIN32)
+ add_subdirectory(qtcreatorcdbext)
+endif()
diff --git a/src/libs/aggregation/CMakeLists.txt b/src/libs/aggregation/CMakeLists.txt
new file mode 100644
index 0000000000..6871c9ab35
--- /dev/null
+++ b/src/libs/aggregation/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_qtc_library(Aggregation
+ DEPENDS Qt5::Core
+ SOURCES
+ aggregate.cpp aggregate.h
+ aggregation_global.h
+)
diff --git a/src/libs/aggregation/examples/text/main.cpp b/src/libs/aggregation/examples/text/main.cpp
index c205ccb838..043196ab78 100644
--- a/src/libs/aggregation/examples/text/main.cpp
+++ b/src/libs/aggregation/examples/text/main.cpp
@@ -31,7 +31,7 @@ MyMain::MyMain(QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
ui.setupUi(this);
- connect(ui.comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(ui.comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MyMain::select);
}
diff --git a/src/libs/clangsupport/CMakeLists.txt b/src/libs/clangsupport/CMakeLists.txt
new file mode 100644
index 0000000000..84cdbaf8b9
--- /dev/null
+++ b/src/libs/clangsupport/CMakeLists.txt
@@ -0,0 +1,137 @@
+add_qtc_library(ClangSupport
+ PUBLIC_DEPENDS Utils Sqlite Qt5::Core Qt5::Network
+ PUBLIC_INCLUDES "${CMAKE_CURRENT_LIST_DIR}"
+ PUBLIC_DEFINES
+ CLANG_VERSION="${CLANG_VERSION}"
+ CLANG_RESOURCE_DIR="${CLANG_RESOURCE_DIR}"
+ CLANG_BINDIR="${CLANG_BIN_DIR}"
+ DEFINES CLANGSUPPORT_BUILD_LIB
+ SOURCES
+ alivemessage.cpp alivemessage.h
+ annotationsmessage.cpp annotationsmessage.h
+ baseserverproxy.cpp baseserverproxy.h
+ cancelmessage.cpp cancelmessage.h
+ changedfilepathcompressor.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
+ clangpathwatcher.h
+ clangpathwatcherinterface.h
+ clangpathwatchernotifier.h
+ clangrefactoringclientmessages.h
+ clangrefactoringmessages.h
+ clangrefactoringservermessages.h
+ clangsupport_global.h
+ clangsupportdebugutils.cpp clangsupportdebugutils.h
+ clangsupportexceptions.h
+ codecompletion.cpp codecompletion.h
+ codecompletionchunk.cpp codecompletionchunk.h
+ commandlinebuilder.h
+ compilermacro.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
+ dynamicastmatcherdiagnosticcontainer.cpp dynamicastmatcherdiagnosticcontainer.h
+ dynamicastmatcherdiagnosticcontextcontainer.cpp dynamicastmatcherdiagnosticcontextcontainer.h
+ dynamicastmatcherdiagnosticmessagecontainer.cpp dynamicastmatcherdiagnosticmessagecontainer.h
+ dynamicmatcherdiagnostics.h
+ echomessage.cpp echomessage.h
+ endmessage.cpp endmessage.h
+ environment.h
+ executeinloop.h
+ filecontainer.cpp filecontainer.h
+ filecontainerv2.cpp filecontainerv2.h
+ filepath.cpp filepath.h
+ filepathcache.h
+ filepathcaching.cpp filepathcaching.h
+ filepathcachingfwd.h
+ filepathcachinginterface.h
+ filepathexceptions.h
+ filepathid.cpp filepathid.h
+ filepathstorage.h
+ filepathstoragesources.h
+ filepathstoragesqlitestatementfactory.h
+ filepathview.h
+ fixitcontainer.cpp fixitcontainer.h
+ followsymbolmessage.cpp followsymbolmessage.h
+ generatedfiles.cpp generatedfiles.h
+ generatedfilesinterface.h
+ idpaths.h
+ includesearchpath.h
+ ipcclientinterface.h
+ ipcclientprovider.h
+ ipcinterface.h
+ ipcserverinterface.h
+ lineprefixer.cpp lineprefixer.h
+ messageenvelop.cpp messageenvelop.h
+ modifiedtimechecker.h
+ modifiedtimecheckerinterface.h
+ nativefilepath.h
+ pchmanagerclientinterface.cpp pchmanagerclientinterface.h
+ pchmanagerclientproxy.cpp pchmanagerclientproxy.h
+ pchmanagerserverinterface.cpp pchmanagerserverinterface.h
+ pchmanagerserverproxy.cpp pchmanagerserverproxy.h
+ pchpaths.h
+ precompiledheadersupdatedmessage.cpp precompiledheadersupdatedmessage.h
+ processcreator.cpp processcreator.h
+ processexception.cpp processexception.h
+ processhandle.h
+ processstartedevent.cpp processstartedevent.h
+ progresscounter.h
+ progressmessage.h
+ projectmanagementserverinterface.h
+ projectpartartefact.cpp projectpartartefact.h
+ projectpartcontainer.cpp projectpartcontainer.h
+ projectpartid.h
+ projectpartpch.cpp projectpartpch.h
+ projectpartsstorage.h
+ projectpartsstorageinterface.h
+ readmessageblock.cpp readmessageblock.h
+ refactoringclientinterface.cpp refactoringclientinterface.h
+ refactoringclientproxy.cpp refactoringclientproxy.h
+ refactoringdatabaseinitializer.h
+ refactoringserverinterface.cpp refactoringserverinterface.h
+ refactoringserverproxy.cpp refactoringserverproxy.h
+ referencesmessage.cpp referencesmessage.h
+ removegeneratedfilesmessage.cpp removegeneratedfilesmessage.h
+ removeprojectpartsmessage.h
+ requestannotationsmessage.cpp requestannotationsmessage.h
+ requestcompletionsmessage.cpp requestcompletionsmessage.h
+ requestfollowsymbolmessage.cpp requestfollowsymbolmessage.h
+ requestreferencesmessage.cpp requestreferencesmessage.h
+ requestsourcelocationforrenamingmessage.cpp requestsourcelocationforrenamingmessage.h
+ requestsourcerangesanddiagnosticsforquerymessage.cpp requestsourcerangesanddiagnosticsforquerymessage.h
+ requestsourcerangesforquerymessage.cpp requestsourcerangesforquerymessage.h
+ requesttooltipmessage.cpp requesttooltipmessage.h
+ sourceentry.h
+ sourcelocationcontainer.cpp sourcelocationcontainer.h
+ sourcelocationcontainerv2.cpp sourcelocationcontainerv2.h
+ sourcelocationscontainer.cpp sourcelocationscontainer.h
+ sourcelocationsforrenamingmessage.cpp sourcelocationsforrenamingmessage.h
+ sourcerangecontainer.cpp sourcerangecontainer.h
+ sourcerangecontainerv2.cpp sourcerangecontainerv2.h
+ sourcerangesanddiagnosticsforquerymessage.cpp sourcerangesanddiagnosticsforquerymessage.h
+ sourcerangescontainer.cpp sourcerangescontainer.h
+ sourcerangesforquerymessage.cpp sourcerangesforquerymessage.h
+ sourcerangewithtextcontainer.cpp sourcerangewithtextcontainer.h
+ stringcache.h
+ stringcachealgorithms.h
+ stringcachefwd.h
+ tokeninfocontainer.cpp tokeninfocontainer.h
+ tooltipinfo.cpp tooltipinfo.h
+ tooltipmessage.cpp tooltipmessage.h
+ unsavedfilesremovedmessage.cpp unsavedfilesremovedmessage.h
+ unsavedfilesupdatedmessage.cpp unsavedfilesupdatedmessage.h
+ updategeneratedfilesmessage.cpp updategeneratedfilesmessage.h
+ updateprojectpartsmessage.cpp updateprojectpartsmessage.h
+ writemessageblock.cpp writemessageblock.h
+)
diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri
index 0668382803..df537f5848 100644
--- a/src/libs/clangsupport/clangsupport-lib.pri
+++ b/src/libs/clangsupport/clangsupport-lib.pri
@@ -110,6 +110,7 @@ HEADERS += \
$$PWD/clangsupportexceptions.h \
$$PWD/completionsmessage.h \
$$PWD/executeinloop.h \
+ $$PWD/pchpaths.h \
$$PWD/projectpartid.h \
$$PWD/projectpartsstorage.h \
$$PWD/projectpartsstorageinterface.h \
@@ -203,7 +204,6 @@ HEADERS += \
$$PWD/nativefilepath.h \
$$PWD/filepathview.h \
$$PWD/compilermacro.h \
- $$PWD/projectpartpchproviderinterface.h \
$$PWD/updategeneratedfilesmessage.h \
$$PWD/removegeneratedfilesmessage.h \
$$PWD/generatedfiles.h \
@@ -213,6 +213,10 @@ HEADERS += \
$$PWD/includesearchpath.h \
$$PWD/commandlinebuilder.h \
$$PWD/projectpartartefact.h \
- $$PWD/projectpartcontainer.h
+ $$PWD/projectpartcontainer.h \
+ $$PWD/sourceentry.h \
+ $$PWD/modifiedtimecheckerinterface.h \
+ $$PWD/environment.h \
+ $$PWD/modifiedtimechecker.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
diff --git a/src/libs/clangsupport/commandlinebuilder.h b/src/libs/clangsupport/commandlinebuilder.h
index 9de1da68d3..dedcf1c518 100644
--- a/src/libs/clangsupport/commandlinebuilder.h
+++ b/src/libs/clangsupport/commandlinebuilder.h
@@ -33,6 +33,9 @@
#include <utils/smallstringvector.h>
#include <utils/cpplanguage_details.h>
+#include <QCoreApplication>
+#include <QDir>
+
namespace ClangBackEnd {
enum class InputFileType : unsigned char { Header, Source };
@@ -46,7 +49,8 @@ public:
InputFileType sourceType = InputFileType::Header,
FilePathView sourcePath = {},
FilePathView outputPath = {},
- FilePathView includePchPath = {})
+ FilePathView includePchPath = {},
+ NativeFilePathView preIncludeSearchPath = {})
{
commandLine.reserve(1024);
@@ -58,6 +62,7 @@ public:
addLanguageVersion(projectInfo);
addNoStdIncAndNoStdLibInc(projectInfo.language);
addCompilerMacros(projectInfo.compilerMacros);
+ addPreIncludeSearchPath(preIncludeSearchPath);
addProjectIncludeSearchPaths(
sortedIncludeSearchPaths(projectInfo.projectIncludeSearchPaths));
addSystemAndBuiltInIncludeSearchPaths(
@@ -97,9 +102,12 @@ public:
if (projectInfo.languageExtension && Utils::LanguageExtension::ObjectiveC)
return sourceType == InputFileType::Header ? "objective-c++-header"
: "objective-c++";
+ return sourceType == InputFileType::Header ? "c++-header" : "c++";
+ case Utils::Language::None:
+ return "none";
}
- return sourceType == InputFileType::Header ? "c++-header" : "c++";
+ return "none";
}
void addLanguage(const ProjectInfo &projectInfo, InputFileType sourceType)
@@ -131,6 +139,8 @@ public:
return "-std=c++17";
case Utils::LanguageVersion::CXX2a:
return "-std=c++2a";
+ case Utils::LanguageVersion::None:
+ return "";
}
return "-std=c++2a";
@@ -159,6 +169,8 @@ public:
return "-std=gnu++17";
case Utils::LanguageVersion::CXX2a:
return "-std=gnu++2a";
+ case Utils::LanguageVersion::None:
+ return "";
}
return "-std=gnu++2a";
@@ -209,6 +221,14 @@ public:
commandLine.emplace_back(Utils::SmallString{"-D", macro.key, "=", macro.value});
}
+ void addPreIncludeSearchPath(NativeFilePathView preIncludeSearchPath)
+ {
+ if (!preIncludeSearchPath.empty()) {
+ commandLine.emplace_back("-isystem");
+ commandLine.emplace_back(preIncludeSearchPath);
+ }
+ }
+
IncludeSearchPaths sortedIncludeSearchPaths(const IncludeSearchPaths &unsortedPaths)
{
IncludeSearchPaths paths = unsortedPaths;
diff --git a/src/libs/clangsupport/connectionclient.cpp b/src/libs/clangsupport/connectionclient.cpp
index bdbedab5c0..b3025baeea 100644
--- a/src/libs/clangsupport/connectionclient.cpp
+++ b/src/libs/clangsupport/connectionclient.cpp
@@ -325,7 +325,7 @@ void ConnectionClient::connectStandardOutputAndError(QProcess *process) const
void ConnectionClient::connectLocalSocketError() const
{
connect(m_localSocket,
- static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
+ QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
this,
&ConnectionClient::printLocalSocketError);
}
diff --git a/src/libs/clangsupport/connectionserver.h b/src/libs/clangsupport/connectionserver.h
index 8f13e631c5..b60083c4f8 100644
--- a/src/libs/clangsupport/connectionserver.h
+++ b/src/libs/clangsupport/connectionserver.h
@@ -72,11 +72,17 @@ public:
}
+ void ensureAliveMessageIsSent()
+ {
+ if (m_aliveTimer.remainingTime() == 0)
+ sendAliveMessage();
+ }
+
private:
void connectToLocalServer(const QString &connectionName)
{
QObject::connect(&m_localSocket,
- static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
+ QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
[&] (QLocalSocket::LocalSocketError) {
qWarning() << "ConnectionServer error:" << m_localSocket.errorString() << connectionName;
});
diff --git a/src/libs/clangsupport/environment.h b/src/libs/clangsupport/environment.h
new file mode 100644
index 0000000000..ffa4d907cc
--- /dev/null
+++ b/src/libs/clangsupport/environment.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <nativefilepath.h>
+
+namespace ClangBackEnd {
+
+class Environment
+{
+public:
+ Environment() = default;
+ Environment(const Environment &) = delete;
+ Environment &operator=(const Environment &) = delete;
+
+ virtual Utils::PathString pchBuildDirectory() const = 0;
+ virtual uint hardwareConcurrency() const = 0;
+ virtual NativeFilePathView preIncludeSearchPath() const = 0;
+
+protected:
+ ~Environment() = default;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/executeinloop.h b/src/libs/clangsupport/executeinloop.h
index 9c3eddeb4d..3642c3ccd3 100644
--- a/src/libs/clangsupport/executeinloop.h
+++ b/src/libs/clangsupport/executeinloop.h
@@ -29,38 +29,6 @@
#include <QCoreApplication>
#include <QThread>
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
-template<typename CallableType>
-class CallableEvent : public QEvent
-{
-public:
- using Callable = std::decay_t<CallableType>;
- CallableEvent(Callable &&callable)
- : QEvent(QEvent::None)
- , callable(std::move(callable))
- {}
- CallableEvent(const Callable &callable)
- : QEvent(QEvent::None)
- , callable(callable)
- {}
-
- ~CallableEvent() { callable(); }
-
-public:
- Callable callable;
-};
-
-template<typename Callable>
-void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance())
-{
- if (QThread *thread = qobject_cast<QThread *>(object))
- object = QAbstractEventDispatcher::instance(thread);
-
- QCoreApplication::postEvent(object,
- new CallableEvent<Callable>(std::forward<Callable>(callable)),
- Qt::HighEventPriority);
-}
-#else
template<typename Callable>
void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance())
{
@@ -69,4 +37,3 @@ void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::inst
QMetaObject::invokeMethod(object, std::forward<Callable>(callable));
}
-#endif
diff --git a/src/libs/clangsupport/generatedfiles.cpp b/src/libs/clangsupport/generatedfiles.cpp
index f4863baba5..644137886b 100644
--- a/src/libs/clangsupport/generatedfiles.cpp
+++ b/src/libs/clangsupport/generatedfiles.cpp
@@ -25,6 +25,8 @@
#include "generatedfiles.h"
+#include <utils/algorithm.h>
+
namespace ClangBackEnd {
void GeneratedFiles::update(V2::FileContainers &&fileContainers)
@@ -32,16 +34,16 @@ void GeneratedFiles::update(V2::FileContainers &&fileContainers)
V2::FileContainers unionFileContainers;
unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size());
- auto compare = [] (const V2::FileContainer &first, const V2::FileContainer &second) {
+ auto compare = [](const V2::FileContainer &first, const V2::FileContainer &second) {
return first.filePath < second.filePath;
};
- std::set_union(std::make_move_iterator(fileContainers.begin()),
- std::make_move_iterator(fileContainers.end()),
- std::make_move_iterator(m_fileContainers.begin()),
- std::make_move_iterator(m_fileContainers.end()),
- std::back_inserter(unionFileContainers),
- compare);
+ Utils::set_union(std::make_move_iterator(fileContainers.begin()),
+ std::make_move_iterator(fileContainers.end()),
+ std::make_move_iterator(m_fileContainers.begin()),
+ std::make_move_iterator(m_fileContainers.end()),
+ std::back_inserter(unionFileContainers),
+ compare);
m_fileContainers = std::move(unionFileContainers);
}
@@ -55,12 +57,12 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers)
return first.filePath < second.filePath;
};
- std::set_union(fileContainers.begin(),
- fileContainers.end(),
- std::make_move_iterator(m_fileContainers.begin()),
- std::make_move_iterator(m_fileContainers.end()),
- std::back_inserter(unionFileContainers),
- compare);
+ Utils::set_union(fileContainers.begin(),
+ fileContainers.end(),
+ std::make_move_iterator(m_fileContainers.begin()),
+ std::make_move_iterator(m_fileContainers.end()),
+ std::back_inserter(unionFileContainers),
+ compare);
m_fileContainers = std::move(unionFileContainers);
}
diff --git a/src/libs/clangsupport/ipcserverinterface.cpp b/src/libs/clangsupport/ipcserverinterface.cpp
deleted file mode 100644
index fbc92de52e..0000000000
--- a/src/libs/clangsupport/ipcserverinterface.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 "ipcserverinterface.h"
-
-namespace ClangBackEnd {
-
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/modifiedtimechecker.h b/src/libs/clangsupport/modifiedtimechecker.h
new file mode 100644
index 0000000000..c9b62c4673
--- /dev/null
+++ b/src/libs/clangsupport/modifiedtimechecker.h
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** 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 "filepathcachinginterface.h"
+#include "modifiedtimecheckerinterface.h"
+
+#include <algorithm>
+#include <iterator>
+
+namespace ClangBackEnd {
+template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
+class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries>
+{
+ using SourceEntry = typename SourceEntries::value_type;
+
+public:
+ using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>;
+ ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache)
+ : m_getModifiedTime(getModifiedTime)
+ , m_filePathCache(filePathCache)
+ {}
+
+ bool isUpToDate(const SourceEntries &sourceEntries) const
+ {
+ if (sourceEntries.empty())
+ return false;
+
+ updateCurrentSourceTimeStamps(sourceEntries);
+
+ return compareEntries(sourceEntries);
+ }
+
+ void pathsChanged(const FilePathIds &filePathIds)
+ {
+ using SourceTimeStampReferences = std::vector<std::reference_wrapper<SourceTimeStamp>>;
+
+ SourceTimeStampReferences timeStampsToUpdate;
+ timeStampsToUpdate.reserve(filePathIds.size());
+
+ std::set_intersection(m_currentSourceTimeStamps.begin(),
+ m_currentSourceTimeStamps.end(),
+ filePathIds.begin(),
+ filePathIds.end(),
+ std::back_inserter(timeStampsToUpdate));
+
+ for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) {
+ sourceTimeStamp.timeStamp = m_getModifiedTime(
+ m_filePathCache.filePath(sourceTimeStamp.sourceId));
+ }
+ }
+
+private:
+ bool compareEntries(const SourceEntries &sourceEntries) const
+ {
+ class CompareSourceId
+ {
+ public:
+ bool operator()(SourceTimeStamp first, SourceTimeStamp second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+
+ bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+
+ bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+
+ bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+ };
+
+ SourceTimeStamps currentSourceTimeStamp;
+ currentSourceTimeStamp.reserve(sourceEntries.size());
+ std::set_intersection(m_currentSourceTimeStamps.begin(),
+ m_currentSourceTimeStamps.end(),
+ sourceEntries.begin(),
+ sourceEntries.end(),
+ std::back_inserter(currentSourceTimeStamp),
+ CompareSourceId{});
+
+ class CompareTime
+ {
+ public:
+ bool operator()(SourceTimeStamp first, SourceTimeStamp second)
+ {
+ return first.timeStamp <= second.timeStamp;
+ }
+
+ bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
+ {
+ return first.timeStamp <= second.timeStamp;
+ }
+
+ bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
+ {
+ return first.timeStamp <= second.timeStamp;
+ }
+
+ bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
+ {
+ return first.timeStamp <= second.timeStamp;
+ }
+ };
+
+ return std::lexicographical_compare(currentSourceTimeStamp.begin(),
+ currentSourceTimeStamp.end(),
+ sourceEntries.begin(),
+ sourceEntries.end(),
+ CompareTime{});
+ }
+
+ void updateCurrentSourceTimeStamps(const SourceEntries &sourceEntries) const
+ {
+ SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries);
+
+ for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) {
+ newSourceTimeStamp.timeStamp = m_getModifiedTime(
+ m_filePathCache.filePath(newSourceTimeStamp.sourceId));
+ }
+
+ auto split = sourceTimeStamps.insert(sourceTimeStamps.end(),
+ m_currentSourceTimeStamps.begin(),
+ m_currentSourceTimeStamps.end());
+ std::inplace_merge(sourceTimeStamps.begin(), split, sourceTimeStamps.end());
+
+ m_currentSourceTimeStamps = sourceTimeStamps;
+ }
+
+ SourceTimeStamps newSourceTimeStamps(const SourceEntries &sourceEntries) const
+ {
+ SourceEntries newSourceEntries;
+ newSourceEntries.reserve(sourceEntries.size());
+
+ class CompareSourceId
+ {
+ public:
+ bool operator()(SourceTimeStamp first, SourceTimeStamp second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+
+ bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+
+ bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+
+ bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+ };
+
+ std::set_difference(sourceEntries.begin(),
+ sourceEntries.end(),
+ m_currentSourceTimeStamps.begin(),
+ m_currentSourceTimeStamps.end(),
+ std::back_inserter(newSourceEntries),
+ CompareSourceId{});
+
+ SourceTimeStamps newTimeStamps;
+ newTimeStamps.reserve(newSourceEntries.size());
+
+ std::transform(newSourceEntries.begin(),
+ newSourceEntries.end(),
+ std::back_inserter(newTimeStamps),
+ [](SourceEntry entry) {
+ return SourceTimeStamp{entry.sourceId, {}};
+ });
+
+ return newTimeStamps;
+ }
+
+private:
+ mutable SourceTimeStamps m_currentSourceTimeStamps;
+ GetModifiedTime &m_getModifiedTime;
+ FilePathCachingInterface &m_filePathCache;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/modifiedtimecheckerinterface.h b/src/libs/clangsupport/modifiedtimecheckerinterface.h
new file mode 100644
index 0000000000..a0e79b0701
--- /dev/null
+++ b/src/libs/clangsupport/modifiedtimecheckerinterface.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 "sourceentry.h"
+
+namespace ClangBackEnd {
+
+template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
+class ModifiedTimeCheckerInterface
+{
+public:
+ ModifiedTimeCheckerInterface() = default;
+ ModifiedTimeCheckerInterface(const ModifiedTimeCheckerInterface &) = delete;
+ ModifiedTimeCheckerInterface &operator=(const ModifiedTimeCheckerInterface &) = delete;
+
+ virtual bool isUpToDate(const SourceEntries &sourceEntries) const = 0;
+
+protected:
+ ~ModifiedTimeCheckerInterface() = default;
+};
+
+} // namespace ClangBackEnd
+
diff --git a/src/libs/clangsupport/pchmanagerclientproxy.h b/src/libs/clangsupport/pchmanagerclientproxy.h
index 516b2e3a86..6dec4ecfca 100644
--- a/src/libs/clangsupport/pchmanagerclientproxy.h
+++ b/src/libs/clangsupport/pchmanagerclientproxy.h
@@ -42,9 +42,6 @@ public:
PchManagerClientProxy(const PchManagerClientProxy&) = delete;
const PchManagerClientProxy &operator=(const PchManagerClientProxy&) = delete;
- PchManagerClientProxy(PchManagerClientProxy &&other) = default;
- PchManagerClientProxy &operator=(PchManagerClientProxy &&other) = default;
-
void readMessages();
void alive() override;
diff --git a/src/libs/clangsupport/pchpaths.h b/src/libs/clangsupport/pchpaths.h
new file mode 100644
index 0000000000..048ec9da8d
--- /dev/null
+++ b/src/libs/clangsupport/pchpaths.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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 "filepath.h"
+
+namespace ClangBackEnd {
+
+class PchPaths
+{
+public:
+ PchPaths() = default;
+ PchPaths(Utils::SmallStringView projectPchPath, Utils::SmallStringView systemPchPath)
+ : projectPchPath(FilePathView{projectPchPath})
+ , systemPchPath(FilePathView{systemPchPath})
+ {}
+
+ friend bool operator==(const PchPaths &first, const PchPaths &second)
+ {
+ return first.projectPchPath == second.projectPchPath
+ && first.systemPchPath == second.systemPchPath;
+ }
+
+public:
+ FilePath projectPchPath;
+ FilePath systemPchPath;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/precompiledheadersupdatedmessage.h b/src/libs/clangsupport/precompiledheadersupdatedmessage.h
index 5a21b995df..5bd24dcd49 100644
--- a/src/libs/clangsupport/precompiledheadersupdatedmessage.h
+++ b/src/libs/clangsupport/precompiledheadersupdatedmessage.h
@@ -25,7 +25,10 @@
#pragma once
-#include "projectpartpch.h"
+#include "clangsupport_global.h"
+#include "projectpartid.h"
+
+#include <utils/smallstringio.h>
namespace ClangBackEnd {
@@ -33,25 +36,26 @@ class PrecompiledHeadersUpdatedMessage
{
public:
PrecompiledHeadersUpdatedMessage() = default;
- PrecompiledHeadersUpdatedMessage(std::vector<ProjectPartPch> &&projectPartPchs)
- : projectPartPchs(std::move(projectPartPchs))
- {}
-
- ProjectPartPchs takeProjectPartPchs() const
+ PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId)
{
- return std::move(projectPartPchs);
+ projectPartIds.push_back(projectPartId);
}
+ PrecompiledHeadersUpdatedMessage(ProjectPartIds &&projectPartIds)
+ : projectPartIds(std::move(projectPartIds))
+ {}
+
+ ProjectPartIds takeProjectPartIds() const { return std::move(projectPartIds); }
friend QDataStream &operator<<(QDataStream &out, const PrecompiledHeadersUpdatedMessage &message)
{
- out << message.projectPartPchs;
+ out << message.projectPartIds;
return out;
}
friend QDataStream &operator>>(QDataStream &in, PrecompiledHeadersUpdatedMessage &message)
{
- in >> message.projectPartPchs;
+ in >> message.projectPartIds;
return in;
}
@@ -59,16 +63,13 @@ public:
friend bool operator==(const PrecompiledHeadersUpdatedMessage &first,
const PrecompiledHeadersUpdatedMessage &second)
{
- return first.projectPartPchs == second.projectPartPchs;
+ return first.projectPartIds == second.projectPartIds;
}
- PrecompiledHeadersUpdatedMessage clone() const
- {
- return PrecompiledHeadersUpdatedMessage(Utils::clone(projectPartPchs));
- }
+ PrecompiledHeadersUpdatedMessage clone() const { return *this; }
public:
- std::vector<ProjectPartPch> projectPartPchs;
+ ProjectPartIds projectPartIds;
};
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const PrecompiledHeadersUpdatedMessage &message);
diff --git a/src/libs/clangsupport/projectpartartefact.cpp b/src/libs/clangsupport/projectpartartefact.cpp
index 7623f38796..56551693e1 100644
--- a/src/libs/clangsupport/projectpartartefact.cpp
+++ b/src/libs/clangsupport/projectpartartefact.cpp
@@ -33,8 +33,6 @@
namespace ClangBackEnd {
-
-
Utils::SmallStringVector ProjectPartArtefact::toStringVector(Utils::SmallStringView jsonText)
{
if (jsonText.isEmpty())
diff --git a/src/libs/clangsupport/projectpartartefact.h b/src/libs/clangsupport/projectpartartefact.h
index ac8c44a891..0d9bcf5c39 100644
--- a/src/libs/clangsupport/projectpartartefact.h
+++ b/src/libs/clangsupport/projectpartartefact.h
@@ -113,8 +113,8 @@ public:
CompilerMacros compilerMacros;
IncludeSearchPaths systemIncludeSearchPaths;
IncludeSearchPaths projectIncludeSearchPaths;
- Utils::Language language = Utils::Language::Cxx;
- Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98;
+ Utils::Language language = Utils::Language::None;
+ Utils::LanguageVersion languageVersion = Utils::LanguageVersion::None;
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None;
};
diff --git a/src/libs/clangsupport/projectpartcontainer.h b/src/libs/clangsupport/projectpartcontainer.h
index f1c64bd237..b2133dcaa2 100644
--- a/src/libs/clangsupport/projectpartcontainer.h
+++ b/src/libs/clangsupport/projectpartcontainer.h
@@ -147,7 +147,8 @@ public:
first.sourcePathIds,
first.language,
first.languageVersion,
- first.languageExtension)
+ first.languageExtension,
+ first.hasPrecompiledHeader)
< std::tie(second.projectPartId,
second.toolChainArguments,
second.compilerMacros,
@@ -157,7 +158,8 @@ public:
second.sourcePathIds,
second.language,
second.languageVersion,
- second.languageExtension);
+ second.languageExtension,
+ second.hasPrecompiledHeader);
}
ProjectPartContainer clone() const
@@ -169,6 +171,7 @@ public:
FilePathIds headerPathIds;
FilePathIds sourcePathIds;
bool updateIsDeferred = false;
+ bool hasPrecompiledHeader = true;
};
using ProjectPartContainerReference = std::reference_wrapper<ProjectPartContainer>;
diff --git a/src/libs/clangsupport/projectpartid.h b/src/libs/clangsupport/projectpartid.h
index c372682baf..fc5f659605 100644
--- a/src/libs/clangsupport/projectpartid.h
+++ b/src/libs/clangsupport/projectpartid.h
@@ -54,7 +54,7 @@ public:
return first.projectPathId < second.projectPathId;
}
- friend QDataStream &operator<<(QDataStream &out, const ProjectPartId &projectPathId)
+ friend QDataStream &operator<<(QDataStream &out, ProjectPartId projectPathId)
{
out << projectPathId.projectPathId;
diff --git a/src/libs/clangsupport/projectpartpch.cpp b/src/libs/clangsupport/projectpartpch.cpp
index aac672441c..9c870ac572 100644
--- a/src/libs/clangsupport/projectpartpch.cpp
+++ b/src/libs/clangsupport/projectpartpch.cpp
@@ -29,8 +29,7 @@ namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch)
{
- debug.nospace() << "FileContainer(" << projectPartPch.projectPartId.projectPathId << ", "
- << projectPartPch.pchPath << ")";
+ debug.nospace() << "FileContainer(" << projectPartPch.projectPartId.projectPathId << ")";
return debug;
}
diff --git a/src/libs/clangsupport/projectpartpch.h b/src/libs/clangsupport/projectpartpch.h
index c471b46b16..213247ae42 100644
--- a/src/libs/clangsupport/projectpartpch.h
+++ b/src/libs/clangsupport/projectpartpch.h
@@ -74,8 +74,7 @@ public:
friend bool operator==(const ProjectPartPch &first,
const ProjectPartPch &second)
{
- return first.projectPartId == second.projectPartId
- && first.pchPath == second.pchPath;
+ return first.projectPartId == second.projectPartId && first.pchPath == second.pchPath;
}
ProjectPartPch clone() const
diff --git a/src/libs/clangsupport/projectpartpchproviderinterface.h b/src/libs/clangsupport/projectpartpchproviderinterface.h
deleted file mode 100644
index 282e541cfd..0000000000
--- a/src/libs/clangsupport/projectpartpchproviderinterface.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 "projectpartpch.h"
-
-#include <utils/optional.h>
-
-namespace ClangBackEnd {
-
-class ProjectPartPchProviderInterface
-{
-public:
- ProjectPartPchProviderInterface() = default;
- ProjectPartPchProviderInterface(const ProjectPartPchProviderInterface &) = delete;
- ProjectPartPchProviderInterface &operator=(const ProjectPartPchProviderInterface &) = delete;
-
- virtual Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch(
- ClangBackEnd::ProjectPartId projectPartId) const = 0;
- virtual const ClangBackEnd::ProjectPartPchs &projectPartPchs() const = 0;
-
-
-protected:
- ~ProjectPartPchProviderInterface() = default;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/projectpartsstorage.h b/src/libs/clangsupport/projectpartsstorage.h
index c91291bca2..e71bb0d51e 100644
--- a/src/libs/clangsupport/projectpartsstorage.h
+++ b/src/libs/clangsupport/projectpartsstorage.h
@@ -74,6 +74,14 @@ public:
.template values<FilePathId>(1024, projectPartId.projectPathId);
}
+ bool hasPrecompiledHeader(ProjectPartId projectPartId) const
+ {
+ auto value = fetchProjectPrecompiledHeaderPathStatement.template value<Utils::SmallString>(
+ projectPartId.projectPathId);
+
+ return value && value->hasContent();
+ }
+
ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const override
{
try {
@@ -88,6 +96,7 @@ public:
if (value) {
value->headerPathIds = fetchHeaders(projectPartId);
value->sourcePathIds = fetchSources(projectPartId);
+ value->hasPrecompiledHeader = hasPrecompiledHeader(projectPartId);
projectParts.push_back(*std::move(value));
}
}
@@ -125,7 +134,7 @@ public:
}
}
- Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const
+ Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const override
{
try {
Sqlite::DeferredTransaction transaction{database};
@@ -236,6 +245,22 @@ public:
return statement.template value<ProjectPartArtefact, 8>(projectPartId.projectPathId);
}
+ void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) override
+ {
+ try {
+ Sqlite::ImmediateTransaction transaction{database};
+
+ for (const ProjectPartContainer &projectPart : projectsParts) {
+ for (FilePathId sourcePathId : projectPart.sourcePathIds)
+ resetDependentIndexingTimeStampsStatement.write(sourcePathId.filePathId);
+ }
+
+ transaction.commit();
+ } catch (const Sqlite::StatementIsBusy &) {
+ resetIndexingTimeStamps(projectsParts);
+ }
+ }
+
Sqlite::TransactionInterface &transactionBackend() override { return database; }
static Utils::SmallString toJson(const Utils::SmallStringVector &strings)
@@ -332,5 +357,13 @@ public:
"SELECT sourceId FROM projectPartsHeaders WHERE projectPartId = ?", database};
mutable ReadStatement fetchProjectPartsSourcesByIdStatement{
"SELECT sourceId FROM projectPartsSources WHERE projectPartId = ?", database};
+ mutable ReadStatement fetchProjectPrecompiledHeaderPathStatement{
+ "SELECT projectPchPath FROM precompiledHeaders WHERE projectPartId = ?", database};
+ WriteStatement resetDependentIndexingTimeStampsStatement{
+ "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
+ "dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
+ "sourceDependencies.sourceId == collectedDependencies.sourceId) UPDATE fileStatuses SET "
+ "indexingTimeStamp = NULL WHERE sourceId IN (SELECT sourceId FROM collectedDependencies)",
+ database};
};
} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/projectpartsstorageinterface.h b/src/libs/clangsupport/projectpartsstorageinterface.h
index 1127f70b1f..2d0675e657 100644
--- a/src/libs/clangsupport/projectpartsstorageinterface.h
+++ b/src/libs/clangsupport/projectpartsstorageinterface.h
@@ -63,6 +63,7 @@ public:
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(
ProjectPartId projectPartId) const = 0;
+ virtual void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) = 0;
virtual Sqlite::TransactionInterface &transactionBackend() = 0;
diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h
index efca925413..a7058d3204 100644
--- a/src/libs/clangsupport/refactoringdatabaseinitializer.h
+++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h
@@ -177,6 +177,7 @@ public:
Sqlite::Contraint::PrimaryKey);
table.addColumn("size", Sqlite::ColumnType::Integer);
table.addColumn("lastModified", Sqlite::ColumnType::Integer);
+ table.addColumn("indexingTimeStamp", Sqlite::ColumnType::Integer);
table.initialize(database);
}
@@ -188,6 +189,7 @@ public:
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
const Sqlite::Column &dependencySourceIdColumn = table.addColumn("dependencySourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn, dependencySourceIdColumn});
+ table.addIndex({dependencySourceIdColumn, sourceIdColumn});
table.initialize(database);
}
diff --git a/src/libs/clangsupport/sourceentry.h b/src/libs/clangsupport/sourceentry.h
new file mode 100644
index 0000000000..c593f1fcd3
--- /dev/null
+++ b/src/libs/clangsupport/sourceentry.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** 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 <filepathid.h>
+
+#include <vector>
+
+namespace ClangBackEnd {
+
+enum class SourceType : unsigned char {
+ TopProjectInclude,
+ TopSystemInclude,
+ UserInclude,
+ ProjectInclude,
+ SystemInclude,
+ Source
+};
+
+enum class HasMissingIncludes : unsigned char { No, Yes };
+
+class TimeStamp
+{
+ using int64 = long long;
+public:
+ TimeStamp() = default;
+ TimeStamp(int64 value)
+ : value(value)
+ {}
+
+ operator int64() const
+ {
+ return value;
+ }
+
+ int64 value = -1;
+};
+
+class SourceTimeStamp
+{
+ using int64 = long long;
+public:
+ SourceTimeStamp(int sourceId, int64 lastModified)
+ : timeStamp(lastModified)
+ , sourceId(sourceId)
+ {}
+
+ SourceTimeStamp(FilePathId sourceId, TimeStamp lastModified)
+ : timeStamp(lastModified)
+ , sourceId(sourceId)
+ {}
+
+ friend bool operator<(SourceTimeStamp first, SourceTimeStamp second)
+ {
+ return first.sourceId < second.sourceId;
+ }
+
+ friend bool operator<(SourceTimeStamp first, FilePathId second)
+ {
+ return first.sourceId < second;
+ }
+
+ friend bool operator<(FilePathId first, SourceTimeStamp second)
+ {
+ return first < second.sourceId;
+ }
+
+ friend bool operator==(SourceTimeStamp first, SourceTimeStamp second)
+ {
+ return first.sourceId == second.sourceId && first.timeStamp == second.timeStamp;
+ }
+
+ friend bool operator!=(SourceTimeStamp first, SourceTimeStamp second)
+ {
+ return !(first == second);
+ }
+
+public:
+ TimeStamp timeStamp;
+ FilePathId sourceId;
+};
+
+using SourceTimeStamps = std::vector<SourceTimeStamp>;
+
+class SourceEntry
+{
+ using int64 = long long;
+
+public:
+ SourceEntry(int sourceId, int64 timeStamp, int sourceType, int hasMissingIncludes)
+ : timeStamp(timeStamp)
+ , sourceId(sourceId)
+ , sourceType(static_cast<SourceType>(sourceType))
+ , hasMissingIncludes(static_cast<HasMissingIncludes>(hasMissingIncludes))
+ {}
+
+ SourceEntry(FilePathId sourceId,
+ SourceType sourceType,
+ TimeStamp timeStamp,
+ HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No)
+ : timeStamp(timeStamp)
+ , sourceId(sourceId)
+ , sourceType(sourceType)
+ , hasMissingIncludes(hasMissingIncludes)
+ {}
+
+ friend bool operator<(SourceEntry first, SourceEntry second) {
+ return first.sourceId < second.sourceId;
+ }
+
+ friend bool operator==(SourceEntry first, SourceEntry second)
+ {
+ return first.sourceId == second.sourceId && first.sourceType == second.sourceType
+ && first.timeStamp == second.timeStamp;
+ }
+
+ friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); }
+
+public:
+ TimeStamp timeStamp;
+ FilePathId sourceId;
+ SourceType sourceType = SourceType::UserInclude;
+ HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No;
+};
+
+using SourceEntries = std::vector<SourceEntry>;
+using SourceEntryReference = std::reference_wrapper<SourceEntry>;
+using SourceEntryReferences = std::vector<SourceEntryReference>;
+} // namespace ClangBackEnd
diff --git a/src/libs/cplusplus/CMakeLists.txt b/src/libs/cplusplus/CMakeLists.txt
new file mode 100644
index 0000000000..593d809394
--- /dev/null
+++ b/src/libs/cplusplus/CMakeLists.txt
@@ -0,0 +1,44 @@
+# 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
+ DEFINES CPLUSPLUS_BUILD_LIB
+ PUBLIC_DEPENDS 3rd_cplusplus Qt5::Concurrent Qt5::Gui
+ PUBLIC_INCLUDES "${CMAKE_SOURCE_DIR}/src/libs/3rdparty"
+ SOURCES
+ ASTParent.cpp ASTParent.h
+ ASTPath.cpp ASTPath.h
+ AlreadyConsideredClassContainer.h
+ BackwardsScanner.cpp BackwardsScanner.h
+ CppDocument.cpp CppDocument.h
+ CppRewriter.cpp CppRewriter.h
+ DependencyTable.cpp DependencyTable.h
+ DeprecatedGenTemplateInstance.cpp DeprecatedGenTemplateInstance.h
+ ExpressionUnderCursor.cpp ExpressionUnderCursor.h
+ FastPreprocessor.cpp FastPreprocessor.h
+ FindUsages.cpp FindUsages.h
+ Icons.cpp Icons.h
+ LookupContext.cpp LookupContext.h
+ LookupItem.cpp LookupItem.h
+ Macro.cpp Macro.h
+ MatchingText.cpp MatchingText.h
+ NamePrettyPrinter.cpp NamePrettyPrinter.h
+ Overview.cpp Overview.h
+ PPToken.cpp PPToken.h
+ PreprocessorClient.cpp PreprocessorClient.h
+ PreprocessorEnvironment.cpp PreprocessorEnvironment.h
+ ResolveExpression.cpp ResolveExpression.h
+ SimpleLexer.cpp SimpleLexer.h
+ SnapshotSymbolVisitor.cpp SnapshotSymbolVisitor.h
+ SymbolNameVisitor.cpp SymbolNameVisitor.h
+ TypeOfExpression.cpp TypeOfExpression.h
+ TypePrettyPrinter.cpp TypePrettyPrinter.h
+ cppmodelmanagerbase.cpp cppmodelmanagerbase.h
+ findcdbbreakpoint.cpp findcdbbreakpoint.h
+ pp-cctype.h pp-engine.cpp
+ pp-engine.h pp-scanner.cpp
+ pp-scanner.h
+ pp.h
+)
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index d892948468..73cc06f26a 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -228,8 +228,7 @@ public:
if (fileName != doc->fileName())
return;
- QString message;
- message.vsprintf(format, ap);
+ const QString message = QString::vasprintf(format, ap);
#ifndef DO_NOT_DUMP_ALL_PARSER_ERRORS
{
@@ -756,17 +755,17 @@ bool Snapshot::isEmpty() const
return _documents.isEmpty();
}
-Snapshot::const_iterator Snapshot::find(const Utils::FileName &fileName) const
+Snapshot::const_iterator Snapshot::find(const Utils::FilePath &fileName) const
{
return _documents.find(fileName);
}
-void Snapshot::remove(const Utils::FileName &fileName)
+void Snapshot::remove(const Utils::FilePath &fileName)
{
_documents.remove(fileName);
}
-bool Snapshot::contains(const Utils::FileName &fileName) const
+bool Snapshot::contains(const Utils::FilePath &fileName) const
{
return _documents.contains(fileName);
}
@@ -774,7 +773,7 @@ bool Snapshot::contains(const Utils::FileName &fileName) const
void Snapshot::insert(Document::Ptr doc)
{
if (doc) {
- _documents.insert(Utils::FileName::fromString(doc->fileName()), doc);
+ _documents.insert(Utils::FilePath::fromString(doc->fileName()), doc);
m_deps.files.clear(); // Will trigger re-build when accessed.
}
}
@@ -794,7 +793,7 @@ static QList<Macro> macrosDefinedUntilLine(const QList<Macro> &macros, int line)
}
Document::Ptr Snapshot::preprocessedDocument(const QByteArray &source,
- const Utils::FileName &fileName,
+ const Utils::FilePath &fileName,
int withDefinedMacrosFromDocumentUntilLine) const
{
Document::Ptr newDoc = Document::create(fileName.toString());
@@ -858,7 +857,7 @@ QList<Snapshot::IncludeLocation> Snapshot::includeLocationsOfDocument(const QStr
return result;
}
-Utils::FileNameList Snapshot::filesDependingOn(const Utils::FileName &fileName) const
+Utils::FilePathList Snapshot::filesDependingOn(const Utils::FilePath &fileName) const
{
updateDependencyTable();
return m_deps.filesDependingOn(fileName);
@@ -887,7 +886,7 @@ void Snapshot::allIncludesForDocument_helper(const QString &fileName, QSet<QStri
}
}
-Document::Ptr Snapshot::document(const Utils::FileName &fileName) const
+Document::Ptr Snapshot::document(const Utils::FilePath &fileName) const
{
return _documents.value(fileName);
}
diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h
index 006f17aba6..74205f1625 100644
--- a/src/libs/cplusplus/CppDocument.h
+++ b/src/libs/cplusplus/CppDocument.h
@@ -389,7 +389,7 @@ private:
class CPLUSPLUS_EXPORT Snapshot
{
- typedef QHash<Utils::FileName, Document::Ptr> Base;
+ typedef QHash<Utils::FilePath, Document::Ptr> Base;
public:
Snapshot();
@@ -403,36 +403,36 @@ public:
bool isEmpty() const;
void insert(Document::Ptr doc); // ### remove
- void remove(const Utils::FileName &fileName); // ### remove
+ void remove(const Utils::FilePath &fileName); // ### remove
void remove(const QString &fileName)
- { remove(Utils::FileName::fromString(fileName)); }
+ { remove(Utils::FilePath::fromString(fileName)); }
const_iterator begin() const { return _documents.begin(); }
const_iterator end() const { return _documents.end(); }
- bool contains(const Utils::FileName &fileName) const;
+ bool contains(const Utils::FilePath &fileName) const;
bool contains(const QString &fileName) const
- { return contains(Utils::FileName::fromString(fileName)); }
+ { return contains(Utils::FilePath::fromString(fileName)); }
- Document::Ptr document(const Utils::FileName &fileName) const;
+ Document::Ptr document(const Utils::FilePath &fileName) const;
Document::Ptr document(const QString &fileName) const
- { return document(Utils::FileName::fromString(fileName)); }
+ { return document(Utils::FilePath::fromString(fileName)); }
- const_iterator find(const Utils::FileName &fileName) const;
+ const_iterator find(const Utils::FilePath &fileName) const;
const_iterator find(const QString &fileName) const
- { return find(Utils::FileName::fromString(fileName)); }
+ { return find(Utils::FilePath::fromString(fileName)); }
Snapshot simplified(Document::Ptr doc) const;
Document::Ptr preprocessedDocument(const QByteArray &source,
- const Utils::FileName &fileName,
+ const Utils::FilePath &fileName,
int withDefinedMacrosFromDocumentUntilLine = -1) const;
Document::Ptr preprocessedDocument(const QByteArray &source,
const QString &fileName,
int withDefinedMacrosFromDocumentUntilLine = -1) const
{
return preprocessedDocument(source,
- Utils::FileName::fromString(fileName),
+ Utils::FilePath::fromString(fileName),
withDefinedMacrosFromDocumentUntilLine);
}
@@ -442,9 +442,9 @@ public:
QSet<QString> allIncludesForDocument(const QString &fileName) const;
QList<IncludeLocation> includeLocationsOfDocument(const QString &fileName) const;
- Utils::FileNameList filesDependingOn(const Utils::FileName &fileName) const;
- Utils::FileNameList filesDependingOn(const QString &fileName) const
- { return filesDependingOn(Utils::FileName::fromString(fileName)); }
+ Utils::FilePathList filesDependingOn(const Utils::FilePath &fileName) const;
+ Utils::FilePathList filesDependingOn(const QString &fileName) const
+ { return filesDependingOn(Utils::FilePath::fromString(fileName)); }
void updateDependencyTable() const;
bool operator==(const Snapshot &other) const;
diff --git a/src/libs/cplusplus/DependencyTable.cpp b/src/libs/cplusplus/DependencyTable.cpp
index f9c17c0b61..8ddc9801d0 100644
--- a/src/libs/cplusplus/DependencyTable.cpp
+++ b/src/libs/cplusplus/DependencyTable.cpp
@@ -29,9 +29,9 @@
using namespace CPlusPlus;
-Utils::FileNameList DependencyTable::filesDependingOn(const Utils::FileName &fileName) const
+Utils::FilePathList DependencyTable::filesDependingOn(const Utils::FilePath &fileName) const
{
- Utils::FileNameList deps;
+ Utils::FilePathList deps;
int index = fileIndex.value(fileName, -1);
if (index == -1)
@@ -66,14 +66,14 @@ void DependencyTable::build(const Snapshot &snapshot)
}
for (int i = 0; i < files.size(); ++i) {
- const Utils::FileName &fileName = files.at(i);
+ const Utils::FilePath &fileName = files.at(i);
if (Document::Ptr doc = snapshot.document(fileName)) {
QBitArray bitmap(files.size());
QList<int> directIncludes;
const QStringList documentIncludes = doc->includedFiles();
foreach (const QString &includedFile, documentIncludes) {
- int index = fileIndex.value(Utils::FileName::fromString(includedFile));
+ int index = fileIndex.value(Utils::FilePath::fromString(includedFile));
if (index == -1)
continue;
diff --git a/src/libs/cplusplus/DependencyTable.h b/src/libs/cplusplus/DependencyTable.h
index 508ae297c5..3e888c59db 100644
--- a/src/libs/cplusplus/DependencyTable.h
+++ b/src/libs/cplusplus/DependencyTable.h
@@ -44,10 +44,10 @@ class CPLUSPLUS_EXPORT DependencyTable
private:
friend class Snapshot;
void build(const Snapshot &snapshot);
- Utils::FileNameList filesDependingOn(const Utils::FileName &fileName) const;
+ Utils::FilePathList filesDependingOn(const Utils::FilePath &fileName) const;
- QVector<Utils::FileName> files;
- QHash<Utils::FileName, int> fileIndex;
+ QVector<Utils::FilePath> files;
+ QHash<Utils::FilePath, int> fileIndex;
QHash<int, QList<int> > includes;
QVector<QBitArray> includeMap;
};
diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index 173a6e2a5e..638fba451b 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -170,7 +170,7 @@ void FindUsages::reportResult(unsigned tokenIndex)
const int len = tk.utf16chars();
- const Usage u(Utils::FileName::fromString(_doc->fileName()), lineText, line, col, len);
+ const Usage u(Utils::FilePath::fromString(_doc->fileName()), lineText, line, col, len);
_usages.append(u);
_references.append(tokenIndex);
}
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index deed69276a..2b6880a55c 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -40,11 +40,11 @@ class CPLUSPLUS_EXPORT Usage
{
public:
Usage() = default;
- Usage(const Utils::FileName &path, const QString &lineText, int line, int col, int len)
+ Usage(const Utils::FilePath &path, const QString &lineText, int line, int col, int len)
: path(path), lineText(lineText), line(line), col(col), len(len) {}
public:
- Utils::FileName path;
+ Utils::FilePath path;
QString lineText;
int line = 0;
int col = 0;
diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp
index c22d3fe89c..59440813a7 100644
--- a/src/libs/cplusplus/MatchingText.cpp
+++ b/src/libs/cplusplus/MatchingText.cpp
@@ -358,6 +358,32 @@ static bool isAfterRecordLikeDefinition(const BackwardsScanner &tokens, int inde
return false;
}
+static bool isControlFlowKeywordRequiringParentheses(const Token &token)
+{
+ return token.is(T_IF)
+ || token.is(T_WHILE)
+ || token.is(T_FOR)
+ || token.is(T_SWITCH)
+ || token.is(T_CATCH);
+}
+
+static bool isAfterControlFlow(const BackwardsScanner &tokens, int index)
+{
+ const Token &token = tokens[index];
+ if (token.is(T_DO) || token.is(T_ELSE) || token.is(T_TRY))
+ return true;
+
+ if (token.is(T_RPAREN)) {
+ const int startIndex = index + 1;
+ const int matchingBraceIndex = tokens.startOfMatchingBrace(startIndex);
+ if (matchingBraceIndex == startIndex)
+ return false; // No matching paren found.
+ return isControlFlowKeywordRequiringParentheses(tokens[matchingBraceIndex - 1]);
+ }
+
+ return false;
+}
+
static bool allowAutoClosingBrace(const QTextCursor &cursor,
MatchingText::IsNextBlockDeeperIndented isNextIndented)
{
@@ -370,6 +396,9 @@ static bool allowAutoClosingBrace(const QTextCursor &cursor,
if (tokens[index].isStringLiteral())
return false;
+ if (isAfterControlFlow(tokens, index))
+ return false;
+
if (isAfterNamespaceDefinition(tokens, index))
return false;
diff --git a/src/libs/extensionsystem/CMakeLists.txt b/src/libs/extensionsystem/CMakeLists.txt
new file mode 100644
index 0000000000..864c57c1ae
--- /dev/null
+++ b/src/libs/extensionsystem/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_qtc_library(ExtensionSystem
+ DEPENDS Aggregation Utils Qt5::Core Qt5::Widgets
+ PUBLIC_DEPENDS Qt5::Core
+ SOURCES
+ extensionsystem_global.h
+ invoker.cpp invoker.h
+ iplugin.cpp iplugin.h iplugin_p.h
+ optionsparser.cpp optionsparser.h
+ plugindetailsview.cpp plugindetailsview.h plugindetailsview.ui
+ pluginerroroverview.cpp pluginerroroverview.h pluginerroroverview.ui
+ pluginerrorview.cpp pluginerrorview.h pluginerrorview.ui
+ pluginmanager.cpp pluginmanager.h pluginmanager_p.h
+ pluginspec.cpp pluginspec.h pluginspec_p.h
+ pluginview.cpp pluginview.h
+ SKIP_AUTOMOC pluginmanager.cpp
+)
diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp
index 76704be823..90b4e86672 100644
--- a/src/libs/extensionsystem/iplugin.cpp
+++ b/src/libs/extensionsystem/iplugin.cpp
@@ -193,7 +193,7 @@ IPlugin::~IPlugin()
}
/*!
- \fn QList<QObject *> IPlugin::createTestObjects() const
+ \fn QVector<QObject *> IPlugin::createTestObjects() const
Returns objects that are meant to be passed on to QTest::qExec().
@@ -201,9 +201,9 @@ IPlugin::~IPlugin()
The ownership of returned objects is transferred to caller.
*/
-QList<QObject *> IPlugin::createTestObjects() const
+QVector<QObject *> IPlugin::createTestObjects() const
{
- return QList<QObject *>();
+ return {};
}
/*!
diff --git a/src/libs/extensionsystem/iplugin.h b/src/libs/extensionsystem/iplugin.h
index 4b14ecd92b..9b7489ce0f 100644
--- a/src/libs/extensionsystem/iplugin.h
+++ b/src/libs/extensionsystem/iplugin.h
@@ -60,7 +60,7 @@ public:
virtual QObject *remoteCommand(const QStringList & /* options */,
const QString & /* workingDirectory */,
const QStringList & /* arguments */) { return nullptr; }
- virtual QList<QObject *> createTestObjects() const;
+ virtual QVector<QObject *> createTestObjects() const;
PluginSpec *pluginSpec() const;
diff --git a/src/libs/extensionsystem/optionsparser.cpp b/src/libs/extensionsystem/optionsparser.cpp
index c3daed5daa..22c45df31f 100644
--- a/src/libs/extensionsystem/optionsparser.cpp
+++ b/src/libs/extensionsystem/optionsparser.cpp
@@ -115,10 +115,10 @@ bool OptionsParser::checkForTestOptions()
if (m_currentArg == QLatin1String(TEST_OPTION)) {
if (nextToken(RequiredToken)) {
if (m_currentArg == QLatin1String("all")) {
- m_pmPrivate->testSpecs =
- Utils::transform(m_pmPrivate->loadQueue(), [](PluginSpec *spec) {
- return PluginManagerPrivate::TestSpec(spec);
- });
+ m_pmPrivate->testSpecs
+ = Utils::transform<std::vector>(m_pmPrivate->loadQueue(), [](PluginSpec *spec) {
+ return PluginManagerPrivate::TestSpec(spec);
+ });
} else {
QStringList args = m_currentArg.split(QLatin1Char(','));
const QString pluginName = args.takeFirst();
@@ -129,7 +129,7 @@ bool OptionsParser::checkForTestOptions()
"The plugin \"%1\" is specified twice for testing.").arg(pluginName);
m_hasError = true;
} else {
- m_pmPrivate->testSpecs.append(PluginManagerPrivate::TestSpec(spec, args));
+ m_pmPrivate->testSpecs.emplace_back(spec, args);
}
} else {
if (m_errorString)
@@ -265,7 +265,7 @@ bool OptionsParser::checkForUnknownOption()
void OptionsParser::forceDisableAllPluginsExceptTestedAndForceEnabled()
{
- for (const PluginManagerPrivate::TestSpec &testSpec : qAsConst(m_pmPrivate->testSpecs))
+ for (const PluginManagerPrivate::TestSpec &testSpec : m_pmPrivate->testSpecs)
testSpec.pluginSpec->d->setForceEnabled(true);
for (PluginSpec *spec : qAsConst(m_pmPrivate->pluginSpecs)) {
if (!spec->isForceEnabled() && !spec->isRequired())
diff --git a/src/libs/extensionsystem/pluginerroroverview.cpp b/src/libs/extensionsystem/pluginerroroverview.cpp
index 828bd013f4..74e7ac73b0 100644
--- a/src/libs/extensionsystem/pluginerroroverview.cpp
+++ b/src/libs/extensionsystem/pluginerroroverview.cpp
@@ -45,7 +45,7 @@ PluginErrorOverview::PluginErrorOverview(QWidget *parent) :
// only show errors on startup if plugin is enabled.
if (spec->hasError() && spec->isEffectivelyEnabled()) {
QListWidgetItem *item = new QListWidgetItem(spec->name());
- item->setData(Qt::UserRole, qVariantFromValue(spec));
+ item->setData(Qt::UserRole, QVariant::fromValue(spec));
m_ui->pluginList->addItem(item);
}
}
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index 956f6f01eb..6fbda8e4ec 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -319,7 +319,7 @@ void PluginManager::removeObject(QObject *obj)
\sa PluginManager::getObject()
*/
-QList<QObject *> PluginManager::allObjects()
+QVector<QObject *> PluginManager::allObjects()
{
return d->allObjects;
}
@@ -376,10 +376,11 @@ QSet<PluginSpec *> PluginManager::pluginsRequiredByPlugin(PluginSpec *spec)
{
QSet<PluginSpec *> recursiveDependencies;
recursiveDependencies.insert(spec);
- QList<PluginSpec *> queue;
- queue.append(spec);
- while (!queue.isEmpty()) {
- PluginSpec *checkSpec = queue.takeFirst();
+ std::queue<PluginSpec *> queue;
+ queue.push(spec);
+ while (!queue.empty()) {
+ PluginSpec *checkSpec = queue.front();
+ queue.pop();
QHashIterator<PluginDependency, PluginSpec *> depIt(checkSpec->dependencySpecs());
while (depIt.hasNext()) {
depIt.next();
@@ -388,7 +389,7 @@ QSet<PluginSpec *> PluginManager::pluginsRequiredByPlugin(PluginSpec *spec)
PluginSpec *depSpec = depIt.value();
if (!recursiveDependencies.contains(depSpec)) {
recursiveDependencies.insert(depSpec);
- queue.append(depSpec);
+ queue.push(depSpec);
}
}
}
@@ -536,12 +537,12 @@ QStringList PluginManager::arguments()
\sa setPluginPaths()
*/
-const QList<PluginSpec *> PluginManager::plugins()
+const QVector<PluginSpec *> PluginManager::plugins()
{
return d->pluginSpecs;
}
-QHash<QString, QList<PluginSpec *> > PluginManager::pluginCollections()
+QHash<QString, QVector<PluginSpec *>> PluginManager::pluginCollections()
{
return d->pluginCategories;
}
@@ -752,7 +753,7 @@ void PluginManager::formatPluginVersions(QTextStream &str)
*/
bool PluginManager::testRunRequested()
{
- return !d->testSpecs.isEmpty();
+ return !d->testSpecs.empty();
}
/*!
@@ -769,7 +770,7 @@ void PluginManager::profilingReport(const char *what, const PluginSpec *spec)
/*!
Returns a list of plugins in load order.
*/
-QList<PluginSpec *> PluginManager::loadQueue()
+QVector<PluginSpec *> PluginManager::loadQueue()
{
return d->loadQueue();
}
@@ -818,15 +819,16 @@ PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec)
void PluginManagerPrivate::nextDelayedInitialize()
{
- while (!delayedInitializeQueue.isEmpty()) {
- PluginSpec *spec = delayedInitializeQueue.takeFirst();
+ while (!delayedInitializeQueue.empty()) {
+ PluginSpec *spec = delayedInitializeQueue.front();
+ delayedInitializeQueue.pop();
profilingReport(">delayedInitialize", spec);
bool delay = spec->d->delayedInitialize();
profilingReport("<delayedInitialize", spec);
if (delay)
break; // do next delayedInitialize after a delay
}
- if (delayedInitializeQueue.isEmpty()) {
+ if (delayedInitializeQueue.empty()) {
m_isInitializationDone = true;
delete delayedInitializeTimer;
delayedInitializeTimer = nullptr;
@@ -903,7 +905,7 @@ void PluginManagerPrivate::stopAll()
delete delayedInitializeTimer;
delayedInitializeTimer = nullptr;
}
- QList<PluginSpec *> queue = loadQueue();
+ QVector<PluginSpec *> queue = loadQueue();
foreach (PluginSpec *spec, queue) {
loadPlugin(spec, PluginSpec::Stopped);
}
@@ -926,8 +928,10 @@ using TestPlanIterator = QMapIterator<QObject *, QStringList>;
static bool isTestFunction(const QMetaMethod &metaMethod)
{
- static const QList<QByteArray> blackList = QList<QByteArray>()
- << "initTestCase()" << "cleanupTestCase()" << "init()" << "cleanup()";
+ static const QVector<QByteArray> blackList = {"initTestCase()",
+ "cleanupTestCase()",
+ "init()",
+ "cleanup()"};
if (metaMethod.methodType() != QMetaMethod::Slot)
return false;
@@ -991,7 +995,7 @@ static QStringList matchingTestFunctions(const QStringList &testFunctions,
return matchingFunctions;
}
-static QObject *objectWithClassName(const QList<QObject *> &objects, const QString &className)
+static QObject *objectWithClassName(const QVector<QObject *> &objects, const QString &className)
{
return Utils::findOr(objects, nullptr, [className] (QObject *object) -> bool {
QString candidate = QString::fromUtf8(object->metaObject()->className());
@@ -1034,7 +1038,7 @@ static int executeTestPlan(const TestPlan &testPlan)
/// Resulting plan consists of all test functions of the plugin object and
/// all test functions of all test objects of the plugin.
-static TestPlan generateCompleteTestPlan(IPlugin *plugin, const QList<QObject *> &testObjects)
+static TestPlan generateCompleteTestPlan(IPlugin *plugin, const QVector<QObject *> &testObjects)
{
TestPlan testPlan;
@@ -1054,7 +1058,8 @@ static TestPlan generateCompleteTestPlan(IPlugin *plugin, const QList<QObject *>
///
/// Since multiple match texts can match the same function, a test function might
/// be included multiple times for a test object.
-static TestPlan generateCustomTestPlan(IPlugin *plugin, const QList<QObject *> &testObjects,
+static TestPlan generateCustomTestPlan(IPlugin *plugin,
+ const QVector<QObject *> &testObjects,
const QStringList &matchTexts)
{
TestPlan testPlan;
@@ -1062,7 +1067,7 @@ static TestPlan generateCustomTestPlan(IPlugin *plugin, const QList<QObject *> &
const QStringList testFunctionsOfPluginObject = testFunctions(plugin->metaObject());
QStringList matchedTestFunctionsOfPluginObject;
QStringList remainingMatchTexts = matchTexts;
- QList<QObject *> remainingTestObjectsOfPlugin = testObjects;
+ QVector<QObject *> remainingTestObjectsOfPlugin = testObjects;
while (!remainingMatchTexts.isEmpty()) {
const QString matchText = remainingMatchTexts.takeFirst();
@@ -1127,11 +1132,12 @@ void PluginManagerPrivate::startTests()
if (!plugin)
continue; // plugin not loaded
- const QList<QObject *> testObjects = plugin->createTestObjects();
+ const QVector<QObject *> testObjects = plugin->createTestObjects();
ExecuteOnDestruction deleteTestObjects([&]() { qDeleteAll(testObjects); });
Q_UNUSED(deleteTestObjects)
- const bool hasDuplicateTestObjects = testObjects.size() != testObjects.toSet().size();
+ const bool hasDuplicateTestObjects = testObjects.size()
+ != Utils::filteredUnique(testObjects).size();
QTC_ASSERT(!hasDuplicateTestObjects, continue);
QTC_ASSERT(!testObjects.contains(plugin), continue);
@@ -1205,7 +1211,7 @@ void PluginManagerPrivate::removeObject(QObject *obj)
*/
void PluginManagerPrivate::loadPlugins()
{
- QList<PluginSpec *> queue = loadQueue();
+ QVector<PluginSpec *> queue = loadQueue();
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsLoading);
foreach (PluginSpec *spec, queue) {
loadPlugin(spec, PluginSpec::Loaded);
@@ -1218,7 +1224,7 @@ void PluginManagerPrivate::loadPlugins()
Utils::reverseForeach(queue, [this](PluginSpec *spec) {
loadPlugin(spec, PluginSpec::Running);
if (spec->state() == PluginSpec::Running) {
- delayedInitializeQueue.append(spec);
+ delayedInitializeQueue.push(spec);
} else {
// Plugin initialization failed, so cleanup after it
spec->d->kill();
@@ -1261,7 +1267,7 @@ void PluginManagerPrivate::asyncShutdownFinished()
{
auto *plugin = qobject_cast<IPlugin *>(sender());
Q_ASSERT(plugin);
- asynchronousPlugins.removeAll(plugin->pluginSpec());
+ asynchronousPlugins.remove(plugin->pluginSpec());
if (asynchronousPlugins.isEmpty())
shutdownEventLoop->exit();
}
@@ -1269,11 +1275,11 @@ void PluginManagerPrivate::asyncShutdownFinished()
/*!
\internal
*/
-QList<PluginSpec *> PluginManagerPrivate::loadQueue()
+QVector<PluginSpec *> PluginManagerPrivate::loadQueue()
{
- QList<PluginSpec *> queue;
+ QVector<PluginSpec *> queue;
foreach (PluginSpec *spec, pluginSpecs) {
- QList<PluginSpec *> circularityCheckQueue;
+ QVector<PluginSpec *> circularityCheckQueue;
loadQueue(spec, queue, circularityCheckQueue);
}
return queue;
@@ -1282,8 +1288,9 @@ QList<PluginSpec *> PluginManagerPrivate::loadQueue()
/*!
\internal
*/
-bool PluginManagerPrivate::loadQueue(PluginSpec *spec, QList<PluginSpec *> &queue,
- QList<PluginSpec *> &circularityCheckQueue)
+bool PluginManagerPrivate::loadQueue(PluginSpec *spec,
+ QVector<PluginSpec *> &queue,
+ QVector<PluginSpec *> &circularityCheckQueue)
{
if (queue.contains(spec))
return true;
@@ -1433,7 +1440,7 @@ void PluginManagerPrivate::readPluginPaths()
pluginCategories.clear();
// default
- pluginCategories.insert(QString(), QList<PluginSpec *>());
+ pluginCategories.insert(QString(), QVector<PluginSpec *>());
foreach (const QString &pluginFile, pluginFiles(pluginPaths)) {
auto *spec = new PluginSpec;
@@ -1477,7 +1484,7 @@ void PluginManagerPrivate::enableDependenciesIndirectly()
foreach (PluginSpec *spec, pluginSpecs)
spec->d->enabledIndirectly = false;
// cannot use reverse loadQueue here, because test dependencies can introduce circles
- QList<PluginSpec *> queue = Utils::filtered(pluginSpecs, &PluginSpec::isEffectivelyEnabled);
+ QVector<PluginSpec *> queue = Utils::filtered(pluginSpecs, &PluginSpec::isEffectivelyEnabled);
while (!queue.isEmpty()) {
PluginSpec *spec = queue.takeFirst();
queue += spec->d->enableDependenciesIndirectly(containsTestSpec(spec));
diff --git a/src/libs/extensionsystem/pluginmanager.h b/src/libs/extensionsystem/pluginmanager.h
index 411a5205b4..c926d07f4a 100644
--- a/src/libs/extensionsystem/pluginmanager.h
+++ b/src/libs/extensionsystem/pluginmanager.h
@@ -55,14 +55,14 @@ public:
// Object pool operations
static void addObject(QObject *obj);
static void removeObject(QObject *obj);
- static QList<QObject *> allObjects();
+ static QVector<QObject *> allObjects();
static QReadWriteLock *listLock();
// This is useful for soft dependencies using pure interfaces.
template <typename T> static T *getObject()
{
QReadLocker lock(listLock());
- QList<QObject *> all = allObjects();
+ QVector<QObject *> all = allObjects();
foreach (QObject *obj, all) {
if (T *result = qobject_cast<T *>(obj))
return result;
@@ -72,7 +72,7 @@ public:
template <typename T, typename Predicate> static T *getObject(Predicate predicate)
{
QReadLocker lock(listLock());
- QList<QObject *> all = allObjects();
+ QVector<QObject *> all = allObjects();
foreach (QObject *obj, all) {
if (T *result = qobject_cast<T *>(obj))
if (predicate(result))
@@ -84,14 +84,14 @@ public:
static QObject *getObjectByName(const QString &name);
// Plugin operations
- static QList<PluginSpec *> loadQueue();
+ static QVector<PluginSpec *> loadQueue();
static void loadPlugins();
static QStringList pluginPaths();
static void setPluginPaths(const QStringList &paths);
static QString pluginIID();
static void setPluginIID(const QString &iid);
- static const QList<PluginSpec *> plugins();
- static QHash<QString, QList<PluginSpec *>> pluginCollections();
+ static const QVector<PluginSpec *> plugins();
+ static QHash<QString, QVector<PluginSpec *>> pluginCollections();
static bool hasError();
static QSet<PluginSpec *> pluginsRequiringPlugin(PluginSpec *spec);
static QSet<PluginSpec *> pluginsRequiredByPlugin(PluginSpec *spec);
diff --git a/src/libs/extensionsystem/pluginmanager_p.h b/src/libs/extensionsystem/pluginmanager_p.h
index b21a3f7ce4..d67ce28c11 100644
--- a/src/libs/extensionsystem/pluginmanager_p.h
+++ b/src/libs/extensionsystem/pluginmanager_p.h
@@ -35,6 +35,8 @@
#include <QScopedPointer>
#include <QReadWriteLock>
+#include <queue>
+
QT_BEGIN_NAMESPACE
class QTime;
class QTimer;
@@ -65,13 +67,13 @@ public:
void loadPlugins();
void shutdown();
void setPluginPaths(const QStringList &paths);
- QList<PluginSpec *> loadQueue();
+ QVector<ExtensionSystem::PluginSpec *> loadQueue();
void loadPlugin(PluginSpec *spec, PluginSpec::State destState);
void resolveDependencies();
void enableDependenciesIndirectly();
void initProfiling();
void profilingSummary() const;
- void profilingReport(const char *what, const PluginSpec *spec = 0);
+ void profilingReport(const char *what, const PluginSpec *spec = nullptr);
void setSettings(QSettings *settings);
void setGlobalSettings(QSettings *settings);
void readSettings();
@@ -80,8 +82,10 @@ public:
class TestSpec {
public:
TestSpec(PluginSpec *pluginSpec, const QStringList &testFunctionsOrObjects = QStringList())
- : pluginSpec(pluginSpec), testFunctionsOrObjects(testFunctionsOrObjects) {}
- PluginSpec *pluginSpec;
+ : pluginSpec(pluginSpec)
+ , testFunctionsOrObjects(testFunctionsOrObjects)
+ {}
+ PluginSpec *pluginSpec = nullptr;
QStringList testFunctionsOrObjects;
};
@@ -95,21 +99,21 @@ public:
testSpecs = Utils::filtered(testSpecs, [pluginSpec](const TestSpec &s) { return s.pluginSpec != pluginSpec; });
}
- QHash<QString, QList<PluginSpec *>> pluginCategories;
- QList<PluginSpec *> pluginSpecs;
- QList<TestSpec> testSpecs;
+ QHash<QString, QVector<PluginSpec *>> pluginCategories;
+ QVector<PluginSpec *> pluginSpecs;
+ std::vector<TestSpec> testSpecs;
QStringList pluginPaths;
QString pluginIID;
- QList<QObject *> allObjects; // ### make this a QList<QPointer<QObject> > > ?
+ QVector<QObject *> allObjects; // ### make this a QVector<QPointer<QObject> > > ?
QStringList defaultDisabledPlugins; // Plugins/Ignored from install settings
QStringList defaultEnabledPlugins; // Plugins/ForceEnabled from install settings
QStringList disabledPlugins;
QStringList forceEnabledPlugins;
// delayed initialization
QTimer *delayedInitializeTimer = nullptr;
- QList<PluginSpec *> delayedInitializeQueue;
+ std::queue<PluginSpec *> delayedInitializeQueue;
// ansynchronous shutdown
- QList<PluginSpec *> asynchronousPlugins; // plugins that have requested async shutdown
+ QSet<PluginSpec *> asynchronousPlugins; // plugins that have requested async shutdown
QEventLoop *shutdownEventLoop = nullptr; // used for async shutdown
QStringList arguments;
@@ -140,8 +144,8 @@ private:
void readPluginPaths();
bool loadQueue(PluginSpec *spec,
- QList<PluginSpec *> &queue,
- QList<PluginSpec *> &circularityCheckQueue);
+ QVector<ExtensionSystem::PluginSpec *> &queue,
+ QVector<ExtensionSystem::PluginSpec *> &circularityCheckQueue);
void stopAll();
void deleteAll();
diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp
index ef9ac19ea2..b8d0643982 100644
--- a/src/libs/extensionsystem/pluginspec.cpp
+++ b/src/libs/extensionsystem/pluginspec.cpp
@@ -885,7 +885,7 @@ int PluginSpecPrivate::versionCompare(const QString &version1, const QString &ve
/*!
\internal
*/
-bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs)
+bool PluginSpecPrivate::resolveDependencies(const QVector<PluginSpec *> &specs)
{
if (hasError)
return false;
@@ -924,11 +924,11 @@ bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs)
}
// returns the plugins that it actually indirectly enabled
-QList<PluginSpec *> PluginSpecPrivate::enableDependenciesIndirectly(bool enableTestDependencies)
+QVector<PluginSpec *> PluginSpecPrivate::enableDependenciesIndirectly(bool enableTestDependencies)
{
if (!q->isEffectivelyEnabled()) // plugin not enabled, nothing to do
return {};
- QList<PluginSpec *> enabled;
+ QVector<PluginSpec *> enabled;
QHashIterator<PluginDependency, PluginSpec *> it(dependencySpecs);
while (it.hasNext()) {
it.next();
diff --git a/src/libs/extensionsystem/pluginspec_p.h b/src/libs/extensionsystem/pluginspec_p.h
index 9d37ed9923..fc6c0c2ff2 100644
--- a/src/libs/extensionsystem/pluginspec_p.h
+++ b/src/libs/extensionsystem/pluginspec_p.h
@@ -52,7 +52,7 @@ public:
bool read(const QString &fileName);
bool provides(const QString &pluginName, const QString &version) const;
- bool resolveDependencies(const QList<PluginSpec *> &specs);
+ bool resolveDependencies(const QVector<PluginSpec *> &specs);
bool loadLibrary();
bool initializePlugin();
bool initializeExtensions();
@@ -103,7 +103,7 @@ public:
static bool isValidVersion(const QString &version);
static int versionCompare(const QString &version1, const QString &version2);
- QList<PluginSpec *> enableDependenciesIndirectly(bool enableTestDependencies = false);
+ QVector<PluginSpec *> enableDependenciesIndirectly(bool enableTestDependencies = false);
bool readMetaData(const QJsonObject &pluginMetaData);
diff --git a/src/libs/extensionsystem/pluginview.cpp b/src/libs/extensionsystem/pluginview.cpp
index 39a39643cb..bb5d6b98ed 100644
--- a/src/libs/extensionsystem/pluginview.cpp
+++ b/src/libs/extensionsystem/pluginview.cpp
@@ -212,8 +212,10 @@ public:
class CollectionItem : public TreeItem
{
public:
- CollectionItem(const QString &name, QList<PluginSpec *> plugins, PluginView *view)
- : m_name(name), m_plugins(plugins), m_view(view)
+ CollectionItem(const QString &name, QVector<PluginSpec *> plugins, PluginView *view)
+ : m_name(name)
+ , m_plugins(plugins)
+ , m_view(view)
{
foreach (PluginSpec *spec, plugins)
appendChild(new PluginItem(spec, view));
@@ -254,9 +256,11 @@ public:
bool setData(int column, const QVariant &data, int role) override
{
if (column == LoadedColumn && role == Qt::CheckStateRole) {
- const QList<PluginSpec *> affectedPlugins =
- Utils::filtered(m_plugins, [](PluginSpec *spec) { return !spec->isRequired(); });
- if (m_view->setPluginsEnabled(affectedPlugins.toSet(), data.toBool())) {
+ const QVector<PluginSpec *> affectedPlugins
+ = Utils::filtered(m_plugins, [](PluginSpec *spec) { return !spec->isRequired(); });
+ if (m_view->setPluginsEnabled(Utils::transform<QSet>(affectedPlugins,
+ [](PluginSpec *s) { return s; }),
+ data.toBool())) {
update();
return true;
}
@@ -274,7 +278,7 @@ public:
public:
QString m_name;
- QList<PluginSpec *> m_plugins;
+ QVector<PluginSpec *> m_plugins;
PluginView *m_view; // Not owned.
};
@@ -408,13 +412,13 @@ void PluginView::updatePlugins()
// Model.
m_model->clear();
-
- QList<CollectionItem *> collections;
- const QHash<QString, QList<PluginSpec *>> pluginCollections = PluginManager::pluginCollections();
+ const QHash<QString, QVector<PluginSpec *>> pluginCollections
+ = PluginManager::pluginCollections();
+ std::vector<CollectionItem *> collections;
const auto end = pluginCollections.cend();
for (auto it = pluginCollections.cbegin(); it != end; ++it) {
const QString name = it.key().isEmpty() ? tr("Utilities") : it.key();
- collections.append(new CollectionItem(name, it.value(), this));
+ collections.push_back(new CollectionItem(name, it.value(), this));
}
Utils::sort(collections, &CollectionItem::m_name);
diff --git a/src/libs/glsl/CMakeLists.txt b/src/libs/glsl/CMakeLists.txt
new file mode 100644
index 0000000000..e5fcb3692b
--- /dev/null
+++ b/src/libs/glsl/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_qtc_library(GLSL
+ DEPENDS Qt5::Core
+ SOURCES
+ glsl.h
+ glslast.cpp glslast.h
+ glslastdump.cpp glslastdump.h
+ glslastvisitor.cpp glslastvisitor.h
+ glslengine.cpp glslengine.h
+ glslkeywords.cpp
+ glsllexer.cpp glsllexer.h
+ glslmemorypool.cpp glslmemorypool.h
+ glslparser.cpp glslparser.h
+ glslparsertable.cpp glslparsertable_p.h
+ glslsemantic.cpp glslsemantic.h
+ glslsymbol.cpp glslsymbol.h
+ glslsymbols.cpp glslsymbols.h
+ glsltype.cpp glsltype.h
+ glsltypes.cpp glsltypes.h
+)
diff --git a/src/libs/glsl/glslparser.h b/src/libs/glsl/glslparser.h
index f0ccf82cb9..5e148c298b 100644
--- a/src/libs/glsl/glslparser.h
+++ b/src/libs/glsl/glslparser.h
@@ -26,6 +26,8 @@
**
****************************************************************************/
+#pragma once
+
#include "glslparsertable_p.h"
#include "glsllexer.h"
#include "glslast.h"
diff --git a/src/libs/languageserverprotocol/CMakeLists.txt b/src/libs/languageserverprotocol/CMakeLists.txt
new file mode 100644
index 0000000000..9ad446817f
--- /dev/null
+++ b/src/libs/languageserverprotocol/CMakeLists.txt
@@ -0,0 +1,23 @@
+add_qtc_library(LanguageServerProtocol
+ DEPENDS Utils
+ SOURCES
+ basemessage.cpp basemessage.h
+ client.cpp client.h
+ clientcapabilities.cpp clientcapabilities.h
+ completion.cpp completion.h
+ diagnostics.cpp diagnostics.h
+ icontent.h
+ initializemessages.cpp initializemessages.h
+ jsonkeys.h
+ jsonobject.cpp jsonobject.h
+ jsonrpcmessages.cpp jsonrpcmessages.h
+ languagefeatures.cpp languagefeatures.h
+ languageserverprotocol_global.h
+ lsptypes.cpp lsptypes.h
+ lsputils.cpp lsputils.h
+ messages.cpp messages.h
+ servercapabilities.cpp servercapabilities.h
+ shutdownmessages.cpp shutdownmessages.h
+ textsynchronization.cpp textsynchronization.h
+ workspace.cpp workspace.h
+)
diff --git a/src/libs/languageserverprotocol/basemessage.cpp b/src/libs/languageserverprotocol/basemessage.cpp
index 1ee17e3eee..950976549e 100644
--- a/src/libs/languageserverprotocol/basemessage.cpp
+++ b/src/libs/languageserverprotocol/basemessage.cpp
@@ -37,6 +37,8 @@
namespace LanguageServerProtocol {
+Q_LOGGING_CATEGORY(parseLog, "qtc.languageserverprotocol.parse", QtWarningMsg)
+
BaseMessage::BaseMessage()
: mimeType(JsonRpcMessageHandler::jsonRpcMimeType())
{ }
@@ -68,8 +70,7 @@ bool BaseMessage::operator==(const BaseMessage &other) const
return true;
}
-static QPair<QByteArray, QByteArray> splitHeaderFieldLine(
- const QByteArray &headerFieldLine, QString &parseError)
+static QPair<QByteArray, QByteArray> splitHeaderFieldLine(const QByteArray &headerFieldLine)
{
static const int fieldSeparatorLength = int(std::strlen(headerFieldSeparator));
int assignmentIndex = headerFieldLine.indexOf(headerFieldSeparator);
@@ -77,8 +78,7 @@ static QPair<QByteArray, QByteArray> splitHeaderFieldLine(
return {headerFieldLine.mid(0, assignmentIndex),
headerFieldLine.mid(assignmentIndex + fieldSeparatorLength)};
}
- parseError = BaseMessage::tr("Unexpected header line \"%1\".")
- .arg(QLatin1String(headerFieldLine));
+ qCWarning(parseLog) << "Unexpected header line:" << QLatin1String(headerFieldLine);
return {};
}
@@ -134,8 +134,7 @@ void BaseMessage::parse(QBuffer *data, QString &parseError, BaseMessage &message
message.content = data->read(message.contentLength);
return;
}
- const QPair<QByteArray, QByteArray> nameAndValue =
- splitHeaderFieldLine(headerFieldLine, parseError);
+ const QPair<QByteArray, QByteArray> nameAndValue = splitHeaderFieldLine(headerFieldLine);
const QByteArray &headerFieldName = nameAndValue.first.trimmed();
const QByteArray &headerFieldValue = nameAndValue.second.trimmed();
@@ -146,9 +145,8 @@ void BaseMessage::parse(QBuffer *data, QString &parseError, BaseMessage &message
} else if (headerFieldName == contentTypeFieldName) {
parseContentType(message, headerFieldValue, parseError);
} else {
- parseError = tr("Unexpected header field \"%1\" in \"%2\".")
- .arg(QLatin1String(headerFieldName),
- QLatin1String(headerFieldLine));
+ qCWarning(parseLog) << "Unexpected header field" << QLatin1String(headerFieldName)
+ << "in" << QLatin1String(headerFieldLine);
}
}
diff --git a/src/libs/languageserverprotocol/basemessage.h b/src/libs/languageserverprotocol/basemessage.h
index ba8238291a..b2835aa7d7 100644
--- a/src/libs/languageserverprotocol/basemessage.h
+++ b/src/libs/languageserverprotocol/basemessage.h
@@ -31,6 +31,7 @@
#include <QByteArray>
#include <QCoreApplication>
+#include <QLoggingCategory>
QT_BEGIN_NAMESPACE
class QBuffer;
@@ -39,6 +40,8 @@ QT_END_NAMESPACE
namespace LanguageServerProtocol {
+LANGUAGESERVERPROTOCOL_EXPORT Q_DECLARE_LOGGING_CATEGORY(parseLog)
+
class LANGUAGESERVERPROTOCOL_EXPORT BaseMessage
{
Q_DECLARE_TR_FUNCTIONS(BaseMessage)
diff --git a/src/libs/languageserverprotocol/clientcapabilities.cpp b/src/libs/languageserverprotocol/clientcapabilities.cpp
index 0200250444..f73c4ee04c 100644
--- a/src/libs/languageserverprotocol/clientcapabilities.cpp
+++ b/src/libs/languageserverprotocol/clientcapabilities.cpp
@@ -27,19 +27,6 @@
namespace LanguageServerProtocol {
-SymbolCapabilities::SymbolKindCapabilities::SymbolKindCapabilities()
-{
- setValueSet({SymbolKind::File, SymbolKind::Module, SymbolKind::Namespace,
- SymbolKind::Package, SymbolKind::Class, SymbolKind::Method,
- SymbolKind::Property, SymbolKind::Field, SymbolKind::Constructor,
- SymbolKind::Enum, SymbolKind::Interface, SymbolKind::Function,
- SymbolKind::Variable, SymbolKind::Constant, SymbolKind::String,
- SymbolKind::Number, SymbolKind::Boolean, SymbolKind::Array,
- SymbolKind::Object, SymbolKind::Key, SymbolKind::Null,
- SymbolKind::EnumMember, SymbolKind::Struct, SymbolKind::Event,
- SymbolKind::Operator, SymbolKind::TypeParameter});
-}
-
Utils::optional<QList<SymbolKind> > SymbolCapabilities::SymbolKindCapabilities::valueSet() const
{
Utils::optional<QList<int>> array = optionalArray<int>(valueSetKey);
@@ -55,13 +42,6 @@ void SymbolCapabilities::SymbolKindCapabilities::setValueSet(const QList<SymbolK
insert(valueSetKey, enumArrayToJsonArray<SymbolKind>(valueSet));
}
-
-ClientCapabilities::ClientCapabilities()
-{
- setTextDocument(TextDocumentClientCapabilities());
- setWorkspace(WorkspaceClientCapabilities());
-}
-
bool ClientCapabilities::isValid(QStringList *error) const
{
return checkOptional<WorkspaceClientCapabilities>(error, workspaceKey)
@@ -85,14 +65,6 @@ bool WorkspaceClientCapabilities::isValid(QStringList *error) const
&& checkOptional<bool>(error,configurationKey);
}
-TextDocumentClientCapabilities::SynchronizationCapabilities::SynchronizationCapabilities()
-{
- setDynamicRegistration(true);
- setWillSave(true);
- setWillSaveWaitUntil(false);
- setDidSave(true);
-}
-
bool TextDocumentClientCapabilities::SynchronizationCapabilities::isValid(QStringList *error) const
{
return DynamicRegistrationCapabilities::isValid(error)
@@ -101,19 +73,6 @@ bool TextDocumentClientCapabilities::SynchronizationCapabilities::isValid(QStrin
&& checkOptional<bool>(error, didSaveKey);
}
-TextDocumentClientCapabilities::TextDocumentClientCapabilities()
-{
- setSynchronization(SynchronizationCapabilities());
- setDocumentSymbol(SymbolCapabilities());
- setCompletion(CompletionCapabilities());
- CodeActionCapabilities cac;
- CodeActionCapabilities::CodeActionLiteralSupport literalSupport;
- literalSupport.setCodeActionKind(
- CodeActionCapabilities::CodeActionLiteralSupport::CodeActionKind(QList<QString>{"*"}));
- cac.setCodeActionLiteralSupport(literalSupport);
- setCodeAction(cac);
-}
-
bool TextDocumentClientCapabilities::isValid(QStringList *error) const
{
return checkOptional<SynchronizationCapabilities>(error, synchronizationKey)
@@ -136,24 +95,12 @@ bool TextDocumentClientCapabilities::isValid(QStringList *error) const
&& checkOptional<DynamicRegistrationCapabilities>(error, renameKey);
}
-SymbolCapabilities::SymbolCapabilities()
-{
- setSymbolKind(SymbolKindCapabilities());
-}
-
bool SymbolCapabilities::isValid(QStringList *error) const
{
return DynamicRegistrationCapabilities::isValid(error)
&& checkOptional<SymbolKindCapabilities>(error, symbolKindKey);
}
-TextDocumentClientCapabilities::CompletionCapabilities::CompletionCapabilities()
-{
- setDynamicRegistration(true);
- setCompletionItem(CompletionItemCapbilities());
- setCompletionItemKind(CompletionItemKindCapabilities());
-}
-
bool TextDocumentClientCapabilities::CompletionCapabilities::isValid(QStringList *error) const
{
return DynamicRegistrationCapabilities::isValid(error)
diff --git a/src/libs/languageserverprotocol/clientcapabilities.h b/src/libs/languageserverprotocol/clientcapabilities.h
index c10341b3f0..3664007dd1 100644
--- a/src/libs/languageserverprotocol/clientcapabilities.h
+++ b/src/libs/languageserverprotocol/clientcapabilities.h
@@ -46,13 +46,11 @@ public:
class LANGUAGESERVERPROTOCOL_EXPORT SymbolCapabilities : public DynamicRegistrationCapabilities
{
public:
- SymbolCapabilities();
using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities;
- class SymbolKindCapabilities : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT SymbolKindCapabilities : public JsonObject
{
public:
- SymbolKindCapabilities();
using JsonObject::JsonObject;
/*
@@ -85,13 +83,11 @@ public:
class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentClientCapabilities : public JsonObject
{
public:
- TextDocumentClientCapabilities();
using JsonObject::JsonObject;
- class SynchronizationCapabilities : public DynamicRegistrationCapabilities
+ class LANGUAGESERVERPROTOCOL_EXPORT SynchronizationCapabilities : public DynamicRegistrationCapabilities
{
public:
- SynchronizationCapabilities();
using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities;
// The client supports sending will save notifications.
@@ -124,16 +120,14 @@ public:
{ insert(synchronizationKey, synchronization); }
void clearSynchronization() { remove(synchronizationKey); }
- class CompletionCapabilities : public DynamicRegistrationCapabilities
+ class LANGUAGESERVERPROTOCOL_EXPORT CompletionCapabilities : public DynamicRegistrationCapabilities
{
public:
- CompletionCapabilities();
using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities;
- class CompletionItemCapbilities : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemCapbilities : public JsonObject
{
public:
- CompletionItemCapbilities();
using JsonObject::JsonObject;
/*
@@ -180,7 +174,7 @@ public:
{ insert(completionItemKey, completionItem); }
void clearCompletionItem() { remove(completionItemKey); }
- class CompletionItemKindCapabilities : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemKindCapabilities : public JsonObject
{
public:
CompletionItemKindCapabilities();
@@ -227,7 +221,7 @@ public:
{ insert(completionKey, completion); }
void clearCompletion() { remove(completionKey); }
- class HoverCapabilities : public DynamicRegistrationCapabilities
+ class LANGUAGESERVERPROTOCOL_EXPORT HoverCapabilities : public DynamicRegistrationCapabilities
{
public:
using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities;
@@ -246,12 +240,12 @@ public:
void setHover(const HoverCapabilities &hover) { insert(hoverKey, hover); }
void clearHover() { remove(hoverKey); }
- class SignatureHelpCapabilities : public DynamicRegistrationCapabilities
+ class LANGUAGESERVERPROTOCOL_EXPORT SignatureHelpCapabilities : public DynamicRegistrationCapabilities
{
public:
using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities;
- class SignatureInformationCapabilities : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT SignatureInformationCapabilities : public JsonObject
{
public:
using JsonObject::JsonObject;
@@ -355,17 +349,17 @@ public:
{ insert(implementationKey, implementation); }
void clearImplementation() { remove(implementationKey); }
- class CodeActionCapabilities : public DynamicRegistrationCapabilities
+ class LANGUAGESERVERPROTOCOL_EXPORT CodeActionCapabilities : public DynamicRegistrationCapabilities
{
public:
using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities;
- class CodeActionLiteralSupport : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT CodeActionLiteralSupport : public JsonObject
{
public:
using JsonObject::JsonObject;
- class CodeActionKind : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT CodeActionKind : public JsonObject
{
public:
using JsonObject::JsonObject;
@@ -454,7 +448,7 @@ public:
void setApplyEdit(bool applyEdit) { insert(applyEditKey, applyEdit); }
void clearApplyEdit() { remove(applyEditKey); }
- class WorkspaceEditCapabilities : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceEditCapabilities : public JsonObject
{
public:
using JsonObject::JsonObject;
@@ -522,7 +516,6 @@ public:
class LANGUAGESERVERPROTOCOL_EXPORT ClientCapabilities : public JsonObject
{
public:
- ClientCapabilities();
using JsonObject::JsonObject;
// Workspace specific client capabilities.
diff --git a/src/libs/languageserverprotocol/icontent.h b/src/libs/languageserverprotocol/icontent.h
index af14604739..1b57165b2e 100644
--- a/src/libs/languageserverprotocol/icontent.h
+++ b/src/libs/languageserverprotocol/icontent.h
@@ -92,7 +92,7 @@ using ResponseHandler = std::function<void(const QByteArray &, QTextCodec *)>;
using ResponseHandlers = std::function<void(MessageId, const QByteArray &, QTextCodec *)>;
using MethodHandler = std::function<void(const QString, MessageId, const IContent *)>;
-inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::MessageId &id)
+inline uint qHash(const LanguageServerProtocol::MessageId &id)
{
if (Utils::holds_alternative<int>(id))
return QT_PREPEND_NAMESPACE(qHash(Utils::get<int>(id)));
@@ -102,8 +102,7 @@ inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::Me
}
template <typename Error>
-inline LANGUAGESERVERPROTOCOL_EXPORT QDebug operator<<(QDebug stream,
- const LanguageServerProtocol::MessageId &id)
+inline QDebug operator<<(QDebug stream, const LanguageServerProtocol::MessageId &id)
{
if (Utils::holds_alternative<int>(id))
stream << Utils::get<int>(id);
diff --git a/src/libs/languageserverprotocol/initializemessages.cpp b/src/libs/languageserverprotocol/initializemessages.cpp
index 0464f8a13c..92e82d5107 100644
--- a/src/libs/languageserverprotocol/initializemessages.cpp
+++ b/src/libs/languageserverprotocol/initializemessages.cpp
@@ -54,27 +54,18 @@ QString Trace::toString() const
}
#undef RETURN_CASE
-TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities::CompletionItemCapbilities()
-{
-}
-
Utils::optional<QList<MarkupKind>>
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities::
documentationFormat() const
{
- Utils::optional<QList<int>> array = optionalArray<int>(documentationFormatKey);
- if (!array)
- return Utils::nullopt;
- return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
- return static_cast<MarkupKind>(value);
- }));
+ return optionalArray<MarkupKind>(documentationFormatKey);
}
void
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities::
setDocumentationFormat(const QList<MarkupKind> &documentationFormat)
{
- insert(documentationFormatKey, enumArrayToJsonArray<MarkupKind>(documentationFormat));
+ insertArray(documentationFormatKey, documentationFormat);
}
TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities::CompletionItemKindCapabilities()
@@ -111,36 +102,26 @@ setValueSet(const QList<CompletionItemKind::Kind> &valueSet)
Utils::optional<QList<MarkupKind> > TextDocumentClientCapabilities::HoverCapabilities::contentFormat() const
{
- Utils::optional<QList<int>> array = optionalArray<int>(contentFormatKey);
- if (!array)
- return Utils::nullopt;
- return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
- return static_cast<MarkupKind>(value);
- }));
+ return optionalArray<MarkupKind>(contentFormatKey);
}
void TextDocumentClientCapabilities::HoverCapabilities::setContentFormat(const QList<MarkupKind> &contentFormat)
{
- insert(contentFormatKey, enumArrayToJsonArray<MarkupKind>(contentFormat));
+ insertArray(contentFormatKey, contentFormat);
}
Utils::optional<QList<MarkupKind>>
TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities::
documentationFormat() const
{
- Utils::optional<QList<int>> array = optionalArray<int>(documentationFormatKey);
- if (!array)
- return Utils::nullopt;
- return Utils::make_optional(Utils::transform(array.value(), [] (int value) {
- return static_cast<MarkupKind>(value);
- }));
+ return optionalArray<MarkupKind>(documentationFormatKey);
}
void
TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities::
setDocumentationFormat(const QList<MarkupKind> &documentationFormat)
{
- insert(documentationFormatKey, enumArrayToJsonArray<MarkupKind>(documentationFormat));
+ insertArray(documentationFormatKey, documentationFormat);
}
InitializeParams::InitializeParams()
diff --git a/src/libs/languageserverprotocol/jsonkeys.h b/src/libs/languageserverprotocol/jsonkeys.h
index 6dfc40c252..e3673085eb 100644
--- a/src/libs/languageserverprotocol/jsonkeys.h
+++ b/src/libs/languageserverprotocol/jsonkeys.h
@@ -69,6 +69,7 @@ constexpr char contentChangesKey[] = "contentChanges";
constexpr char contentCharsetName[] = "charset";
constexpr char contentFormatKey[] = "contentFormat";
constexpr char contentKey[] = "value";
+constexpr char contentsKey[] = "contents";
constexpr char contentLengthFieldName[] = "Content-Length";
constexpr char contentTypeFieldName[] = "Content-Type";
constexpr char contextKey[] = "context";
diff --git a/src/libs/languageserverprotocol/jsonobject.cpp b/src/libs/languageserverprotocol/jsonobject.cpp
index 1f471db47b..0156276a67 100644
--- a/src/libs/languageserverprotocol/jsonobject.cpp
+++ b/src/libs/languageserverprotocol/jsonobject.cpp
@@ -61,11 +61,7 @@ JsonObject &JsonObject::operator=(const JsonObject &other) = default;
JsonObject &JsonObject::operator=(JsonObject &&other)
{
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
m_jsonObject.swap(other.m_jsonObject);
-#else
- m_jsonObject = other.m_jsonObject; // NOTE use QJsonObject::swap when minimum required Qt version >= 5.10
-#endif
return *this;
}
diff --git a/src/libs/languageserverprotocol/jsonrpcmessages.h b/src/libs/languageserverprotocol/jsonrpcmessages.h
index 66c28bea4b..473c9fe580 100644
--- a/src/libs/languageserverprotocol/jsonrpcmessages.h
+++ b/src/libs/languageserverprotocol/jsonrpcmessages.h
@@ -232,6 +232,7 @@ template <typename Result, typename ErrorDataType>
class Response : public JsonRpcMessage
{
public:
+ explicit Response(const MessageId &id) { setId(id); }
using JsonRpcMessage::JsonRpcMessage;
MessageId id() const
diff --git a/src/libs/languageserverprotocol/languagefeatures.cpp b/src/libs/languageserverprotocol/languagefeatures.cpp
index 06793217f1..cfb4cc6fab 100644
--- a/src/libs/languageserverprotocol/languagefeatures.cpp
+++ b/src/libs/languageserverprotocol/languagefeatures.cpp
@@ -49,19 +49,19 @@ constexpr const char DocumentOnTypeFormattingRequest::methodName[];
constexpr const char RenameRequest::methodName[];
constexpr const char SignatureHelpRequest::methodName[];
-MarkedString LanguageServerProtocol::Hover::content() const
+HoverContent LanguageServerProtocol::Hover::content() const
{
- return MarkedString(value(contentKey));
+ return HoverContent(value(contentsKey));
}
-void Hover::setContent(const MarkedString &content)
+void Hover::setContent(const HoverContent &content)
{
- if (auto val = Utils::get_if<MarkedLanguageString>(&content))
- insert(contentKey, *val);
+ if (auto val = Utils::get_if<MarkedString>(&content))
+ insert(contentsKey, *val);
else if (auto val = Utils::get_if<MarkupContent>(&content))
- insert(contentKey, *val);
- else if (auto val = Utils::get_if<QList<MarkedLanguageString>>(&content))
- insert(contentKey, LanguageClientArray<MarkedLanguageString>(*val).toJson());
+ insert(contentsKey, *val);
+ else if (auto val = Utils::get_if<QList<MarkedString>>(&content))
+ insert(contentsKey, LanguageClientArray<MarkedString>(*val).toJson());
else
QTC_ASSERT_STRING("LanguageClient Using unknown type Hover::setContent");
}
@@ -334,31 +334,52 @@ DocumentHighlightsResult::DocumentHighlightsResult(const QJsonValue &value)
MarkedString::MarkedString(const QJsonValue &value)
{
+ if (value.isObject()) {
+ MarkedLanguageString string(value.toObject());
+ if (string.isValid(nullptr))
+ emplace<MarkedLanguageString>(string);
+ } else if (value.isString()) {
+ emplace<QString>(value.toString());
+ }
+}
+
+LanguageServerProtocol::MarkedString::operator QJsonValue() const
+{
+ if (auto val = Utils::get_if<QString>(this))
+ return *val;
+ if (auto val = Utils::get_if<MarkedLanguageString>(this))
+ return QJsonValue(*val);
+ return {};
+}
+
+HoverContent::HoverContent(const QJsonValue &value)
+{
if (value.isArray()) {
- emplace<QList<MarkedLanguageString>>(
- LanguageClientArray<MarkedLanguageString>(value).toList());
+ emplace<QList<MarkedString>>(LanguageClientArray<MarkedString>(value).toList());
} else if (value.isObject()) {
const QJsonObject &object = value.toObject();
MarkedLanguageString markedLanguageString(object);
if (markedLanguageString.isValid(nullptr))
- emplace<MarkedLanguageString>(markedLanguageString);
+ emplace<MarkedString>(markedLanguageString);
else
emplace<MarkupContent>(MarkupContent(object));
+ } else if (value.isString()) {
+ emplace<MarkedString>(MarkedString(value.toString()));
}
}
-bool MarkedString::isValid(QStringList *errorHierarchy) const
+bool HoverContent::isValid(QStringList *errorHierarchy) const
{
- if (Utils::holds_alternative<MarkedLanguageString>(*this)
+ if (Utils::holds_alternative<MarkedString>(*this)
|| Utils::holds_alternative<MarkupContent>(*this)
- || Utils::holds_alternative<QList<MarkedLanguageString>>(*this)) {
+ || Utils::holds_alternative<QList<MarkedString>>(*this)) {
return true;
}
if (errorHierarchy) {
*errorHierarchy << QCoreApplication::translate(
- "LanguageServerProtocol::MarkedString",
- "MarkedString should be either MarkedLanguageString, "
- "MarkupContent, or QList<MarkedLanguageString>.");
+ "LanguageServerProtocol::HoverContent",
+ "HoverContent should be either MarkedString, "
+ "MarkupContent, or QList<MarkedString>.");
}
return false;
}
diff --git a/src/libs/languageserverprotocol/languagefeatures.h b/src/libs/languageserverprotocol/languagefeatures.h
index 30f3591e64..ddd732718a 100644
--- a/src/libs/languageserverprotocol/languagefeatures.h
+++ b/src/libs/languageserverprotocol/languagefeatures.h
@@ -58,14 +58,31 @@ public:
{ return check<QString>(error, languageKey) && check<QString>(error, valueKey); }
};
-class MarkedString : public Utils::variant<MarkedLanguageString, QList<MarkedLanguageString>, MarkupContent>
+class LANGUAGESERVERPROTOCOL_EXPORT MarkedString
+ : public Utils::variant<QString, MarkedLanguageString>
{
public:
MarkedString() = default;
- explicit MarkedString(const MarkedLanguageString &other) : variant(other) {}
- explicit MarkedString(const QList<MarkedLanguageString> &other) : variant(other) {}
- explicit MarkedString(const MarkupContent &other) : variant(other) {}
+ explicit MarkedString(const MarkedLanguageString &other)
+ : variant(other)
+ {}
+ explicit MarkedString(const QString &other)
+ : variant(other)
+ {}
explicit MarkedString(const QJsonValue &value);
+
+ operator QJsonValue() const;
+};
+
+class LANGUAGESERVERPROTOCOL_EXPORT HoverContent
+ : public Utils::variant<MarkedString, QList<MarkedString>, MarkupContent>
+{
+public:
+ HoverContent() = default;
+ explicit HoverContent(const MarkedString &other) : variant(other) {}
+ explicit HoverContent(const QList<MarkedString> &other) : variant(other) {}
+ explicit HoverContent(const MarkupContent &other) : variant(other) {}
+ explicit HoverContent(const QJsonValue &value);
bool isValid(QStringList *errorHierarchy) const;
};
@@ -74,15 +91,15 @@ class LANGUAGESERVERPROTOCOL_EXPORT Hover : public JsonObject
public:
using JsonObject::JsonObject;
- MarkedString content() const;
- void setContent(const MarkedString &content);
+ HoverContent content() const;
+ void setContent(const HoverContent &content);
Utils::optional<Range> range() const { return optionalValue<Range>(rangeKey); }
void setRange(const Range &range) { insert(rangeKey, range); }
void clearRange() { remove(rangeKey); }
bool isValid(QStringList *error) const override
- { return check<MarkedString>(error, contentKey) && checkOptional<Range>(error, rangeKey); }
+ { return check<HoverContent>(error, contentsKey) && checkOptional<Range>(error, rangeKey); }
};
class LANGUAGESERVERPROTOCOL_EXPORT HoverRequest
@@ -332,9 +349,23 @@ public:
using variant::variant;
DocumentSymbolsResult() : variant(nullptr) {}
DocumentSymbolsResult(const QJsonValue &value);
+ DocumentSymbolsResult(const DocumentSymbolsResult &other) : variant(other) {}
+ DocumentSymbolsResult(DocumentSymbolsResult &&other) : variant(std::move(other)) {}
+
using variant::operator=;
+ DocumentSymbolsResult &operator =(DocumentSymbolsResult &&other)
+ {
+ variant::operator=(std::move(other));
+ return *this;
+ }
+ DocumentSymbolsResult &operator =(const DocumentSymbolsResult &other)
+ {
+ variant::operator=(other);
+ return *this;
+ }
};
+
class LANGUAGESERVERPROTOCOL_EXPORT DocumentSymbolsRequest
: public Request<DocumentSymbolsResult, std::nullptr_t, DocumentSymbolParams>
{
diff --git a/src/libs/languageserverprotocol/lsptypes.cpp b/src/libs/languageserverprotocol/lsptypes.cpp
index 991f7cc1f8..8aa1ecf81c 100644
--- a/src/libs/languageserverprotocol/lsptypes.cpp
+++ b/src/libs/languageserverprotocol/lsptypes.cpp
@@ -324,8 +324,10 @@ Position::Position(const QTextCursor &cursor)
int Position::toPositionInDocument(QTextDocument *doc) const
{
const QTextBlock block = doc->findBlockByNumber(line());
- if (!block.isValid() || block.length() <= character())
+ if (!block.isValid())
return -1;
+ if (block.length() <= character())
+ return block.position() + block.length();
return block.position() + character();
}
@@ -360,7 +362,7 @@ bool Range::overlaps(const Range &range) const
return contains(range.start()) || contains(range.end());
}
-bool DocumentFilter::applies(const Utils::FileName &fileName, const Utils::MimeType &mimeType) const
+bool DocumentFilter::applies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType) const
{
if (Utils::optional<QString> _scheme = scheme()) {
if (_scheme.value() == fileName.toString())
@@ -404,14 +406,30 @@ DocumentUri::DocumentUri(const QString &other)
: QUrl(QUrl::fromPercentEncoding(other.toLocal8Bit()))
{ }
-DocumentUri::DocumentUri(const Utils::FileName &other)
+DocumentUri::DocumentUri(const Utils::FilePath &other)
: QUrl(QUrl::fromLocalFile(other.toString()))
{ }
-Utils::FileName DocumentUri::toFileName() const
+Utils::FilePath DocumentUri::toFileName() const
{
- return isLocalFile() ? Utils::FileName::fromUserInput(QUrl(*this).toLocalFile())
- : Utils::FileName();
+ return isLocalFile() ? Utils::FilePath::fromUserInput(QUrl(*this).toLocalFile())
+ : Utils::FilePath();
+}
+
+MarkupKind::MarkupKind(const QJsonValue &value)
+{
+ m_value = value.toString() == "markdown" ? markdown : plaintext;
+}
+
+LanguageServerProtocol::MarkupKind::operator QJsonValue() const
+{
+ switch (m_value) {
+ case MarkupKind::markdown:
+ return "markdown";
+ case MarkupKind::plaintext:
+ return "plaintext";
+ }
+ return {};
}
} // namespace LanguageServerProtocol
diff --git a/src/libs/languageserverprotocol/lsptypes.h b/src/libs/languageserverprotocol/lsptypes.h
index 9fe9a47a63..ade3ac7ccf 100644
--- a/src/libs/languageserverprotocol/lsptypes.h
+++ b/src/libs/languageserverprotocol/lsptypes.h
@@ -45,16 +45,16 @@ class LANGUAGESERVERPROTOCOL_EXPORT DocumentUri : public QUrl
{
public:
DocumentUri() = default;
- Utils::FileName toFileName() const;
+ Utils::FilePath toFileName() const;
static DocumentUri fromProtocol(const QString &uri) { return DocumentUri(uri); }
- static DocumentUri fromFileName(const Utils::FileName &file) { return DocumentUri(file); }
+ static DocumentUri fromFileName(const Utils::FilePath &file) { return DocumentUri(file); }
operator QJsonValue() const { return QJsonValue(toString()); }
private:
DocumentUri(const QString &other);
- DocumentUri(const Utils::FileName &other);
+ DocumentUri(const Utils::FilePath &other);
friend class LanguageClientValue<QString>;
};
@@ -372,16 +372,30 @@ public:
void setPattern(const QString &pattern) { insert(patternKey, pattern); }
void clearPattern() { remove(patternKey); }
- bool applies(const Utils::FileName &fileName,
+ bool applies(const Utils::FilePath &fileName,
const Utils::MimeType &mimeType = Utils::MimeType()) const;
bool isValid(QStringList *error) const override;
};
-enum class MarkupKind
+class LANGUAGESERVERPROTOCOL_EXPORT MarkupKind
{
- plaintext,
- markdown,
+public:
+ enum Value { plaintext, markdown };
+ MarkupKind() = default;
+ MarkupKind(const Value value)
+ : m_value(value)
+ {}
+ MarkupKind(const QJsonValue &value);
+
+ operator QJsonValue() const;
+ Value value() const { return m_value; }
+
+ bool operator==(const Value &value) const { return m_value == value; }
+
+ bool isValid(void *) const { return true; }
+private:
+ Value m_value = plaintext;
};
class LANGUAGESERVERPROTOCOL_EXPORT MarkupContent : public JsonObject
@@ -390,15 +404,15 @@ public:
using JsonObject::JsonObject;
// The type of the Markup
- MarkupKind kind() const { return static_cast<MarkupKind>(typedValue<int>(kindKey)); }
- void setKind(MarkupKind kind) { insert(kindKey, static_cast<int>(kind)); }
+ MarkupKind kind() const { return value(kindKey); }
+ void setKind(MarkupKind kind) { insert(kindKey, kind); }
// The content itself
QString content() const { return typedValue<QString>(contentKey); }
void setContent(const QString &content) { insert(contentKey, content); }
bool isValid(QStringList *error) const override
- { return check<int>(error, kindKey) && check<QString>(error, contentKey); }
+ { return check<MarkupKind>(error, kindKey) && check<QString>(error, contentKey); }
};
class LANGUAGESERVERPROTOCOL_EXPORT MarkupOrString : public Utils::variant<QString, MarkupContent>
diff --git a/src/libs/languageserverprotocol/lsputils.h b/src/libs/languageserverprotocol/lsputils.h
index ee98db37f4..4646f181e9 100644
--- a/src/libs/languageserverprotocol/lsputils.h
+++ b/src/libs/languageserverprotocol/lsputils.h
@@ -71,6 +71,8 @@ public:
using Utils::variant<QList<T>, std::nullptr_t>::variant;
using Utils::variant<QList<T>, std::nullptr_t>::operator=;
+ LanguageClientArray() {}
+
LanguageClientArray(const QList<T> &list)
{ *this = list; }
diff --git a/src/libs/languageserverprotocol/servercapabilities.cpp b/src/libs/languageserverprotocol/servercapabilities.cpp
index fcd1fadeac..6ebf4f431f 100644
--- a/src/libs/languageserverprotocol/servercapabilities.cpp
+++ b/src/libs/languageserverprotocol/servercapabilities.cpp
@@ -161,7 +161,7 @@ bool ServerCapabilities::WorkspaceServerCapabilities::WorkspaceFoldersCapabiliti
&& checkOptional<QString, bool>(error, changeNotificationsKey);
}
-bool TextDocumentRegistrationOptions::filterApplies(const Utils::FileName &fileName,
+bool TextDocumentRegistrationOptions::filterApplies(const Utils::FilePath &fileName,
const Utils::MimeType &mimeType) const
{
const LanguageClientArray<DocumentFilter> &selector = documentSelector();
diff --git a/src/libs/languageserverprotocol/servercapabilities.h b/src/libs/languageserverprotocol/servercapabilities.h
index 0e31821b17..71d3e4a496 100644
--- a/src/libs/languageserverprotocol/servercapabilities.h
+++ b/src/libs/languageserverprotocol/servercapabilities.h
@@ -52,7 +52,7 @@ public:
void setDocumentSelector(const LanguageClientArray<DocumentFilter> &documentSelector)
{ insert(documentSelectorKey, documentSelector.toJson()); }
- bool filterApplies(const Utils::FileName &fileName,
+ bool filterApplies(const Utils::FilePath &fileName,
const Utils::MimeType &mimeType = Utils::MimeType()) const;
bool isValid(QStringList *error) const override
@@ -268,7 +268,7 @@ public:
void setDocumentSelector(const LanguageClientArray<DocumentFilter> &documentSelector)
{ insert(documentSelectorKey, documentSelector.toJson()); }
- bool filterApplies(const Utils::FileName &fileName,
+ bool filterApplies(const Utils::FilePath &fileName,
const Utils::MimeType &mimeType = Utils::MimeType()) const;
// The id used to register the request. The id can be used to deregister
diff --git a/src/libs/languageserverprotocol/textsynchronization.h b/src/libs/languageserverprotocol/textsynchronization.h
index 2b659366cd..fa81cae51a 100644
--- a/src/libs/languageserverprotocol/textsynchronization.h
+++ b/src/libs/languageserverprotocol/textsynchronization.h
@@ -83,7 +83,7 @@ public:
void setTextDocument(const VersionedTextDocumentIdentifier &textDocument)
{ insert(textDocumentKey, textDocument); }
- class TextDocumentContentChangeEvent : public JsonObject
+ class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentContentChangeEvent : public JsonObject
{
/*
* An event describing a change to a text document. If range and rangeLength are omitted
diff --git a/src/libs/languageserverprotocol/workspace.cpp b/src/libs/languageserverprotocol/workspace.cpp
index 9f73af2ac0..e411878877 100644
--- a/src/libs/languageserverprotocol/workspace.cpp
+++ b/src/libs/languageserverprotocol/workspace.cpp
@@ -98,4 +98,14 @@ ExecuteCommandParams::ExecuteCommandParams(const Command &command)
setArguments(command.arguments().value());
}
+LanguageServerProtocol::WorkSpaceFolderResult::operator const QJsonValue() const
+{
+ if (!Utils::holds_alternative<QList<WorkSpaceFolder>>(*this))
+ return QJsonValue::Null;
+ QJsonArray array;
+ for (auto folder : Utils::get<QList<WorkSpaceFolder>>(*this))
+ array.append(QJsonValue(folder));
+ return array;
+}
+
} // namespace LanguageServerProtocol
diff --git a/src/libs/languageserverprotocol/workspace.h b/src/libs/languageserverprotocol/workspace.h
index 5f69d2c782..bf6a1b9096 100644
--- a/src/libs/languageserverprotocol/workspace.h
+++ b/src/libs/languageserverprotocol/workspace.h
@@ -29,8 +29,17 @@
namespace LanguageServerProtocol {
+class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderResult
+ : public Utils::variant<QList<WorkSpaceFolder>, std::nullptr_t>
+{
+public:
+ using variant::variant;
+ using variant::operator=;
+ operator const QJsonValue() const;
+};
+
class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderRequest : public Request<
- Utils::variant<QList<WorkSpaceFolder>, Utils::nullopt_t>, std::nullptr_t, std::nullptr_t>
+ WorkSpaceFolderResult, std::nullptr_t, std::nullptr_t>
{
public:
WorkSpaceFolderRequest();
diff --git a/src/libs/languageutils/CMakeLists.txt b/src/libs/languageutils/CMakeLists.txt
new file mode 100644
index 0000000000..0cc47e7c60
--- /dev/null
+++ b/src/libs/languageutils/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_library(LanguageUtils
+ PUBLIC_DEPENDS Qt5::Core
+ SOURCES
+ componentversion.cpp componentversion.h
+ fakemetaobject.cpp fakemetaobject.h
+ languageutils_global.h
+)
diff --git a/src/libs/libs.pro b/src/libs/libs.pro
index 26495bbbf0..cbd788ced0 100644
--- a/src/libs/libs.pro
+++ b/src/libs/libs.pro
@@ -14,9 +14,9 @@ SUBDIRS += \
qmleditorwidgets \
glsl \
ssh \
- sqlite \
clangsupport \
- languageserverprotocol
+ languageserverprotocol \
+ sqlite
qtHaveModule(quick) {
SUBDIRS += \
diff --git a/src/libs/modelinglib/CMakeLists.txt b/src/libs/modelinglib/CMakeLists.txt
new file mode 100644
index 0000000000..7b09c932e4
--- /dev/null
+++ b/src/libs/modelinglib/CMakeLists.txt
@@ -0,0 +1,196 @@
+add_qtc_library(Modeling
+ DEFINES MODELING_LIBRARY
+ DEPENDS Qt5::Widgets Utils
+ PUBLIC_DEPENDS OptionalSvg
+ INCLUDES qtserialization/inc
+ PUBLIC_INCLUDES "${CMAKE_CURRENT_LIST_DIR}"
+ SOURCES
+ qmt/config/configcontroller.cpp qmt/config/configcontroller.h
+ qmt/config/sourcepos.cpp qmt/config/sourcepos.h
+ qmt/config/stereotypedefinitionparser.cpp qmt/config/stereotypedefinitionparser.h
+ qmt/config/stringtextsource.cpp qmt/config/stringtextsource.h
+ qmt/config/textscanner.cpp qmt/config/textscanner.h
+ qmt/config/textsource.h
+ qmt/config/token.cpp qmt/config/token.h
+ qmt/controller/container.h
+ qmt/controller/namecontroller.cpp qmt/controller/namecontroller.h
+ qmt/controller/references.h
+ qmt/controller/selection.cpp qmt/controller/selection.h
+ qmt/controller/undocommand.cpp qmt/controller/undocommand.h
+ qmt/controller/undocontroller.cpp qmt/controller/undocontroller.h
+ qmt/diagram_controller/dclonevisitor.cpp qmt/diagram_controller/dclonevisitor.h
+ qmt/diagram_controller/dcontainer.h
+ qmt/diagram_controller/dfactory.cpp qmt/diagram_controller/dfactory.h
+ qmt/diagram_controller/dflatassignmentvisitor.cpp qmt/diagram_controller/dflatassignmentvisitor.h
+ qmt/diagram_controller/diagramcontroller.cpp qmt/diagram_controller/diagramcontroller.h
+ qmt/diagram_controller/dreferences.h
+ qmt/diagram_controller/dselection.h
+ qmt/diagram_controller/dupdatevisitor.cpp qmt/diagram_controller/dupdatevisitor.h
+ qmt/diagram_controller/dvoidvisitor.cpp qmt/diagram_controller/dvoidvisitor.h
+ qmt/diagram/dannotation.cpp qmt/diagram/dannotation.h
+ qmt/diagram/dassociation.cpp qmt/diagram/dassociation.h
+ qmt/diagram/dboundary.cpp qmt/diagram/dboundary.h
+ qmt/diagram/dclass.cpp qmt/diagram/dclass.h
+ qmt/diagram/dcomponent.cpp qmt/diagram/dcomponent.h
+ qmt/diagram/dconnection.cpp qmt/diagram/dconnection.h
+ qmt/diagram/dconstvisitor.h
+ qmt/diagram/ddependency.cpp qmt/diagram/ddependency.h
+ qmt/diagram/ddiagram.cpp qmt/diagram/ddiagram.h
+ qmt/diagram/delement.cpp qmt/diagram/delement.h
+ qmt/diagram/dinheritance.cpp qmt/diagram/dinheritance.h
+ qmt/diagram/ditem.cpp qmt/diagram/ditem.h
+ qmt/diagram/dobject.cpp qmt/diagram/dobject.h
+ qmt/diagram/dpackage.cpp qmt/diagram/dpackage.h
+ qmt/diagram/drelation.cpp qmt/diagram/drelation.h
+ qmt/diagram/dswimlane.cpp qmt/diagram/dswimlane.h
+ qmt/diagram/dvisitor.h
+ qmt/diagram_scene/capabilities/alignable.h
+ qmt/diagram_scene/capabilities/editable.h
+ qmt/diagram_scene/capabilities/intersectionable.h
+ qmt/diagram_scene/capabilities/latchable.h
+ qmt/diagram_scene/capabilities/moveable.h
+ qmt/diagram_scene/capabilities/relationable.h
+ qmt/diagram_scene/capabilities/resizable.h
+ qmt/diagram_scene/capabilities/selectable.h
+ qmt/diagram_scene/capabilities/windable.h
+ qmt/diagram_scene/diagramgraphicsscene.cpp qmt/diagram_scene/diagramgraphicsscene.h
+ qmt/diagram_scene/diagramsceneconstants.h
+ qmt/diagram_scene/diagramscenemodel.cpp qmt/diagram_scene/diagramscenemodel.h
+ qmt/diagram_scene/diagramscenemodelitemvisitors.cpp qmt/diagram_scene/diagramscenemodelitemvisitors.h
+ qmt/diagram_scene/items/annotationitem.cpp qmt/diagram_scene/items/annotationitem.h
+ qmt/diagram_scene/items/associationitem.cpp qmt/diagram_scene/items/associationitem.h
+ qmt/diagram_scene/items/boundaryitem.cpp qmt/diagram_scene/items/boundaryitem.h
+ qmt/diagram_scene/items/classitem.cpp qmt/diagram_scene/items/classitem.h
+ qmt/diagram_scene/items/componentitem.cpp qmt/diagram_scene/items/componentitem.h
+ qmt/diagram_scene/items/connectionitem.cpp qmt/diagram_scene/items/connectionitem.h
+ qmt/diagram_scene/items/diagramitem.cpp qmt/diagram_scene/items/diagramitem.h
+ qmt/diagram_scene/items/itemitem.cpp qmt/diagram_scene/items/itemitem.h
+ qmt/diagram_scene/items/objectitem.cpp qmt/diagram_scene/items/objectitem.h
+ qmt/diagram_scene/items/packageitem.cpp qmt/diagram_scene/items/packageitem.h
+ qmt/diagram_scene/items/relationitem.cpp qmt/diagram_scene/items/relationitem.h
+ qmt/diagram_scene/items/stereotypedisplayvisitor.cpp qmt/diagram_scene/items/stereotypedisplayvisitor.h
+ qmt/diagram_scene/items/swimlaneitem.cpp qmt/diagram_scene/items/swimlaneitem.h
+ qmt/diagram_scene/latchcontroller.cpp qmt/diagram_scene/latchcontroller.h
+ qmt/diagram_scene/parts/alignbuttonsitem.cpp qmt/diagram_scene/parts/alignbuttonsitem.h
+ qmt/diagram_scene/parts/alignlineitem.cpp qmt/diagram_scene/parts/alignlineitem.h
+ qmt/diagram_scene/parts/arrowitem.cpp qmt/diagram_scene/parts/arrowitem.h
+ qmt/diagram_scene/parts/contextlabelitem.cpp qmt/diagram_scene/parts/contextlabelitem.h
+ qmt/diagram_scene/parts/customiconitem.cpp qmt/diagram_scene/parts/customiconitem.h
+ qmt/diagram_scene/parts/editabletextitem.cpp qmt/diagram_scene/parts/editabletextitem.h
+ qmt/diagram_scene/parts/pathselectionitem.cpp qmt/diagram_scene/parts/pathselectionitem.h
+ qmt/diagram_scene/parts/rectangularselectionitem.cpp qmt/diagram_scene/parts/rectangularselectionitem.h
+ qmt/diagram_scene/parts/relationstarter.cpp qmt/diagram_scene/parts/relationstarter.h
+ qmt/diagram_scene/parts/stereotypesitem.cpp qmt/diagram_scene/parts/stereotypesitem.h
+ qmt/diagram_scene/parts/templateparameterbox.cpp qmt/diagram_scene/parts/templateparameterbox.h
+ qmt/diagram_ui/diagram_mime_types.h
+ qmt/diagram_ui/diagramsmanager.cpp qmt/diagram_ui/diagramsmanager.h
+ qmt/diagram_ui/diagramsviewinterface.h
+ qmt/diagram_ui/sceneinspector.cpp qmt/diagram_ui/sceneinspector.h
+ qmt/diagram_widgets_ui/diagramsview.cpp qmt/diagram_widgets_ui/diagramsview.h
+ qmt/diagram_widgets_ui/diagramview.cpp qmt/diagram_widgets_ui/diagramview.h
+ qmt/diagram_widgets_ui/stackeddiagramsview.cpp qmt/diagram_widgets_ui/stackeddiagramsview.h
+ qmt/document_controller/documentcontroller.cpp qmt/document_controller/documentcontroller.h
+ qmt/infrastructure/contextmenuaction.cpp qmt/infrastructure/contextmenuaction.h
+ qmt/infrastructure/exceptions.cpp qmt/infrastructure/exceptions.h
+ qmt/infrastructure/geometryutilities.cpp qmt/infrastructure/geometryutilities.h
+ qmt/infrastructure/handle.h
+ qmt/infrastructure/handles.h
+ qmt/infrastructure/ioexceptions.cpp qmt/infrastructure/ioexceptions.h
+ qmt/infrastructure/qcompressedfile.cpp qmt/infrastructure/qcompressedfile.h
+ qmt/infrastructure/qmtassert.h
+ qmt/infrastructure/qmt_global.h
+ qmt/infrastructure/uid.h
+ qmt/model_controller/mchildrenvisitor.cpp qmt/model_controller/mchildrenvisitor.h
+ qmt/model_controller/mclonevisitor.cpp qmt/model_controller/mclonevisitor.h
+ qmt/model_controller/mcontainer.h
+ qmt/model_controller/mflatassignmentvisitor.cpp qmt/model_controller/mflatassignmentvisitor.h
+ qmt/model_controller/modelcontroller.cpp qmt/model_controller/modelcontroller.h
+ qmt/model_controller/mreferences.h
+ qmt/model_controller/mselection.h
+ qmt/model_controller/mvoidvisitor.cpp qmt/model_controller/mvoidvisitor.h
+ qmt/model/massociation.cpp qmt/model/massociation.h
+ qmt/model/mcanvasdiagram.cpp qmt/model/mcanvasdiagram.h
+ qmt/model/mclass.cpp qmt/model/mclass.h
+ qmt/model/mclassmember.cpp qmt/model/mclassmember.h
+ qmt/model/mcomponent.cpp qmt/model/mcomponent.h
+ qmt/model/mconnection.cpp qmt/model/mconnection.h
+ qmt/model/mconstvisitor.h
+ qmt/model/mdependency.cpp qmt/model/mdependency.h
+ qmt/model/mdiagram.cpp qmt/model/mdiagram.h
+ qmt/model/melement.cpp qmt/model/melement.h
+ qmt/model/minheritance.cpp qmt/model/minheritance.h
+ qmt/model/mitem.cpp qmt/model/mitem.h
+ qmt/model/mobject.cpp qmt/model/mobject.h
+ qmt/model/mpackage.cpp qmt/model/mpackage.h
+ qmt/model/mrelation.cpp qmt/model/mrelation.h
+ qmt/model/msourceexpansion.cpp qmt/model/msourceexpansion.h
+ qmt/model/mvisitor.h
+ qmt/model_ui/modeltreeviewinterface.h
+ qmt/model_ui/sortedtreemodel.cpp qmt/model_ui/sortedtreemodel.h
+ qmt/model_ui/stereotypescontroller.cpp qmt/model_ui/stereotypescontroller.h
+ qmt/model_ui/treemodel.cpp qmt/model_ui/treemodel.h
+ qmt/model_ui/treemodelmanager.cpp qmt/model_ui/treemodelmanager.h
+ qmt/model_widgets_ui/classmembersedit.cpp qmt/model_widgets_ui/classmembersedit.h
+ qmt/model_widgets_ui/modeltreeview.cpp qmt/model_widgets_ui/modeltreeview.h
+ qmt/model_widgets_ui/palettebox.cpp qmt/model_widgets_ui/palettebox.h
+ qmt/model_widgets_ui/propertiesview.cpp qmt/model_widgets_ui/propertiesview.h
+ 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/serializer/diagramserializer.cpp qmt/serializer/diagramserializer.h
+ qmt/serializer/infrastructureserializer.cpp qmt/serializer/infrastructureserializer.h
+ qmt/serializer/modelserializer.cpp qmt/serializer/modelserializer.h
+ qmt/serializer/projectserializer.cpp qmt/serializer/projectserializer.h
+ qmt/stereotype/customrelation.cpp qmt/stereotype/customrelation.h
+ qmt/stereotype/iconshape.cpp qmt/stereotype/iconshape.h
+ qmt/stereotype/shape.h
+ qmt/stereotype/shapepaintvisitor.cpp qmt/stereotype/shapepaintvisitor.h
+ qmt/stereotype/shapes.cpp qmt/stereotype/shapes.h
+ qmt/stereotype/shapevalue.cpp qmt/stereotype/shapevalue.h
+ qmt/stereotype/shapevisitor.h
+ qmt/stereotype/stereotypecontroller.cpp qmt/stereotype/stereotypecontroller.h
+ qmt/stereotype/stereotypeicon.cpp qmt/stereotype/stereotypeicon.h
+ qmt/stereotype/toolbar.cpp qmt/stereotype/toolbar.h
+ qmt/style/defaultstyle.cpp
+ qmt/style/defaultstyleengine.cpp qmt/style/defaultstyleengine.h
+ qmt/style/defaultstyle.h
+ qmt/style/objectvisuals.cpp qmt/style/objectvisuals.h
+ qmt/style/relationstarterstyle.cpp qmt/style/relationstarterstyle.h
+ qmt/style/stylecontroller.cpp qmt/style/stylecontroller.h
+ qmt/style/style.cpp
+ qmt/style/styledobject.cpp qmt/style/styledobject.h
+ qmt/style/styledrelation.cpp qmt/style/styledrelation.h
+ qmt/style/styleengine.h
+ qmt/style/style.h
+ qmt/tasks/alignonrastervisitor.cpp qmt/tasks/alignonrastervisitor.h
+ qmt/tasks/diagramscenecontroller.cpp qmt/tasks/diagramscenecontroller.h
+ qmt/tasks/finddiagramvisitor.cpp qmt/tasks/finddiagramvisitor.h
+ qmt/tasks/findrootdiagramvisitor.cpp qmt/tasks/findrootdiagramvisitor.h
+ qmt/tasks/ielementtasks.h
+ qmt/tasks/isceneinspector.h
+ qmt/tasks/voidelementtasks.cpp qmt/tasks/voidelementtasks.h
+ qstringparser/qstringparser.cpp qstringparser/qstringparser.h
+ qtserialization/inc/qark/access.h
+ qtserialization/inc/qark/archivebasics.h
+ qtserialization/inc/qark/attribute.h
+ qtserialization/inc/qark/baseclass.h
+ qtserialization/inc/qark/flag.h
+ qtserialization/inc/qark/friend_access.h
+ qtserialization/inc/qark/impl/loadingrefmap.h
+ qtserialization/inc/qark/impl/objectid.h
+ qtserialization/inc/qark/impl/savingrefmap.h
+ qtserialization/inc/qark/parameters.h
+ qtserialization/inc/qark/qxmlinarchive.h
+ qtserialization/inc/qark/qxmloutarchive.h
+ qtserialization/inc/qark/reference.h
+ qtserialization/inc/qark/serialize_basic.h
+ qtserialization/inc/qark/serialize_container.h
+ qtserialization/inc/qark/serialize_enum.h
+ qtserialization/inc/qark/serialize.h
+ qtserialization/inc/qark/serialize_pointer.h
+ qtserialization/inc/qark/tag.h
+ qtserialization/inc/qark/typeregistry.h
+ qtserialization/src/flag.cpp
+ qtserialization/src/savingrefmap.cpp
+)
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp
index 37e74adeac..3bcc0727fb 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp
@@ -173,14 +173,13 @@ void ModelTreeView::dragMoveEvent(QDragMoveEvent *event)
if (dynamic_cast<MObject*>(modelElement))
accept = true;
if (m_autoDelayIndex == dropIndex) {
- if (m_autoDelayStartTime.elapsed() > 1000) {
+ if (m_autoDelayStartTimer.elapsed() > 1000) {
setExpanded(dropIndex, !isExpanded(dropIndex));
- m_autoDelayStartTime.start();
+ m_autoDelayStartTimer.start();
}
} else {
m_autoDelayIndex = dropIndex;
- m_autoDelayStartTime = QTime::currentTime();
- m_autoDelayStartTime.start();
+ m_autoDelayStartTimer.start();
}
}
event->setAccepted(accept);
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h
index 724097a365..565d3671c2 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h
@@ -25,11 +25,11 @@
#pragma once
-#include <QTreeView>
#include "qmt/infrastructure/qmt_global.h"
#include "qmt/model_ui/modeltreeviewinterface.h"
-#include <QTime>
+#include <QElapsedTimer>
+#include <QTreeView>
namespace qmt {
@@ -70,7 +70,7 @@ private:
SortedTreeModel *m_sortedTreeModel = nullptr;
IElementTasks *m_elementTasks = nullptr;
QModelIndex m_autoDelayIndex;
- QTime m_autoDelayStartTime;
+ QElapsedTimer m_autoDelayStartTimer;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp
index 63d716d2d1..c8b11d44e1 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp
@@ -352,7 +352,7 @@ void PropertiesView::MView::visitMElement(const MElement *element)
m_stereotypeComboBox->addItems(m_propertiesView->stereotypeController()->knownStereotypes(m_stereotypeElement));
connect(m_stereotypeComboBox->lineEdit(), &QLineEdit::textEdited,
this, &PropertiesView::MView::onStereotypesChanged);
- connect(m_stereotypeComboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ connect(m_stereotypeComboBox, QOverload<const QString &>::of(&QComboBox::activated),
this, &PropertiesView::MView::onStereotypesChanged);
}
if (!m_stereotypeComboBox->hasFocus()) {
@@ -580,7 +580,7 @@ void PropertiesView::MView::visitMDependency(const MDependency *dependency)
m_directionSelector = new QComboBox(m_topWidget);
m_directionSelector->addItems(QStringList({ "->", "<-", "<->" }));
addRow(tr("Direction:"), m_directionSelector, "direction");
- connect(m_directionSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_directionSelector, QOverload<int>::of(&QComboBox::activated),
this, &PropertiesView::MView::onDependencyDirectionChanged);
}
if (isSingleSelection) {
@@ -664,7 +664,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
m_endAKind = new QComboBox(m_topWidget);
m_endAKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") });
addRow(tr("Relationship:"), m_endAKind, "relationship a");
- connect(m_endAKind, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_endAKind, QOverload<int>::of(&QComboBox::activated),
this, &PropertiesView::MView::onAssociationEndAKindChanged);
}
if (isSingleSelection) {
@@ -729,7 +729,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
m_endBKind = new QComboBox(m_topWidget);
m_endBKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") });
addRow(tr("Relationship:"), m_endBKind, "relationship b");
- connect(m_endBKind, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_endBKind, QOverload<int>::of(&QComboBox::activated),
this, &PropertiesView::MView::onAssociationEndBKindChanged);
}
if (isSingleSelection) {
@@ -930,7 +930,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
m_visualSecondaryRoleSelector->addItems({ tr("Normal"), tr("Lighter"), tr("Darker"),
tr("Soften"), tr("Outline"), tr("Flat") });
addRow(tr("Role:"), m_visualSecondaryRoleSelector, "role");
- connect(m_visualSecondaryRoleSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_visualSecondaryRoleSelector, QOverload<int>::of(&QComboBox::activated),
this, &PropertiesView::MView::onVisualSecondaryRoleChanged);
}
if (!m_visualSecondaryRoleSelector->hasFocus()) {
@@ -958,7 +958,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
m_stereotypeDisplaySelector->addItems({ tr("Smart"), tr("None"), tr("Label"),
tr("Decoration"), tr("Icon") });
addRow(tr("Stereotype display:"), m_stereotypeDisplaySelector, "stereotype display");
- connect(m_stereotypeDisplaySelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_stereotypeDisplaySelector, QOverload<int>::of(&QComboBox::activated),
this, &PropertiesView::MView::onStereotypeDisplayChanged);
}
if (!m_stereotypeDisplaySelector->hasFocus()) {
@@ -995,7 +995,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
m_templateDisplaySelector = new QComboBox(m_topWidget);
m_templateDisplaySelector->addItems({ tr("Smart"), tr("Box"), tr("Angle Brackets") });
addRow(tr("Template display:"), m_templateDisplaySelector, "template display");
- connect(m_templateDisplaySelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_templateDisplaySelector, QOverload<int>::of(&QComboBox::activated),
this, &PropertiesView::MView::onTemplateDisplayChanged);
}
if (!m_templateDisplaySelector->hasFocus()) {
@@ -1126,7 +1126,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
tr("Subtitle"), tr("Emphasized"),
tr("Soften"), tr("Footnote") }));
addRow(tr("Role:"), m_annotationVisualRoleSelector, "visual role");
- connect(m_annotationVisualRoleSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_annotationVisualRoleSelector, QOverload<int>::of(&QComboBox::activated),
this, &PropertiesView::MView::onAnnotationVisualRoleChanged);
}
if (!m_annotationVisualRoleSelector->hasFocus()) {
diff --git a/src/libs/qmldebug/CMakeLists.txt b/src/libs/qmldebug/CMakeLists.txt
new file mode 100644
index 0000000000..cdc4c36fb4
--- /dev/null
+++ b/src/libs/qmldebug/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_qtc_library(QmlDebug
+ DEPENDS Qt5::Network Utils
+ SOURCES
+ baseenginedebugclient.cpp baseenginedebugclient.h
+ basetoolsclient.cpp basetoolsclient.h
+ qdebugmessageclient.cpp qdebugmessageclient.h
+ qmldebug_global.h
+ qmldebugclient.cpp qmldebugclient.h
+ qmldebugcommandlinearguments.h
+ qmldebugconnection.cpp qmldebugconnection.h
+ qmldebugconnectionmanager.cpp qmldebugconnectionmanager.h
+ qmldebugconstants.h
+ qmlenginecontrolclient.cpp qmlenginecontrolclient.h
+ qmlenginedebugclient.h
+ qmloutputparser.cpp qmloutputparser.h
+ qmltoolsclient.cpp qmltoolsclient.h
+ qpacketprotocol.cpp qpacketprotocol.h
+)
diff --git a/src/libs/qmldebug/baseenginedebugclient.cpp b/src/libs/qmldebug/baseenginedebugclient.cpp
index 86f54741fc..45cf7590c9 100644
--- a/src/libs/qmldebug/baseenginedebugclient.cpp
+++ b/src/libs/qmldebug/baseenginedebugclient.cpp
@@ -121,7 +121,7 @@ void BaseEngineDebugClient::decode(QDataStream &ds,
{
ObjectReference obj;
obj.m_debugId = prop.m_value.toInt();
- prop.m_value = qVariantFromValue(obj);
+ prop.m_value = QVariant::fromValue(obj);
break;
}
case QmlObjectProperty::Unknown:
diff --git a/src/libs/qmldebug/qmldebugcommandlinearguments.h b/src/libs/qmldebug/qmldebugcommandlinearguments.h
index 0e265c27cc..0c9979647a 100644
--- a/src/libs/qmldebug/qmldebugcommandlinearguments.h
+++ b/src/libs/qmldebug/qmldebugcommandlinearguments.h
@@ -39,7 +39,7 @@ enum QmlDebugServicesPreset {
QmlPreviewServices
};
-static inline QString qmlDebugServices(QmlDebugServicesPreset preset)
+inline QString qmlDebugServices(QmlDebugServicesPreset preset)
{
switch (preset) {
case NoQmlDebugServices:
@@ -58,7 +58,7 @@ static inline QString qmlDebugServices(QmlDebugServicesPreset preset)
}
}
-static inline QString qmlDebugCommandLineArguments(QmlDebugServicesPreset services,
+inline QString qmlDebugCommandLineArguments(QmlDebugServicesPreset services,
const QString &connectionMode, bool block)
{
if (services == NoQmlDebugServices)
@@ -68,19 +68,19 @@ static inline QString qmlDebugCommandLineArguments(QmlDebugServicesPreset servic
.arg(QLatin1String(block ? ",block" : "")).arg(qmlDebugServices(services));
}
-static inline QString qmlDebugTcpArguments(QmlDebugServicesPreset services,
- Utils::Port port, bool block = true)
+inline QString qmlDebugTcpArguments(QmlDebugServicesPreset services,
+ Utils::Port port, bool block = true)
{
return qmlDebugCommandLineArguments(services, QString("port:%1").arg(port.number()), block);
}
-static inline QString qmlDebugNativeArguments(QmlDebugServicesPreset services, bool block = true)
+inline QString qmlDebugNativeArguments(QmlDebugServicesPreset services, bool block = true)
{
return qmlDebugCommandLineArguments(services, QLatin1String("native"), block);
}
-static inline QString qmlDebugLocalArguments(QmlDebugServicesPreset services, const QString &socket,
- bool block = true)
+inline QString qmlDebugLocalArguments(QmlDebugServicesPreset services, const QString &socket,
+ bool block = true)
{
return qmlDebugCommandLineArguments(services, QLatin1String("file:") + socket, block);
}
diff --git a/src/libs/qmldebug/qmldebugconnection.cpp b/src/libs/qmldebug/qmldebugconnection.cpp
index 6664df2b99..143277b379 100644
--- a/src/libs/qmldebug/qmldebugconnection.cpp
+++ b/src/libs/qmldebug/qmldebugconnection.cpp
@@ -45,17 +45,16 @@ const QString clientId = QLatin1String("QDeclarativeDebugClient");
class QmlDebugConnectionPrivate
{
public:
- QmlDebugConnectionPrivate();
- QPacketProtocol *protocol;
- QLocalServer *server;
- QIODevice *device; // Currently a QTcpSocket or a QLocalSocket
+ QPacketProtocol *protocol = nullptr;
+ QLocalServer *server = nullptr;
+ QIODevice *device = nullptr; // Currently a QTcpSocket or a QLocalSocket
- bool gotHello;
+ bool gotHello = false;
QHash <QString, float> serverPlugins;
QHash<QString, QmlDebugClient *> plugins;
- int currentDataStreamVersion;
- int maximumDataStreamVersion;
+ int currentDataStreamVersion = QmlDebugConnection::minimumDataStreamVersion();
+ int maximumDataStreamVersion = QDataStream::Qt_DefaultCompiledVersion;
void advertisePlugins();
void flush();
@@ -75,13 +74,6 @@ static QString socketErrorToString(QAbstractSocket::SocketError error)
return QmlDebugConnection::tr("Error: %1").arg(errorString);
}
-QmlDebugConnectionPrivate::QmlDebugConnectionPrivate() :
- protocol(0), server(0), device(0), gotHello(false),
- currentDataStreamVersion(QmlDebugConnection::minimumDataStreamVersion()),
- maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion)
-{
-}
-
void QmlDebugConnectionPrivate::advertisePlugins()
{
if (!gotHello)
@@ -118,7 +110,7 @@ void QmlDebugConnection::socketDisconnected()
if (d->protocol) {
d->protocol->disconnect();
d->protocol->deleteLater();
- d->protocol = 0;
+ d->protocol = nullptr;
}
if (d->device) {
// Don't allow any "connected()" or "disconnected()" signals to be triggered anymore.
@@ -126,7 +118,7 @@ void QmlDebugConnection::socketDisconnected()
d->device->disconnect();
// Don't immediately delete it as it may do some cleanup on returning from a signal.
d->device->deleteLater();
- d->device = 0;
+ d->device = nullptr;
}
}
@@ -220,7 +212,7 @@ void QmlDebugConnection::protocolReadyRead()
QHash<QString, QmlDebugClient *>::Iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter) {
- const QString pluginName = iter.key();
+ const QString &pluginName = iter.key();
QmlDebugClient::State newState = QmlDebugClient::Unavailable;
if (d->serverPlugins.contains(pluginName))
newState = QmlDebugClient::Enabled;
@@ -282,7 +274,7 @@ void QmlDebugConnection::close()
QmlDebugClient *QmlDebugConnection::client(const QString &name) const
{
Q_D(const QmlDebugConnection);
- return d->plugins.value(name, 0);
+ return d->plugins.value(name, nullptr);
}
bool QmlDebugConnection::addClient(const QString &name, QmlDebugClient *client)
@@ -324,16 +316,11 @@ bool QmlDebugConnection::sendMessage(const QString &name, const QByteArray &mess
return true;
}
-int QmlDebugConnection::minimumDataStreamVersion()
-{
- return QDataStream::Qt_4_7;
-}
-
void QmlDebugConnectionPrivate::flush()
{
- if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(device))
+ if (auto socket = qobject_cast<QAbstractSocket *>(device))
socket->flush();
- else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(device))
+ else if (auto socket = qobject_cast<QLocalSocket *>(device))
socket->flush();
}
@@ -341,7 +328,7 @@ void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
{
Q_D(QmlDebugConnection);
socketDisconnected();
- QTcpSocket *socket = new QTcpSocket(this);
+ auto socket = new QTcpSocket(this);
socket->setProxy(QNetworkProxy::NoProxy);
d->device = socket;
d->protocol = new QPacketProtocol(socket, this);
@@ -352,8 +339,8 @@ void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
emit logStateChange(socketStateToString(state));
});
- connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>
- (&QAbstractSocket::error), this, [this](QAbstractSocket::SocketError error) {
+ connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
+ this, [this](QAbstractSocket::SocketError error) {
emit logError(socketErrorToString(error));
socketDisconnected();
});
@@ -391,8 +378,8 @@ void QmlDebugConnection::newConnection()
connect(socket, &QLocalSocket::disconnected, this, &QmlDebugConnection::socketDisconnected);
- connect(socket, static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>
- (&QLocalSocket::error), this, [this](QLocalSocket::LocalSocketError error) {
+ connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
+ this, [this](QLocalSocket::LocalSocketError error) {
emit logError(socketErrorToString(static_cast<QAbstractSocket::SocketError>(error)));
socketDisconnected();
});
@@ -420,12 +407,11 @@ void QmlDebugConnection::setMaximumDataStreamVersion(int maximumVersion)
QAbstractSocket::SocketState QmlDebugConnection::socketState() const
{
Q_D(const QmlDebugConnection);
- if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(d->device))
+ if (auto socket = qobject_cast<QAbstractSocket *>(d->device))
return socket->state();
- else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(d->device))
+ if (auto socket = qobject_cast<QLocalSocket *>(d->device))
return static_cast<QAbstractSocket::SocketState>(socket->state());
- else
- return QAbstractSocket::UnconnectedState;
+ return QAbstractSocket::UnconnectedState;
}
} // namespace QmlDebug
diff --git a/src/libs/qmldebug/qmldebugconnection.h b/src/libs/qmldebug/qmldebugconnection.h
index 6fe2e35a16..6ca73a1f3c 100644
--- a/src/libs/qmldebug/qmldebugconnection.h
+++ b/src/libs/qmldebug/qmldebugconnection.h
@@ -30,6 +30,7 @@
#include <QObject>
#include <QUrl>
#include <QAbstractSocket>
+#include <QDataStream>
namespace QmlDebug {
@@ -38,10 +39,9 @@ class QmlDebugConnectionPrivate;
class QMLDEBUG_EXPORT QmlDebugConnection : public QObject
{
Q_OBJECT
- Q_DISABLE_COPY(QmlDebugConnection)
Q_DECLARE_PRIVATE(QmlDebugConnection)
public:
- QmlDebugConnection(QObject * = 0);
+ QmlDebugConnection(QObject *parent = nullptr);
~QmlDebugConnection() override;
void connectToHost(const QString &hostName, quint16 port);
@@ -62,7 +62,10 @@ public:
float serviceVersion(const QString &serviceName) const;
bool sendMessage(const QString &name, const QByteArray &message);
- static int minimumDataStreamVersion();
+ static constexpr int minimumDataStreamVersion()
+ {
+ return QDataStream::Qt_4_7;
+ }
signals:
void connected();
diff --git a/src/libs/qmleditorwidgets/CMakeLists.txt b/src/libs/qmleditorwidgets/CMakeLists.txt
new file mode 100644
index 0000000000..b235601754
--- /dev/null
+++ b/src/libs/qmleditorwidgets/CMakeLists.txt
@@ -0,0 +1,22 @@
+add_qtc_library(QmlEditorWidgets
+ DEPENDS qmljs Utils Qt5::Widgets
+ SOURCES
+ colorbox.cpp colorbox.h
+ colorbutton.cpp colorbutton.h
+ contextpanetext.ui
+ contextpanetextwidget.cpp contextpanetextwidget.h
+ contextpanewidget.cpp contextpanewidget.h
+ contextpanewidgetborderimage.ui
+ contextpanewidgetimage.cpp contextpanewidgetimage.h contextpanewidgetimage.ui
+ contextpanewidgetrectangle.cpp contextpanewidgetrectangle.h contextpanewidgetrectangle.ui
+ customcolordialog.cpp customcolordialog.h
+ easingpane/easingcontextpane.cpp easingpane/easingcontextpane.h easingpane/easingcontextpane.ui
+ easingpane/easinggraph.cpp easingpane/easinggraph.h
+ easingpane/easingpane.qrc
+ filewidget.cpp filewidget.h
+ fontsizespinbox.cpp fontsizespinbox.h
+ gradientline.cpp gradientline.h
+ huecontrol.cpp huecontrol.h
+ qmleditorwidgets_global.h
+ resources.qrc
+)
diff --git a/src/libs/qmleditorwidgets/colorbox.cpp b/src/libs/qmleditorwidgets/colorbox.cpp
index ad8109c27d..b0da2642e2 100644
--- a/src/libs/qmleditorwidgets/colorbox.cpp
+++ b/src/libs/qmleditorwidgets/colorbox.cpp
@@ -29,12 +29,10 @@
static inline QString properName(const QColor &color)
{
- QString s;
if (color.alpha() == 255)
- s.sprintf("#%02x%02x%02x", color.red(), color.green(), color.blue());
+ return QString::asprintf("#%02x%02x%02x", color.red(), color.green(), color.blue());
else
- s.sprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue());
- return s;
+ return QString::asprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue());
}
static inline QColor properColor(const QString &str)
diff --git a/src/libs/qmleditorwidgets/contextpanetextwidget.cpp b/src/libs/qmleditorwidgets/contextpanetextwidget.cpp
index bba9bf4d95..70b6c700db 100644
--- a/src/libs/qmleditorwidgets/contextpanetextwidget.cpp
+++ b/src/libs/qmleditorwidgets/contextpanetextwidget.cpp
@@ -73,8 +73,7 @@ ContextPaneTextWidget::ContextPaneTextWidget(QWidget *parent) :
connect(parentContextWidget->colorDialog(), &CustomColorDialog::rejected,
this, &ContextPaneTextWidget::onColorDialogCancled);
- connect(ui->fontSizeSpinBox,
- static_cast<void (QmlEditorWidgets::FontSizeSpinBox::*)(int)>(&QmlEditorWidgets::FontSizeSpinBox::valueChanged),
+ connect(ui->fontSizeSpinBox, QOverload<int>::of(&QmlEditorWidgets::FontSizeSpinBox::valueChanged),
this, &ContextPaneTextWidget::onFontSizeChanged);
connect(ui->fontSizeSpinBox, &QmlEditorWidgets::FontSizeSpinBox::formatChanged,
this, &ContextPaneTextWidget::onFontFormatChanged);
@@ -104,7 +103,7 @@ ContextPaneTextWidget::ContextPaneTextWidget(QWidget *parent) :
connect(ui->bottomAlignmentButton, &QToolButton::toggled,
this, &ContextPaneTextWidget::onVerticalAlignmentChanged);
- connect(ui->styleComboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
+ connect(ui->styleComboBox, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
this, &ContextPaneTextWidget::onStyleComboBoxChanged);
}
diff --git a/src/libs/qmleditorwidgets/customcolordialog.cpp b/src/libs/qmleditorwidgets/customcolordialog.cpp
index a99410467f..de603e0ea9 100644
--- a/src/libs/qmleditorwidgets/customcolordialog.cpp
+++ b/src/libs/qmleditorwidgets/customcolordialog.cpp
@@ -113,17 +113,13 @@ CustomColorDialog::CustomColorDialog(QWidget *parent) : QFrame(parent )
resize(sizeHint());
connect(m_colorBox, &ColorBox::colorChanged, this, &CustomColorDialog::onColorBoxChanged);
- connect(m_alphaSpinBox,
- static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_alphaSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &CustomColorDialog::spinBoxChanged);
- connect(m_rSpinBox,
- static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_rSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &CustomColorDialog::spinBoxChanged);
- connect(m_gSpinBox,
- static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_gSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &CustomColorDialog::spinBoxChanged);
- connect(m_bSpinBox,
- static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_bSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &CustomColorDialog::spinBoxChanged);
connect(m_hueControl, &HueControl::hueChanged, this, &CustomColorDialog::onHueChanged);
diff --git a/src/libs/qmljs/CMakeLists.txt b/src/libs/qmljs/CMakeLists.txt
new file mode 100644
index 0000000000..6a4ef362bc
--- /dev/null
+++ b/src/libs/qmljs/CMakeLists.txt
@@ -0,0 +1,53 @@
+add_qtc_library(qmljs
+ DEPENDS ExtensionSystem Utils
+ PUBLIC_DEPENDS CPlusPlus Qt5::Widgets Qt5::Xml LanguageUtils
+ SOURCES
+ jsoncheck.cpp jsoncheck.h
+ parser/qmldirparser.cpp parser/qmldirparser_p.h
+ parser/qmlerror.cpp parser/qmlerror.h
+ parser/qmljsast.cpp parser/qmljsast_p.h
+ parser/qmljsastfwd_p.h
+ parser/qmljsastvisitor.cpp parser/qmljsastvisitor_p.h
+ parser/qmljsengine_p.cpp parser/qmljsengine_p.h
+ parser/qmljsglobal_p.h
+ parser/qmljsgrammar.cpp parser/qmljsgrammar_p.h
+ parser/qmljskeywords_p.h
+ parser/qmljslexer.cpp parser/qmljslexer_p.h
+ parser/qmljsmemorypool_p.h
+ parser/qmljsparser.cpp parser/qmljsparser_p.h
+ persistenttrie.cpp persistenttrie.h
+ qmljs_global.h
+ qmljsbind.cpp qmljsbind.h
+ qmljsbundle.cpp qmljsbundle.h
+ qmljscheck.cpp qmljscheck.h
+ qmljscodeformatter.cpp qmljscodeformatter.h
+ qmljscompletioncontextfinder.cpp qmljscompletioncontextfinder.h
+ qmljsconstants.h
+ qmljscontext.cpp qmljscontext.h
+ qmljsdialect.cpp qmljsdialect.h
+ qmljsdocument.cpp qmljsdocument.h
+ qmljsevaluate.cpp qmljsevaluate.h
+ qmljsfindexportedcpptypes.cpp qmljsfindexportedcpptypes.h
+ qmljsicons.cpp qmljsicons.h
+ qmljsicontextpane.h
+ qmljsimportdependencies.cpp qmljsimportdependencies.h
+ qmljsindenter.cpp qmljsindenter.h
+ qmljsinterpreter.cpp qmljsinterpreter.h
+ qmljslineinfo.cpp qmljslineinfo.h
+ qmljslink.cpp qmljslink.h
+ qmljsmodelmanagerinterface.cpp qmljsmodelmanagerinterface.h
+ qmljsplugindumper.cpp qmljsplugindumper.h
+ qmljspropertyreader.cpp qmljspropertyreader.h
+ qmljsreformatter.cpp qmljsreformatter.h
+ qmljsrewriter.cpp qmljsrewriter.h
+ qmljsscanner.cpp qmljsscanner.h
+ qmljsscopeastpath.cpp qmljsscopeastpath.h
+ qmljsscopebuilder.cpp qmljsscopebuilder.h
+ qmljsscopechain.cpp qmljsscopechain.h
+ qmljssimplereader.cpp qmljssimplereader.h
+ qmljsstaticanalysismessage.cpp qmljsstaticanalysismessage.h
+ qmljstypedescriptionreader.cpp qmljstypedescriptionreader.h
+ qmljsutils.cpp qmljsutils.h
+ qmljsvalueowner.cpp qmljsvalueowner.h
+ qmljsviewercontext.cpp qmljsviewercontext.h
+)
diff --git a/src/libs/qmljs/parser/qmljslexer.cpp b/src/libs/qmljs/parser/qmljslexer.cpp
index 19d367be1b..ab7a33917e 100644
--- a/src/libs/qmljs/parser/qmljslexer.cpp
+++ b/src/libs/qmljs/parser/qmljslexer.cpp
@@ -116,6 +116,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
_tokenText.reserve(1024);
_errorMessage.clear();
_tokenSpell = QStringRef();
+ _rawString = QStringRef();
_codePtr = code.unicode();
_endPtr = _codePtr + code.length();
@@ -149,13 +150,20 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
void Lexer::scanChar()
{
- unsigned sequenceLength = isLineTerminatorSequence();
+ if (_skipLinefeed) {
+ Q_ASSERT(*_codePtr == QLatin1Char('\n'));
+ ++_codePtr;
+ _skipLinefeed = false;
+ }
_char = *_codePtr++;
- if (sequenceLength == 2)
- _char = *_codePtr++;
-
++_currentColumnNumber;
+
if (isLineTerminator()) {
+ if (_char == QLatin1Char('\r')) {
+ if (_codePtr < _endPtr && *_codePtr == QLatin1Char('\n'))
+ _skipLinefeed = true;
+ _char = QLatin1Char('\n');
+ }
++_currentLineNumber;
_currentColumnNumber = 0;
}
@@ -232,6 +240,7 @@ int Lexer::lex()
again:
_tokenSpell = QStringRef();
+ _rawString = QStringRef();
_tokenKind = scanToken();
_tokenLength = _codePtr - _tokenStartPtr - 1;
@@ -807,12 +816,15 @@ int Lexer::scanString(ScanStringMode mode)
QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode);
bool multilineStringLiteral = false;
- const QChar *startCode = _codePtr;
+ const QChar *startCode = _codePtr - 1;
+ // in case we just parsed a \r, we need to reset this flag to get things working
+ // correctly in the loop below and afterwards
+ _skipLinefeed = false;
if (_engine) {
while (_codePtr <= _endPtr) {
- if (isLineTerminator() && quote != QLatin1Char('`')) {
- if (qmlMode())
+ if (isLineTerminator()) {
+ if ((quote == QLatin1Char('`') || qmlMode()))
break;
_errorCode = IllegalCharacter;
_errorMessage = QCoreApplication::translate("QmlParser", "Stray newline in string literal");
@@ -822,7 +834,8 @@ int Lexer::scanString(ScanStringMode mode)
} else if (_char == '$' && quote == QLatin1Char('`')) {
break;
} else if (_char == quote) {
- _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode);
+ _tokenSpell = _engine->midRef(startCode - _code.unicode(), _codePtr - startCode - 1);
+ _rawString = _tokenSpell;
scanChar();
if (quote == QLatin1Char('`'))
@@ -835,28 +848,36 @@ int Lexer::scanString(ScanStringMode mode)
else
return T_STRING_LITERAL;
}
- scanChar();
+ // don't use scanChar() here, that would transform \r sequences and the midRef() call would create the wrong result
+ _char = *_codePtr++;
+ ++_currentColumnNumber;
}
}
+ // rewind by one char, so things gets scanned correctly
+ --_codePtr;
+
_validTokenText = true;
- _tokenText.resize(0);
- startCode--;
- while (startCode != _codePtr - 1)
- _tokenText += *startCode++;
+ _tokenText = QString(startCode, _codePtr - startCode);
+
+ auto setRawString = [&](const QChar *end) {
+ QString raw(startCode, end - startCode - 1);
+ raw.replace(QLatin1String("\r\n"), QLatin1String("\n"));
+ raw.replace(QLatin1Char('\r'), QLatin1Char('\n'));
+ _rawString = _engine->newStringRef(raw);
+ };
+
+ scanChar();
while (_codePtr <= _endPtr) {
- if (unsigned sequenceLength = isLineTerminatorSequence()) {
- multilineStringLiteral = true;
- _tokenText += _char;
- if (sequenceLength == 2)
- _tokenText += *_codePtr;
- scanChar();
- } else if (_char == mode) {
+ if (_char == quote) {
scanChar();
- if (_engine)
+ if (_engine) {
_tokenSpell = _engine->newStringRef(_tokenText);
+ if (quote == QLatin1Char('`'))
+ setRawString(_codePtr - 1);
+ }
if (quote == QLatin1Char('`'))
_bracesCount = _outerTemplateBraceCount.pop();
@@ -871,8 +892,10 @@ int Lexer::scanString(ScanStringMode mode)
scanChar();
scanChar();
_bracesCount = 1;
- if (_engine)
+ if (_engine) {
_tokenSpell = _engine->newStringRef(_tokenText);
+ setRawString(_codePtr - 2);
+ }
return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE);
} else if (_char == QLatin1Char('\\')) {
diff --git a/src/libs/qmljs/parser/qmljslexer_p.h b/src/libs/qmljs/parser/qmljslexer_p.h
index 39128b4409..5773606c39 100644
--- a/src/libs/qmljs/parser/qmljslexer_p.h
+++ b/src/libs/qmljs/parser/qmljslexer_p.h
@@ -146,6 +146,7 @@ public:
int tokenStartColumn() const { return _tokenColumn; }
inline QStringRef tokenSpell() const { return _tokenSpell; }
+ inline QStringRef rawString() const { return _rawString; }
double tokenValue() const { return _tokenValue; }
QString tokenText() const;
@@ -198,6 +199,7 @@ private:
QString _tokenText;
QString _errorMessage;
QStringRef _tokenSpell;
+ QStringRef _rawString;
const QChar *_codePtr;
const QChar *_endPtr;
@@ -233,6 +235,7 @@ private:
bool _followsClosingBrace;
bool _delimited;
bool _qmlMode;
+ bool _skipLinefeed = false;
int _generatorLevel = 0;
bool _staticIsKeyword = false;
};
diff --git a/src/libs/qmljs/persistenttrie.cpp b/src/libs/qmljs/persistenttrie.cpp
index f3be5a48ca..08c17dd164 100644
--- a/src/libs/qmljs/persistenttrie.cpp
+++ b/src/libs/qmljs/persistenttrie.cpp
@@ -545,7 +545,6 @@ QDebug &operator<<(QDebug &dbg, const Trie &trie)
}
Trie::Trie() {}
Trie::Trie(const TrieNode::Ptr &trie) : trie(trie) {}
-Trie::Trie(const Trie &o) : trie(o.trie){}
QStringList Trie::complete(const QString &root, const QString &base,
LookupFlags flags) const
diff --git a/src/libs/qmljs/persistenttrie.h b/src/libs/qmljs/persistenttrie.h
index 35ab652967..184525b13e 100644
--- a/src/libs/qmljs/persistenttrie.h
+++ b/src/libs/qmljs/persistenttrie.h
@@ -79,7 +79,6 @@ class QMLJS_EXPORT Trie
public:
Trie();
Trie(const TrieNode::Ptr &t);
- Trie(const Trie &o);
QStringList complete(const QString &root, const QString &base = QString(),
LookupFlags flags = LookupFlags(CaseInsensitive|Partial)) const;
diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri
index 2aa95a9f7a..47967446bf 100644
--- a/src/libs/qmljs/qmljs-lib.pri
+++ b/src/libs/qmljs/qmljs-lib.pri
@@ -36,7 +36,6 @@ HEADERS += \
$$PWD/jsoncheck.h \
$$PWD/qmljssimplereader.h \
$$PWD/persistenttrie.h \
- $$PWD/qmljsqrcparser.h \
$$PWD/qmljsconstants.h \
$$PWD/qmljsimportdependencies.h \
$$PWD/qmljsviewercontext.h \
@@ -70,7 +69,6 @@ SOURCES += \
$$PWD/jsoncheck.cpp \
$$PWD/qmljssimplereader.cpp \
$$PWD/persistenttrie.cpp \
- $$PWD/qmljsqrcparser.cpp \
$$PWD/qmljsimportdependencies.cpp \
$$PWD/qmljsviewercontext.cpp \
$$PWD/qmljsdialect.cpp
diff --git a/src/libs/qmljs/qmljs.qbs b/src/libs/qmljs/qmljs.qbs
index ddfb4c200e..a2580cab1e 100644
--- a/src/libs/qmljs/qmljs.qbs
+++ b/src/libs/qmljs/qmljs.qbs
@@ -42,7 +42,6 @@ Project {
"qmljsmodelmanagerinterface.cpp", "qmljsmodelmanagerinterface.h",
"qmljsplugindumper.cpp", "qmljsplugindumper.h",
"qmljspropertyreader.cpp", "qmljspropertyreader.h",
- "qmljsqrcparser.cpp", "qmljsqrcparser.h",
"qmljsreformatter.cpp", "qmljsreformatter.h",
"qmljsrewriter.cpp", "qmljsrewriter.h",
"qmljsscanner.cpp", "qmljsscanner.h",
diff --git a/src/libs/qmljs/qmljsbundle.cpp b/src/libs/qmljs/qmljsbundle.cpp
index ec46379f2c..9789d37492 100644
--- a/src/libs/qmljs/qmljsbundle.cpp
+++ b/src/libs/qmljs/qmljsbundle.cpp
@@ -35,11 +35,6 @@
namespace QmlJS {
typedef PersistentTrie::Trie Trie;
-QmlBundle::QmlBundle(const QmlBundle &o)
- : m_name(o.m_name), m_searchPaths(o.searchPaths()), m_installPaths(o.installPaths()),
- m_supportedImports(o.m_supportedImports), m_implicitImports(o.m_implicitImports)
-{ }
-
QmlBundle::QmlBundle()
{ }
diff --git a/src/libs/qmljs/qmljsbundle.h b/src/libs/qmljs/qmljsbundle.h
index 0bf00ab755..8057abc6d7 100644
--- a/src/libs/qmljs/qmljsbundle.h
+++ b/src/libs/qmljs/qmljsbundle.h
@@ -51,7 +51,6 @@ class QMLJS_EXPORT QmlBundle
{
typedef PersistentTrie::Trie Trie;
public:
- QmlBundle(const QmlBundle &o);
QmlBundle();
QmlBundle(const QString &name,
const Trie &searchPaths,
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index ea43a4dec8..e5243830cd 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -384,6 +384,7 @@ protected:
_possiblyUndeclaredUses.clear();
_seenNonDeclarationStatement = false;
_formalParameterNames.clear();
+ QTC_ASSERT(_block == 0, _block = 0);
}
void postVisit(Node *ast)
@@ -399,8 +400,11 @@ protected:
if (ast->name.isEmpty())
return false;
const QString &name = ast->name.toString();
- if (!_declaredFunctions.contains(name) && !_declaredVariables.contains(name))
+ if (!_declaredFunctions.contains(name)
+ && !(_declaredVariables.contains(name)
+ || _declaredBlockVariables.contains({name, _block}))) {
_possiblyUndeclaredUses[name].append(ast->identifierToken);
+ }
return false;
}
@@ -416,13 +420,26 @@ protected:
if (ast->bindingIdentifier.isEmpty() || !ast->isVariableDeclaration())
return true;
const QString &name = ast->bindingIdentifier.toString();
-
- if (_formalParameterNames.contains(name))
+ VariableScope scope = ast->scope;
+ if (_formalParameterNames.contains(name)) {
addMessage(WarnAlreadyFormalParameter, ast->identifierToken, name);
- else if (_declaredFunctions.contains(name))
+ } else if (_declaredFunctions.contains(name)) {
addMessage(WarnAlreadyFunction, ast->identifierToken, name);
- else if (_declaredVariables.contains(name))
- addMessage(WarnDuplicateDeclaration, ast->identifierToken, name);
+ } else if (scope == VariableScope::Let || scope == VariableScope::Const) {
+ if (_declaredBlockVariables.contains({name, _block}))
+ addMessage(WarnDuplicateDeclaration, ast->identifierToken, name);
+ } else if (scope == VariableScope::Var) {
+ if (_declaredVariables.contains(name)) {
+ addMessage(WarnDuplicateDeclaration, ast->identifierToken, name);
+ } else {
+ for (auto k : _declaredBlockVariables.keys()) {
+ if (k.first == name) {
+ addMessage(WarnDuplicateDeclaration, ast->identifierToken, name);
+ break;
+ }
+ }
+ }
+ }
if (_possiblyUndeclaredUses.contains(name)) {
foreach (const SourceLocation &loc, _possiblyUndeclaredUses.value(name)) {
@@ -430,7 +447,10 @@ protected:
}
_possiblyUndeclaredUses.remove(name);
}
- _declaredVariables[name] = ast;
+ if (scope == VariableScope::Let || scope == VariableScope::Const)
+ _declaredBlockVariables[{name, _block}] = ast;
+ else
+ _declaredVariables[name] = ast;
return true;
}
@@ -451,7 +471,7 @@ protected:
if (_formalParameterNames.contains(name))
addMessage(WarnAlreadyFormalParameter, ast->identifierToken, name);
- else if (_declaredVariables.contains(name))
+ else if (_declaredVariables.contains(name) || _declaredBlockVariables.contains({name, _block}))
addMessage(WarnAlreadyVar, ast->identifierToken, name);
else if (_declaredFunctions.contains(name))
addMessage(WarnDuplicateDeclaration, ast->identifierToken, name);
@@ -469,6 +489,25 @@ protected:
return false;
}
+ bool visit(Block *) override
+ {
+ ++_block;
+ return true;
+ }
+
+ void endVisit(Block *) override
+ {
+ auto it = _declaredBlockVariables.begin();
+ auto end = _declaredBlockVariables.end();
+ while (it != end) {
+ if (it.key().second == _block)
+ it = _declaredBlockVariables.erase(it);
+ else
+ ++it;
+ }
+ --_block;
+ }
+
private:
void addMessage(Type type, const SourceLocation &loc, const QString &arg1 = QString())
{
@@ -478,9 +517,11 @@ private:
QList<Message> _messages;
QStringList _formalParameterNames;
QHash<QString, PatternElement *> _declaredVariables;
+ QHash<QPair<QString, uint>, PatternElement *> _declaredBlockVariables;
QHash<QString, FunctionDeclaration *> _declaredFunctions;
QHash<QString, QList<SourceLocation> > _possiblyUndeclaredUses;
bool _seenNonDeclarationStatement;
+ uint _block = 0;
};
class IdsThatShouldNotBeUsedInDesigner : public QStringList
@@ -1635,7 +1676,7 @@ bool Check::visit(CallExpression *ast)
if (!whiteListedFunction && !isMathFunction && !isDateFunction && !isDirectInConnectionsScope)
addMessage(ErrFunctionsNotSupportedInQmlUi, location);
- static const QStringList globalFunctions = {"String", "Boolean", "Date", "Number", "Object", "QT_TR_NOOP", "QT_TRANSLATE_NOOP", "QT_TRID_NOOP"};
+ static const QStringList globalFunctions = {"String", "Boolean", "Date", "Number", "Object", "Array", "QT_TR_NOOP", "QT_TRANSLATE_NOOP", "QT_TRID_NOOP"};
if (!name.isEmpty() && name.at(0).isUpper() && !globalFunctions.contains(name)) {
addMessage(WarnExpectedNewWithUppercaseFunction, location);
diff --git a/src/libs/qmljs/qmljsdialect.cpp b/src/libs/qmljs/qmljsdialect.cpp
index 0cb463b2e5..cfe71b2265 100644
--- a/src/libs/qmljs/qmljsdialect.cpp
+++ b/src/libs/qmljs/qmljsdialect.cpp
@@ -30,7 +30,6 @@
namespace QmlJS {
-
bool Dialect::isQmlLikeLanguage() const
{
switch (m_dialect) {
@@ -233,7 +232,7 @@ QDebug operator << (QDebug &dbg, const Dialect &dialect)
return dbg;
}
-PathAndLanguage::PathAndLanguage(const Utils::FileName &path, Dialect language)
+PathAndLanguage::PathAndLanguage(const Utils::FilePath &path, Dialect language)
: m_path(path), m_language(language)
{ }
@@ -294,11 +293,11 @@ void PathsAndLanguages::compact()
return;
int oldCompactionPlace = 0;
- Utils::FileName oldPath = m_list.first().path();
+ Utils::FilePath oldPath = m_list.first().path();
QList<PathAndLanguage> compactedList;
bool restrictFailed = false;
for (int i = 1; i < m_list.length(); ++i) {
- Utils::FileName newPath = m_list.at(i).path();
+ Utils::FilePath newPath = m_list.at(i).path();
if (newPath == oldPath) {
int newCompactionPlace = i - 1;
compactedList << m_list.mid(oldCompactionPlace, newCompactionPlace - oldCompactionPlace);
diff --git a/src/libs/qmljs/qmljsdialect.h b/src/libs/qmljs/qmljsdialect.h
index 8d1ca30deb..230642e145 100644
--- a/src/libs/qmljs/qmljsdialect.h
+++ b/src/libs/qmljs/qmljsdialect.h
@@ -78,11 +78,8 @@ QMLJS_EXPORT QDebug operator << (QDebug &dbg, const Dialect &dialect);
class QMLJS_EXPORT PathAndLanguage {
public:
- PathAndLanguage(const Utils::FileName &path = Utils::FileName(), Dialect language = Dialect::AnyLanguage);
- PathAndLanguage(const PathAndLanguage &o)
- : m_path(o.path()), m_language(o.language())
- { }
- Utils::FileName path() const {
+ PathAndLanguage(const Utils::FilePath &path = Utils::FilePath(), Dialect language = Dialect::AnyLanguage);
+ Utils::FilePath path() const {
return m_path;
}
Dialect language() const {
@@ -91,7 +88,7 @@ public:
bool operator ==(const PathAndLanguage &other) const;
bool operator < (const PathAndLanguage &other) const;
private:
- Utils::FileName m_path;
+ Utils::FilePath m_path;
Dialect m_language;
};
@@ -130,11 +127,8 @@ public:
explicit PathsAndLanguages(const QList<PathAndLanguage> &list)
: m_list(list)
{ }
- PathsAndLanguages(const PathsAndLanguages &o)
- : m_list(o.m_list)
- { }
- bool maybeInsert(const Utils::FileName &path, Dialect language = Dialect::AnyLanguage) {
+ bool maybeInsert(const Utils::FilePath &path, Dialect language = Dialect::AnyLanguage) {
return maybeInsert(PathAndLanguage(path, language));
}
diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp
index a4551b1c1c..6ebe5b0b2f 100644
--- a/src/libs/qmljs/qmljsdocument.cpp
+++ b/src/libs/qmljs/qmljsdocument.cpp
@@ -458,14 +458,6 @@ Snapshot::~Snapshot()
{
}
-Snapshot::Snapshot(const Snapshot &o)
- : _documents(o._documents),
- _documentsByPath(o._documentsByPath),
- _libraries(o._libraries),
- _dependencies(o._dependencies)
-{
-}
-
void Snapshot::insert(const Document::Ptr &document, bool allowInvalid)
{
if (document && (allowInvalid || document->qmlProgram() || document->jsProgram())) {
diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h
index 4029373992..82df720776 100644
--- a/src/libs/qmljs/qmljsdocument.h
+++ b/src/libs/qmljs/qmljsdocument.h
@@ -230,7 +230,6 @@ class QMLJS_EXPORT Snapshot
public:
Snapshot();
- Snapshot(const Snapshot &o);
~Snapshot();
typedef Base::iterator iterator;
diff --git a/src/libs/qmljs/qmljsimportdependencies.cpp b/src/libs/qmljs/qmljsimportdependencies.cpp
index adc9c9ff57..afa8d58b3a 100644
--- a/src/libs/qmljs/qmljsimportdependencies.cpp
+++ b/src/libs/qmljs/qmljsimportdependencies.cpp
@@ -25,9 +25,9 @@
#include "qmljsimportdependencies.h"
#include "qmljsinterpreter.h"
-#include "qmljsqrcparser.h"
#include "qmljsviewercontext.h"
+#include <utils/qrcparser.h>
#include <utils/qtcassert.h>
#include <QCryptographicHash>
@@ -139,10 +139,10 @@ ImportKey::ImportKey(ImportType::Enum type, const QString &path, int majorVersio
break;
case ImportType::File:
case ImportType::QrcFile:
- splitPath = QrcParser::normalizedQrcFilePath(path).split(QLatin1Char('/'));
+ splitPath = Utils::QrcParser::normalizedQrcFilePath(path).split(QLatin1Char('/'));
break;
case ImportType::QrcDirectory:
- splitPath = QrcParser::normalizedQrcDirectoryPath(path).split(QLatin1Char('/'));
+ splitPath = Utils::QrcParser::normalizedQrcDirectoryPath(path).split(QLatin1Char('/'));
if (splitPath.length() > 1 && splitPath.last().isEmpty())
splitPath.removeLast();
break;
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 03083501b6..91f195f8fc 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -2340,6 +2340,16 @@ Import::Import(const Import &other)
valid(other.valid), used(false)
{ }
+Import &Import::operator=(const Import &other)
+{
+ object = other.object;
+ info = other.info;
+ libraryPath = other.libraryPath;
+ valid = other.valid;
+ used = false;
+ return *this;
+}
+
TypeScope::TypeScope(const Imports *imports, ValueOwner *valueOwner)
: ObjectValue(valueOwner)
, m_imports(imports)
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 9da1aa8635..f2e953180c 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -1038,6 +1038,7 @@ class QMLJS_EXPORT Import {
public:
Import();
Import(const Import &other);
+ Import &operator=(const Import &other);
// const!
ObjectValue *object;
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index 737ec6cc46..1acdb68ed9 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -30,9 +30,10 @@
#include "qmljsbind.h"
#include "qmljsutils.h"
#include "qmljsmodelmanagerinterface.h"
-#include "qmljsqrcparser.h"
#include "qmljsconstants.h"
+#include <utils/qrcparser.h>
+
#include <QDir>
using namespace LanguageUtils;
@@ -557,7 +558,7 @@ void LinkPrivate::loadImplicitDirectoryImports(Imports *imports, Document::Ptr d
foreach (const QString &path,
ModelManagerInterface::instance()->qrcPathsForFile(doc->fileName())) {
processImport(ImportInfo::qrcDirectoryImport(
- QrcParser::qrcDirectoryPathForQrcFilePath(path)));
+ Utils::QrcParser::qrcDirectoryPathForQrcFilePath(path)));
}
}
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index 82d4da3f4a..6bb1bc8ff9 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -52,6 +52,8 @@
#include <stdio.h>
+using namespace Utils;
+
namespace QmlJS {
QMLJS_EXPORT Q_LOGGING_CATEGORY(qmljsLog, "qtc.qmljs.common", QtWarningMsg)
@@ -1098,14 +1100,14 @@ void ModelManagerInterface::updateImportPaths()
PathAndLanguage pAndL = iPaths.at(i);
const QString canonicalPath = pAndL.path().toFileInfo().canonicalFilePath();
if (!canonicalPath.isEmpty())
- allImportPaths.maybeInsert(Utils::FileName::fromString(canonicalPath),
+ allImportPaths.maybeInsert(Utils::FilePath::fromString(canonicalPath),
pAndL.language());
}
}
while (vCtxsIter.hasNext()) {
vCtxsIter.next();
foreach (const QString &path, vCtxsIter.value().paths)
- allImportPaths.maybeInsert(Utils::FileName::fromString(path), vCtxsIter.value().language);
+ allImportPaths.maybeInsert(Utils::FilePath::fromString(path), vCtxsIter.value().language);
}
pInfoIter.toFront();
while (pInfoIter.hasNext()) {
@@ -1116,7 +1118,7 @@ void ModelManagerInterface::updateImportPaths()
.searchPaths().stringList()) {
const QString canonicalPath = QFileInfo(path).canonicalFilePath();
if (!canonicalPath.isEmpty())
- allImportPaths.maybeInsert(Utils::FileName::fromString(canonicalPath), l);
+ allImportPaths.maybeInsert(Utils::FilePath::fromString(canonicalPath), l);
}
}
}
@@ -1125,16 +1127,16 @@ void ModelManagerInterface::updateImportPaths()
pInfoIter.next();
QString pathAtt = pInfoIter.value().qtQmlPath;
if (!pathAtt.isEmpty())
- allImportPaths.maybeInsert(Utils::FileName::fromString(pathAtt), Dialect::QmlQtQuick2);
+ allImportPaths.maybeInsert(Utils::FilePath::fromString(pathAtt), Dialect::QmlQtQuick2);
}
{
QString pathAtt = defaultProjectInfo().qtQmlPath;
if (!pathAtt.isEmpty())
- allImportPaths.maybeInsert(Utils::FileName::fromString(pathAtt), Dialect::QmlQtQuick2);
+ allImportPaths.maybeInsert(Utils::FilePath::fromString(pathAtt), Dialect::QmlQtQuick2);
}
foreach (const QString &path, m_defaultImportPaths)
- allImportPaths.maybeInsert(Utils::FileName::fromString(path), Dialect::Qml);
+ allImportPaths.maybeInsert(Utils::FilePath::fromString(path), Dialect::Qml);
allImportPaths.compact();
{
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index 5de25eead3..cd36cbca2f 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -28,11 +28,11 @@
#include "qmljs_global.h"
#include "qmljsbundle.h"
#include "qmljsdocument.h"
-#include "qmljsqrcparser.h"
#include "qmljsdialect.h"
#include <cplusplus/CppDocument.h>
#include <utils/environment.h>
+#include <utils/qrcparser.h>
#include <QFuture>
#include <QHash>
@@ -255,7 +255,7 @@ private:
void cleanupFutures();
void iterateQrcFiles(ProjectExplorer::Project *project,
QrcResourceSelector resources,
- std::function<void(QrcParser::ConstPtr)> callback);
+ std::function<void(Utils::QrcParser::ConstPtr)> callback);
mutable QMutex m_mutex;
QmlJS::Snapshot m_validSnapshot;
@@ -272,7 +272,7 @@ private:
QTimer *m_asyncResetTimer = nullptr;
QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments;
QFuture<void> m_cppQmlTypesUpdater;
- QrcCache m_qrcCache;
+ Utils::QrcCache m_qrcCache;
QHash<QString, QString> m_qrcContents;
CppDataHash m_cppDataHash;
diff --git a/src/libs/qmljs/qmljsqrcparser.cpp b/src/libs/qmljs/qmljsqrcparser.cpp
deleted file mode 100644
index 0a68ebe2fb..0000000000
--- a/src/libs/qmljs/qmljsqrcparser.cpp
+++ /dev/null
@@ -1,556 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "qmljsqrcparser.h"
-#include "qmljsconstants.h"
-#include <QFile>
-#include <QDir>
-#include <QFileInfo>
-#include <QStringList>
-#include <QDomDocument>
-#include <QLocale>
-#include <QMutex>
-#include <QSet>
-#include <QMutexLocker>
-#include <QMultiHash>
-#include <QCoreApplication>
-#include <utils/qtcassert.h>
-
-namespace QmlJS {
-
-namespace Internal {
-/*!
- * \class QrcParser
- * \brief Parses one or more qrc files, and keeps their content cached
- *
- * A Qrc resource contains files read from the filesystem but organized in a possibly different way.
- *
- * To easily describe that with a simple structure we use a map from qrc paths to the paths in the
- * filesystem.
- * By using a map we can easily find all qrc paths that start with a given prefix, and thus loop
- * on a qrc directory.
- *
- * Qrc files also support languages, those are mapped to a prefix of the qrc path.
- * For example the french /image/bla.png (lang=fr) will have the path "fr/image/bla.png".
- * The empty language represent the default resource.
- * Languages are looked up using the locale uiLanguages() property
- *
- * For a single qrc a given path maps to a single file, but when one has multiple
- * (platform specific exclusive) qrc files, then multiple files match, so QStringList are used.
- *
- * Especially the collect* functions are thought as low level interface.
- */
-class QrcParserPrivate
-{
- Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcParser)
-public:
- typedef QMap<QString,QStringList> SMap;
- QrcParserPrivate(QrcParser *q);
- 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 = 0) const;
- bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const;
- void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
- const QLocale *locale = 0) const;
- void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
- const QLocale *locale = 0) const;
-
- QStringList errorMessages() const;
- QStringList languages() const;
-private:
- static QString fixPrefix(const QString &prefix);
- QStringList allUiLanguages(const QLocale *locale) const;
-
- SMap m_resources;
- SMap m_files;
- QStringList m_languages;
- QStringList m_errorMessages;
-};
-
-class QrcCachePrivate
-{
- Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcCachePrivate)
-public:
- QrcCachePrivate(QrcCache *q);
- QrcParser::Ptr addPath(const QString &path, const QString &contents);
- void removePath(const QString &path);
- QrcParser::Ptr updatePath(const QString &path, const QString &contents);
- QrcParser::Ptr parsedPath(const QString &path);
- void clear();
-private:
- QHash<QString, QPair<QrcParser::Ptr,int> > m_cache;
- QMutex m_mutex;
-};
-} // namespace Internal
-
-/*! \brief normalizes the path to a file in a qrc resource by dropping the "qrc:/" or ":" and
- * any extra slashes at the beginning
- */
-QString QrcParser::normalizedQrcFilePath(const QString &path) {
- QString normPath = path;
- int endPrefix = 0;
- if (path.startsWith(QLatin1String("qrc:/")))
- endPrefix = 4;
- else if (path.startsWith(QLatin1String(":/")))
- endPrefix = 1;
- if (endPrefix < path.size() && path.at(endPrefix) == QLatin1Char('/'))
- while (endPrefix + 1 < path.size() && path.at(endPrefix+1) == QLatin1Char('/'))
- ++endPrefix;
- normPath = path.right(path.size()-endPrefix);
- if (!normPath.startsWith(QLatin1Char('/')))
- normPath.insert(0, QLatin1Char('/'));
- return normPath;
-}
-
-/*! \brief normalizes the path to a directory in a qrc resource by dropping the "qrc:/" or ":" and
- * any extra slashes at the beginning, and ensuring it ends with a slash
- */
-QString QrcParser::normalizedQrcDirectoryPath(const QString &path) {
- QString normPath = normalizedQrcFilePath(path);
- if (!normPath.endsWith(QLatin1Char('/')))
- normPath.append(QLatin1Char('/'));
- return normPath;
-}
-
-QString QrcParser::qrcDirectoryPathForQrcFilePath(const QString &file)
-{
- return file.left(file.lastIndexOf(QLatin1Char('/')));
-}
-
-QrcParser::QrcParser()
-{
- d = new Internal::QrcParserPrivate(this);
-}
-
-QrcParser::~QrcParser()
-{
- delete d;
-}
-
-bool QrcParser::parseFile(const QString &path, const QString &contents)
-{
- return d->parseFile(path, contents);
-}
-
-/*! \brief returns fs path of the first (active) file at the given qrc path
- */
-QString QrcParser::firstFileAtPath(const QString &path, const QLocale &locale) const
-{
- return d->firstFileAtPath(path, locale);
-}
-
-/*! \brief adds al the fs paths for the given qrc path to *res
- * If locale is null all possible files are added, otherwise just the first match
- * using that locale.
- */
-void QrcParser::collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale) const
-{
- d->collectFilesAtPath(path, res, locale);
-}
-
-/*! \brief returns true if the given path is a non empty directory
- */
-bool QrcParser::hasDirAtPath(const QString &path, const QLocale *locale) const
-{
- return d->hasDirAtPath(path, locale);
-}
-
-/*! \brief adds the directory contents of the given qrc path to res
- *
- * adds the qrcFileName => fs paths associations contained in the given qrc path
- * to res. If addDirs is true directories are also added.
- * If locale is null all possible files are added, otherwise just the first match
- * using that locale.
- */
-void QrcParser::collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs,
- const QLocale *locale) const
-{
- d->collectFilesInPath(path, res, addDirs, locale);
-}
-
-void QrcParser::collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
- const QLocale *locale) const
-{
- d->collectResourceFilesForSourceFile(sourceFile, res, locale);
-}
-
-/*! \brief returns the errors found while parsing
- */
-QStringList QrcParser::errorMessages() const
-{
- return d->errorMessages();
-}
-
-/*! \brief returns all languages used in this qrc resource
- */
-QStringList QrcParser::languages() const
-{
- return d->languages();
-}
-
-/*! \brief if the contents are valid
- */
-bool QrcParser::isValid() const
-{
- return errorMessages().isEmpty();
-}
-
-QrcParser::Ptr QrcParser::parseQrcFile(const QString &path, const QString &contents)
-{
- Ptr res(new QrcParser);
- if (!path.isEmpty())
- res->parseFile(path, contents);
- return res;
-}
-
-// ----------------
-
-QrcCache::QrcCache()
-{
- d = new Internal::QrcCachePrivate(this);
-}
-
-QrcCache::~QrcCache()
-{
- delete d;
-}
-
-QrcParser::ConstPtr QrcCache::addPath(const QString &path, const QString &contents)
-{
- return d->addPath(path, contents);
-}
-
-void QrcCache::removePath(const QString &path)
-{
- d->removePath(path);
-}
-
-QrcParser::ConstPtr QrcCache::updatePath(const QString &path, const QString &contents)
-{
- return d->updatePath(path, contents);
-}
-
-QrcParser::ConstPtr QrcCache::parsedPath(const QString &path)
-{
- return d->parsedPath(path);
-}
-
-void QrcCache::clear()
-{
- d->clear();
-}
-
-// --------------------
-
-namespace Internal {
-
-QrcParserPrivate::QrcParserPrivate(QrcParser *)
-{ }
-
-bool QrcParserPrivate::parseFile(const QString &path, const QString &contents)
-{
- QDomDocument doc;
- QDir baseDir(QFileInfo(path).path());
-
- if (contents.isEmpty()) {
- // Regular file
- QFile file(path);
- if (!file.open(QIODevice::ReadOnly)) {
- m_errorMessages.append(file.errorString());
- return false;
- }
-
- QString error_msg;
- int error_line, error_col;
- if (!doc.setContent(&file, &error_msg, &error_line, &error_col)) {
- m_errorMessages.append(tr("XML error on line %1, col %2: %3")
- .arg(error_line).arg(error_col).arg(error_msg));
- return false;
- }
- } else {
- // Virtual file from qmake evaluator
- QString error_msg;
- int error_line, error_col;
- if (!doc.setContent(contents, &error_msg, &error_line, &error_col)) {
- m_errorMessages.append(tr("XML error on line %1, col %2: %3")
- .arg(error_line).arg(error_col).arg(error_msg));
- return false;
- }
- }
-
- QDomElement root = doc.firstChildElement(QLatin1String("RCC"));
- if (root.isNull()) {
- m_errorMessages.append(tr("The <RCC> root element is missing."));
- return false;
- }
-
- QDomElement relt = root.firstChildElement(QLatin1String("qresource"));
- for (; !relt.isNull(); relt = relt.nextSiblingElement(QLatin1String("qresource"))) {
-
- QString prefix = fixPrefix(relt.attribute(QLatin1String("prefix")));
- const QString language = relt.attribute(QLatin1String("lang"));
- if (!m_languages.contains(language))
- m_languages.append(language);
-
- QDomElement felt = relt.firstChildElement(QLatin1String("file"));
- for (; !felt.isNull(); felt = felt.nextSiblingElement(QLatin1String("file"))) {
- const QString fileName = felt.text();
- const QString alias = felt.attribute(QLatin1String("alias"));
- QString filePath = baseDir.absoluteFilePath(fileName);
- QString accessPath;
- if (!alias.isEmpty())
- accessPath = language + prefix + alias;
- else
- accessPath = language + prefix + fileName;
- QStringList &resources = m_resources[accessPath];
- if (!resources.contains(filePath))
- resources.append(filePath);
- QStringList &files = m_files[filePath];
- if (!files.contains(accessPath))
- files.append(accessPath);
- }
- }
- return true;
-}
-
-// path is assumed to be a normalized absolute path
-QString QrcParserPrivate::firstFileAtPath(const QString &path, const QLocale &locale) const
-{
- QTC_CHECK(path.startsWith(QLatin1Char('/')));
- QStringList langs = allUiLanguages(&locale);
- foreach (const QString &language, langs) {
- if (m_languages.contains(language)) {
- SMap::const_iterator res = m_resources.find(language + path);
- if (res != m_resources.end())
- return res.value().at(0);
- }
- }
- return QString();
-}
-
-void QrcParserPrivate::collectFilesAtPath(const QString &path, QStringList *files,
- const QLocale *locale) const
-{
- QTC_CHECK(path.startsWith(QLatin1Char('/')));
- QStringList langs = allUiLanguages(locale);
- foreach (const QString &language, langs) {
- if (m_languages.contains(language)) {
- SMap::const_iterator res = m_resources.find(language + path);
- if (res != m_resources.end())
- (*files) << res.value();
- }
- }
-}
-
-// path is expected to be normalized and start and end with a slash
-bool QrcParserPrivate::hasDirAtPath(const QString &path, const QLocale *locale) const
-{
- QTC_CHECK(path.startsWith(QLatin1Char('/')));
- QTC_CHECK(path.endsWith(QLatin1Char('/')));
- QStringList langs = allUiLanguages(locale);
- foreach (const QString &language, langs) {
- if (m_languages.contains(language)) {
- QString key = language + path;
- SMap::const_iterator res = m_resources.lowerBound(key);
- if (res != m_resources.end() && res.key().startsWith(key))
- return true;
- }
- }
- return false;
-}
-
-void QrcParserPrivate::collectFilesInPath(const QString &path, QMap<QString,QStringList> *contents,
- bool addDirs, const QLocale *locale) const
-{
- QTC_CHECK(path.startsWith(QLatin1Char('/')));
- QTC_CHECK(path.endsWith(QLatin1Char('/')));
- SMap::const_iterator end = m_resources.end();
- QStringList langs = allUiLanguages(locale);
- foreach (const QString &language, langs) {
- QString key = language + path;
- SMap::const_iterator res = m_resources.lowerBound(key);
- while (res != end && res.key().startsWith(key)) {
- const QString &actualKey = res.key();
- int endDir = actualKey.indexOf(QLatin1Char('/'), key.size());
- if (endDir == -1) {
- QString fileName = res.key().right(res.key().size()-key.size());
- QStringList &els = (*contents)[fileName];
- foreach (const QString &val, res.value())
- if (!els.contains(val))
- els << val;
- ++res;
- } else {
- QString dirName = res.key().mid(key.size(), endDir - key.size() + 1);
- if (addDirs)
- contents->insert(dirName, QStringList());
- QString key2 = key + dirName;
- do {
- ++res;
- } while (res != end && res.key().startsWith(key2));
- }
- }
- }
-}
-
-void QrcParserPrivate::collectResourceFilesForSourceFile(const QString &sourceFile,
- QStringList *results,
- const QLocale *locale) const
-{
- // TODO: use FileName from fileutils for file paths
-
- QStringList langs = allUiLanguages(locale);
- SMap::const_iterator file = m_files.find(sourceFile);
- if (file == m_files.end())
- return;
- foreach (const QString &resource, file.value()) {
- foreach (const QString &language, langs) {
- if (resource.startsWith(language) && !results->contains(resource))
- results->append(resource);
- }
- }
-}
-
-QStringList QrcParserPrivate::errorMessages() const
-{
- return m_errorMessages;
-}
-
-QStringList QrcParserPrivate::languages() const
-{
- return m_languages;
-}
-
-QString QrcParserPrivate::fixPrefix(const QString &prefix)
-{
- const QChar slash = QLatin1Char('/');
- QString result = QString(slash);
- for (int i = 0; i < prefix.size(); ++i) {
- const QChar c = prefix.at(i);
- if (c == slash && result.at(result.size() - 1) == slash)
- continue;
- result.append(c);
- }
-
- if (!result.endsWith(slash))
- result.append(slash);
-
- return result;
-}
-
-QStringList QrcParserPrivate::allUiLanguages(const QLocale *locale) const
-{
- if (!locale)
- return languages();
- QStringList langs = locale->uiLanguages();
- foreach (const QString &language, langs) { // qt4 support
- if (language.contains(QLatin1Char('_')) || language.contains(QLatin1Char('-'))) {
- QStringList splits = QString(language).replace(QLatin1Char('_'), QLatin1Char('-'))
- .split(QLatin1Char('-'));
- if (splits.size() > 1 && !langs.contains(splits.at(0)))
- langs.append(splits.at(0));
- }
- }
- if (!langs.contains(QString()))
- langs.append(QString());
- return langs;
-}
-
-// ----------------
-
-QrcCachePrivate::QrcCachePrivate(QrcCache *)
-{ }
-
-QrcParser::Ptr QrcCachePrivate::addPath(const QString &path, const QString &contents)
-{
- QPair<QrcParser::Ptr,int> currentValue;
- {
- QMutexLocker l(&m_mutex);
- currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
- currentValue.second += 1;
- if (currentValue.second > 1) {
- m_cache.insert(path, currentValue);
- return currentValue.first;
- }
- }
- QrcParser::Ptr newParser = QrcParser::parseQrcFile(path, contents);
- if (!newParser->isValid())
- qCWarning(qmljsLog) << "adding invalid qrc " << path << " to the cache:" << newParser->errorMessages();
- {
- QMutexLocker l(&m_mutex);
- QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
- if (currentValue.first.isNull())
- currentValue.first = newParser;
- currentValue.second += 1;
- m_cache.insert(path, currentValue);
- return currentValue.first;
- }
-}
-
-void QrcCachePrivate::removePath(const QString &path)
-{
- QPair<QrcParser::Ptr,int> currentValue;
- {
- QMutexLocker l(&m_mutex);
- currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
- if (currentValue.second == 1) {
- m_cache.remove(path);
- } else if (currentValue.second > 1) {
- currentValue.second -= 1;
- m_cache.insert(path, currentValue);
- } else {
- QTC_CHECK(!m_cache.contains(path));
- }
- }
-}
-
-QrcParser::Ptr QrcCachePrivate::updatePath(const QString &path, const QString &contents)
-{
- QrcParser::Ptr newParser = QrcParser::parseQrcFile(path, contents);
- {
- QMutexLocker l(&m_mutex);
- QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
- currentValue.first = newParser;
- if (currentValue.second == 0)
- currentValue.second = 1; // add qrc files that are not in the resources of a project
- m_cache.insert(path, currentValue);
- return currentValue.first;
- }
-}
-
-QrcParser::Ptr QrcCachePrivate::parsedPath(const QString &path)
-{
- QMutexLocker l(&m_mutex);
- QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
- return currentValue.first;
-}
-
-void QrcCachePrivate::clear()
-{
- QMutexLocker l(&m_mutex);
- m_cache.clear();
-}
-
-} // namespace Internal
-} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsqrcparser.h b/src/libs/qmljs/qmljsqrcparser.h
deleted file mode 100644
index 6973fa6d39..0000000000
--- a/src/libs/qmljs/qmljsqrcparser.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 "qmljs_global.h"
-
-#include <QMap>
-#include <QSharedPointer>
-#include <QString>
-#include <QStringList>
-
-QT_FORWARD_DECLARE_CLASS(QLocale)
-
-namespace QmlJS {
-
-namespace Internal {
-class QrcParserPrivate;
-class QrcCachePrivate;
-}
-
-class QMLJS_EXPORT QrcParser
-{
-public:
- 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 = 0) const;
- bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const;
- void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
- const QLocale *locale = 0) const;
- void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *results,
- const QLocale *locale = 0) const;
-
- QStringList errorMessages() const;
- QStringList languages() const;
- bool isValid() const;
-
- static Ptr parseQrcFile(const QString &path, const QString &contents);
- static QString normalizedQrcFilePath(const QString &path);
- static QString normalizedQrcDirectoryPath(const QString &path);
- static QString qrcDirectoryPathForQrcFilePath(const QString &file);
-private:
- QrcParser();
- QrcParser(const QrcParser &);
- Internal::QrcParserPrivate *d;
-};
-
-class QMLJS_EXPORT QrcCache
-{
-public:
- QrcCache();
- ~QrcCache();
- QrcParser::ConstPtr addPath(const QString &path, const QString &contents);
- void removePath(const QString &path);
- QrcParser::ConstPtr updatePath(const QString &path, const QString &contents);
- QrcParser::ConstPtr parsedPath(const QString &path);
- void clear();
-private:
- Internal::QrcCachePrivate *d;
-};
-}
diff --git a/src/libs/qmljs/qmljsreformatter.cpp b/src/libs/qmljs/qmljsreformatter.cpp
index e95ff2f339..d60d6179f3 100644
--- a/src/libs/qmljs/qmljsreformatter.cpp
+++ b/src/libs/qmljs/qmljsreformatter.cpp
@@ -96,6 +96,7 @@ class Rewriter : protected Visitor
int _lastNewlineOffset = -1;
bool _hadEmptyLine = false;
int _binaryExpDepth = 0;
+ bool _hasOpenComment = false;
public:
Rewriter(Document::Ptr doc)
@@ -201,6 +202,9 @@ protected:
void out(const QString &str, const SourceLocation &lastLoc = SourceLocation())
{
+ if (_hasOpenComment) {
+ newLine();
+ }
if (lastLoc.isValid()) {
QList<SourceLocation> comments = _doc->engine()->comments();
for (; _nextComment < comments.size(); ++_nextComment) {
@@ -371,6 +375,7 @@ protected:
{
// if preceded by a newline, it's an empty line!
_hadEmptyLine = _line.trimmed().isEmpty();
+ _hasOpenComment = false;
// if the preceding line wasn't empty, reindent etc.
if (!_hadEmptyLine) {
@@ -524,6 +529,7 @@ protected:
out(" ");
out(toString(nextCommentLoc));
+ _hasOpenComment = true;
}
}
}
@@ -531,6 +537,39 @@ protected:
bool visit(UiPragma *ast) override
{
out("pragma ", ast->pragmaToken);
+ out(ast->name.toString());
+ newLine();
+ return false;
+ }
+
+ bool visit(UiEnumDeclaration *ast) override
+ {
+ out(ast->enumToken);
+ out(" ");
+ out(ast->name.toString());
+ out(" ");
+ out("{"); // TODO: out(ast->lbraceToken);
+ newLine();
+
+ accept(ast->members);
+
+ out(ast->rbraceToken);
+ return false;
+ }
+
+ bool visit(UiEnumMemberList *list) override
+ {
+ for (UiEnumMemberList *it = list; it; it = it->next) {
+ out(it->memberToken);
+ if (it->valueToken.isValid()) {
+ out(" = ");
+ out(it->valueToken);
+ }
+ if (it->next) {
+ out(",");
+ }
+ newLine();
+ }
return false;
}
@@ -563,9 +602,10 @@ protected:
bool visit(UiObjectInitializer *ast) override
{
out(ast->lbraceToken);
- if (ast->members)
+ if (ast->members) {
lnAcceptIndented(ast->members);
- newLine();
+ newLine();
+ }
out(ast->rbraceToken);
return false;
}
@@ -593,10 +633,10 @@ protected:
if (!ast->typeModifier.isNull()) {
out(ast->typeModifierToken);
out("<");
- out(ast->typeToken);
+ accept(ast->memberType);
out(">");
} else {
- out(ast->typeToken);
+ accept(ast->memberType);
}
out(" ");
if (ast->statement) {
@@ -677,8 +717,10 @@ protected:
bool visit(ObjectPattern *ast) override
{
out(ast->lbraceToken);
- lnAcceptIndented(ast->properties);
- newLine();
+ if (ast->properties) {
+ lnAcceptIndented(ast->properties);
+ newLine();
+ }
out(ast->rbraceToken);
return false;
}
@@ -914,14 +956,23 @@ protected:
bool visit(VariableStatement *ast) override
{
- out("var ", ast->declarationKindToken);
+ out(ast->declarationKindToken);
+ out(" ");
accept(ast->declarations);
return false;
}
bool visit(PatternElement *ast) override
{
-
+ if (ast->isForDeclaration) {
+ if (ast->scope == VariableScope::Var) {
+ out("var ");
+ } else if (ast->scope == VariableScope::Let) {
+ out("let ");
+ } else if (ast->scope == VariableScope::Const) {
+ out("const ");
+ }
+ }
out(ast->identifierToken);
if (ast->initializer) {
if (ast->isVariableDeclaration())
@@ -985,7 +1036,12 @@ protected:
out(ast->forToken);
out(" ");
out(ast->lparenToken);
- accept(ast->initialiser);
+ if (ast->initialiser) {
+ accept(ast->initialiser);
+ } else if (ast->declarations) {
+ out("var ");
+ accept(ast->declarations);
+ }
out("; ", ast->firstSemicolonToken);
accept(ast->condition);
out("; ", ast->secondSemicolonToken);
@@ -1273,6 +1329,8 @@ protected:
{
for (FormalParameterList *it = ast; it; it = it->next) {
out(it->element->bindingIdentifier.toString()); // TODO
+ if (it->next)
+ out(", ");
}
return false;
}
diff --git a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp
index c8f03ea8d9..8e1deea715 100644
--- a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp
+++ b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp
@@ -145,8 +145,7 @@ void DumpSender::sendDumpAndQuit()
connect(reply, &QNetworkReply::uploadProgress, this, &DumpSender::uploadProgress);
connect(reply, &QNetworkReply::finished, QCoreApplication::instance(), &QCoreApplication::quit);
- connect(reply,
- static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
+ connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
QCoreApplication::instance(), &QCoreApplication::quit);
}
diff --git a/src/libs/qtcreatorcdbext/CMakeLists.txt b/src/libs/qtcreatorcdbext/CMakeLists.txt
new file mode 100644
index 0000000000..15ab799083
--- /dev/null
+++ b/src/libs/qtcreatorcdbext/CMakeLists.txt
@@ -0,0 +1,46 @@
+#todo
+# - handle if there is no debug python lib python35_d
+# - needs to be tested
+
+if (MINGW)
+ message(STATUS "MinGW detected. Removing qtcreatorcdbext from build.")
+ return()
+endif()
+
+include(CheckIncludeFile)
+check_include_file(wdbgexts.h HAVE_WDBGEXTS_H)
+if (NOT HAVE_WDBGEXTS_H)
+ message(WARNING "wdbgexts.h not found. Removing qtcreatorcdbext from build.")
+ return()
+endif()
+
+find_package(PythonLibs 3.5)
+if (NOT ${PYTHONLIBS_FOUND})
+ message(WARNING "PythonLibs 3.5 not found. Removing qtcreatorcdbext from build.")
+ return()
+endif()
+
+add_qtc_library(qtcreatorcdbext
+ DEPENDS ${PYTHON_LIBRARIES}
+ INCLUDES ${PYTHON_INCLUDE_DIR}
+ DEFINES WITH_PYTHON=1
+ SOURCES
+ common.cpp common.h
+ containers.cpp containers.h
+ eventcallback.cpp eventcallback.h
+ extensioncontext.cpp extensioncontext.h
+ gdbmihelpers.cpp gdbmihelpers.h
+ iinterfacepointer.h
+ knowntype.h
+ outputcallback.cpp outputcallback.h
+ pycdbextmodule.cpp pycdbextmodule.h
+ pyfield.cpp pyfield.h
+ pystdoutredirect.cpp pystdoutredirect.h
+ pytype.cpp pytype.h
+ pyvalue.cpp pyvalue.h
+ qtcreatorcdbextension.cpp
+ stringutils.cpp stringutils.h
+ symbolgroup.cpp symbolgroup.h
+ symbolgroupnode.cpp symbolgroupnode.h
+ symbolgroupvalue.cpp symbolgroupvalue.h
+)
diff --git a/src/libs/qtcreatorcdbext/common.h b/src/libs/qtcreatorcdbext/common.h
index b538313b3f..fd76c1be7e 100644
--- a/src/libs/qtcreatorcdbext/common.h
+++ b/src/libs/qtcreatorcdbext/common.h
@@ -34,9 +34,16 @@
#include <windows.h>
#define KDEXT_64BIT
-#pragma warning( disable : 4838 )
-#include <wdbgexts.h>
-#pragma warning( default : 4838 )
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wc++11-narrowing"
+# include <wdbgexts.h>
+# pragma clang diagnostic pop
+#else
+# pragma warning( disable : 4838 )
+# include <wdbgexts.h>
+# pragma warning( default : 4838 )
+#endif // __clang__
#include <dbgeng.h>
typedef IDebugControl3 CIDebugControl;
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro
index 545656dc24..774e889b2a 100644
--- a/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro
@@ -100,7 +100,7 @@ HEADERS += extensioncontext.h \
symbolgroupnode.h
isEmpty(PYTHON_INSTALL_DIR):PYTHON_INSTALL_DIR=$$(PYTHON_INSTALL_DIR)
-exists($$PYTHON_INSTALL_DIR) {
+!isEmpty(PYTHON_INSTALL_DIR):exists($$PYTHON_INSTALL_DIR) {
DEFINES += WITH_PYTHON=1
INCLUDEPATH += $$PYTHON_INSTALL_DIR/include
diff --git a/src/libs/sqlite/CMakeLists.txt b/src/libs/sqlite/CMakeLists.txt
new file mode 100644
index 0000000000..22ba4bac34
--- /dev/null
+++ b/src/libs/sqlite/CMakeLists.txt
@@ -0,0 +1,27 @@
+add_qtc_library(Sqlite
+ DEFINES
+ SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS
+ SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA
+ BUILD_SQLITE_LIBRARY
+ DEPENDS Qt5::Core
+ PUBLIC_INCLUDES "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/../3rdparty/sqlite"
+ SOURCES
+ ../3rdparty/sqlite/sqlite3.c
+ createtablesqlstatementbuilder.cpp createtablesqlstatementbuilder.h
+ sqlitebasestatement.cpp sqlitebasestatement.h
+ sqlitecolumn.h
+ sqlitedatabase.cpp sqlitedatabase.h
+ sqlitedatabasebackend.cpp sqlitedatabasebackend.h
+ sqliteexception.cpp sqliteexception.h
+ sqliteglobal.cpp sqliteglobal.h
+ sqliteindex.h
+ sqlitereadstatement.cpp sqlitereadstatement.h
+ sqlitereadwritestatement.cpp sqlitereadwritestatement.h
+ sqlitetable.h
+ sqlitetransaction.h
+ sqlitewritestatement.cpp sqlitewritestatement.h
+ sqlstatementbuilder.cpp sqlstatementbuilder.h
+ sqlstatementbuilderexception.h
+ utf8string.cpp utf8string.h
+ utf8stringvector.cpp utf8stringvector.h
+)
diff --git a/src/libs/sqlite/README.md b/src/libs/sqlite/README.md
new file mode 100644
index 0000000000..88944dcd42
--- /dev/null
+++ b/src/libs/sqlite/README.md
@@ -0,0 +1,13 @@
+# SQLite
+
+Minimum version is the same as the sqlite version in the source tree.
+
+We compile SQLite with the flowing settings:
+* SQLITE_THREADSAFE=2
+* SQLITE_ENABLE_FTS4
+* SQLITE_ENABLE_FTS3_PARENTHESIS
+* SQLITE_ENABLE_UNLOCK_NOTIFY
+* SQLITE_ENABLE_COLUMN_METADATA
+* SQLITE_ENABLE_JSON1
+
+Be prepared that we demand more functionality from SQLite in the future.
diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri
index fb46370052..4d7f906a19 100644
--- a/src/libs/sqlite/sqlite-lib.pri
+++ b/src/libs/sqlite/sqlite-lib.pri
@@ -19,16 +19,14 @@ SOURCES += \
$$PWD/sqlitereadwritestatement.cpp \
$$PWD/sqlitewritestatement.cpp \
$$PWD/sqlstatementbuilder.cpp \
- $$PWD/sqlstatementbuilderexception.cpp \
$$PWD/utf8string.cpp \
$$PWD/utf8stringvector.cpp \
$$PWD/sqlitedatabase.cpp \
- $$PWD/sqlitetable.cpp \
- $$PWD/sqlitecolumn.cpp \
$$PWD/sqlitebasestatement.cpp
HEADERS += \
$$PWD/createtablesqlstatementbuilder.h \
$$PWD/sqlitedatabasebackend.h \
+ $$PWD/sqlitedatabaseinterface.h \
$$PWD/sqliteexception.h \
$$PWD/sqliteglobal.h \
$$PWD/sqlitereadstatement.h \
@@ -48,4 +46,6 @@ HEADERS += \
DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS \
SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA SQLITE_ENABLE_JSON1
+OTHER_FILES += README.md
+
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
diff --git a/src/libs/sqlite/sqlite-source.pri b/src/libs/sqlite/sqlite-source.pri
index b297e31da2..5729293901 100644
--- a/src/libs/sqlite/sqlite-source.pri
+++ b/src/libs/sqlite/sqlite-source.pri
@@ -17,12 +17,9 @@ SOURCES += \
sqliteworkerthread.cpp \
sqlitewritestatement.cpp \
sqlstatementbuilder.cpp \
- sqlstatementbuilderexception.cpp \
utf8string.cpp \
utf8stringvector.cpp \
sqlitedatabase.cpp \
- sqlitetable.cpp \
- sqlitecolumn.cpp \
tablewriteworker.cpp \
tablewriteworkerproxy.cpp
HEADERS += \
diff --git a/src/libs/sqlite/sqlitecolumn.cpp b/src/libs/sqlite/sqlitecolumn.cpp
deleted file mode 100644
index 201f1fbcb9..0000000000
--- a/src/libs/sqlite/sqlitecolumn.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 "sqlitecolumn.h"
-
-namespace Sqlite {
-
-
-} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h
index d0eae28f79..2c35a293c2 100644
--- a/src/libs/sqlite/sqlitedatabase.h
+++ b/src/libs/sqlite/sqlitedatabase.h
@@ -26,6 +26,7 @@
#pragma once
#include "sqlitedatabasebackend.h"
+#include "sqlitedatabaseinterface.h"
#include "sqliteglobal.h"
#include "sqlitetable.h"
#include "sqlitetransaction.h"
@@ -43,7 +44,7 @@ using namespace std::chrono_literals;
class ReadStatement;
class WriteStatement;
-class SQLITE_EXPORT Database final : public TransactionInterface
+class SQLITE_EXPORT Database final : public TransactionInterface, public DatabaseInterface
{
template <typename Database>
friend class Statement;
@@ -105,19 +106,18 @@ public:
return m_databaseBackend.changesCount();
}
- int totalChangesCount()
- {
- return m_databaseBackend.totalChangesCount();
- }
+ int totalChangesCount() { return m_databaseBackend.totalChangesCount(); }
+
+ void walCheckpointFull() override { m_databaseBackend.walCheckpointFull(); }
private:
- void deferredBegin();
- void immediateBegin();
- void exclusiveBegin();
- void commit();
- void rollback();
- void lock();
- void unlock();
+ void deferredBegin() override;
+ void immediateBegin() override;
+ void exclusiveBegin() override;
+ void commit() override;
+ void rollback() override;
+ void lock() override;
+ void unlock() override;
void initializeTables();
void registerTransactionStatements();
diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp
index a42564aca5..bf9dfab6fc 100644
--- a/src/libs/sqlite/sqlitedatabasebackend.cpp
+++ b/src/libs/sqlite/sqlitedatabasebackend.cpp
@@ -406,6 +406,27 @@ void DatabaseBackend::setBusyTimeout(std::chrono::milliseconds timeout)
sqlite3_busy_timeout(m_databaseHandle, int(timeout.count()));
}
+void DatabaseBackend::walCheckpointFull()
+{
+ int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle,
+ nullptr,
+ SQLITE_CHECKPOINT_TRUNCATE,
+ nullptr,
+ nullptr);
+
+ switch (resultCode) {
+ case SQLITE_OK:
+ break;
+ case SQLITE_BUSY:
+ throw DatabaseIsBusy("DatabaseBackend::walCheckpointFull: Operation could not concluded "
+ "because database is busy!");
+ case SQLITE_ERROR:
+ throwException("DatabaseBackend::walCheckpointFull: Error occurred!");
+ case SQLITE_MISUSE:
+ throwExceptionStatic("DatabaseBackend::walCheckpointFull: Misuse of database!");
+ }
+}
+
void DatabaseBackend::throwExceptionStatic(const char *whatHasHappens)
{
throw Exception(whatHasHappens);
diff --git a/src/libs/sqlite/sqlitedatabasebackend.h b/src/libs/sqlite/sqlitedatabasebackend.h
index 2de55672aa..7f3973f878 100644
--- a/src/libs/sqlite/sqlitedatabasebackend.h
+++ b/src/libs/sqlite/sqlitedatabasebackend.h
@@ -85,6 +85,8 @@ public:
void setBusyTimeout(std::chrono::milliseconds timeout);
+ void walCheckpointFull();
+
protected:
bool databaseIsOpen() const;
diff --git a/src/libs/sqlite/sqlitedatabaseinterface.h b/src/libs/sqlite/sqlitedatabaseinterface.h
new file mode 100644
index 0000000000..61ea3ac928
--- /dev/null
+++ b/src/libs/sqlite/sqlitedatabaseinterface.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** 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
+
+namespace Sqlite {
+class DatabaseInterface
+{
+public:
+ virtual void walCheckpointFull() = 0;
+
+protected:
+ ~DatabaseInterface() = default;
+};
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitetable.cpp b/src/libs/sqlite/sqlitetable.cpp
deleted file mode 100644
index 99b0e95938..0000000000
--- a/src/libs/sqlite/sqlitetable.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 "sqlitetable.h"
-
-namespace Sqlite {
-
-
-
-} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlstatementbuilderexception.cpp b/src/libs/sqlite/sqlstatementbuilderexception.cpp
deleted file mode 100644
index 82f5b4f792..0000000000
--- a/src/libs/sqlite/sqlstatementbuilderexception.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 "sqlstatementbuilderexception.h"
-
-namespace Sqlite {
-
-
-
-
-
-} // namespace Sqlite
diff --git a/src/libs/ssh/CMakeLists.txt b/src/libs/ssh/CMakeLists.txt
new file mode 100644
index 0000000000..6f5d1cb764
--- /dev/null
+++ b/src/libs/ssh/CMakeLists.txt
@@ -0,0 +1,22 @@
+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/sftpfilesystemmodel.cpp b/src/libs/ssh/sftpfilesystemmodel.cpp
index 555796b812..0e9eb48e5e 100644
--- a/src/libs/ssh/sftpfilesystemmodel.cpp
+++ b/src/libs/ssh/sftpfilesystemmodel.cpp
@@ -30,6 +30,7 @@
#include "sshconnectionmanager.h"
#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
#include <QFileInfo>
#include <QHash>
@@ -167,9 +168,9 @@ QVariant SftpFileSystemModel::data(const QModelIndex &index, int role) const
switch (node->fileInfo.type) {
case FileTypeRegular:
case FileTypeOther:
- return QIcon(":/ssh/images/unknownfile.png");
+ return Utils::Icons::UNKNOWN_FILE.icon();
case FileTypeDirectory:
- return QIcon(":/ssh/images/dir.png");
+ return Utils::Icons::DIR.icon();
case FileTypeUnknown:
return QIcon(":/ssh/images/help.png"); // Shows a question mark.
}
diff --git a/src/libs/ssh/sftpsession.cpp b/src/libs/ssh/sftpsession.cpp
index 0119bea266..528475ed2b 100644
--- a/src/libs/ssh/sftpsession.cpp
+++ b/src/libs/ssh/sftpsession.cpp
@@ -83,6 +83,8 @@ struct SftpSession::SftpSessionPrivate
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();
@@ -111,6 +113,7 @@ SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionP
{
d->connectionArgs = connectionArgs;
connect(&d->sftpProc, &QProcess::started, [this] {
+ qCDebug(sshLog) << "sftp process started";
d->sftpProc.write("\n"); // Force initial prompt.
});
connect(&d->sftpProc, &QProcess::errorOccurred, [this](QProcess::ProcessError error) {
@@ -120,6 +123,8 @@ SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionP
}
});
connect(&d->sftpProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this] {
+ qCDebug(sshLog) << "sftp process finished";
+
d->state = State::Inactive;
if (d->sftpProc.exitStatus() != QProcess::NormalExit) {
emit done(tr("sftp crashed."));
@@ -138,7 +143,7 @@ void SftpSession::doStart()
{
if (d->state != State::Starting)
return;
- const FileName sftpBinary = SshSettings::sftpFilePath();
+ 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.")
@@ -269,6 +274,8 @@ void SftpSession::start()
void SftpSession::quit()
{
+ qCDebug(sshLog) << "quitting sftp session, current state is" << int(state());
+
switch (state()) {
case State::Starting:
case State::Closing:
diff --git a/src/libs/ssh/sftptransfer.cpp b/src/libs/ssh/sftptransfer.cpp
index 887d8f36fa..52b821bc39 100644
--- a/src/libs/ssh/sftptransfer.cpp
+++ b/src/libs/ssh/sftptransfer.cpp
@@ -132,7 +132,7 @@ SftpTransfer::SftpTransfer(const FilesToTransfer &files, Internal::FileTransferT
void SftpTransfer::doStart()
{
- const FileName sftpBinary = SshSettings::sftpFilePath();
+ const FilePath sftpBinary = SshSettings::sftpFilePath();
if (!sftpBinary.exists()) {
emitError(tr("sftp binary \"%1\" does not exist.").arg(sftpBinary.toUserOutput()));
return;
diff --git a/src/libs/ssh/ssh.qrc b/src/libs/ssh/ssh.qrc
index 4b0c6a8c51..9801217093 100644
--- a/src/libs/ssh/ssh.qrc
+++ b/src/libs/ssh/ssh.qrc
@@ -1,7 +1,5 @@
<RCC>
<qresource prefix="/ssh">
- <file>images/dir.png</file>
<file>images/help.png</file>
- <file>images/unknownfile.png</file>
</qresource>
</RCC>
diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp
index 91d8446db9..b368ccc8ef 100644
--- a/src/libs/ssh/sshconnection.cpp
+++ b/src/libs/ssh/sshconnection.cpp
@@ -231,7 +231,7 @@ void SshConnection::disconnectFromHost()
case Connecting:
case Connected:
if (!d->sharingEnabled) {
- emitDisconnected();
+ QTimer::singleShot(0, this, &SshConnection::emitDisconnected);
return;
}
d->state = Disconnecting;
@@ -309,7 +309,7 @@ SshConnection::~SshConnection()
delete d;
}
-SshRemoteProcessPtr SshConnection::createRemoteProcess(const QByteArray &command)
+SshRemoteProcessPtr SshConnection::createRemoteProcess(const QString &command)
{
QTC_ASSERT(state() == Connected, return SshRemoteProcessPtr());
return SshRemoteProcessPtr(new SshRemoteProcess(command, d->connectionArgs()));
@@ -317,7 +317,7 @@ SshRemoteProcessPtr SshConnection::createRemoteProcess(const QByteArray &command
SshRemoteProcessPtr SshConnection::createRemoteShell()
{
- return createRemoteProcess(QByteArray());
+ return createRemoteProcess({});
}
SftpTransferPtr SshConnection::createUpload(const FilesToTransfer &files,
@@ -342,7 +342,7 @@ void SshConnection::doConnectToHost()
{
if (d->state != Connecting)
return;
- const FileName sshBinary = SshSettings::sshFilePath();
+ const FilePath sshBinary = SshSettings::sshFilePath();
if (!sshBinary.exists()) {
emitError(tr("Cannot establish SSH connection: ssh binary \"%1\" does not exist.")
.arg(sshBinary.toUserOutput()));
diff --git a/src/libs/ssh/sshconnection.h b/src/libs/ssh/sshconnection.h
index 1b5775682e..89af4d71d9 100644
--- a/src/libs/ssh/sshconnection.h
+++ b/src/libs/ssh/sshconnection.h
@@ -111,7 +111,7 @@ public:
bool sharingEnabled() const;
~SshConnection();
- SshRemoteProcessPtr createRemoteProcess(const QByteArray &command);
+ SshRemoteProcessPtr createRemoteProcess(const QString &command);
SshRemoteProcessPtr createRemoteShell();
SftpTransferPtr createUpload(const FilesToTransfer &files,
FileTransferErrorHandling errorHandlingMode);
diff --git a/src/libs/ssh/sshremoteprocess.cpp b/src/libs/ssh/sshremoteprocess.cpp
index 4bd09b37e1..635f23e150 100644
--- a/src/libs/ssh/sshremoteprocess.cpp
+++ b/src/libs/ssh/sshremoteprocess.cpp
@@ -54,21 +54,19 @@ using namespace Internal;
struct SshRemoteProcess::SshRemoteProcessPrivate
{
- QByteArray remoteCommand;
+ QString remoteCommand;
QStringList connectionArgs;
QString displayName;
bool useTerminal = false;
};
-SshRemoteProcess::SshRemoteProcess(const QByteArray &command, const QStringList &connectionArgs)
+SshRemoteProcess::SshRemoteProcess(const QString &command, const QStringList &connectionArgs)
: d(new SshRemoteProcessPrivate)
{
d->remoteCommand = command;
d->connectionArgs = connectionArgs;
- connect(this,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
- [this] {
+ connect(this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this] {
QString error;
if (exitStatus() == QProcess::CrashExit)
error = tr("The ssh process crashed: %1").arg(errorString());
@@ -129,7 +127,7 @@ QStringList SshRemoteProcess::fullLocalCommandLine() const
if (!d->displayName.isEmpty())
args.prepend("-X");
if (!d->remoteCommand.isEmpty())
- args << QLatin1String(d->remoteCommand);
+ args << d->remoteCommand;
args.prepend(SshSettings::sshFilePath().toString());
return args;
}
diff --git a/src/libs/ssh/sshremoteprocess.h b/src/libs/ssh/sshremoteprocess.h
index 82dd1b9dcb..02ab3546fd 100644
--- a/src/libs/ssh/sshremoteprocess.h
+++ b/src/libs/ssh/sshremoteprocess.h
@@ -30,10 +30,6 @@
#include <QStringList>
-QT_BEGIN_NAMESPACE
-class QByteArray;
-QT_END_NAMESPACE
-
namespace QSsh {
class SshConnection;
@@ -56,7 +52,7 @@ signals:
void done(const QString &error);
private:
- SshRemoteProcess(const QByteArray &command, const QStringList &connectionArgs);
+ SshRemoteProcess(const QString &command, const QStringList &connectionArgs);
void doStart();
struct SshRemoteProcessPrivate;
diff --git a/src/libs/ssh/sshremoteprocessrunner.cpp b/src/libs/ssh/sshremoteprocessrunner.cpp
index 11b75f6a25..7a062e6ab8 100644
--- a/src/libs/ssh/sshremoteprocessrunner.cpp
+++ b/src/libs/ssh/sshremoteprocessrunner.cpp
@@ -50,7 +50,7 @@ public:
SshRemoteProcessPtr m_process;
SshConnection *m_connection;
bool m_runInTerminal;
- QByteArray m_command;
+ QString m_command;
QString m_lastConnectionErrorString;
QProcess::ExitStatus m_exitStatus;
QByteArray m_stdout;
@@ -76,8 +76,7 @@ SshRemoteProcessRunner::~SshRemoteProcessRunner()
delete d;
}
-void SshRemoteProcessRunner::run(const QByteArray &command,
- const SshConnectionParameters &sshParams)
+void SshRemoteProcessRunner::run(const QString &command, const SshConnectionParameters &sshParams)
{
QTC_ASSERT(d->m_state == Inactive, return);
@@ -85,14 +84,14 @@ void SshRemoteProcessRunner::run(const QByteArray &command,
runInternal(command, sshParams);
}
-void SshRemoteProcessRunner::runInTerminal(const QByteArray &command,
+void SshRemoteProcessRunner::runInTerminal(const QString &command,
const SshConnectionParameters &sshParams)
{
d->m_runInTerminal = true;
runInternal(command, sshParams);
}
-void SshRemoteProcessRunner::runInternal(const QByteArray &command,
+void SshRemoteProcessRunner::runInternal(const QString &command,
const SshConnectionParameters &sshParams)
{
setState(Connecting);
@@ -197,7 +196,7 @@ void SshRemoteProcessRunner::setState(int newState)
}
}
-QByteArray SshRemoteProcessRunner::command() const { return d->m_command; }
+QString SshRemoteProcessRunner::command() const { return d->m_command; }
QString SshRemoteProcessRunner::lastConnectionErrorString() const {
return d->m_lastConnectionErrorString;
}
diff --git a/src/libs/ssh/sshremoteprocessrunner.h b/src/libs/ssh/sshremoteprocessrunner.h
index 029fb6bb3d..082f30ed57 100644
--- a/src/libs/ssh/sshremoteprocessrunner.h
+++ b/src/libs/ssh/sshremoteprocessrunner.h
@@ -39,9 +39,9 @@ public:
SshRemoteProcessRunner(QObject *parent = 0);
~SshRemoteProcessRunner();
- void run(const QByteArray &command, const SshConnectionParameters &sshParams);
- void runInTerminal(const QByteArray &command, const SshConnectionParameters &sshParams);
- QByteArray command() const;
+ void run(const QString &command, const SshConnectionParameters &sshParams);
+ void runInTerminal(const QString &command, const SshConnectionParameters &sshParams);
+ QString command() const;
QString lastConnectionErrorString() const;
@@ -69,7 +69,7 @@ private:
void handleProcessFinished(const QString &error);
void handleStdout();
void handleStderr();
- void runInternal(const QByteArray &command, const QSsh::SshConnectionParameters &sshParams);
+ void runInternal(const QString &command, const QSsh::SshConnectionParameters &sshParams);
void setState(int newState);
Internal::SshRemoteProcessRunnerPrivate * const d;
diff --git a/src/libs/ssh/sshsettings.cpp b/src/libs/ssh/sshsettings.cpp
index 12f17bbade..0086d05376 100644
--- a/src/libs/ssh/sshsettings.cpp
+++ b/src/libs/ssh/sshsettings.cpp
@@ -39,11 +39,11 @@ struct SshSettings
{
bool useConnectionSharing = !HostOsInfo::isWindowsHost();
int connectionSharingTimeOutInMinutes = 10;
- FileName sshFilePath;
- FileName sftpFilePath;
- FileName askpassFilePath;
- FileName keygenFilePath;
- QSsh::SshSettings::SearchPathRetriever searchPathRetriever = [] { return FileNameList(); };
+ FilePath sshFilePath;
+ FilePath sftpFilePath;
+ FilePath askpassFilePath;
+ FilePath keygenFilePath;
+ QSsh::SshSettings::SearchPathRetriever searchPathRetriever = [] { return FilePathList(); };
};
} // namespace Internal
@@ -79,11 +79,11 @@ void SshSettings::loadSettings(QSettings *settings)
value = settings->value(connectionSharingTimeoutKey());
if (value.isValid())
sshSettings->connectionSharingTimeOutInMinutes = value.toInt();
- sshSettings->sshFilePath = FileName::fromString(settings->value(sshFilePathKey()).toString());
- sshSettings->sftpFilePath = FileName::fromString(settings->value(sftpFilePathKey()).toString());
- sshSettings->askpassFilePath = FileName::fromString(
+ 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 = FileName::fromString(
+ sshSettings->keygenFilePath = FilePath::fromString(
settings->value(keygenFilePathKey()).toString());
}
@@ -114,51 +114,51 @@ int SshSettings::connectionSharingTimeout()
return sshSettings->connectionSharingTimeOutInMinutes;
}
-static FileName filePathValue(const FileName &value, const QStringList &candidateFileNames)
+static FilePath filePathValue(const FilePath &value, const QStringList &candidateFileNames)
{
if (!value.isEmpty())
return value;
- const QList<FileName> additionalSearchPaths = sshSettings->searchPathRetriever();
+ const QList<FilePath> additionalSearchPaths = sshSettings->searchPathRetriever();
for (const QString &candidate : candidateFileNames) {
- const FileName filePath = Environment::systemEnvironment()
+ const FilePath filePath = Environment::systemEnvironment()
.searchInPath(candidate, additionalSearchPaths);
if (!filePath.isEmpty())
return filePath;
}
- return FileName();
+ return FilePath();
}
-static FileName filePathValue(const FileName &value, const QString &candidateFileName)
+static FilePath filePathValue(const FilePath &value, const QString &candidateFileName)
{
return filePathValue(value, QStringList(candidateFileName));
}
-void SshSettings::setSshFilePath(const FileName &ssh) { sshSettings->sshFilePath = ssh; }
-FileName SshSettings::sshFilePath() { return filePathValue(sshSettings->sshFilePath, "ssh"); }
+void SshSettings::setSshFilePath(const FilePath &ssh) { sshSettings->sshFilePath = ssh; }
+FilePath SshSettings::sshFilePath() { return filePathValue(sshSettings->sshFilePath, "ssh"); }
-void SshSettings::setSftpFilePath(const FileName &sftp) { sshSettings->sftpFilePath = sftp; }
-FileName SshSettings::sftpFilePath() { return filePathValue(sshSettings->sftpFilePath, "sftp"); }
+void SshSettings::setSftpFilePath(const FilePath &sftp) { sshSettings->sftpFilePath = sftp; }
+FilePath SshSettings::sftpFilePath() { return filePathValue(sshSettings->sftpFilePath, "sftp"); }
-void SshSettings::setAskpassFilePath(const FileName &askPass)
+void SshSettings::setAskpassFilePath(const FilePath &askPass)
{
sshSettings->askpassFilePath = askPass;
}
-FileName SshSettings::askpassFilePath()
+FilePath SshSettings::askpassFilePath()
{
- FileName candidate;
+ FilePath candidate;
candidate = sshSettings->askpassFilePath;
if (candidate.isEmpty())
- candidate = FileName::fromString(Environment::systemEnvironment().value("SSH_ASKPASS"));
+ candidate = FilePath::fromString(Environment::systemEnvironment().value("SSH_ASKPASS"));
return filePathValue(candidate, QStringList{"qtc-askpass", "ssh-askpass"});
}
-void SshSettings::setKeygenFilePath(const FileName &keygen)
+void SshSettings::setKeygenFilePath(const FilePath &keygen)
{
sshSettings->keygenFilePath = keygen;
}
-FileName SshSettings::keygenFilePath()
+FilePath SshSettings::keygenFilePath()
{
return filePathValue(sshSettings->keygenFilePath, "ssh-keygen");
}
diff --git a/src/libs/ssh/sshsettings.h b/src/libs/ssh/sshsettings.h
index dc29ead606..08692b6e8c 100644
--- a/src/libs/ssh/sshsettings.h
+++ b/src/libs/ssh/sshsettings.h
@@ -49,19 +49,19 @@ public:
static void setConnectionSharingTimeout(int timeInMinutes);
static int connectionSharingTimeout();
- static void setSshFilePath(const Utils::FileName &ssh);
- static Utils::FileName sshFilePath();
+ static void setSshFilePath(const Utils::FilePath &ssh);
+ static Utils::FilePath sshFilePath();
- static void setSftpFilePath(const Utils::FileName &sftp);
- static Utils::FileName sftpFilePath();
+ static void setSftpFilePath(const Utils::FilePath &sftp);
+ static Utils::FilePath sftpFilePath();
- static void setAskpassFilePath(const Utils::FileName &askPass);
- static Utils::FileName askpassFilePath();
+ static void setAskpassFilePath(const Utils::FilePath &askPass);
+ static Utils::FilePath askpassFilePath();
- static void setKeygenFilePath(const Utils::FileName &keygen);
- static Utils::FileName keygenFilePath();
+ static void setKeygenFilePath(const Utils::FilePath &keygen);
+ static Utils::FilePath keygenFilePath();
- using SearchPathRetriever = std::function<Utils::FileNameList()>;
+ using SearchPathRetriever = std::function<Utils::FilePathList()>;
static void setExtraSearchPathRetriever(const SearchPathRetriever &pathRetriever);
};
diff --git a/src/libs/tracing/CMakeLists.txt b/src/libs/tracing/CMakeLists.txt
new file mode 100644
index 0000000000..153756323e
--- /dev/null
+++ b/src/libs/tracing/CMakeLists.txt
@@ -0,0 +1,35 @@
+if (WITH_TESTS)
+ set(TEST_SOURCES
+ runscenegraphtest.cpp runscenegraphtest.h
+ )
+endif()
+
+add_qtc_library(Tracing
+ DEPENDS Utils Qt5::Qml Qt5::Quick
+ PUBLIC_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES ${TEST_SOURCES}
+ flamegraph.cpp flamegraph.h
+ flamegraphattached.h
+ safecastable.h
+ qml/tracing.qrc
+ timelineabstractrenderer.cpp timelineabstractrenderer.h timelineabstractrenderer_p.h
+ timelineformattime.cpp timelineformattime.h
+ timelineitemsrenderpass.cpp timelineitemsrenderpass.h
+ timelinemodel.cpp timelinemodel.h timelinemodel_p.h
+ timelinemodelaggregator.cpp timelinemodelaggregator.h
+ timelinenotesmodel.cpp timelinenotesmodel.h timelinenotesmodel_p.h
+ timelinenotesrenderpass.cpp timelinenotesrenderpass.h
+ timelineoverviewrenderer.cpp timelineoverviewrenderer.h timelineoverviewrenderer_p.h
+ timelinerenderer.cpp timelinerenderer.h timelinerenderer_p.h
+ timelinerenderpass.cpp timelinerenderpass.h
+ timelinerenderstate.cpp timelinerenderstate.h timelinerenderstate_p.h
+ timelineselectionrenderpass.cpp timelineselectionrenderpass.h
+ timelinetheme.cpp timelinetheme.h
+ timelinetracefile.cpp timelinetracefile.h
+ timelinetracemanager.cpp timelinetracemanager.h
+ timelinezoomcontrol.cpp timelinezoomcontrol.h
+ traceevent.h
+ traceeventtype.h
+ tracestashfile.h
+ tracing_global.h
+)
diff --git a/src/libs/tracing/timelineabstractrenderer.h b/src/libs/tracing/timelineabstractrenderer.h
index f28fd07672..64475ef3ae 100644
--- a/src/libs/tracing/timelineabstractrenderer.h
+++ b/src/libs/tracing/timelineabstractrenderer.h
@@ -35,7 +35,6 @@
namespace Timeline {
-
class TRACING_EXPORT TimelineAbstractRenderer : public QQuickItem
{
Q_OBJECT
diff --git a/src/libs/tracing/timelinemodel_p.h b/src/libs/tracing/timelinemodel_p.h
index 53136571be..bc2ac76850 100644
--- a/src/libs/tracing/timelinemodel_p.h
+++ b/src/libs/tracing/timelinemodel_p.h
@@ -90,7 +90,7 @@ public:
ranges.prepend(start);
return 0;
}
- const Range &range = ranges[--i];
+ const Range &range = ranges.at(--i);
if (range.start < start.start || (range.start == start.start &&
range.duration >= start.duration)) {
ranges.insert(++i, start);
@@ -106,7 +106,7 @@ public:
endTimes.prepend(end);
return 0;
}
- if (endTimes[--i].end <= end.end) {
+ if (endTimes.at(--i).end <= end.end) {
endTimes.insert(++i, end);
return i;
}
diff --git a/src/libs/tracing/timelinerenderer.h b/src/libs/tracing/timelinerenderer.h
index b963ec7871..16a766d695 100644
--- a/src/libs/tracing/timelinerenderer.h
+++ b/src/libs/tracing/timelinerenderer.h
@@ -35,7 +35,6 @@
namespace Timeline {
-
class TRACING_EXPORT TimelineRenderer : public TimelineAbstractRenderer
{
Q_OBJECT
diff --git a/src/libs/tracing/tracestashfile.h b/src/libs/tracing/tracestashfile.h
index c3443e1300..0ab6105047 100644
--- a/src/libs/tracing/tracestashfile.h
+++ b/src/libs/tracing/tracestashfile.h
@@ -153,7 +153,7 @@ public:
void clear()
{
file.remove();
- stream.unsetDevice();
+ stream.setDevice(nullptr);
}
bool flush()
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
new file mode 100644
index 0000000000..00307728a6
--- /dev/null
+++ b/src/libs/utils/CMakeLists.txt
@@ -0,0 +1,204 @@
+if (IDE_LIBEXEC_PATH AND IDE_BIN_PATH)
+ file(RELATIVE_PATH RELATIVE_TOOLS_PATH
+ "${CMAKE_INSTALL_PREFIX}/${IDE_BIN_PATH}" "${CMAKE_INSTALL_PREFIX}/${IDE_LIBEXEC_PATH}")
+else()
+ message(WARNING "IDE_LIBEXEC_PATH or IDE_BIN_PATH undefined when calculating tools path")
+ set(RELATIVE_TOOLS_PATH "")
+endif()
+
+add_qtc_library(Utils
+ DEPENDS Qt5::Xml
+ PUBLIC_DEPENDS Qt5::Concurrent Qt5::Core Qt5::Network Qt5::Qml Qt5::Gui Qt5::Widgets
+ DEFINES
+ "QTC_REL_TOOLS_PATH=\"${RELATIVE_TOOLS_PATH}\""
+ SOURCES
+ ../3rdparty/optional/optional.hpp
+ ../3rdparty/variant/variant.hpp
+ QtConcurrentTools
+ algorithm.h
+ ansiescapecodehandler.cpp ansiescapecodehandler.h
+ appmainwindow.cpp appmainwindow.h
+ basetreeview.cpp basetreeview.h
+ benchmarker.cpp benchmarker.h
+ buildablehelperlibrary.cpp buildablehelperlibrary.h
+ categorysortfiltermodel.cpp categorysortfiltermodel.h
+ changeset.cpp changeset.h
+ checkablemessagebox.cpp checkablemessagebox.h
+ classnamevalidatinglineedit.cpp classnamevalidatinglineedit.h
+ codegeneration.cpp codegeneration.h
+ completinglineedit.cpp completinglineedit.h
+ completingtextedit.cpp completingtextedit.h
+ consoleprocess.cpp consoleprocess.h consoleprocess_p.h
+ cpplanguage_details.h
+ crumblepath.cpp crumblepath.h
+ delegates.cpp delegates.h
+ declarationmacros.h
+ detailsbutton.cpp detailsbutton.h
+ detailswidget.cpp detailswidget.h
+ differ.cpp differ.h
+ dropsupport.cpp dropsupport.h
+ elfreader.cpp elfreader.h
+ elidinglabel.cpp elidinglabel.h
+ environment.cpp environment.h
+ environmentdialog.cpp environmentdialog.h
+ environmentmodel.cpp environmentmodel.h
+ execmenu.cpp execmenu.h
+ executeondestruction.h
+ fadingindicator.cpp fadingindicator.h
+ faketooltip.cpp faketooltip.h
+ fancylineedit.cpp fancylineedit.h
+ fancymainwindow.cpp fancymainwindow.h
+ filecrumblabel.cpp filecrumblabel.h
+ fileinprojectfinder.cpp fileinprojectfinder.h
+ filenamevalidatinglineedit.cpp filenamevalidatinglineedit.h
+ filesearch.cpp filesearch.h
+ filesystemwatcher.cpp filesystemwatcher.h
+ fileutils.cpp fileutils.h
+ filewizardpage.cpp filewizardpage.h
+ fixedsizeclicklabel.cpp fixedsizeclicklabel.h
+ flowlayout.cpp flowlayout.h
+ functiontraits.h
+ fuzzymatcher.cpp fuzzymatcher.h
+ genericconstants.h
+ globalfilechangeblocker.cpp globalfilechangeblocker.h
+ guard.cpp guard.h
+ headerviewstretcher.cpp headerviewstretcher.h
+ highlightingitemdelegate.cpp highlightingitemdelegate.h
+ historycompleter.cpp historycompleter.h
+ hostosinfo.cpp hostosinfo.h
+ htmldocextractor.cpp htmldocextractor.h
+ icon.cpp icon.h
+ itemviews.cpp itemviews.h
+ json.cpp json.h
+ jsontreeitem.cpp jsontreeitem.h
+ linecolumn.h
+ link.h
+ listmodel.h
+ 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
+ navigationtreeview.cpp navigationtreeview.h
+ networkaccessmanager.cpp networkaccessmanager.h
+ newclasswidget.cpp newclasswidget.h newclasswidget.ui
+ optional.h
+ osspecificaspects.h
+ outputformat.h
+ outputformatter.cpp outputformatter.h
+ overridecursor.cpp overridecursor.h
+ parameteraction.cpp parameteraction.h
+ pathchooser.cpp pathchooser.h
+ pathlisteditor.cpp pathlisteditor.h
+ persistentsettings.cpp persistentsettings.h
+ pointeralgorithm.h
+ port.cpp port.h
+ portlist.cpp portlist.h
+ predicates.h
+ processhandle.cpp processhandle.h
+ progressindicator.cpp progressindicator.h
+ projectintropage.cpp projectintropage.h projectintropage.ui
+ proxyaction.cpp proxyaction.h
+ proxycredentialsdialog.cpp proxycredentialsdialog.h proxycredentialsdialog.ui
+ qrcparser.cpp qrcparser.h
+ qtcassert.cpp qtcassert.h
+ qtcolorbutton.cpp qtcolorbutton.h
+ qtcprocess.cpp qtcprocess.h
+ reloadpromptutils.cpp reloadpromptutils.h
+ removefiledialog.cpp removefiledialog.h removefiledialog.ui
+ runextensions.cpp runextensions.h
+ savedaction.cpp savedaction.h
+ savefile.cpp savefile.h
+ scopedswap.h
+ settingsaccessor.cpp settingsaccessor.h
+ settingsselector.cpp settingsselector.h
+ settingsutils.h
+ shellcommand.cpp shellcommand.h
+ shellcommandpage.cpp shellcommandpage.h
+ sizedarray.h
+ smallstring.h
+ smallstringfwd.h
+ smallstringio.h
+ smallstringiterator.h
+ smallstringlayout.h
+ smallstringliteral.h
+ smallstringmemory.h
+ smallstringvector.h
+ smallstringview.h
+ statuslabel.cpp statuslabel.h
+ stringutils.cpp stringutils.h
+ styledbar.cpp styledbar.h
+ stylehelper.cpp stylehelper.h
+ synchronousprocess.cpp synchronousprocess.h
+ templateengine.cpp templateengine.h
+ temporarydirectory.cpp temporarydirectory.h
+ temporaryfile.cpp temporaryfile.h
+ textfieldcheckbox.cpp textfieldcheckbox.h
+ textfieldcombobox.cpp textfieldcombobox.h
+ textfileformat.cpp textfileformat.h
+ textutils.cpp textutils.h
+ theme/theme.cpp theme/theme.h theme/theme_p.h
+ tooltip/effects.h
+ tooltip/reuse.h
+ tooltip/tips.cpp tooltip/tips.h
+ tooltip/tooltip.cpp tooltip/tooltip.h
+ touchbar/touchbar.h
+ treemodel.cpp treemodel.h
+ treeviewcombobox.cpp treeviewcombobox.h
+ uncommentselection.cpp uncommentselection.h
+ unixutils.cpp unixutils.h
+ url.cpp url.h
+ utils.qrc
+ utils_global.h
+ utilsicons.cpp utilsicons.h
+ variant.h
+ winutils.cpp winutils.h
+ wizard.cpp wizard.h
+ wizardpage.cpp wizardpage.h
+)
+
+extend_qtc_target(Utils CONDITION WIN32
+ SOURCES
+ consoleprocess_win.cpp
+ process_ctrlc_stub.cpp
+ touchbar/touchbar.cpp
+ DEPENDS
+ user32 iphlpapi ws2_32 shell32
+ DEFINES
+ _UNICODE UNICODE
+ PUBLIC_DEFINES
+ _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS
+)
+
+extend_qtc_target(Utils CONDITION APPLE
+ SOURCES
+ consoleprocess_unix.cpp
+ fileutils_mac.mm fileutils_mac.h
+ processhandle_mac.mm
+ theme/theme_mac.mm theme/theme_mac.h
+ touchbar/touchbar_appdelegate_mac.mm touchbar/touchbar_appdelegate_mac_p.h
+ touchbar/touchbar_mac.mm touchbar/touchbar_mac_p.h
+ DEPENDS
+ ${FWFoundation} ${FWAppKit}
+)
+
+extend_qtc_target(Utils CONDITION UNIX AND NOT APPLE
+ SOURCES
+ consoleprocess_unix.cpp
+ touchbar/touchbar.cpp
+)
+
+if (WIN32)
+ add_qtc_executable(qtcreator_process_stub
+ SOURCES process_stub_win.c
+ DEPENDS shell32
+ DEFINES _UNICODE UNICODE _CRT_SECURE_NO_WARNINGS
+ )
+else()
+ add_qtc_executable(qtcreator_process_stub SOURCES process_stub_unix.c)
+endif()
diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h
index bae78aacda..9e80755a3a 100644
--- a/src/libs/utils/algorithm.h
+++ b/src/libs/utils/algorithm.h
@@ -48,6 +48,323 @@
namespace Utils
{
+/////////////////////////
+// anyOf
+/////////////////////////
+template<typename T, typename F>
+bool anyOf(const T &container, F predicate);
+template<typename T, typename R, typename S>
+bool anyOf(const T &container, R (S::*predicate)() const);
+template<typename T, typename R, typename S>
+bool anyOf(const T &container, R S::*member);
+
+/////////////////////////
+// count
+/////////////////////////
+template<typename T, typename F>
+int count(const T &container, F predicate);
+
+/////////////////////////
+// allOf
+/////////////////////////
+template<typename T, typename F>
+bool allOf(const T &container, F predicate);
+
+/////////////////////////
+// erase
+/////////////////////////
+template<typename T, typename F>
+void erase(T &container, F predicate);
+
+/////////////////////////
+// contains
+/////////////////////////
+template<typename T, typename F>
+bool contains(const T &container, F function);
+template<typename T, typename R, typename S>
+bool contains(const T &container, R (S::*function)() const);
+template<typename C, typename R, typename S>
+bool contains(const C &container, R S::*member);
+
+/////////////////////////
+// findOr
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT typename C::value_type findOr(const C &container,
+ typename C::value_type other,
+ F function);
+template<typename T, typename R, typename S>
+Q_REQUIRED_RESULT typename T::value_type findOr(const T &container,
+ typename T::value_type other,
+ R (S::*function)() const);
+template<typename T, typename R, typename S>
+Q_REQUIRED_RESULT typename T::value_type findOr(const T &container,
+ typename T::value_type other,
+ R S::*member);
+
+/////////////////////////
+// findOrDefault
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
+ typename C::value_type>
+findOrDefault(const C &container, F function);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
+ typename C::value_type>
+findOrDefault(const C &container, R (S::*function)() const);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
+ typename C::value_type>
+findOrDefault(const C &container, R S::*member);
+
+/////////////////////////
+// indexOf
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT int indexOf(const C &container, F function);
+
+/////////////////////////
+// maxElementOr
+/////////////////////////
+template<typename T>
+typename T::value_type maxElementOr(const T &container, typename T::value_type other);
+
+/////////////////////////
+// filtered
+/////////////////////////
+template<typename C, typename F>
+Q_REQUIRED_RESULT C filtered(const C &container, F predicate);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT C filtered(const C &container, R (S::*predicate)() const);
+
+/////////////////////////
+// partition
+/////////////////////////
+// Recommended usage:
+// C hit;
+// C miss;
+// std::tie(hit, miss) = Utils::partition(container, predicate);
+template<typename C, typename F>
+Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, F predicate);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, R (S::*predicate)() const);
+
+/////////////////////////
+// filteredUnique
+/////////////////////////
+template<typename C>
+Q_REQUIRED_RESULT C filteredUnique(const C &container);
+
+/////////////////////////
+// qobject_container_cast
+/////////////////////////
+template<class T, template<typename> class Container, typename Base>
+Container<T> qobject_container_cast(const Container<Base> &container);
+
+/////////////////////////
+// static_container_cast
+/////////////////////////
+template<class T, template<typename> class Container, typename Base>
+Container<T> static_container_cast(const Container<Base> &container);
+
+/////////////////////////
+// sort
+/////////////////////////
+template<typename Container>
+inline void sort(Container &container);
+template<typename Container, typename Predicate>
+inline void sort(Container &container, Predicate p);
+template<typename Container, typename R, typename S>
+inline void sort(Container &container, R S::*member);
+template<typename Container, typename R, typename S>
+inline void sort(Container &container, R (S::*function)() const);
+
+/////////////////////////
+// reverseForeach
+/////////////////////////
+template<typename Container, typename Op>
+inline void reverseForeach(const Container &c, const Op &operation);
+
+/////////////////////////
+// toReferences
+/////////////////////////
+template<template<typename...> class ResultContainer, typename SourceContainer>
+auto toReferences(SourceContainer &sources);
+template<typename SourceContainer>
+auto toReferences(SourceContainer &sources);
+
+/////////////////////////
+// toConstReferences
+/////////////////////////
+template<template<typename...> class ResultContainer, typename SourceContainer>
+auto toConstReferences(const SourceContainer &sources);
+template<typename SourceContainer>
+auto toConstReferences(const SourceContainer &sources);
+
+/////////////////////////
+// take
+/////////////////////////
+template<class C, typename P>
+Q_REQUIRED_RESULT optional<typename C::value_type> take(C &container, P predicate);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT decltype(auto) take(C &container, R S::*member);
+template<typename C, typename R, typename S>
+Q_REQUIRED_RESULT decltype(auto) take(C &container, R (S::*function)() const);
+
+/////////////////////////
+// setUnionMerge
+/////////////////////////
+// Works like std::set_union but provides a merge function for items that match
+// !(a > b) && !(b > a) which normally means that there is an "equal" match.
+// It uses iterators to support move_iterators.
+template<class InputIt1, class InputIt2, class OutputIt, class Merge, class Compare>
+OutputIt setUnionMerge(InputIt1 first1,
+ InputIt1 last1,
+ InputIt2 first2,
+ InputIt2 last2,
+ OutputIt d_first,
+ Merge merge,
+ Compare comp);
+template<class InputIt1, class InputIt2, class OutputIt, class Merge>
+OutputIt setUnionMerge(
+ InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge);
+template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge, class Compare>
+OutputContainer setUnionMerge(InputContainer1 &&input1,
+ InputContainer2 &&input2,
+ Merge merge,
+ Compare comp);
+template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge>
+OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge);
+
+/////////////////////////
+// usize / ssize
+/////////////////////////
+template<typename Container>
+std::make_unsigned_t<typename Container::size_type> usize(Container container);
+template<typename Container>
+std::make_signed_t<typename Container::size_type> ssize(Container container);
+
+/////////////////////////
+// setUnion
+/////////////////////////
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp);
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result);
+
+/////////////////////////
+// transform
+/////////////////////////
+// function without result type deduction:
+template<typename ResultContainer, // complete result container type
+ typename SC, // input container type
+ typename F> // function type
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
+
+// function with result type deduction:
+template<template<typename> class C, // result container type
+ typename SC, // input container type
+ typename F, // function type
+ typename Value = typename std::decay_t<SC>::value_type,
+ typename Result = std::decay_t<std::result_of_t<F(Value &)>>,
+ typename ResultContainer = C<Result>>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
+template<template<typename, typename> class C, // result container type
+ typename SC, // input container type
+ typename F, // function type
+ typename Value = typename std::decay_t<SC>::value_type,
+ typename Result = std::decay_t<std::result_of_t<F(Value &)>>,
+ typename ResultContainer = C<Result, std::allocator<Result>>>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
+
+// member function without result type deduction:
+template<template<typename...> class C, // result container type
+ typename SC, // input container type
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const);
+
+// member function with result type deduction:
+template<typename ResultContainer, // complete result container type
+ typename SC, // input container type
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const);
+
+// member without result type deduction:
+template<typename ResultContainer, // complete result container type
+ typename SC, // input container
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p);
+
+// member with result type deduction:
+template<template<typename...> class C, // result container
+ typename SC, // input container
+ typename R,
+ typename S>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p);
+
+// same container types for input and output, const input
+// function:
+template<template<typename...> class C, // container type
+ typename F, // function type
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, F function);
+
+// same container types for input and output, const input
+// member function:
+template<template<typename...> class C, // container type
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R (S::*p)() const);
+
+// same container types for input and output, const input
+// members:
+template<template<typename...> class C, // container
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R S::*p);
+
+// same container types for input and output, non-const input
+// function:
+template<template<typename...> class C, // container type
+ typename F, // function type
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, F function);
+
+// same container types for input and output, non-const input
+// member function:
+template<template<typename...> class C, // container type
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R (S::*p)() const);
+
+// same container types for input and output, non-const input
+// members:
+template<template<typename...> class C, // container
+ typename R,
+ typename S,
+ typename... CArgs> // Arguments to SC
+Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R S::*p);
+
+/////////////////////////////////////////////////////////////////////////////
+//////// Implementations //////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
//////////////////
// anyOf
/////////////////
@@ -367,25 +684,23 @@ decltype(auto) transform(SC &&container, F function)
// function with result type deduction:
template<template<typename> class C, // result container type
- typename SC, // input container type
- typename F, // function type
- typename Value = typename std::decay_t<SC>::value_type,
- typename Result = std::decay_t<std::result_of_t<F(Value&)>>,
- typename ResultContainer = C<Result>>
-Q_REQUIRED_RESULT
-decltype(auto) transform(SC &&container, F function)
+ typename SC, // input container type
+ typename F, // function type
+ typename Value,
+ typename Result,
+ typename ResultContainer>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function)
{
return transform<ResultContainer>(std::forward<SC>(container), function);
}
template<template<typename, typename> class C, // result container type
- typename SC, // input container type
- typename F, // function type
- typename Value = typename std::decay_t<SC>::value_type,
- typename Result = std::decay_t<std::result_of_t<F(Value&)>>,
- typename ResultContainer = C<Result, std::allocator<Result>>>
-Q_REQUIRED_RESULT
-decltype(auto) transform(SC &&container, F function)
+ typename SC, // input container type
+ typename F, // function type
+ typename Value,
+ typename Result,
+ typename ResultContainer>
+Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function)
{
return transform<ResultContainer>(std::forward<SC>(container), function);
}
@@ -862,4 +1177,70 @@ std::make_signed_t<typename Container::size_type> ssize(Container container)
{
return static_cast<std::make_signed_t<typename Container::size_type>>(container.size());
}
+
+template<typename Compare>
+struct CompareIter
+{
+ Compare compare;
+
+ explicit constexpr CompareIter(Compare compare)
+ : compare(std::move(compare))
+ {}
+
+ template<typename Iterator1, typename Iterator2>
+ constexpr bool operator()(Iterator1 it1, Iterator2 it2)
+ {
+ return bool(compare(*it1, *it2));
+ }
+};
+
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
+OutputIterator set_union_impl(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp)
+{
+ auto compare = CompareIter<Compare>(comp);
+
+ while (first1 != last1 && first2 != last2) {
+ if (compare(first1, first2)) {
+ *result = *first1;
+ ++first1;
+ } else if (compare(first2, first1)) {
+ *result = *first2;
+ ++first2;
+ } else {
+ *result = *first1;
+ ++first1;
+ ++first2;
+ }
+ ++result;
+ }
+
+ return std::copy(first2, last2, std::copy(first1, last1, result));
+}
+
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp)
+{
+ return Utils::set_union_impl(first1, last1, first2, last2, result, comp);
+}
+
+template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
+OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result)
+{
+ return Utils::set_union_impl(
+ first1, last1, first2, last2, result, std::less<typename InputIterator1::value_type>{});
+}
} // namespace Utils
diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp
index d77b8d4d55..352b17bb4b 100644
--- a/src/libs/utils/basetreeview.cpp
+++ b/src/libs/utils/basetreeview.cpp
@@ -183,7 +183,7 @@ public:
QAbstractItemModel *m = q->model();
for (int i = 0; i < 100 && a.isValid(); ++i) {
const QString s = m->data(a).toString();
- int w = fm.width(s) + 10;
+ int w = fm.horizontalAdvance(s) + 10;
if (column == 0) {
for (QModelIndex b = a.parent(); b.isValid(); b = b.parent())
w += ind;
@@ -204,7 +204,8 @@ public:
QTC_ASSERT(m, return -1);
QFontMetrics fm = q->fontMetrics();
- int minimum = fm.width(m->headerData(column, Qt::Horizontal).toString()) + 2 * fm.width(QLatin1Char('m'));
+ int minimum = fm.horizontalAdvance(m->headerData(column, Qt::Horizontal).toString())
+ + 2 * fm.horizontalAdvance(QLatin1Char('m'));
considerItems(column, q->indexAt(QPoint(1, 1)), &minimum, false);
QVariant extraIndices = m->data(QModelIndex(), BaseTreeView::ExtraIndicesForColumnWidth);
@@ -254,8 +255,8 @@ public:
// when we have that size already, in that case minimize.
if (currentSize == suggestedSize) {
QFontMetrics fm = q->fontMetrics();
- int headerSize = fm.width(q->model()->headerData(logicalIndex, Qt::Horizontal).toString());
- int minSize = 10 * fm.width(QLatin1Char('x'));
+ int headerSize = fm.horizontalAdvance(q->model()->headerData(logicalIndex, Qt::Horizontal).toString());
+ int minSize = 10 * fm.horizontalAdvance(QLatin1Char('x'));
targetSize = qMax(minSize, headerSize);
}
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index 3c53e09b2a..33ba624dc4 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -27,11 +27,13 @@
#include "hostosinfo.h"
#include "synchronousprocess.h"
-#include <QDir>
#include <QDateTime>
#include <QDebug>
+#include <QDir>
#include <QRegExp>
+#include <set>
+
namespace Utils {
bool BuildableHelperLibrary::isQtChooser(const QFileInfo &info)
@@ -71,32 +73,54 @@ static bool isQmake(const QString &path)
return !BuildableHelperLibrary::qtVersionForQMake(fi.absoluteFilePath()).isEmpty();
}
-FileName BuildableHelperLibrary::findSystemQt(const Environment &env)
+static FilePath findQmakeInDir(const FilePath &path)
{
- const QString qmake = QLatin1String("qmake");
- FileNameList paths = env.path();
- foreach (const FileName &path, paths) {
- if (path.isEmpty())
- continue;
-
- QDir dir(path.toString());
+ if (path.isEmpty())
+ return FilePath();
+
+ const QString qmake = "qmake";
+ QDir dir(path.toString());
+ if (dir.exists(qmake)) {
+ const QString qmakePath = dir.absoluteFilePath(qmake);
+ if (isQmake(qmakePath))
+ return FilePath::fromString(qmakePath);
+ }
- if (dir.exists(qmake)) {
- const QString qmakePath = dir.absoluteFilePath(qmake);
- if (isQmake(qmakePath))
- return FileName::fromString(qmakePath);
- }
+ // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order.
+ const QFileInfoList candidates = dir.entryInfoList(
+ BuildableHelperLibrary::possibleQMakeCommands(),
+ QDir::Files, QDir::Name | QDir::Reversed);
+ for (const QFileInfo &fi : candidates) {
+ if (fi.fileName() == qmake)
+ continue;
+ if (isQmake(fi.absoluteFilePath()))
+ return FilePath::fromFileInfo(fi);
+ }
+ return FilePath();
+}
- // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order.
- foreach (const QFileInfo &fi, dir.entryInfoList(possibleQMakeCommands(), QDir::Files, QDir::Name | QDir::Reversed)) {
- if (fi.fileName() == qmake)
- continue;
+FilePath BuildableHelperLibrary::findSystemQt(const Environment &env)
+{
+ const FilePathList list = findQtsInEnvironment(env, 1);
+ return list.size() == 1 ? list.first() : FilePath();
+}
- if (isQmake(fi.absoluteFilePath()))
- return FileName(fi);
- }
+FilePathList BuildableHelperLibrary::findQtsInEnvironment(const Environment &env, int maxCount)
+{
+ FilePathList qmakeList;
+ std::set<QString> canonicalEnvPaths;
+ const FilePathList paths = env.path();
+ for (const FilePath &path : paths) {
+ if (!canonicalEnvPaths.insert(path.toFileInfo().canonicalFilePath()).second)
+ continue;
+ const FilePath qmake = findQmakeInDir(path);
+ if (qmake.isEmpty())
+ continue;
+ qmakeList << qmake;
+ if (maxCount != -1 && qmakeList.size() == maxCount)
+ break;
}
- return FileName();
+ return qmakeList;
}
QString BuildableHelperLibrary::qtVersionForQMake(const QString &qmakePath)
@@ -165,7 +189,7 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath,
QString *errorMessage)
{
// try remove the directory
- if (!FileUtils::removeRecursively(FileName::fromString(targetDirectory), errorMessage))
+ if (!FileUtils::removeRecursively(FilePath::fromString(targetDirectory), errorMessage))
return false;
if (!QDir().mkpath(targetDirectory)) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The target directory %1 could not be created.").arg(targetDirectory);
@@ -196,7 +220,7 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath,
// Helper: Run a build process with merged stdout/stderr
static inline bool runBuildProcessI(QProcess &proc,
- const FileName &binary,
+ const FilePath &binary,
const QStringList &args,
int timeoutS,
bool ignoreNonNullExitCode,
@@ -237,7 +261,7 @@ static inline bool runBuildProcessI(QProcess &proc,
// Run a build process with merged stdout/stderr and qWarn about errors.
static bool runBuildProcess(QProcess &proc,
- const FileName &binary,
+ const FilePath &binary,
const QStringList &args,
int timeoutS,
bool ignoreNonNullExitCode,
@@ -276,7 +300,7 @@ bool BuildableHelperLibrary::buildHelper(const BuildHelperArguments &arguments,
arguments.directory));
log->append(newline);
- const FileName makeFullPath = arguments.environment.searchInPath(arguments.makeCommand);
+ const FilePath makeFullPath = arguments.environment.searchInPath(arguments.makeCommand);
if (QFileInfo::exists(arguments.directory + QLatin1String("/Makefile"))) {
if (makeFullPath.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary",
diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h
index c818749f2b..45d37d65c4 100644
--- a/src/libs/utils/buildablehelperlibrary.h
+++ b/src/libs/utils/buildablehelperlibrary.h
@@ -37,7 +37,8 @@ class QTCREATOR_UTILS_EXPORT BuildableHelperLibrary
public:
// returns the full path to the first qmake, qmake-qt4, qmake4 that has
// at least version 2.0.0 and thus is a qt4 qmake
- static FileName findSystemQt(const Environment &env);
+ static FilePath findSystemQt(const Environment &env);
+ static FilePathList findQtsInEnvironment(const Environment &env, int maxCount = -1);
static bool isQtChooser(const QFileInfo &info);
static QString qtChooserToQmakePath(const QString &path);
// return true if the qmake at qmakePath is a Qt (used by QtVersion)
@@ -60,9 +61,9 @@ public:
QString directory;
Environment environment;
- FileName qmakeCommand;
+ FilePath qmakeCommand;
QString targetMode;
- FileName mkspec;
+ FilePath mkspec;
QString proFilename;
QStringList qmakeArguments;
diff --git a/src/libs/utils/checkablemessagebox.cpp b/src/libs/utils/checkablemessagebox.cpp
index 857711fd8a..3ec411cfb3 100644
--- a/src/libs/utils/checkablemessagebox.cpp
+++ b/src/libs/utils/checkablemessagebox.cpp
@@ -32,6 +32,7 @@
#include <QLabel>
#include <QPushButton>
#include <QSettings>
+#include <QStyle>
/*!
\class Utils::CheckableMessageBox
@@ -107,6 +108,7 @@ public:
QCheckBox *checkBox = nullptr;
QDialogButtonBox *buttonBox = nullptr;
QAbstractButton *clickedButton = nullptr;
+ QMessageBox::Icon icon = QMessageBox::NoIcon;
};
CheckableMessageBox::CheckableMessageBox(QWidget *parent) :
@@ -148,17 +150,53 @@ void CheckableMessageBox::setText(const QString &t)
d->messageLabel->setText(t);
}
-QPixmap CheckableMessageBox::iconPixmap() const
-{
- if (const QPixmap *p = d->pixmapLabel->pixmap())
- return QPixmap(*p);
+QMessageBox::Icon CheckableMessageBox::icon() const
+{
+ return d->icon;
+}
+
+// See QMessageBoxPrivate::standardIcon
+static QPixmap pixmapForIcon(QMessageBox::Icon icon, QWidget *w)
+{
+ const QStyle *style = w ? w->style() : QApplication::style();
+ const int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, w);
+ QIcon tmpIcon;
+ switch (icon) {
+ case QMessageBox::Information:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, w);
+ break;
+ case QMessageBox::Warning:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, w);
+ break;
+ case QMessageBox::Critical:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, w);
+ break;
+ case QMessageBox::Question:
+ tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, w);
+ break;
+ default:
+ break;
+ }
+ if (!tmpIcon.isNull()) {
+ QWindow *window = nullptr;
+ if (w) {
+ window = w->windowHandle();
+ if (!window) {
+ if (const QWidget *nativeParent = w->nativeParentWidget())
+ window = nativeParent->windowHandle();
+ }
+ }
+ return tmpIcon.pixmap(window, QSize(iconSize, iconSize));
+ }
return QPixmap();
}
-void CheckableMessageBox::setIconPixmap(const QPixmap &p)
+void CheckableMessageBox::setIcon(QMessageBox::Icon icon)
{
- d->pixmapLabel->setPixmap(p);
- d->pixmapLabel->setVisible(!p.isNull());
+ d->icon = icon;
+ const QPixmap pixmap = pixmapForIcon(icon, this);
+ d->pixmapLabel->setPixmap(pixmap);
+ d->pixmapLabel->setVisible(!pixmap.isNull());
}
bool CheckableMessageBox::isChecked() const
@@ -239,7 +277,7 @@ CheckableMessageBox::question(QWidget *parent,
{
CheckableMessageBox mb(parent);
mb.setWindowTitle(title);
- mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question));
+ mb.setIcon(QMessageBox::Question);
mb.setText(question);
mb.setCheckBoxText(checkBoxText);
mb.setChecked(*checkBoxSetting);
@@ -261,7 +299,7 @@ CheckableMessageBox::information(QWidget *parent,
{
CheckableMessageBox mb(parent);
mb.setWindowTitle(title);
- mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Information));
+ mb.setIcon(QMessageBox::Information);
mb.setText(text);
mb.setCheckBoxText(checkBoxText);
mb.setChecked(*checkBoxSetting);
@@ -297,9 +335,7 @@ void initDoNotAskAgainMessageBox(CheckableMessageBox &messageBox, const QString
DoNotAskAgainType type)
{
messageBox.setWindowTitle(title);
- messageBox.setIconPixmap(QMessageBox::standardIcon(type == Information
- ? QMessageBox::Information
- : QMessageBox::Question));
+ messageBox.setIcon(type == Information ? QMessageBox::Information : QMessageBox::Question);
messageBox.setText(text);
messageBox.setCheckBoxVisible(true);
messageBox.setCheckBoxText(type == Information ? CheckableMessageBox::msgDoNotShowAgain()
diff --git a/src/libs/utils/checkablemessagebox.h b/src/libs/utils/checkablemessagebox.h
index c6359f72cd..042e88aa96 100644
--- a/src/libs/utils/checkablemessagebox.h
+++ b/src/libs/utils/checkablemessagebox.h
@@ -42,7 +42,7 @@ class QTCREATOR_UTILS_EXPORT CheckableMessageBox : public QDialog
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
- Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
+ Q_PROPERTY(QMessageBox::Icon icon READ icon WRITE setIcon)
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText)
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
@@ -109,9 +109,8 @@ public:
QDialogButtonBox::StandardButton defaultButton() const;
void setDefaultButton(QDialogButtonBox::StandardButton s);
- // See static QMessageBox::standardPixmap()
- QPixmap iconPixmap() const;
- void setIconPixmap (const QPixmap &p);
+ QMessageBox::Icon icon() const;
+ void setIcon(QMessageBox::Icon icon);
// Query the result
QAbstractButton *clickedButton() const;
diff --git a/src/libs/utils/completingtextedit.cpp b/src/libs/utils/completingtextedit.cpp
index f4d7b0441c..3a34973c00 100644
--- a/src/libs/utils/completingtextedit.cpp
+++ b/src/libs/utils/completingtextedit.cpp
@@ -114,7 +114,7 @@ void CompletingTextEdit::setCompleter(QCompleter *c)
completer()->setWidget(this);
completer()->setCompletionMode(QCompleter::PopupCompletion);
- connect(completer(), static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::activated),
+ connect(completer(), QOverload<const QString &>::of(&QCompleter::activated),
this, [this](const QString &str) { d->insertCompletion(str); });
}
diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h
index 28be67f0bf..3dec9838c3 100644
--- a/src/libs/utils/consoleprocess.h
+++ b/src/libs/utils/consoleprocess.h
@@ -70,7 +70,9 @@ public:
QProcess::ProcessError error() const;
QString errorString() const;
- bool start(const QString &program, const QString &args);
+ enum class MetaCharMode { Abort, Ignore };
+ bool start(const QString &program, const QString &args,
+ MetaCharMode metaCharMode = MetaCharMode::Abort);
public slots:
void stop();
diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp
index 92b69952f6..43afffa0a2 100644
--- a/src/libs/utils/consoleprocess_unix.cpp
+++ b/src/libs/utils/consoleprocess_unix.cpp
@@ -65,7 +65,7 @@ void ConsoleProcess::setSettings(QSettings *settings)
d->m_settings = settings;
}
-bool ConsoleProcess::start(const QString &program, const QString &args)
+bool ConsoleProcess::start(const QString &program, const QString &args, MetaCharMode metaCharMode)
{
if (isRunning())
return false;
@@ -75,7 +75,8 @@ bool ConsoleProcess::start(const QString &program, const QString &args)
QtcProcess::SplitError perr;
QtcProcess::Arguments pargs = QtcProcess::prepareArgs(args, &perr, HostOsInfo::hostOs(),
- &d->m_environment, &d->m_workingDir);
+ &d->m_environment, &d->m_workingDir,
+ metaCharMode == MetaCharMode::Abort);
QString pcmd;
if (perr == QtcProcess::SplitOk) {
pcmd = program;
@@ -436,12 +437,6 @@ bool ConsoleProcess::startTerminalEmulator(QSettings *settings, const QString &w
const Utils::Environment &env)
{
const TerminalCommand term = terminalEmulator(settings);
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- // for 5.9 and below we cannot set the environment
- Q_UNUSED(env);
- return QProcess::startDetached(term.command, QtcProcess::splitArgs(term.openArgs),
- workingDir);
-#else
QProcess process;
process.setProgram(term.command);
process.setArguments(QtcProcess::splitArgs(term.openArgs));
@@ -449,7 +444,6 @@ bool ConsoleProcess::startTerminalEmulator(QSettings *settings, const QString &w
process.setWorkingDirectory(workingDir);
return process.startDetached();
-#endif
}
} // namespace Utils
diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp
index 2a68ddaba8..be65c42cc8 100644
--- a/src/libs/utils/consoleprocess_win.cpp
+++ b/src/libs/utils/consoleprocess_win.cpp
@@ -51,8 +51,10 @@ qint64 ConsoleProcess::applicationMainThreadID() const
return d->m_appMainThreadId;
}
-bool ConsoleProcess::start(const QString &program, const QString &args)
+bool ConsoleProcess::start(const QString &program, const QString &args, MetaCharMode metaCharMode)
{
+ Q_UNUSED(metaCharMode);
+
if (isRunning())
return false;
diff --git a/src/libs/utils/cpplanguage_details.h b/src/libs/utils/cpplanguage_details.h
index 43474d03cb..e9c9a5aa40 100644
--- a/src/libs/utils/cpplanguage_details.h
+++ b/src/libs/utils/cpplanguage_details.h
@@ -29,9 +29,10 @@
namespace Utils {
-enum class Language : unsigned char { C, Cxx };
+enum class Language : unsigned char { None, C, Cxx };
enum class LanguageVersion : unsigned char {
+ None,
C89,
C99,
C11,
diff --git a/src/libs/utils/delegates.cpp b/src/libs/utils/delegates.cpp
index a677c8c992..2240e8a6a4 100644
--- a/src/libs/utils/delegates.cpp
+++ b/src/libs/utils/delegates.cpp
@@ -84,7 +84,7 @@ void AnnotatedItemDelegate::paint(QPainter *painter,
painter->save();
painter->setPen(disabled.color(QPalette::WindowText));
- static int extra = opt.fontMetrics.width(m_delimiter) + 10;
+ static int extra = opt.fontMetrics.horizontalAdvance(m_delimiter) + 10;
const QPixmap &pixmap = opt.icon.pixmap(opt.decorationSize);
const QRect &iconRect = style->itemPixmapRect(opt.rect, opt.decorationAlignment, pixmap);
const QRect &displayRect = style->itemTextRect(opt.fontMetrics, opt.rect,
diff --git a/src/libs/utils/detailsbutton.cpp b/src/libs/utils/detailsbutton.cpp
index 5f2c88eca3..329975afdb 100644
--- a/src/libs/utils/detailsbutton.cpp
+++ b/src/libs/utils/detailsbutton.cpp
@@ -79,7 +79,7 @@ DetailsButton::DetailsButton(QWidget *parent) : QAbstractButton(parent), m_fader
QSize DetailsButton::sizeHint() const
{
// TODO: Adjust this when icons become available!
- const int w = fontMetrics().width(text()) + 32;
+ const int w = fontMetrics().horizontalAdvance(text()) + 32;
if (HostOsInfo::isMacHost())
return QSize(w, 34);
return QSize(w, 22);
diff --git a/src/libs/utils/elidinglabel.cpp b/src/libs/utils/elidinglabel.cpp
index e584bd8bb6..1d90665af5 100644
--- a/src/libs/utils/elidinglabel.cpp
+++ b/src/libs/utils/elidinglabel.cpp
@@ -66,7 +66,7 @@ void ElidingLabel::paintEvent(QPaintEvent *)
QRect contents = contentsRect().adjusted(m, m, -m, -m);
QFontMetrics fm = fontMetrics();
QString txt = text();
- if (txt.length() > 4 && fm.width(txt) > contents.width()) {
+ if (txt.length() > 4 && fm.horizontalAdvance(txt) > contents.width()) {
setToolTip(txt);
txt = fm.elidedText(txt, m_elideMode, contents.width());
} else {
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index a82d6c27f0..d61a75ebf7 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -392,14 +392,14 @@ void Environment::clear()
m_values.clear();
}
-FileName Environment::searchInDirectory(const QStringList &execs, const FileName &directory,
- QSet<FileName> &alreadyChecked) const
+FilePath Environment::searchInDirectory(const QStringList &execs, const FilePath &directory,
+ QSet<FilePath> &alreadyChecked) const
{
const int checkedCount = alreadyChecked.count();
alreadyChecked.insert(directory);
if (directory.isEmpty() || alreadyChecked.count() == checkedCount)
- return FileName();
+ return FilePath();
const QString dir = directory.toString();
@@ -407,9 +407,9 @@ FileName Environment::searchInDirectory(const QStringList &execs, const FileName
for (const QString &exec : execs) {
fi.setFile(dir, exec);
if (fi.isFile() && fi.isExecutable())
- return FileName::fromString(fi.absoluteFilePath());
+ return FilePath::fromString(fi.absoluteFilePath());
}
- return FileName();
+ return FilePath();
}
QStringList Environment::appendExeExtensions(const QString &executable) const
@@ -435,23 +435,25 @@ bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) con
const QStringList exe2List = appendExeExtensions(exe2);
for (const QString &i1 : exe1List) {
for (const QString &i2 : exe2List) {
- const FileName f1 = FileName::fromString(i1);
- const FileName f2 = FileName::fromString(i2);
+ const FilePath f1 = FilePath::fromString(i1);
+ const FilePath f2 = FilePath::fromString(i2);
if (f1 == f2)
return true;
if (FileUtils::resolveSymlinks(f1) == FileUtils::resolveSymlinks(f2))
return true;
+ if (FileUtils::fileId(f1) == FileUtils::fileId(f2))
+ return true;
}
}
return false;
}
-FileName Environment::searchInPath(const QString &executable,
- const FileNameList &additionalDirs,
+FilePath Environment::searchInPath(const QString &executable,
+ const FilePathList &additionalDirs,
const PathFilter &func) const
{
if (executable.isEmpty())
- return FileName();
+ return FilePath();
const QString exec = QDir::cleanPath(expandVariables(executable));
const QFileInfo fi(exec);
@@ -462,34 +464,34 @@ FileName Environment::searchInPath(const QString &executable,
for (const QString &path : execs) {
QFileInfo pfi = QFileInfo(path);
if (pfi.isFile() && pfi.isExecutable())
- return FileName::fromString(path);
+ return FilePath::fromString(path);
}
- return FileName::fromString(exec);
+ return FilePath::fromString(exec);
}
- QSet<FileName> alreadyChecked;
- for (const FileName &dir : additionalDirs) {
- FileName tmp = searchInDirectory(execs, dir, alreadyChecked);
+ QSet<FilePath> alreadyChecked;
+ for (const FilePath &dir : additionalDirs) {
+ FilePath tmp = searchInDirectory(execs, dir, alreadyChecked);
if (!tmp.isEmpty() && (!func || func(tmp)))
return tmp;
}
if (executable.contains('/'))
- return FileName();
+ return FilePath();
- for (const FileName &p : path()) {
- FileName tmp = searchInDirectory(execs, p, alreadyChecked);
+ for (const FilePath &p : path()) {
+ FilePath tmp = searchInDirectory(execs, p, alreadyChecked);
if (!tmp.isEmpty() && (!func || func(tmp)))
return tmp;
}
- return FileName();
+ return FilePath();
}
-FileNameList Environment::path() const
+FilePathList Environment::path() const
{
const QStringList pathComponents = value("PATH")
.split(OsSpecificAspects::pathListSeparator(m_osType), QString::SkipEmptyParts);
- return Utils::transform(pathComponents, &FileName::fromUserInput);
+ return Utils::transform(pathComponents, &FilePath::fromUserInput);
}
QString Environment::value(const QString &key) const
@@ -688,6 +690,11 @@ QString Environment::expandVariables(const QString &input) const
return result;
}
+FilePath Environment::expandVariables(const FilePath &variables) const
+{
+ return FilePath::fromString(expandVariables(variables.toString()));
+}
+
QStringList Environment::expandVariables(const QStringList &variables) const
{
return Utils::transform(variables, [this](const QString &i) { return expandVariables(i); });
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index cab78a082b..f1e957ab6d 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -124,17 +124,18 @@ public:
Environment::const_iterator constEnd() const;
Environment::const_iterator constFind(const QString &name) const;
- using PathFilter = std::function<bool(const FileName &)>;
- FileName searchInPath(const QString &executable,
- const FileNameList &additionalDirs = FileNameList(),
+ using PathFilter = std::function<bool(const FilePath &)>;
+ FilePath searchInPath(const QString &executable,
+ const FilePathList &additionalDirs = FilePathList(),
const PathFilter &func = PathFilter()) const;
- FileNameList path() const;
+ FilePathList path() const;
QStringList appendExeExtensions(const QString &executable) const;
bool isSameExecutable(const QString &exe1, const QString &exe2) const;
QString expandVariables(const QString &input) const;
+ FilePath expandVariables(const FilePath &input) const;
QStringList expandVariables(const QStringList &input) const;
bool operator!=(const Environment &other) const;
@@ -143,8 +144,8 @@ public:
static void modifySystemEnvironment(const QList<EnvironmentItem> &list); // use with care!!!
private:
- FileName searchInDirectory(const QStringList &execs, const FileName &directory,
- QSet<FileName> &alreadyChecked) const;
+ FilePath searchInDirectory(const QStringList &execs, const FilePath &directory,
+ QSet<FilePath> &alreadyChecked) const;
QMap<QString, QString> m_values;
OsType m_osType;
};
diff --git a/src/libs/utils/filecrumblabel.cpp b/src/libs/utils/filecrumblabel.cpp
index a4bbe37c44..cf03af553c 100644
--- a/src/libs/utils/filecrumblabel.cpp
+++ b/src/libs/utils/filecrumblabel.cpp
@@ -38,22 +38,22 @@ FileCrumbLabel::FileCrumbLabel(QWidget *parent)
setTextFormat(Qt::RichText);
setWordWrap(true);
connect(this, &QLabel::linkActivated, this, [this](const QString &url) {
- emit pathClicked(FileName::fromString(QUrl(url).toLocalFile()));
+ emit pathClicked(FilePath::fromString(QUrl(url).toLocalFile()));
});
- setPath(FileName());
+ setPath(FilePath());
}
-static QString linkForPath(const FileName &path, const QString &display)
+static QString linkForPath(const FilePath &path, const QString &display)
{
return "<a href=\""
+ QUrl::fromLocalFile(path.toString()).toString(QUrl::FullyEncoded) + "\">"
+ display + "</a>";
}
-void FileCrumbLabel::setPath(const FileName &path)
+void FileCrumbLabel::setPath(const FilePath &path)
{
QStringList links;
- FileName current = path;
+ FilePath current = path;
while (!current.isEmpty()) {
const QString fileName = current.fileName();
if (!fileName.isEmpty()) {
diff --git a/src/libs/utils/filecrumblabel.h b/src/libs/utils/filecrumblabel.h
index 6320b115c0..05dd050812 100644
--- a/src/libs/utils/filecrumblabel.h
+++ b/src/libs/utils/filecrumblabel.h
@@ -38,10 +38,10 @@ class QTCREATOR_UTILS_EXPORT FileCrumbLabel : public QLabel
public:
FileCrumbLabel(QWidget *parent = nullptr);
- void setPath(const FileName &path);
+ void setPath(const FilePath &path);
signals:
- void pathClicked(const FileName &path);
+ void pathClicked(const FilePath &path);
};
} // Utils
diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp
index 2be64260e8..3dbde17792 100644
--- a/src/libs/utils/fileinprojectfinder.cpp
+++ b/src/libs/utils/fileinprojectfinder.cpp
@@ -24,15 +24,20 @@
****************************************************************************/
#include "fileinprojectfinder.h"
+
+#include "algorithm.h"
#include "fileutils.h"
#include "hostosinfo.h"
+#include "qrcparser.h"
#include "qtcassert.h"
+#include <QCursor>
#include <QDebug>
+#include <QDir>
#include <QFileInfo>
#include <QLoggingCategory>
+#include <QMenu>
#include <QUrl>
-#include <QDir>
#include <algorithm>
@@ -77,7 +82,7 @@ static bool checkPath(const QString &candidate, int matchLength,
FileInProjectFinder::FileInProjectFinder() = default;
FileInProjectFinder::~FileInProjectFinder() = default;
-void FileInProjectFinder::setProjectDirectory(const FileName &absoluteProjectPath)
+void FileInProjectFinder::setProjectDirectory(const FilePath &absoluteProjectPath)
{
if (absoluteProjectPath == m_projectDir)
return;
@@ -90,21 +95,22 @@ void FileInProjectFinder::setProjectDirectory(const FileName &absoluteProjectPat
m_cache.clear();
}
-FileName FileInProjectFinder::projectDirectory() const
+FilePath FileInProjectFinder::projectDirectory() const
{
return m_projectDir;
}
-void FileInProjectFinder::setProjectFiles(const FileNameList &projectFiles)
+void FileInProjectFinder::setProjectFiles(const FilePathList &projectFiles)
{
if (m_projectFiles == projectFiles)
return;
m_projectFiles = projectFiles;
m_cache.clear();
+ m_qrcUrlFinder.setProjectFiles(projectFiles);
}
-void FileInProjectFinder::setSysroot(const FileName &sysroot)
+void FileInProjectFinder::setSysroot(const FilePath &sysroot)
{
if (m_sysroot == sysroot)
return;
@@ -113,7 +119,7 @@ void FileInProjectFinder::setSysroot(const FileName &sysroot)
m_cache.clear();
}
-void FileInProjectFinder::addMappedPath(const FileName &localFilePath, const QString &remoteFilePath)
+void FileInProjectFinder::addMappedPath(const FilePath &localFilePath, const QString &remoteFilePath)
{
const QStringList segments = remoteFilePath.split('/', QString::SkipEmptyParts);
@@ -136,18 +142,29 @@ void FileInProjectFinder::addMappedPath(const FileName &localFilePath, const QSt
folder specified. Third, we walk the list of project files, and search for a file name match
there. If all fails, it returns the original path from the file URL.
*/
-QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
+FilePathList FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
{
qCDebug(finderLog) << "FileInProjectFinder: trying to find file" << fileUrl.toString() << "...";
+ if (fileUrl.scheme() == "qrc" || fileUrl.toString().startsWith(':')) {
+ const FilePathList result = m_qrcUrlFinder.find(fileUrl);
+ if (!result.isEmpty()) {
+ if (success)
+ *success = true;
+ return result;
+ }
+ }
+
QString originalPath = fileUrl.toLocalFile();
if (originalPath.isEmpty()) // e.g. qrc://
originalPath = fileUrl.path();
- QString result = originalPath;
+ FilePathList result;
bool found = findFileOrDirectory(originalPath, [&](const QString &fileName, int) {
- result = fileName;
+ result << FilePath::fromString(fileName);
});
+ if (!found)
+ result << FilePath::fromString(originalPath);
if (success)
*success = found;
@@ -155,12 +172,12 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
return result;
}
-bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QString &found,
+bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QStringList &found,
int matchLength, const char *where) const
{
qCDebug(finderLog) << "FileInProjectFinder: found" << found << where;
CacheEntry entry;
- entry.path = found;
+ entry.paths = found;
entry.matchLength = matchLength;
m_cache.insert(originalPath, entry);
return true;
@@ -189,8 +206,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (node) {
if (!node->localPath.isEmpty()) {
const QString localPath = node->localPath.toString();
- if (checkPath(localPath, origLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, localPath, origLength, "in mapped paths");
+ if (checkPath(localPath, origLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(localPath), origLength,
+ "in mapped paths");
+ }
} else if (directoryHandler) {
directoryHandler(node->children.keys(), origLength);
qCDebug(finderLog) << "FileInProjectFinder: found virtual directory" << originalPath
@@ -203,13 +222,18 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (it != m_cache.end()) {
qCDebug(finderLog) << "FileInProjectFinder: checking cache ...";
// check if cached path is still there
- const CacheEntry &candidate = it.value();
- if (checkPath(candidate.path, candidate.matchLength, fileHandler, directoryHandler)) {
- qCDebug(finderLog) << "FileInProjectFinder: found" << candidate.path << "in the cache";
- return true;
- } else {
- m_cache.erase(it);
+ CacheEntry &candidate = it.value();
+ for (auto pathIt = candidate.paths.begin(); pathIt != candidate.paths.end();) {
+ if (checkPath(*pathIt, candidate.matchLength, fileHandler, directoryHandler)) {
+ qCDebug(finderLog) << "FileInProjectFinder: found" << *pathIt << "in the cache";
+ ++pathIt;
+ } else {
+ pathIt = candidate.paths.erase(pathIt);
+ }
}
+ if (!candidate.paths.empty())
+ return true;
+ m_cache.erase(it);
}
if (!m_projectDir.isEmpty()) {
@@ -231,7 +255,7 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (prefixToIgnore == -1
&& checkPath(originalPath, origLength, fileHandler, directoryHandler)) {
- return handleSuccess(originalPath, originalPath, origLength,
+ return handleSuccess(originalPath, QStringList(originalPath), origLength,
"in project directory");
}
}
@@ -254,8 +278,11 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
candidate.remove(0, prefixToIgnore);
candidate.prepend(m_projectDir.toString());
const int matchLength = origLength - prefixToIgnore;
- if (checkPath(candidate, matchLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, candidate, matchLength, "in project directory");
+ // FIXME: This might be a worse match than what we find later.
+ if (checkPath(candidate, matchLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(candidate), matchLength,
+ "in project directory");
+ }
prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1);
}
}
@@ -264,31 +291,38 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
qCDebug(finderLog) << "FileInProjectFinder: checking project files ...";
QStringList matches;
- const QString lastSegment = FileName::fromString(originalPath).fileName();
+ const QString lastSegment = FilePath::fromString(originalPath).fileName();
if (fileHandler)
matches.append(filesWithSameFileName(lastSegment));
if (directoryHandler)
matches.append(pathSegmentsWithSameName(lastSegment));
- const QString matchedFilePath = bestMatch(matches, originalPath);
- const int matchLength = commonPostFixLength(matchedFilePath, originalPath);
- if (!matchedFilePath.isEmpty()
- && checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler)) {
- return handleSuccess(originalPath, matchedFilePath, matchLength,
- "when matching project files");
+ const QStringList matchedFilePaths = bestMatches(matches, originalPath);
+ if (!matchedFilePaths.empty()) {
+ const int matchLength = commonPostFixLength(matchedFilePaths.first(), originalPath);
+ QStringList hits;
+ for (const QString &matchedFilePath : matchedFilePaths) {
+ if (checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler))
+ hits << matchedFilePath;
+ }
+ if (!hits.empty())
+ return handleSuccess(originalPath, hits, matchLength, "when matching project files");
}
CacheEntry foundPath = findInSearchPaths(originalPath, fileHandler, directoryHandler);
- if (!foundPath.path.isEmpty())
- return handleSuccess(originalPath, foundPath.path, foundPath.matchLength, "in search path");
+ if (!foundPath.paths.isEmpty()) {
+ return handleSuccess(originalPath, foundPath.paths, foundPath.matchLength,
+ "in search path");
+ }
qCDebug(finderLog) << "FileInProjectFinder: checking absolute path in sysroot ...";
// check if absolute path is found in sysroot
if (!m_sysroot.isEmpty()) {
- FileName sysrootPath = m_sysroot;
- sysrootPath.appendPath(originalPath);
- if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, sysrootPath.toString(), origLength, "in sysroot");
+ const FilePath sysrootPath = m_sysroot.pathAppended(originalPath);
+ if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(sysrootPath.toString()), origLength,
+ "in sysroot");
+ }
}
qCDebug(finderLog) << "FileInProjectFinder: couldn't find file!";
@@ -299,10 +333,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPaths(
const QString &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const
{
- for (const FileName &dirPath : m_searchDirectories) {
+ for (const FilePath &dirPath : m_searchDirectories) {
const CacheEntry found = findInSearchPath(dirPath.toString(), filePath,
fileHandler, directoryHandler);
- if (!found.path.isEmpty())
+ if (!found.paths.isEmpty())
return found;
}
@@ -327,17 +361,17 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath(
QString s = filePath;
while (!s.isEmpty()) {
CacheEntry result;
- result.path = searchPath + QLatin1Char('/') + s;
+ result.paths << searchPath + '/' + s;
result.matchLength = s.length() + 1;
- qCDebug(finderLog) << "FileInProjectFinder: trying" << result.path;
+ qCDebug(finderLog) << "FileInProjectFinder: trying" << result.paths.first();
- if (checkPath(result.path, result.matchLength, fileHandler, directoryHandler))
+ if (checkPath(result.paths.first(), result.matchLength, fileHandler, directoryHandler))
return result;
QString next = chopFirstDir(s);
if (next.isEmpty()) {
if (directoryHandler && QFileInfo(searchPath).fileName() == s) {
- result.path = searchPath;
+ result.paths = QStringList{searchPath};
directoryHandler(QDir(searchPath).entryList(), result.matchLength);
return result;
}
@@ -352,7 +386,7 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath(
QStringList FileInProjectFinder::filesWithSameFileName(const QString &fileName) const
{
QStringList result;
- foreach (const FileName &f, m_projectFiles) {
+ foreach (const FilePath &f, m_projectFiles) {
if (f.fileName() == fileName)
result << f.toString();
}
@@ -362,8 +396,8 @@ QStringList FileInProjectFinder::filesWithSameFileName(const QString &fileName)
QStringList FileInProjectFinder::pathSegmentsWithSameName(const QString &pathSegment) const
{
QStringList result;
- for (const FileName &f : m_projectFiles) {
- FileName currentPath = f.parentDir();
+ for (const FilePath &f : m_projectFiles) {
+ FilePath currentPath = f.parentDir();
do {
if (currentPath.fileName() == pathSegment) {
if (result.isEmpty() || result.last() != currentPath.toString())
@@ -386,32 +420,38 @@ int FileInProjectFinder::commonPostFixLength(const QString &candidatePath,
return rank;
}
-QString FileInProjectFinder::bestMatch(const QStringList &filePaths, const QString &filePathToFind)
+QStringList FileInProjectFinder::bestMatches(const QStringList &filePaths,
+ const QString &filePathToFind)
{
if (filePaths.isEmpty())
- return QString();
+ return {};
if (filePaths.length() == 1) {
qCDebug(finderLog) << "FileInProjectFinder: found" << filePaths.first()
<< "in project files";
- return filePaths.first();
+ return filePaths;
}
- auto it = std::max_element(filePaths.constBegin(), filePaths.constEnd(),
- [&filePathToFind] (const QString &a, const QString &b) -> bool {
- return commonPostFixLength(a, filePathToFind) < commonPostFixLength(b, filePathToFind);
- });
- if (it != filePaths.cend()) {
- qCDebug(finderLog) << "FileInProjectFinder: found best match" << *it << "in project files";
- return *it;
+ int bestRank = -1;
+ QStringList bestFilePaths;
+ for (const QString &fp : filePaths) {
+ const int currentRank = commonPostFixLength(fp, filePathToFind);
+ if (currentRank < bestRank)
+ continue;
+ if (currentRank > bestRank) {
+ bestRank = currentRank;
+ bestFilePaths.clear();
+ }
+ bestFilePaths << fp;
}
- return QString();
+ QTC_CHECK(!bestFilePaths.empty());
+ return bestFilePaths;
}
-FileNameList FileInProjectFinder::searchDirectories() const
+FilePathList FileInProjectFinder::searchDirectories() const
{
return m_searchDirectories;
}
-void FileInProjectFinder::setAdditionalSearchDirectories(const FileNameList &searchDirectories)
+void FileInProjectFinder::setAdditionalSearchDirectories(const FilePathList &searchDirectories)
{
m_searchDirectories = searchDirectories;
}
@@ -421,4 +461,43 @@ FileInProjectFinder::PathMappingNode::~PathMappingNode()
qDeleteAll(children);
}
+FilePathList FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const
+{
+ const auto fileIt = m_fileCache.constFind(fileUrl);
+ if (fileIt != m_fileCache.cend())
+ return fileIt.value();
+ QStringList hits;
+ for (const FilePath &f : m_allQrcFiles) {
+ QrcParser::Ptr &qrcParser = m_parserCache[f];
+ if (!qrcParser)
+ qrcParser = QrcParser::parseQrcFile(f.toString(), QString());
+ if (!qrcParser->isValid())
+ continue;
+ qrcParser->collectFilesAtPath(QrcParser::normalizedQrcFilePath(fileUrl.toString()), &hits);
+ }
+ hits.removeDuplicates();
+ const FilePathList result = transform(hits, &FilePath::fromString);
+ m_fileCache.insert(fileUrl, result);
+ return result;
+}
+
+void FileInProjectFinder::QrcUrlFinder::setProjectFiles(const FilePathList &projectFiles)
+{
+ m_allQrcFiles = filtered(projectFiles, [](const FilePath &f) { return f.endsWith(".qrc"); });
+ m_fileCache.clear();
+ m_parserCache.clear();
+}
+
+FilePath chooseFileFromList(const FilePathList &candidates)
+{
+ if (candidates.length() == 1)
+ return candidates.first();
+ QMenu filesMenu;
+ for (const FilePath &candidate : candidates)
+ filesMenu.addAction(candidate.toUserOutput());
+ if (const QAction * const action = filesMenu.exec(QCursor::pos()))
+ return FilePath::fromUserInput(action->text());
+ return FilePath();
+}
+
} // namespace Utils
diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h
index 43a954ff93..66b5317235 100644
--- a/src/libs/utils/fileinprojectfinder.h
+++ b/src/libs/utils/fileinprojectfinder.h
@@ -29,11 +29,13 @@
#include <utils/fileutils.h>
#include <QHash>
+#include <QSharedPointer>
#include <QStringList>
QT_FORWARD_DECLARE_CLASS(QUrl)
namespace Utils {
+class QrcParser;
class QTCREATOR_UTILS_EXPORT FileInProjectFinder
{
@@ -45,34 +47,44 @@ public:
FileInProjectFinder();
~FileInProjectFinder();
- void setProjectDirectory(const FileName &absoluteProjectPath);
- FileName projectDirectory() const;
+ void setProjectDirectory(const FilePath &absoluteProjectPath);
+ FilePath projectDirectory() const;
- void setProjectFiles(const FileNameList &projectFiles);
- void setSysroot(const FileName &sysroot);
+ void setProjectFiles(const FilePathList &projectFiles);
+ void setSysroot(const FilePath &sysroot);
- void addMappedPath(const FileName &localFilePath, const QString &remoteFilePath);
+ void addMappedPath(const FilePath &localFilePath, const QString &remoteFilePath);
- QString findFile(const QUrl &fileUrl, bool *success = nullptr) const;
+ FilePathList findFile(const QUrl &fileUrl, bool *success = nullptr) const;
bool findFileOrDirectory(const QString &originalPath, FileHandler fileHandler = nullptr,
DirectoryHandler directoryHandler = nullptr) const;
- FileNameList searchDirectories() const;
- void setAdditionalSearchDirectories(const FileNameList &searchDirectories);
+ FilePathList searchDirectories() const;
+ void setAdditionalSearchDirectories(const FilePathList &searchDirectories);
private:
struct PathMappingNode
{
~PathMappingNode();
- FileName localPath;
+ FilePath localPath;
QHash<QString, PathMappingNode *> children;
};
struct CacheEntry {
- QString path;
+ QStringList paths;
int matchLength = 0;
};
+ class QrcUrlFinder {
+ public:
+ FilePathList find(const QUrl &fileUrl) const;
+ void setProjectFiles(const FilePathList &projectFiles);
+ private:
+ FilePathList m_allQrcFiles;
+ mutable QHash<QUrl, FilePathList> m_fileCache;
+ mutable QHash<FilePath, QSharedPointer<QrcParser>> m_parserCache;
+ };
+
CacheEntry findInSearchPaths(const QString &filePath, FileHandler fileHandler,
DirectoryHandler directoryHandler) const;
static CacheEntry findInSearchPath(const QString &searchPath, const QString &filePath,
@@ -80,19 +92,22 @@ private:
QStringList filesWithSameFileName(const QString &fileName) const;
QStringList pathSegmentsWithSameName(const QString &path) const;
- bool handleSuccess(const QString &originalPath, const QString &found, int confidence,
+ bool handleSuccess(const QString &originalPath, const QStringList &found, int confidence,
const char *where) const;
static int commonPostFixLength(const QString &candidatePath, const QString &filePathToFind);
- static QString bestMatch(const QStringList &filePaths, const QString &filePathToFind);
+ static QStringList bestMatches(const QStringList &filePaths, const QString &filePathToFind);
- FileName m_projectDir;
- FileName m_sysroot;
- FileNameList m_projectFiles;
- FileNameList m_searchDirectories;
+ FilePath m_projectDir;
+ FilePath m_sysroot;
+ FilePathList m_projectFiles;
+ FilePathList m_searchDirectories;
PathMappingNode m_pathMapRoot;
mutable QHash<QString, CacheEntry> m_cache;
+ QrcUrlFinder m_qrcUrlFinder;
};
+QTCREATOR_UTILS_EXPORT FilePath chooseFileFromList(const FilePathList &candidates);
+
} // namespace Utils
diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index c34532a1de..0bdf3991c5 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -482,7 +482,7 @@ static bool matches(const QList<QRegExp> &exprList, const QString &filePath)
{
return Utils::anyOf(exprList, [&filePath](QRegExp reg) {
return (reg.exactMatch(filePath)
- || reg.exactMatch(FileName::fromString(filePath).fileName()));
+ || reg.exactMatch(FilePath::fromString(filePath).fileName()));
});
}
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index a476cd8d89..acf9c6190d 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -28,20 +28,27 @@
#include "algorithm.h"
#include "qtcassert.h"
+#include "qtcprocess.h"
#include <QDataStream>
#include <QDir>
#include <QDebug>
#include <QDateTime>
+#include <QOperatingSystemVersion>
#include <QRegExp>
#include <QTimer>
#include <QUrl>
+#include <qplatformdefs.h>
#ifdef QT_GUI_LIB
#include <QMessageBox>
#endif
#ifdef Q_OS_WIN
+// We need defines for Windows 8
+#undef _WIN32_WINNT
+#define _WIN32_WINNT _WIN32_WINNT_WIN8
+
#include <qt_windows.h>
#include <shlobj.h>
#endif
@@ -51,7 +58,7 @@
#endif
QT_BEGIN_NAMESPACE
-QDebug operator<<(QDebug dbg, const Utils::FileName &c)
+QDebug operator<<(QDebug dbg, const Utils::FilePath &c)
{
return dbg << c.toString();
}
@@ -60,6 +67,34 @@ QT_END_NAMESPACE
namespace Utils {
+/*! \class Utils::CommandLine
+
+ \brief The CommandLine class represents a command line of a QProcess
+ or similar utility.
+
+*/
+
+void CommandLine::addArg(const QString &arg, OsType osType)
+{
+ QtcProcess::addArg(&m_arguments, arg, osType);
+}
+
+void CommandLine::addArgs(const QStringList &inArgs, OsType osType)
+{
+ for (const QString &arg : inArgs)
+ addArg(arg, osType);
+}
+
+void CommandLine::addArgs(const QString &inArgs)
+{
+ QtcProcess::addArgs(&m_arguments, inArgs);
+}
+
+QString CommandLine::toUserOutput() const
+{
+ return m_executable.toUserOutput() + ' ' + m_arguments;
+}
+
/*! \class Utils::FileUtils
\brief The FileUtils class contains file and directory related convenience
@@ -74,7 +109,7 @@ namespace Utils {
Returns whether the operation succeeded.
*/
-bool FileUtils::removeRecursively(const FileName &filePath, QString *error)
+bool FileUtils::removeRecursively(const FilePath &filePath, QString *error)
{
QFileInfo fileInfo = filePath.toFileInfo();
if (!fileInfo.exists() && !fileInfo.isSymLink())
@@ -101,7 +136,7 @@ bool FileUtils::removeRecursively(const FileName &filePath, QString *error)
QStringList fileNames = dir.entryList(QDir::Files | QDir::Hidden
| QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
foreach (const QString &fileName, fileNames) {
- if (!removeRecursively(FileName(filePath).appendPath(fileName), error))
+ if (!removeRecursively(filePath.pathAppended(fileName), error))
return false;
}
if (!QDir::root().rmdir(dir.path())) {
@@ -140,7 +175,7 @@ bool FileUtils::removeRecursively(const FileName &filePath, QString *error)
Returns whether the operation succeeded.
*/
-bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgtFilePath,
+bool FileUtils::copyRecursively(const FilePath &srcFilePath, const FilePath &tgtFilePath,
QString *error, const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper)
{
QFileInfo srcFileInfo = srcFilePath.toFileInfo();
@@ -160,10 +195,8 @@ bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgt
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot
| QDir::Hidden | QDir::System);
foreach (const QString &fileName, fileNames) {
- FileName newSrcFilePath = srcFilePath;
- newSrcFilePath.appendPath(fileName);
- FileName newTgtFilePath = tgtFilePath;
- newTgtFilePath.appendPath(fileName);
+ const FilePath newSrcFilePath = srcFilePath.pathAppended(fileName);
+ const FilePath newTgtFilePath = tgtFilePath.pathAppended(fileName);
if (!copyRecursively(newSrcFilePath, newTgtFilePath, error, copyHelper))
return false;
}
@@ -185,23 +218,23 @@ bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgt
}
/*!
- If \a filePath is a directory, the function will recursively check all files and return
- true if one of them is newer than \a timeStamp. If \a filePath is a single file, true will
+ If this is a directory, the function will recursively check all files and return
+ true if one of them is newer than \a timeStamp. If this is a single file, true will
be returned if the file is newer than \a timeStamp.
Returns whether at least one file in \a filePath has a newer date than
\a timeStamp.
*/
-bool FileUtils::isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp)
+bool FilePath::isNewerThan(const QDateTime &timeStamp) const
{
- QFileInfo fileInfo = filePath.toFileInfo();
+ const QFileInfo fileInfo = toFileInfo();
if (!fileInfo.exists() || fileInfo.lastModified() >= timeStamp)
return true;
if (fileInfo.isDir()) {
- const QStringList dirContents = QDir(filePath.toString())
+ const QStringList dirContents = QDir(toString())
.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- foreach (const QString &curFileName, dirContents) {
- if (isFileNewerThan(FileName(filePath).appendPath(curFileName), timeStamp))
+ for (const QString &curFileName : dirContents) {
+ if (pathAppended(curFileName).isNewerThan(timeStamp))
return true;
}
}
@@ -218,30 +251,30 @@ bool FileUtils::isFileNewerThan(const FileName &filePath, const QDateTime &timeS
Returns the symlink target file path.
*/
-FileName FileUtils::resolveSymlinks(const FileName &path)
+FilePath FileUtils::resolveSymlinks(const FilePath &path)
{
QFileInfo f = path.toFileInfo();
int links = 16;
while (links-- && f.isSymLink())
f.setFile(f.dir(), f.symLinkTarget());
if (links <= 0)
- return FileName();
- return FileName::fromString(f.filePath());
+ return FilePath();
+ return FilePath::fromString(f.filePath());
}
/*!
- Recursively resolves possibly present symlinks in \a filePath.
+ Recursively resolves possibly present symlinks in this file name.
Unlike QFileInfo::canonicalFilePath(), this function will not return an empty
string if path doesn't exist.
Returns the canonical path.
*/
-FileName FileUtils::canonicalPath(const FileName &path)
+FilePath FilePath::canonicalPath() const
{
- const QString result = path.toFileInfo().canonicalFilePath();
+ const QString result = toFileInfo().canonicalFilePath();
if (result.isEmpty())
- return path;
- return FileName::fromString(result);
+ return *this;
+ return FilePath::fromString(result);
}
/*!
@@ -250,16 +283,16 @@ FileName FileUtils::canonicalPath(const FileName &path)
Returns the possibly shortened path with native separators.
*/
-QString FileUtils::shortNativePath(const FileName &path)
+QString FilePath::shortNativePath() const
{
if (HostOsInfo::isAnyUnixHost()) {
- const FileName home = FileName::fromString(QDir::cleanPath(QDir::homePath()));
- if (path.isChildOf(home)) {
+ const FilePath home = FilePath::fromString(QDir::cleanPath(QDir::homePath()));
+ if (isChildOf(home)) {
return QLatin1Char('~') + QDir::separator()
- + QDir::toNativeSeparators(path.relativeChildPath(home).toString());
+ + QDir::toNativeSeparators(relativeChildPath(home).toString());
}
}
- return path.toUserOutput();
+ return toUserOutput();
}
QString FileUtils::fileSystemFriendlyName(const QString &name)
@@ -293,10 +326,10 @@ QString FileUtils::qmakeFriendlyName(const QString &name)
return fileSystemFriendlyName(result);
}
-bool FileUtils::makeWritable(const FileName &path)
+bool FileUtils::makeWritable(const FilePath &path)
{
- const QString fileName = path.toString();
- return QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
+ const QString filePath = path.toString();
+ return QFile::setPermissions(filePath, QFile::permissions(filePath) | QFile::WriteUser);
}
// makes sure that capitalization of directories is canonical on Windows and OS X.
@@ -347,12 +380,80 @@ QString FileUtils::resolvePath(const QString &baseDir, const QString &fileName)
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
}
-FileName FileUtils::commonPath(const FileName &oldCommonPath, const FileName &fileName)
+FilePath FileUtils::commonPath(const FilePath &oldCommonPath, const FilePath &filePath)
{
- FileName newCommonPath = oldCommonPath;
- while (!newCommonPath.isEmpty() && !fileName.isChildOf(newCommonPath))
+ FilePath newCommonPath = oldCommonPath;
+ while (!newCommonPath.isEmpty() && !filePath.isChildOf(newCommonPath))
newCommonPath = newCommonPath.parentDir();
- return canonicalPath(newCommonPath);
+ return newCommonPath.canonicalPath();
+}
+
+// Copied from qfilesystemengine_win.cpp
+#ifdef Q_OS_WIN
+
+// File ID for Windows up to version 7.
+static inline QByteArray fileIdWin7(HANDLE handle)
+{
+ BY_HANDLE_FILE_INFORMATION info;
+ if (GetFileInformationByHandle(handle, &info)) {
+ char buffer[sizeof "01234567:0123456701234567\0"];
+ qsnprintf(buffer, sizeof(buffer), "%lx:%08lx%08lx",
+ info.dwVolumeSerialNumber,
+ info.nFileIndexHigh,
+ info.nFileIndexLow);
+ return QByteArray(buffer);
+ }
+ return QByteArray();
+}
+
+// File ID for Windows starting from version 8.
+static QByteArray fileIdWin8(HANDLE handle)
+{
+ QByteArray result;
+ FILE_ID_INFO infoEx;
+ if (GetFileInformationByHandleEx(handle,
+ static_cast<FILE_INFO_BY_HANDLE_CLASS>(18), // FileIdInfo in Windows 8
+ &infoEx, sizeof(FILE_ID_INFO))) {
+ result = QByteArray::number(infoEx.VolumeSerialNumber, 16);
+ result += ':';
+ // Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one.
+ result += QByteArray(reinterpret_cast<const char *>(&infoEx.FileId), int(sizeof(infoEx.FileId))).toHex();
+ }
+ return result;
+}
+
+static QByteArray fileIdWin(HANDLE fHandle)
+{
+ return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ?
+ fileIdWin8(HANDLE(fHandle)) : fileIdWin7(HANDLE(fHandle));
+}
+#endif
+
+QByteArray FileUtils::fileId(const FilePath &fileName)
+{
+ QByteArray result;
+
+#ifdef Q_OS_WIN
+ const HANDLE handle =
+ CreateFile((wchar_t*)fileName.toUserOutput().utf16(), 0,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (handle != INVALID_HANDLE_VALUE) {
+ result = fileIdWin(handle);
+ CloseHandle(handle);
+ }
+#else // Copied from qfilesystemengine_unix.cpp
+ if (Q_UNLIKELY(fileName.isEmpty()))
+ return result;
+
+ QT_STATBUF statResult;
+ if (QT_STAT(fileName.toString().toLocal8Bit().constData(), &statResult))
+ return result;
+ result = QByteArray::number(quint64(statResult.st_dev), 16);
+ result += ':';
+ result += QByteArray::number(quint64(statResult.st_ino));
+#endif
+ return result;
}
QByteArray FileReader::fetchQrc(const QString &fileName)
@@ -553,114 +654,131 @@ TempFileSaver::~TempFileSaver()
QFile::remove(m_fileName);
}
-/*! \class Utils::FileName
+/*! \class Utils::FilePath
- \brief The FileName class is a light-weight convenience class for filenames.
+ \brief The FilePath class is a light-weight convenience class for filenames.
On windows filenames are compared case insensitively.
*/
-FileName::FileName()
- : QString()
+FilePath::FilePath()
{
-
}
-/// Constructs a FileName from \a info
-FileName::FileName(const QFileInfo &info)
- : QString(info.absoluteFilePath())
+/// Constructs a FilePath from \a info
+FilePath FilePath::fromFileInfo(const QFileInfo &info)
{
+ return FilePath::fromString(info.absoluteFilePath());
}
/// \returns a QFileInfo
-QFileInfo FileName::toFileInfo() const
+QFileInfo FilePath::toFileInfo() const
{
- return QFileInfo(*this);
+ return QFileInfo(m_data);
+}
+
+FilePath FilePath::fromUrl(const QUrl &url)
+{
+ FilePath fn;
+ fn.m_url = url;
+ fn.m_data = url.path();
+ return fn;
}
/// \returns a QString for passing on to QString based APIs
-const QString &FileName::toString() const
+const QString &FilePath::toString() const
+{
+ return m_data;
+}
+
+QUrl FilePath::toUrl() const
{
- return *this;
+ return m_url;
}
/// \returns a QString to display to the user
/// Converts the separators to the native format
-QString FileName::toUserOutput() const
+QString FilePath::toUserOutput() const
{
- return QDir::toNativeSeparators(toString());
+ if (m_url.isEmpty())
+ return QDir::toNativeSeparators(toString());
+ return m_url.toString();
}
-QString FileName::fileName(int pathComponents) const
+QString FilePath::fileName(int pathComponents) const
{
if (pathComponents < 0)
- return *this;
+ return m_data;
const QChar slash = QLatin1Char('/');
- int i = lastIndexOf(slash);
+ int i = m_data.lastIndexOf(slash);
if (pathComponents == 0 || i == -1)
- return mid(i + 1);
+ return m_data.mid(i + 1);
int component = i + 1;
// skip adjacent slashes
- while (i > 0 && at(--i) == slash);
+ while (i > 0 && m_data.at(--i) == slash)
+ ;
while (i >= 0 && --pathComponents >= 0) {
- i = lastIndexOf(slash, i);
+ i = m_data.lastIndexOf(slash, i);
component = i + 1;
- while (i > 0 && at(--i) == slash);
+ while (i > 0 && m_data.at(--i) == slash)
+ ;
}
// If there are no more slashes before the found one, return the entire string
- if (i > 0 && lastIndexOf(slash, i) != -1)
- return mid(component);
- return *this;
+ if (i > 0 && m_data.lastIndexOf(slash, i) != -1)
+ return m_data.mid(component);
+ return m_data;
}
/// \returns a bool indicating whether a file with this
-/// FileName exists.
-bool FileName::exists() const
+/// FilePath exists.
+bool FilePath::exists() const
{
- return !isEmpty() && QFileInfo::exists(*this);
+ return !isEmpty() && QFileInfo::exists(m_data);
}
/// Find the parent directory of a given directory.
-/// Returns an empty FileName if the current directory is already
+/// Returns an empty FilePath if the current directory is already
/// a root level directory.
-/// \returns \a FileName with the last segment removed.
-FileName FileName::parentDir() const
+/// \returns \a FilePath with the last segment removed.
+FilePath FilePath::parentDir() const
{
const QString basePath = toString();
if (basePath.isEmpty())
- return FileName();
+ return FilePath();
const QDir base(basePath);
if (base.isRoot())
- return FileName();
+ return FilePath();
const QString path = basePath + QLatin1String("/..");
const QString parent = QDir::cleanPath(path);
- QTC_ASSERT(parent != path, return FileName());
+ QTC_ASSERT(parent != path, return FilePath());
- return FileName::fromString(parent);
+ return FilePath::fromString(parent);
}
-/// Constructs a FileName from \a filename
+/// Constructs a FilePath from \a filename
/// \a filename is not checked for validity.
-FileName FileName::fromString(const QString &filename)
+FilePath FilePath::fromString(const QString &filename)
{
- return FileName(filename);
+ FilePath fn;
+ fn.m_data = filename;
+ return fn;
}
-/// Constructs a FileName from \a fileName. The \a defaultExtension is appended
+/// Constructs a FilePath from \a filePath. The \a defaultExtension is appended
/// to \a filename if that does not have an extension already.
-/// \a fileName is not checked for validity.
-FileName FileName::fromString(const QString &filename, const QString &defaultExtension)
+/// \a filePath is not checked for validity.
+FilePath FilePath::fromStringWithExtension(const QString &filepath, const QString &defaultExtension)
{
- if (filename.isEmpty() || defaultExtension.isEmpty())
- return filename;
+ if (filepath.isEmpty() || defaultExtension.isEmpty())
+ return FilePath::fromString(filepath);
- QString rc = filename;
- QFileInfo fi(filename);
+ QString rc = filepath;
+ QFileInfo fi(filepath);
// Add extension unless user specified something else
const QChar dot = QLatin1Char('.');
if (!fi.fileName().contains(dot)) {
@@ -668,138 +786,148 @@ FileName FileName::fromString(const QString &filename, const QString &defaultExt
rc += dot;
rc += defaultExtension;
}
- return rc;
-}
-
-/// Constructs a FileName from \a fileName
-/// \a fileName is not checked for validity.
-FileName FileName::fromLatin1(const QByteArray &filename)
-{
- return FileName(QString::fromLatin1(filename));
+ return FilePath::fromString(rc);
}
-/// Constructs a FileName from \a fileName
-/// \a fileName is only passed through QDir::cleanPath
-FileName FileName::fromUserInput(const QString &filename)
+/// Constructs a FilePath from \a filePath
+/// \a filePath is only passed through QDir::cleanPath
+FilePath FilePath::fromUserInput(const QString &filePath)
{
- QString clean = QDir::cleanPath(filename);
+ QString clean = QDir::cleanPath(filePath);
if (clean.startsWith(QLatin1String("~/")))
clean = QDir::homePath() + clean.mid(1);
- return FileName(clean);
+ return FilePath::fromString(clean);
}
-/// Constructs a FileName from \a fileName, which is encoded as UTF-8.
-/// \a fileName is not checked for validity.
-FileName FileName::fromUtf8(const char *filename, int filenameSize)
+/// Constructs a FilePath from \a filePath, which is encoded as UTF-8.
+/// \a filePath is not checked for validity.
+FilePath FilePath::fromUtf8(const char *filename, int filenameSize)
{
- return FileName(QString::fromUtf8(filename, filenameSize));
+ return FilePath::fromString(QString::fromUtf8(filename, filenameSize));
}
-FileName::FileName(const QString &string)
- : QString(string)
+FilePath FilePath::fromVariant(const QVariant &variant)
{
+ if (variant.type() == QVariant::Url)
+ return FilePath::fromUrl(variant.toUrl());
+ return FilePath::fromString(variant.toString());
+}
+QVariant FilePath::toVariant() const
+{
+ if (!m_url.isEmpty())
+ return m_url;
+ return m_data;
}
-bool FileName::operator==(const FileName &other) const
+bool FilePath::operator==(const FilePath &other) const
{
- return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) == 0;
+ if (!m_url.isEmpty())
+ return m_url == other.m_url;
+ return QString::compare(m_data, other.m_data, HostOsInfo::fileNameCaseSensitivity()) == 0;
}
-bool FileName::operator!=(const FileName &other) const
+bool FilePath::operator!=(const FilePath &other) const
{
return !(*this == other);
}
-bool FileName::operator<(const FileName &other) const
+bool FilePath::operator<(const FilePath &other) const
{
- return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) < 0;
+ if (!m_url.isEmpty())
+ return m_url < other.m_url;
+ return QString::compare(m_data, other.m_data, HostOsInfo::fileNameCaseSensitivity()) < 0;
}
-bool FileName::operator<=(const FileName &other) const
+bool FilePath::operator<=(const FilePath &other) const
{
- return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) <= 0;
+ return !(other < *this);
}
-bool FileName::operator>(const FileName &other) const
+bool FilePath::operator>(const FilePath &other) const
{
return other < *this;
}
-bool FileName::operator>=(const FileName &other) const
+bool FilePath::operator>=(const FilePath &other) const
{
- return other <= *this;
+ return !(*this < other);
}
-FileName FileName::operator+(const QString &s) const
+FilePath FilePath::operator+(const QString &s) const
{
- FileName result(*this);
- result.appendString(s);
- return result;
+ return FilePath::fromString(m_data + s);
}
-/// \returns whether FileName is a child of \a s
-bool FileName::isChildOf(const FileName &s) const
+/// \returns whether FilePath is a child of \a s
+bool FilePath::isChildOf(const FilePath &s) const
{
if (s.isEmpty())
return false;
- if (!QString::startsWith(s, HostOsInfo::fileNameCaseSensitivity()))
+ if (!m_data.startsWith(s.m_data, HostOsInfo::fileNameCaseSensitivity()))
return false;
- if (size() <= s.size())
+ if (m_data.size() <= s.m_data.size())
return false;
// s is root, '/' was already tested in startsWith
- if (s.QString::endsWith(QLatin1Char('/')))
+ if (s.m_data.endsWith(QLatin1Char('/')))
return true;
// s is a directory, next character should be '/' (/tmpdir is NOT a child of /tmp)
- return at(s.size()) == QLatin1Char('/');
+ return m_data.at(s.m_data.size()) == QLatin1Char('/');
}
/// \overload
-bool FileName::isChildOf(const QDir &dir) const
+bool FilePath::isChildOf(const QDir &dir) const
{
- return isChildOf(FileName::fromString(dir.absolutePath()));
+ return isChildOf(FilePath::fromString(dir.absolutePath()));
}
-/// \returns whether FileName endsWith \a s
-bool FileName::endsWith(const QString &s) const
+/// \returns whether FilePath endsWith \a s
+bool FilePath::endsWith(const QString &s) const
{
- return QString::endsWith(s, HostOsInfo::fileNameCaseSensitivity());
+ return m_data.endsWith(s, HostOsInfo::fileNameCaseSensitivity());
}
-/// \returns the relativeChildPath of FileName to parent if FileName is a child of parent
-/// \note returns a empty FileName if FileName is not a child of parent
+bool FilePath::isLocal() const
+{
+ return m_url.isEmpty() || m_url.isLocalFile();
+}
+
+/// \returns the relativeChildPath of FilePath to parent if FilePath is a child of parent
+/// \note returns a empty FilePath if FilePath is not a child of parent
/// That is, this never returns a path starting with "../"
-FileName FileName::relativeChildPath(const FileName &parent) const
+FilePath FilePath::relativeChildPath(const FilePath &parent) const
{
if (!isChildOf(parent))
- return FileName();
- return FileName(QString::mid(parent.size() + 1, -1));
+ return FilePath();
+ return FilePath::fromString(m_data.mid(parent.m_data.size() + 1, -1));
}
-/// Appends \a s, ensuring a / between the parts
-FileName &FileName::appendPath(const QString &s)
+FilePath FilePath::pathAppended(const QString &str) const
{
- if (s.isEmpty())
- return *this;
- if (!isEmpty() && !QString::endsWith(QLatin1Char('/')))
- appendString(QLatin1Char('/'));
- appendString(s);
- return *this;
+ FilePath fn = *this;
+ if (str.isEmpty())
+ return fn;
+ if (!isEmpty() && !m_data.endsWith(QLatin1Char('/')))
+ fn.m_data.append('/');
+ fn.m_data.append(str);
+ return fn;
}
-FileName &FileName::appendString(const QString &str)
+FilePath FilePath::stringAppended(const QString &str) const
{
- QString::append(str);
- return *this;
+ FilePath fn = *this;
+ fn.m_data.append(str);
+ return fn;
}
-FileName &FileName::appendString(QChar str)
+uint FilePath::hash(uint seed) const
{
- QString::append(str);
- return *this;
+ if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
+ return qHash(m_data.toUpper(), seed);
+ return qHash(m_data, seed);
}
-QTextStream &operator<<(QTextStream &s, const FileName &fn)
+QTextStream &operator<<(QTextStream &s, const FilePath &fn)
{
return s << fn.toString();
}
@@ -813,14 +941,4 @@ void withNtfsPermissions(const std::function<void()> &task)
qt_ntfs_permission_lookup--;
}
#endif
-
} // namespace Utils
-
-QT_BEGIN_NAMESPACE
-uint qHash(const Utils::FileName &a)
-{
- if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
- return qHash(a.toString().toUpper());
- return qHash(a.toString());
-}
-QT_END_NAMESPACE
diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h
index aa6310c760..ec018b9c3b 100644
--- a/src/libs/utils/fileutils.h
+++ b/src/libs/utils/fileutils.h
@@ -33,11 +33,12 @@
#include <QXmlStreamWriter> // Mac.
#include <QMetaType>
#include <QStringList>
+#include <QUrl>
#include <functional>
#include <memory>
-namespace Utils {class FileName; }
+namespace Utils { class FilePath; }
QT_BEGIN_NAMESPACE
class QDataStream;
@@ -49,7 +50,7 @@ class QTemporaryFile;
class QTextStream;
class QWidget;
-QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FileName &c);
+QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FilePath &c);
// for withNtfsPermissions
#ifdef Q_OS_WIN
@@ -60,76 +61,114 @@ QT_END_NAMESPACE
namespace Utils {
-class QTCREATOR_UTILS_EXPORT FileName : private QString
+class QTCREATOR_UTILS_EXPORT FilePath
{
public:
- FileName();
- explicit FileName(const QFileInfo &info);
- QFileInfo toFileInfo() const;
- static FileName fromString(const QString &filename);
- static FileName fromString(const QString &filename, const QString &defaultExtension);
- static FileName fromLatin1(const QByteArray &filename);
- static FileName fromUserInput(const QString &filename);
- static FileName fromUtf8(const char *filename, int filenameSize = -1);
+ FilePath();
+
+ static FilePath fromString(const QString &filepath);
+ static FilePath fromFileInfo(const QFileInfo &info);
+ static FilePath fromStringWithExtension(const QString &filepath, const QString &defaultExtension);
+ static FilePath fromUserInput(const QString &filepath);
+ static FilePath fromUtf8(const char *filepath, int filepathSize = -1);
+ static FilePath fromVariant(const QVariant &variant);
+
const QString &toString() const;
+ QFileInfo toFileInfo() const;
+ QVariant toVariant() const;
+
QString toUserOutput() const;
+ QString shortNativePath() const;
+
QString fileName(int pathComponents = 0) const;
bool exists() const;
- FileName parentDir() const;
+ FilePath parentDir() const;
- bool operator==(const FileName &other) const;
- bool operator!=(const FileName &other) const;
- bool operator<(const FileName &other) const;
- bool operator<=(const FileName &other) const;
- bool operator>(const FileName &other) const;
- bool operator>=(const FileName &other) const;
- FileName operator+(const QString &s) const;
+ bool operator==(const FilePath &other) const;
+ bool operator!=(const FilePath &other) const;
+ bool operator<(const FilePath &other) const;
+ bool operator<=(const FilePath &other) const;
+ bool operator>(const FilePath &other) const;
+ bool operator>=(const FilePath &other) const;
+ FilePath operator+(const QString &s) const;
- bool isChildOf(const FileName &s) const;
+ bool isChildOf(const FilePath &s) const;
bool isChildOf(const QDir &dir) const;
bool endsWith(const QString &s) const;
+ bool isLocal() const;
+
+ bool isNewerThan(const QDateTime &timeStamp) const;
+
+ FilePath relativeChildPath(const FilePath &parent) const;
+ FilePath pathAppended(const QString &str) const;
+ FilePath stringAppended(const QString &str) const;
+
+ FilePath canonicalPath() const;
+
+ void clear() { m_data.clear(); }
+ bool isEmpty() const { return m_data.isEmpty(); }
+
+ uint hash(uint seed) const;
+
+ // NOTE: FileName operations on FilePath created from URL currenly
+ // do not work except for .toVariant() and .toUrl().
+ static FilePath fromUrl(const QUrl &url);
+ QUrl toUrl() const;
- FileName relativeChildPath(const FileName &parent) const;
- FileName &appendPath(const QString &s);
- FileName &appendString(const QString &str);
- FileName &appendString(QChar str);
-
- using QString::chop;
- using QString::clear;
- using QString::count;
- using QString::isEmpty;
- using QString::isNull;
- using QString::length;
- using QString::size;
private:
- FileName(const QString &string);
+ QString m_data;
+ QUrl m_url;
};
-QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FileName &fn);
+QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FilePath &fn);
+
+using FilePathList = QList<FilePath>;
+
+using FileName = FilePath;
+using FileNameList = FilePathList;
-using FileNameList = QList<FileName>;
+class QTCREATOR_UTILS_EXPORT CommandLine
+{
+public:
+ CommandLine() {}
+
+ CommandLine(const FilePath &executable, const QString &arguments)
+ : m_executable(executable), m_arguments(arguments)
+ {}
+
+ void addArg(const QString &arg, OsType osType = HostOsInfo::hostOs());
+ void addArgs(const QStringList &inArgs, OsType osType = HostOsInfo::hostOs());
+ void addArgs(const QString &inArgs);
+
+ QString toUserOutput() const;
+
+ FilePath executable() const { return m_executable; }
+ QString arguments() const { return m_arguments; }
+
+private:
+ FilePath m_executable;
+ QString m_arguments;
+};
class QTCREATOR_UTILS_EXPORT FileUtils {
public:
- static bool removeRecursively(const FileName &filePath, QString *error = nullptr);
+ static bool removeRecursively(const FilePath &filePath, QString *error = nullptr);
static bool copyRecursively(
- const FileName &srcFilePath, const FileName &tgtFilePath, QString *error = nullptr,
+ const FilePath &srcFilePath, const FilePath &tgtFilePath, QString *error = nullptr,
const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper = nullptr);
- static bool isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp);
- static FileName resolveSymlinks(const FileName &path);
- static FileName canonicalPath(const FileName &path);
- static QString shortNativePath(const FileName &path);
+ static FilePath resolveSymlinks(const FilePath &path);
static QString fileSystemFriendlyName(const QString &name);
static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0);
static QString qmakeFriendlyName(const QString &name);
- static bool makeWritable(const FileName &path);
+ static bool makeWritable(const FilePath &path);
static QString normalizePathName(const QString &name);
static bool isRelativePath(const QString &fileName);
static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
static QString resolvePath(const QString &baseDir, const QString &fileName);
- static FileName commonPath(const FileName &oldCommonPath, const FileName &fileName);
+ static FilePath commonPath(const FilePath &oldCommonPath, const FilePath &fileName);
+ static QByteArray fileId(const FilePath &fileName);
};
// for actually finding out if e.g. directories are writable on Windows
@@ -240,16 +279,14 @@ private:
bool m_autoRemove = true;
};
-} // namespace Utils
+inline uint qHash(const Utils::FilePath &a, uint seed = 0) { return a.hash(seed); }
-QT_BEGIN_NAMESPACE
-QTCREATOR_UTILS_EXPORT uint qHash(const Utils::FileName &a);
-QT_END_NAMESPACE
+} // namespace Utils
namespace std {
-template<> struct hash<Utils::FileName>
+template<> struct hash<Utils::FilePath>
{
- using argument_type = Utils::FileName;
+ using argument_type = Utils::FilePath;
using result_type = size_t;
result_type operator()(const argument_type &fn) const
{
@@ -260,4 +297,4 @@ template<> struct hash<Utils::FileName>
};
} // namespace std
-Q_DECLARE_METATYPE(Utils::FileName)
+Q_DECLARE_METATYPE(Utils::FilePath)
diff --git a/src/libs/utils/genericconstants.h b/src/libs/utils/genericconstants.h
new file mode 100644
index 0000000000..a380fc15ba
--- /dev/null
+++ b/src/libs/utils/genericconstants.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the 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 Utils {
+
+namespace Constants {
+
+const char BEAUTIFIER_SETTINGS_GROUP[] = "Beautifier";
+const char BEAUTIFIER_GENERAL_GROUP[] = "General";
+const char BEAUTIFIER_AUTO_FORMAT_ON_SAVE[] = "autoFormatOnSave";
+
+} // namespace Constants
+} // namespace Utils
diff --git a/src/libs/utils/highlightingitemdelegate.cpp b/src/libs/utils/highlightingitemdelegate.cpp
index e253689843..4874200e86 100644
--- a/src/libs/utils/highlightingitemdelegate.cpp
+++ b/src/libs/utils/highlightingitemdelegate.cpp
@@ -114,7 +114,8 @@ int HighlightingItemDelegate::drawLineNumber(QPainter *painter, const QStyleOpti
const bool isSelected = option.state & QStyle::State_Selected;
const QString lineText = QString::number(lineNumber);
const int minimumLineNumberDigits = qMax(kMinimumLineNumberDigits, lineText.count());
- const int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, '0'));
+ const int fontWidth =
+ painter->fontMetrics().horizontalAdvance(QString(minimumLineNumberDigits, '0'));
const int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth
+ lineNumberAreaHorizontalPadding;
QRect lineNumberAreaRect(rect);
diff --git a/src/libs/ssh/images/dir.png b/src/libs/utils/images/dir.png
index 57cec6bcd3..57cec6bcd3 100644
--- a/src/libs/ssh/images/dir.png
+++ b/src/libs/utils/images/dir.png
Binary files differ
diff --git a/src/libs/utils/images/pinned.png b/src/libs/utils/images/pinned.png
new file mode 100644
index 0000000000..dc96231ca4
--- /dev/null
+++ b/src/libs/utils/images/pinned.png
Binary files differ
diff --git a/src/libs/utils/images/pinned@2x.png b/src/libs/utils/images/pinned@2x.png
new file mode 100644
index 0000000000..d7c59e83ce
--- /dev/null
+++ b/src/libs/utils/images/pinned@2x.png
Binary files differ
diff --git a/src/libs/utils/images/settings.png b/src/libs/utils/images/settings.png
new file mode 100644
index 0000000000..2621923499
--- /dev/null
+++ b/src/libs/utils/images/settings.png
Binary files differ
diff --git a/src/libs/utils/images/settings@2x.png b/src/libs/utils/images/settings@2x.png
new file mode 100644
index 0000000000..456f0cc56b
--- /dev/null
+++ b/src/libs/utils/images/settings@2x.png
Binary files differ
diff --git a/src/plugins/autotest/images/sort.png b/src/libs/utils/images/sort_alphabetically.png
index c15eb56d50..c15eb56d50 100644
--- a/src/plugins/autotest/images/sort.png
+++ b/src/libs/utils/images/sort_alphabetically.png
Binary files differ
diff --git a/src/plugins/autotest/images/sort@2x.png b/src/libs/utils/images/sort_alphabetically@2x.png
index 1a2e5d9520..1a2e5d9520 100644
--- a/src/plugins/autotest/images/sort@2x.png
+++ b/src/libs/utils/images/sort_alphabetically@2x.png
Binary files differ
diff --git a/src/libs/utils/images/toggleprogressdetails.png b/src/libs/utils/images/toggleprogressdetails.png
new file mode 100644
index 0000000000..b2353cd9d0
--- /dev/null
+++ b/src/libs/utils/images/toggleprogressdetails.png
Binary files differ
diff --git a/src/libs/utils/images/toggleprogressdetails@2x.png b/src/libs/utils/images/toggleprogressdetails@2x.png
new file mode 100644
index 0000000000..28a212491e
--- /dev/null
+++ b/src/libs/utils/images/toggleprogressdetails@2x.png
Binary files differ
diff --git a/src/libs/ssh/images/unknownfile.png b/src/libs/utils/images/unknownfile.png
index 88f77592d1..88f77592d1 100644
--- a/src/libs/ssh/images/unknownfile.png
+++ b/src/libs/utils/images/unknownfile.png
Binary files differ
diff --git a/src/libs/utils/listmodel.h b/src/libs/utils/listmodel.h
new file mode 100644
index 0000000000..5f4de811e6
--- /dev/null
+++ b/src/libs/utils/listmodel.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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 "utils_global.h"
+#include "treemodel.h"
+
+namespace Utils {
+
+template <class ChildType>
+class BaseListModel : public TreeModel<TypedTreeItem<ChildType>, ChildType>
+{
+public:
+ using BaseModel = TreeModel<TypedTreeItem<ChildType>, ChildType>;
+ using BaseModel::rootItem;
+
+ explicit BaseListModel(QObject *parent = nullptr) : BaseModel(parent) {}
+
+ int itemCount() const { return rootItem()->childCount(); }
+ ChildType *itemAt(int row) const { return rootItem()->childAt(row); }
+
+ void appendItem(ChildType *item) { rootItem()->appendChild(item); }
+
+ template <class Predicate>
+ void forItems(const Predicate &pred) const
+ {
+ rootItem()->forFirstLevelChildren(pred);
+ }
+
+ template <class Predicate>
+ ChildType *findItem(const Predicate &pred) const
+ {
+ return rootItem()->findFirstLevelChild(pred);
+ }
+
+ void sortItems(const std::function<bool(const ChildType *, const ChildType *)> &lessThan)
+ {
+ return rootItem()->sortChildren([lessThan](const TreeItem *a, const TreeItem *b) {
+ return lessThan(static_cast<const ChildType *>(a), static_cast<const ChildType *>(b));
+ });
+ }
+
+ int indexOf(const ChildType *item) const { return rootItem()->indexOf(item); }
+
+ void clear() { rootItem()->removeChildren(); }
+
+ using const_iterator = typename QVector<TreeItem *>::const_iterator;
+ const_iterator begin() const { return rootItem()->begin(); }
+ const_iterator end() const { return rootItem()->end(); }
+
+};
+
+template <class ItemData>
+class ListItem : public TreeItem
+{
+public:
+ ItemData itemData;
+};
+
+template <class ItemData>
+class ListModel : public BaseListModel<ListItem<ItemData>>
+{
+public:
+ using ChildType = ListItem<ItemData>;
+ using BaseModel = BaseListModel<ChildType>;
+
+ explicit ListModel(QObject *parent = nullptr) : BaseModel(parent) {}
+
+ const ItemData &dataAt(int row) const
+ {
+ static const ItemData dummyData = {};
+ auto item = BaseModel::itemAt(row);
+ return item ? item->itemData : dummyData;
+ }
+
+ ChildType *findItemByData(const std::function<bool(const ItemData &)> &pred) const
+ {
+ return BaseModel::rootItem()->findFirstLevelChild([pred](ChildType *child) {
+ return pred(child->itemData);
+ });
+ }
+
+ void destroyItems(const std::function<bool(const ItemData &)> &pred)
+ {
+ QList<ChildType *> toDestroy;
+ BaseModel::rootItem()->forFirstLevelChildren([pred, &toDestroy](ChildType *item) {
+ if (pred(item->itemData))
+ toDestroy.append(item);
+ });
+ for (ChildType *item : toDestroy)
+ this->destroyItem(item);
+ }
+
+ ItemData *findData(const std::function<bool(const ItemData &)> &pred) const
+ {
+ ChildType *item = findItemByData(pred);
+ return item ? &item->itemData : nullptr;
+ }
+
+ void forItems(const std::function<void(ItemData &)> &func) const
+ {
+ BaseModel::rootItem()->forFirstLevelChildren([func](ChildType *child) {
+ func(child->itemData);
+ });
+ }
+
+ ChildType *appendItem(const ItemData &data)
+ {
+ auto item = new ChildType;
+ item->itemData = data;
+ BaseModel::rootItem()->appendChild(item);
+ return item;
+ }
+
+ QVariant data(const QModelIndex &idx, int role) const override
+ {
+ TreeItem *item = BaseModel::itemForIndex(idx);
+ if (item && item->parent() == BaseModel::rootItem())
+ return itemData(static_cast<ChildType *>(item)->itemData, idx.column(), role);
+ return {};
+ }
+
+ Qt::ItemFlags flags(const QModelIndex &idx) const override
+ {
+ TreeItem *item = BaseModel::itemForIndex(idx);
+ if (item && item->parent() == BaseModel::rootItem())
+ return itemFlags(static_cast<ChildType *>(item)->itemData, idx.column());
+ return {};
+ }
+
+ virtual QVariant itemData(const ItemData &idata, int column, int role) const
+ {
+ if (m_dataAccessor)
+ return m_dataAccessor(idata, column, role);
+ return {};
+ }
+
+ virtual Qt::ItemFlags itemFlags(const ItemData &idata, int column) const
+ {
+ if (m_flagsAccessor)
+ return m_flagsAccessor(idata, column);
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ }
+
+ void setDataAccessor(const std::function<QVariant(const ItemData &, int, int)> &accessor)
+ {
+ m_dataAccessor = accessor;
+ }
+
+ void setFlagsAccessor(const std::function<Qt::ItemFlags(const ItemData &, int)> &accessor)
+ {
+ m_flagsAccessor = accessor;
+ }
+
+private:
+ std::function<QVariant(const ItemData &, int, int)> m_dataAccessor;
+ std::function<Qt::ItemFlags(const ItemData &, int)> m_flagsAccessor;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp
index eb3f05e175..a41fbde31d 100644
--- a/src/libs/utils/macroexpander.cpp
+++ b/src/libs/utils/macroexpander.cpp
@@ -290,11 +290,39 @@ QString MacroExpander::expand(const QString &stringWithVariables) const
return res;
}
+FilePath MacroExpander::expand(const FilePath &fileNameWithVariables) const
+{
+ return FilePath::fromString(expand(fileNameWithVariables.toString()));
+}
+
QByteArray MacroExpander::expand(const QByteArray &stringWithVariables) const
{
return expand(QString::fromLatin1(stringWithVariables)).toLatin1();
}
+QVariant MacroExpander::expandVariant(const QVariant &v) const
+{
+ const auto type = QMetaType::Type(v.type());
+ if (type == QMetaType::QString) {
+ return expand(v.toString());
+ } else if (type == QMetaType::QStringList) {
+ return Utils::transform(v.toStringList(),
+ [this](const QString &s) -> QVariant { return expand(s); });
+ } else if (type == QMetaType::QVariantList) {
+ return Utils::transform(v.toList(), [this](const QVariant &v) { return expandVariant(v); });
+ } else if (type == QMetaType::QVariantMap) {
+ const auto map = v.toMap();
+ QVariantMap result;
+ QMapIterator<QString, QVariant> it(map);
+ while (it.hasNext()) {
+ it.next();
+ result.insert(it.key(), expandVariant(it.value()));
+ }
+ return result;
+ }
+ return v;
+}
+
QString MacroExpander::expandProcessArgs(const QString &argsWithVariables) const
{
return QtcProcess::expandMacros(argsWithVariables, d);
@@ -394,7 +422,7 @@ void MacroExpander::registerFileVariables(const QByteArray &prefix,
registerVariable(prefix + kFileNamePostfix,
tr("%1: File name without path.").arg(heading),
- [base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : FileName::fromString(tmp).fileName(); },
+ [base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : FilePath::fromString(tmp).fileName(); },
visibleInChooser);
registerVariable(prefix + kFileBaseNamePostfix,
diff --git a/src/libs/utils/macroexpander.h b/src/libs/utils/macroexpander.h
index f17ae86b8c..70448069c5 100644
--- a/src/libs/utils/macroexpander.h
+++ b/src/libs/utils/macroexpander.h
@@ -37,6 +37,7 @@ namespace Utils {
namespace Internal { class MacroExpanderPrivate; }
+class FilePath;
class MacroExpander;
using MacroExpanderProvider = std::function<MacroExpander *()>;
using MacroExpanderProviders = QVector<MacroExpanderProvider>;
@@ -55,7 +56,9 @@ public:
QString value(const QByteArray &variable, bool *found = nullptr) const;
QString expand(const QString &stringWithVariables) const;
+ FilePath expand(const FilePath &fileNameWithVariables) const;
QByteArray expand(const QByteArray &stringWithVariables) const;
+ QVariant expandVariant(const QVariant &v) const;
QString expandProcessArgs(const QString &argsWithVariables) const;
diff --git a/src/libs/utils/mimetypes/mimeprovider.cpp b/src/libs/utils/mimetypes/mimeprovider.cpp
index d444aa899c..46d3eb71bd 100644
--- a/src/libs/utils/mimetypes/mimeprovider.cpp
+++ b/src/libs/utils/mimetypes/mimeprovider.cpp
@@ -803,11 +803,7 @@ void MimeXMLProvider::ensureLoaded()
// if (!fdoXmlFound) {
// // We could instead install the file as part of installing Qt?
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
const char freedesktopOrgXml[] = ":/qt-project.org/qmime/packages/freedesktop.org.xml";
-#else
- const char freedesktopOrgXml[] = ":/qt-project.org/qmime/freedesktop.org.xml";
-#endif
allFiles.prepend(QLatin1String(freedesktopOrgXml));
// }
diff --git a/src/libs/utils/newclasswidget.cpp b/src/libs/utils/newclasswidget.cpp
index 8700b8204c..9205d435dc 100644
--- a/src/libs/utils/newclasswidget.cpp
+++ b/src/libs/utils/newclasswidget.cpp
@@ -88,7 +88,7 @@ NewClassWidget::NewClassWidget(QWidget *parent) :
connect(d->m_ui.classLineEdit, &QLineEdit::textEdited,
this, &NewClassWidget::classNameEdited);
connect(d->m_ui.baseClassComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &NewClassWidget::suggestClassNameFromBase);
connect(d->m_ui.baseClassComboBox, &QComboBox::editTextChanged,
this, &NewClassWidget::slotValidChanged);
diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp
index ec85a748a6..7926422da6 100644
--- a/src/libs/utils/outputformatter.cpp
+++ b/src/libs/utils/outputformatter.cpp
@@ -78,7 +78,8 @@ void OutputFormatter::appendMessage(const QString &text, OutputFormat format)
void OutputFormatter::appendMessage(const QString &text, const QTextCharFormat &format)
{
- foreach (const FormattedText &output, parseAnsi(text, format))
+ const QList<FormattedText> formattedTextList = parseAnsi(text, format);
+ for (const FormattedText &output : formattedTextList)
append(output.text, output.format);
}
diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h
index c516ca14e2..1db42453d5 100644
--- a/src/libs/utils/outputformatter.h
+++ b/src/libs/utils/outputformatter.h
@@ -62,6 +62,9 @@ public:
virtual void clear() {}
void setBoldFontEnabled(bool enabled);
+signals:
+ void contentChanged();
+
protected:
void initFormats();
virtual void clearLastLine();
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index e29b0c7663..f08391d6a6 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -193,14 +193,14 @@ QString PathChooserPrivate::expandedPath(const QString &input) const
if (m_macroExpander)
expandedInput = m_macroExpander->expand(expandedInput);
- const QString path = FileName::fromUserInput(expandedInput).toString();
+ const QString path = FilePath::fromUserInput(expandedInput).toString();
if (path.isEmpty())
return path;
switch (m_acceptingKind) {
case PathChooser::Command:
case PathChooser::ExistingCommand: {
- const FileName expanded = m_environment.searchInPath(path, {FileName::fromString(m_baseDirectory)});
+ const FilePath expanded = m_environment.searchInPath(path, {FilePath::fromString(m_baseDirectory)});
return expanded.isEmpty() ? path : expanded.toString();
}
case PathChooser::Any:
@@ -293,12 +293,12 @@ void PathChooser::setBaseDirectory(const QString &directory)
triggerChanged();
}
-FileName PathChooser::baseFileName() const
+FilePath PathChooser::baseFileName() const
{
- return FileName::fromString(d->m_baseDirectory);
+ return FilePath::fromString(d->m_baseDirectory);
}
-void PathChooser::setBaseFileName(const FileName &base)
+void PathChooser::setBaseFileName(const FilePath &base)
{
setBaseDirectory(base.toString());
}
@@ -323,14 +323,14 @@ QString PathChooser::path() const
return fileName().toString();
}
-FileName PathChooser::rawFileName() const
+FilePath PathChooser::rawFileName() const
{
- return FileName::fromString(QDir::fromNativeSeparators(d->m_lineEdit->text()));
+ return FilePath::fromString(QDir::fromNativeSeparators(d->m_lineEdit->text()));
}
-FileName PathChooser::fileName() const
+FilePath PathChooser::fileName() const
{
- return FileName::fromUserInput(d->expandedPath(rawFileName().toString()));
+ return FilePath::fromUserInput(d->expandedPath(rawFileName().toString()));
}
// FIXME: try to remove again
@@ -352,7 +352,7 @@ void PathChooser::setPath(const QString &path)
d->m_lineEdit->setTextKeepingActiveCursor(QDir::toNativeSeparators(path));
}
-void PathChooser::setFileName(const FileName &fn)
+void PathChooser::setFileName(const FilePath &fn)
{
d->m_lineEdit->setTextKeepingActiveCursor(fn.toUserOutput());
}
diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h
index 73939e1bf4..09d98e71c8 100644
--- a/src/libs/utils/pathchooser.h
+++ b/src/libs/utils/pathchooser.h
@@ -55,8 +55,8 @@ class QTCREATOR_UTILS_EXPORT PathChooser : public QWidget
Q_PROPERTY(QStringList commandVersionArguments READ commandVersionArguments WRITE setCommandVersionArguments)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly DESIGNABLE true)
// Designer does not know this type, so force designable to false:
- Q_PROPERTY(Utils::FileName fileName READ fileName WRITE setFileName DESIGNABLE false)
- Q_PROPERTY(Utils::FileName baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false)
+ Q_PROPERTY(Utils::FilePath fileName READ fileName WRITE setFileName DESIGNABLE false)
+ Q_PROPERTY(Utils::FilePath baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false)
Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor DESIGNABLE true)
Q_PROPERTY(QColor okColor READ okColor WRITE setOkColor DESIGNABLE true)
@@ -93,8 +93,8 @@ public:
QString path() const;
QString rawPath() const; // The raw unexpanded input.
- FileName rawFileName() const; // The raw unexpanded input.
- FileName fileName() const;
+ FilePath rawFileName() const; // The raw unexpanded input.
+ FilePath fileName() const;
static QString expandedDirectory(const QString &input, const Environment &env,
const QString &baseDir);
@@ -102,8 +102,8 @@ public:
QString baseDirectory() const;
void setBaseDirectory(const QString &directory);
- FileName baseFileName() const;
- void setBaseFileName(const FileName &base);
+ FilePath baseFileName() const;
+ void setBaseFileName(const FilePath &base);
void setEnvironment(const Environment &env);
@@ -172,7 +172,7 @@ signals:
public slots:
void setPath(const QString &);
- void setFileName(const FileName &);
+ void setFileName(const FilePath &);
void setErrorColor(const QColor &errorColor);
void setOkColor(const QColor &okColor);
diff --git a/src/libs/utils/persistentsettings.cpp b/src/libs/utils/persistentsettings.cpp
index db0f8d0db5..92d32109ea 100644
--- a/src/libs/utils/persistentsettings.cpp
+++ b/src/libs/utils/persistentsettings.cpp
@@ -341,7 +341,7 @@ QVariantMap PersistentSettingsReader::restoreValues() const
return m_valueMap;
}
-bool PersistentSettingsReader::load(const FileName &fileName)
+bool PersistentSettingsReader::load(const FilePath &fileName)
{
m_valueMap.clear();
@@ -409,7 +409,7 @@ static void writeVariantValue(QXmlStreamWriter &w, const Context &ctx,
}
}
-PersistentSettingsWriter::PersistentSettingsWriter(const FileName &fileName, const QString &docType) :
+PersistentSettingsWriter::PersistentSettingsWriter(const FilePath &fileName, const QString &docType) :
m_fileName(fileName), m_docType(docType)
{ }
@@ -438,7 +438,7 @@ bool PersistentSettingsWriter::save(const QVariantMap &data, QWidget *parent) co
}
#endif // QT_GUI_LIB
-FileName PersistentSettingsWriter::fileName() const
+FilePath PersistentSettingsWriter::fileName() const
{ return m_fileName; }
//** * @brief Set contents of file (e.g. from data read from it). */
diff --git a/src/libs/utils/persistentsettings.h b/src/libs/utils/persistentsettings.h
index a7255dcb8a..92dbf0d8c9 100644
--- a/src/libs/utils/persistentsettings.h
+++ b/src/libs/utils/persistentsettings.h
@@ -42,7 +42,7 @@ public:
PersistentSettingsReader();
QVariant restoreValue(const QString &variable, const QVariant &defaultValue = QVariant()) const;
QVariantMap restoreValues() const;
- bool load(const FileName &fileName);
+ bool load(const FilePath &fileName);
private:
QMap<QString, QVariant> m_valueMap;
@@ -51,7 +51,7 @@ private:
class QTCREATOR_UTILS_EXPORT PersistentSettingsWriter
{
public:
- PersistentSettingsWriter(const FileName &fileName, const QString &docType);
+ PersistentSettingsWriter(const FilePath &fileName, const QString &docType);
~PersistentSettingsWriter();
bool save(const QVariantMap &data, QString *errorString) const;
@@ -59,14 +59,14 @@ public:
bool save(const QVariantMap &data, QWidget *parent) const;
#endif
- FileName fileName() const;
+ FilePath fileName() const;
void setContents(const QVariantMap &data);
private:
bool write(const QVariantMap &data, QString *errorString) const;
- const FileName m_fileName;
+ const FilePath m_fileName;
const QString m_docType;
mutable QMap<QString, QVariant> m_savedData;
};
diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp
index a449fe1285..56127ac479 100644
--- a/src/libs/utils/projectintropage.cpp
+++ b/src/libs/utils/projectintropage.cpp
@@ -101,7 +101,7 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) :
connect(d->m_ui.nameLineEdit, &FancyLineEdit::validReturnPressed,
this, &ProjectIntroPage::slotActivated);
connect(d->m_ui.projectComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ProjectIntroPage::slotChanged);
setProperty(SHORT_TITLE_PROPERTY, tr("Location"));
diff --git a/src/libs/utils/qrcparser.cpp b/src/libs/utils/qrcparser.cpp
new file mode 100644
index 0000000000..21904d3716
--- /dev/null
+++ b/src/libs/utils/qrcparser.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qrcparser.h"
+
+#include <utils/qtcassert.h>
+
+#include <QCoreApplication>
+#include <QDir>
+#include <QDomDocument>
+#include <QFile>
+#include <QFileInfo>
+#include <QLocale>
+#include <QLoggingCategory>
+#include <QMultiHash>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QSet>
+#include <QStringList>
+
+Q_LOGGING_CATEGORY(qrcParserLog, "qtc.qrcParser", QtWarningMsg)
+
+namespace Utils {
+
+namespace Internal {
+/*!
+ * \class QrcParser
+ * \brief Parses one or more qrc files, and keeps their content cached
+ *
+ * A Qrc resource contains files read from the filesystem but organized in a possibly different way.
+ *
+ * To easily describe that with a simple structure we use a map from qrc paths to the paths in the
+ * filesystem.
+ * By using a map we can easily find all qrc paths that start with a given prefix, and thus loop
+ * on a qrc directory.
+ *
+ * Qrc files also support languages, those are mapped to a prefix of the qrc path.
+ * For example the french /image/bla.png (lang=fr) will have the path "fr/image/bla.png".
+ * The empty language represent the default resource.
+ * Languages are looked up using the locale uiLanguages() property
+ *
+ * For a single qrc a given path maps to a single file, but when one has multiple
+ * (platform specific exclusive) qrc files, then multiple files match, so QStringList are used.
+ *
+ * Especially the collect* functions are thought as low level interface.
+ */
+class QrcParserPrivate
+{
+ Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcParser)
+public:
+ typedef QMap<QString,QStringList> SMap;
+ QrcParserPrivate(QrcParser *q);
+ 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 = 0) const;
+ bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const;
+ void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
+ const QLocale *locale = 0) const;
+ void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
+ const QLocale *locale = 0) const;
+
+ QStringList errorMessages() const;
+ QStringList languages() const;
+private:
+ static QString fixPrefix(const QString &prefix);
+ const QStringList allUiLanguages(const QLocale *locale) const;
+
+ SMap m_resources;
+ SMap m_files;
+ QStringList m_languages;
+ QStringList m_errorMessages;
+};
+
+class QrcCachePrivate
+{
+ Q_DECLARE_TR_FUNCTIONS(QmlJS::QrcCachePrivate)
+public:
+ QrcCachePrivate(QrcCache *q);
+ QrcParser::Ptr addPath(const QString &path, const QString &contents);
+ void removePath(const QString &path);
+ QrcParser::Ptr updatePath(const QString &path, const QString &contents);
+ QrcParser::Ptr parsedPath(const QString &path);
+ void clear();
+private:
+ QHash<QString, QPair<QrcParser::Ptr,int> > m_cache;
+ QMutex m_mutex;
+};
+} // namespace Internal
+
+/*! \brief normalizes the path to a file in a qrc resource by dropping the "qrc:/" or ":" and
+ * any extra slashes at the beginning
+ */
+QString QrcParser::normalizedQrcFilePath(const QString &path) {
+ QString normPath = path;
+ int endPrefix = 0;
+ if (path.startsWith(QLatin1String("qrc:/")))
+ endPrefix = 4;
+ else if (path.startsWith(QLatin1String(":/")))
+ endPrefix = 1;
+ if (endPrefix < path.size() && path.at(endPrefix) == QLatin1Char('/'))
+ while (endPrefix + 1 < path.size() && path.at(endPrefix+1) == QLatin1Char('/'))
+ ++endPrefix;
+ normPath = path.right(path.size()-endPrefix);
+ if (!normPath.startsWith(QLatin1Char('/')))
+ normPath.insert(0, QLatin1Char('/'));
+ return normPath;
+}
+
+/*! \brief normalizes the path to a directory in a qrc resource by dropping the "qrc:/" or ":" and
+ * any extra slashes at the beginning, and ensuring it ends with a slash
+ */
+QString QrcParser::normalizedQrcDirectoryPath(const QString &path) {
+ QString normPath = normalizedQrcFilePath(path);
+ if (!normPath.endsWith(QLatin1Char('/')))
+ normPath.append(QLatin1Char('/'));
+ return normPath;
+}
+
+QString QrcParser::qrcDirectoryPathForQrcFilePath(const QString &file)
+{
+ return file.left(file.lastIndexOf(QLatin1Char('/')));
+}
+
+QrcParser::QrcParser()
+{
+ d = new Internal::QrcParserPrivate(this);
+}
+
+QrcParser::~QrcParser()
+{
+ delete d;
+}
+
+bool QrcParser::parseFile(const QString &path, const QString &contents)
+{
+ return d->parseFile(path, contents);
+}
+
+/*! \brief returns fs path of the first (active) file at the given qrc path
+ */
+QString QrcParser::firstFileAtPath(const QString &path, const QLocale &locale) const
+{
+ return d->firstFileAtPath(path, locale);
+}
+
+/*! \brief adds al the fs paths for the given qrc path to *res
+ * If locale is null all possible files are added, otherwise just the first match
+ * using that locale.
+ */
+void QrcParser::collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale) const
+{
+ d->collectFilesAtPath(path, res, locale);
+}
+
+/*! \brief returns true if the given path is a non empty directory
+ */
+bool QrcParser::hasDirAtPath(const QString &path, const QLocale *locale) const
+{
+ return d->hasDirAtPath(path, locale);
+}
+
+/*! \brief adds the directory contents of the given qrc path to res
+ *
+ * adds the qrcFileName => fs paths associations contained in the given qrc path
+ * to res. If addDirs is true directories are also added.
+ * If locale is null all possible files are added, otherwise just the first match
+ * using that locale.
+ */
+void QrcParser::collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs,
+ const QLocale *locale) const
+{
+ d->collectFilesInPath(path, res, addDirs, locale);
+}
+
+void QrcParser::collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
+ const QLocale *locale) const
+{
+ d->collectResourceFilesForSourceFile(sourceFile, res, locale);
+}
+
+/*! \brief returns the errors found while parsing
+ */
+QStringList QrcParser::errorMessages() const
+{
+ return d->errorMessages();
+}
+
+/*! \brief returns all languages used in this qrc resource
+ */
+QStringList QrcParser::languages() const
+{
+ return d->languages();
+}
+
+/*! \brief if the contents are valid
+ */
+bool QrcParser::isValid() const
+{
+ return errorMessages().isEmpty();
+}
+
+QrcParser::Ptr QrcParser::parseQrcFile(const QString &path, const QString &contents)
+{
+ Ptr res(new QrcParser);
+ if (!path.isEmpty())
+ res->parseFile(path, contents);
+ return res;
+}
+
+// ----------------
+
+QrcCache::QrcCache()
+{
+ d = new Internal::QrcCachePrivate(this);
+}
+
+QrcCache::~QrcCache()
+{
+ delete d;
+}
+
+QrcParser::ConstPtr QrcCache::addPath(const QString &path, const QString &contents)
+{
+ return d->addPath(path, contents);
+}
+
+void QrcCache::removePath(const QString &path)
+{
+ d->removePath(path);
+}
+
+QrcParser::ConstPtr QrcCache::updatePath(const QString &path, const QString &contents)
+{
+ return d->updatePath(path, contents);
+}
+
+QrcParser::ConstPtr QrcCache::parsedPath(const QString &path)
+{
+ return d->parsedPath(path);
+}
+
+void QrcCache::clear()
+{
+ d->clear();
+}
+
+// --------------------
+
+namespace Internal {
+
+QrcParserPrivate::QrcParserPrivate(QrcParser *)
+{ }
+
+bool QrcParserPrivate::parseFile(const QString &path, const QString &contents)
+{
+ QDomDocument doc;
+ QDir baseDir(QFileInfo(path).path());
+
+ if (contents.isEmpty()) {
+ // Regular file
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly)) {
+ m_errorMessages.append(file.errorString());
+ return false;
+ }
+
+ QString error_msg;
+ int error_line, error_col;
+ if (!doc.setContent(&file, &error_msg, &error_line, &error_col)) {
+ m_errorMessages.append(tr("XML error on line %1, col %2: %3")
+ .arg(error_line).arg(error_col).arg(error_msg));
+ return false;
+ }
+ } else {
+ // Virtual file from qmake evaluator
+ QString error_msg;
+ int error_line, error_col;
+ if (!doc.setContent(contents, &error_msg, &error_line, &error_col)) {
+ m_errorMessages.append(tr("XML error on line %1, col %2: %3")
+ .arg(error_line).arg(error_col).arg(error_msg));
+ return false;
+ }
+ }
+
+ QDomElement root = doc.firstChildElement(QLatin1String("RCC"));
+ if (root.isNull()) {
+ m_errorMessages.append(tr("The <RCC> root element is missing."));
+ return false;
+ }
+
+ QDomElement relt = root.firstChildElement(QLatin1String("qresource"));
+ for (; !relt.isNull(); relt = relt.nextSiblingElement(QLatin1String("qresource"))) {
+
+ QString prefix = fixPrefix(relt.attribute(QLatin1String("prefix")));
+ const QString language = relt.attribute(QLatin1String("lang"));
+ if (!m_languages.contains(language))
+ m_languages.append(language);
+
+ QDomElement felt = relt.firstChildElement(QLatin1String("file"));
+ for (; !felt.isNull(); felt = felt.nextSiblingElement(QLatin1String("file"))) {
+ const QString fileName = felt.text();
+ const QString alias = felt.attribute(QLatin1String("alias"));
+ QString filePath = baseDir.absoluteFilePath(fileName);
+ QString accessPath;
+ if (!alias.isEmpty())
+ accessPath = language + prefix + alias;
+ else
+ accessPath = language + prefix + fileName;
+ QStringList &resources = m_resources[accessPath];
+ if (!resources.contains(filePath))
+ resources.append(filePath);
+ QStringList &files = m_files[filePath];
+ if (!files.contains(accessPath))
+ files.append(accessPath);
+ }
+ }
+ return true;
+}
+
+// path is assumed to be a normalized absolute path
+QString QrcParserPrivate::firstFileAtPath(const QString &path, const QLocale &locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ for (const QString &language : allUiLanguages(&locale)) {
+ if (m_languages.contains(language)) {
+ SMap::const_iterator res = m_resources.find(language + path);
+ if (res != m_resources.end())
+ return res.value().at(0);
+ }
+ }
+ return QString();
+}
+
+void QrcParserPrivate::collectFilesAtPath(const QString &path, QStringList *files,
+ const QLocale *locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ for (const QString &language : allUiLanguages(locale)) {
+ if (m_languages.contains(language)) {
+ SMap::const_iterator res = m_resources.find(language + path);
+ if (res != m_resources.end())
+ (*files) << res.value();
+ }
+ }
+}
+
+// path is expected to be normalized and start and end with a slash
+bool QrcParserPrivate::hasDirAtPath(const QString &path, const QLocale *locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ QTC_CHECK(path.endsWith(QLatin1Char('/')));
+ for (const QString &language : allUiLanguages(locale)) {
+ if (m_languages.contains(language)) {
+ QString key = language + path;
+ SMap::const_iterator res = m_resources.lowerBound(key);
+ if (res != m_resources.end() && res.key().startsWith(key))
+ return true;
+ }
+ }
+ return false;
+}
+
+void QrcParserPrivate::collectFilesInPath(const QString &path, QMap<QString,QStringList> *contents,
+ bool addDirs, const QLocale *locale) const
+{
+ QTC_CHECK(path.startsWith(QLatin1Char('/')));
+ QTC_CHECK(path.endsWith(QLatin1Char('/')));
+ SMap::const_iterator end = m_resources.end();
+ for (const QString &language : allUiLanguages(locale)) {
+ QString key = language + path;
+ SMap::const_iterator res = m_resources.lowerBound(key);
+ while (res != end && res.key().startsWith(key)) {
+ const QString &actualKey = res.key();
+ int endDir = actualKey.indexOf(QLatin1Char('/'), key.size());
+ if (endDir == -1) {
+ QString fileName = res.key().right(res.key().size()-key.size());
+ QStringList &els = (*contents)[fileName];
+ for (const QString &val : res.value())
+ if (!els.contains(val))
+ els << val;
+ ++res;
+ } else {
+ QString dirName = res.key().mid(key.size(), endDir - key.size() + 1);
+ if (addDirs)
+ contents->insert(dirName, QStringList());
+ QString key2 = key + dirName;
+ do {
+ ++res;
+ } while (res != end && res.key().startsWith(key2));
+ }
+ }
+ }
+}
+
+void QrcParserPrivate::collectResourceFilesForSourceFile(const QString &sourceFile,
+ QStringList *results,
+ const QLocale *locale) const
+{
+ // TODO: use FileName from fileutils for file paths
+
+ const QStringList langs = allUiLanguages(locale);
+ SMap::const_iterator file = m_files.find(sourceFile);
+ if (file == m_files.end())
+ return;
+ for (const QString &resource : file.value()) {
+ for (const QString &language : langs) {
+ if (resource.startsWith(language) && !results->contains(resource))
+ results->append(resource);
+ }
+ }
+}
+
+QStringList QrcParserPrivate::errorMessages() const
+{
+ return m_errorMessages;
+}
+
+QStringList QrcParserPrivate::languages() const
+{
+ return m_languages;
+}
+
+QString QrcParserPrivate::fixPrefix(const QString &prefix)
+{
+ const QChar slash = QLatin1Char('/');
+ QString result = QString(slash);
+ for (int i = 0; i < prefix.size(); ++i) {
+ const QChar c = prefix.at(i);
+ if (c == slash && result.at(result.size() - 1) == slash)
+ continue;
+ result.append(c);
+ }
+
+ if (!result.endsWith(slash))
+ result.append(slash);
+
+ return result;
+}
+
+const QStringList QrcParserPrivate::allUiLanguages(const QLocale *locale) const
+{
+ if (!locale)
+ return languages();
+ QStringList langs = locale->uiLanguages();
+ foreach (const QString &language, langs) { // qt4 support
+ if (language.contains(QLatin1Char('_')) || language.contains(QLatin1Char('-'))) {
+ QStringList splits = QString(language).replace(QLatin1Char('_'), QLatin1Char('-'))
+ .split(QLatin1Char('-'));
+ if (splits.size() > 1 && !langs.contains(splits.at(0)))
+ langs.append(splits.at(0));
+ }
+ }
+ if (!langs.contains(QString()))
+ langs.append(QString());
+ return langs;
+}
+
+// ----------------
+
+QrcCachePrivate::QrcCachePrivate(QrcCache *)
+{ }
+
+QrcParser::Ptr QrcCachePrivate::addPath(const QString &path, const QString &contents)
+{
+ QPair<QrcParser::Ptr,int> currentValue;
+ {
+ QMutexLocker l(&m_mutex);
+ currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ currentValue.second += 1;
+ if (currentValue.second > 1) {
+ m_cache.insert(path, currentValue);
+ return currentValue.first;
+ }
+ }
+ QrcParser::Ptr newParser = QrcParser::parseQrcFile(path, contents);
+ if (!newParser->isValid())
+ qCWarning(qrcParserLog) << "adding invalid qrc " << path << " to the cache:" << newParser->errorMessages();
+ {
+ QMutexLocker l(&m_mutex);
+ QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ if (currentValue.first.isNull())
+ currentValue.first = newParser;
+ currentValue.second += 1;
+ m_cache.insert(path, currentValue);
+ return currentValue.first;
+ }
+}
+
+void QrcCachePrivate::removePath(const QString &path)
+{
+ QPair<QrcParser::Ptr,int> currentValue;
+ {
+ QMutexLocker l(&m_mutex);
+ currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ if (currentValue.second == 1) {
+ m_cache.remove(path);
+ } else if (currentValue.second > 1) {
+ currentValue.second -= 1;
+ m_cache.insert(path, currentValue);
+ } else {
+ QTC_CHECK(!m_cache.contains(path));
+ }
+ }
+}
+
+QrcParser::Ptr QrcCachePrivate::updatePath(const QString &path, const QString &contents)
+{
+ QrcParser::Ptr newParser = QrcParser::parseQrcFile(path, contents);
+ {
+ QMutexLocker l(&m_mutex);
+ QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ currentValue.first = newParser;
+ if (currentValue.second == 0)
+ currentValue.second = 1; // add qrc files that are not in the resources of a project
+ m_cache.insert(path, currentValue);
+ return currentValue.first;
+ }
+}
+
+QrcParser::Ptr QrcCachePrivate::parsedPath(const QString &path)
+{
+ QMutexLocker l(&m_mutex);
+ QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0});
+ return currentValue.first;
+}
+
+void QrcCachePrivate::clear()
+{
+ QMutexLocker l(&m_mutex);
+ m_cache.clear();
+}
+
+} // namespace Internal
+} // namespace QmlJS
diff --git a/src/libs/utils/qrcparser.h b/src/libs/utils/qrcparser.h
new file mode 100644
index 0000000000..b5a7be761b
--- /dev/null
+++ b/src/libs/utils/qrcparser.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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 <QMap>
+#include <QSharedPointer>
+#include <QString>
+#include <QStringList>
+
+QT_FORWARD_DECLARE_CLASS(QLocale)
+
+namespace Utils {
+
+namespace Internal {
+class QrcParserPrivate;
+class QrcCachePrivate;
+}
+
+class QTCREATOR_UTILS_EXPORT QrcParser
+{
+public:
+ 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 = 0) const;
+ bool hasDirAtPath(const QString &path, const QLocale *locale = 0) const;
+ void collectFilesInPath(const QString &path, QMap<QString,QStringList> *res, bool addDirs = false,
+ const QLocale *locale = 0) const;
+ void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *results,
+ const QLocale *locale = 0) const;
+
+ QStringList errorMessages() const;
+ QStringList languages() const;
+ bool isValid() const;
+
+ static Ptr parseQrcFile(const QString &path, const QString &contents);
+ static QString normalizedQrcFilePath(const QString &path);
+ static QString normalizedQrcDirectoryPath(const QString &path);
+ static QString qrcDirectoryPathForQrcFilePath(const QString &file);
+private:
+ QrcParser();
+ QrcParser(const QrcParser &);
+ Internal::QrcParserPrivate *d;
+};
+
+class QTCREATOR_UTILS_EXPORT QrcCache
+{
+public:
+ QrcCache();
+ ~QrcCache();
+ QrcParser::ConstPtr addPath(const QString &path, const QString &contents);
+ void removePath(const QString &path);
+ QrcParser::ConstPtr updatePath(const QString &path, const QString &contents);
+ QrcParser::ConstPtr parsedPath(const QString &path);
+ void clear();
+private:
+ Internal::QrcCachePrivate *d;
+};
+}
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
index dd4fe16f49..992e1817c0 100644
--- a/src/libs/utils/qtcprocess.cpp
+++ b/src/libs/utils/qtcprocess.cpp
@@ -595,12 +595,12 @@ static QString quoteArgWin(const QString &arg)
}
QtcProcess::Arguments QtcProcess::prepareArgs(const QString &cmd, SplitError *err, OsType osType,
- const Environment *env, const QString *pwd)
+ const Environment *env, const QString *pwd, bool abortOnMeta)
{
if (osType == OsTypeWindows)
return prepareArgsWin(cmd, err, env, pwd);
else
- return Arguments::createUnixArgs(splitArgs(cmd, osType, true, err, env, pwd));
+ return Arguments::createUnixArgs(splitArgs(cmd, osType, abortOnMeta, err, env, pwd));
}
@@ -694,7 +694,8 @@ void QtcProcess::start()
const OsType osType = HostOsInfo::hostOs();
if (m_haveEnv) {
if (m_environment.size() == 0)
- qWarning("QtcProcess::start: Empty environment set when running '%s'.", qPrintable(m_command));
+ qWarning("QtcProcess::start: Empty environment set when running '%s'.",
+ qPrintable(m_commandLine.executable().toString()));
env = m_environment;
QProcess::setEnvironment(env.toStringList());
@@ -705,7 +706,9 @@ void QtcProcess::start()
const QString &workDir = workingDirectory();
QString command;
QtcProcess::Arguments arguments;
- bool success = prepareCommand(m_command, m_arguments, &command, &arguments, osType, &env, &workDir);
+ bool success = prepareCommand(m_commandLine.executable().toString(),
+ m_commandLine.arguments(),
+ &command, &arguments, osType, &env, &workDir);
if (osType == OsTypeWindows) {
QString args;
if (m_useCtrlCStub) {
diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h
index 44c5786661..5eeacf666e 100644
--- a/src/libs/utils/qtcprocess.h
+++ b/src/libs/utils/qtcprocess.h
@@ -38,10 +38,9 @@ class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess
public:
QtcProcess(QObject *parent = nullptr);
- void setEnvironment(const Environment &env)
- { m_environment = env; m_haveEnv = true; }
- void setCommand(const QString &command, const QString &arguments)
- { m_command = command; m_arguments = arguments; }
+
+ void setEnvironment(const Environment &env) { m_environment = env; m_haveEnv = true; }
+ void setCommand(const CommandLine &cmdLine) { m_commandLine = cmdLine; }
void setUseCtrlCStub(bool enabled);
void start();
void terminate();
@@ -80,7 +79,8 @@ public:
//! Prepare argument of a shell command for feeding into QProcess
static Arguments prepareArgs(const QString &cmd, SplitError *err,
OsType osType = HostOsInfo::hostOs(),
- const Environment *env = nullptr, const QString *pwd = nullptr);
+ const Environment *env = nullptr, const QString *pwd = nullptr,
+ bool abortOnMeta = true);
//! Prepare a shell command for feeding into QProcess
static bool prepareCommand(const QString &command, const QString &arguments,
QString *outCmd, Arguments *outArgs, OsType osType = HostOsInfo::hostOs(),
@@ -141,8 +141,7 @@ public:
};
private:
- QString m_command;
- QString m_arguments;
+ CommandLine m_commandLine;
Environment m_environment;
bool m_haveEnv = false;
bool m_useCtrlCStub = false;
diff --git a/src/libs/utils/reloadpromptutils.cpp b/src/libs/utils/reloadpromptutils.cpp
index 2270053be0..09a9855784 100644
--- a/src/libs/utils/reloadpromptutils.cpp
+++ b/src/libs/utils/reloadpromptutils.cpp
@@ -33,7 +33,7 @@
namespace Utils {
-QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
+QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FilePath &fileName,
bool modified,
bool enableDiffOption,
QWidget *parent)
@@ -50,7 +50,10 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
msg = QCoreApplication::translate("Utils::reloadPrompt",
"The file <i>%1</i> has been changed on disk. Do you want to reload it?");
}
- msg = msg.arg(fileName.fileName());
+ msg = "<p>" + msg.arg(fileName.fileName()) + "</p><p>" +
+ QCoreApplication::translate("Utils::reloadPrompt",
+ "The default behavior can be set in Tools > Options > Environment > System.")
+ + "</p>";
return reloadPrompt(title, msg, fileName.toUserOutput(), enableDiffOption, parent);
}
diff --git a/src/libs/utils/reloadpromptutils.h b/src/libs/utils/reloadpromptutils.h
index 8991d52b59..82aa409cf5 100644
--- a/src/libs/utils/reloadpromptutils.h
+++ b/src/libs/utils/reloadpromptutils.h
@@ -33,7 +33,7 @@ class QWidget;
QT_END_NAMESPACE
namespace Utils {
-class FileName;
+class FilePath;
enum ReloadPromptAnswer {
ReloadCurrent,
@@ -44,7 +44,7 @@ enum ReloadPromptAnswer {
CloseCurrent
};
-QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
+QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FilePath &fileName,
bool modified,
bool enableDiffOption,
QWidget *parent);
diff --git a/src/libs/utils/runextensions.h b/src/libs/utils/runextensions.h
index 6925504693..eacbd8dc4c 100644
--- a/src/libs/utils/runextensions.h
+++ b/src/libs/utils/runextensions.h
@@ -600,4 +600,59 @@ const QFuture<T> &onResultReady(const QFuture<T> &future, Function f)
return future;
}
-} // Utils
+/*!
+ Adds a handler for when the future is finished.
+ This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
+ or create a QFutureWatcher already for other reasons.
+*/
+template<typename R, typename T>
+const QFuture<T> &onFinished(const QFuture<T> &future,
+ R *receiver,
+ void (R::*member)(const QFuture<T> &))
+{
+ auto watcher = new QFutureWatcher<T>();
+ QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
+ QObject::connect(watcher,
+ &QFutureWatcherBase::finished,
+ receiver,
+ [receiver, member, watcher]() { (receiver->*member)(watcher->future()); });
+ watcher->setFuture(future);
+ return future;
+}
+
+/*!
+ Adds a handler for when the future is finished. The guard object determines the lifetime of
+ the connection.
+ This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
+ or create a QFutureWatcher already for other reasons.
+*/
+template<typename T, typename Function>
+const QFuture<T> &onFinished(const QFuture<T> &future, QObject *guard, Function f)
+{
+ auto watcher = new QFutureWatcher<T>();
+ QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
+ QObject::connect(watcher, &QFutureWatcherBase::finished, guard, [f, watcher]() {
+ f(watcher->future());
+ });
+ watcher->setFuture(future);
+ return future;
+}
+
+/*!
+ Adds a handler for when the future is finished.
+ This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
+ or create a QFutureWatcher already for other reasons.
+*/
+template<typename T, typename Function>
+const QFuture<T> &onFinished(const QFuture<T> &future, Function f)
+{
+ auto watcher = new QFutureWatcher<T>();
+ QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
+ QObject::connect(watcher, &QFutureWatcherBase::finished, [f, watcher]() {
+ f(watcher->future());
+ });
+ watcher->setFuture(future);
+ return future;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/savedaction.cpp b/src/libs/utils/savedaction.cpp
index 0000e54d31..87a785f6db 100644
--- a/src/libs/utils/savedaction.cpp
+++ b/src/libs/utils/savedaction.cpp
@@ -235,7 +235,7 @@ void SavedAction::connectWidget(QWidget *widget, ApplyMode applyMode)
} else if (auto spinBox = qobject_cast<QSpinBox *>(widget)) {
spinBox->setValue(m_value.toInt());
if (applyMode == ImmediateApply) {
- connect(spinBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, [this, spinBox]() { setValue(spinBox->value()); });
}
} else if (auto lineEdit = qobject_cast<QLineEdit *>(widget)) {
diff --git a/src/libs/utils/savefile.cpp b/src/libs/utils/savefile.cpp
index cac25546db..b25432a280 100644
--- a/src/libs/utils/savefile.cpp
+++ b/src/libs/utils/savefile.cpp
@@ -119,7 +119,7 @@ bool SaveFile::commit()
}
QString finalFileName
- = FileUtils::resolveSymlinks(FileName::fromString(m_finalFileName)).toString();
+ = FileUtils::resolveSymlinks(FilePath::fromString(m_finalFileName)).toString();
#ifdef Q_OS_WIN
// Release the file lock
diff --git a/src/libs/utils/settingsaccessor.cpp b/src/libs/utils/settingsaccessor.cpp
index 662ad4bd43..f6d90df7e0 100644
--- a/src/libs/utils/settingsaccessor.cpp
+++ b/src/libs/utils/settingsaccessor.cpp
@@ -98,7 +98,7 @@ bool SettingsAccessor::saveSettings(const QVariantMap &data, QWidget *parent) co
/*!
* Read data from \a path. Do all the necessary postprocessing of the data.
*/
-SettingsAccessor::RestoreData SettingsAccessor::readData(const FileName &path, QWidget *parent) const
+SettingsAccessor::RestoreData SettingsAccessor::readData(const FilePath &path, QWidget *parent) const
{
Q_UNUSED(parent);
RestoreData result = readFile(path);
@@ -111,13 +111,13 @@ SettingsAccessor::RestoreData SettingsAccessor::readData(const FileName &path, Q
* Store the \a data in \a path on disk. Do all the necessary preprocessing of the data.
*/
optional<SettingsAccessor::Issue>
-SettingsAccessor::writeData(const FileName &path, const QVariantMap &data, QWidget *parent) const
+SettingsAccessor::writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const
{
Q_UNUSED(parent);
return writeFile(path, prepareToWriteSettings(data));
}
-QVariantMap SettingsAccessor::restoreSettings(const FileName &settingsPath, QWidget *parent) const
+QVariantMap SettingsAccessor::restoreSettings(const FilePath &settingsPath, QWidget *parent) const
{
const RestoreData result = readData(settingsPath, parent);
@@ -131,7 +131,7 @@ QVariantMap SettingsAccessor::restoreSettings(const FileName &settingsPath, QWid
*
* This method does not do *any* processing of the file contents.
*/
-SettingsAccessor::RestoreData SettingsAccessor::readFile(const FileName &path) const
+SettingsAccessor::RestoreData SettingsAccessor::readFile(const FilePath &path) const
{
PersistentSettingsReader reader;
if (!reader.load(path)) {
@@ -156,7 +156,7 @@ SettingsAccessor::RestoreData SettingsAccessor::readFile(const FileName &path) c
* This method does not do *any* processing of the file contents.
*/
optional<SettingsAccessor::Issue>
-SettingsAccessor::writeFile(const FileName &path, const QVariantMap &data) const
+SettingsAccessor::writeFile(const FilePath &path, const QVariantMap &data) const
{
if (data.isEmpty()) {
return Issue(QCoreApplication::translate("Utils::SettingsAccessor", "Failed to Write File"),
@@ -176,7 +176,7 @@ SettingsAccessor::writeFile(const FileName &path, const QVariantMap &data) const
}
SettingsAccessor::ProceedInfo
-SettingsAccessor::reportIssues(const SettingsAccessor::Issue &issue, const FileName &path,
+SettingsAccessor::reportIssues(const SettingsAccessor::Issue &issue, const FilePath &path,
QWidget *parent) const
{
if (!path.exists())
@@ -217,14 +217,14 @@ QVariantMap SettingsAccessor::prepareToWriteSettings(const QVariantMap &data) co
// BackingUpSettingsAccessor:
// --------------------------------------------------------------------
-FileNameList BackUpStrategy::readFileCandidates(const FileName &baseFileName) const
+FilePathList BackUpStrategy::readFileCandidates(const FilePath &baseFileName) const
{
const QFileInfo pfi = baseFileName.toFileInfo();
const QStringList filter(pfi.fileName() + '*');
const QFileInfoList list = QDir(pfi.dir()).entryInfoList(filter, QDir::Files | QDir::Hidden | QDir::System);
- return Utils::transform(list, [](const QFileInfo &fi) { return FileName::fromString(fi.absoluteFilePath()); });
+ return Utils::transform(list, [](const QFileInfo &fi) { return FilePath::fromString(fi.absoluteFilePath()); });
}
int BackUpStrategy::compare(const SettingsAccessor::RestoreData &data1,
@@ -239,14 +239,12 @@ int BackUpStrategy::compare(const SettingsAccessor::RestoreData &data1,
return 0;
}
-optional<FileName>
-BackUpStrategy::backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const
+optional<FilePath>
+BackUpStrategy::backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const
{
if (oldData == data)
return nullopt;
- FileName backup = path;
- backup.appendString(".bak");
- return backup;
+ return path.stringAppended(".bak");
}
BackingUpSettingsAccessor::BackingUpSettingsAccessor(const QString &docType,
@@ -264,9 +262,9 @@ BackingUpSettingsAccessor::BackingUpSettingsAccessor(std::unique_ptr<BackUpStrat
{ }
SettingsAccessor::RestoreData
-BackingUpSettingsAccessor::readData(const FileName &path, QWidget *parent) const
+BackingUpSettingsAccessor::readData(const FilePath &path, QWidget *parent) const
{
- const FileNameList fileList = readFileCandidates(path);
+ const FilePathList fileList = readFileCandidates(path);
if (fileList.isEmpty()) // No settings found at all.
return RestoreData(path, QVariantMap());
@@ -289,7 +287,7 @@ BackingUpSettingsAccessor::readData(const FileName &path, QWidget *parent) const
}
optional<SettingsAccessor::Issue>
-BackingUpSettingsAccessor::writeData(const FileName &path, const QVariantMap &data,
+BackingUpSettingsAccessor::writeData(const FilePath &path, const QVariantMap &data,
QWidget *parent) const
{
if (data.isEmpty())
@@ -300,9 +298,9 @@ BackingUpSettingsAccessor::writeData(const FileName &path, const QVariantMap &da
return SettingsAccessor::writeData(path, data, parent);
}
-FileNameList BackingUpSettingsAccessor::readFileCandidates(const FileName &path) const
+FilePathList BackingUpSettingsAccessor::readFileCandidates(const FilePath &path) const
{
- FileNameList result = Utils::filteredUnique(m_strategy->readFileCandidates(path));
+ FilePathList result = Utils::filteredUnique(m_strategy->readFileCandidates(path));
if (result.removeOne(baseFilePath()))
result.prepend(baseFilePath());
@@ -310,10 +308,10 @@ FileNameList BackingUpSettingsAccessor::readFileCandidates(const FileName &path)
}
SettingsAccessor::RestoreData
-BackingUpSettingsAccessor::bestReadFileData(const FileNameList &candidates, QWidget *parent) const
+BackingUpSettingsAccessor::bestReadFileData(const FilePathList &candidates, QWidget *parent) const
{
SettingsAccessor::RestoreData bestMatch;
- for (const FileName &c : candidates) {
+ for (const FilePath &c : candidates) {
RestoreData cData = SettingsAccessor::readData(c, parent);
if (m_strategy->compare(bestMatch, cData) > 0)
bestMatch = cData;
@@ -321,7 +319,7 @@ BackingUpSettingsAccessor::bestReadFileData(const FileNameList &candidates, QWid
return bestMatch;
}
-void BackingUpSettingsAccessor::backupFile(const FileName &path, const QVariantMap &data,
+void BackingUpSettingsAccessor::backupFile(const FilePath &path, const QVariantMap &data,
QWidget *parent) const
{
RestoreData oldSettings = SettingsAccessor::readData(path, parent);
@@ -330,7 +328,7 @@ void BackingUpSettingsAccessor::backupFile(const FileName &path, const QVariantM
// Do we need to do a backup?
const QString origName = path.toString();
- optional<FileName> backupFileName = m_strategy->backupName(oldSettings.data, path, data);
+ optional<FilePath> backupFileName = m_strategy->backupName(oldSettings.data, path, data);
if (backupFileName)
QFile::copy(origName, backupFileName.value().toString());
}
@@ -361,22 +359,23 @@ int VersionedBackUpStrategy::compare(const SettingsAccessor::RestoreData &data1,
return -1;
}
-optional<FileName>
-VersionedBackUpStrategy::backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const
+optional<FilePath>
+VersionedBackUpStrategy::backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const
{
Q_UNUSED(data);
- FileName backupName = path;
+ FilePath backupName = path;
const QByteArray oldEnvironmentId = settingsIdFromMap(oldData);
const int oldVersion = versionFromMap(oldData);
if (!oldEnvironmentId.isEmpty() && oldEnvironmentId != m_accessor->settingsId())
- backupName.appendString('.' + QString::fromLatin1(oldEnvironmentId).mid(1, 7));
+ backupName = backupName.stringAppended
+ ('.' + QString::fromLatin1(oldEnvironmentId).mid(1, 7));
if (oldVersion != m_accessor->currentVersion()) {
VersionUpgrader *upgrader = m_accessor->upgrader(oldVersion);
if (upgrader)
- backupName.appendString('.' + upgrader->backupExtension());
+ backupName = backupName.stringAppended('.' + upgrader->backupExtension());
else
- backupName.appendString('.' + QString::number(oldVersion));
+ backupName = backupName.stringAppended('.' + QString::number(oldVersion));
}
if (backupName == path)
return nullopt;
@@ -464,7 +463,7 @@ bool UpgradingSettingsAccessor::isValidVersionAndId(const int version, const QBy
&& (id.isEmpty() || id == m_id || m_id.isEmpty());
}
-SettingsAccessor::RestoreData UpgradingSettingsAccessor::readData(const FileName &path,
+SettingsAccessor::RestoreData UpgradingSettingsAccessor::readData(const FilePath &path,
QWidget *parent) const
{
return upgradeSettings(BackingUpSettingsAccessor::readData(path, parent), currentVersion());
@@ -606,7 +605,7 @@ MergingSettingsAccessor::MergingSettingsAccessor(std::unique_ptr<BackUpStrategy>
UpgradingSettingsAccessor(std::move(strategy), docType, displayName, applicationDisplayName)
{ }
-SettingsAccessor::RestoreData MergingSettingsAccessor::readData(const FileName &path,
+SettingsAccessor::RestoreData MergingSettingsAccessor::readData(const FilePath &path,
QWidget *parent) const
{
RestoreData mainData = UpgradingSettingsAccessor::readData(path, parent); // FULLY upgraded!
diff --git a/src/libs/utils/settingsaccessor.h b/src/libs/utils/settingsaccessor.h
index 10675cbf4c..fd5cf87ef7 100644
--- a/src/libs/utils/settingsaccessor.h
+++ b/src/libs/utils/settingsaccessor.h
@@ -99,7 +99,7 @@ public:
class RestoreData {
public:
RestoreData() = default;
- RestoreData(const FileName &path, const QVariantMap &data) : path{path}, data{data} { }
+ RestoreData(const FilePath &path, const QVariantMap &data) : path{path}, data{data} { }
RestoreData(const QString &title, const QString &message, const Issue::Type type) :
RestoreData(Issue(title, message, type))
{ }
@@ -109,7 +109,7 @@ public:
bool hasError() const { return hasIssue() && issue.value().type == Issue::Type::ERROR; }
bool hasWarning() const { return hasIssue() && issue.value().type == Issue::Type::WARNING; }
- FileName path;
+ FilePath path;
QVariantMap data;
optional<Issue> issue;
};
@@ -121,26 +121,26 @@ public:
const QString displayName;
const QString applicationDisplayName;
- void setBaseFilePath(const FileName &baseFilePath) { m_baseFilePath = baseFilePath; }
+ void setBaseFilePath(const FilePath &baseFilePath) { m_baseFilePath = baseFilePath; }
void setReadOnly() { m_readOnly = true; }
- FileName baseFilePath() const { return m_baseFilePath; }
+ FilePath baseFilePath() const { return m_baseFilePath; }
- virtual RestoreData readData(const FileName &path, QWidget *parent) const;
- virtual optional<Issue> writeData(const FileName &path, const QVariantMap &data, QWidget *parent) const;
+ virtual RestoreData readData(const FilePath &path, QWidget *parent) const;
+ virtual optional<Issue> writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const;
protected:
// Report errors:
- QVariantMap restoreSettings(const FileName &settingsPath, QWidget *parent) const;
- ProceedInfo reportIssues(const Issue &issue, const FileName &path, QWidget *parent) const;
+ QVariantMap restoreSettings(const FilePath &settingsPath, QWidget *parent) const;
+ ProceedInfo reportIssues(const Issue &issue, const FilePath &path, QWidget *parent) const;
virtual QVariantMap preprocessReadSettings(const QVariantMap &data) const;
virtual QVariantMap prepareToWriteSettings(const QVariantMap &data) const;
- virtual RestoreData readFile(const FileName &path) const;
- virtual optional<Issue> writeFile(const FileName &path, const QVariantMap &data) const;
+ virtual RestoreData readFile(const FilePath &path) const;
+ virtual optional<Issue> writeFile(const FilePath &path, const QVariantMap &data) const;
private:
- FileName m_baseFilePath;
+ FilePath m_baseFilePath;
mutable std::unique_ptr<PersistentSettingsWriter> m_writer;
bool m_readOnly = false;
};
@@ -154,14 +154,14 @@ class QTCREATOR_UTILS_EXPORT BackUpStrategy
public:
virtual ~BackUpStrategy() = default;
- virtual FileNameList readFileCandidates(const FileName &baseFileName) const;
+ virtual FilePathList readFileCandidates(const FilePath &baseFileName) const;
// Return -1 if data1 is better that data2, 0 if both are equally worthwhile
// and 1 if data2 is better than data1
virtual int compare(const SettingsAccessor::RestoreData &data1,
const SettingsAccessor::RestoreData &data2) const;
- virtual optional<FileName>
- backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const;
+ virtual optional<FilePath>
+ backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const;
};
class QTCREATOR_UTILS_EXPORT BackingUpSettingsAccessor : public SettingsAccessor
@@ -172,16 +172,16 @@ public:
BackingUpSettingsAccessor(std::unique_ptr<BackUpStrategy> &&strategy, const QString &docType,
const QString &displayName, const QString &applicationDisplayName);
- RestoreData readData(const FileName &path, QWidget *parent) const override;
- optional<Issue> writeData(const FileName &path, const QVariantMap &data,
+ RestoreData readData(const FilePath &path, QWidget *parent) const override;
+ optional<Issue> writeData(const FilePath &path, const QVariantMap &data,
QWidget *parent) const override;
BackUpStrategy *strategy() const { return m_strategy.get(); }
private:
- FileNameList readFileCandidates(const FileName &path) const;
- RestoreData bestReadFileData(const FileNameList &candidates, QWidget *parent) const;
- void backupFile(const FileName &path, const QVariantMap &data, QWidget *parent) const;
+ FilePathList readFileCandidates(const FilePath &path) const;
+ RestoreData bestReadFileData(const FilePathList &candidates, QWidget *parent) const;
+ void backupFile(const FilePath &path, const QVariantMap &data, QWidget *parent) const;
std::unique_ptr<BackUpStrategy> m_strategy;
};
@@ -202,8 +202,8 @@ public:
int compare(const SettingsAccessor::RestoreData &data1,
const SettingsAccessor::RestoreData &data2) const override;
- optional<FileName>
- backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const override;
+ optional<FilePath>
+ backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const override;
const UpgradingSettingsAccessor *accessor() const { return m_accessor; }
@@ -251,7 +251,7 @@ public:
bool isValidVersionAndId(const int version, const QByteArray &id) const;
VersionUpgrader *upgrader(const int version) const;
- RestoreData readData(const FileName &path, QWidget *parent) const override;
+ RestoreData readData(const FilePath &path, QWidget *parent) const override;
protected:
QVariantMap prepareToWriteSettings(const QVariantMap &data) const override;
@@ -284,7 +284,7 @@ public:
const QString &docType, const QString &displayName,
const QString &applicationDisplayName);
- RestoreData readData(const FileName &path, QWidget *parent) const final;
+ RestoreData readData(const FilePath &path, QWidget *parent) const final;
void setSecondaryAccessor(std::unique_ptr<SettingsAccessor> &&secondary);
diff --git a/src/libs/utils/settingsselector.cpp b/src/libs/utils/settingsselector.cpp
index ddfa7a137c..6ae5bff43c 100644
--- a/src/libs/utils/settingsselector.cpp
+++ b/src/libs/utils/settingsselector.cpp
@@ -73,7 +73,7 @@ SettingsSelector::SettingsSelector(QWidget *parent) :
connect(m_renameButton, &QAbstractButton::clicked,
this, &SettingsSelector::renameButtonClicked);
connect(m_configurationCombo,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SettingsSelector::currentChanged);
}
diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp
index 14f52d2539..5a84c92f15 100644
--- a/src/libs/utils/shellcommand.cpp
+++ b/src/libs/utils/shellcommand.cpp
@@ -68,11 +68,11 @@ class ShellCommandPrivate
{
public:
struct Job {
- explicit Job(const QString &wd, const FileName &b, const QStringList &a, int t,
+ explicit Job(const QString &wd, const FilePath &b, const QStringList &a, int t,
const ExitCodeInterpreter &interpreter);
QString workingDirectory;
- FileName binary;
+ FilePath binary;
QStringList arguments;
ExitCodeInterpreter exitCodeInterpreter;
int timeoutS;
@@ -113,7 +113,7 @@ ShellCommandPrivate::~ShellCommandPrivate()
delete m_progressParser;
}
-ShellCommandPrivate::Job::Job(const QString &wd, const FileName &b, const QStringList &a,
+ShellCommandPrivate::Job::Job(const QString &wd, const FilePath &b, const QStringList &a,
int t, const ExitCodeInterpreter &interpreter) :
workingDirectory(wd),
binary(b),
@@ -195,13 +195,13 @@ void ShellCommand::addFlags(unsigned f)
d->m_flags |= f;
}
-void ShellCommand::addJob(const FileName &binary, const QStringList &arguments,
+void ShellCommand::addJob(const FilePath &binary, const QStringList &arguments,
const QString &workingDirectory, const ExitCodeInterpreter &interpreter)
{
addJob(binary, arguments, defaultTimeoutS(), workingDirectory, interpreter);
}
-void ShellCommand::addJob(const FileName &binary, const QStringList &arguments, int timeoutS,
+void ShellCommand::addJob(const FilePath &binary, const QStringList &arguments, int timeoutS,
const QString &workingDirectory, const ExitCodeInterpreter &interpreter)
{
d->m_jobs.push_back(Internal::ShellCommandPrivate::Job(workDirectory(workingDirectory), binary,
@@ -319,7 +319,7 @@ void ShellCommand::run(QFutureInterface<void> &future)
this->deleteLater();
}
-SynchronousProcessResponse ShellCommand::runCommand(const FileName &binary,
+SynchronousProcessResponse ShellCommand::runCommand(const FilePath &binary,
const QStringList &arguments, int timeoutS,
const QString &workingDirectory,
const ExitCodeInterpreter &interpreter)
@@ -359,7 +359,7 @@ SynchronousProcessResponse ShellCommand::runCommand(const FileName &binary,
return response;
}
-SynchronousProcessResponse ShellCommand::runFullySynchronous(const FileName &binary,
+SynchronousProcessResponse ShellCommand::runFullySynchronous(const FilePath &binary,
const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS,
@@ -399,7 +399,7 @@ SynchronousProcessResponse ShellCommand::runFullySynchronous(const FileName &bin
return resp;
}
-SynchronousProcessResponse ShellCommand::runSynchronous(const FileName &binary,
+SynchronousProcessResponse ShellCommand::runSynchronous(const FilePath &binary,
const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS,
diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h
index 22ff4a8df2..f0c427ef53 100644
--- a/src/libs/utils/shellcommand.h
+++ b/src/libs/utils/shellcommand.h
@@ -46,7 +46,7 @@ QT_END_NAMESPACE
namespace Utils {
-class FileName;
+class FilePath;
namespace Internal { class ShellCommandPrivate; }
class QTCREATOR_UTILS_EXPORT ProgressParser
@@ -79,7 +79,7 @@ signals:
void append(const QString &text);
void appendSilently(const QString &text);
void appendError(const QString &text);
- void appendCommand(const QString &workingDirectory, const Utils::FileName &binary,
+ void appendCommand(const QString &workingDirectory, const Utils::FilePath &binary,
const QStringList &args);
void appendMessage(const QString &text);
};
@@ -112,9 +112,9 @@ public:
QString displayName() const;
void setDisplayName(const QString &name);
- void addJob(const FileName &binary, const QStringList &arguments,
+ void addJob(const FilePath &binary, const QStringList &arguments,
const QString &workingDirectory = QString(), const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
- void addJob(const FileName &binary, const QStringList &arguments, int timeoutS,
+ void addJob(const FilePath &binary, const QStringList &arguments, int timeoutS,
const QString &workingDirectory = QString(), const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
void execute(); // Execute tasks asynchronously!
void abort();
@@ -145,7 +145,7 @@ public:
// This is called once per job in a thread.
// When called from the UI thread it will execute fully synchronously, so no signals will
// be triggered!
- virtual SynchronousProcessResponse runCommand(const FileName &binary, const QStringList &arguments,
+ virtual SynchronousProcessResponse runCommand(const FilePath &binary, const QStringList &arguments,
int timeoutS,
const QString &workingDirectory = QString(),
const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
@@ -171,12 +171,12 @@ private:
void run(QFutureInterface<void> &future);
// Run without a event loop in fully blocking mode. No signals will be delivered.
- SynchronousProcessResponse runFullySynchronous(const FileName &binary, const QStringList &arguments,
+ SynchronousProcessResponse runFullySynchronous(const FilePath &binary, const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS, const QString &workingDirectory,
const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
// Run with an event loop. Signals will be delivered.
- SynchronousProcessResponse runSynchronous(const FileName &binary, const QStringList &arguments,
+ SynchronousProcessResponse runSynchronous(const FilePath &binary, const QStringList &arguments,
QSharedPointer<OutputProxy> proxy,
int timeoutS, const QString &workingDirectory,
const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter);
diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h
index dc6867af5d..c381fbd44b 100644
--- a/src/libs/utils/smallstringlayout.h
+++ b/src/libs/utils/smallstringlayout.h
@@ -198,13 +198,6 @@ struct StringDataLayout {
shortString.string[0] = '\0';
}
- StringDataLayout &operator=(const StringDataLayout &other)
- {
- this->shortString = other.shortString;
-
- return *this;
- }
-
union {
AllocatedLayout<MaximumShortStringDataAreaSize> allocated;
ReferenceLayout<MaximumShortStringDataAreaSize> reference;
diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp
index b39af367d5..161cf44e74 100644
--- a/src/libs/utils/stringutils.cpp
+++ b/src/libs/utils/stringutils.cpp
@@ -143,7 +143,7 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt
varName.reserve(strLen - i);
for (; i < strLen; prev = c) {
c = str.at(i++);
- if (c == '\\' && i < strLen && validateVarName(varName)) {
+ if (c == '\\' && i < strLen) {
c = str.at(i++);
// For the replacement, do not skip the escape sequence when followed by a digit.
// This is needed for enabling convenient capture group replacement,
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index e44037f5a1..388da7eeba 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -209,9 +209,9 @@ static void verticalGradientHelper(QPainter *p, const QRect &spanRect, const QRe
void StyleHelper::verticalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored)
{
if (StyleHelper::usePixmapCache()) {
- QString key;
+
QColor keyColor = baseColor(lightColored);
- key.sprintf("mh_vertical %d %d %d %d %d",
+ const QString key = QString::asprintf("mh_vertical %d %d %d %d %d",
spanRect.width(), spanRect.height(), clipRect.width(),
clipRect.height(), keyColor.rgb());
@@ -267,9 +267,9 @@ QRect &rect, bool lightColored)
void StyleHelper::horizontalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored)
{
if (StyleHelper::usePixmapCache()) {
- QString key;
+
QColor keyColor = baseColor(lightColored);
- key.sprintf("mh_horizontal %d %d %d %d %d %d",
+ const QString key = QString::asprintf("mh_horizontal %d %d %d %d %d %d",
spanRect.width(), spanRect.height(), clipRect.width(),
clipRect.height(), keyColor.rgb(), spanRect.x());
@@ -309,8 +309,7 @@ void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *painter,
QRect r = option->rect;
int size = qMin(r.height(), r.width());
QPixmap pixmap;
- QString pixmapName;
- pixmapName.sprintf("StyleHelper::drawArrow-%d-%d-%d-%f",
+ const QString pixmapName = QString::asprintf("StyleHelper::drawArrow-%d-%d-%d-%f",
element, size, enabled, devicePixelRatio);
if (!QPixmapCache::find(pixmapName, &pixmap)) {
QImage image(size * devicePixelRatio, size * devicePixelRatio, QImage::Format_ARGB32_Premultiplied);
@@ -351,8 +350,7 @@ void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *painter,
void StyleHelper::menuGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect)
{
if (StyleHelper::usePixmapCache()) {
- QString key;
- key.sprintf("mh_menu %d %d %d %d %d",
+ const QString key = QString::asprintf("mh_menu %d %d %d %d %d",
spanRect.width(), spanRect.height(), clipRect.width(),
clipRect.height(), StyleHelper::baseColor().rgb());
diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp
index a153e6ac91..bfb9d0d296 100644
--- a/src/libs/utils/synchronousprocess.cpp
+++ b/src/libs/utils/synchronousprocess.cpp
@@ -297,8 +297,7 @@ SynchronousProcess::SynchronousProcess() :
{
d->m_timer.setInterval(1000);
connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout);
- connect(&d->m_process,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&d->m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &SynchronousProcess::finished);
connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error);
connect(&d->m_process, &QProcess::readyReadStandardOutput,
diff --git a/src/libs/utils/textfieldcombobox.cpp b/src/libs/utils/textfieldcombobox.cpp
index db940ad53a..aad64d2e7d 100644
--- a/src/libs/utils/textfieldcombobox.cpp
+++ b/src/libs/utils/textfieldcombobox.cpp
@@ -43,7 +43,7 @@ TextFieldComboBox::TextFieldComboBox(QWidget *parent) :
QComboBox(parent)
{
setEditable(false);
- connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &TextFieldComboBox::slotCurrentIndexChanged);
}
diff --git a/src/libs/utils/touchbar/touchbar.pri b/src/libs/utils/touchbar/touchbar.pri
index 8d60ee423b..5f18595785 100644
--- a/src/libs/utils/touchbar/touchbar.pri
+++ b/src/libs/utils/touchbar/touchbar.pri
@@ -9,7 +9,6 @@ macos {
$$PWD/touchbar_mac.mm \
$$PWD/touchbar_appdelegate_mac.mm
- QT += macextras
LIBS += -framework Foundation -framework AppKit
} else {
SOURCES += $$PWD/touchbar.cpp
diff --git a/src/libs/utils/touchbar/touchbar_mac.mm b/src/libs/utils/touchbar/touchbar_mac.mm
index 67c83aec0c..ee5a45bf72 100644
--- a/src/libs/utils/touchbar/touchbar_mac.mm
+++ b/src/libs/utils/touchbar/touchbar_mac.mm
@@ -29,8 +29,6 @@
#include <utils/utilsicons.h>
-#include <QtMac>
-
#import <AppKit/NSButton.h>
#import <AppKit/NSCustomTouchBarItem.h>
#import <AppKit/NSImage.h>
@@ -145,8 +143,12 @@ static NSImage *iconToTemplateNSImage(const QIcon &icon)
{
// touch bar icons are max 18-22 pts big. our are always 22 pts big.
const QPixmap pixmap = icon.pixmap(22);
- NSImage *image = QtMac::toNSImage(pixmap);
- // toNSImage ignores devicePixelRatio, so fixup after the fact
+
+ CGImageRef cgImage = pixmap.toImage().toCGImage();
+ NSImage *image = [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
+ CFRelease(cgImage);
+
+ // The above code ignores devicePixelRatio, so fixup after the fact
const CGFloat userWidth = pixmap.width() / pixmap.devicePixelRatio();
const CGFloat userHeight = pixmap.height() / pixmap.devicePixelRatio();
image.size = CGSizeMake(userWidth, userHeight); // scales the image
diff --git a/src/libs/utils/unixutils.cpp b/src/libs/utils/unixutils.cpp
index 7db05c22ea..77daae645c 100644
--- a/src/libs/utils/unixutils.cpp
+++ b/src/libs/utils/unixutils.cpp
@@ -77,7 +77,7 @@ QString UnixUtils::substituteFileBrowserParameters(const QString &pre, const QSt
} else if (c == QLatin1Char('f')) {
s = QLatin1Char('"') + file + QLatin1Char('"');
} else if (c == QLatin1Char('n')) {
- s = QLatin1Char('"') + FileName::fromString(file).fileName() + QLatin1Char('"');
+ s = QLatin1Char('"') + FilePath::fromString(file).fileName() + QLatin1Char('"');
} else if (c == QLatin1Char('%')) {
s = c;
} else {
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 5a2712cc3f..c7fef47c97 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -13,7 +13,7 @@ shared {
}
}
-QT += widgets gui network qml
+QT += widgets gui network qml xml
CONFIG += exceptions # used by portlist.cpp, textfileformat.cpp, and ssh/*
@@ -27,6 +27,7 @@ SOURCES += \
$$PWD/environment.cpp \
$$PWD/environmentmodel.cpp \
$$PWD/environmentdialog.cpp \
+ $$PWD/qrcparser.cpp \
$$PWD/qtcprocess.cpp \
$$PWD/reloadpromptutils.cpp \
$$PWD/settingsaccessor.cpp \
@@ -131,12 +132,14 @@ win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
HEADERS += \
+ $$PWD/genericconstants.h \
$$PWD/globalfilechangeblocker.h \
$$PWD/benchmarker.h \
$$PWD/environment.h \
$$PWD/environmentmodel.h \
$$PWD/environmentdialog.h \
$$PWD/pointeralgorithm.h \
+ $$PWD/qrcparser.h \
$$PWD/qtcprocess.h \
$$PWD/utils_global.h \
$$PWD/reloadpromptutils.h \
@@ -266,7 +269,8 @@ HEADERS += \
$$PWD/removefiledialog.h \
$$PWD/differ.h \
$$PWD/cpplanguage_details.h \
- $$PWD/jsontreeitem.h
+ $$PWD/jsontreeitem.h \
+ $$PWD/listmodel.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/newclasswidget.ui \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index d50f7f41f6..694045e290 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -33,7 +33,7 @@ Project {
cpp.frameworks: ["Foundation", "AppKit"]
}
- Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets"] }
+ Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets", "xml"] }
Depends { name: "Qt.macextras"; condition: qbs.targetOS.contains("macos") }
Depends { name: "app_version_header" }
@@ -146,6 +146,7 @@ Project {
"jsontreeitem.h",
"linecolumn.h",
"link.h",
+ "listmodel.h",
"listutils.h",
"macroexpander.cpp",
"macroexpander.h",
@@ -191,6 +192,8 @@ Project {
"proxycredentialsdialog.cpp",
"proxycredentialsdialog.h",
"proxycredentialsdialog.ui",
+ "qrcparser.cpp",
+ "qrcparser.h",
"qtcassert.cpp",
"qtcassert.h",
"qtcolorbutton.cpp",
diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc
index 6ad7dd3196..a8731b6b20 100644
--- a/src/libs/utils/utils.qrc
+++ b/src/libs/utils/utils.qrc
@@ -34,6 +34,8 @@
<file>images/locked@2x.png</file>
<file>images/unlocked.png</file>
<file>images/unlocked@2x.png</file>
+ <file>images/pinned.png</file>
+ <file>images/pinned@2x.png</file>
<file>images/broken.png</file>
<file>images/broken@2x.png</file>
<file>images/notloaded.png</file>
@@ -213,6 +215,14 @@
<file>images/macos_touchbar_bookmark@2x.png</file>
<file>images/macos_touchbar_clear.png</file>
<file>images/macos_touchbar_clear@2x.png</file>
+ <file>images/settings.png</file>
+ <file>images/settings@2x.png</file>
+ <file>images/sort_alphabetically.png</file>
+ <file>images/sort_alphabetically@2x.png</file>
+ <file>images/toggleprogressdetails.png</file>
+ <file>images/toggleprogressdetails@2x.png</file>
+ <file>images/unknownfile.png</file>
+ <file>images/dir.png</file>
</qresource>
<qresource prefix="/codemodel">
<file>images/enum.png</file>
diff --git a/src/libs/utils/utilsicons.cpp b/src/libs/utils/utilsicons.cpp
index 9855165c3e..2227f530c6 100644
--- a/src/libs/utils/utilsicons.cpp
+++ b/src/libs/utils/utilsicons.cpp
@@ -28,7 +28,6 @@
namespace Utils {
namespace Icons {
-
const Icon HOME({
{QLatin1String(":/utils/images/home.png"), Theme::PanelTextColorDark}}, Icon::Tint);
const Icon HOME_TOOLBAR({
@@ -43,6 +42,8 @@ const Icon LOCKED({
{QLatin1String(":/utils/images/locked.png"), Theme::PanelTextColorDark}}, Icon::Tint);
const Icon UNLOCKED_TOOLBAR({
{QLatin1String(":/utils/images/unlocked.png"), Theme::IconsBaseColor}});
+const Icon PINNED({
+ {QLatin1String(":/utils/images/pinned.png"), Theme::PanelTextColorDark}}, Icon::Tint);
const Icon NEXT({
{QLatin1String(":/utils/images/next.png"), Theme::IconsWarningColor}}, Icon::MenuTintedStyle);
const Icon NEXT_TOOLBAR({
@@ -85,6 +86,8 @@ const Icon SNAPSHOT_TOOLBAR({
const Icon NEWSEARCH_TOOLBAR({
{QLatin1String(":/utils/images/zoom.png"), Theme::IconsBaseColor},
{QLatin1String(":/utils/images/iconoverlay_add_small.png"), Theme::IconsRunColor}});
+const Icon SETTINGS_TOOLBAR({
+ {QLatin1String(":/utils/images/settings.png"), Theme::IconsBaseColor}});
const Icon NEWFILE({
{QLatin1String(":/utils/images/filenew.png"), Theme::PanelTextColorMid}}, Icon::Tint);
@@ -102,6 +105,11 @@ const Icon EXPORTFILE_TOOLBAR({
const Icon MULTIEXPORTFILE_TOOLBAR({
{QLatin1String(":/utils/images/filemultiexport.png"), Theme::IconsBaseColor}});
+const Icon UNKNOWN_FILE({
+ {QLatin1String(":/utils/images/unknownfile.png"), Theme::IconsBaseColor}});
+const Icon DIR({
+ {QLatin1String(":/utils/images/dir.png"), Theme::IconsBaseColor}});
+
const Icon UNDO({
{QLatin1String(":/utils/images/undo.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon UNDO_TOOLBAR({
@@ -182,6 +190,11 @@ const Icon LINK({
{QLatin1String(":/utils/images/linkicon.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon LINK_TOOLBAR({
{QLatin1String(":/utils/images/linkicon.png"), Theme::IconsBaseColor}});
+const Icon SORT_ALPHABETICALLY_TOOLBAR({
+ {QLatin1String(":/utils/images/sort_alphabetically.png"), Theme::IconsBaseColor}});
+const Icon TOGGLE_PROGRESSDETAILS_TOOLBAR({
+ {QLatin1String(":/utils/images/toggleprogressdetails.png"), Theme::IconsBaseColor}});
+
const Icon WARNING({
{QLatin1String(":/utils/images/warningfill.png"), Theme::BackgroundColorNormal},
{QLatin1String(":/utils/images/warning.png"), Theme::IconsWarningColor}}, Icon::Tint);
@@ -444,6 +457,10 @@ QIcon CodeModelIcon::iconForType(CodeModelIcon::Type type)
}, Icon::Tint).icon());
return icon;
}
+ case Unknown: {
+ const static QIcon icon(Icons::EMPTY16.icon());
+ return icon;
+ }
default:
break;
}
diff --git a/src/libs/utils/utilsicons.h b/src/libs/utils/utilsicons.h
index b229523911..ae6cd4d1dc 100644
--- a/src/libs/utils/utilsicons.h
+++ b/src/libs/utils/utilsicons.h
@@ -38,6 +38,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon EDIT_CLEAR_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon LOCKED_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon LOCKED;
QTCREATOR_UTILS_EXPORT extern const Icon UNLOCKED_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon PINNED;
QTCREATOR_UTILS_EXPORT extern const Icon NEXT;
QTCREATOR_UTILS_EXPORT extern const Icon NEXT_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon PREV;
@@ -56,6 +57,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TEXTEDITOR;
QTCREATOR_UTILS_EXPORT extern const Icon SNAPSHOT_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon NEWSEARCH_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon SETTINGS_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon NEWFILE;
QTCREATOR_UTILS_EXPORT extern const Icon OPENFILE;
@@ -66,6 +68,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 UNDO;
QTCREATOR_UTILS_EXPORT extern const Icon UNDO_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon REDO;
@@ -106,6 +111,8 @@ QTCREATOR_UTILS_EXPORT extern const Icon CLOSE_SPLIT_RIGHT;
QTCREATOR_UTILS_EXPORT extern const Icon FILTER;
QTCREATOR_UTILS_EXPORT extern const Icon LINK;
QTCREATOR_UTILS_EXPORT extern const Icon LINK_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon SORT_ALPHABETICALLY_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon TOGGLE_PROGRESSDETAILS_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon INFO;
QTCREATOR_UTILS_EXPORT extern const Icon INFO_TOOLBAR;
diff --git a/src/libs/utils/variant.h b/src/libs/utils/variant.h
index 00e9eaf252..371b9312d3 100644
--- a/src/libs/utils/variant.h
+++ b/src/libs/utils/variant.h
@@ -30,10 +30,25 @@
*/
// TODO: replace by #include <(experimental/)variant> depending on compiler and C++ version
-#include <3rdparty/variant/variant.hpp>
+#if __cplusplus >= 201703L
+#error Please delete variant.hpp and the #else section below, then remove this error
+#include <variant>
namespace Utils {
+using std::get;
+using std::get_if;
+using std::holds_alternative;
+using std::variant;
+} // namespace Utils
-using namespace mpark;
+#else
+#include <3rdparty/variant/variant.hpp>
+namespace Utils {
+using mpark::get;
+using mpark::get_if;
+using mpark::holds_alternative;
+using mpark::variant;
} // namespace Utils
+
+#endif
diff --git a/src/libs/utils/wizardpage.h b/src/libs/utils/wizardpage.h
index fa8c60b052..abeccfce13 100644
--- a/src/libs/utils/wizardpage.h
+++ b/src/libs/utils/wizardpage.h
@@ -29,6 +29,7 @@
#include <QSet>
#include <QString>
+#include <QVariant>
#include <QWizardPage>
#include <functional>
@@ -41,30 +42,30 @@ namespace Internal {
class QTCREATOR_UTILS_EXPORT ObjectToFieldWidgetConverter : public QWidget
{
Q_OBJECT
- Q_PROPERTY(QString text READ text NOTIFY textChanged)
+ Q_PROPERTY(QVariant value READ value NOTIFY valueChanged)
public:
- template <class T, typename... Arguments>
- static ObjectToFieldWidgetConverter *create(T *sender, void (T::*member)(Arguments...), const std::function<QString()> &toTextFunction)
+ template<class T, typename... Arguments>
+ static ObjectToFieldWidgetConverter *create(T *sender,
+ void (T::*member)(Arguments...),
+ const std::function<QVariant()> &toVariantFunction)
{
auto widget = new ObjectToFieldWidgetConverter();
- widget->toTextFunction = toTextFunction;
+ widget->toVariantFunction = toVariantFunction;
connect(sender, &QObject::destroyed, widget, &QObject::deleteLater);
- connect(sender, member, widget, [widget] () {
- emit widget->textChanged(widget->text());
- });
+ connect(sender, member, widget, [widget]() { emit widget->valueChanged(widget->value()); });
return widget;
}
signals:
- void textChanged(const QString&);
+ void valueChanged(const QVariant &);
private:
ObjectToFieldWidgetConverter () = default;
- // is used by the property text
- QString text() {return toTextFunction();}
- std::function<QString()> toTextFunction;
+ // is used by the property value
+ QVariant value() { return toVariantFunction(); }
+ std::function<QVariant()> toVariantFunction;
};
} // Internal
@@ -79,10 +80,17 @@ public:
virtual void pageWasAdded(); // called when this page was added to a Utils::Wizard
template<class T, typename... Arguments>
- void registerObjectAsFieldWithName(const QString &name, T *sender, void (T::*changeSignal)(Arguments...),
- const std::function<QString()> &senderToString)
+ void registerObjectAsFieldWithName(const QString &name,
+ T *sender,
+ void (T::*changeSignal)(Arguments...),
+ const std::function<QVariant()> &senderToVariant)
{
- registerFieldWithName(name, Internal::ObjectToFieldWidgetConverter::create(sender, changeSignal, senderToString), "text", SIGNAL(textChanged(QString)));
+ registerFieldWithName(name,
+ Internal::ObjectToFieldWidgetConverter::create(sender,
+ changeSignal,
+ senderToVariant),
+ "value",
+ SIGNAL(valueChanged(QValue)));
}
void registerFieldWithName(const QString &name, QWidget *widget,
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
new file mode 100644
index 0000000000..d81318c499
--- /dev/null
+++ b/src/plugins/CMakeLists.txt
@@ -0,0 +1,84 @@
+# Level 0:
+add_subdirectory(coreplugin)
+
+# Level 1: (only depends of Level 0)
+add_subdirectory(texteditor)
+add_subdirectory(serialterminal)
+add_subdirectory(helloworld)
+add_subdirectory(imageviewer)
+add_subdirectory(updateinfo)
+add_subdirectory(welcome)
+
+# Level 2: (only depends on Level 1 and below)
+add_subdirectory(bineditor)
+add_subdirectory(cpaster)
+add_subdirectory(diffeditor)
+add_subdirectory(emacskeys)
+add_subdirectory(macros)
+add_subdirectory(projectexplorer)
+add_subdirectory(silversearcher)
+
+# Level 3: (only depends on Level 2 and below)
+add_subdirectory(bookmarks)
+add_subdirectory(cpptools)
+add_subdirectory(help)
+add_subdirectory(resourceeditor)
+add_subdirectory(tasklist)
+add_subdirectory(nim)
+
+# Level 4: (only depends on Level 3 and below)
+add_subdirectory(clangpchmanager)
+add_subdirectory(classview)
+add_subdirectory(cppcheck)
+add_subdirectory(cppeditor)
+add_subdirectory(glsleditor)
+add_subdirectory(modeleditor)
+add_subdirectory(qtsupport)
+add_subdirectory(todo)
+add_subdirectory(vcsbase)
+
+# Level 5:
+add_subdirectory(bazaar)
+add_subdirectory(beautifier)
+add_subdirectory(clangformat)
+add_subdirectory(clangrefactoring)
+add_subdirectory(clearcase)
+add_subdirectory(cmakeprojectmanager)
+add_subdirectory(cvs)
+add_subdirectory(debugger)
+add_subdirectory(designer)
+add_subdirectory(fakevim)
+add_subdirectory(genericprojectmanager)
+add_subdirectory(git)
+add_subdirectory(mercurial)
+add_subdirectory(perforce)
+add_subdirectory(pythoneditor)
+add_subdirectory(qmakeprojectmanager)
+add_subdirectory(qmljstools)
+add_subdirectory(qmlprojectmanager)
+add_subdirectory(scxmleditor)
+add_subdirectory(subversion)
+add_subdirectory(compilationdatabaseprojectmanager)
+add_subdirectory(languageclient)
+add_subdirectory(studiowelcome)
+
+# Level 6:
+add_subdirectory(android)
+add_subdirectory(autotest)
+add_subdirectory(autotoolsprojectmanager)
+add_subdirectory(baremetal)
+add_subdirectory(clangcodemodel)
+add_subdirectory(clangtools)
+add_subdirectory(ios)
+add_subdirectory(qmljseditor)
+add_subdirectory(qmlpreview)
+add_subdirectory(qmlprofiler)
+add_subdirectory(remotelinux)
+add_subdirectory(valgrind)
+add_subdirectory(winrt)
+add_subdirectory(perfprofiler)
+add_subdirectory(qbsprojectmanager)
+
+# Level 7:
+add_subdirectory(qmldesigner)
+add_subdirectory(qnx)
diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt
new file mode 100644
index 0000000000..36bde749a9
--- /dev/null
+++ b/src/plugins/android/CMakeLists.txt
@@ -0,0 +1,52 @@
+add_qtc_plugin(Android
+ DEPENDS QtcSsh QmlDebug Qt5::Xml
+ PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
+ SOURCES
+ adbcommandswidget.cpp adbcommandswidget.h adbcommandswidget.ui
+ addnewavddialog.ui
+ android.qrc
+ android_global.h
+ androidavdmanager.cpp androidavdmanager.h
+ androidbuildapkstep.cpp androidbuildapkstep.h
+ androidbuildapkwidget.cpp androidbuildapkwidget.h
+ androidconfigurations.cpp androidconfigurations.h
+ androidconstants.h
+ androidcreatekeystorecertificate.cpp androidcreatekeystorecertificate.h androidcreatekeystorecertificate.ui
+ androiddebugsupport.cpp androiddebugsupport.h
+ androiddeployqtstep.cpp androiddeployqtstep.h
+ androiddevice.cpp androiddevice.h
+ androiddevicedialog.cpp androiddevicedialog.h androiddevicedialog.ui
+ androiderrormessage.cpp androiderrormessage.h
+ androidextralibrarylistmodel.cpp androidextralibrarylistmodel.h
+ androidgdbserverkitinformation.cpp androidgdbserverkitinformation.h
+ androidglobal.h
+ androidmanager.cpp androidmanager.h
+ androidmanifestdocument.cpp androidmanifestdocument.h
+ androidmanifesteditor.cpp androidmanifesteditor.h
+ androidmanifesteditorfactory.cpp androidmanifesteditorfactory.h
+ androidmanifesteditorwidget.cpp androidmanifesteditorwidget.h
+ androidpackageinstallationstep.cpp androidpackageinstallationstep.h
+ androidplugin.cpp androidplugin.h
+ androidpotentialkit.cpp androidpotentialkit.h
+ androidqmltoolingsupport.cpp androidqmltoolingsupport.h
+ androidqtversion.cpp androidqtversion.h
+ androidrunconfiguration.cpp androidrunconfiguration.h
+ androidruncontrol.cpp androidruncontrol.h
+ androidrunner.cpp androidrunner.h
+ androidrunnerworker.cpp androidrunnerworker.h
+ androidsdkmanager.cpp androidsdkmanager.h
+ androidsdkmanagerwidget.cpp androidsdkmanagerwidget.h androidsdkmanagerwidget.ui
+ androidsdkmodel.cpp androidsdkmodel.h
+ androidsdkpackage.cpp androidsdkpackage.h
+ androidsettingspage.cpp androidsettingspage.h
+ androidsettingswidget.cpp androidsettingswidget.h androidsettingswidget.ui
+ androidsignaloperation.cpp androidsignaloperation.h
+ androidtoolchain.cpp androidtoolchain.h
+ androidtoolmanager.cpp androidtoolmanager.h
+ avddialog.cpp avddialog.h
+ certificatesmodel.cpp certificatesmodel.h
+ createandroidmanifestwizard.cpp createandroidmanifestwizard.h
+ javaeditor.cpp javaeditor.h
+ javaindenter.cpp javaindenter.h
+ javaparser.cpp javaparser.h
+)
diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro
index e48edd2fee..f0a952c622 100644
--- a/src/plugins/android/android.pro
+++ b/src/plugins/android/android.pro
@@ -19,12 +19,10 @@ HEADERS += \
androidrunner.h \
androidrunnerworker.h \
androiddebugsupport.h \
- androidqtversionfactory.h \
androidqtversion.h \
androidcreatekeystorecertificate.h \
javaparser.h \
androidplugin.h \
- androiddevicefactory.h \
androiddevice.h \
androidgdbserverkitinformation.h \
androidqmltoolingsupport.h \
@@ -52,8 +50,7 @@ HEADERS += \
androidsdkmanagerwidget.h \
androidpackageinstallationstep.h \
androidextralibrarylistmodel.h \
- createandroidmanifestwizard.h \
- androidrunenvironmentaspect.h
+ createandroidmanifestwizard.h
SOURCES += \
androidconfigurations.cpp \
@@ -67,12 +64,10 @@ SOURCES += \
androidrunner.cpp \
androidrunnerworker.cpp \
androiddebugsupport.cpp \
- androidqtversionfactory.cpp \
androidqtversion.cpp \
androidcreatekeystorecertificate.cpp \
javaparser.cpp \
androidplugin.cpp \
- androiddevicefactory.cpp \
androiddevice.cpp \
androidgdbserverkitinformation.cpp \
androidqmltoolingsupport.cpp \
@@ -99,15 +94,13 @@ SOURCES += \
androidsdkmanagerwidget.cpp \
androidpackageinstallationstep.cpp \
androidextralibrarylistmodel.cpp \
- createandroidmanifestwizard.cpp \
- androidrunenvironmentaspect.cpp
+ createandroidmanifestwizard.cpp
FORMS += \
androidsettingswidget.ui \
addnewavddialog.ui \
androidcreatekeystorecertificate.ui \
androiddevicedialog.ui \
- androidbuildapkwidget.ui \
adbcommandswidget.ui \
androidsdkmanagerwidget.ui
diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs
index 912bca631e..1c6ed28a41 100644
--- a/src/plugins/android/android.qbs
+++ b/src/plugins/android/android.qbs
@@ -36,7 +36,6 @@ Project {
"androidbuildapkstep.h",
"androidbuildapkwidget.cpp",
"androidbuildapkwidget.h",
- "androidbuildapkwidget.ui",
"androiddeployqtstep.cpp",
"androiddeployqtstep.h",
"androiddebugsupport.cpp",
@@ -46,8 +45,6 @@ Project {
"androiddevicedialog.ui",
"androiddevice.cpp",
"androiddevice.h",
- "androiddevicefactory.cpp",
- "androiddevicefactory.h",
"androiderrormessage.h",
"androiderrormessage.cpp",
"androidextralibrarylistmodel.cpp",
@@ -75,12 +72,8 @@ Project {
"androidqmltoolingsupport.h",
"androidqtversion.cpp",
"androidqtversion.h",
- "androidqtversionfactory.cpp",
- "androidqtversionfactory.h",
"androidrunconfiguration.cpp",
"androidrunconfiguration.h",
- "androidrunenvironmentaspect.h",
- "androidrunenvironmentaspect.cpp",
"androidruncontrol.cpp",
"androidruncontrol.h",
"androidrunner.cpp",
diff --git a/src/plugins/android/androidavdmanager.cpp b/src/plugins/android/androidavdmanager.cpp
index f6fcd85c68..17a9eb9b59 100644
--- a/src/plugins/android/androidavdmanager.cpp
+++ b/src/plugins/android/androidavdmanager.cpp
@@ -290,9 +290,9 @@ bool AndroidAvdManager::startAvdAsync(const QString &avdName) const
return false;
}
auto avdProcess = new QProcess();
- avdProcess->setReadChannelMode(QProcess::MergedChannels);
+ avdProcess->setProcessChannelMode(QProcess::MergedChannels);
QObject::connect(avdProcess,
- static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
avdProcess,
std::bind(&avdProcessFinished, std::placeholders::_1, avdProcess));
@@ -429,12 +429,11 @@ bool AvdManagerOutputParser::parseAvd(const QStringList &deviceInfo, AndroidDevi
} else if (valueForKey(avdInfoNameKey, line, &value)) {
avd->avdname = value;
} else if (valueForKey(avdInfoPathKey, line, &value)) {
- const Utils::FileName avdPath = Utils::FileName::fromString(value);
+ const Utils::FilePath avdPath = Utils::FilePath::fromString(value);
if (avdPath.exists())
{
// Get ABI.
- Utils::FileName configFile = avdPath;
- configFile.appendPath("config.ini");
+ const Utils::FilePath configFile = avdPath.pathAppended("config.ini");
QSettings config(configFile.toString(), QSettings::IniFormat);
value = config.value(avdInfoAbiKey).toString();
if (!value.isEmpty())
@@ -443,9 +442,9 @@ bool AvdManagerOutputParser::parseAvd(const QStringList &deviceInfo, AndroidDevi
qCDebug(avdManagerLog) << "Avd Parsing: Cannot find ABI:" << configFile;
// Get Target
- Utils::FileName avdInfoFile = avdPath.parentDir();
QString avdInfoFileName = avdPath.toFileInfo().baseName() + ".ini";
- avdInfoFile.appendPath(avdInfoFileName);
+ const Utils::FilePath
+ avdInfoFile = avdPath.parentDir().pathAppended(avdInfoFileName);
QSettings avdInfo(avdInfoFile.toString(), QSettings::IniFormat);
value = avdInfo.value(avdInfoTargetKey).toString();
if (!value.isEmpty())
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index d4320b039a..b9d77469b7 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -54,10 +54,11 @@
#include <utils/synchronousprocess.h>
#include <utils/utilsicons.h>
-#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
-
+#include <QDateTime>
#include <QDialogButtonBox>
#include <QHBoxLayout>
+#include <QJsonDocument>
+#include <QJsonObject>
#include <QLabel>
#include <QLineEdit>
#include <QLoggingCategory>
@@ -69,6 +70,7 @@
#include <memory>
using namespace ProjectExplorer;
+using namespace Utils;
using namespace Android::Internal;
namespace {
@@ -89,10 +91,10 @@ static void setupProcessParameters(ProcessParameters *pp,
const QString &command)
{
pp->setMacroExpander(bc->macroExpander());
- pp->setWorkingDirectory(bc->buildDirectory().toString());
+ pp->setWorkingDirectory(bc->buildDirectory());
Utils::Environment env = bc->environment();
pp->setEnvironment(env);
- pp->setCommand(command);
+ pp->setCommand(FilePath::fromString(command));
pp->setArguments(Utils::QtcProcess::joinArgs(arguments));
pp->resolveAll();
}
@@ -160,13 +162,13 @@ bool AndroidBuildApkStep::init()
OutputFormat::ErrorMessage);
}
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target()->kit());
if (!version)
return false;
const QVersionNumber sdkToolsVersion = AndroidConfigurations::currentConfig().sdkToolsVersion();
if (sdkToolsVersion >= gradleScriptRevokedSdkVersion) {
- if (!version->sourcePath().appendPath("src/3rdparty/gradle").exists()) {
+ if (!version->sourcePath().pathAppended("src/3rdparty/gradle").exists()) {
emit addOutput(tr("The installed SDK tools version (%1) does not include Gradle "
"scripts. The minimum Qt version required for Gradle build to work "
"is %2").arg(sdkToolsVersion.toString()).arg("5.9.0/5.6.3"),
@@ -189,14 +191,19 @@ bool AndroidBuildApkStep::init()
auto parser = new JavaParser;
parser->setProjectFileList(Utils::transform(target()->project()->files(ProjectExplorer::Project::AllFiles),
- &Utils::FileName::toString));
+ &Utils::FilePath::toString));
RunConfiguration *rc = target()->activeRunConfiguration();
- const ProjectNode *node = rc ? target()->project()->findNodeForBuildKey(rc->buildKey()) : nullptr;
+ const QString buildKey = rc ? rc->buildKey() : QString();
+ const ProjectNode *node = rc ? target()->project()->findNodeForBuildKey(buildKey) : nullptr;
+
+ QString sourceDirName;
+ if (node)
+ sourceDirName = node->data(Constants::AndroidPackageSourceDir).toString();
- QFileInfo sourceDirInfo(node ? node->data(Constants::AndroidPackageSourceDir).toString() : QString());
- parser->setSourceDirectory(Utils::FileName::fromString(sourceDirInfo.canonicalFilePath()));
- parser->setBuildDirectory(Utils::FileName::fromString(bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString()));
+ QFileInfo sourceDirInfo(sourceDirName);
+ parser->setSourceDirectory(Utils::FilePath::fromString(sourceDirInfo.canonicalFilePath()));
+ parser->setBuildDirectory(bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY));
setOutputParser(parser);
m_openPackageLocationForRun = m_openPackageLocation;
@@ -213,7 +220,7 @@ bool AndroidBuildApkStep::init()
if (Utils::HostOsInfo::isWindowsHost())
command += ".exe";
- QString outputDir = bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString();
+ QString outputDir = bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString();
QString inputFile;
if (node)
@@ -273,7 +280,7 @@ bool AndroidBuildApkStep::init()
// Generate arguments with keystore password concealed
ProjectExplorer::ProcessParameters pp2;
setupProcessParameters(&pp2, bc, argumentsPasswordConcealed, command);
- m_command = pp2.effectiveCommand();
+ m_command = pp2.effectiveCommand().toString();
m_argumentsPasswordConcealed = pp2.prettyArguments();
return true;
@@ -340,13 +347,89 @@ bool AndroidBuildApkStep::verifyCertificatePassword()
return success;
}
+
+static bool copyFileIfNewer(const QString &sourceFileName,
+ const QString &destinationFileName)
+{
+ if (QFile::exists(destinationFileName)) {
+ QFileInfo destinationFileInfo(destinationFileName);
+ QFileInfo sourceFileInfo(sourceFileName);
+ if (sourceFileInfo.lastModified() <= destinationFileInfo.lastModified())
+ return true;
+ if (!QFile(destinationFileName).remove())
+ return false;
+ }
+
+ if (!QDir().mkpath(QFileInfo(destinationFileName).path()))
+ return false;
+ return QFile::copy(sourceFileName, destinationFileName);
+}
+
void AndroidBuildApkStep::doRun()
{
if (m_skipBuilding) {
- emit addOutput(tr("No application .pro file found, not building an APK."), BuildStep::OutputFormat::ErrorMessage);
+ emit addOutput(tr("Android deploy settings file not found, not building an APK."), BuildStep::OutputFormat::ErrorMessage);
emit finished(true);
return;
}
+
+ auto setup = [this] {
+ auto bc = target()->activeBuildConfiguration();
+ Utils::FilePath androidLibsDir = bc->buildDirectory()
+ .pathAppended("android-build/libs")
+ .pathAppended(AndroidManager::targetArch(target()));
+ if (!androidLibsDir.exists() && !QDir{bc->buildDirectory().toString()}.mkpath(androidLibsDir.toString()))
+ return false;
+
+
+ QJsonObject deploySettings = Android::AndroidManager::deploymentSettings(target());
+ RunConfiguration *rc = target()->activeRunConfiguration();
+ const QString buildKey = rc ? rc->buildKey() : QString();
+ const ProjectNode *node = rc ? target()->project()->findNodeForBuildKey(buildKey) : nullptr;
+
+ if (!node)
+ return false;
+
+ auto targets = node->data(Android::Constants::AndroidTargets).toStringList();
+ if (targets.isEmpty())
+ return true; // qmake does this job for us
+
+ // Copy targets to android build folder
+ for (const auto &target : targets) {
+ if (!copyFileIfNewer(target, androidLibsDir.pathAppended(QFileInfo{target}.fileName()).toString()))
+ return false;
+ }
+
+ QString extraLibs = node->data(Android::Constants::AndroidExtraLibs).toString();
+ if (!extraLibs.isEmpty())
+ deploySettings["android-extra-libs"] = extraLibs;
+
+ QString androidSrcs = node->data(Android::Constants::AndroidPackageSourceDir).toString();
+ if (!androidSrcs.isEmpty())
+ deploySettings["android-package-source-directory"] = androidSrcs;
+
+ QString qmlImportPath = node->data("QML_IMPORT_PATH").toString();
+ if (!qmlImportPath.isEmpty())
+ deploySettings["qml-import-paths"] = qmlImportPath;
+
+ QString qmlRootPath = node->data("QML_ROOT_PATH").toString();
+ if (qmlRootPath.isEmpty())
+ qmlRootPath = target()->project()->rootProjectDirectory().toString();
+ deploySettings["qml-root-path"] = qmlRootPath;
+
+ QFile f{bc->buildDirectory().pathAppended("android_deployment_settings.json").toString()};
+ if (!f.open(QIODevice::WriteOnly))
+ return false;
+ f.write(QJsonDocument{deploySettings}.toJson());
+ return true;
+ };
+
+ if (!setup()) {
+ emit addOutput(tr("Cannot set up Android, not building an APK."), BuildStep::OutputFormat::ErrorMessage);
+ emit finished(false);
+ return;
+ }
+
AbstractProcessStep::doRun();
}
@@ -360,7 +443,7 @@ void AndroidBuildApkStep::processStarted()
bool AndroidBuildApkStep::fromMap(const QVariantMap &map)
{
- m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString());
+ m_keystorePath = Utils::FilePath::fromString(map.value(KeystoreLocationKey).toString());
m_signPackage = false; // don't restore this
m_buildTargetSdk = map.value(BuildTargetSdkKey).toString();
if (m_buildTargetSdk.isEmpty()) {
@@ -382,7 +465,7 @@ QVariantMap AndroidBuildApkStep::toMap() const
return map;
}
-Utils::FileName AndroidBuildApkStep::keystorePath()
+Utils::FilePath AndroidBuildApkStep::keystorePath()
{
return m_keystorePath;
}
@@ -398,7 +481,19 @@ void AndroidBuildApkStep::setBuildTargetSdk(const QString &sdk)
AndroidManager::updateGradleProperties(target());
}
-void AndroidBuildApkStep::setKeystorePath(const Utils::FileName &path)
+QVariant AndroidBuildApkStep::data(Core::Id id) const
+{
+ if (id == Constants::AndroidNdkPlatform)
+ return AndroidConfigurations::currentConfig().bestNdkPlatformMatch(AndroidManager::minimumSDK(target())).mid(8);
+ if (id == Constants::NdkLocation)
+ return QVariant::fromValue(AndroidConfigurations::currentConfig().ndkLocation());
+ if (id == Constants::AndroidABI)
+ return AndroidManager::targetArch(target());
+
+ return AbstractProcessStep::data(id);
+}
+
+void AndroidBuildApkStep::setKeystorePath(const Utils::FilePath &path)
{
m_keystorePath = path;
m_certificatePasswd.clear();
@@ -568,7 +663,6 @@ namespace Internal {
AndroidBuildApkStepFactory::AndroidBuildApkStepFactory()
{
registerStep<AndroidBuildApkStep>(Constants::ANDROID_BUILD_APK_ID);
- setSupportedProjectType(QmakeProjectManager::Constants::QMAKEPROJECT_ID);
setSupportedDeviceType(Constants::ANDROID_DEVICE_TYPE);
setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
setDisplayName(AndroidBuildApkStep::tr("Build Android APK"));
diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h
index e336d5c5c7..9e7ec4a07a 100644
--- a/src/plugins/android/androidbuildapkstep.h
+++ b/src/plugins/android/androidbuildapkstep.h
@@ -51,8 +51,8 @@ public:
QVariantMap toMap() const override;
// signing
- Utils::FileName keystorePath();
- void setKeystorePath(const Utils::FileName &path);
+ Utils::FilePath keystorePath();
+ void setKeystorePath(const Utils::FilePath &path);
void setKeystorePassword(const QString &pwd);
void setCertificateAlias(const QString &alias);
void setCertificatePassword(const QString &pwd);
@@ -76,6 +76,7 @@ public:
QString buildTargetSdk() const;
void setBuildTargetSdk(const QString &sdk);
+ QVariant data(Core::Id id) const override;
private:
Q_INVOKABLE void showInGraphicalShell();
@@ -96,7 +97,7 @@ private:
bool m_addDebugger = true;
QString m_buildTargetSdk;
- Utils::FileName m_keystorePath;
+ Utils::FilePath m_keystorePath;
QString m_keystorePasswd;
QString m_certificateAlias;
QString m_certificatePasswd;
diff --git a/src/plugins/android/androidbuildapkwidget.cpp b/src/plugins/android/androidbuildapkwidget.cpp
index 02d0c3e92b..ff8441f889 100644
--- a/src/plugins/android/androidbuildapkwidget.cpp
+++ b/src/plugins/android/androidbuildapkwidget.cpp
@@ -24,14 +24,15 @@
**
****************************************************************************/
-#include "androidbuildapkstep.h"
#include "androidbuildapkwidget.h"
+
+#include "androidbuildapkstep.h"
#include "androidconfigurations.h"
+#include "androidextralibrarylistmodel.h"
#include "androidcreatekeystorecertificate.h"
#include "androidmanager.h"
#include "androidsdkmanager.h"
#include "createandroidmanifestwizard.h"
-#include "ui_androidbuildapkwidget.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
@@ -45,8 +46,10 @@
#include <utils/pathchooser.h>
#include <utils/utilsicons.h>
-#include <QFileDialog>
+#include <QCheckBox>
+#include <QComboBox>
#include <QGroupBox>
+#include <QFileDialog>
#include <QLabel>
#include <QListView>
#include <QPushButton>
@@ -56,271 +59,297 @@
#include <algorithm>
using namespace ProjectExplorer;
+using namespace Utils;
namespace Android {
namespace Internal {
-AndroidBuildApkInnerWidget::AndroidBuildApkInnerWidget(AndroidBuildApkStep *step)
- : ProjectExplorer::BuildStepConfigWidget(step),
- m_ui(new Ui::AndroidBuildApkWidget),
- m_step(step)
+AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
+ : BuildStepConfigWidget(step), m_step(step)
{
- m_ui->setupUi(this);
setDisplayName("<b>" + tr("Build Android APK") + "</b>");
setSummaryText(displayName());
- // Target sdk combobox
- const int minApiSupported = AndroidManager::apiLevelRange().first;
- QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::sdkManager()->
- filteredSdkPlatforms(minApiSupported));
- targets.removeDuplicates();
- m_ui->targetSDKComboBox->addItems(targets);
- m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(AndroidManager::buildTargetSDK(step->target())));
-
- // Ministro
- if (m_step->useMinistro())
- m_ui->ministroOption->setChecked(true);
-
- // signing
- m_ui->signPackageCheckBox->setChecked(m_step->signPackage());
- m_ui->KeystoreLocationPathChooser->setExpectedKind(Utils::PathChooser::File);
- m_ui->KeystoreLocationPathChooser->lineEdit()->setReadOnly(true);
- m_ui->KeystoreLocationPathChooser->setPath(m_step->keystorePath().toUserOutput());
- m_ui->KeystoreLocationPathChooser->setInitialBrowsePathBackup(QDir::homePath());
- m_ui->KeystoreLocationPathChooser->setPromptDialogFilter(tr("Keystore files (*.keystore *.jks)"));
- m_ui->KeystoreLocationPathChooser->setPromptDialogTitle(tr("Select Keystore File"));
- m_ui->signingDebugWarningIcon->setPixmap(Utils::Icons::WARNING.pixmap());
- m_ui->signingDebugWarningIcon->hide();
- m_ui->signingDebugWarningLabel->hide();
- signPackageCheckBoxToggled(m_step->signPackage());
-
- m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput());
- m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
- m_ui->addDebuggerCheckBox->setChecked(m_step->addDebugger());
+ auto vbox = new QVBoxLayout(this);
+ vbox->addWidget(createSignPackageGroup());
+ vbox->addWidget(createApplicationGroup());
+ vbox->addWidget(createAdvancedGroup());
+ vbox->addWidget(createCreateTemplatesGroup());
+ vbox->addWidget(createAdditionalLibrariesGroup());
- // target sdk
- connect(m_ui->targetSDKComboBox,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
- this, &AndroidBuildApkInnerWidget::setTargetSdk);
+ connect(m_step->buildConfiguration(), &BuildConfiguration::buildTypeChanged,
+ this, &AndroidBuildApkWidget::updateSigningWarning);
- // deployment options
- connect(m_ui->ministroOption, &QAbstractButton::clicked,
- m_step, &AndroidBuildApkStep::setUseMinistro);
-
- connect(m_ui->openPackageLocationCheckBox, &QAbstractButton::toggled,
- this, &AndroidBuildApkInnerWidget::openPackageLocationCheckBoxToggled);
- connect(m_ui->verboseOutputCheckBox, &QAbstractButton::toggled,
- this, &AndroidBuildApkInnerWidget::verboseOutputCheckBoxToggled);
- connect(m_ui->addDebuggerCheckBox, &QAbstractButton::toggled,
- m_step, &AndroidBuildApkStep::setAddDebugger);
-
- //signing
- connect(m_ui->signPackageCheckBox, &QAbstractButton::toggled,
- this, &AndroidBuildApkInnerWidget::signPackageCheckBoxToggled);
- connect(m_ui->KeystoreCreatePushButton, &QAbstractButton::clicked,
- this, &AndroidBuildApkInnerWidget::createKeyStore);
- connect(m_ui->KeystoreLocationPathChooser, &Utils::PathChooser::pathChanged,
- this, &AndroidBuildApkInnerWidget::updateKeyStorePath);
- connect(m_ui->certificatesAliasComboBox,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
- this, &AndroidBuildApkInnerWidget::certificatesAliasComboBoxActivated);
- connect(m_ui->certificatesAliasComboBox,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
- this, &AndroidBuildApkInnerWidget::certificatesAliasComboBoxCurrentIndexChanged);
-
- connect(m_step->buildConfiguration(), &ProjectExplorer::BuildConfiguration::buildTypeChanged,
- this, &AndroidBuildApkInnerWidget::updateSigningWarning);
+ connect(m_signPackageCheckBox, &QAbstractButton::clicked,
+ m_addDebuggerCheckBox, &QWidget::setEnabled);
+ signPackageCheckBoxToggled(m_step->signPackage());
updateSigningWarning();
}
-AndroidBuildApkInnerWidget::~AndroidBuildApkInnerWidget()
+QWidget *AndroidBuildApkWidget::createApplicationGroup()
{
- delete m_ui;
-}
-
-void AndroidBuildApkInnerWidget::setTargetSdk(const QString &sdk)
-{
- m_step->setBuildTargetSdk(sdk);
-}
+ const int minApiSupported = AndroidManager::apiLevelRange().first;
+ QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::sdkManager()->
+ filteredSdkPlatforms(minApiSupported));
+ targets.removeDuplicates();
-void AndroidBuildApkInnerWidget::signPackageCheckBoxToggled(bool checked)
-{
- m_ui->certificatesAliasComboBox->setEnabled(checked);
- m_step->setSignPackage(checked);
- m_ui->addDebuggerCheckBox->setChecked(!checked);
- updateSigningWarning();
- if (!checked)
- return;
- if (!m_step->keystorePath().isEmpty())
- setCertificates();
-}
+ auto group = new QGroupBox(tr("Application"), this);
-void AndroidBuildApkInnerWidget::createKeyStore()
-{
- AndroidCreateKeystoreCertificate d;
- if (d.exec() != QDialog::Accepted)
- return;
- m_ui->KeystoreLocationPathChooser->setPath(d.keystoreFilePath().toUserOutput());
- m_step->setKeystorePath(d.keystoreFilePath());
- m_step->setKeystorePassword(d.keystorePassword());
- m_step->setCertificateAlias(d.certificateAlias());
- m_step->setCertificatePassword(d.certificatePassword());
- setCertificates();
-}
+ auto targetSDKComboBox = new QComboBox(group);
+ targetSDKComboBox->addItems(targets);
+ targetSDKComboBox->setCurrentIndex(targets.indexOf(AndroidManager::buildTargetSDK(step()->target())));
-void AndroidBuildApkInnerWidget::setCertificates()
-{
- QAbstractItemModel *certificates = m_step->keystoreCertificates();
- if (certificates) {
- m_ui->signPackageCheckBox->setChecked(certificates);
- m_ui->certificatesAliasComboBox->setModel(certificates);
- }
-}
+ const auto cbActivated = QOverload<int>::of(&QComboBox::activated);
+ connect(targetSDKComboBox, cbActivated, this, [this, targetSDKComboBox](int idx) {
+ const QString sdk = targetSDKComboBox->itemText(idx);
+ m_step->setBuildTargetSdk(sdk);
+ });
-void AndroidBuildApkInnerWidget::updateKeyStorePath(const QString &path)
-{
- Utils::FileName file = Utils::FileName::fromString(path);
- m_step->setKeystorePath(file);
- m_ui->signPackageCheckBox->setChecked(!file.isEmpty());
- if (!file.isEmpty())
- setCertificates();
-}
+ auto hbox = new QHBoxLayout(group);
+ hbox->addWidget(new QLabel(tr("Android build SDK:"), group));
+ hbox->addWidget(targetSDKComboBox);
-void AndroidBuildApkInnerWidget::certificatesAliasComboBoxActivated(const QString &alias)
-{
- if (alias.length())
- m_step->setCertificateAlias(alias);
+ return group;
}
-void AndroidBuildApkInnerWidget::certificatesAliasComboBoxCurrentIndexChanged(const QString &alias)
+QWidget *AndroidBuildApkWidget::createSignPackageGroup()
{
- if (alias.length())
- m_step->setCertificateAlias(alias);
-}
+ QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+
+ auto group = new QGroupBox(tr("Sign package"), this);
+
+ auto keystoreLocationLabel = new QLabel(tr("Keystore:"), group);
+ keystoreLocationLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ auto keystoreLocationChooser = new PathChooser(group);
+ keystoreLocationChooser->setExpectedKind(PathChooser::File);
+ keystoreLocationChooser->lineEdit()->setReadOnly(true);
+ keystoreLocationChooser->setPath(m_step->keystorePath().toUserOutput());
+ keystoreLocationChooser->setInitialBrowsePathBackup(QDir::homePath());
+ keystoreLocationChooser->setPromptDialogFilter(tr("Keystore files (*.keystore *.jks)"));
+ keystoreLocationChooser->setPromptDialogTitle(tr("Select Keystore File"));
+ connect(keystoreLocationChooser, &PathChooser::pathChanged, this, [this](const QString &path) {
+ FilePath file = FilePath::fromString(path);
+ m_step->setKeystorePath(file);
+ m_signPackageCheckBox->setChecked(!file.isEmpty());
+ if (!file.isEmpty())
+ setCertificates();
+ });
-void AndroidBuildApkInnerWidget::openPackageLocationCheckBoxToggled(bool checked)
-{
- m_step->setOpenPackageLocation(checked);
-}
+ auto keystoreCreateButton = new QPushButton(tr("Create..."), group);
+ connect(keystoreCreateButton, &QAbstractButton::clicked, this, [this, keystoreLocationChooser] {
+ AndroidCreateKeystoreCertificate d;
+ if (d.exec() != QDialog::Accepted)
+ return;
+ keystoreLocationChooser->setPath(d.keystoreFilePath().toUserOutput());
+ m_step->setKeystorePath(d.keystoreFilePath());
+ m_step->setKeystorePassword(d.keystorePassword());
+ m_step->setCertificateAlias(d.certificateAlias());
+ m_step->setCertificatePassword(d.certificatePassword());
+ setCertificates();
+ });
-void AndroidBuildApkInnerWidget::verboseOutputCheckBoxToggled(bool checked)
-{
- m_step->setVerboseOutput(checked);
+ m_signPackageCheckBox = new QCheckBox(tr("Sign package"), group);
+ m_signPackageCheckBox->setChecked(m_step->signPackage());
+
+ m_signingDebugWarningIcon = new QLabel(group);
+ m_signingDebugWarningIcon->setSizePolicy(sizePolicy);
+ m_signingDebugWarningIcon->setPixmap(Icons::WARNING.pixmap());
+ m_signingDebugWarningIcon->hide();
+
+ m_signingDebugWarningLabel = new QLabel(tr("Signing a debug package"), group);
+ m_signingDebugWarningLabel->setSizePolicy(sizePolicy);
+ m_signingDebugWarningLabel->hide();
+
+ auto certificateAliasLabel = new QLabel(tr("Certificate alias:"), group);
+ certificateAliasLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ m_certificatesAliasComboBox = new QComboBox(group);
+ m_certificatesAliasComboBox->setEnabled(false);
+ QSizePolicy sizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ sizePolicy2.setHorizontalStretch(0);
+ sizePolicy2.setVerticalStretch(0);
+ m_certificatesAliasComboBox->setSizePolicy(sizePolicy2);
+ m_certificatesAliasComboBox->setMinimumSize(QSize(300, 0));
+
+ auto horizontalLayout_2 = new QHBoxLayout;
+ horizontalLayout_2->addWidget(keystoreLocationLabel);
+ horizontalLayout_2->addWidget(keystoreLocationChooser);
+ horizontalLayout_2->addWidget(keystoreCreateButton);
+
+ auto horizontalLayout_3 = new QHBoxLayout;
+ horizontalLayout_3->addWidget(m_signingDebugWarningIcon);
+ horizontalLayout_3->addWidget(m_signingDebugWarningLabel);
+ horizontalLayout_3->addWidget(certificateAliasLabel);
+ horizontalLayout_3->addWidget(m_certificatesAliasComboBox);
+
+ auto vbox = new QVBoxLayout(group);
+ vbox->addLayout(horizontalLayout_2);
+ vbox->addWidget(m_signPackageCheckBox);
+ vbox->addLayout(horizontalLayout_3);
+
+ connect(m_signPackageCheckBox, &QAbstractButton::toggled,
+ this, &AndroidBuildApkWidget::signPackageCheckBoxToggled);
+
+ auto updateAlias = [this](int idx) {
+ QString alias = m_certificatesAliasComboBox->itemText(idx);
+ if (alias.length())
+ m_step->setCertificateAlias(alias);
+ };
+
+ const auto cbActivated = QOverload<int>::of(&QComboBox::activated);
+ const auto cbCurrentIndexChanged = QOverload<int>::of(&QComboBox::currentIndexChanged);
+
+ connect(m_certificatesAliasComboBox, cbActivated, this, updateAlias);
+ connect(m_certificatesAliasComboBox, cbCurrentIndexChanged, this, updateAlias);
+
+ return group;
}
-void AndroidBuildApkInnerWidget::updateSigningWarning()
+QWidget *AndroidBuildApkWidget::createAdvancedGroup()
{
- bool nonRelease = m_step->buildConfiguration()->buildType()
- != ProjectExplorer::BuildConfiguration::Release;
- if (m_step->signPackage() && nonRelease) {
- m_ui->signingDebugWarningIcon->setVisible(true);
- m_ui->signingDebugWarningLabel->setVisible(true);
- } else {
- m_ui->signingDebugWarningIcon->setVisible(false);
- m_ui->signingDebugWarningLabel->setVisible(false);
- }
-}
+ auto group = new QGroupBox(tr("Advanced Actions"), this);
+
+ auto openPackageLocationCheckBox = new QCheckBox(tr("Open package location after build"), group);
+ openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
+ connect(openPackageLocationCheckBox, &QAbstractButton::toggled,
+ this, [this](bool checked) { m_step->setOpenPackageLocation(checked); });
+
+ m_addDebuggerCheckBox = new QCheckBox(tr("Add debug server"), group);
+ m_addDebuggerCheckBox->setEnabled(false);
+ m_addDebuggerCheckBox->setToolTip(tr("Packages debug server with "
+ "the APK to enable debugging. For the signed APK this option is unchecked by default."));
+ m_addDebuggerCheckBox->setChecked(m_step->addDebugger());
+ connect(m_addDebuggerCheckBox, &QAbstractButton::toggled,
+ m_step, &AndroidBuildApkStep::setAddDebugger);
+ auto verboseOutputCheckBox = new QCheckBox(tr("Verbose output"), group);
+ verboseOutputCheckBox->setChecked(m_step->verboseOutput());
-// AndroidBuildApkWidget
+ auto ministroOption = new QCheckBox(tr("Use Ministro service to install Qt"), group);
+ ministroOption->setToolTip(tr("Uses the external Ministro application to download and maintain Qt libraries."));
+ ministroOption->setChecked(m_step->useMinistro());
+ connect(ministroOption, &QAbstractButton::clicked,
+ m_step, &AndroidBuildApkStep::setUseMinistro);
-AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step) :
- BuildStepConfigWidget(step),
- m_step(step)
-{
- setDisplayName("<b>" + tr("Build Android APK") + "</b>");
- setSummaryText("<b>" + tr("Build Android APK") + "</b>");
+ auto vbox = new QVBoxLayout(group);
+ vbox->addWidget(openPackageLocationCheckBox);
+ vbox->addWidget(verboseOutputCheckBox);
+ vbox->addWidget(m_addDebuggerCheckBox);
+ vbox->addWidget(ministroOption);
- m_extraLibraryListModel = new AndroidExtraLibraryListModel(m_step->target(), this);
+ connect(verboseOutputCheckBox, &QAbstractButton::toggled,
+ this, [this](bool checked) { m_step->setVerboseOutput(checked); });
- auto base = new AndroidBuildApkInnerWidget(step);
- base->layout()->setContentsMargins(0, 0, 0, 0);
+ return group;
+}
+QWidget *AndroidBuildApkWidget::createCreateTemplatesGroup()
+{
auto createTemplatesGroupBox = new QGroupBox(tr("Android"));
createTemplatesGroupBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
auto createAndroidTemplatesButton = new QPushButton(tr("Create Templates"));
+ connect(createAndroidTemplatesButton, &QAbstractButton::clicked, this, [this] {
+ CreateAndroidManifestWizard wizard(m_step->target());
+ wizard.exec();
+ });
auto horizontalLayout = new QHBoxLayout(createTemplatesGroupBox);
horizontalLayout->addWidget(createAndroidTemplatesButton);
horizontalLayout->addStretch(1);
- auto additionalLibrariesGroupBox = new QGroupBox(tr("Additional Libraries"));
- additionalLibrariesGroupBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
-
- m_androidExtraLibsListView = new QListView;
- m_androidExtraLibsListView->setSelectionMode(QAbstractItemView::ExtendedSelection);
- m_androidExtraLibsListView->setToolTip(tr("List of extra libraries to include in Android package and load on startup."));
- m_androidExtraLibsListView->setModel(m_extraLibraryListModel);
-
- auto addAndroidExtraLibButton = new QToolButton;
- addAndroidExtraLibButton->setText(tr("Add..."));
- addAndroidExtraLibButton->setToolTip(tr("Select library to include in package."));
- addAndroidExtraLibButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
- addAndroidExtraLibButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
-
- m_removeAndroidExtraLibButton = new QToolButton;
- m_removeAndroidExtraLibButton->setText(tr("Remove"));
- m_removeAndroidExtraLibButton->setToolTip(tr("Remove currently selected library from list."));
-
- auto androidExtraLibsButtonLayout = new QVBoxLayout();
- androidExtraLibsButtonLayout->addWidget(addAndroidExtraLibButton);
- androidExtraLibsButtonLayout->addWidget(m_removeAndroidExtraLibButton);
- androidExtraLibsButtonLayout->addStretch(1);
-
- auto androidExtraLibsLayout = new QHBoxLayout(additionalLibrariesGroupBox);
- androidExtraLibsLayout->addWidget(m_androidExtraLibsListView);
- androidExtraLibsLayout->addLayout(androidExtraLibsButtonLayout);
-
- auto topLayout = new QVBoxLayout(this);
- topLayout->addWidget(base);
- topLayout->addWidget(createTemplatesGroupBox);
- topLayout->addWidget(additionalLibrariesGroupBox);
+ return createTemplatesGroupBox;
+}
- connect(createAndroidTemplatesButton, &QAbstractButton::clicked, this, [this] {
- CreateAndroidManifestWizard wizard(m_step->target());
- wizard.exec();
+QWidget *AndroidBuildApkWidget::createAdditionalLibrariesGroup()
+{
+ auto group = new QGroupBox(tr("Additional Libraries"));
+ group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
+
+ auto libsModel = new AndroidExtraLibraryListModel(m_step->target(), this);
+ connect(libsModel, &AndroidExtraLibraryListModel::enabledChanged,
+ group, &QWidget::setEnabled);
+
+ auto libsView = new QListView;
+ libsView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ libsView->setToolTip(tr("List of extra libraries to include in Android package and load on startup."));
+ libsView->setModel(libsModel);
+
+ auto addLibButton = new QToolButton;
+ addLibButton->setText(tr("Add..."));
+ addLibButton->setToolTip(tr("Select library to include in package."));
+ addLibButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ addLibButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
+ connect(addLibButton, &QAbstractButton::clicked, this, [this, libsModel] {
+ QStringList fileNames = QFileDialog::getOpenFileNames(this,
+ tr("Select additional libraries"),
+ QDir::homePath(),
+ tr("Libraries (*.so)"));
+ if (!fileNames.isEmpty())
+ libsModel->addEntries(fileNames);
});
- connect(addAndroidExtraLibButton, &QAbstractButton::clicked,
- this, &AndroidBuildApkWidget::addAndroidExtraLib);
+ auto removeLibButton = new QToolButton;
+ removeLibButton->setText(tr("Remove"));
+ removeLibButton->setToolTip(tr("Remove currently selected library from list."));
+ connect(removeLibButton, &QAbstractButton::clicked, this, [libsModel, libsView] {
+ QModelIndexList removeList = libsView->selectionModel()->selectedIndexes();
+ libsModel->removeEntries(removeList);
+ });
- connect(m_removeAndroidExtraLibButton, &QAbstractButton::clicked,
- this, &AndroidBuildApkWidget::removeAndroidExtraLib);
+ auto libsButtonLayout = new QVBoxLayout;
+ libsButtonLayout->addWidget(addLibButton);
+ libsButtonLayout->addWidget(removeLibButton);
+ libsButtonLayout->addStretch(1);
- connect(m_androidExtraLibsListView->selectionModel(), &QItemSelectionModel::selectionChanged,
- this, &AndroidBuildApkWidget::checkEnableRemoveButton);
+ auto hbox = new QHBoxLayout(group);
+ hbox->addWidget(libsView);
+ hbox->addLayout(libsButtonLayout);
- connect(m_extraLibraryListModel, &AndroidExtraLibraryListModel::enabledChanged,
- additionalLibrariesGroupBox, &QWidget::setEnabled);
+ QItemSelectionModel *libSelection = libsView->selectionModel();
+ connect(libSelection, &QItemSelectionModel::selectionChanged, this, [libSelection, removeLibButton] {
+ removeLibButton->setEnabled(libSelection->hasSelection());
+ });
Target *target = m_step->target();
RunConfiguration *rc = target->activeRunConfiguration();
const ProjectNode *node = rc ? target->project()->findNodeForBuildKey(rc->buildKey()) : nullptr;
- additionalLibrariesGroupBox->setEnabled(node && !node->parseInProgress());
+ group->setEnabled(node && !node->parseInProgress());
+
+ return group;
}
-void AndroidBuildApkWidget::addAndroidExtraLib()
+void AndroidBuildApkWidget::signPackageCheckBoxToggled(bool checked)
{
- QStringList fileNames = QFileDialog::getOpenFileNames(this,
- tr("Select additional libraries"),
- QDir::homePath(),
- tr("Libraries (*.so)"));
-
- if (!fileNames.isEmpty())
- m_extraLibraryListModel->addEntries(fileNames);
+ m_certificatesAliasComboBox->setEnabled(checked);
+ m_step->setSignPackage(checked);
+ m_addDebuggerCheckBox->setChecked(!checked);
+ updateSigningWarning();
+ if (!checked)
+ return;
+ if (!m_step->keystorePath().isEmpty())
+ setCertificates();
}
-void AndroidBuildApkWidget::removeAndroidExtraLib()
+void AndroidBuildApkWidget::setCertificates()
{
- QModelIndexList removeList = m_androidExtraLibsListView->selectionModel()->selectedIndexes();
- m_extraLibraryListModel->removeEntries(removeList);
+ QAbstractItemModel *certificates = m_step->keystoreCertificates();
+ if (certificates) {
+ m_signPackageCheckBox->setChecked(certificates);
+ m_certificatesAliasComboBox->setModel(certificates);
+ }
}
-void AndroidBuildApkWidget::checkEnableRemoveButton()
+void AndroidBuildApkWidget::updateSigningWarning()
{
- m_removeAndroidExtraLibButton->setEnabled(m_androidExtraLibsListView->selectionModel()->hasSelection());
+ bool nonRelease = m_step->buildConfiguration()->buildType() != BuildConfiguration::Release;
+ bool visible = m_step->signPackage() && nonRelease;
+ m_signingDebugWarningIcon->setVisible(visible);
+ m_signingDebugWarningLabel->setVisible(visible);
}
} // Internal
diff --git a/src/plugins/android/androidbuildapkwidget.h b/src/plugins/android/androidbuildapkwidget.h
index 03dcf21ec2..4c35b5dcd7 100644
--- a/src/plugins/android/androidbuildapkwidget.h
+++ b/src/plugins/android/androidbuildapkwidget.h
@@ -29,67 +29,43 @@
#include "android_global.h"
#include "androidbuildapkstep.h"
-#include "androidextralibrarylistmodel.h"
#include <projectexplorer/buildstep.h>
-#include <QListView>
-#include <QToolButton>
-
QT_BEGIN_NAMESPACE
-namespace Ui { class AndroidBuildApkWidget; }
+class QCheckBox;
+class QComboBox;
+class QLabel;
QT_END_NAMESPACE
namespace Android {
namespace Internal {
-class AndroidBuildApkInnerWidget : public ProjectExplorer::BuildStepConfigWidget
+class AndroidBuildApkWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
- AndroidBuildApkInnerWidget(AndroidBuildApkStep *step);
- ~AndroidBuildApkInnerWidget() override;
+ explicit AndroidBuildApkWidget(AndroidBuildApkStep *step);
private:
- void setTargetSdk(const QString &sdk);
- void createKeyStore();
- void certificatesAliasComboBoxCurrentIndexChanged(const QString &alias);
- void certificatesAliasComboBoxActivated(const QString &alias);
+ void setCertificates();
void updateSigningWarning();
- void openPackageLocationCheckBoxToggled(bool checked);
- void verboseOutputCheckBoxToggled(bool checked);
- void updateKeyStorePath(const QString &path);
void signPackageCheckBoxToggled(bool checked);
- void setCertificates();
-
- Ui::AndroidBuildApkWidget *m_ui;
- AndroidBuildApkStep *m_step;
-};
-
-class AndroidBuildApkWidget : public ProjectExplorer::BuildStepConfigWidget
-{
- Q_OBJECT
-
-public:
- explicit AndroidBuildApkWidget(AndroidBuildApkStep *step);
-
-signals:
- void requestAndroidTemplates();
-
-private:
- void addAndroidExtraLib();
- void removeAndroidExtraLib();
- void checkEnableRemoveButton();
+ QWidget *createApplicationGroup();
+ QWidget *createSignPackageGroup();
+ QWidget *createAdvancedGroup();
+ QWidget *createCreateTemplatesGroup();
+ QWidget *createAdditionalLibrariesGroup();
private:
- QListView *m_androidExtraLibsListView = nullptr;
- QToolButton *m_removeAndroidExtraLibButton = nullptr;
-
AndroidBuildApkStep *m_step = nullptr;
- Android::AndroidExtraLibraryListModel *m_extraLibraryListModel = nullptr;
- bool m_ignoreChange = false;
+ QCheckBox *m_signPackageCheckBox = nullptr;
+ QLabel *m_signingDebugWarningIcon = nullptr;
+ QLabel *m_signingDebugWarningLabel = nullptr;
+ QComboBox *m_certificatesAliasComboBox = nullptr;
+ QCheckBox *m_addDebuggerCheckBox = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/android/androidbuildapkwidget.ui b/src/plugins/android/androidbuildapkwidget.ui
deleted file mode 100644
index 98c53b64b7..0000000000
--- a/src/plugins/android/androidbuildapkwidget.ui
+++ /dev/null
@@ -1,217 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>AndroidBuildApkWidget</class>
- <widget class="QWidget" name="AndroidBuildApkWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>641</width>
- <height>349</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="1" column="0" colspan="2">
- <widget class="QGroupBox" name="signPackage">
- <property name="title">
- <string>Sign package</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLabel" name="KeystoreLocationLabel">
- <property name="text">
- <string>Keystore:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Utils::PathChooser" name="KeystoreLocationPathChooser" native="true"/>
- </item>
- <item>
- <widget class="QPushButton" name="KeystoreCreatePushButton">
- <property name="text">
- <string>Create...</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QCheckBox" name="signPackageCheckBox">
- <property name="text">
- <string>Sign package</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QLabel" name="signingDebugWarningIcon">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="signingDebugWarningLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Signing a debug package</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="KeystoreLocationLabel_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Certificate alias:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="certificatesAliasComboBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>300</width>
- <height>0</height>
- </size>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="0" colspan="2">
- <widget class="QGroupBox" name="application">
- <property name="title">
- <string>Application</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="targetSDKLabel">
- <property name="text">
- <string>Android build SDK:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="targetSDKComboBox"/>
- </item>
- </layout>
- </widget>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QGroupBox" name="advancedActions">
- <property name="title">
- <string>Advanced Actions</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="2">
- <widget class="QCheckBox" name="openPackageLocationCheckBox">
- <property name="text">
- <string>Open package location after build</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QCheckBox" name="addDebuggerCheckBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="toolTip">
- <string>Packages debug server with the APK to enable debugging. For the signed APK this option is unchecked by default.</string>
- </property>
- <property name="text">
- <string>Add debug server</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0" colspan="2">
- <widget class="QCheckBox" name="verboseOutputCheckBox">
- <property name="text">
- <string>Verbose output</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0" colspan="2">
- <widget class="QCheckBox" name="ministroOption">
- <property name="toolTip">
- <string>Uses the external Ministro application to download and maintain Qt libraries.</string>
- </property>
- <property name="text">
- <string>Use Ministro service to install Qt</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>Utils::PathChooser</class>
- <extends>QWidget</extends>
- <header location="global">utils/pathchooser.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections>
- <connection>
- <sender>signPackageCheckBox</sender>
- <signal>clicked(bool)</signal>
- <receiver>addDebuggerCheckBox</receiver>
- <slot>setEnabled(bool)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>113</x>
- <y>178</y>
- </hint>
- <hint type="destinationlabel">
- <x>510</x>
- <y>452</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index d26ca3c191..292fe361da 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -98,22 +98,16 @@ namespace {
const QLatin1String ArmToolchainPrefix("arm-linux-androideabi");
const QLatin1String X86ToolchainPrefix("x86");
- const QLatin1String MipsToolchainPrefix("mipsel-linux-android");
- const QLatin1String Mips64ToolchainPrefix("mips64el-linux-android");
const QLatin1String AArch64ToolchainPrefix("aarch64-linux-android");
const QLatin1String X86_64ToolchainPrefix("x86_64");
const QLatin1String ArmToolsPrefix("arm-linux-androideabi");
const QLatin1String X86ToolsPrefix("i686-linux-android");
- const QLatin1String MipsToolsPrefix("mipsel-linux-android");
- const QLatin1String Mips64ToolsPrefix("mips64el-linux-android");
const QLatin1String AArch64ToolsPrefix("aarch64-linux-android");
const QLatin1String X86_64ToolsPrefix("x86_64-linux-android");
const QLatin1String ArmToolsDisplayName("arm");
const QLatin1String X86ToolsDisplayName("i686");
- const QLatin1String MipsToolsDisplayName("mipsel");
- const QLatin1String Mips64ToolsDisplayName("mips64el");
const QLatin1String AArch64ToolsDisplayName("aarch64");
const QLatin1String X86_64ToolsDisplayName("x86_64");
@@ -168,17 +162,12 @@ Abi AndroidConfig::abiForToolChainPrefix(const QString &toolchainPrefix)
arch = Abi::ArmArchitecture;
} else if (toolchainPrefix == X86ToolchainPrefix) {
arch = Abi::X86Architecture;
- } else if (toolchainPrefix == MipsToolchainPrefix) {
- arch = Abi::MipsArchitecture;
} else if (toolchainPrefix == AArch64ToolchainPrefix) {
arch = Abi::ArmArchitecture;
wordWidth = 64;
} else if (toolchainPrefix == X86_64ToolchainPrefix) {
arch = Abi::X86Architecture;
wordWidth = 64;
- } else if (toolchainPrefix == Mips64ToolchainPrefix) {
- arch = Abi::MipsArchitecture;
- wordWidth = 64;
}
return Abi(arch, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, wordWidth);
@@ -195,10 +184,6 @@ QLatin1String AndroidConfig::toolchainPrefix(const Abi &abi)
if (abi.wordWidth() == 64)
return X86_64ToolchainPrefix;
return X86ToolchainPrefix;
- case Abi::MipsArchitecture:
- if (abi.wordWidth() == 64)
- return Mips64ToolchainPrefix;
- return MipsToolchainPrefix;
default:
return Unknown;
}
@@ -215,10 +200,6 @@ QLatin1String AndroidConfig::toolsPrefix(const Abi &abi)
if (abi.wordWidth() == 64)
return X86_64ToolsPrefix;
return X86ToolsPrefix;
- case Abi::MipsArchitecture:
- if (abi.wordWidth() == 64)
- return Mips64ToolsPrefix;
- return MipsToolsPrefix;
default:
return Unknown;
}
@@ -235,10 +216,6 @@ QLatin1String AndroidConfig::displayName(const Abi &abi)
if (abi.wordWidth() == 64)
return X86_64ToolsDisplayName;
return X86ToolsDisplayName;
- case Abi::MipsArchitecture:
- if (abi.wordWidth() == 64)
- return Mips64ToolsDisplayName;
- return MipsToolsDisplayName;
default:
return Unknown;
}
@@ -248,23 +225,23 @@ void AndroidConfig::load(const QSettings &settings)
{
// user settings
m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
- m_sdkLocation = FileName::fromString(settings.value(SDKLocationKey).toString());
+ m_sdkLocation = FilePath::fromString(settings.value(SDKLocationKey).toString());
m_sdkManagerToolArgs = settings.value(SDKManagerToolArgsKey).toStringList();
- m_ndkLocation = FileName::fromString(settings.value(NDKLocationKey).toString());
- m_openJDKLocation = FileName::fromString(settings.value(OpenJDKLocationKey).toString());
- m_keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString());
+ m_ndkLocation = FilePath::fromString(settings.value(NDKLocationKey).toString());
+ m_openJDKLocation = FilePath::fromString(settings.value(OpenJDKLocationKey).toString());
+ m_keystoreLocation = FilePath::fromString(settings.value(KeystoreLocationKey).toString());
m_toolchainHost = settings.value(ToolchainHostKey).toString();
m_automaticKitCreation = settings.value(AutomaticKitCreationKey, true).toBool();
PersistentSettingsReader reader;
- if (reader.load(FileName::fromString(sdkSettingsFileName()))
+ if (reader.load(FilePath::fromString(sdkSettingsFileName()))
&& settings.value(changeTimeStamp).toInt() != QFileInfo(sdkSettingsFileName()).lastModified().toMSecsSinceEpoch() / 1000) {
// persisten settings
- m_sdkLocation = FileName::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
+ m_sdkLocation = FilePath::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
m_sdkManagerToolArgs = reader.restoreValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs).toStringList();
- m_ndkLocation = FileName::fromString(reader.restoreValue(NDKLocationKey, m_ndkLocation.toString()).toString());
- m_openJDKLocation = FileName::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
- m_keystoreLocation = FileName::fromString(reader.restoreValue(KeystoreLocationKey, m_keystoreLocation.toString()).toString());
+ m_ndkLocation = FilePath::fromString(reader.restoreValue(NDKLocationKey, m_ndkLocation.toString()).toString());
+ m_openJDKLocation = FilePath::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
+ m_keystoreLocation = FilePath::fromString(reader.restoreValue(KeystoreLocationKey, m_keystoreLocation.toString()).toString());
m_toolchainHost = reader.restoreValue(ToolchainHostKey, m_toolchainHost).toString();
m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool();
// persistent settings
@@ -294,8 +271,7 @@ void AndroidConfig::updateNdkInformation() const
if (m_NdkInformationUpToDate)
return;
m_availableNdkPlatforms.clear();
- FileName path = ndkLocation();
- QDirIterator it(path.appendPath("platforms").toString(), QStringList("android-*"), QDir::Dirs);
+ QDirIterator it(m_ndkLocation.pathAppended("platforms").toString(), QStringList("android-*"), QDir::Dirs);
while (it.hasNext()) {
const QString &fileName = it.next();
m_availableNdkPlatforms.push_back(fileName.midRef(fileName.lastIndexOf(QLatin1Char('-')) + 1).toInt());
@@ -317,8 +293,7 @@ void AndroidConfig::updateNdkInformation() const
default: /* unknown host */ return;
}
- path = ndkLocation();
- QDirIterator jt(path.appendPath(QLatin1String("prebuilt")).toString(), hostPatterns, QDir::Dirs);
+ QDirIterator jt(m_ndkLocation.pathAppended("prebuilt").toString(), hostPatterns, QDir::Dirs);
if (jt.hasNext()) {
jt.next();
m_toolchainHost = jt.fileName();
@@ -338,76 +313,62 @@ QString AndroidConfig::apiLevelNameFor(const SdkPlatform *platform)
QString("android-%1").arg(platform->apiLevel()) : "";
}
-FileName AndroidConfig::adbToolPath() const
+FilePath AndroidConfig::adbToolPath() const
{
- FileName path = m_sdkLocation;
- return path.appendPath(QLatin1String("platform-tools/adb" QTC_HOST_EXE_SUFFIX));
+ return m_sdkLocation.pathAppended("platform-tools/adb" QTC_HOST_EXE_SUFFIX);
}
-FileName AndroidConfig::androidToolPath() const
+FilePath AndroidConfig::androidToolPath() const
{
if (HostOsInfo::isWindowsHost()) {
// I want to switch from using android.bat to using an executable. All it really does is call
// Java and I've made some progress on it. So if android.exe exists, return that instead.
- FileName path = m_sdkLocation;
- path.appendPath(QLatin1String("tools/android" QTC_HOST_EXE_SUFFIX));
+ const FilePath path = m_sdkLocation.pathAppended("tools/android" QTC_HOST_EXE_SUFFIX);
if (path.exists())
return path;
- path = m_sdkLocation;
- return path.appendPath(QLatin1String("tools/android" ANDROID_BAT_SUFFIX));
- } else {
- FileName path = m_sdkLocation;
- return path.appendPath(QLatin1String("tools/android"));
+ return m_sdkLocation.pathAppended("tools/android" ANDROID_BAT_SUFFIX);
}
+ return m_sdkLocation.pathAppended("tools/android");
}
-FileName AndroidConfig::emulatorToolPath() const
+FilePath AndroidConfig::emulatorToolPath() const
{
- FileName path = m_sdkLocation;
QString relativePath = "emulator/emulator";
if (sdkToolsVersion() < QVersionNumber(25, 3, 0))
relativePath = "tools/emulator";
- return path.appendPath(relativePath + QTC_HOST_EXE_SUFFIX);
+ return m_sdkLocation.pathAppended(relativePath + QTC_HOST_EXE_SUFFIX);
}
-FileName AndroidConfig::sdkManagerToolPath() const
+FilePath AndroidConfig::sdkManagerToolPath() const
{
- FileName sdkPath = m_sdkLocation;
QString toolPath = "tools/bin/sdkmanager";
if (HostOsInfo::isWindowsHost())
toolPath += ANDROID_BAT_SUFFIX;
- sdkPath = sdkPath.appendPath(toolPath);
- return sdkPath;
+ return m_sdkLocation.pathAppended(toolPath);
}
-FileName AndroidConfig::avdManagerToolPath() const
+FilePath AndroidConfig::avdManagerToolPath() const
{
- FileName avdManagerPath = m_sdkLocation;
QString toolPath = "tools/bin/avdmanager";
if (HostOsInfo::isWindowsHost())
toolPath += ANDROID_BAT_SUFFIX;
- avdManagerPath = avdManagerPath.appendPath(toolPath);
- return avdManagerPath;
+ return m_sdkLocation.pathAppended(toolPath);
}
-FileName AndroidConfig::aaptToolPath() const
+FilePath AndroidConfig::aaptToolPath() const
{
- Utils::FileName aaptToolPath = m_sdkLocation;
- aaptToolPath.appendPath("build-tools");
+ const Utils::FilePath aaptToolPath = m_sdkLocation.pathAppended("build-tools");
QString toolPath = QString("%1/aapt").arg(buildToolsVersion().toString());
if (HostOsInfo::isWindowsHost())
toolPath += QTC_HOST_EXE_SUFFIX;
- aaptToolPath.appendPath(toolPath);
- return aaptToolPath;
+ return aaptToolPath.pathAppended(toolPath);
}
-FileName AndroidConfig::clangPath() const
+FilePath AndroidConfig::clangPath() const
{
- FileName clangPath = m_ndkLocation;
- clangPath.appendPath("toolchains/llvm/prebuilt/");
- FileName oldNdkClangPath = m_ndkLocation;
- oldNdkClangPath.appendPath("toolchains/llvm-3.6/prebuilt/");
- const QVector<FileName> clangSearchPaths{clangPath, oldNdkClangPath};
+ const FilePath clangPath = m_ndkLocation.pathAppended("toolchains/llvm/prebuilt/");
+ const FilePath oldNdkClangPath = m_ndkLocation.pathAppended("toolchains/llvm-3.6/prebuilt/");
+ const QVector<FilePath> clangSearchPaths{clangPath, oldNdkClangPath};
// detect toolchain host
QStringList hostPatterns;
@@ -421,54 +382,49 @@ FileName AndroidConfig::clangPath() const
case OsTypeMac:
hostPatterns << QLatin1String("darwin*");
break;
- default: /* unknown host */ return FileName();
+ default: /* unknown host */ return FilePath();
}
- for (const FileName &path : clangSearchPaths) {
+ for (const FilePath &path : clangSearchPaths) {
QDirIterator iter(path.toString(), hostPatterns, QDir::Dirs);
if (iter.hasNext()) {
iter.next();
- FileName found = path;
- return found.appendPath(iter.fileName())
- .appendPath(HostOsInfo::withExecutableSuffix("bin/clang"));
+ return path.pathAppended(iter.fileName())
+ .pathAppended(HostOsInfo::withExecutableSuffix("bin/clang"));
}
}
return {};
}
-FileName AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi) const
+FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi) const
{
- FileName path = m_ndkLocation;
- path.appendPath(QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
+ const FilePath path = m_ndkLocation.pathAppended(
+ QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
if (path.exists())
return path;
// fallback for old NDKs (e.g. 10e)
- path = m_ndkLocation;
- path.appendPath(
- QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
+ return m_ndkLocation.pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
.arg(toolchainPrefix(abi), toolchainHost(), toolsPrefix(abi), QTC_HOST_EXE_SUFFIX));
- return path;
}
-FileName AndroidConfig::makePath() const
+FilePath AndroidConfig::makePath() const
{
- FileName path = m_ndkLocation;
- path.appendPath(QString("prebuilt/%1/bin/make%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
- return path;
+ return m_ndkLocation.pathAppended(
+ QString("prebuilt/%1/bin/make%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX));
}
-FileName AndroidConfig::openJDKBinPath() const
+FilePath AndroidConfig::openJDKBinPath() const
{
- FileName path = m_openJDKLocation;
+ const FilePath path = m_openJDKLocation;
if (!path.isEmpty())
- return path.appendPath(QLatin1String("bin"));
+ return path.pathAppended("bin");
return path;
}
-FileName AndroidConfig::keytoolPath() const
+FilePath AndroidConfig::keytoolPath() const
{
- return openJDKBinPath().appendPath(keytoolName);
+ return openJDKBinPath().pathAppended(keytoolName);
}
QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
@@ -729,12 +685,12 @@ QString AndroidConfig::bestNdkPlatformMatch(int target) const
return QString("android-%1").arg(AndroidManager::apiLevelRange().first);
}
-FileName AndroidConfig::sdkLocation() const
+FilePath AndroidConfig::sdkLocation() const
{
return m_sdkLocation;
}
-void AndroidConfig::setSdkLocation(const FileName &sdkLocation)
+void AndroidConfig::setSdkLocation(const FilePath &sdkLocation)
{
m_sdkLocation = sdkLocation;
}
@@ -743,8 +699,8 @@ QVersionNumber AndroidConfig::sdkToolsVersion() const
{
QVersionNumber version;
if (m_sdkLocation.exists()) {
- Utils::FileName sdkToolsPropertiesPath(m_sdkLocation);
- sdkToolsPropertiesPath.appendPath("tools/source.properties");
+ const Utils::FilePath sdkToolsPropertiesPath
+ = m_sdkLocation.pathAppended("tools/source.properties");
QSettings settings(sdkToolsPropertiesPath.toString(), QSettings::IniFormat);
auto versionStr = settings.value(sdkToolsVersionKey).toString();
version = QVersionNumber::fromString(versionStr);
@@ -755,9 +711,7 @@ QVersionNumber AndroidConfig::sdkToolsVersion() const
QVersionNumber AndroidConfig::buildToolsVersion() const
{
QVersionNumber maxVersion;
- Utils::FileName buildtoolsDir = m_sdkLocation;
- buildtoolsDir.appendPath("build-tools");
- QDir buildToolsDir(buildtoolsDir.toString());
+ QDir buildToolsDir(m_sdkLocation.pathAppended("build-tools").toString());
for (const QFileInfo &file: buildToolsDir.entryList(QDir::Dirs|QDir::NoDotAndDotDot))
maxVersion = qMax(maxVersion, QVersionNumber::fromString(file.fileName()));
return maxVersion;
@@ -774,7 +728,7 @@ void AndroidConfig::setSdkManagerToolArgs(const QStringList &args)
m_sdkManagerToolArgs = args;
}
-FileName AndroidConfig::ndkLocation() const
+FilePath AndroidConfig::ndkLocation() const
{
return m_ndkLocation;
}
@@ -790,10 +744,10 @@ static inline QString gdbServerArch(const Abi &abi)
};
}
-FileName AndroidConfig::gdbServer(const ProjectExplorer::Abi &abi) const
+FilePath AndroidConfig::gdbServer(const ProjectExplorer::Abi &abi) const
{
- FileName path = AndroidConfigurations::currentConfig().ndkLocation();
- path.appendPath(QString::fromLatin1("prebuilt/android-%1/gdbserver/gdbserver")
+ const FilePath path = AndroidConfigurations::currentConfig().ndkLocation()
+ .pathAppended(QString("prebuilt/android-%1/gdbserver/gdbserver")
.arg(gdbServerArch(abi)));
if (path.exists())
return path;
@@ -809,8 +763,7 @@ QVersionNumber AndroidConfig::ndkVersion() const
return version;
}
- Utils::FileName ndkPropertiesPath(m_ndkLocation);
- ndkPropertiesPath.appendPath("source.properties");
+ const FilePath ndkPropertiesPath = m_ndkLocation.pathAppended("source.properties");
if (ndkPropertiesPath.exists()) {
// source.properties files exists in NDK version > 11
QSettings settings(ndkPropertiesPath.toString(), QSettings::IniFormat);
@@ -818,8 +771,7 @@ QVersionNumber AndroidConfig::ndkVersion() const
version = QVersionNumber::fromString(versionStr);
} else {
// No source.properties. There should be a file named RELEASE.TXT
- Utils::FileName ndkReleaseTxtPath(m_ndkLocation);
- ndkReleaseTxtPath.appendPath("RELEASE.TXT");
+ const FilePath ndkReleaseTxtPath = m_ndkLocation.pathAppended("RELEASE.TXT");
Utils::FileReader reader;
QString errorString;
if (reader.fetch(ndkReleaseTxtPath.toString(), &errorString)) {
@@ -847,28 +799,28 @@ QVersionNumber AndroidConfig::ndkVersion() const
return version;
}
-void AndroidConfig::setNdkLocation(const FileName &ndkLocation)
+void AndroidConfig::setNdkLocation(const FilePath &ndkLocation)
{
m_ndkLocation = ndkLocation;
m_NdkInformationUpToDate = false;
}
-FileName AndroidConfig::openJDKLocation() const
+FilePath AndroidConfig::openJDKLocation() const
{
return m_openJDKLocation;
}
-void AndroidConfig::setOpenJDKLocation(const FileName &openJDKLocation)
+void AndroidConfig::setOpenJDKLocation(const FilePath &openJDKLocation)
{
m_openJDKLocation = openJDKLocation;
}
-FileName AndroidConfig::keystoreLocation() const
+FilePath AndroidConfig::keystoreLocation() const
{
return m_keystoreLocation;
}
-void AndroidConfig::setKeystoreLocation(const FileName &keystoreLocation)
+void AndroidConfig::setKeystoreLocation(const FilePath &keystoreLocation)
{
m_keystoreLocation = keystoreLocation;
}
@@ -899,12 +851,12 @@ void AndroidConfig::setAutomaticKitCreation(bool b)
m_automaticKitCreation = b;
}
-FileName AndroidConfig::qtLiveApkPath() const
+FilePath AndroidConfig::qtLiveApkPath() const
{
QString apkPathStr(defaultQtLiveApk);
if (qEnvironmentVariableIsSet("QTC_QT_LIVE_APK_PATH"))
apkPathStr = QString::fromLocal8Bit(qgetenv("QTC_QT_LIVE_APK_PATH"));
- return Utils::FileName::fromString(apkPathStr);
+ return Utils::FilePath::fromString(apkPathStr);
}
///////////////////////////////////
@@ -974,17 +926,6 @@ static bool matchToolChain(const ToolChain *atc, const ToolChain *btc)
return aatc->targetAbi() == abtc->targetAbi();
}
-static bool matchKits(const Kit *a, const Kit *b)
-{
- if (QtSupport::QtKitInformation::qtVersion(a) != QtSupport::QtKitInformation::qtVersion(b))
- return false;
-
- return matchToolChain(ToolChainKitInformation::toolChain(a, ProjectExplorer::Constants::CXX_LANGUAGE_ID),
- ToolChainKitInformation::toolChain(b, ProjectExplorer::Constants::CXX_LANGUAGE_ID))
- && matchToolChain(ToolChainKitInformation::toolChain(a, ProjectExplorer::Constants::C_LANGUAGE_ID),
- ToolChainKitInformation::toolChain(b, ProjectExplorer::Constants::C_LANGUAGE_ID));
-}
-
void AndroidConfigurations::registerNewToolChains()
{
const QList<ToolChain *> existingAndroidToolChains
@@ -1006,11 +947,11 @@ void AndroidConfigurations::removeOldToolChains()
static QVariant findOrRegisterDebugger(ToolChain *tc)
{
- const FileName command = tc->suggestedDebugger();
+ const FilePath command = tc->suggestedDebugger();
// check if the debugger is already registered, but ignoring the display name
const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(command);
if (existing && existing->engineType() == Debugger::GdbEngineType && existing->isAutoDetected()
- && existing->abis() == QList<Abi>{tc->targetAbi()})
+ && existing->abis() == Abis{tc->targetAbi()})
return existing->id();
// debugger not found, register a new one
Debugger::DebuggerItem debugger;
@@ -1026,11 +967,23 @@ static QVariant findOrRegisterDebugger(ToolChain *tc)
void AndroidConfigurations::updateAutomaticKitList()
{
+ const QList<Kit *> androidKits = Utils::filtered(KitManager::kits(), [](Kit *k) {
+ Core::Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(k);
+ return deviceTypeId == Core::Id(Constants::ANDROID_DEVICE_TYPE);
+ });
+
+ for (auto k: androidKits) {
+ if (k->value(Constants::ANDROID_KIT_NDK).isNull() || k->value(Constants::ANDROID_KIT_SDK).isNull()) {
+ k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation().toString());
+ k->setValue(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
+ }
+ }
+
const QList<Kit *> existingKits = Utils::filtered(KitManager::kits(), [](Kit *k) {
- Core::Id deviceTypeId = DeviceTypeKitInformation::deviceTypeId(k);
+ Core::Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(k);
if (k->isAutoDetected() && !k->isSdkProvided()
&& deviceTypeId == Core::Id(Constants::ANDROID_DEVICE_TYPE)) {
- if (!QtSupport::QtKitInformation::qtVersion(k))
+ if (!QtSupport::QtKitAspect::qtVersion(k))
KitManager::deregisterKit(k); // Remove autoDetected kits without Qt.
else
return true;
@@ -1044,7 +997,7 @@ void AndroidConfigurations::updateAutomaticKitList()
return v->type() == Constants::ANDROIDQT;
});
for (const QtSupport::BaseQtVersion *qtVersion : qtVersions) {
- const QList<Abi> qtAbis = qtVersion->qtAbis();
+ const Abis qtAbis = qtVersion->qtAbis();
if (qtAbis.empty())
continue;
qtVersionsForArch[qtAbis.first()].append(qtVersion);
@@ -1073,41 +1026,42 @@ void AndroidConfigurations::updateAutomaticKitList()
return tc->targetAbi() == otherTc->targetAbi();
});
- auto initBasicKitData = [allLanguages, device](Kit *k, const QtSupport::BaseQtVersion *qt) {
- k->setAutoDetected(true);
- k->setAutoDetectionSource("AndroidConfiguration");
- DeviceTypeKitInformation::setDeviceTypeId(k, Core::Id(Constants::ANDROID_DEVICE_TYPE));
- for (ToolChain *tc : allLanguages)
- ToolChainKitInformation::setToolChain(k, tc);
- QtSupport::QtKitInformation::setQtVersion(k, qt);
- DeviceKitInformation::setDevice(k, device);
- };
+ QHash<Core::Id, ToolChain *> toolChainForLanguage;
+ for (ToolChain *tc : allLanguages)
+ toolChainForLanguage[tc->language()] = tc;
for (const QtSupport::BaseQtVersion *qt : qtVersionsForArch.value(tc->targetAbi())) {
- auto newKit = std::make_unique<Kit>();
- Kit *toSetup = newKit.get();
- initBasicKitData(toSetup, qt);
- Kit *existingKit = Utils::findOrDefault(existingKits, [toSetup](const Kit *k) {
- return matchKits(toSetup, k);
+ Kit *existingKit = Utils::findOrDefault(existingKits, [&](const Kit *b) {
+ if (qt != QtSupport::QtKitAspect::qtVersion(b))
+ return false;
+ return matchToolChain(toolChainForLanguage[ProjectExplorer::Constants::CXX_LANGUAGE_ID],
+ ToolChainKitAspect::toolChain(b, ProjectExplorer::Constants::CXX_LANGUAGE_ID))
+ && matchToolChain(toolChainForLanguage[ProjectExplorer::Constants::C_LANGUAGE_ID],
+ ToolChainKitAspect::toolChain(b, ProjectExplorer::Constants::C_LANGUAGE_ID));
});
- if (existingKit) {
- // Existing kit found.
- // Update the existing kit with new data.
- initBasicKitData(existingKit, qt);
- newKit.reset();
- toSetup = existingKit;
- }
-
- Debugger::DebuggerKitInformation::setDebugger(toSetup, findOrRegisterDebugger(tc));
- AndroidGdbServerKitInformation::setGdbSever(toSetup, currentConfig().gdbServer(tc->targetAbi()));
- toSetup->makeSticky();
-
- toSetup->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)")
- .arg(static_cast<const AndroidQtVersion *>(qt)->targetArch())
- .arg(qt->displayName()));
- if (!existingKit)
- KitManager::registerKit(std::move(newKit));
+ const auto initializeKit = [allLanguages, device, tc, qt](Kit *k) {
+ k->setAutoDetected(true);
+ k->setAutoDetectionSource("AndroidConfiguration");
+ DeviceTypeKitAspect::setDeviceTypeId(k, Core::Id(Constants::ANDROID_DEVICE_TYPE));
+ for (ToolChain *tc : allLanguages)
+ ToolChainKitAspect::setToolChain(k, tc);
+ QtSupport::QtKitAspect::setQtVersion(k, qt);
+ DeviceKitAspect::setDevice(k, device);
+ Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc));
+ AndroidGdbServerKitAspect::setGdbSever(k, currentConfig().gdbServer(tc->targetAbi()));
+ k->makeSticky();
+ k->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)")
+ .arg(static_cast<const AndroidQtVersion *>(qt)->targetArch())
+ .arg(qt->displayName()));
+ k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation().toString());
+ k->setValueSilently(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
+ };
+
+ if (existingKit)
+ initializeKit(existingKit); // Update the existing kit with new data.
+ else
+ KitManager::registerKit(initializeKit);
}
}
}
@@ -1120,12 +1074,10 @@ bool AndroidConfigurations::force32bitEmulator()
QProcessEnvironment AndroidConfigurations::toolsEnvironment(const AndroidConfig &config)
{
Environment env = Environment::systemEnvironment();
- Utils::FileName jdkLocation = config.openJDKLocation();
+ Utils::FilePath jdkLocation = config.openJDKLocation();
if (!jdkLocation.isEmpty()) {
env.set("JAVA_HOME", jdkLocation.toUserOutput());
- Utils::FileName binPath = jdkLocation;
- binPath.appendPath("bin");
- env.prependOrSetPath(binPath.toUserOutput());
+ env.prependOrSetPath(jdkLocation.pathAppended("bin").toUserOutput());
}
return env.toProcessEnvironment();
}
@@ -1195,7 +1147,7 @@ AndroidConfigurations::AndroidConfigurations()
AndroidConfigurations::~AndroidConfigurations() = default;
-static FileName javaHomeForJavac(const FileName &location)
+static FilePath javaHomeForJavac(const FilePath &location)
{
QFileInfo fileInfo = location.toFileInfo();
int tries = 5;
@@ -1203,14 +1155,14 @@ static FileName javaHomeForJavac(const FileName &location)
QDir dir = fileInfo.dir();
dir.cdUp();
if (QFileInfo::exists(dir.filePath(QLatin1String("lib/tools.jar"))))
- return FileName::fromString(dir.path());
+ return FilePath::fromString(dir.path());
if (fileInfo.isSymLink())
fileInfo.setFile(fileInfo.symLinkTarget());
else
break;
--tries;
}
- return FileName();
+ return FilePath();
}
void AndroidConfigurations::load()
@@ -1223,7 +1175,7 @@ void AndroidConfigurations::load()
if (m_config.openJDKLocation().isEmpty()) {
if (HostOsInfo::isLinuxHost()) {
Environment env = Environment::systemEnvironment();
- FileName location = env.searchInPath(QLatin1String("javac"));
+ FilePath location = env.searchInPath(QLatin1String("javac"));
QFileInfo fi = location.toFileInfo();
if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
m_config.setOpenJDKLocation(javaHomeForJavac(location));
@@ -1239,7 +1191,7 @@ void AndroidConfigurations::load()
if (response.result == SynchronousProcessResponse::Finished) {
const QString &javaHome = response.allOutput().trimmed();
if (!javaHome.isEmpty() && QFileInfo::exists(javaHome))
- m_config.setOpenJDKLocation(FileName::fromString(javaHome));
+ m_config.setOpenJDKLocation(FilePath::fromString(javaHome));
}
}
} else if (HostOsInfo::isWindowsHost()) {
@@ -1281,7 +1233,7 @@ void AndroidConfigurations::load()
}
}
if (!javaHome.isEmpty()) {
- m_config.setOpenJDKLocation(FileName::fromString(javaHome));
+ m_config.setOpenJDKLocation(FilePath::fromString(javaHome));
saveSettings = true;
}
}
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index 70d97c129c..3b9ecb4bb1 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -52,7 +52,6 @@ class Project;
namespace Android {
-
namespace Internal {
class AndroidSdkManager;
class AndroidPluginPrivate;
@@ -98,23 +97,23 @@ public:
static QStringList apiLevelNamesFor(const SdkPlatformList &platforms);
static QString apiLevelNameFor(const SdkPlatform *platform);
- Utils::FileName sdkLocation() const;
- void setSdkLocation(const Utils::FileName &sdkLocation);
+ Utils::FilePath sdkLocation() const;
+ void setSdkLocation(const Utils::FilePath &sdkLocation);
QVersionNumber sdkToolsVersion() const;
QVersionNumber buildToolsVersion() const;
QStringList sdkManagerToolArgs() const;
void setSdkManagerToolArgs(const QStringList &args);
- Utils::FileName ndkLocation() const;
- Utils::FileName gdbServer(const ProjectExplorer::Abi &abi) const;
+ Utils::FilePath ndkLocation() const;
+ Utils::FilePath gdbServer(const ProjectExplorer::Abi &abi) const;
QVersionNumber ndkVersion() const;
- void setNdkLocation(const Utils::FileName &ndkLocation);
+ void setNdkLocation(const Utils::FilePath &ndkLocation);
- Utils::FileName openJDKLocation() const;
- void setOpenJDKLocation(const Utils::FileName &openJDKLocation);
+ Utils::FilePath openJDKLocation() const;
+ void setOpenJDKLocation(const Utils::FilePath &openJDKLocation);
- Utils::FileName keystoreLocation() const;
- void setKeystoreLocation(const Utils::FileName &keystoreLocation);
+ Utils::FilePath keystoreLocation() const;
+ void setKeystoreLocation(const Utils::FilePath &keystoreLocation);
QString toolchainHost() const;
@@ -124,20 +123,20 @@ public:
bool automaticKitCreation() const;
void setAutomaticKitCreation(bool b);
- Utils::FileName qtLiveApkPath() const;
+ Utils::FilePath qtLiveApkPath() const;
- Utils::FileName adbToolPath() const;
- Utils::FileName androidToolPath() const;
- Utils::FileName emulatorToolPath() const;
- Utils::FileName sdkManagerToolPath() const;
- Utils::FileName avdManagerToolPath() const;
- Utils::FileName aaptToolPath() const;
+ Utils::FilePath adbToolPath() const;
+ Utils::FilePath androidToolPath() const;
+ Utils::FilePath emulatorToolPath() const;
+ Utils::FilePath sdkManagerToolPath() const;
+ Utils::FilePath avdManagerToolPath() const;
+ Utils::FilePath aaptToolPath() const;
- Utils::FileName clangPath() const;
- Utils::FileName gdbPath(const ProjectExplorer::Abi &abi) const;
- Utils::FileName makePath() const;
+ Utils::FilePath clangPath() const;
+ Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi) const;
+ Utils::FilePath makePath() const;
- Utils::FileName keytoolPath() const;
+ Utils::FilePath keytoolPath() const;
QVector<AndroidDeviceInfo> connectedDevices(QString *error = nullptr) const;
static QVector<AndroidDeviceInfo> connectedDevices(const QString &adbToolPath, QString *error = nullptr);
@@ -159,7 +158,7 @@ public:
private:
static QString getDeviceProperty(const QString &adbToolPath, const QString &device, const QString &property);
- Utils::FileName openJDKBinPath() const;
+ Utils::FilePath openJDKBinPath() const;
int getSDKVersion(const QString &device) const;
static int getSDKVersion(const QString &adbToolPath, const QString &device);
QStringList getAbis(const QString &device) const;
@@ -170,11 +169,11 @@ private:
void updateNdkInformation() const;
- Utils::FileName m_sdkLocation;
+ Utils::FilePath m_sdkLocation;
QStringList m_sdkManagerToolArgs;
- Utils::FileName m_ndkLocation;
- Utils::FileName m_openJDKLocation;
- Utils::FileName m_keystoreLocation;
+ Utils::FilePath m_ndkLocation;
+ Utils::FilePath m_openJDKLocation;
+ Utils::FilePath m_keystoreLocation;
unsigned m_partitionSize = 1024;
bool m_automaticKitCreation = true;
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
index ee2630c198..f34da07f4e 100644
--- a/src/plugins/android/androidconstants.h
+++ b/src/plugins/android/androidconstants.h
@@ -63,23 +63,34 @@ const char ANDROID_MANIFEST_MIME_TYPE[] = "application/vnd.google.android.androi
const char ANDROID_MANIFEST_EDITOR_ID[] = "Android.AndroidManifestEditor.Id";
const char ANDROID_MANIFEST_EDITOR_CONTEXT[] = "Android.AndroidManifestEditor.Id";
+const char ANDROID_KIT_NDK[] = "Android.NDK";
+const char ANDROID_KIT_SDK[] = "Android.SDK";
+
const char ANDROID_BUILDDIRECTORY[] = "android-build";
const char JAVA_EDITOR_ID[] = "java.editor";
const char JAVA_MIMETYPE[] = "text/x-java";
const char ANDROID_ARCHITECTURE[] = "Android.Architecture";
-const char ANDROID_DEPLOY_SETTINGS_FILE[] = "AndroidDeploySettingsFile";
const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
const char ANDROID_PACKAGENAME[] = "Android.PackageName";
-const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] = "Qt4ProjectManager.AndroidPackageInstallationStep";
+const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[]
+ = "Qt4ProjectManager.AndroidPackageInstallationStep";
const char ANDROID_BUILD_APK_ID[] = "QmakeProjectManager.AndroidBuildApkStep";
const char AndroidPackageSourceDir[] = "AndroidPackageSourceDir"; // QString
const char AndroidDeploySettingsFile[] = "AndroidDeploySettingsFile"; // QString
const char AndroidExtraLibs[] = "AndroidExtraLibs"; // QStringList
+// REMOVE ME
const char AndroidArch[] = "AndroidArch"; // QString
const char AndroidSoLibPath[] = "AndroidSoLibPath"; // QStringList
+const char AndroidTargets[] = "AndroidTargets"; // QStringList
+const char AndroidApk[] = "Android.APK"; // QStringList
+const char AndroidManifest[] = "Android.Manifest"; // QStringList
+
+const char AndroidNdkPlatform[] = "AndroidNdkPlatform"; //QString
+const char NdkLocation[] = "NdkLocation"; // FileName
+const char AndroidABI[] = "AndroidABI"; // QString
} // namespace Constants;
} // namespace Android
diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp
index dd2906e575..1ac6e1ea12 100644
--- a/src/plugins/android/androidcreatekeystorecertificate.cpp
+++ b/src/plugins/android/androidcreatekeystorecertificate.cpp
@@ -58,7 +58,7 @@ AndroidCreateKeystoreCertificate::~AndroidCreateKeystoreCertificate()
delete ui;
}
-Utils::FileName AndroidCreateKeystoreCertificate::keystoreFilePath()
+Utils::FilePath AndroidCreateKeystoreCertificate::keystoreFilePath()
{
return m_keystoreFilePath;
}
@@ -152,7 +152,7 @@ void AndroidCreateKeystoreCertificate::on_buttonBox_accepted()
if (!validateUserInput())
return;
- m_keystoreFilePath = Utils::FileName::fromString(QFileDialog::getSaveFileName(this, tr("Keystore Filename"),
+ m_keystoreFilePath = Utils::FilePath::fromString(QFileDialog::getSaveFileName(this, tr("Keystore Filename"),
QDir::homePath() + QLatin1String("/android_release.keystore"),
tr("Keystore files (*.keystore *.jks)")));
if (m_keystoreFilePath.isEmpty())
diff --git a/src/plugins/android/androidcreatekeystorecertificate.h b/src/plugins/android/androidcreatekeystorecertificate.h
index 86c9f36fcf..4a9cbe9c42 100644
--- a/src/plugins/android/androidcreatekeystorecertificate.h
+++ b/src/plugins/android/androidcreatekeystorecertificate.h
@@ -49,7 +49,7 @@ class AndroidCreateKeystoreCertificate : public QDialog
public:
explicit AndroidCreateKeystoreCertificate(QWidget *parent = nullptr);
~AndroidCreateKeystoreCertificate() override;
- Utils::FileName keystoreFilePath();
+ Utils::FilePath keystoreFilePath();
QString keystorePassword();
QString certificateAlias();
QString certificatePassword();
@@ -69,7 +69,7 @@ private slots:
private:
bool validateUserInput();
Ui::AndroidCreateKeystoreCertificate *ui;
- Utils::FileName m_keystoreFilePath;
+ Utils::FilePath m_keystoreFilePath;
};
} // namespace Internal
diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp
index 2af97bdffd..a703c31936 100644
--- a/src/plugins/android/androiddebugsupport.cpp
+++ b/src/plugins/android/androiddebugsupport.cpp
@@ -29,6 +29,7 @@
#include "androidglobal.h"
#include "androidrunner.h"
#include "androidmanager.h"
+#include "androidqtversion.h"
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerrunconfigurationaspect.h>
@@ -92,10 +93,8 @@ static QStringList uniquePaths(const QStringList &files)
return paths.toList();
}
-static QStringList getSoLibSearchPath(const RunConfiguration *rc)
+static QStringList getSoLibSearchPath(const ProjectNode *node)
{
- Target *target = rc->target();
- const ProjectNode *node = target->project()->findNodeForBuildKey(rc->buildKey());
if (!node)
return {};
@@ -121,12 +120,10 @@ static QStringList getSoLibSearchPath(const RunConfiguration *rc)
return res;
}
-static QStringList getExtraLibs(const RunConfiguration *rc)
+static QStringList getExtraLibs(const ProjectNode *node)
{
- const ProjectNode *node = rc->target()->project()->findNodeForBuildKey(rc->buildKey());
if (!node)
return {};
-
return node->data(Android::Constants::AndroidExtraLibs).toStringList();
}
@@ -149,8 +146,7 @@ AndroidDebugSupport::AndroidDebugSupport(RunControl *runControl, const QString &
void AndroidDebugSupport::start()
{
- auto runConfig = runControl()->runConfiguration();
- Target *target = runConfig->target();
+ Target *target = runControl()->target();
Kit *kit = target->kit();
setStartMode(AttachToRemoteServer);
@@ -167,14 +163,17 @@ void AndroidDebugSupport::start()
setUseTargetAsync(true);
}
- QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit);
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
if (isCppDebugging()) {
qCDebug(androidDebugSupportLog) << "C++ debugging enabled";
- QStringList solibSearchPath = getSoLibSearchPath(runConfig);
- QStringList extraLibs = getExtraLibs(runConfig);
+ const ProjectNode *node = target->project()->findNodeForBuildKey(runControl()->buildKey());
+ QStringList solibSearchPath = getSoLibSearchPath(node);
+ QStringList extraLibs = getExtraLibs(node);
solibSearchPath.append(qtSoPaths(qtVersion));
solibSearchPath.append(uniquePaths(extraLibs));
+ solibSearchPath.append(target->activeBuildConfiguration()->buildDirectory().toString());
+ solibSearchPath.removeDuplicates();
setSolibSearchPath(solibSearchPath);
qCDebug(androidDebugSupportLog) << "SoLibSearchPath: "<<solibSearchPath;
setSymbolFile(target->activeBuildConfiguration()->buildDirectory().toString()
@@ -186,12 +185,15 @@ void AndroidDebugSupport::start()
gdbServer.setPort(m_runner->gdbServerPort().number());
setRemoteChannel(gdbServer);
- int sdkVersion = qMax(AndroidManager::minimumSDK(target->kit()),
- AndroidManager::minimumNDK(target->kit()));
- Utils::FileName sysRoot = AndroidConfigurations::currentConfig().ndkLocation()
- .appendPath("platforms")
- .appendPath(QString("android-%1").arg(sdkVersion))
- .appendPath(toNdkArch(AndroidManager::targetArch(target)));
+ auto qt = static_cast<AndroidQtVersion *>(qtVersion);
+ QTC_CHECK(qt);
+ const int minimumNdk = qt ? qt->minimumNDK() : 0;
+
+ int sdkVersion = qMax(AndroidManager::minimumSDK(kit), minimumNdk);
+ Utils::FilePath sysRoot = AndroidConfigurations::currentConfig().ndkLocation()
+ .pathAppended("platforms")
+ .pathAppended(QString("android-%1").arg(sdkVersion))
+ .pathAppended(toNdkArch(AndroidManager::targetArch(target)));
setSysRoot(sysRoot);
qCDebug(androidDebugSupportLog) << "Sysroot: " << sysRoot;
}
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index 1de24c76e7..42a3c7d6e0 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -63,8 +63,10 @@
#include <QVBoxLayout>
using namespace ProjectExplorer;
-using namespace Android;
-using namespace Android::Internal;
+using namespace Utils;
+
+namespace Android {
+namespace Internal {
namespace {
Q_LOGGING_CATEGORY(deployStepLog, "qtc.android.build.androiddeployqtstep", QtWarningMsg)
@@ -149,7 +151,7 @@ AndroidDeployQtStep::AndroidDeployQtStep(ProjectExplorer::BuildStepList *parent)
: ProjectExplorer::BuildStep(parent, stepId())
{
setImmutable(true);
- m_uninstallPreviousPackage = QtSupport::QtKitInformation::qtVersion(target()->kit())->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0);
+ m_uninstallPreviousPackage = QtSupport::QtKitAspect::qtVersion(target()->kit())->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0);
//: AndroidDeployQtStep default display name
setDefaultDisplayName(tr("Deploy to Android device"));
@@ -169,7 +171,7 @@ Core::Id AndroidDeployQtStep::stepId()
bool AndroidDeployQtStep::init()
{
- m_androiddeployqtArgs.clear();
+ m_androiddeployqtArgs = CommandLine();
m_targetArch = AndroidManager::targetArch(target());
if (m_targetArch.isEmpty()) {
@@ -186,11 +188,6 @@ bool AndroidDeployQtStep::init()
QTC_ASSERT(deployQtLive || bc, return false);
auto androidBuildApkStep = AndroidBuildApkStep::findInBuild(bc);
- if (!androidBuildApkStep && !deployQtLive) {
- emit addOutput(tr("Cannot find the android build step."), OutputFormat::Stderr);
- return false;
- }
-
int minTargetApi = AndroidManager::minimumSDK(target());
qCDebug(deployStepLog) << "Target architecture:" << m_targetArch
<< "Min target API" << minTargetApi;
@@ -224,7 +221,7 @@ bool AndroidDeployQtStep::init()
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::Stdout);
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target()->kit());
if (!version)
return false;
@@ -236,60 +233,60 @@ bool AndroidDeployQtStep::init()
version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0);
if (m_useAndroiddeployqt) {
- m_command = version->qmakeProperty("QT_HOST_BINS");
- if (m_command.isEmpty()) {
- emit addOutput(tr("Cannot find the androiddeployqt tool."), OutputFormat::Stderr);
- return false;
- }
- qCDebug(deployStepLog) << "Using androiddeployqt";
- if (!m_command.endsWith(QLatin1Char('/')))
- m_command += QLatin1Char('/');
- m_command += Utils::HostOsInfo::withExecutableSuffix(QLatin1String("androiddeployqt"));
-
- m_workingDirectory = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();
-
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--verbose"));
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--output"));
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, m_workingDirectory);
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--no-build"));
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--input"));
-
- QString jsonFile;
- if (const ProjectNode *node = target()->project()->findNodeForBuildKey(rc->buildKey()))
- jsonFile = node->data(Constants::AndroidDeploySettingsFile).toString();
- if (jsonFile.isEmpty()) {
- emit addOutput(tr("Cannot find the androiddeploy Json file."), OutputFormat::Stderr);
+ const ProjectNode *node = target()->project()->findNodeForBuildKey(rc->buildKey());
+ if (!node)
return false;
- }
+ m_apkPath = Utils::FilePath::fromString(node->data(Constants::AndroidApk).toString());
+ if (!m_apkPath.isEmpty()) {
+ m_manifestName = Utils::FilePath::fromString(node->data(Constants::AndroidManifest).toString());
+ m_command = AndroidConfigurations::currentConfig().adbToolPath();
+ AndroidManager::setManifestPath(target(), m_manifestName);
+ } else {
+ QString jsonFile = node->data(Constants::AndroidDeploySettingsFile).toString();
+ if (jsonFile.isEmpty()) {
+ emit addOutput(tr("Cannot find the androiddeploy Json file."), OutputFormat::Stderr);
+ return false;
+ }
+ m_command = FilePath::fromString(version->qmakeProperty("QT_HOST_BINS"));
+ if (m_command.isEmpty()) {
+ emit addOutput(tr("Cannot find the androiddeployqt tool."), OutputFormat::Stderr);
+ return false;
+ }
+ qCDebug(deployStepLog) << "Using androiddeployqt";
+ m_command = m_command.pathAppended(HostOsInfo::withExecutableSuffix("androiddeployqt"));
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, jsonFile);
- if (androidBuildApkStep && androidBuildApkStep->useMinistro()) {
- qCDebug(deployStepLog) << "Using ministro";
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--deployment"));
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("ministro"));
- }
+ m_workingDirectory = bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY);
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--gradle"));
+ m_androiddeployqtArgs.addArgs({"--verbose",
+ "--output", m_workingDirectory.toString(),
+ "--no-build",
+ "--input", jsonFile});
- if (androidBuildApkStep && androidBuildApkStep->signPackage()) {
- // The androiddeployqt tool is not really written to do stand-alone installations.
- // This hack forces it to use the correct filename for the apk file when installing
- // as a temporary fix until androiddeployqt gets the support. Since the --sign is
- // only used to get the correct file name of the apk, its parameters are ignored.
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--sign"));
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("foo"));
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("bar"));
+ if (androidBuildApkStep && androidBuildApkStep->useMinistro()) {
+ qCDebug(deployStepLog) << "Using ministro";
+ m_androiddeployqtArgs.addArgs({"--deployment", "ministro"});
+ }
+
+ m_androiddeployqtArgs.addArg("--gradle");
+
+ if (androidBuildApkStep && androidBuildApkStep->signPackage()) {
+ // The androiddeployqt tool is not really written to do stand-alone installations.
+ // This hack forces it to use the correct filename for the apk file when installing
+ // as a temporary fix until androiddeployqt gets the support. Since the --sign is
+ // only used to get the correct file name of the apk, its parameters are ignored.
+ m_androiddeployqtArgs.addArgs({"--sign", "foo", "bar"});
+ }
}
} else {
m_uninstallPreviousPackageRun = true;
- m_command = AndroidConfigurations::currentConfig().adbToolPath().toString();
+ m_command = AndroidConfigurations::currentConfig().adbToolPath();
const AndroidConfig &config = AndroidConfigurations::currentConfig();
m_apkPath = deployQtLive ? config.qtLiveApkPath() : AndroidManager::apkPath(target());
- m_workingDirectory = bc ? bc->buildDirectory().toString() : QString();
+ m_workingDirectory = bc ? bc->buildDirectory() : FilePath();
}
m_environment = bc ? bc->environment() : Utils::Environment();
- m_adbPath = AndroidConfigurations::currentConfig().adbToolPath().toString();
+ m_adbPath = AndroidConfigurations::currentConfig().adbToolPath();
AndroidAvdManager avdManager;
// Start the AVD if not running.
@@ -300,18 +297,17 @@ bool AndroidDeployQtStep::init()
AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
{
- QString args;
- if (m_useAndroiddeployqt) {
- args = m_androiddeployqtArgs;
+ CommandLine cmd(m_command, {});
+ if (m_useAndroiddeployqt && m_apkPath.isEmpty()) {
+ cmd.addArgs(m_androiddeployqtArgs.arguments());
if (m_uninstallPreviousPackageRun)
- Utils::QtcProcess::addArg(&args, QLatin1String("--install"));
+ cmd.addArg("--install");
else
- Utils::QtcProcess::addArg(&args, QLatin1String("--reinstall"));
+ cmd.addArg("--reinstall");
+
+ if (!m_serialNumber.isEmpty() && !m_serialNumber.startsWith("????"))
+ cmd.addArgs({"--device", m_serialNumber});
- if (!m_serialNumber.isEmpty() && !m_serialNumber.startsWith(QLatin1String("????"))) {
- Utils::QtcProcess::addArg(&args, QLatin1String("--device"));
- Utils::QtcProcess::addArg(&args, m_serialNumber);
- }
} else {
RunConfiguration *rc = target()->activeRunConfiguration();
QTC_ASSERT(rc, return DeployErrorCode::Failure);
@@ -349,22 +345,18 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
}
qCDebug(deployStepLog) << "Uninstalling previous package";
emit addOutput(tr("Uninstall previous package %1.").arg(packageName), OutputFormat::NormalMessage);
- runCommand(m_adbPath,
+ runCommand(m_adbPath.toString(),
AndroidDeviceInfo::adbSelector(m_serialNumber)
<< QLatin1String("uninstall") << packageName);
}
- foreach (const QString &arg, AndroidDeviceInfo::adbSelector(m_serialNumber))
- Utils::QtcProcess::addArg(&args, arg);
-
- Utils::QtcProcess::addArg(&args, QLatin1String("install"));
- Utils::QtcProcess::addArg(&args, QLatin1String("-r"));
- Utils::QtcProcess::addArg(&args, m_apkPath.toString());
+ cmd.addArgs(AndroidDeviceInfo::adbSelector(m_serialNumber));
+ cmd.addArgs({"install", "-r", m_apkPath.toString()});
}
m_process = new Utils::QtcProcess;
- m_process->setCommand(m_command, args);
- m_process->setWorkingDirectory(m_workingDirectory);
+ m_process->setCommand(cmd);
+ m_process->setWorkingDirectory(m_workingDirectory.toString());
m_process->setEnvironment(m_environment);
if (Utils::HostOsInfo::isWindowsHost())
@@ -378,8 +370,7 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
m_process->start();
- emit addOutput(tr("Starting: \"%1\" %2")
- .arg(QDir::toNativeSeparators(m_command), args),
+ emit addOutput(tr("Starting: \"%1\"").arg(cmd.toUserOutput()),
BuildStep::OutputFormat::NormalMessage);
while (!m_process->waitForFinished(200)) {
@@ -410,14 +401,15 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
m_process = nullptr;
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
- emit addOutput(tr("The process \"%1\" exited normally.").arg(m_command),
+ emit addOutput(tr("The process \"%1\" exited normally.").arg(m_command.toUserOutput()),
BuildStep::OutputFormat::NormalMessage);
} else if (exitStatus == QProcess::NormalExit) {
emit addOutput(tr("The process \"%1\" exited with code %2.")
- .arg(m_command, QString::number(exitCode)),
+ .arg(m_command.toUserOutput(), QString::number(exitCode)),
BuildStep::OutputFormat::ErrorMessage);
} else {
- emit addOutput(tr("The process \"%1\" crashed.").arg(m_command), BuildStep::OutputFormat::ErrorMessage);
+ emit addOutput(tr("The process \"%1\" crashed.").arg(m_command.toUserOutput()),
+ BuildStep::OutputFormat::ErrorMessage);
}
if (deployError != NoError) {
@@ -497,7 +489,7 @@ bool AndroidDeployQtStep::runImpl()
for (auto itr = m_filesToPull.constBegin(); itr != m_filesToPull.constEnd(); ++itr) {
QFile::remove(itr.value());
- runCommand(m_adbPath,
+ runCommand(m_adbPath.toString(),
AndroidDeviceInfo::adbSelector(m_serialNumber)
<< "pull" << itr.key() << itr.value());
if (!QFileInfo::exists(itr.value())) {
@@ -527,7 +519,7 @@ void AndroidDeployQtStep::gatherFilesToPull()
if (m_deviceInfo.cpuAbi.contains(QLatin1String("arm64-v8a")) ||
m_deviceInfo.cpuAbi.contains(QLatin1String("x86_64"))) {
const Core::Id cxxLanguageId = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
- ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit(), cxxLanguageId);
+ ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(), cxxLanguageId);
if (tc && tc->targetAbi().wordWidth() == 64) {
m_filesToPull["/system/bin/app_process64"] = buildDir + "app_process";
libDirName = "lib64";
@@ -634,7 +626,10 @@ void AndroidDeployQtStep::setUninstallPreviousPackage(bool uninstall)
AndroidDeployQtStep::UninstallType AndroidDeployQtStep::uninstallPreviousPackage()
{
- if (QtSupport::QtKitInformation::qtVersion(target()->kit())->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0))
+ if (QtSupport::QtKitAspect::qtVersion(target()->kit())->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0))
return ForceUnintall;
return m_uninstallPreviousPackage ? Uninstall : Keep;
}
+
+} // Internal
+} // Android
diff --git a/src/plugins/android/androiddeployqtstep.h b/src/plugins/android/androiddeployqtstep.h
index b2a831efe7..48faf2abf5 100644
--- a/src/plugins/android/androiddeployqtstep.h
+++ b/src/plugins/android/androiddeployqtstep.h
@@ -33,8 +33,7 @@
#include <qtsupport/baseqtversion.h>
#include <utils/environment.h>
-
-namespace Utils { class QtcProcess; }
+#include <utils/qtcprocess.h>
namespace Android {
namespace Internal {
@@ -106,10 +105,10 @@ private:
friend void operator|=(DeployErrorCode &e1, const DeployErrorCode &e2) { e1 = static_cast<AndroidDeployQtStep::DeployErrorCode>((int)e1 | (int)e2); }
friend DeployErrorCode operator|(const DeployErrorCode &e1, const DeployErrorCode &e2) { return static_cast<AndroidDeployQtStep::DeployErrorCode>((int)e1 | (int)e2); }
- Utils::FileName m_manifestName;
+ Utils::FilePath m_manifestName;
QString m_serialNumber;
QString m_avdName;
- Utils::FileName m_apkPath;
+ Utils::FilePath m_apkPath;
QMap<QString, QString> m_filesToPull;
QString m_targetArch;
@@ -118,10 +117,10 @@ private:
bool m_useAndroiddeployqt = false;
bool m_askForUninstall = false;
static const Core::Id Id;
- QString m_androiddeployqtArgs;
- QString m_adbPath;
- QString m_command;
- QString m_workingDirectory;
+ Utils::CommandLine m_androiddeployqtArgs;
+ Utils::FilePath m_adbPath;
+ 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 e33c3e3d12..3803ac5073 100644
--- a/src/plugins/android/androiddevice.cpp
+++ b/src/plugins/android/androiddevice.cpp
@@ -90,11 +90,6 @@ Utils::OsType AndroidDevice::osType() const
return Utils::OsTypeOtherUnix;
}
-IDevice::Ptr AndroidDevice::clone() const
-{
- return IDevice::Ptr(new AndroidDevice(*this));
-}
-
QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
{
QUrl url;
@@ -103,5 +98,18 @@ QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
return url;
}
+
+// Factory
+
+AndroidDeviceFactory::AndroidDeviceFactory()
+ : ProjectExplorer::IDeviceFactory(Constants::ANDROID_DEVICE_TYPE)
+{
+ setObjectName(QLatin1String("AndroidDeviceFactory"));
+ setDisplayName(tr("Android Device"));
+ setCombinedIcon(":/android/images/androiddevicesmall.png",
+ ":/android/images/androiddevice.png");
+ setConstructionFunction(&AndroidDevice::create);
+}
+
} // namespace Internal
} // namespace Android
diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h
index 22a0e53df1..7a66e1d15c 100644
--- a/src/plugins/android/androiddevice.h
+++ b/src/plugins/android/androiddevice.h
@@ -26,6 +26,7 @@
#pragma once
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefactory.h>
namespace Android {
namespace Internal {
@@ -46,9 +47,15 @@ private:
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override;
Utils::OsType osType() const override;
- ProjectExplorer::IDevice::Ptr clone() const override;
QUrl toolControlChannel(const ControlChannelHint &) const override;
};
+class AndroidDeviceFactory : public ProjectExplorer::IDeviceFactory
+{
+ Q_OBJECT
+public:
+ AndroidDeviceFactory();
+};
+
} // namespace Internal
} // namespace Android
diff --git a/src/plugins/android/androiddevicedialog.cpp b/src/plugins/android/androiddevicedialog.cpp
index 529b2a066a..a0b786ad69 100644
--- a/src/plugins/android/androiddevicedialog.cpp
+++ b/src/plugins/android/androiddevicedialog.cpp
@@ -173,7 +173,7 @@ public:
// topRight
auto drawTopRight = [&](const QString text, const QFontMetrics &fm) {
- painter->drawText(opt.rect.right() - fm.width(text) - 6 , 2 + opt.rect.top() + fm.ascent(), text);
+ painter->drawText(opt.rect.right() - fm.horizontalAdvance(text) - 6 , 2 + opt.rect.top() + fm.ascent(), text);
};
if (device.type == AndroidDeviceInfo::Hardware) {
diff --git a/src/plugins/android/androiddevicefactory.cpp b/src/plugins/android/androiddevicefactory.cpp
deleted file mode 100644
index 19a4679491..0000000000
--- a/src/plugins/android/androiddevicefactory.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "androiddevicefactory.h"
-#include "androiddevice.h"
-
-#include "androidconstants.h"
-
-namespace Android {
-namespace Internal {
-
-AndroidDeviceFactory::AndroidDeviceFactory()
- : ProjectExplorer::IDeviceFactory(Constants::ANDROID_DEVICE_TYPE)
-{
- setObjectName(QLatin1String("AndroidDeviceFactory"));
- setDisplayName(tr("Android Device"));
- setCombinedIcon(":/android/images/androiddevicesmall.png",
- ":/android/images/androiddevice.png");
- setConstructionFunction(&AndroidDevice::create);
-}
-
-} // namespace Internal
-} // namespace Android
diff --git a/src/plugins/android/androiddevicefactory.h b/src/plugins/android/androiddevicefactory.h
deleted file mode 100644
index 10e97bcd0e..0000000000
--- a/src/plugins/android/androiddevicefactory.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/idevicefactory.h>
-
-namespace Android {
-namespace Internal {
-
-class AndroidDeviceFactory : public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-public:
- AndroidDeviceFactory();
-};
-
-} // namespace Internal
-} // namespace Android
diff --git a/src/plugins/android/androidgdbserverkitinformation.cpp b/src/plugins/android/androidgdbserverkitinformation.cpp
index d4a7e17d85..fdc5946c80 100644
--- a/src/plugins/android/androidgdbserverkitinformation.cpp
+++ b/src/plugins/android/androidgdbserverkitinformation.cpp
@@ -50,78 +50,96 @@ using namespace Utils;
namespace Android {
namespace Internal {
-AndroidGdbServerKitInformation::AndroidGdbServerKitInformation()
+class AndroidGdbServerKitAspectWidget : public KitAspectWidget
{
- setId(AndroidGdbServerKitInformation::id());
+ Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidGdbServerKitAspect)
+public:
+ AndroidGdbServerKitAspectWidget(Kit *kit, const KitAspect *ki);
+ ~AndroidGdbServerKitAspectWidget() override;
+
+ void makeReadOnly() override;
+ void refresh() override;
+
+ QWidget *mainWidget() const override;
+ QWidget *buttonWidget() const override;
+
+private:
+ void autoDetectDebugger();
+ void showDialog();
+
+ QLabel *m_label;
+ QPushButton *m_button;
+};
+
+
+AndroidGdbServerKitAspect::AndroidGdbServerKitAspect()
+{
+ setId(AndroidGdbServerKitAspect::id());
+ setDisplayName(tr("Android GDB server"));
+ setDescription(tr("The GDB server to use for this kit."));
setPriority(27999); // Just one less than Debugger!
}
-QVariant AndroidGdbServerKitInformation::defaultValue(const Kit *kit) const
+void AndroidGdbServerKitAspect::setup(Kit *kit)
{
- return autoDetect(kit).toString();
+ if (kit && !kit->hasValue(id()))
+ kit->setValue(id(), autoDetect(kit).toString());
}
-QList<Task> AndroidGdbServerKitInformation::validate(const Kit *) const
+Tasks AndroidGdbServerKitAspect::validate(const Kit *) const
{
- return QList<Task>();
+ return {};
}
-KitInformation::ItemList AndroidGdbServerKitInformation::toUserOutput(const Kit *kit) const
+bool AndroidGdbServerKitAspect::isApplicableToKit(const Kit *k) const
{
- return KitInformation::ItemList()
- << qMakePair(tr("GDB server"), AndroidGdbServerKitInformation::gdbServer(kit).toUserOutput());
+ return DeviceKitAspect::deviceId(k) == Constants::ANDROID_DEVICE_ID;
}
-KitConfigWidget *AndroidGdbServerKitInformation::createConfigWidget(Kit *kit) const
+KitAspect::ItemList AndroidGdbServerKitAspect::toUserOutput(const Kit *kit) const
{
- QTC_ASSERT(kit, return nullptr);
- return new AndroidGdbServerKitInformationWidget(kit, this);
+ return {{tr("GDB server"), AndroidGdbServerKitAspect::gdbServer(kit).toUserOutput()}};
}
-Core::Id AndroidGdbServerKitInformation::id()
+KitAspectWidget *AndroidGdbServerKitAspect::createConfigWidget(Kit *kit) const
{
- return "Android.GdbServer.Information";
+ QTC_ASSERT(kit, return nullptr);
+ return new AndroidGdbServerKitAspectWidget(kit, this);
}
-bool AndroidGdbServerKitInformation::isAndroidKit(const Kit *kit)
+Core::Id AndroidGdbServerKitAspect::id()
{
- QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(kit);
- ToolChain *tc = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
- if (qt && tc)
- return qt->type() == QLatin1String(Constants::ANDROIDQT)
- && tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID;
- return false;
-
+ return "Android.GdbServer.Information";
}
-FileName AndroidGdbServerKitInformation::gdbServer(const Kit *kit)
+FilePath AndroidGdbServerKitAspect::gdbServer(const Kit *kit)
{
- QTC_ASSERT(kit, return FileName());
- return FileName::fromString(kit->value(AndroidGdbServerKitInformation::id()).toString());
+ QTC_ASSERT(kit, return FilePath());
+ return FilePath::fromString(kit->value(AndroidGdbServerKitAspect::id()).toString());
}
-void AndroidGdbServerKitInformation::setGdbSever(Kit *kit, const FileName &gdbServerCommand)
+void AndroidGdbServerKitAspect::setGdbSever(Kit *kit, const FilePath &gdbServerCommand)
{
QTC_ASSERT(kit, return);
- kit->setValue(AndroidGdbServerKitInformation::id(), gdbServerCommand.toString());
+ kit->setValue(AndroidGdbServerKitAspect::id(), gdbServerCommand.toString());
}
-FileName AndroidGdbServerKitInformation::autoDetect(const Kit *kit)
+FilePath AndroidGdbServerKitAspect::autoDetect(const Kit *kit)
{
- ToolChain *tc = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChain *tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_ID)
- return FileName();
+ return FilePath();
auto atc = static_cast<AndroidToolChain *>(tc);
return atc->suggestedGdbServer();
}
///////////////
-// AndroidGdbServerKitInformationWidget
+// AndroidGdbServerKitAspectWidget
///////////////
-AndroidGdbServerKitInformationWidget::AndroidGdbServerKitInformationWidget(Kit *kit, const KitInformation *ki) :
- KitConfigWidget(kit, ki),
+AndroidGdbServerKitAspectWidget::AndroidGdbServerKitAspectWidget(Kit *kit, const KitAspect *ki) :
+ KitAspectWidget(kit, ki),
m_label(new ElidingLabel),
m_button(new QPushButton(tr("Manage...")))
{
@@ -129,62 +147,47 @@ AndroidGdbServerKitInformationWidget::AndroidGdbServerKitInformationWidget(Kit *
auto buttonMenu = new QMenu(m_button);
QAction *autoDetectAction = buttonMenu->addAction(tr("Auto-detect"));
connect(autoDetectAction, &QAction::triggered,
- this, &AndroidGdbServerKitInformationWidget::autoDetectDebugger);
+ this, &AndroidGdbServerKitAspectWidget::autoDetectDebugger);
QAction *changeAction = buttonMenu->addAction(tr("Edit..."));
connect(changeAction, &QAction::triggered,
- this, &AndroidGdbServerKitInformationWidget::showDialog);
+ this, &AndroidGdbServerKitAspectWidget::showDialog);
m_button->setMenu(buttonMenu);
refresh();
}
-AndroidGdbServerKitInformationWidget::~AndroidGdbServerKitInformationWidget()
+AndroidGdbServerKitAspectWidget::~AndroidGdbServerKitAspectWidget()
{
delete m_button;
delete m_label;
}
-QString AndroidGdbServerKitInformationWidget::displayName() const
-{
- return tr("Android GDB server");
-}
-
-QString AndroidGdbServerKitInformationWidget::toolTip() const
-{
- return tr("The GDB server to use for this kit.");
-}
-
-void AndroidGdbServerKitInformationWidget::makeReadOnly()
+void AndroidGdbServerKitAspectWidget::makeReadOnly()
{
m_button->setEnabled(false);
}
-void AndroidGdbServerKitInformationWidget::refresh()
-{
- m_label->setText(AndroidGdbServerKitInformation::gdbServer(m_kit).toString());
-}
-
-bool AndroidGdbServerKitInformationWidget::visibleInKit()
+void AndroidGdbServerKitAspectWidget::refresh()
{
- return DeviceKitInformation::deviceId(m_kit) == Constants::ANDROID_DEVICE_ID;
+ m_label->setText(AndroidGdbServerKitAspect::gdbServer(m_kit).toString());
}
-QWidget *AndroidGdbServerKitInformationWidget::mainWidget() const
+QWidget *AndroidGdbServerKitAspectWidget::mainWidget() const
{
return m_label;
}
-QWidget *AndroidGdbServerKitInformationWidget::buttonWidget() const
+QWidget *AndroidGdbServerKitAspectWidget::buttonWidget() const
{
return m_button;
}
-void AndroidGdbServerKitInformationWidget::autoDetectDebugger()
+void AndroidGdbServerKitAspectWidget::autoDetectDebugger()
{
- AndroidGdbServerKitInformation::setGdbSever(m_kit, AndroidGdbServerKitInformation::autoDetect(m_kit));
+ AndroidGdbServerKitAspect::setGdbSever(m_kit, AndroidGdbServerKitAspect::autoDetect(m_kit));
}
-void AndroidGdbServerKitInformationWidget::showDialog()
+void AndroidGdbServerKitAspectWidget::showDialog()
{
QDialog dialog;
auto layout = new QVBoxLayout(&dialog);
@@ -194,7 +197,7 @@ void AndroidGdbServerKitInformationWidget::showDialog()
auto binaryLabel = new QLabel(tr("&Binary:"));
auto chooser = new PathChooser;
chooser->setExpectedKind(PathChooser::ExistingCommand);
- chooser->setPath(AndroidGdbServerKitInformation::gdbServer(m_kit).toString());
+ chooser->setPath(AndroidGdbServerKitAspect::gdbServer(m_kit).toString());
binaryLabel->setBuddy(chooser);
formLayout->addRow(binaryLabel, chooser);
layout->addLayout(formLayout);
@@ -207,7 +210,7 @@ void AndroidGdbServerKitInformationWidget::showDialog()
dialog.setWindowTitle(tr("GDB Server for \"%1\"").arg(m_kit->displayName()));
if (dialog.exec() == QDialog::Accepted)
- AndroidGdbServerKitInformation::setGdbSever(m_kit, chooser->fileName());
+ AndroidGdbServerKitAspect::setGdbSever(m_kit, chooser->fileName());
}
} // namespace Internal
diff --git a/src/plugins/android/androidgdbserverkitinformation.h b/src/plugins/android/androidgdbserverkitinformation.h
index 8271926e30..db4f349344 100644
--- a/src/plugins/android/androidgdbserverkitinformation.h
+++ b/src/plugins/android/androidgdbserverkitinformation.h
@@ -26,60 +26,27 @@
#pragma once
#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/kitconfigwidget.h>
-
-QT_BEGIN_NAMESPACE
-class QLabel;
-class QPushButton;
-QT_END_NAMESPACE
namespace Android {
namespace Internal {
-class AndroidGdbServerKitInformationWidget : public ProjectExplorer::KitConfigWidget
-{
- Q_OBJECT
-public:
- AndroidGdbServerKitInformationWidget(ProjectExplorer::Kit *kit,
- const ProjectExplorer::KitInformation *ki);
- ~AndroidGdbServerKitInformationWidget() override;
-
- QString displayName() const override;
- QString toolTip() const override;
- void makeReadOnly() override;
- void refresh() override;
- bool visibleInKit() override;
-
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
-
-private:
- void autoDetectDebugger();
- void showDialog();
-
- QLabel *m_label;
- QPushButton *m_button;
-};
-
-class AndroidGdbServerKitInformation : public ProjectExplorer::KitInformation
+class AndroidGdbServerKitAspect : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- AndroidGdbServerKitInformation();
-
- QVariant defaultValue(const ProjectExplorer::Kit *) const override;
-
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *) const override;
+ AndroidGdbServerKitAspect();
+ void setup(ProjectExplorer::Kit *) override;
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *) const override;
+ bool isApplicableToKit(const ProjectExplorer::Kit *k) const override;
ItemList toUserOutput(const ProjectExplorer::Kit *) const override;
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *) const override;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *) const override;
static Core::Id id();
- static bool isAndroidKit(const ProjectExplorer::Kit *kit);
- static Utils::FileName gdbServer(const ProjectExplorer::Kit *kit);
- static void setGdbSever(ProjectExplorer::Kit *kit, const Utils::FileName &gdbServerCommand);
- static Utils::FileName autoDetect(const ProjectExplorer::Kit *kit);
+ static Utils::FilePath gdbServer(const ProjectExplorer::Kit *kit);
+ static void setGdbSever(ProjectExplorer::Kit *kit, const Utils::FilePath &gdbServerCommand);
+ static Utils::FilePath autoDetect(const ProjectExplorer::Kit *kit);
};
} // namespace Internal
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index c31302f114..bccc0e3b2a 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -109,7 +109,7 @@ public:
using LibrariesMap = QMap<QString, Library>;
-static bool openXmlFile(QDomDocument &doc, const Utils::FileName &fileName);
+static bool openXmlFile(QDomDocument &doc, const Utils::FilePath &fileName);
static bool openManifest(ProjectExplorer::Target *target, QDomDocument &doc);
static int parseMinSdk(const QDomElement &manifestElem);
@@ -129,7 +129,7 @@ QString AndroidManager::packageName(ProjectExplorer::Target *target)
return manifestElem.attribute(QLatin1String("package"));
}
-QString AndroidManager::packageName(const Utils::FileName &manifestFile)
+QString AndroidManager::packageName(const Utils::FilePath &manifestFile)
{
QDomDocument doc;
if (!openXmlFile(doc, manifestFile))
@@ -174,7 +174,7 @@ int AndroidManager::packageVersionCode(const QString &deviceSerial,
return -1;
}
-void AndroidManager::apkInfo(const Utils::FileName &apkPath,
+void AndroidManager::apkInfo(const Utils::FilePath &apkPath,
QString *packageName,
int *version,
QString *activityPath)
@@ -235,10 +235,10 @@ int AndroidManager::minimumSDK(ProjectExplorer::Target *target)
int AndroidManager::minimumSDK(const ProjectExplorer::Kit *kit)
{
int minSDKVersion = -1;
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit);
if (version && version->targetDeviceTypes().contains(Constants::ANDROID_DEVICE_TYPE)) {
- Utils::FileName stockManifestFilePath =
- Utils::FileName::fromUserInput(version->qmakeProperty("QT_INSTALL_PREFIX") +
+ Utils::FilePath stockManifestFilePath =
+ Utils::FilePath::fromUserInput(version->qmakeProperty("QT_INSTALL_PREFIX") +
QLatin1String("/src/android/templates/AndroidManifest.xml"));
QDomDocument doc;
if (openXmlFile(doc, stockManifestFilePath)) {
@@ -248,12 +248,6 @@ int AndroidManager::minimumSDK(const ProjectExplorer::Kit *kit)
return minSDKVersion;
}
-int AndroidManager::minimumNDK(const Kit *kit)
-{
- auto qt = static_cast<AndroidQtVersion *>(QtSupport::QtKitInformation::qtVersion(kit));
- return qt->mininmumNDK();
-}
-
QString AndroidManager::buildTargetSDK(ProjectExplorer::Target *target)
{
if (auto androidBuildApkStep = AndroidBuildApkStep::findInBuild(target->activeBuildConfiguration()))
@@ -264,26 +258,54 @@ QString AndroidManager::buildTargetSDK(ProjectExplorer::Target *target)
return fallback;
}
-QString AndroidManager::targetArch(ProjectExplorer::Target *target)
+QString AndroidManager::targetArch(const Target *target)
{
- auto qt = static_cast<AndroidQtVersion *>(QtSupport::QtKitInformation::qtVersion(target->kit()));
+ auto qt = static_cast<AndroidQtVersion *>(QtSupport::QtKitAspect::qtVersion(target->kit()));
return qt->targetArch();
}
-Utils::FileName AndroidManager::dirPath(const ProjectExplorer::Target *target)
+QJsonObject AndroidManager::deploymentSettings(const Target *target)
+{
+ QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target->kit());
+ if (!qt)
+ return {};
+
+ auto tc = ProjectExplorer::ToolChainKitAspect::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_ID)
+ return {};
+ QJsonObject settings;
+ settings["description"] = "This file is generated by QtCreator to be read by androiddeployqt and should not be modified by hand.";
+ settings["qt"] = qt->qmakeProperty("QT_INSTALL_PREFIX");
+ settings["ndk"] = AndroidConfigurations::currentConfig().ndkLocation().toString();
+ settings["sdk"] = AndroidConfigurations::currentConfig().sdkLocation().toString();
+ settings["sdkBuildToolsRevision"] = AndroidConfigurations::currentConfig().buildToolsVersion().toString();
+ settings["application-binary"] = target->activeRunConfiguration()->buildTargetInfo().targetFilePath.toString();
+ settings["target-architecture"] = targetArch(target);
+ settings["toolchain-prefix"] = "llvm";
+ settings["tool-prefix"] = "llvm";
+ settings["useLLVM"] = true;
+ settings["ndk-host"] = AndroidConfigurations::currentConfig().toolchainHost();
+ settings["stdcpp-path"] = AndroidConfigurations::currentConfig().ndkLocation()
+ .pathAppended("/sources/cxx-stl/llvm-libc++/libs/"
+ + targetArch(target)
+ + "/libc++_shared.so").toString();
+ return settings;
+}
+
+Utils::FilePath AndroidManager::dirPath(const ProjectExplorer::Target *target)
{
if (target->activeBuildConfiguration())
- return target->activeBuildConfiguration()->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY));
- return Utils::FileName();
+ return target->activeBuildConfiguration()->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY);
+ return Utils::FilePath();
}
-Utils::FileName AndroidManager::apkPath(const ProjectExplorer::Target *target)
+Utils::FilePath AndroidManager::apkPath(const ProjectExplorer::Target *target)
{
- QTC_ASSERT(target, return Utils::FileName());
+ QTC_ASSERT(target, return Utils::FilePath());
auto buildApkStep = AndroidBuildApkStep::findInBuild(target->activeBuildConfiguration());
if (!buildApkStep)
- return Utils::FileName();
+ return Utils::FilePath();
QString apkPath("build/outputs/apk/android-build-");
if (buildApkStep->signPackage())
@@ -291,16 +313,16 @@ Utils::FileName AndroidManager::apkPath(const ProjectExplorer::Target *target)
else
apkPath += QLatin1String("debug.apk");
- return dirPath(target).appendPath(apkPath);
+ return dirPath(target).pathAppended(apkPath);
}
-Utils::FileName AndroidManager::manifestSourcePath(ProjectExplorer::Target *target)
+Utils::FilePath AndroidManager::manifestSourcePath(ProjectExplorer::Target *target)
{
if (const ProjectNode *node = currentProjectNode(target)) {
const QString packageSource
= node->data(Android::Constants::AndroidPackageSourceDir).toString();
if (!packageSource.isEmpty()) {
- const FileName manifest = FileName::fromUserInput(packageSource + "/AndroidManifest.xml");
+ const FilePath manifest = FilePath::fromUserInput(packageSource + "/AndroidManifest.xml");
if (manifest.exists())
return manifest;
}
@@ -308,14 +330,22 @@ Utils::FileName AndroidManager::manifestSourcePath(ProjectExplorer::Target *targ
return manifestPath(target);
}
-Utils::FileName AndroidManager::manifestPath(ProjectExplorer::Target *target)
+Utils::FilePath AndroidManager::manifestPath(ProjectExplorer::Target *target)
+{
+ QVariant manifest = target->namedSettings(AndroidManifestName);
+ if (manifest.isValid())
+ return manifest.value<FilePath>();
+ return dirPath(target).pathAppended(AndroidManifestName);
+}
+
+void AndroidManager::setManifestPath(Target *target, const FilePath &path)
{
- return dirPath(target).appendPath(AndroidManifestName);
+ target->setNamedSettings(AndroidManifestName, QVariant::fromValue(path));
}
-Utils::FileName AndroidManager::defaultPropertiesPath(ProjectExplorer::Target *target)
+Utils::FilePath AndroidManager::defaultPropertiesPath(ProjectExplorer::Target *target)
{
- return dirPath(target).appendPath(AndroidDefaultPropertiesName);
+ return dirPath(target).pathAppended(AndroidDefaultPropertiesName);
}
QString AndroidManager::deviceSerialNumber(ProjectExplorer::Target *target)
@@ -410,7 +440,7 @@ static void raiseError(const QString &reason)
QMessageBox::critical(nullptr, AndroidManager::tr("Error creating Android templates."), reason);
}
-static bool openXmlFile(QDomDocument &doc, const Utils::FileName &fileName)
+static bool openXmlFile(QDomDocument &doc, const Utils::FilePath &fileName)
{
QFile f(fileName.toString());
if (!f.open(QIODevice::ReadOnly))
@@ -603,7 +633,7 @@ static bool mergeGradleProperties(const QString &path, GradleProperties properti
bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
{
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
if (!version)
return false;
@@ -611,13 +641,14 @@ bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
if (!node)
return false;
- QFileInfo sourceDirInfo(node->data(Constants::AndroidPackageSourceDir).toString());
- FileName packageSourceDir = FileName::fromString(sourceDirInfo.canonicalFilePath());
- if (!packageSourceDir.appendPath("gradlew").exists())
+ const QString sourceDirName = node->data(Constants::AndroidPackageSourceDir).toString();
+ QFileInfo sourceDirInfo(sourceDirName);
+ const FilePath packageSourceDir = FilePath::fromString(sourceDirInfo.canonicalFilePath())
+ .pathAppended("gradlew");
+ if (!packageSourceDir.exists())
return false;
- Utils::FileName wrapperProps = packageSourceDir;
- wrapperProps.appendPath(QLatin1String("gradle/wrapper/gradle-wrapper.properties"));
+ const FilePath wrapperProps = packageSourceDir.pathAppended("gradle/wrapper/gradle-wrapper.properties");
if (wrapperProps.exists()) {
GradleProperties wrapperProperties = readGradleProperties(wrapperProps.toString());
QString distributionUrl = QString::fromLocal8Bit(wrapperProperties["distributionUrl"]);
@@ -630,10 +661,11 @@ bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
GradleProperties localProperties;
localProperties["sdk.dir"] = AndroidConfigurations::currentConfig().sdkLocation().toString().toLocal8Bit();
- if (!mergeGradleProperties(packageSourceDir.appendPath("local.properties").toString(), localProperties))
+ const FilePath localPropertiesFile = packageSourceDir.pathAppended("local.properties");
+ if (!mergeGradleProperties(localPropertiesFile.toString(), localProperties))
return false;
- QString gradlePropertiesPath = packageSourceDir.appendPath("gradle.properties").toString();
+ const QString gradlePropertiesPath = packageSourceDir.pathAppended("gradle.properties").toString();
GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath);
gradleProperties["qt5AndroidDir"] = version->qmakeProperty("QT_INSTALL_PREFIX")
.append(QLatin1String("/src/android/java")).toLocal8Bit();
@@ -648,11 +680,10 @@ bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
return mergeGradleProperties(gradlePropertiesPath, gradleProperties);
}
-int AndroidManager::findApiLevel(const Utils::FileName &platformPath)
+int AndroidManager::findApiLevel(const Utils::FilePath &platformPath)
{
int apiLevel = -1;
- Utils::FileName propertiesPath = platformPath;
- propertiesPath.appendPath("/source.properties");
+ const Utils::FilePath propertiesPath = platformPath.pathAppended("/source.properties");
if (propertiesPath.exists()) {
QSettings sdkProperties(propertiesPath.toString(), QSettings::IniFormat);
bool validInt = false;
@@ -672,7 +703,7 @@ QProcess *AndroidManager::runAdbCommandDetached(const QStringList &args, QString
p->start(adb, args);
if (p->waitForStarted(500) && p->state() == QProcess::Running) {
if (deleteOnFinish) {
- connect(p.get(), static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ connect(p.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
p.get(), &QObject::deleteLater);
}
return p.release();
diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h
index e624f2dd1d..12bf9ddf90 100644
--- a/src/plugins/android/androidmanager.h
+++ b/src/plugins/android/androidmanager.h
@@ -40,7 +40,7 @@ class Kit;
class Target;
}
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace Android {
@@ -66,10 +66,10 @@ class ANDROID_EXPORT AndroidManager : public QObject
public:
static QString packageName(ProjectExplorer::Target *target);
- static QString packageName(const Utils::FileName &manifestFile);
+ static QString packageName(const Utils::FilePath &manifestFile);
static bool packageInstalled(const QString &deviceSerial, const QString &packageName);
static int packageVersionCode(const QString &deviceSerial, const QString &packageName);
- static void apkInfo(const Utils::FileName &apkPath,
+ static void apkInfo(const Utils::FilePath &apkPath,
QString *packageName = nullptr,
int *version = nullptr,
QString *activityPath = nullptr);
@@ -86,15 +86,15 @@ public:
static int minimumSDK(ProjectExplorer::Target *target);
static int minimumSDK(const ProjectExplorer::Kit *kit);
- static int minimumNDK(const ProjectExplorer::Kit *kit);
- static QString targetArch(ProjectExplorer::Target *target);
+ static QString targetArch(const ProjectExplorer::Target *target);
- static Utils::FileName dirPath(const ProjectExplorer::Target *target);
- static Utils::FileName manifestPath(ProjectExplorer::Target *target);
- static Utils::FileName manifestSourcePath(ProjectExplorer::Target *target);
- static Utils::FileName defaultPropertiesPath(ProjectExplorer::Target *target);
- static Utils::FileName apkPath(const ProjectExplorer::Target *target);
+ static Utils::FilePath dirPath(const ProjectExplorer::Target *target);
+ static Utils::FilePath manifestPath(ProjectExplorer::Target *target);
+ static void setManifestPath(ProjectExplorer::Target *target, const Utils::FilePath &path);
+ static Utils::FilePath manifestSourcePath(ProjectExplorer::Target *target);
+ static Utils::FilePath defaultPropertiesPath(ProjectExplorer::Target *target);
+ static Utils::FilePath apkPath(const ProjectExplorer::Target *target);
static QPair<int, int> apiLevelRange();
static QString androidNameForApiLevel(int x);
@@ -107,7 +107,7 @@ public:
static bool checkCertificateExists(const QString &keystorePath, const QString &keystorePasswd,
const QString &alias);
static bool updateGradleProperties(ProjectExplorer::Target *target);
- static int findApiLevel(const Utils::FileName &platformPath);
+ static int findApiLevel(const Utils::FilePath &platformPath);
static QProcess *runAdbCommandDetached(const QStringList &args, QString *err = nullptr,
bool deleteOnFinish = false);
@@ -115,6 +115,8 @@ public:
int timeoutS = 30);
static SdkToolResult runAaptCommand(const QStringList &args, int timeoutS = 30);
+ static QJsonObject deploymentSettings(const ProjectExplorer::Target *target);
+
private:
static SdkToolResult runCommand(const QString &executable, const QStringList &args,
const QByteArray &writeData = {}, int timeoutS = 30);
diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp
index e040c0db87..72ab0c9984 100644
--- a/src/plugins/android/androidmanifesteditorwidget.cpp
+++ b/src/plugins/android/androidmanifesteditorwidget.cpp
@@ -85,13 +85,13 @@ bool checkPackageName(const QString &packageName)
return QRegExp(packageNameRegExp).exactMatch(packageName);
}
-Project *androidProject(const Utils::FileName &fileName)
+Project *androidProject(const Utils::FilePath &fileName)
{
for (Project *project : SessionManager::projects()) {
if (!project->activeTarget())
continue;
Kit *kit = project->activeTarget()->kit();
- if (DeviceTypeKitInformation::deviceTypeId(kit) == Android::Constants::ANDROID_DEVICE_TYPE
+ if (DeviceTypeKitAspect::deviceTypeId(kit) == Android::Constants::ANDROID_DEVICE_TYPE
&& fileName.isChildOf(project->projectDirectory()))
return project;
}
@@ -202,10 +202,10 @@ void AndroidManifestEditorWidget::initializePage()
connect(m_versionNameLinedit, &QLineEdit::textEdited,
this, setDirtyFunc);
connect(m_androidMinSdkVersion,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, setDirtyFunc);
connect(m_androidTargetSdkVersion,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, setDirtyFunc);
}
@@ -492,7 +492,7 @@ void AndroidManifestEditorWidget::updateTargetComboBox()
QStringList items;
if (project) {
Kit *kit = project->activeTarget()->kit();
- if (DeviceTypeKitInformation::deviceTypeId(kit) == Constants::ANDROID_DEVICE_TYPE) {
+ if (DeviceTypeKitAspect::deviceTypeId(kit) == Constants::ANDROID_DEVICE_TYPE) {
ProjectNode *root = project->rootProjectNode();
root->forEachProjectNode([&items](const ProjectNode *projectNode) {
items << projectNode->targetApplications();
@@ -604,7 +604,7 @@ void AndroidManifestEditorWidget::preSave()
void AndroidManifestEditorWidget::postSave()
{
- const Utils::FileName docPath = m_textEditorWidget->textDocument()->filePath();
+ const Utils::FilePath docPath = m_textEditorWidget->textDocument()->filePath();
ProjectExplorer::Project *project = androidProject(docPath);
if (project) {
if (Target *target = project->activeTarget()) {
@@ -1211,23 +1211,17 @@ void AndroidManifestEditorWidget::parseUnknownElement(QXmlStreamReader &reader,
}
}
-QString AndroidManifestEditorWidget::iconPath(const QString &baseDir, IconDPI dpi)
+QString AndroidManifestEditorWidget::iconPath(IconDPI dpi)
{
- Utils::FileName fileName = Utils::FileName::fromString(baseDir);
switch (dpi) {
case HighDPI:
- fileName.appendPath(QLatin1String("res/drawable-hdpi/icon.png"));
- break;
+ return QString("/res/drawable-hdpi/icon.png");
case MediumDPI:
- fileName.appendPath(QLatin1String("res/drawable-mdpi/icon.png"));
- break;
+ return QString("/res/drawable-mdpi/icon.png");
case LowDPI:
- fileName.appendPath(QLatin1String("res/drawable-ldpi/icon.png"));
- break;
- default:
- return QString();
+ return QString("/res/drawable-ldpi/icon.png");
}
- return fileName.toString();
+ return {};
}
QIcon AndroidManifestEditorWidget::icon(const QString &baseDir, IconDPI dpi)
@@ -1242,7 +1236,7 @@ QIcon AndroidManifestEditorWidget::icon(const QString &baseDir, IconDPI dpi)
if (dpi == LowDPI && !m_lIconPath.isEmpty())
return QIcon(m_lIconPath);
- QString fileName = iconPath(baseDir, dpi);
+ QString fileName = baseDir + iconPath(dpi);
if (fileName.isEmpty())
return QIcon();
return QIcon(fileName);
@@ -1253,7 +1247,7 @@ void AndroidManifestEditorWidget::copyIcon(IconDPI dpi, const QString &baseDir,
if (!QFileInfo::exists(filePath))
return;
- const QString targetPath = iconPath(baseDir, dpi);
+ const QString targetPath = baseDir + iconPath(dpi);
QFile::remove(targetPath);
QDir dir;
dir.mkpath(QFileInfo(targetPath).absolutePath());
diff --git a/src/plugins/android/androidmanifesteditorwidget.h b/src/plugins/android/androidmanifesteditorwidget.h
index 49d1ec1155..d7a7ff092c 100644
--- a/src/plugins/android/androidmanifesteditorwidget.h
+++ b/src/plugins/android/androidmanifesteditorwidget.h
@@ -137,7 +137,7 @@ private:
int *errorLine, int *errorColumn);
enum IconDPI { LowDPI, MediumDPI, HighDPI };
QIcon icon(const QString &baseDir, IconDPI dpi);
- QString iconPath(const QString &baseDir, IconDPI dpi);
+ QString iconPath(IconDPI dpi);
void copyIcon(IconDPI dpi, const QString &baseDir, const QString &filePath);
void updateInfoBar(const QString &errorMessage, int line, int column);
diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp
index a5d81c2f87..9ad698bdec 100644
--- a/src/plugins/android/androidpackageinstallationstep.cpp
+++ b/src/plugins/android/androidpackageinstallationstep.cpp
@@ -61,17 +61,18 @@ AndroidPackageInstallationStep::AndroidPackageInstallationStep(BuildStepList *bs
bool AndroidPackageInstallationStep::init()
{
BuildConfiguration *bc = buildConfiguration();
- QString dirPath = bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString();
+ QString dirPath = bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString();
if (HostOsInfo::isWindowsHost())
if (bc->environment().searchInPath("sh.exe").isEmpty())
dirPath = QDir::toNativeSeparators(dirPath);
- ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit(),
+ ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(),
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ QTC_ASSERT(tc, return false);
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
- pp->setWorkingDirectory(bc->buildDirectory().toString());
+ pp->setWorkingDirectory(bc->buildDirectory());
pp->setCommand(tc->makeCommand(bc->environment()));
Environment env = bc->environment();
Environment::setupEnglishOutput(&env);
@@ -99,7 +100,7 @@ void AndroidPackageInstallationStep::doRun()
{
QString error;
foreach (const QString &dir, m_androidDirsToClean) {
- FileName androidDir = FileName::fromString(dir);
+ FilePath androidDir = FilePath::fromString(dir);
if (!dir.isEmpty() && androidDir.exists()) {
emit addOutput(tr("Removing directory %1").arg(dir), OutputFormat::NormalMessage);
if (!FileUtils::removeRecursively(androidDir, &error)) {
diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp
index 2b19da438f..29f4392712 100644
--- a/src/plugins/android/androidplugin.cpp
+++ b/src/plugins/android/androidplugin.cpp
@@ -30,14 +30,13 @@
#include "androiddebugsupport.h"
#include "androiddeployqtstep.h"
#include "androiddevice.h"
-#include "androiddevicefactory.h"
#include "androidgdbserverkitinformation.h"
#include "androidmanager.h"
#include "androidmanifesteditorfactory.h"
#include "androidpackageinstallationstep.h"
#include "androidpotentialkit.h"
#include "androidqmltoolingsupport.h"
-#include "androidqtversionfactory.h"
+#include "androidqtversion.h"
#include "androidrunconfiguration.h"
#include "androidruncontrol.h"
#include "androidsettingspage.h"
@@ -86,10 +85,25 @@ public:
registerRunConfiguration<Android::AndroidRunConfiguration>
("Qt4ProjectManager.AndroidRunConfiguration:");
addSupportedTargetDeviceType(Android::Constants::ANDROID_DEVICE_TYPE);
- addRunWorkerFactory<AndroidRunSupport>(NORMAL_RUN_MODE);
- addRunWorkerFactory<AndroidDebugSupport>(DEBUG_RUN_MODE);
- addRunWorkerFactory<AndroidQmlToolingSupport>(QML_PROFILER_RUN_MODE);
- addRunWorkerFactory<AndroidQmlToolingSupport>(QML_PREVIEW_RUN_MODE);
+ }
+};
+
+class QmlPreviewRunWorkerFactory : public RunWorkerFactory
+{
+public:
+ QmlPreviewRunWorkerFactory()
+ {
+ addSupportedRunMode(QML_PREVIEW_RUN_MODE);
+ setProducer([](RunControl *runControl) -> RunWorker * {
+ const Runnable runnable = runControl->runConfiguration()->runnable();
+ return new AndroidQmlToolingSupport(runControl, runnable.executable);
+ });
+ addConstraint([](RunConfiguration *runConfig) {
+ return runConfig->isEnabled()
+ && runConfig->id().name().startsWith("QmlProjectManager.QmlRunConfiguration")
+ && DeviceTypeKitAspect::deviceTypeId(runConfig->target()->kit())
+ == Android::Constants::ANDROID_DEVICE_TYPE;
+ });
}
};
@@ -107,7 +121,7 @@ public:
void handleNewTarget(Target *target)
{
- if (DeviceTypeKitInformation::deviceTypeId(target->kit()) != Android::Constants::ANDROID_DEVICE_TYPE)
+ if (DeviceTypeKitAspect::deviceTypeId(target->kit()) != Android::Constants::ANDROID_DEVICE_TYPE)
return;
for (BuildConfiguration *bc : target->buildConfigurations())
@@ -136,7 +150,18 @@ public:
AndroidPackageInstallationFactory packackeInstallationFactory;
AndroidManifestEditorFactory manifestEditorFactory;
AndroidRunConfigurationFactory runConfigFactory;
+
+ SimpleRunWorkerFactory<AndroidRunSupport, AndroidRunConfiguration> runWorkerFactory;
+ SimpleRunWorkerFactory<AndroidDebugSupport, AndroidRunConfiguration>
+ debugWorkerFactory{DEBUG_RUN_MODE};
+ SimpleRunWorkerFactory<AndroidQmlToolingSupport, AndroidRunConfiguration>
+ profilerWorkerFactory{QML_PROFILER_RUN_MODE};
+ SimpleRunWorkerFactory<AndroidQmlToolingSupport, AndroidRunConfiguration>
+ qmlPreviewWorkerFactory{QML_PREVIEW_RUN_MODE};
+ QmlPreviewRunWorkerFactory qmlPreviewWorkerFactory2;
+
AndroidBuildApkStepFactory buildApkStepFactory;
+ AndroidGdbServerKitAspect gdbServerKitAspect;
};
AndroidPlugin::~AndroidPlugin()
@@ -149,20 +174,8 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa
Q_UNUSED(arguments);
Q_UNUSED(errorMessage);
- RunControl::registerWorker(QML_PREVIEW_RUN_MODE, [](RunControl *runControl) -> RunWorker* {
- const Runnable runnable = runControl->runConfiguration()->runnable();
- return new AndroidQmlToolingSupport(runControl, runnable.executable);
- }, [](RunConfiguration *runConfig) {
- return runConfig->isEnabled()
- && runConfig->id().name().startsWith("QmlProjectManager.QmlRunConfiguration")
- && DeviceTypeKitInformation::deviceTypeId(runConfig->target()->kit())
- == Android::Constants::ANDROID_DEVICE_TYPE;
- });
-
d = new AndroidPluginPrivate;
- KitManager::registerKitInformation<Internal::AndroidGdbServerKitInformation>();
-
connect(KitManager::instance(), &KitManager::kitsLoaded,
this, &AndroidPlugin::kitsRestored);
diff --git a/src/plugins/android/androidplugin.h b/src/plugins/android/androidplugin.h
index 5f71e3886c..7042491b86 100644
--- a/src/plugins/android/androidplugin.h
+++ b/src/plugins/android/androidplugin.h
@@ -29,16 +29,12 @@
namespace Android {
namespace Internal {
-class AndroidPluginPrivate;
+
class AndroidPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Android.json")
-public:
- AndroidPlugin() = default;
-
-private:
~AndroidPlugin() final;
bool initialize(const QStringList &arguments, QString *errorMessage) final;
@@ -46,7 +42,7 @@ private:
void kitsRestored();
- AndroidPluginPrivate *d = nullptr;
+ class AndroidPluginPrivate *d = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/android/androidpotentialkit.cpp b/src/plugins/android/androidpotentialkit.cpp
index 8264415a12..f755551b28 100644
--- a/src/plugins/android/androidpotentialkit.cpp
+++ b/src/plugins/android/androidpotentialkit.cpp
@@ -68,7 +68,7 @@ bool AndroidPotentialKit::isEnabled() const
{
QList<ProjectExplorer::Kit *> kits = ProjectExplorer::KitManager::kits();
foreach (ProjectExplorer::Kit *kit, kits) {
- Core::Id deviceId = ProjectExplorer::DeviceKitInformation::deviceId(kit);
+ Core::Id deviceId = ProjectExplorer::DeviceKitAspect::deviceId(kit);
if (kit->isAutoDetected()
&& deviceId == Core::Id(Constants::ANDROID_DEVICE_ID)
&& !kit->isSdkProvided()) {
@@ -120,7 +120,7 @@ void AndroidPotentialKitWidget::recheck()
{
QList<ProjectExplorer::Kit *> kits = ProjectExplorer::KitManager::kits();
foreach (ProjectExplorer::Kit *kit, kits) {
- Core::Id deviceId = ProjectExplorer::DeviceKitInformation::deviceId(kit);
+ Core::Id deviceId = ProjectExplorer::DeviceKitAspect::deviceId(kit);
if (kit->isAutoDetected()
&& deviceId == Core::Id(Constants::ANDROID_DEVICE_ID)
&& !kit->isSdkProvided()) {
diff --git a/src/plugins/android/androidqmltoolingsupport.h b/src/plugins/android/androidqmltoolingsupport.h
index 5e1d00aa3b..8351de59a9 100644
--- a/src/plugins/android/androidqmltoolingsupport.h
+++ b/src/plugins/android/androidqmltoolingsupport.h
@@ -25,7 +25,7 @@
#pragma once
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
namespace Android {
diff --git a/src/plugins/android/androidqtversion.cpp b/src/plugins/android/androidqtversion.cpp
index 9916fc1deb..eff95c3f04 100644
--- a/src/plugins/android/androidqtversion.cpp
+++ b/src/plugins/android/androidqtversion.cpp
@@ -42,30 +42,16 @@
#include <proparser/profileevaluator.h>
-using namespace Android::Internal;
using namespace ProjectExplorer;
+namespace Android {
+namespace Internal {
+
AndroidQtVersion::AndroidQtVersion()
: QtSupport::BaseQtVersion()
{
}
-AndroidQtVersion::AndroidQtVersion(const Utils::FileName &path, bool isAutodetected, const QString &autodetectionSource)
- : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource)
-{
- setUnexpandedDisplayName(defaultUnexpandedDisplayName(path, false));
-}
-
-AndroidQtVersion *AndroidQtVersion::clone() const
-{
- return new AndroidQtVersion(*this);
-}
-
-QString AndroidQtVersion::type() const
-{
- return QLatin1String(Constants::ANDROIDQT);
-}
-
bool AndroidQtVersion::isValid() const
{
if (!BaseQtVersion::isValid())
@@ -83,9 +69,9 @@ QString AndroidQtVersion::invalidReason() const
return tmp;
}
-QList<Abi> AndroidQtVersion::detectQtAbis() const
+Abis AndroidQtVersion::detectQtAbis() const
{
- QList<Abi> abis = qtAbisFromLibrary(qtCorePaths());
+ Abis abis = BaseQtVersion::detectQtAbis();
for (int i = 0; i < abis.count(); ++i) {
abis[i] = Abi(abis.at(i).architecture(),
abis.at(i).os(),
@@ -103,7 +89,7 @@ void AndroidQtVersion::addToEnvironment(const Kit *k, Utils::Environment &env) c
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHost());
env.set(QLatin1String("ANDROID_NDK_ROOT"), config.ndkLocation().toUserOutput());
env.set(QLatin1String("ANDROID_NDK_PLATFORM"),
- config.bestNdkPlatformMatch(qMax(AndroidManager::minimumNDK(k), AndroidManager::minimumSDK(k))));
+ config.bestNdkPlatformMatch(qMax(minimumNDK(), AndroidManager::minimumSDK(k))));
}
Utils::Environment AndroidQtVersion::qmakeRunEnvironment() const
@@ -125,7 +111,7 @@ QString AndroidQtVersion::targetArch() const
return m_targetArch;
}
-int AndroidQtVersion::mininmumNDK() const
+int AndroidQtVersion::minimumNDK() const
{
ensureMkSpecParsed();
return m_minNdk;
@@ -160,3 +146,22 @@ QSet<Core::Id> AndroidQtVersion::targetDeviceTypes() const
{
return {Constants::ANDROID_DEVICE_TYPE};
}
+
+
+// Factory
+
+AndroidQtVersionFactory::AndroidQtVersionFactory()
+{
+ setQtVersionCreator([] { return new AndroidQtVersion; });
+ setSupportedType(Constants::ANDROIDQT);
+ setPriority(90);
+
+ setRestrictionChecker([](const SetupData &setup) {
+ return !setup.config.contains("android-no-sdk")
+ && (setup.config.contains("android")
+ || setup.platforms.contains("android"));
+ });
+}
+
+} // Internal
+} // Android
diff --git a/src/plugins/android/androidqtversion.h b/src/plugins/android/androidqtversion.h
index d009c68ceb..519d702ead 100644
--- a/src/plugins/android/androidqtversion.h
+++ b/src/plugins/android/androidqtversion.h
@@ -26,6 +26,7 @@
#pragma once
#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtversionfactory.h>
#include <QCoreApplication>
@@ -38,14 +39,11 @@ class AndroidQtVersion : public QtSupport::BaseQtVersion
public:
AndroidQtVersion();
- AndroidQtVersion(const Utils::FileName &path, bool isAutodetected = false, const QString &autodetectionSource = QString());
- AndroidQtVersion *clone() const override;
- QString type() const override;
bool isValid() const override;
QString invalidReason() const override;
- QList<ProjectExplorer::Abi> detectQtAbis() const override;
+ ProjectExplorer::Abis detectQtAbis() const override;
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const override;
Utils::Environment qmakeRunEnvironment() const override;
@@ -55,7 +53,8 @@ public:
QString description() const override;
QString targetArch() const;
- int mininmumNDK() const;
+ int minimumNDK() const;
+
protected:
void parseMkSpec(ProFileEvaluator *) const override;
private:
@@ -63,5 +62,11 @@ private:
mutable int m_minNdk = -1;
};
+class AndroidQtVersionFactory : public QtSupport::QtVersionFactory
+{
+public:
+ AndroidQtVersionFactory();
+};
+
} // namespace Internal
} // namespace Android
diff --git a/src/plugins/android/androidqtversionfactory.cpp b/src/plugins/android/androidqtversionfactory.cpp
deleted file mode 100644
index 00df010def..0000000000
--- a/src/plugins/android/androidqtversionfactory.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "androidqtversionfactory.h"
-#include "androidqtversion.h"
-#include "androidconstants.h"
-#include <qtsupport/qtsupportconstants.h>
-#include <utils/qtcassert.h>
-#include <proparser/profileevaluator.h>
-
-#include <QFileInfo>
-
-namespace Android {
-namespace Internal {
-
-AndroidQtVersionFactory::AndroidQtVersionFactory(QObject *parent)
- : QtSupport::QtVersionFactory(parent)
-{
-}
-
-bool AndroidQtVersionFactory::canRestore(const QString &type)
-{
- return type == QLatin1String(Constants::ANDROIDQT);
-}
-
-QtSupport::BaseQtVersion *AndroidQtVersionFactory::restore(const QString &type,
- const QVariantMap &data)
-{
- QTC_ASSERT(canRestore(type), return nullptr);
- auto v = new AndroidQtVersion;
- v->fromMap(data);
- return v;
-}
-
-int AndroidQtVersionFactory::priority() const
-{
- return 90;
-}
-
-QtSupport::BaseQtVersion *AndroidQtVersionFactory::create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator, bool isAutoDetected, const QString &autoDetectionSource)
-{
- QFileInfo fi = qmakePath.toFileInfo();
- if (!fi.exists() || !fi.isExecutable() || !fi.isFile())
- return nullptr;
- if (!evaluator->values(QLatin1String("CONFIG")).contains(QLatin1String("android"))
- && evaluator->value(QLatin1String("QMAKE_PLATFORM")) != QLatin1String("android"))
- return nullptr;
- if (evaluator->values(QLatin1String("CONFIG")).contains(QLatin1String("android-no-sdk")))
- return nullptr;
- return new AndroidQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
-}
-
-} // Internal
-} // Android
diff --git a/src/plugins/android/androidqtversionfactory.h b/src/plugins/android/androidqtversionfactory.h
deleted file mode 100644
index 92d2e44725..0000000000
--- a/src/plugins/android/androidqtversionfactory.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/qtversionfactory.h>
-
-namespace Android {
-namespace Internal {
-
-class AndroidQtVersionFactory : public QtSupport::QtVersionFactory
-{
-public:
- explicit AndroidQtVersionFactory(QObject *parent = nullptr);
-
- bool canRestore(const QString &type) override;
- QtSupport::BaseQtVersion *restore(const QString &type, const QVariantMap &data) override;
-
- int priority() const override;
- QtSupport::BaseQtVersion *create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator,
- bool isAutoDetected = false, const QString &autoDetectionSource = QString()) override;
-};
-
-} // namespace Internal
-} // namespace Android
diff --git a/src/plugins/android/androidrunconfiguration.cpp b/src/plugins/android/androidrunconfiguration.cpp
index 1f16851fff..fa81749cd4 100644
--- a/src/plugins/android/androidrunconfiguration.cpp
+++ b/src/plugins/android/androidrunconfiguration.cpp
@@ -30,7 +30,6 @@
#include "androidtoolchain.h"
#include "androidmanager.h"
#include "adbcommandswidget.h"
-#include "androidrunenvironmentaspect.h"
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
@@ -108,7 +107,9 @@ void BaseStringListAspect::setLabel(const QString &label)
AndroidRunConfiguration::AndroidRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- addAspect<AndroidRunEnvironmentAspect>();
+ auto envAspect = addAspect<EnvironmentAspect>();
+ envAspect->addSupportedBaseEnvironment(tr("Clean Environment"), {});
+
addAspect<ArgumentsAspect>();
auto amStartArgsAspect = addAspect<BaseStringAspect>();
@@ -155,22 +156,4 @@ void AndroidRunConfiguration::updateTargetInformation()
setDefaultDisplayName(bti.displayName);
}
-QString AndroidRunConfiguration::disabledReason() const
-{
- const BuildTargetInfo bti = buildTargetInfo();
- const QString projectFileName = bti.projectFilePath.toString();
-
- if (project()->isParsing())
- return tr("The project file \"%1\" is currently being parsed.").arg(projectFileName);
-
- if (!project()->hasParsingData()) {
- if (!bti.projectFilePath.exists())
- return tr("The project file \"%1\" does not exist.").arg(projectFileName);
-
- return tr("The project file \"%1\" could not be parsed.").arg(projectFileName);
- }
-
- return QString();
-}
-
} // namespace Android
diff --git a/src/plugins/android/androidrunconfiguration.h b/src/plugins/android/androidrunconfiguration.h
index bc6e10b90c..6723048f37 100644
--- a/src/plugins/android/androidrunconfiguration.h
+++ b/src/plugins/android/androidrunconfiguration.h
@@ -68,7 +68,6 @@ class ANDROID_EXPORT AndroidRunConfiguration : public ProjectExplorer::RunConfig
public:
explicit AndroidRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
- QString disabledReason() const override;
QWidget *createConfigurationWidget() override;
private:
diff --git a/src/plugins/android/androidrunenvironmentaspect.cpp b/src/plugins/android/androidrunenvironmentaspect.cpp
deleted file mode 100644
index 1db75f0352..0000000000
--- a/src/plugins/android/androidrunenvironmentaspect.cpp
+++ /dev/null
@@ -1,47 +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 "androidrunenvironmentaspect.h"
-
-namespace {
-enum BaseEnvironmentBase {
- CleanEnvironmentBase
-};
-}
-
-namespace Android {
-
-AndroidRunEnvironmentAspect::AndroidRunEnvironmentAspect()
-{
- addSupportedBaseEnvironment(CleanEnvironmentBase, tr("Clean Environment"));
-}
-
-Utils::Environment AndroidRunEnvironmentAspect::baseEnvironment() const
-{
- // Clean Environment
- return Utils::Environment();
-}
-
-} // namespace Android
-
diff --git a/src/plugins/android/androidrunenvironmentaspect.h b/src/plugins/android/androidrunenvironmentaspect.h
deleted file mode 100644
index 0620f57746..0000000000
--- a/src/plugins/android/androidrunenvironmentaspect.h
+++ /dev/null
@@ -1,42 +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 <projectexplorer/environmentaspect.h>
-
-namespace Android {
-
-class AndroidRunEnvironmentAspect : public ProjectExplorer::EnvironmentAspect
-{
- Q_OBJECT
-
-public:
- AndroidRunEnvironmentAspect();
-
- Utils::Environment baseEnvironment() const override;
-};
-
-} // namespace Android
-
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index f20f834c60..24ac13a4f1 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -119,7 +119,7 @@ namespace Android {
namespace Internal {
AndroidRunner::AndroidRunner(RunControl *runControl, const QString &intentName)
- : RunWorker(runControl), m_target(runControl->runConfiguration()->target())
+ : RunWorker(runControl), m_target(runControl->target())
{
setId("AndroidRunner");
static const int metaTypes[] = {
diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h
index d56b59c001..d8e0726c1b 100644
--- a/src/plugins/android/androidrunner.h
+++ b/src/plugins/android/androidrunner.h
@@ -27,7 +27,7 @@
#include "androidconfigurations.h"
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
#include <qmldebug/qmloutputparser.h>
diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp
index 4a4386740b..b84ec9df74 100644
--- a/src/plugins/android/androidrunnerworker.cpp
+++ b/src/plugins/android/androidrunnerworker.cpp
@@ -32,11 +32,15 @@
#include "androidgdbserverkitinformation.h"
#include <debugger/debuggerrunconfigurationaspect.h>
+
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
+
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
+
#include <utils/hostosinfo.h>
#include <utils/runextensions.h>
#include <utils/synchronousprocess.h>
@@ -63,7 +67,6 @@ using namespace ProjectExplorer;
namespace Android {
namespace Internal {
-
static const QString pidScript = "pidof -s \"%1\"";
static const QString pidScriptPreNougat = QStringLiteral("for p in /proc/[0-9]*; "
"do cat <$p/cmdline && echo :${p##*/}; done");
@@ -162,9 +165,9 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
, m_jdbProcess(nullptr, deleter)
{
- auto runConfig = runner->runControl()->runConfiguration();
- auto aspect = runConfig->aspect<Debugger::DebuggerRunConfigurationAspect>();
- Core::Id runMode = runner->runMode();
+ auto runControl = runner->runControl();
+ auto aspect = runControl->aspect<Debugger::DebuggerRunConfigurationAspect>();
+ Core::Id runMode = runControl->runMode();
const bool debuggingMode = runMode == ProjectExplorer::Constants::DEBUG_RUN_MODE;
m_useCppDebugger = debuggingMode && aspect->useCppDebugger();
if (debuggingMode && aspect->useQmlDebugger())
@@ -190,27 +193,27 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
m_localJdbServerPort = Utils::Port(5038);
QTC_CHECK(m_localJdbServerPort.isValid());
- auto target = runConfig->target();
+ auto target = runControl->target();
m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target);
m_apiLevel = AndroidManager::deviceApiLevel(target);
- m_extraEnvVars = runConfig->aspect<EnvironmentAspect>()->environment();
+ m_extraEnvVars = runControl->aspect<EnvironmentAspect>()->environment();
qCDebug(androidRunWorkerLog) << "Environment variables for the app"
<< m_extraEnvVars.toStringList();
- m_extraAppParams = runConfig->runnable().commandLineArguments;
+ m_extraAppParams = runControl->runnable().commandLineArguments;
- if (auto aspect = runConfig->aspect(Constants::ANDROID_AMSTARTARGS))
+ if (auto aspect = runControl->aspect(Constants::ANDROID_AMSTARTARGS))
m_amStartExtraArgs = static_cast<BaseStringAspect *>(aspect)->value().split(' ');
- if (auto aspect = runConfig->aspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) {
+ if (auto aspect = runControl->aspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) {
for (const QString &shellCmd : static_cast<BaseStringListAspect *>(aspect)->value())
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
}
for (const QString &shellCmd : runner->recordedData(Constants::ANDROID_PRESTARTSHELLCMDLIST).toStringList())
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
- if (auto aspect = runConfig->aspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) {
+ if (auto aspect = runControl->aspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) {
for (const QString &shellCmd : static_cast<BaseStringListAspect *>(aspect)->value())
m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
}
@@ -222,8 +225,8 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
<< "Extra Start Args:" << m_amStartExtraArgs
<< "Before Start ADB cmds:" << m_beforeStartAdbCommands
<< "After finish ADB cmds:" << m_afterFinishAdbCommands;
- m_gdbserverPath = AndroidGdbServerKitInformation::gdbServer(target->kit()).toString();
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
+ m_gdbserverPath = AndroidGdbServerKitAspect::gdbServer(target->kit()).toString();
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
m_useAppParamsForQmlDebugger = version->qtVersion() >= QtSupport::QtVersionNumber(5, 12);
}
@@ -585,11 +588,11 @@ void AndroidRunnerWorker::handleJdbWaiting()
}
m_afterFinishAdbCommands.push_back(removeForward.join(' '));
- auto jdbPath = AndroidConfigurations::currentConfig().openJDKLocation().appendPath("bin");
+ auto jdbPath = AndroidConfigurations::currentConfig().openJDKLocation().pathAppended("bin");
if (Utils::HostOsInfo::isWindowsHost())
- jdbPath.appendPath("jdb.exe");
+ jdbPath = jdbPath.pathAppended("jdb.exe");
else
- jdbPath.appendPath("jdb");
+ jdbPath = jdbPath.pathAppended("jdb");
QStringList jdbArgs("-connect");
jdbArgs << QString("com.sun.jdi.SocketAttach:hostname=localhost,port=%1")
@@ -672,7 +675,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
QTC_ASSERT(m_psIsAlive, return);
m_psIsAlive->setObjectName("IsAliveProcess");
m_psIsAlive->setProcessChannelMode(QProcess::MergedChannels);
- connect(m_psIsAlive.get(), static_cast<void(QProcess::*)(int)>(&QProcess::finished),
+ connect(m_psIsAlive.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, bind(&AndroidRunnerWorker::onProcessIdChanged, this, -1));
}
}
diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp
index e2c0453d6c..8b58cdd1ad 100644
--- a/src/plugins/android/androidsdkmanager.cpp
+++ b/src/plugins/android/androidsdkmanager.cpp
@@ -223,7 +223,7 @@ private:
AndroidSdkManager &m_sdkManager;
const AndroidConfig &m_config;
AndroidSdkPackageList m_allPackages;
- FileName lastSdkManagerPath;
+ FilePath lastSdkManagerPath;
QString m_licenseTextCache;
QByteArray m_licenseUserInput;
mutable QReadWriteLock m_licenseInputLock;
@@ -243,7 +243,7 @@ class SdkManagerOutputParser
QStringList headerParts;
QVersionNumber revision;
QString description;
- Utils::FileName installedLocation;
+ Utils::FilePath installedLocation;
QMap<QString, QString> extraData;
};
@@ -612,7 +612,7 @@ bool SdkManagerOutputParser::parseAbstractData(SdkManagerOutputParser::GenericPa
for (const auto &key: qAsConst(extraKeys)) {
if (valueForKey(key, line, &value)) {
if (key == installLocationKey)
- output.installedLocation = Utils::FileName::fromString(value);
+ output.installedLocation = Utils::FilePath::fromString(value);
else if (key == revisionKey)
output.revision = QVersionNumber::fromString(value);
else if (key == descriptionKey)
@@ -930,7 +930,7 @@ void AndroidSdkManagerPrivate::getPendingLicense(SdkCmdFutureInterface &fi)
QtcProcess licenseCommand;
licenseCommand.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(m_config));
bool reviewingLicenses = false;
- licenseCommand.setCommand(m_config.sdkManagerToolPath().toString(), {"--licenses"});
+ licenseCommand.setCommand(CommandLine(m_config.sdkManagerToolPath(), "--licenses"));
if (Utils::HostOsInfo::isWindowsHost())
licenseCommand.setUseCtrlCStub(true);
licenseCommand.start();
diff --git a/src/plugins/android/androidsdkpackage.cpp b/src/plugins/android/androidsdkpackage.cpp
index 127aa97a2e..59978b3b7d 100644
--- a/src/plugins/android/androidsdkpackage.cpp
+++ b/src/plugins/android/androidsdkpackage.cpp
@@ -69,7 +69,7 @@ const QString &AndroidSdkPackage::sdkStylePath() const
return m_sdkStylePath;
}
-const Utils::FileName &AndroidSdkPackage::installedLocation() const
+const Utils::FilePath &AndroidSdkPackage::installedLocation() const
{
return m_installedLocation;
}
@@ -89,7 +89,7 @@ void AndroidSdkPackage::setState(AndroidSdkPackage::PackageState state)
m_state = state;
}
-void AndroidSdkPackage::setInstalledLocation(const Utils::FileName &path)
+void AndroidSdkPackage::setInstalledLocation(const Utils::FilePath &path)
{
m_installedLocation = path;
if (m_installedLocation.exists())
diff --git a/src/plugins/android/androidsdkpackage.h b/src/plugins/android/androidsdkpackage.h
index beca0472dd..9f85e87be9 100644
--- a/src/plugins/android/androidsdkpackage.h
+++ b/src/plugins/android/androidsdkpackage.h
@@ -77,13 +77,13 @@ public:
const QVersionNumber &revision() const;
PackageState state() const;
const QString &sdkStylePath() const;
- const Utils::FileName &installedLocation() const;
+ const Utils::FilePath &installedLocation() const;
protected:
void setDisplayText(const QString &str);
void setDescriptionText(const QString &str);
void setState(PackageState state);
- void setInstalledLocation(const Utils::FileName &path);
+ void setInstalledLocation(const Utils::FilePath &path);
virtual void updatePackageDetails();
@@ -93,7 +93,7 @@ private:
QVersionNumber m_revision;
PackageState m_state = PackageState::Unknown;
QString m_sdkStylePath;
- Utils::FileName m_installedLocation;
+ Utils::FilePath m_installedLocation;
friend class Internal::SdkManagerOutputParser;
friend class Internal::AndroidToolOutputParser;
diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp
index b45da47d41..494af3065f 100644
--- a/src/plugins/android/androidsettingswidget.cpp
+++ b/src/plugins/android/androidsettingswidget.cpp
@@ -371,32 +371,28 @@ void AndroidSettingsWidget::saveSettings()
void AndroidSettingsWidget::validateJdk()
{
- auto javaPath = Utils::FileName::fromUserInput(m_ui->OpenJDKLocationPathChooser->rawPath());
+ auto javaPath = Utils::FilePath::fromUserInput(m_ui->OpenJDKLocationPathChooser->rawPath());
m_androidConfig.setOpenJDKLocation(javaPath);
bool jdkPathExists = m_androidConfig.openJDKLocation().exists();
auto summaryWidget = static_cast<SummaryWidget *>(m_ui->javaDetailsWidget->widget());
summaryWidget->setPointValid(JavaPathExistsRow, jdkPathExists);
- Utils::FileName bin = m_androidConfig.openJDKLocation();
- bin.appendPath(QLatin1String("bin/javac" QTC_HOST_EXE_SUFFIX));
+ const Utils::FilePath bin = m_androidConfig.openJDKLocation().pathAppended("bin/javac" QTC_HOST_EXE_SUFFIX);
summaryWidget->setPointValid(JavaJdkValidRow, jdkPathExists && bin.exists());
updateUI();
}
void AndroidSettingsWidget::validateNdk()
{
- auto ndkPath = Utils::FileName::fromUserInput(m_ui->NDKLocationPathChooser->rawPath());
+ auto ndkPath = Utils::FilePath::fromUserInput(m_ui->NDKLocationPathChooser->rawPath());
m_androidConfig.setNdkLocation(ndkPath);
auto summaryWidget = static_cast<SummaryWidget *>(m_ui->androidDetailsWidget->widget());
summaryWidget->setPointValid(NdkPathExistsRow, m_androidConfig.ndkLocation().exists());
- Utils::FileName ndkPlatformsDir(ndkPath);
- ndkPlatformsDir.appendPath("platforms");
- Utils::FileName ndkToolChainsDir(ndkPath);
- ndkToolChainsDir.appendPath("toolchains");
- Utils::FileName ndkSourcesDir(ndkPath);
- ndkSourcesDir.appendPath("sources/cxx-stl");
+ const Utils::FilePath ndkPlatformsDir = ndkPath.pathAppended("platforms");
+ const Utils::FilePath ndkToolChainsDir = ndkPath.pathAppended("toolchains");
+ const Utils::FilePath ndkSourcesDir = ndkPath.pathAppended("sources/cxx-stl");
summaryWidget->setPointValid(NdkDirStructureRow,
ndkPlatformsDir.exists()
&& ndkToolChainsDir.exists()
@@ -409,7 +405,7 @@ void AndroidSettingsWidget::validateNdk()
void AndroidSettingsWidget::onSdkPathChanged()
{
- auto sdkPath = Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath());
+ auto sdkPath = Utils::FilePath::fromUserInput(m_ui->SDKLocationPathChooser->rawPath());
m_androidConfig.setSdkLocation(sdkPath);
// Package reload will trigger validateSdk.
m_sdkManager->reloadPackages();
diff --git a/src/plugins/android/androidsignaloperation.cpp b/src/plugins/android/androidsignaloperation.cpp
index bb54b833ab..2410ed4732 100644
--- a/src/plugins/android/androidsignaloperation.cpp
+++ b/src/plugins/android/androidsignaloperation.cpp
@@ -63,8 +63,7 @@ void Android::Internal::AndroidSignalOperation::adbFindRunAsFinished(int exitCod
m_state = Idle;
emit finished(m_errorMessage);
} else {
- connect(m_adbProcess,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_adbProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &AndroidSignalOperation::adbKillFinished);
m_state = Kill;
m_timeout->start();
@@ -113,8 +112,7 @@ void Android::Internal::AndroidSignalOperation::signalOperationViaADB(qint64 pid
m_adbProcess->disconnect(this);
m_pid = pid;
m_signal = signal;
- connect(m_adbProcess,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_adbProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &AndroidSignalOperation::adbFindRunAsFinished);
m_state = RunAs;
m_timeout->start();
diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp
index 1a7315309d..3c45885471 100644
--- a/src/plugins/android/androidtoolchain.cpp
+++ b/src/plugins/android/androidtoolchain.cpp
@@ -60,7 +60,7 @@ static const QHash<QString, Abi> ClangTargets = {
static const QList<Core::Id> LanguageIds = {ProjectExplorer::Constants::CXX_LANGUAGE_ID,
ProjectExplorer::Constants::C_LANGUAGE_ID};
-static ToolChain *findToolChain(Utils::FileName &compilerPath, Core::Id lang, const QString &target,
+static ToolChain *findToolChain(Utils::FilePath &compilerPath, Core::Id lang, const QString &target,
CToolChainList &alreadyKnown)
{
ToolChain * tc = Utils::findOrDefault(alreadyKnown, [target, compilerPath, lang](ToolChain *tc) {
@@ -92,12 +92,11 @@ void AndroidToolChain::addToEnvironment(Environment &env) const
{
env.set(QLatin1String("ANDROID_NDK_HOST"),
AndroidConfigurations::currentConfig().toolchainHost());
- const Utils::FileName javaHome = AndroidConfigurations::currentConfig().openJDKLocation();
- if (!javaHome.isEmpty() && javaHome.toFileInfo().exists()) {
+ const Utils::FilePath javaHome = AndroidConfigurations::currentConfig().openJDKLocation();
+ if (!javaHome.exists()) {
env.set(QLatin1String("JAVA_HOME"), javaHome.toString());
- Utils::FileName javaBin = javaHome;
- javaBin.appendPath(QLatin1String("bin"));
- if (!Utils::contains(env.path(), [&javaBin](const Utils::FileName &p) { return p == javaBin; }))
+ const FilePath javaBin = javaHome.pathAppended("bin");
+ if (!Utils::contains(env.path(), [&javaBin](const Utils::FilePath &p) { return p == javaBin; }))
env.prependOrSetPath(javaBin.toUserOutput());
}
env.set(QLatin1String("ANDROID_HOME"),
@@ -106,13 +105,13 @@ void AndroidToolChain::addToEnvironment(Environment &env) const
AndroidConfigurations::currentConfig().sdkLocation().toString());
}
-FileName AndroidToolChain::suggestedDebugger() const
+FilePath AndroidToolChain::suggestedDebugger() const
{
// TODO: Make use of LLDB if available.
return AndroidConfigurations::currentConfig().gdbPath(targetAbi());
}
-FileName AndroidToolChain::suggestedGdbServer() const
+FilePath AndroidToolChain::suggestedGdbServer() const
{
return AndroidConfigurations::currentConfig().gdbServer(targetAbi());
}
@@ -124,17 +123,16 @@ bool AndroidToolChain::fromMap(const QVariantMap &data)
return isValid();
}
-FileNameList AndroidToolChain::suggestedMkspecList() const
+QStringList AndroidToolChain::suggestedMkspecList() const
{
- return FileNameList() << FileName::fromLatin1("android-g++")
- << FileName::fromLatin1("android-clang");
+ return {"android-g++", "android-clang"};
}
-QString AndroidToolChain::makeCommand(const Environment &env) const
+FilePath AndroidToolChain::makeCommand(const Environment &env) const
{
Q_UNUSED(env);
- FileName makePath = AndroidConfigurations::currentConfig().makePath();
- return makePath.exists() ? makePath.toString() : "make";
+ FilePath makePath = AndroidConfigurations::currentConfig().makePath();
+ return makePath.exists() ? makePath : FilePath::fromString("make");
}
GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
@@ -154,11 +152,9 @@ GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
AndroidToolChainFactory::AndroidToolChainFactory()
{
setDisplayName(tr("Android Clang"));
-}
-
-QSet<Core::Id> Android::Internal::AndroidToolChainFactory::supportedLanguages() const
-{
- return {ProjectExplorer::Constants::CXX_LANGUAGE_ID};
+ setSupportedToolChainType(Constants::ANDROID_TOOLCHAIN_ID);
+ setSupportedLanguages({ProjectExplorer::Constants::CXX_LANGUAGE_ID});
+ setToolchainConstructor([] { return new AndroidToolChain; });
}
ToolChainList AndroidToolChainFactory::autoDetect(CToolChainList &alreadyKnown)
@@ -166,24 +162,9 @@ ToolChainList AndroidToolChainFactory::autoDetect(CToolChainList &alreadyKnown)
return autodetectToolChainsForNdk(alreadyKnown);
}
-bool AndroidToolChainFactory::canRestore(const QVariantMap &data)
+static FilePath clangPlusPlusPath(const FilePath &clangPath)
{
- return typeIdFromMap(data) == Constants::ANDROID_TOOLCHAIN_ID;
-}
-
-ToolChain *AndroidToolChainFactory::restore(const QVariantMap &data)
-{
- auto tc = new AndroidToolChain();
- if (tc->fromMap(data))
- return tc;
-
- delete tc;
- return nullptr;
-}
-
-static FileName clangPlusPlusPath(const FileName &clangPath)
-{
- return clangPath.parentDir().appendPath(
+ return clangPath.parentDir().pathAppended(
HostOsInfo::withExecutableSuffix(
QFileInfo(clangPath.toString()).baseName() + "++"));
}
@@ -191,7 +172,7 @@ static FileName clangPlusPlusPath(const FileName &clangPath)
ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(CToolChainList &alreadyKnown)
{
QList<ToolChain *> result;
- FileName clangPath = AndroidConfigurations::currentConfig().clangPath();
+ FilePath clangPath = AndroidConfigurations::currentConfig().clangPath();
if (!clangPath.exists()) {
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"<< clangPath;
return result;
@@ -201,7 +182,7 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(CToolChainList
<< AndroidConfigurations::currentConfig().ndkLocation();
for (const Core::Id &lang : LanguageIds) {
- FileName compilerCommand = clangPath;
+ FilePath compilerCommand = clangPath;
if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
compilerCommand = clangPlusPlusPath(clangPath);
@@ -214,12 +195,22 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(CToolChainList
auto targetItr = ClangTargets.constBegin();
while (targetItr != ClangTargets.constEnd()) {
const Abi &abi = targetItr.value();
- ToolChain *tc = findToolChain(compilerCommand, lang, targetItr.key(), alreadyKnown);
+ const QString target = targetItr.key();
+ ToolChain *tc = findToolChain(compilerCommand, lang, target, alreadyKnown);
if (tc) {
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
} else {
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
- auto atc = new AndroidToolChain(targetItr.key(), lang);
+ auto atc = new AndroidToolChain;
+ atc->setOriginalTargetTriple(target);
+ atc->setLanguage(lang);
+ atc->setTargetAbi(ClangTargets[target]);
+ atc->setPlatformCodeGenFlags({"-target", target});
+ atc->setPlatformLinkerFlags({"-target", target});
+ atc->setDetection(ToolChain::AutoDetection);
+ atc->setDisplayName(QString("Android Clang (%1, %2)")
+ .arg(ToolChainManager::displayNameOfLanguageId(lang),
+ AndroidConfig::displayName(abi)));
atc->resetToolChain(compilerCommand);
tc = atc;
}
@@ -233,23 +224,10 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(CToolChainList
// for fromMap
AndroidToolChain::AndroidToolChain()
- : ClangToolChain(Constants::ANDROID_TOOLCHAIN_ID, ToolChain::ManualDetection)
+ : ClangToolChain(Constants::ANDROID_TOOLCHAIN_ID)
{
}
-AndroidToolChain::AndroidToolChain(const QString& target, Core::Id languageId)
- : ClangToolChain(Constants::ANDROID_TOOLCHAIN_ID, ToolChain::AutoDetection)
-{
- setOriginalTargetTriple(target);
- setLanguage(languageId);
- setTargetAbi(ClangTargets[target]);
- setPlatformCodeGenFlags({"-target", target});
- setPlatformLinkerFlags({"-target", target});
- setDisplayName(QString::fromLatin1("Android Clang (%1, %2)")
- .arg(ToolChainManager::displayNameOfLanguageId(languageId),
- AndroidConfig::displayName(targetAbi())));
-}
-
} // namespace Internal
} // namespace Android
diff --git a/src/plugins/android/androidtoolchain.h b/src/plugins/android/androidtoolchain.h
index b8dbe4c6c2..1665f49b6a 100644
--- a/src/plugins/android/androidtoolchain.h
+++ b/src/plugins/android/androidtoolchain.h
@@ -42,10 +42,10 @@ public:
bool isValid() const override;
void addToEnvironment(Utils::Environment &env) const override;
- Utils::FileName suggestedDebugger() const override;
- Utils::FileName suggestedGdbServer() const;
- Utils::FileNameList suggestedMkspecList() const override;
- QString makeCommand(const Utils::Environment &environment) const override;
+ Utils::FilePath suggestedDebugger() const override;
+ Utils::FilePath suggestedGdbServer() const;
+ QStringList suggestedMkspecList() const override;
+ Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
bool fromMap(const QVariantMap &data) override;
protected:
@@ -53,7 +53,6 @@ protected:
private:
explicit AndroidToolChain();
- AndroidToolChain(const QString &target, Core::Id languageId);
friend class AndroidToolChainFactory;
};
@@ -64,17 +63,14 @@ class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory
public:
AndroidToolChainFactory();
- QSet<Core::Id> supportedLanguages() const override;
ToolChainList autoDetect(CToolChainList &alreadyKnown) override;
- bool canRestore(const QVariantMap &data) override;
- ProjectExplorer::ToolChain *restore(const QVariantMap &data) override;
class AndroidToolChainInformation
{
public:
Core::Id language;
- Utils::FileName compilerCommand;
+ Utils::FilePath compilerCommand;
ProjectExplorer::Abi abi;
QString version;
};
diff --git a/src/plugins/android/androidtoolmanager.cpp b/src/plugins/android/androidtoolmanager.cpp
index b547145772..be26329f98 100644
--- a/src/plugins/android/androidtoolmanager.cpp
+++ b/src/plugins/android/androidtoolmanager.cpp
@@ -46,7 +46,7 @@ using namespace Utils;
class AndroidToolOutputParser
{
public:
- void parseTargetListing(const QString &output, const FileName &sdkLocation,
+ void parseTargetListing(const QString &output, const FilePath &sdkLocation,
SdkPlatformList &platformList);
QList<SdkPlatform> m_installedPlatforms;
@@ -57,7 +57,7 @@ public:
environment. Returns \c true for successful execution. Command's output is copied to \a
output.
*/
-static bool androidToolCommand(Utils::FileName toolPath, const QStringList &args,
+static bool androidToolCommand(Utils::FilePath toolPath, const QStringList &args,
const QProcessEnvironment &environment, QString *output)
{
QString androidToolPath = toolPath.toString();
@@ -143,7 +143,7 @@ QFuture<AndroidDeviceInfoList> AndroidToolManager::androidVirtualDevicesFuture()
AndroidConfigurations::toolsEnvironment(m_config));
}
-CreateAvdInfo AndroidToolManager::createAvdImpl(CreateAvdInfo info, FileName androidToolPath,
+CreateAvdInfo AndroidToolManager::createAvdImpl(CreateAvdInfo info, FilePath androidToolPath,
QProcessEnvironment env)
{
QProcess proc;
@@ -195,8 +195,8 @@ CreateAvdInfo AndroidToolManager::createAvdImpl(CreateAvdInfo info, FileName and
return info;
}
-AndroidDeviceInfoList AndroidToolManager::androidVirtualDevices(const Utils::FileName &androidTool,
- const FileName &sdkLocationPath,
+AndroidDeviceInfoList AndroidToolManager::androidVirtualDevices(const Utils::FilePath &androidTool,
+ const FilePath &sdkLocationPath,
const QProcessEnvironment &env)
{
AndroidDeviceInfoList devices;
@@ -244,9 +244,8 @@ AndroidDeviceInfoList AndroidToolManager::androidVirtualDevices(const Utils::Fil
if (lastIndex == -1) // skip line
break;
QString tmp = line.mid(lastIndex).remove(QLatin1Char(')')).trimmed();
- Utils::FileName platformPath = sdkLocationPath;
- platformPath.appendPath(QString("/platforms/android-%1").arg(tmp));
- dev.sdk = AndroidManager::findApiLevel(platformPath);
+ dev.sdk = AndroidManager::findApiLevel(
+ sdkLocationPath.pathAppended(QString("/platforms/android-%1").arg(tmp)));
}
if (line.contains(QLatin1String("Tag/ABI:"))) {
int lastIndex = line.lastIndexOf(QLatin1Char('/')) + 1;
@@ -275,7 +274,7 @@ AndroidDeviceInfoList AndroidToolManager::androidVirtualDevices(const Utils::Fil
}
void AndroidToolOutputParser::parseTargetListing(const QString &output,
- const Utils::FileName &sdkLocation,
+ const Utils::FilePath &sdkLocation,
SdkPlatformList &platformList)
{
auto addSystemImage = [](const QStringList& abiList, SdkPlatform *platform) {
@@ -292,7 +291,7 @@ void AndroidToolOutputParser::parseTargetListing(const QString &output,
QVersionNumber revision;
int apiLevel = -1;
QString description;
- Utils::FileName installedLocation;
+ Utils::FilePath installedLocation;
void clear() {
abiList.clear();
@@ -312,10 +311,8 @@ void AndroidToolOutputParser::parseTargetListing(const QString &output,
continue;
QString androidTarget = line.mid(index + 1, line.length() - index - 2);
const QString tmp = androidTarget.mid(androidTarget.lastIndexOf(QLatin1Char('-')) + 1);
- Utils::FileName platformPath = sdkLocation;
- platformPath.appendPath(QString("/platforms/android-%1").arg(tmp));
- platformParams.installedLocation = platformPath;
- platformParams.apiLevel = AndroidManager::findApiLevel(platformPath);
+ platformParams.installedLocation = sdkLocation.pathAppended(QString("/platforms/android-%1").arg(tmp));
+ platformParams.apiLevel = AndroidManager::findApiLevel(platformParams.installedLocation);
} else if (line.startsWith(QLatin1String("Name:"))) {
platformParams.description = line.mid(6);
} else if (line.startsWith(QLatin1String("Revision:"))) {
diff --git a/src/plugins/android/androidtoolmanager.h b/src/plugins/android/androidtoolmanager.h
index 76cff1881e..61db46cee2 100644
--- a/src/plugins/android/androidtoolmanager.h
+++ b/src/plugins/android/androidtoolmanager.h
@@ -58,10 +58,10 @@ public:
// Helper methods
private:
- static CreateAvdInfo createAvdImpl(CreateAvdInfo info, Utils::FileName androidToolPath,
+ static CreateAvdInfo createAvdImpl(CreateAvdInfo info, Utils::FilePath androidToolPath,
QProcessEnvironment env);
- static AndroidDeviceInfoList androidVirtualDevices(const Utils::FileName &androidTool,
- const Utils::FileName &sdkLlocationPath,
+ static AndroidDeviceInfoList androidVirtualDevices(const Utils::FilePath &androidTool,
+ const Utils::FilePath &sdkLlocationPath,
const QProcessEnvironment &env);
private:
const AndroidConfig &m_config;
diff --git a/src/plugins/android/avddialog.cpp b/src/plugins/android/avddialog.cpp
index 7097f5c1c6..c0f692734c 100644
--- a/src/plugins/android/avddialog.cpp
+++ b/src/plugins/android/avddialog.cpp
@@ -51,8 +51,8 @@ AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStri
m_hideTipTimer.setSingleShot(true);
if (targetArch.isEmpty()) {
- m_avdDialog.abiComboBox->addItems(QStringList({"armeabi-v7a", "armeabi", "x86", "mips",
- "arm64-v8a", "x86_64", "mips64"}));
+ m_avdDialog.abiComboBox->addItems(QStringList({"armeabi-v7a", "armeabi", "x86",
+ "arm64-v8a", "x86_64"}));
} else {
m_avdDialog.abiComboBox->addItems(QStringList(targetArch));
}
@@ -66,7 +66,7 @@ AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStri
updateApiLevelComboBox();
connect(m_avdDialog.abiComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AvdDialog::updateApiLevelComboBox);
connect(&m_hideTipTimer, &QTimer::timeout,
diff --git a/src/plugins/android/createandroidmanifestwizard.cpp b/src/plugins/android/createandroidmanifestwizard.cpp
index 079fd5bd64..ca386fa907 100644
--- a/src/plugins/android/createandroidmanifestwizard.cpp
+++ b/src/plugins/android/createandroidmanifestwizard.cpp
@@ -86,8 +86,7 @@ ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard)
currentBuildTarget = rc->buildKey();
m_comboBox = new QComboBox(this);
- const BuildTargetInfoList buildTargets = wizard->target()->applicationTargets();
- for (const BuildTargetInfo &bti : buildTargets.list) {
+ for (const BuildTargetInfo &bti : wizard->target()->applicationTargets()) {
const QString displayName = bti.buildKey;
m_comboBox->addItem(displayName, QVariant(bti.buildKey)); // TODO something more?
if (bti.buildKey == currentBuildTarget)
@@ -95,7 +94,7 @@ ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard)
}
nodeSelected(m_comboBox->currentIndex());
- connect(m_comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ChooseProFilePage::nodeSelected);
fl->addRow(tr(".pro file:"), m_comboBox);
@@ -157,7 +156,7 @@ ChooseDirectoryPage::ChooseDirectoryPage(CreateAndroidManifestWizard *wizard)
void ChooseDirectoryPage::checkPackageSourceDir()
{
const QString buildKey = m_wizard->buildKey();
- const BuildTargetInfo bti = m_wizard->target()->applicationTargets().buildTargetInfo(buildKey);
+ const BuildTargetInfo bti = m_wizard->target()->buildTarget(buildKey);
const QString projectDir = bti.projectFilePath.toFileInfo().absolutePath();
const QString newDir = m_androidPackageSourceDir->path();
@@ -181,7 +180,7 @@ void ChooseDirectoryPage::initializePage()
{
const Target *target = m_wizard->target();
const QString buildKey = m_wizard->buildKey();
- const BuildTargetInfo bti = target->applicationTargets().buildTargetInfo(buildKey);
+ const BuildTargetInfo bti = target->buildTarget(buildKey);
const QString projectDir = bti.projectFilePath.toFileInfo().absolutePath();
QString androidPackageDir;
@@ -214,15 +213,15 @@ CreateAndroidManifestWizard::CreateAndroidManifestWizard(ProjectExplorer::Target
{
setWindowTitle(tr("Create Android Template Files Wizard"));
- const BuildTargetInfoList buildTargets = target->applicationTargets();
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
+ const QList<BuildTargetInfo> buildTargets = target->applicationTargets();
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit());
m_copyGradle = version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0);
- if (buildTargets.list.isEmpty()) {
+ if (buildTargets.isEmpty()) {
// oh uhm can't create anything
addPage(new NoApplicationProFilePage(this));
- } else if (buildTargets.list.size() == 1) {
- setBuildKey(buildTargets.list.first().buildKey);
+ } else if (buildTargets.size() == 1) {
+ setBuildKey(buildTargets.first().buildKey);
addPage(new ChooseDirectoryPage(this));
} else {
addPage(new ChooseProFilePage(this));
@@ -319,28 +318,28 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles()
return;
QStringList addedFiles;
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(m_target->kit());
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(m_target->kit());
if (!version)
return;
if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
const QString src(version->qmakeProperty("QT_INSTALL_PREFIX")
.append(QLatin1String("/src/android/java/AndroidManifest.xml")));
- FileUtils::copyRecursively(FileName::fromString(src),
- FileName::fromString(m_directory + QLatin1String("/AndroidManifest.xml")),
+ FileUtils::copyRecursively(FilePath::fromString(src),
+ FilePath::fromString(m_directory + QLatin1String("/AndroidManifest.xml")),
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);});
} else {
const QString src(version->qmakeProperty("QT_INSTALL_PREFIX")
.append(QLatin1String("/src/android/templates")));
- FileUtils::copyRecursively(FileName::fromString(src),
- FileName::fromString(m_directory),
+ FileUtils::copyRecursively(FilePath::fromString(src),
+ FilePath::fromString(m_directory),
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);});
if (m_copyGradle) {
- FileName gradlePath = FileName::fromString(version->qmakeProperty("QT_INSTALL_PREFIX").append(QLatin1String("/src/3rdparty/gradle")));
+ FilePath gradlePath = FilePath::fromString(version->qmakeProperty("QT_INSTALL_PREFIX").append(QLatin1String("/src/3rdparty/gradle")));
if (!gradlePath.exists())
- gradlePath = AndroidConfigurations::currentConfig().sdkLocation().appendPath(QLatin1String("/tools/templates/gradle/wrapper"));
- FileUtils::copyRecursively(gradlePath, FileName::fromString(m_directory),
+ gradlePath = AndroidConfigurations::currentConfig().sdkLocation().pathAppended("/tools/templates/gradle/wrapper");
+ FileUtils::copyRecursively(gradlePath, FilePath::fromString(m_directory),
nullptr, [this, &addedFiles](QFileInfo src, QFileInfo dst, QString *){return copy(src, dst, &addedFiles);});
}
@@ -357,7 +356,7 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles()
if (androidPackageDir.isEmpty()) {
// and now time for some magic
- const BuildTargetInfo bti = m_target->applicationTargets().buildTargetInfo(m_buildKey);
+ const BuildTargetInfo bti = m_target->buildTarget(m_buildKey);
const QString value = "$$PWD/" + bti.projectFilePath.toFileInfo().absoluteDir().relativeFilePath(m_directory);
bool result = node->setData(Android::Constants::AndroidPackageSourceDir, value);
diff --git a/src/plugins/android/javaparser.cpp b/src/plugins/android/javaparser.cpp
index 0e89ba00ea..d6c0a8d254 100644
--- a/src/plugins/android/javaparser.cpp
+++ b/src/plugins/android/javaparser.cpp
@@ -53,12 +53,12 @@ void JavaParser::setProjectFileList(const QStringList &fileList)
m_fileList = fileList;
}
-void JavaParser::setBuildDirectory(const Utils::FileName &buildDirectory)
+void JavaParser::setBuildDirectory(const Utils::FilePath &buildDirectory)
{
m_buildDirectory = buildDirectory;
}
-void JavaParser::setSourceDirectory(const Utils::FileName &sourceDirectory)
+void JavaParser::setSourceDirectory(const Utils::FilePath &sourceDirectory)
{
m_sourceDirectory = sourceDirectory;
}
@@ -70,17 +70,16 @@ void JavaParser::parse(const QString &line)
int lineno = m_javaRegExp.cap(3).toInt(&ok);
if (!ok)
lineno = -1;
- Utils::FileName file = Utils::FileName::fromUserInput(m_javaRegExp.cap(2));
+ Utils::FilePath file = Utils::FilePath::fromUserInput(m_javaRegExp.cap(2));
if (file.isChildOf(m_buildDirectory)) {
- Utils::FileName relativePath = file.relativeChildPath(m_buildDirectory);
- file = m_sourceDirectory;
- file.appendPath(relativePath.toString());
+ Utils::FilePath relativePath = file.relativeChildPath(m_buildDirectory);
+ file = m_sourceDirectory.pathAppended(relativePath.toString());
}
if (file.toFileInfo().isRelative()) {
for (int i = 0; i < m_fileList.size(); i++)
if (m_fileList[i].endsWith(file.toString())) {
- file = Utils::FileName::fromString(m_fileList[i]);
+ file = Utils::FilePath::fromString(m_fileList[i]);
break;
}
}
diff --git a/src/plugins/android/javaparser.h b/src/plugins/android/javaparser.h
index 5199f1057a..ee9a53df1f 100644
--- a/src/plugins/android/javaparser.h
+++ b/src/plugins/android/javaparser.h
@@ -43,16 +43,16 @@ public:
void stdError(const QString &line) override;
void setProjectFileList(const QStringList &fileList);
- void setBuildDirectory(const Utils::FileName &buildDirectory);
- void setSourceDirectory(const Utils::FileName &sourceDirectory);
+ void setBuildDirectory(const Utils::FilePath &buildDirectory);
+ void setSourceDirectory(const Utils::FilePath &sourceDirectory);
private:
void parse(const QString &line);
QRegExp m_javaRegExp;
QStringList m_fileList;
- Utils::FileName m_sourceDirectory;
- Utils::FileName m_buildDirectory;
+ Utils::FilePath m_sourceDirectory;
+ Utils::FilePath m_buildDirectory;
};
} // namespace Internal
diff --git a/src/plugins/autotest/CMakeLists.txt b/src/plugins/autotest/CMakeLists.txt
new file mode 100644
index 0000000000..a5291ce315
--- /dev/null
+++ b/src/plugins/autotest/CMakeLists.txt
@@ -0,0 +1,80 @@
+if (WITH_TESTS)
+ set(TEST_COMPONENT QmakeProjectManager QtSupport)
+endif()
+
+add_qtc_plugin(AutoTest
+ PLUGIN_DEPENDS Core CppTools Debugger ProjectExplorer QmlJSTools TextEditor ${TEST_COMPONENT}
+ SOURCES
+ autotest.qrc
+ autotest_global.h
+ autotestconstants.h
+ autotesticons.h
+ autotestplugin.cpp autotestplugin.h
+ autotestunittests.qrc
+ boost/boostcodeparser.cpp boost/boostcodeparser.h
+ boost/boosttestconfiguration.cpp boost/boosttestconfiguration.h
+ boost/boosttestconstants.h
+ boost/boosttestframework.cpp boost/boosttestframework.h
+ boost/boosttestoutputreader.cpp boost/boosttestoutputreader.h
+ boost/boosttestparser.cpp boost/boosttestparser.h
+ boost/boosttestresult.cpp boost/boosttestresult.h
+ boost/boosttestsettings.cpp boost/boosttestsettings.h
+ boost/boosttestsettingspage.cpp boost/boosttestsettingspage.h boost/boosttestsettingspage.ui
+ boost/boosttesttreeitem.cpp boost/boosttesttreeitem.h
+ gtest/gtest_utils.cpp gtest/gtest_utils.h
+ gtest/gtestconfiguration.cpp gtest/gtestconfiguration.h
+ gtest/gtestconstants.h
+ gtest/gtestframework.cpp gtest/gtestframework.h
+ gtest/gtestoutputreader.cpp gtest/gtestoutputreader.h
+ gtest/gtestparser.cpp gtest/gtestparser.h
+ gtest/gtestresult.cpp gtest/gtestresult.h
+ gtest/gtestsettings.cpp gtest/gtestsettings.h
+ gtest/gtestsettingspage.cpp gtest/gtestsettingspage.h gtest/gtestsettingspage.ui
+ gtest/gtesttreeitem.cpp gtest/gtesttreeitem.h
+ gtest/gtestvisitors.cpp gtest/gtestvisitors.h
+ iframeworksettings.h
+ itestframework.h
+ itestparser.cpp itestparser.h
+ itestsettingspage.h
+ qtest/qttest_utils.cpp qtest/qttest_utils.h
+ qtest/qttestconfiguration.cpp qtest/qttestconfiguration.h
+ qtest/qttestconstants.h
+ qtest/qttestframework.cpp qtest/qttestframework.h
+ qtest/qttestoutputreader.cpp qtest/qttestoutputreader.h
+ qtest/qttestparser.cpp qtest/qttestparser.h
+ qtest/qttestresult.cpp qtest/qttestresult.h
+ qtest/qttestsettings.cpp qtest/qttestsettings.h
+ qtest/qttestsettingspage.cpp qtest/qttestsettingspage.h qtest/qttestsettingspage.ui
+ qtest/qttesttreeitem.cpp qtest/qttesttreeitem.h
+ qtest/qttestvisitors.cpp qtest/qttestvisitors.h
+ quick/quicktest_utils.cpp quick/quicktest_utils.h
+ quick/quicktestconfiguration.cpp quick/quicktestconfiguration.h
+ quick/quicktestframework.cpp quick/quicktestframework.h
+ quick/quicktestparser.cpp quick/quicktestparser.h
+ quick/quicktesttreeitem.cpp quick/quicktesttreeitem.h
+ quick/quicktestvisitors.cpp quick/quicktestvisitors.h
+ testcodeparser.cpp testcodeparser.h
+ testconfiguration.cpp testconfiguration.h
+ testeditormark.cpp testeditormark.h
+ testframeworkmanager.cpp testframeworkmanager.h
+ testnavigationwidget.cpp testnavigationwidget.h
+ testoutputreader.cpp testoutputreader.h
+ testresult.cpp testresult.h
+ testresultdelegate.cpp testresultdelegate.h
+ testresultmodel.cpp testresultmodel.h
+ testresultspane.cpp testresultspane.h
+ testrunconfiguration.h
+ testrunner.cpp testrunner.h
+ testsettings.cpp testsettings.h
+ testsettingspage.cpp testsettingspage.h testsettingspage.ui
+ testtreeitem.cpp testtreeitem.h
+ testtreeitemdelegate.cpp testtreeitemdelegate.h
+ testtreemodel.cpp testtreemodel.h
+ testtreeview.cpp testtreeview.h
+ EXPLICIT_MOC boost/boosttestsettingspage.h
+)
+
+extend_qtc_plugin(AutoTest
+ CONDITION WITH_TESTS
+ SOURCES autotestunittests.cpp autotestunittests.h
+)
diff --git a/src/plugins/autotest/autotest.pro b/src/plugins/autotest/autotest.pro
index d8af2b75c7..22e2b594c9 100644
--- a/src/plugins/autotest/autotest.pro
+++ b/src/plugins/autotest/autotest.pro
@@ -49,6 +49,15 @@ SOURCES += \
quick/quicktestvisitors.cpp \
quick/quicktestframework.cpp \
quick/quicktest_utils.cpp \
+ boost/boostcodeparser.cpp \
+ boost/boosttestframework.cpp \
+ boost/boosttesttreeitem.cpp \
+ boost/boosttestparser.cpp \
+ boost/boosttestconfiguration.cpp \
+ boost/boosttestoutputreader.cpp \
+ boost/boosttestresult.cpp \
+ boost/boosttestsettings.cpp \
+ boost/boosttestsettingspage.cpp \
testframeworkmanager.cpp \
testeditormark.cpp
@@ -104,6 +113,16 @@ HEADERS += \
quick/quicktest_utils.h \
quick/quicktestvisitors.h \
quick/quicktestframework.h \
+ boost/boostcodeparser.h \
+ boost/boosttestframework.h \
+ boost/boosttestconstants.h \
+ boost/boosttesttreeitem.h \
+ boost/boosttestparser.h \
+ boost/boosttestconfiguration.h \
+ boost/boosttestoutputreader.h \
+ boost/boosttestresult.h \
+ boost/boosttestsettingspage.h \
+ boost/boosttestsettings.h \
testframeworkmanager.h \
testrunconfiguration.h \
itestsettingspage.h \
@@ -114,6 +133,7 @@ RESOURCES += \
FORMS += \
testsettingspage.ui \
+ boost/boosttestsettingspage.ui \
qtest/qttestsettingspage.ui \
gtest/gtestsettingspage.ui
diff --git a/src/plugins/autotest/autotest.qbs b/src/plugins/autotest/autotest.qbs
index b25a27ce9c..9d31d53646 100644
--- a/src/plugins/autotest/autotest.qbs
+++ b/src/plugins/autotest/autotest.qbs
@@ -102,6 +102,13 @@ QtcPlugin {
}
Group {
+ name: "Boost Test framework files"
+ files: [
+ "boost/*"
+ ]
+ }
+
+ Group {
name: "Test sources"
condition: qtc.testsEnabled
files: [
diff --git a/src/plugins/autotest/autotest.qrc b/src/plugins/autotest/autotest.qrc
index 0c3a24d7ac..51d19022da 100644
--- a/src/plugins/autotest/autotest.qrc
+++ b/src/plugins/autotest/autotest.qrc
@@ -2,8 +2,6 @@
<qresource prefix="/autotest">
<file>images/settingscategory_autotest.png</file>
<file>images/settingscategory_autotest@2x.png</file>
- <file>images/sort.png</file>
- <file>images/sort@2x.png</file>
<file>images/leafsort.png</file>
<file>images/leafsort@2x.png</file>
<file>images/benchmark.png</file>
@@ -13,11 +11,14 @@
<file>images/runselected_tickmarks.png</file>
<file>images/runselected_tickmarks@2x.png</file>
<file>images/data.png</file>
+ <file>images/data@2x.png</file>
<file>images/text.png</file>
<file>images/text@2x.png</file>
<file>images/visual.png</file>
<file>images/visual@2x.png</file>
<file>images/run_file.png</file>
<file>images/run_file@2x.png</file>
+ <file>images/suite.png</file>
+ <file>images/suite@2x.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h
index 83bffffeb0..c8bfb63bbf 100644
--- a/src/plugins/autotest/autotesticons.h
+++ b/src/plugins/autotest/autotesticons.h
@@ -30,8 +30,6 @@
namespace Autotest {
namespace Icons {
-const Utils::Icon SORT_ALPHABETICALLY({
- {":/autotest/images/sort.png", Utils::Theme::IconsBaseColor}});
const Utils::Icon SORT_NATURALLY({
{":/autotest/images/leafsort.png", Utils::Theme::IconsBaseColor}});
const Utils::Icon RUN_SELECTED_OVERLAY({
diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp
index 9a513bd2d4..5f90f33aca 100644
--- a/src/plugins/autotest/autotestplugin.cpp
+++ b/src/plugins/autotest/autotestplugin.cpp
@@ -40,6 +40,7 @@
#include "qtest/qttestframework.h"
#include "quick/quicktestframework.h"
#include "gtest/gtestframework.h"
+#include "boost/boosttestframework.h"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
@@ -176,6 +177,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri
m_frameworkManager->registerTestFramework(new QtTestFramework);
m_frameworkManager->registerTestFramework(new QuickTestFramework);
m_frameworkManager->registerTestFramework(new GTestFramework);
+ m_frameworkManager->registerTestFramework(new BoostTestFramework);
m_frameworkManager->synchronizeSettings(ICore::settings());
m_testSettingPage = new TestSettingsPage(m_settings);
@@ -248,7 +250,7 @@ void AutotestPlugin::onRunFileTriggered()
if (!document)
return;
- const Utils::FileName &fileName = document->filePath();
+ const Utils::FilePath &fileName = document->filePath();
if (fileName.isEmpty())
return;
@@ -349,9 +351,15 @@ void AutotestPlugin::clearChoiceCache()
s_instance->m_runconfigCache.clear();
}
-QList<QObject *> AutotestPlugin::createTestObjects() const
+void AutotestPlugin::popupResultsPane()
{
- QList<QObject *> tests;
+ if (s_instance)
+ s_instance->m_resultsPane->popup(Core::IOutputPane::NoModeSwitch);
+}
+
+QVector<QObject *> AutotestPlugin::createTestObjects() const
+{
+ QVector<QObject *> tests;
#ifdef WITH_TESTS
tests << new AutoTestUnitTests(TestTreeModel::instance());
#endif
diff --git a/src/plugins/autotest/autotestplugin.h b/src/plugins/autotest/autotestplugin.h
index dcbdb5ddde..c846d3e0b0 100644
--- a/src/plugins/autotest/autotestplugin.h
+++ b/src/plugins/autotest/autotestplugin.h
@@ -71,6 +71,7 @@ public:
static void cacheRunConfigChoice(const QString &buildTargetKey, const ChoicePair &choice);
static ChoicePair cachedChoiceFor(const QString &buildTargetKey);
static void clearChoiceCache();
+ static void popupResultsPane();
private:
void initializeMenuEntries();
@@ -78,7 +79,7 @@ private:
void onRunSelectedTriggered();
void onRunFileTriggered();
void onRunUnderCursorTriggered(TestRunMode mode);
- QList<QObject *> createTestObjects() const override;
+ QVector<QObject *> createTestObjects() const override;
const QSharedPointer<TestSettings> m_settings;
TestFrameworkManager *m_frameworkManager = nullptr;
TestSettingsPage *m_testSettingPage = nullptr;
diff --git a/src/plugins/autotest/autotestunittests.cpp b/src/plugins/autotest/autotestunittests.cpp
index 706824566c..614a61a6c2 100644
--- a/src/plugins/autotest/autotestunittests.cpp
+++ b/src/plugins/autotest/autotestunittests.cpp
@@ -39,6 +39,7 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/toolchain.h>
+#include <QFileInfo>
#include <QSignalSpy>
#include <QTest>
@@ -53,9 +54,7 @@ namespace Internal {
AutoTestUnitTests::AutoTestUnitTests(TestTreeModel *model, QObject *parent)
: QObject(parent),
- m_model(model),
- m_tmpDir(nullptr),
- m_isQt4(false)
+ m_model(model)
{
}
@@ -64,16 +63,27 @@ void AutoTestUnitTests::initTestCase()
const QList<Kit *> allKits = KitManager::kits();
if (allKits.count() != 1)
QSKIP("This test requires exactly one kit to be present");
- if (auto qtVersion = QtSupport::QtKitInformation::qtVersion(allKits.first()))
+ if (auto qtVersion = QtSupport::QtKitAspect::qtVersion(allKits.first()))
m_isQt4 = qtVersion->qtVersionString().startsWith('4');
else
QSKIP("Could not figure out which Qt version is used for default kit.");
- const ToolChain * const toolchain = ToolChainKitInformation::toolChain(allKits.first(),
+ const ToolChain * const toolchain = ToolChainKitAspect::toolChain(allKits.first(),
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!toolchain)
QSKIP("This test requires that there is a kit with a toolchain.");
m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(":/unit_test");
+
+ if (!qgetenv("BOOST_INCLUDE_DIR").isEmpty()) {
+ m_checkBoost = true;
+ } else {
+ if (Utils::HostOsInfo::isLinuxHost()
+ && (QFileInfo::exists("/usr/include/boost/version.hpp")
+ || QFileInfo::exists("/usr/local/include/boost/version.hpp"))) {
+ qDebug() << "Found boost at system level - will run boost parser test.";
+ m_checkBoost = true;
+ }
+ }
}
void AutoTestUnitTests::cleanupTestCase()
@@ -218,6 +228,7 @@ void AutoTestUnitTests::testCodeParserGTest()
QCOMPARE(m_model->namedQuickTestsCount(), 0);
QCOMPARE(m_model->unnamedQuickTestsCount(), 0);
QCOMPARE(m_model->dataTagsCount(), 0);
+ QCOMPARE(m_model->boostTestNamesCount(), 0);
}
void AutoTestUnitTests::testCodeParserGTest_data()
@@ -229,5 +240,51 @@ void AutoTestUnitTests::testCodeParserGTest_data()
<< QString(m_tmpDir->path() + "/simple_gt/simple_gt.qbs");
}
+void AutoTestUnitTests::testCodeParserBoostTest()
+{
+ if (!m_checkBoost)
+ QSKIP("This test needs boost - set BOOST_INCLUDE_DIR (or have it installed)");
+
+ QFETCH(QString, projectFilePath);
+ CppTools::Tests::ProjectOpenerAndCloser projectManager;
+ CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
+ QVERIFY(projectInfo.isValid());
+
+ QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished()));
+ QSignalSpy modelUpdateSpy(m_model, SIGNAL(sweepingDone()));
+ QVERIFY(parserSpy.wait(20000));
+ QVERIFY(modelUpdateSpy.wait());
+
+ QCOMPARE(m_model->boostTestNamesCount(), 5);
+
+ QMultiMap<QString, int> expectedSuitesAndTests;
+ expectedSuitesAndTests.insert(QStringLiteral("Master Test Suite"), 2); // decorators w/o suite
+ expectedSuitesAndTests.insert(QStringLiteral("Master Test Suite"), 2); // fixtures
+ expectedSuitesAndTests.insert(QStringLiteral("Master Test Suite"), 3); // functions
+ expectedSuitesAndTests.insert(QStringLiteral("Suite1"), 4);
+ expectedSuitesAndTests.insert(QStringLiteral("SuiteOuter"), 5); // 2 sub suites + 3 tests
+
+ QMultiMap<QString, int> foundNamesAndSets = m_model->boostTestSuitesAndTests();
+ QCOMPARE(expectedSuitesAndTests.size(), foundNamesAndSets.size());
+ for (const QString &name : expectedSuitesAndTests.keys())
+ QCOMPARE(expectedSuitesAndTests.values(name), foundNamesAndSets.values(name));
+
+ // check also that no Qt related tests have been found
+ QCOMPARE(m_model->autoTestsCount(), 0);
+ QCOMPARE(m_model->namedQuickTestsCount(), 0);
+ QCOMPARE(m_model->unnamedQuickTestsCount(), 0);
+ QCOMPARE(m_model->dataTagsCount(), 0);
+ QCOMPARE(m_model->gtestNamesCount(), 0);
+}
+
+void AutoTestUnitTests::testCodeParserBoostTest_data()
+{
+ QTest::addColumn<QString>("projectFilePath");
+ QTest::newRow("simpleBoostTest")
+ << QString(m_tmpDir->path() + "/simple_boost/simple_boost.pro");
+ QTest::newRow("simpleBoostTestQbs")
+ << QString(m_tmpDir->path() + "/simple_boost/simple_boost.qbs");
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/autotestunittests.h b/src/plugins/autotest/autotestunittests.h
index 1d0e0b397b..3b464fc709 100644
--- a/src/plugins/autotest/autotestunittests.h
+++ b/src/plugins/autotest/autotestunittests.h
@@ -51,11 +51,14 @@ private slots:
void testCodeParserSwitchStartup_data();
void testCodeParserGTest();
void testCodeParserGTest_data();
+ void testCodeParserBoostTest();
+ void testCodeParserBoostTest_data();
private:
- TestTreeModel *m_model;
- CppTools::Tests::TemporaryCopiedDir *m_tmpDir;
- bool m_isQt4;
+ TestTreeModel *m_model = nullptr;
+ CppTools::Tests::TemporaryCopiedDir *m_tmpDir = nullptr;
+ bool m_isQt4 = false;
+ bool m_checkBoost = false;
};
} // namespace Internal
diff --git a/src/plugins/autotest/autotestunittests.qrc b/src/plugins/autotest/autotestunittests.qrc
index 68285166cd..13db89f567 100644
--- a/src/plugins/autotest/autotestunittests.qrc
+++ b/src/plugins/autotest/autotestunittests.qrc
@@ -72,5 +72,22 @@
<file>unit_test/mixed_atp/tests/auto/quickauto3/quickauto3.qbs</file>
<file>unit_test/mixed_atp/tests/auto/quickauto3/tst_test1.qml</file>
<file>unit_test/mixed_atp/tests/auto/quickauto3/tst_test2.qml</file>
+ <file>unit_test/simple_boost/simple_boost.pro</file>
+ <file>unit_test/simple_boost/simple_boost.qbs</file>
+ <file>unit_test/simple_boost/src/main.cpp</file>
+ <file>unit_test/simple_boost/src/src.pro</file>
+ <file>unit_test/simple_boost/src/src.qbs</file>
+ <file>unit_test/simple_boost/tests/tests.pro</file>
+ <file>unit_test/simple_boost/tests/tests.qbs</file>
+ <file>unit_test/simple_boost/tests/deco/deco.pro</file>
+ <file>unit_test/simple_boost/tests/deco/deco.qbs</file>
+ <file>unit_test/simple_boost/tests/deco/enab.h</file>
+ <file>unit_test/simple_boost/tests/deco/main.cpp</file>
+ <file>unit_test/simple_boost/tests/fix/fix.cpp</file>
+ <file>unit_test/simple_boost/tests/fix/fix.pro</file>
+ <file>unit_test/simple_boost/tests/fix/fix.qbs</file>
+ <file>unit_test/simple_boost/tests/params/main.cpp</file>
+ <file>unit_test/simple_boost/tests/params/params.pro</file>
+ <file>unit_test/simple_boost/tests/params/params.qbs</file>
</qresource>
</RCC>
diff --git a/src/plugins/autotest/boost/boostcodeparser.cpp b/src/plugins/autotest/boost/boostcodeparser.cpp
new file mode 100644
index 0000000000..79c612285b
--- /dev/null
+++ b/src/plugins/autotest/boost/boostcodeparser.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** 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 "boostcodeparser.h"
+#include "boosttestconstants.h"
+
+#include <cplusplus/Overview.h>
+#include <cplusplus/Token.h>
+#include <utils/qtcassert.h>
+
+namespace Autotest {
+namespace Internal {
+
+using namespace CPlusPlus;
+
+BoostCodeParser::BoostCodeParser(const QByteArray &source, const LanguageFeatures &features,
+ const Document::Ptr &doc, const Snapshot &snapshot)
+ : m_source(source)
+ , m_features(features)
+ , m_doc(doc)
+ , m_snapshot(snapshot)
+ , m_lookupContext(m_doc, m_snapshot)
+{
+ m_typeOfExpression.init(m_doc, m_snapshot);
+}
+
+static BoostTestCodeLocationAndType locationAndTypeFromToken(const Token &tkn,
+ const QByteArray &src,
+ BoostTestTreeItem::TestStates state,
+ const BoostTestInfoList &suitesStates)
+{
+ BoostTestCodeLocationAndType locationAndType;
+ locationAndType.m_name = QString::fromUtf8(src.mid(int(tkn.bytesBegin()), int(tkn.bytes())));
+ locationAndType.m_type = TestTreeItem::TestCase;
+ locationAndType.m_line = tkn.lineno;
+ locationAndType.m_column = 0;
+ locationAndType.m_state = state;
+ if (suitesStates.isEmpty()) {
+ // should we handle renaming of master suite?
+ BoostTestInfo dummy{QString(BoostTest::Constants::BOOST_MASTER_SUITE),
+ BoostTestTreeItem::Enabled, 0};
+ locationAndType.m_suitesState.append(dummy);
+ } else {
+ locationAndType.m_suitesState.append(suitesStates);
+ }
+ return locationAndType;
+}
+
+static Tokens tokensForSource(const QByteArray &source, const LanguageFeatures &features)
+{
+ CPlusPlus::SimpleLexer lexer;
+ lexer.setPreprocessorMode(false); // or true? does not make a difference so far..
+ lexer.setLanguageFeatures(features);
+ return lexer(QString::fromUtf8(source));
+}
+
+BoostTestCodeLocationList BoostCodeParser::findTests()
+{
+ m_tokens = tokensForSource(m_source, m_features);
+ m_currentIndex = 0;
+ for ( ; m_currentIndex < m_tokens.size(); ++m_currentIndex) {
+ const Token &token = m_tokens.at(m_currentIndex);
+
+ if (token.kind() == T_IDENTIFIER)
+ handleIdentifier();
+
+ }
+ return m_testCases;
+}
+
+void BoostCodeParser::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 == "BOOST_AUTO_TEST_SUITE") {
+ handleSuiteBegin(false);
+ } else if (identifier == "BOOST_FIXTURE_TEST_SUITE") {
+ handleSuiteBegin(true);
+ } else if (identifier == "BOOST_AUTO_TEST_SUITE_END") {
+ handleSuiteEnd();
+ } else if (identifier == "BOOST_TEST_CASE") {
+ handleTestCase(TestCaseType::Functions);
+ } else if (identifier == "BOOST_PARAM_TEST_CASE") {
+ handleTestCase(TestCaseType::Parameter);
+ } else if (identifier == "BOOST_AUTO_TEST_CASE") {
+ handleTestCase(TestCaseType::Auto);
+ } else if (identifier == "BOOST_FIXTURE_TEST_CASE") {
+ handleTestCase(TestCaseType::Fixture);
+ } else if (identifier == "BOOST_DATA_TEST_CASE") {
+ handleTestCase(TestCaseType::Data);
+ } else if (identifier == "BOOST_DATA_TEST_CASE_F") {
+ m_currentState.setFlag(BoostTestTreeItem::Fixture);
+ handleTestCase(TestCaseType::Data);
+ } else if (identifier == "BOOST_AUTO_TEST_CASE_TEMPLATE") {
+ m_currentState.setFlag(BoostTestTreeItem::Templated);
+ handleTestCase(TestCaseType::Auto);
+ } else if (identifier == "BOOST_FIXTURE_TEST_CASE_TEMPLATE") {
+ m_currentState.setFlag(BoostTestTreeItem::Fixture);
+ m_currentState.setFlag(BoostTestTreeItem::Templated);
+ handleTestCase(TestCaseType::Auto);
+ } else if (identifier == "BOOST_TEST_DECORATOR") {
+ handleDecorator();
+ }
+}
+
+void BoostCodeParser::handleSuiteBegin(bool isFixture)
+{
+ m_currentSuite.clear();
+ if (!skipCommentsUntil(T_LPAREN))
+ return;
+ if (!skipCommentsUntil(T_IDENTIFIER))
+ return;
+
+ const Token &token = m_tokens.at(m_currentIndex);
+ const QByteArray &identifier = m_source.mid(int(token.bytesBegin()), int(token.bytes()));
+ m_lineNo = token.lineno;
+ m_currentSuite = QString::fromUtf8(identifier);
+ if (!m_suites.isEmpty())
+ m_currentSuite.prepend(m_suites.last().fullName + '/');
+
+ if (isFixture) { // fixture suites have a (fixture) class name as 2nd parameter
+ m_currentState.setFlag(BoostTestTreeItem::Fixture);
+ if (!skipCommentsUntil(T_COMMA))
+ return;
+ if (!skipCommentsUntil(T_IDENTIFIER))
+ return;
+ }
+
+ if (!skipCommentsUntil(T_COMMA)) {
+ if (skipCommentsUntil(T_RPAREN)) {
+ // we have no decorators (or we have them before this macro)
+ m_suites << BoostTestInfo{m_currentSuite, m_currentState, m_lineNo};
+ m_currentState = BoostTestTreeItem::Enabled;
+ }
+ } else {
+ handleDecorators();
+ m_suites << BoostTestInfo{m_currentSuite, m_currentState, m_lineNo};
+ m_currentState = BoostTestTreeItem::Enabled;
+ }
+}
+
+void BoostCodeParser::handleSuiteEnd()
+{
+ if (!skipCommentsUntil(T_LPAREN))
+ return;
+ skipCommentsUntil(T_RPAREN);
+ if (m_suites.isEmpty())
+ return;
+ m_suites.removeLast();
+}
+
+void BoostCodeParser::handleTestCase(TestCaseType testCaseType)
+{
+ if (!skipCommentsUntil(T_LPAREN))
+ return;
+
+ Token token;
+ BoostTestCodeLocationAndType locationAndType;
+
+ switch (testCaseType) {
+ case TestCaseType::Functions: // cannot have decorators passed as parameter
+ case TestCaseType::Parameter:
+ case TestCaseType::Data:
+ if (testCaseType != TestCaseType::Data) {
+ if (!skipCommentsUntil(T_AMPER)) {
+ // content without the leading lparen
+ const QByteArray content = contentUntil(T_RPAREN).mid(1);
+ const QList<QByteArray> parts = content.split(',');
+ if (parts.size() == 0)
+ return;
+ locationAndType = locationAndTypeFromToken(token, m_source, m_currentState, m_suites);
+
+ const QByteArray functionName = parts.first();
+ if (isBoostBindCall(functionName))
+ locationAndType.m_name = QString::fromUtf8(content).append(')');
+ else
+ locationAndType.m_name = QString::fromUtf8(functionName);
+ m_testCases.append(locationAndType);
+ m_currentState = BoostTestTreeItem::Enabled;
+ return;
+ }
+ if (testCaseType == TestCaseType::Parameter)
+ m_currentState |= BoostTestTreeItem::Parameterized;
+ } else if (m_currentState.testFlag(BoostTestTreeItem::Fixture)) {
+ // ignore first parameter (fixture) and first comma
+ if (!skipCommentsUntil(T_IDENTIFIER))
+ return;
+ if (!skipCommentsUntil(T_COMMA))
+ return;
+ }
+ if (!skipCommentsUntil(T_IDENTIFIER))
+ return;
+ token = m_tokens.at(m_currentIndex);
+ locationAndType = locationAndTypeFromToken(token, m_source, m_currentState, m_suites);
+ m_testCases.append(locationAndType);
+ m_currentState = BoostTestTreeItem::Enabled;
+ return;
+
+ case TestCaseType::Auto:
+ case TestCaseType::Fixture:
+ if (!skipCommentsUntil(T_IDENTIFIER))
+ return;
+ token = m_tokens.at(m_currentIndex);
+
+ if (testCaseType == TestCaseType::Fixture) { // skip fixture class parameter
+ m_currentState |= BoostTestTreeItem::Fixture;
+ if (!skipCommentsUntil(T_COMMA))
+ return;
+ if (!skipCommentsUntil(T_IDENTIFIER))
+ return;
+ }
+ break;
+ }
+
+ // check and handle decorators and add the found test case
+ if (!skipCommentsUntil(T_COMMA)) {
+ if (skipCommentsUntil(T_RPAREN)) {
+ locationAndType = locationAndTypeFromToken(token, m_source, m_currentState, m_suites);
+ m_testCases.append(locationAndType);
+ m_currentState = BoostTestTreeItem::Enabled;
+ }
+ } else {
+ if (!m_currentState.testFlag(BoostTestTreeItem::Templated))
+ handleDecorators();
+ locationAndType = locationAndTypeFromToken(token, m_source, m_currentState, m_suites);
+ m_testCases.append(locationAndType);
+ m_currentState = BoostTestTreeItem::Enabled;
+ }
+}
+
+void BoostCodeParser::handleDecorator()
+{
+ skipCommentsUntil(T_LPAREN);
+ m_currentState = BoostTestTreeItem::Enabled;
+ handleDecorators();
+}
+
+void BoostCodeParser::handleDecorators()
+{
+ if (!skipCommentsUntil(T_STAR))
+ return;
+ if (!skipCommentsUntil(T_IDENTIFIER))
+ return;
+
+ QByteArray decorator = contentUntil(T_LPAREN);
+ if (decorator.isEmpty())
+ return;
+
+ bool aliasedOrReal;
+ QString symbolName;
+ QByteArray simplifiedName;
+
+ if (!evalCurrentDecorator(decorator, &symbolName, &simplifiedName, &aliasedOrReal))
+ return;
+
+ if (symbolName == "decorator::disabled" || (aliasedOrReal && simplifiedName == "::disabled")) {
+ m_currentState.setFlag(BoostTestTreeItem::Disabled);
+ } else if (symbolName == "decorator::enabled"
+ || (aliasedOrReal && simplifiedName == "::enabled")) {
+ m_currentState.setFlag(BoostTestTreeItem::Disabled, false);
+ m_currentState.setFlag(BoostTestTreeItem::ExplicitlyEnabled);
+ } else if (symbolName == "decorator::enable_if"
+ || (aliasedOrReal && simplifiedName.startsWith("::enable_if<"))) {
+ // figure out the passed template value
+ QByteArray templateType = decorator.mid(decorator.indexOf('<') + 1);
+ templateType.chop(templateType.size() - templateType.indexOf('>'));
+
+ if (templateType == "true") {
+ m_currentState.setFlag(BoostTestTreeItem::Disabled, false);
+ m_currentState.setFlag(BoostTestTreeItem::ExplicitlyEnabled);
+ } else if (templateType == "false") {
+ m_currentState.setFlag(BoostTestTreeItem::Disabled);
+ } else {
+ // FIXME we have a const(expr) bool? currently not easily achievable
+ }
+ } else if (symbolName == "decorator::fixture"
+ || (aliasedOrReal && simplifiedName.startsWith("::fixture"))){
+ m_currentState.setFlag(BoostTestTreeItem::Fixture);
+ }
+ // TODO.. depends_on, label, precondition, timeout,...
+
+ skipCommentsUntil(T_LPAREN);
+ skipCommentsUntil(T_RPAREN);
+
+ handleDecorators(); // check for more decorators
+}
+
+bool BoostCodeParser::skipCommentsUntil(const Kind nextExpectedKind)
+{
+ for (int index = m_currentIndex + 1, end = m_tokens.size(); index < end; ++index) {
+ const Token &token = m_tokens.at(index);
+ if (token.isComment())
+ continue;
+ if (token.kind() != nextExpectedKind)
+ break;
+ m_currentIndex = index;
+ return true;
+ }
+ return false;
+}
+
+QByteArray BoostCodeParser::contentUntil(Kind stopKind)
+{
+ QByteArray result;
+ for (int oldIndex = m_currentIndex, end = m_tokens.size(); oldIndex < end; ++oldIndex) {
+ const Token &token = m_tokens.at(oldIndex);
+ if (token.isComment())
+ continue;
+ if (token.kind() == stopKind)
+ return result;
+ result.append(m_source.mid(int(token.bytesBegin()), int(token.bytes())));
+ }
+ return result;
+}
+
+bool BoostCodeParser::isBoostBindCall(const QByteArray &function)
+{
+ if (!function.contains("bind"))
+ return false;
+ int index = function.indexOf('(');
+ if (index == -1)
+ return false;
+ QByteArray funcCall = function.left(index);
+ const QList<LookupItem> lookupItems = m_typeOfExpression(funcCall, m_doc->globalNamespace());
+ if (lookupItems.isEmpty())
+ return false;
+
+ if (funcCall.contains("::")) {
+ bool aliasedOrReal = false;
+ aliasedOrRealNamespace(funcCall, "boost", nullptr, &aliasedOrReal);
+ return aliasedOrReal;
+ }
+
+ Overview overview;
+ for (const LookupItem &item : lookupItems) {
+ if (Symbol *symbol = item.declaration()) {
+ const QString fullQualified = overview.prettyName(
+ m_lookupContext.fullyQualifiedName(symbol->enclosingNamespace()));
+ if (fullQualified == "boost")
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BoostCodeParser::aliasedOrRealNamespace(const QByteArray &symbolName,
+ const QString &origNamespace,
+ QByteArray *simplifiedName, bool *aliasedOrReal)
+{
+ Overview overview;
+ const QByteArray classOrNamespace = symbolName.left(symbolName.lastIndexOf("::"));
+ const QList<LookupItem> lookup = m_typeOfExpression(classOrNamespace, m_doc->globalNamespace());
+ for (const LookupItem &it : lookup) {
+ if (auto classOrNamespaceSymbol = it.declaration()) {
+ const QString fullQualified = overview.prettyName(
+ m_lookupContext.fullyQualifiedName(classOrNamespaceSymbol));
+ if (fullQualified == origNamespace) {
+ *aliasedOrReal = true;
+ if (simplifiedName)
+ *simplifiedName = symbolName.mid(symbolName.lastIndexOf("::"));
+ return true;
+ }
+ if (auto namespaceAlias = classOrNamespaceSymbol->asNamespaceAlias()) {
+ if (auto aliasName = namespaceAlias->namespaceName()) {
+ if (overview.prettyName(aliasName) == origNamespace) {
+ *aliasedOrReal = true;
+ if (simplifiedName)
+ *simplifiedName = symbolName.mid(symbolName.lastIndexOf("::"));
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool BoostCodeParser::evalCurrentDecorator(const QByteArray &decorator, QString *symbolName,
+ QByteArray *simplifiedName, bool *aliasedOrReal)
+{
+ const QList<LookupItem> lookupItems = m_typeOfExpression(decorator, m_doc->globalNamespace());
+ if (lookupItems.isEmpty())
+ return false;
+
+ Overview overview;
+ Symbol *symbol = lookupItems.first().declaration();
+ if (!symbol->name())
+ return false;
+
+ *symbolName = overview.prettyName(symbol->name());
+ *aliasedOrReal = false;
+ if (decorator.contains("::"))
+ return aliasedOrRealNamespace(decorator, "boost::unit_test", simplifiedName, aliasedOrReal);
+ return true;
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boostcodeparser.h b/src/plugins/autotest/boost/boostcodeparser.h
new file mode 100644
index 0000000000..23fd4b3c03
--- /dev/null
+++ b/src/plugins/autotest/boost/boostcodeparser.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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 "boosttesttreeitem.h"
+
+#include <cplusplus/CppDocument.h>
+#include <cplusplus/LookupContext.h>
+#include <cplusplus/SimpleLexer.h>
+#include <cplusplus/TypeOfExpression.h>
+
+#include <QByteArray>
+
+namespace Autotest {
+namespace Internal {
+
+class BoostCodeParser
+{
+public:
+ BoostCodeParser(const QByteArray &source, const CPlusPlus::LanguageFeatures &features,
+ const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot);
+ virtual ~BoostCodeParser() = default;
+ BoostTestCodeLocationList findTests();
+private:
+ enum class TestCaseType {Auto, Functions, Parameter, Fixture, Data};
+
+ void handleIdentifier();
+ void handleSuiteBegin(bool isFixture);
+ void handleSuiteEnd();
+ void handleTestCase(TestCaseType testCaseType);
+ void handleDecorator();
+ void handleDecorators();
+
+ bool skipCommentsUntil(CPlusPlus::Kind nextExpectedKind); // moves currentIndex if succeeds
+ QByteArray contentUntil(CPlusPlus::Kind stopKind); // does not move currentIndex
+
+ bool isBoostBindCall(const QByteArray &function);
+ bool aliasedOrRealNamespace(const QByteArray &symbolName, const QString &origNamespace,
+ QByteArray *simplifiedName, bool *aliasedOrReal);
+ bool evalCurrentDecorator(const QByteArray &decorator, QString *symbolName,
+ QByteArray *simplifiedName, bool *aliasedOrReal);
+
+ const QByteArray &m_source;
+ const CPlusPlus::LanguageFeatures &m_features;
+ const CPlusPlus::Document::Ptr &m_doc;
+ const CPlusPlus::Snapshot &m_snapshot;
+ CPlusPlus::LookupContext m_lookupContext;
+ CPlusPlus::TypeOfExpression m_typeOfExpression;
+ CPlusPlus::Tokens m_tokens;
+ int m_currentIndex = 0;
+ BoostTestCodeLocationList m_testCases;
+ QVector<BoostTestInfo> m_suites;
+ QString m_currentSuite;
+ BoostTestTreeItem::TestStates m_currentState = BoostTestTreeItem::Enabled;
+ unsigned m_lineNo = 0;
+};
+
+} // Internal
+} // Autotest
diff --git a/src/plugins/autotest/boost/boosttestconfiguration.cpp b/src/plugins/autotest/boost/boosttestconfiguration.cpp
new file mode 100644
index 0000000000..276c83bc6d
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestconfiguration.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** 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 "boosttestconfiguration.h"
+#include "boosttestconstants.h"
+#include "boosttestoutputreader.h"
+#include "boosttestsettings.h"
+
+#include "../autotestplugin.h"
+#include "../testframeworkmanager.h"
+#include "../testsettings.h"
+
+namespace Autotest {
+namespace Internal {
+
+static QSharedPointer<BoostTestSettings> getBoostSettings()
+{
+ const Core::Id id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(
+ BoostTest::Constants::FRAMEWORK_NAME);
+ TestFrameworkManager *manager = TestFrameworkManager::instance();
+ return qSharedPointerCast<BoostTestSettings>(manager->settingsForTestFramework(id));
+}
+
+TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
+ QProcess *app) const
+{
+ auto settings = getBoostSettings();
+ return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(),
+ settings->logLevel, settings->reportLevel);
+}
+
+enum class InterferingType { Options, EnvironmentVariables };
+
+static QStringList interfering(InterferingType type)
+{
+ const QStringList knownInterfering { "log_level", "log_format", "log_sink",
+ "report_level", "report_format", "report_sink",
+ "output_format", "color_output", "no_color_output",
+ "catch_system_errors", "no_catch_system_errors",
+ "detect_fp_exceptions", "no_detect_fp_exceptions",
+ "detect_memory_leaks", "random", "run_test",
+ "show_progress", "result_code", "no_result_code",
+ "help", "list_content", "list_labels", "version"
+ };
+ switch (type) {
+ case InterferingType::Options:
+ return Utils::transform(knownInterfering, [](const QString &item) {
+ return QString("--" + item);
+ });
+ case InterferingType::EnvironmentVariables:
+ return Utils::transform(knownInterfering, [](const QString &item) {
+ return QString("BOOST_TEST_" + item).toUpper();
+ });
+ }
+ return QStringList();
+}
+
+static QStringList filterInterfering(const QStringList &provided, QStringList *omitted)
+{
+ const QStringList knownInterfering = interfering(InterferingType::Options);
+ const QString interferingSingleWithParam = "efklortcpsx?";
+ QStringList allowed;
+ bool filterNextArg = false;
+ bool ignoreRest = false;
+ for (auto arg : provided) {
+ bool filterArg = filterNextArg;
+ filterNextArg = false;
+ if (ignoreRest) {
+ allowed.append(arg);
+ continue;
+ }
+ bool interferes = false;
+ if (filterArg && !arg.startsWith('-')) {
+ interferes = true;
+ } else if (arg.startsWith("--")) {
+ if (arg.size() == 2)
+ ignoreRest = true;
+ else
+ interferes = knownInterfering.contains(arg.left(arg.indexOf('=')));
+ } else if (arg.startsWith('-') && arg.size() > 1) {
+ interferes = interferingSingleWithParam.contains(arg.at(1));
+ filterNextArg = interferes;
+ }
+ if (!interferes)
+ allowed.append(arg);
+ else if (omitted)
+ omitted->append(arg);
+ }
+ return allowed;
+}
+
+QStringList BoostTestConfiguration::argumentsForTestRunner(QStringList *omitted) const
+{
+ auto boostSettings = getBoostSettings();
+ QStringList arguments;
+ arguments << "-l" << BoostTestSettings::logLevelToOption(boostSettings->logLevel);
+ arguments << "-r" << BoostTestSettings::reportLevelToOption(boostSettings->reportLevel);
+ arguments << "--no_color_output"; // ensure that colored output is not used as default
+
+ if (boostSettings->randomize)
+ arguments << QString("--random=").append(QString::number(boostSettings->seed));
+
+ if (boostSettings->systemErrors)
+ arguments << "-s";
+ if (boostSettings->fpExceptions)
+ arguments << "--detect_fp_exceptions";
+ if (!boostSettings->memLeaks)
+ arguments << "--detect_memory_leaks=0";
+
+ // TODO improve the test case gathering and arguments building to avoid too long command lines
+ for (const QString &test : testCases())
+ arguments << "-t" << test;
+
+ if (AutotestPlugin::settings()->processArgs) {
+ arguments << filterInterfering(runnable().commandLineArguments.split(
+ ' ', QString::SkipEmptyParts), omitted);
+ }
+ return arguments;
+}
+
+Utils::Environment BoostTestConfiguration::filteredEnvironment(const Utils::Environment &original) const
+{
+ const QStringList interferingEnv = interfering(InterferingType::EnvironmentVariables);
+
+ Utils::Environment result = original;
+ for (const QString &key : interferingEnv)
+ result.unset(key);
+ return result;
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestconfiguration.h b/src/plugins/autotest/boost/boosttestconfiguration.h
new file mode 100644
index 0000000000..e792fe21d5
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestconfiguration.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** 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 "../testconfiguration.h"
+
+namespace Autotest {
+namespace Internal {
+
+class BoostTestConfiguration : public DebuggableTestConfiguration
+{
+public:
+ BoostTestConfiguration() {}
+ TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
+ QProcess *app) const override;
+ QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
+ Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
+};
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestconstants.h b/src/plugins/autotest/boost/boosttestconstants.h
new file mode 100644
index 0000000000..2c993c1d4f
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestconstants.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** 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 <QtGlobal>
+
+namespace Autotest {
+namespace BoostTest {
+namespace Constants {
+
+const char FRAMEWORK_NAME[] = "Boost";
+const char FRAMEWORK_SETTINGS_CATEGORY[] = QT_TRANSLATE_NOOP("BoostTestFramework", "Boost Test");
+const unsigned FRAMEWORK_PRIORITY = 11;
+const char BOOST_MASTER_SUITE[] = "Master Test Suite";
+
+} // namespace Constants
+} // namespace BoostTest
+} // namespace AutoTest
diff --git a/src/plugins/autotest/boost/boosttestframework.cpp b/src/plugins/autotest/boost/boosttestframework.cpp
new file mode 100644
index 0000000000..a6b7515154
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestframework.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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 "boosttestframework.h"
+#include "boosttestconstants.h"
+#include "boosttestsettings.h"
+#include "boosttestsettingspage.h"
+#include "boosttesttreeitem.h"
+#include "boosttestparser.h"
+#include "../testframeworkmanager.h"
+
+namespace Autotest {
+namespace Internal {
+
+ITestParser *BoostTestFramework::createTestParser() const
+{
+ return new BoostTestParser;
+}
+
+TestTreeItem *BoostTestFramework::createRootNode() const
+{
+ return new BoostTestTreeItem(
+ QCoreApplication::translate("BoostTestFramework",
+ BoostTest::Constants::FRAMEWORK_SETTINGS_CATEGORY),
+ QString(), TestTreeItem::Root);
+}
+
+const char *BoostTestFramework::name() const
+{
+ return BoostTest::Constants::FRAMEWORK_NAME;
+}
+
+unsigned BoostTestFramework::priority() const
+{
+ return BoostTest::Constants::FRAMEWORK_PRIORITY;
+}
+
+IFrameworkSettings *BoostTestFramework::createFrameworkSettings() const
+{
+ return new BoostTestSettings;
+}
+
+ITestSettingsPage *BoostTestFramework::createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const
+{
+ return new BoostTestSettingsPage(settings, this);
+}
+
+bool BoostTestFramework::hasFrameworkSettings() const
+{
+ return true;
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestframework.h b/src/plugins/autotest/boost/boosttestframework.h
new file mode 100644
index 0000000000..c9db343deb
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestframework.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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 "../itestframework.h"
+
+namespace Autotest {
+namespace Internal {
+
+class BoostTestFramework : public ITestFramework
+{
+public:
+ BoostTestFramework() : ITestFramework(true) {}
+ const char *name() const override;
+ unsigned priority() const override;
+ IFrameworkSettings *createFrameworkSettings() const override;
+ ITestSettingsPage *createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const override;
+ bool hasFrameworkSettings() const override;
+protected:
+ ITestParser *createTestParser() const override;
+ TestTreeItem *createRootNode() const override;
+};
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp
new file mode 100644
index 0000000000..3ae5756d3a
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** 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 "boosttestoutputreader.h"
+#include "boosttestsettings.h"
+#include "boosttestresult.h"
+
+#include <utils/qtcassert.h>
+
+#include <QDir>
+#include <QFileInfo>
+#include <QLoggingCategory>
+#include <QRegularExpression>
+
+namespace Autotest {
+namespace Internal {
+
+static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg)
+
+static QString constructSourceFilePath(const QString &path, const QString &filePath)
+{
+ return QFileInfo(path, filePath).canonicalFilePath();
+}
+
+BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
+ QProcess *testApplication,
+ const QString &buildDirectory,
+ const QString &projectFile,
+ LogLevel log, ReportLevel report)
+ : TestOutputReader(futureInterface, testApplication, buildDirectory)
+ , m_projectFile(projectFile)
+ , m_logLevel(log)
+ , m_reportLevel(report)
+{
+ if (m_testApplication) {
+ connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, &BoostTestOutputReader::onFinished);
+ }
+}
+
+// content of "error:..." / "info:..." / ... messages
+static QString caseFromContent(const QString &content)
+{
+ const int length = content.length();
+ if (content.startsWith("last checkpoint:")) {
+ int index = content.indexOf('"');
+ if (index != 17 || length <= 18) {
+ qCDebug(orLog) << "double quote position" << index << " or content length" << length
+ << "wrong on content" << content;
+ return QString();
+ }
+ index = content.indexOf('"', 18);
+ if (index == -1) {
+ qCDebug(orLog) << "no closing double quote" << content;
+ return QString();
+ }
+ return content.mid(18, index - 1);
+ }
+
+ int index = content.indexOf(": in ");
+ if (index == -1) // "info: check true has passed"
+ return QString();
+
+ if (index <= 4 || length < index + 4) {
+ qCDebug(orLog) << "unexpected position" << index << "for info" << content;
+ return QString();
+ }
+
+ QString result = content.mid(index + 5);
+ static QRegularExpression functionName("\"(.+)\":.*");
+ const QRegularExpressionMatch matcher = functionName.match(result);
+ if (!matcher.hasMatch()) {
+ qCDebug(orLog) << "got no match";
+ return QString();
+ }
+ return matcher.captured(1);
+}
+
+void BoostTestOutputReader::sendCompleteInformation()
+{
+ QTC_ASSERT(m_result != ResultType::Invalid, return);
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule);
+ result->setTestSuite(m_currentSuite);
+ result->setTestCase(m_currentTest);
+ if (m_lineNumber) {
+ result->setLine(m_lineNumber);
+ result->setFileName(m_fileName);
+ }
+
+ result->setDescription(m_description);
+ result->setResult(m_result);
+ reportResult(TestResultPtr(result));
+ m_result = ResultType::Invalid;
+}
+
+void BoostTestOutputReader::handleMessageMatch(const QRegularExpressionMatch &match)
+{
+ m_fileName = constructSourceFilePath(m_buildDir, match.captured(1));
+ m_lineNumber = match.captured(2).toInt();
+
+ const QString &content = match.captured(3);
+ if (content.startsWith("info:")) {
+ if (m_currentTest.isEmpty() || m_logLevel > LogLevel::UnitScope) {
+ QString tmp = caseFromContent(content);
+ if (!tmp.isEmpty())
+ m_currentTest = tmp;
+ }
+ m_result = ResultType::Pass;
+ m_description = content;
+ } else if (content.startsWith("error:")) {
+ if (m_currentTest.isEmpty() || m_logLevel > LogLevel::UnitScope)
+ m_currentTest = caseFromContent(content);
+ m_result = ResultType::Fail;
+ if (m_reportLevel == ReportLevel::No)
+ ++m_summary[ResultType::Fail];
+ m_description = content;
+ } else if (content.startsWith("fatal error:")) {
+ if (m_currentTest.isEmpty() || m_logLevel > LogLevel::UnitScope)
+ m_currentTest = caseFromContent(content);
+ m_result = ResultType::MessageFatal;
+ m_description = content;
+ } else if (content.startsWith("last checkpoint:")) {
+ if (m_currentTest.isEmpty() || m_logLevel > LogLevel::UnitScope)
+ m_currentTest = caseFromContent(content);
+ m_result = ResultType::MessageInfo;
+ m_description = content;
+ } else if (content.startsWith("Entering")) {
+ m_result = ResultType::TestStart;
+ const QString type = match.captured(8);
+ if (type == "case") {
+ m_currentTest = match.captured(9);
+ m_description = tr("Executing test case %1").arg(m_currentTest);
+ } else if (type == "suite") {
+ m_currentSuite = match.captured(9);
+ m_description = tr("Executing test suite %1").arg(m_currentSuite);
+ }
+ } else if (content.startsWith("Leaving")) {
+ const QString type = match.captured(10);
+ if (type == "case") {
+ if (m_currentTest != match.captured(11) && m_currentTest.isEmpty())
+ m_currentTest = match.captured(11);
+ m_result = ResultType::TestEnd;
+ m_description = tr("Test execution took %1").arg(match.captured(12));
+ } else if (type == "suite") {
+ if (m_currentSuite != match.captured(11) && m_currentSuite.isEmpty())
+ m_currentSuite = match.captured(11);
+ m_currentTest.clear();
+ m_result = ResultType::TestEnd;
+ m_description = tr("Test suite execution took %1").arg(match.captured(12));
+ }
+ } else if (content.startsWith("Test case ")) {
+ m_currentTest = match.captured(4);
+ m_result = ResultType::Skip;
+ if (m_reportLevel == ReportLevel::Confirm || m_reportLevel == ReportLevel::No)
+ ++m_summary[ResultType::Skip];
+ m_description = content;
+ }
+
+ if (m_result != ResultType::Invalid) // we got a new result
+ sendCompleteInformation();
+}
+
+void BoostTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLine)
+{
+ static QRegularExpression newTestStart("^Running (\\d+) test cases?\\.\\.\\.$");
+ static QRegularExpression dependency("^Including test case (.+) as a dependency of "
+ "test case (.+)$");
+ static QRegularExpression messages("^(.+)\\((\\d+)\\): (info: (.+)|error: (.+)|"
+ "fatal error: (.+)|last checkpoint: (.+)"
+ "|Entering test (case|suite) \"(.+)\""
+ "|Leaving test (case|suite) \"(.+)\"; testing time: (\\d+.+)"
+ "|Test case \"(.+)\" is skipped because .+$)$");
+ static QRegularExpression moduleMssg("^(Entering test module \"(.+)\"|"
+ "Leaving test module \"(.+)\"; testing time: (\\d+.+))$");
+ static QRegularExpression noAssertion("^Test case (.*) did not check any assertions$");
+
+ static QRegularExpression summaryPreamble("^\\s*Test (module|suite|case) \"(.*)\" has "
+ "(failed|passed)( with:)?$");
+ static QRegularExpression summarySkip("^\\s+Test case \"(.*)\" was skipped$");
+ static QRegularExpression summaryDetail("^\\s+(\\d+) test cases? out of (\\d+) "
+ "(failed|passed|skipped)$");
+ static QRegularExpression summaryAssertion("^\\s+(\\d+) assertions? out of (\\d+) "
+ "(failed|passed)$");
+
+ static QRegularExpression finish("^\\*{3} (\\d+) failure(s are| is) detected in the "
+ "test module \"(.*)\"$");
+ static QRegularExpression errDetect("^\\*{3} Errors where detected in the "
+ "test module \"(.*}\"; see standard output for details");
+ QString noErrors("*** No errors detected");
+
+ const QString line = QString::fromUtf8(chopLineBreak(outputLineWithNewLine));
+ if (line.trimmed().isEmpty())
+ return;
+
+ QRegularExpressionMatch match = messages.match(line);
+ if (match.hasMatch()) {
+ handleMessageMatch(match);
+ return;
+ }
+
+ match = dependency.match(line);
+ if (match.hasMatch()) {
+ if (m_result != ResultType::Invalid)
+ sendCompleteInformation();
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule);
+ result->setDescription(match.captured(0));
+ result->setResult(ResultType::MessageInfo);
+ reportResult(TestResultPtr(result));
+ return;
+ }
+
+ match = newTestStart.match(line);
+ if (match.hasMatch()) {
+ if (m_result != ResultType::Invalid)
+ sendCompleteInformation();
+ m_testCaseCount = match.captured(1).toInt();
+ m_description.clear();
+ return;
+ }
+
+ match = moduleMssg.match(line);
+ if (match.hasMatch()) {
+ if (m_result != ResultType::Invalid)
+ sendCompleteInformation();
+ if (match.captured(1).startsWith("Entering")) {
+ m_currentModule = match.captured(2);
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule);
+ result->setDescription(tr("Executing test module %1").arg(m_currentModule));
+ result->setResult(ResultType::TestStart);
+ reportResult(TestResultPtr(result));
+ m_description.clear();
+ } else {
+ QTC_CHECK(m_currentModule == match.captured(3));
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule);
+ result->setDescription(tr("Test module execution took %1").arg(match.captured(4)));
+ result->setResult(ResultType::TestEnd);
+ reportResult(TestResultPtr(result));
+
+ m_currentTest.clear();
+ m_currentSuite.clear();
+ m_currentModule.clear();
+ m_description.clear();
+ }
+ return;
+ }
+
+ match = noAssertion.match(line);
+ if (match.hasMatch()) {
+ if (m_result != ResultType::Invalid)
+ sendCompleteInformation();
+ const QString caseWithOptionalSuite = match.captured(1);
+ int index = caseWithOptionalSuite.lastIndexOf('/');
+ if (index == -1) {
+ QTC_CHECK(caseWithOptionalSuite == m_currentTest);
+ } else {
+ QTC_CHECK(caseWithOptionalSuite.mid(index + 1) == m_currentTest);
+ int sIndex = caseWithOptionalSuite.lastIndexOf('/', index - 1);
+ if (sIndex == -1) {
+ QTC_CHECK(caseWithOptionalSuite.left(index) == m_currentSuite);
+ m_currentSuite = caseWithOptionalSuite.left(index); // FIXME should not be necessary - but we currently do not care for the whole suite path
+ } else {
+ QTC_CHECK(caseWithOptionalSuite.mid(sIndex + 1, index - sIndex - 1) == m_currentSuite);
+ }
+ }
+ createAndReportResult(match.captured(0), ResultType::MessageWarn);
+ return;
+ }
+
+ match = summaryPreamble.match(line);
+ if (match.hasMatch()) {
+ createAndReportResult(match.captured(0), ResultType::MessageInfo);
+ if (m_reportLevel == ReportLevel::Detailed || match.captured(4).isEmpty()) {
+ if (match.captured(1) == "case") {
+ if (match.captured(3) == "passed")
+ ++m_summary[ResultType::Pass];
+ else
+ ++m_summary[ResultType::Fail];
+ }
+ }
+ return;
+ }
+
+ match = summaryDetail.match(line);
+ if (match.hasMatch()) {
+ createAndReportResult(match.captured(0), ResultType::MessageInfo);
+ int report = match.captured(1).toInt();
+ QString type = match.captured(3);
+ if (m_reportLevel != ReportLevel::Detailed) {
+ if (type == "passed")
+ m_summary[ResultType::Pass] += report;
+ else if (type == "failed")
+ m_summary[ResultType::Fail] += report;
+ else if (type == "skipped")
+ m_summary[ResultType::Skip] += report;
+ }
+
+ return;
+ }
+
+ match = summaryAssertion.match(line);
+ if (match.hasMatch()) {
+ createAndReportResult(match.captured(0), ResultType::MessageInfo);
+ return;
+ }
+
+ match = summarySkip.match(line);
+ if (match.hasMatch()) {
+ createAndReportResult(match.captured(0), ResultType::MessageInfo);
+ if (m_reportLevel == ReportLevel::Detailed)
+ ++m_summary[ResultType::Skip];
+ return;
+ }
+
+ match = finish.match(line);
+ if (match.hasMatch()) {
+ if (m_result != ResultType::Invalid)
+ sendCompleteInformation();
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, QString());
+ int failed = match.captured(1).toInt();
+ QString txt = tr("%1 failures detected in %2.").arg(failed).arg(match.captured(3));
+ int passed = (m_testCaseCount != -1)
+ ? m_testCaseCount - failed - m_summary[ResultType::Skip] : -1;
+ if (m_testCaseCount != -1)
+ txt.append(' ').append(tr("%1 tests passed.").arg(passed));
+ result->setDescription(txt);
+ result->setResult(ResultType::MessageInfo);
+ reportResult(TestResultPtr(result));
+ if (m_reportLevel == ReportLevel::Confirm) { // for the final summary
+ m_summary[ResultType::Pass] += passed;
+ m_summary[ResultType::Fail] += failed;
+ }
+ m_testCaseCount = -1;
+ return;
+ }
+
+ if (line == noErrors) {
+ if (m_result != ResultType::Invalid)
+ sendCompleteInformation();
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, QString());
+ QString txt = tr("No errors detected.");
+ if (m_testCaseCount != -1)
+ txt.append(' ').append(tr("%1 tests passed.").arg(m_testCaseCount));
+ result->setDescription(txt);
+ result->setResult(ResultType::MessageInfo);
+ reportResult(TestResultPtr(result));
+ if (m_reportLevel == ReportLevel::Confirm) // for the final summary
+ m_summary.insert(ResultType::Pass, m_testCaseCount);
+ return;
+ }
+
+ // some plain output...
+ if (!m_description.isEmpty())
+ m_description.append('\n');
+ m_description.append(line);
+}
+
+void BoostTestOutputReader::processStdError(const QByteArray &output)
+{
+ // we need to process the output, Boost UTF uses both out streams
+ int start = 0;
+ int index = -1;
+ while ((index = output.indexOf('\n', start)) != -1) {
+ const QByteArray &line = output.mid(start, index - start + 1);
+ if (!line.isEmpty()) {
+ if (line != QByteArray(1, '\n'))
+ processOutputLine(line);
+ emit newOutputAvailable(line);
+ }
+ start = index + 1;
+ }
+ if (start > 0) { // remove? this never happens
+ const QByteArray lastLine = output.mid(start) + '\n';
+ if (!lastLine.isEmpty()) {
+ if (lastLine != QByteArray(1, '\n'))
+ processOutputLine(lastLine);
+ emit newOutputAvailable(lastLine);
+ }
+ }
+}
+
+TestResultPtr BoostTestOutputReader::createDefaultResult() const
+{
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule);
+ result->setTestSuite(m_currentSuite);
+ result->setTestCase(m_currentTest);
+
+ return TestResultPtr(result);
+}
+
+void BoostTestOutputReader::onFinished(int exitCode, QProcess::ExitStatus /*exitState*/) {
+ 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);
+ }
+ // boost::exit_success (0), boost::exit_test_failure (201)
+ // or boost::exit_exception_failure (200)
+ // be graceful and do not add a fatal for exit_test_failure
+ if (m_logLevel == LogLevel::Nothing && m_reportLevel == ReportLevel::No) {
+ switch (exitCode) {
+ case 0:
+ reportNoOutputFinish(tr("Running tests exited with ") + "boost::exit_success.",
+ ResultType::Pass);
+ break;
+ case 200:
+ reportNoOutputFinish(
+ tr("Running tests exited with ") + "boost::exit_test_exception.",
+ ResultType::MessageFatal);
+ break;
+ case 201:
+ reportNoOutputFinish(tr("Running tests exited with ")
+ + "boost::exit_test_failure.", ResultType::Fail);
+ break;
+ }
+ } else if (exitCode != 0 && exitCode != 201 && !m_description.isEmpty()) {
+ if (m_description.startsWith("Test setup error:")) {
+ createAndReportResult(m_description + '\n' + tr("Executable: %1")
+ .arg(id()), ResultType::MessageWarn);
+ } else {
+ createAndReportResult(tr("Running tests failed.\n%1\nExecutable: %2")
+ .arg(m_description).arg(id()), ResultType::MessageFatal);
+ }
+ }
+}
+
+void BoostTestOutputReader::reportNoOutputFinish(const QString &description, ResultType type)
+{
+ BoostTestResult *result = new BoostTestResult(id(), m_projectFile, m_currentModule);
+ result->setTestCase(tr("Running tests without output."));
+ result->setDescription(description);
+ result->setResult(type);
+ reportResult(TestResultPtr(result));
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestoutputreader.h b/src/plugins/autotest/boost/boosttestoutputreader.h
new file mode 100644
index 0000000000..e16c1fb996
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestoutputreader.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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 "../testoutputreader.h"
+
+namespace Autotest {
+namespace Internal {
+
+class BoostTestResult;
+class TestTreeItem;
+enum class LogLevel;
+enum class ReportLevel;
+
+class BoostTestOutputReader : public TestOutputReader
+{
+public:
+ BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
+ QProcess *testApplication, const QString &buildDirectory,
+ const QString &projectFile, LogLevel log, ReportLevel report);
+protected:
+ void processOutputLine(const QByteArray &outputLineWithNewLine) override;
+ void processStdError(const QByteArray &output) override;
+ TestResultPtr createDefaultResult() const override;
+
+private:
+ void onFinished(int exitCode, QProcess::ExitStatus /*exitState*/);
+ void sendCompleteInformation();
+ void handleMessageMatch(const QRegularExpressionMatch &match);
+ void reportNoOutputFinish(const QString &description, ResultType type);
+ QString m_projectFile;
+ QString m_currentModule;
+ QString m_currentSuite;
+ QString m_currentTest;
+ QString m_description;
+ QString m_fileName;
+ ResultType m_result = ResultType::Invalid;
+ int m_lineNumber = 0;
+ int m_testCaseCount = -1;
+ LogLevel m_logLevel;
+ ReportLevel m_reportLevel;
+};
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestparser.cpp b/src/plugins/autotest/boost/boosttestparser.cpp
new file mode 100644
index 0000000000..6f953e515a
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestparser.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** 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 "boosttestparser.h"
+#include "boostcodeparser.h"
+#include "boosttesttreeitem.h"
+
+#include <cpptools/cppmodelmanager.h>
+
+#include <QMap>
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
+
+namespace Autotest {
+namespace Internal {
+
+namespace BoostTestUtils {
+static const QStringList relevant = {
+ QStringLiteral("BOOST_AUTO_TEST_CASE"), QStringLiteral("BOOST_TEST_CASE"),
+ QStringLiteral("BOOST_DATA_TEST_CASE"), QStringLiteral("BOOST_FIXTURE_TEST_CASE"),
+ QStringLiteral("BOOST_PARAM_TEST_CASE"), QStringLiteral("BOOST_DATA_TEST_CASE_F"),
+ QStringLiteral("BOOST_AUTO_TEST_CASE_TEMPLATE"),
+ QStringLiteral("BOOST_FIXTURE_TEST_CASE_TEMPLATE"),
+};
+
+bool isBoostTestMacro(const QString &macro)
+{
+ return relevant.contains(macro);
+}
+} // BoostTestUtils
+
+TestTreeItem *BoostTestParseResult::createTestTreeItem() const
+{
+ if (itemType == TestTreeItem::Root)
+ return nullptr;
+
+ BoostTestTreeItem *item = new BoostTestTreeItem(displayName, fileName, itemType);
+ item->setProFile(proFile);
+ item->setLine(line);
+ item->setColumn(column);
+ item->setStates(state);
+ item->setFullName(name);
+
+ for (const TestParseResult *funcParseResult : children)
+ item->appendChild(funcParseResult->createTestTreeItem());
+ return item;
+}
+
+
+static bool includesBoostTest(const CPlusPlus::Document::Ptr &doc,
+ const CPlusPlus::Snapshot &snapshot)
+{
+ static const QRegularExpression boostTestHpp("^.*/boost/test/.*\\.hpp$");
+ for (const CPlusPlus::Document::Include &inc : doc->resolvedIncludes()) {
+ if (boostTestHpp.match(inc.resolvedFileName()).hasMatch())
+ return true;
+ }
+
+ for (const QString &include : snapshot.allIncludesForDocument(doc->fileName())) {
+ if (boostTestHpp.match(include).hasMatch())
+ return true;
+ }
+
+ return false;
+}
+
+static bool hasBoostTestMacros(const CPlusPlus::Document::Ptr &doc)
+{
+ for (const CPlusPlus::Document::MacroUse &macro : doc->macroUses()) {
+ if (!macro.isFunctionLike())
+ continue;
+ if (BoostTestUtils::isBoostTestMacro(QLatin1String(macro.macro().name())))
+ return true;
+ }
+ return false;
+}
+
+static BoostTestParseResult *createParseResult(const QString &name, const QString &filePath,
+ const QString &projectFile, const Core::Id &id,
+ TestTreeItem::Type type, const BoostTestInfo &info)
+{
+ BoostTestParseResult *partialSuite = new BoostTestParseResult(id);
+ partialSuite->itemType = type;
+ partialSuite->fileName = filePath;
+ partialSuite->name = info.fullName;
+ partialSuite->displayName = name;
+ partialSuite->line = info.line;
+ partialSuite->column = 0;
+ partialSuite->proFile = projectFile;
+ partialSuite->state = info.state;
+ return partialSuite;
+
+}
+
+static bool handleBoostTest(QFutureInterface<TestParseResultPtr> futureInterface,
+ const CPlusPlus::Document::Ptr &doc,
+ const CPlusPlus::Snapshot &snapshot,
+ const Core::Id &id)
+{
+ const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
+ const QString &filePath = doc->fileName();
+
+ const QList<CppTools::ProjectPart::Ptr> projectParts = modelManager->projectPart(filePath);
+ if (projectParts.isEmpty()) // happens if shutting down while parsing
+ return false;
+ const CppTools::ProjectPart::Ptr projectPart = projectParts.first();
+ const auto projectFile = projectPart->projectFile;
+ const QByteArray &fileContent = CppParser::getFileContent(filePath);
+
+ BoostCodeParser codeParser(fileContent, projectPart->languageFeatures, doc, snapshot);
+ const BoostTestCodeLocationList foundTests = codeParser.findTests();
+ if (foundTests.isEmpty())
+ return false;
+
+ for (const BoostTestCodeLocationAndType &locationAndType : foundTests) {
+ BoostTestInfoList suitesStates = locationAndType.m_suitesState;
+ BoostTestInfo firstSuite = suitesStates.first();
+ QStringList suites = firstSuite.fullName.split('/');
+ BoostTestParseResult *topLevelSuite = createParseResult(suites.first(), filePath,
+ projectFile, id,
+ TestTreeItem::TestSuite,
+ firstSuite);
+ BoostTestParseResult *currentSuite = topLevelSuite;
+ suitesStates.removeFirst();
+ while (suitesStates.size()) {
+ firstSuite = suitesStates.first();
+ suites = firstSuite.fullName.split('/');
+ BoostTestParseResult *suiteResult = createParseResult(suites.last(), filePath,
+ projectFile, id,
+ TestTreeItem::TestSuite,
+ firstSuite);
+ currentSuite->children.append(suiteResult);
+ suitesStates.removeFirst();
+ currentSuite = suiteResult;
+ }
+
+ if (currentSuite) {
+ BoostTestInfo tmpInfo{
+ locationAndType.m_suitesState.last().fullName + "::" + locationAndType.m_name,
+ locationAndType.m_state, locationAndType.m_line};
+ BoostTestParseResult *funcResult = createParseResult(locationAndType.m_name, filePath,
+ projectFile, id,
+ locationAndType.m_type,
+ tmpInfo);
+ currentSuite->children.append(funcResult);
+ futureInterface.reportResult(TestParseResultPtr(topLevelSuite));
+ }
+ }
+ return true;
+}
+
+bool BoostTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
+ const QString &fileName)
+{
+ CPlusPlus::Document::Ptr doc = document(fileName);
+ if (doc.isNull() || !includesBoostTest(doc, m_cppSnapshot) || !hasBoostTestMacros(doc))
+ return false;
+ return handleBoostTest(futureInterface, doc, m_cppSnapshot, id());
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestparser.h b/src/plugins/autotest/boost/boosttestparser.h
new file mode 100644
index 0000000000..678b859cc9
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestparser.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** 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 "../itestparser.h"
+#include "boosttesttreeitem.h"
+
+namespace Autotest {
+namespace Internal {
+
+class BoostTestParseResult : public TestParseResult
+{
+public:
+ explicit BoostTestParseResult(const Core::Id &id) : TestParseResult(id) {}
+ TestTreeItem *createTestTreeItem() const override;
+ // TODO special attributes/states (labeled, timeout,...?)
+ BoostTestTreeItem::TestStates state = BoostTestTreeItem::Enabled;
+};
+
+class BoostTestParser : public CppParser
+{
+public:
+ bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
+ const QString &fileName) override;
+};
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestresult.cpp b/src/plugins/autotest/boost/boosttestresult.cpp
new file mode 100644
index 0000000000..cf6d6e7b41
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestresult.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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 "boosttestresult.h"
+
+namespace Autotest {
+namespace Internal {
+
+BoostTestResult::BoostTestResult(const QString &id, const QString &projectFile, const QString &name)
+ : TestResult(id, name), m_projectFile(projectFile)
+{
+}
+
+const QString BoostTestResult::outputString(bool selected) const
+{
+ const QString &desc = description();
+ QString output;
+ switch (result()) {
+ case ResultType::Pass:
+ case ResultType::Fail:
+ output = m_testCase;
+ if (selected && !desc.isEmpty())
+ output.append('\n').append(desc);
+ break;
+ default:
+ output = desc;
+ if (!selected)
+ output = output.split('\n').first();
+ }
+ return output;
+}
+
+bool BoostTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermediate) const
+{
+ if (!TestResult::isDirectParentOf(other, needsIntermediate))
+ return false;
+
+ const BoostTestResult *boostOther = static_cast<const BoostTestResult *>(other);
+
+ if (m_testSuite != boostOther->m_testSuite)
+ return false;
+
+ if (result() == ResultType::TestStart) {
+ if (!boostOther->m_testCase.isEmpty())
+ return boostOther->m_testSuite == m_testSuite && boostOther->result() != ResultType::TestStart;
+
+ return boostOther->m_testCase == m_testCase;
+ }
+ return false;
+}
+
+} // namespace Internal
+} // namespace Autotest
+
diff --git a/src/plugins/autotest/boost/boosttestresult.h b/src/plugins/autotest/boost/boosttestresult.h
new file mode 100644
index 0000000000..b27dda16e8
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestresult.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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 "../testresult.h"
+
+namespace Autotest {
+namespace Internal {
+
+class BoostTestResult : public TestResult
+{
+public:
+ BoostTestResult(const QString &id, const QString &projectFile, const QString &name);
+ const QString outputString(bool selected) const override;
+
+ bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override;
+ void setTestSuite(const QString &testSuite) { m_testSuite = testSuite; }
+ void setTestCase(const QString &testCase) { m_testCase = testCase; }
+private:
+ QString m_projectFile;
+ QString m_testSuite;
+ QString m_testCase;
+};
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestsettings.cpp b/src/plugins/autotest/boost/boosttestsettings.cpp
new file mode 100644
index 0000000000..7b1fc855ed
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestsettings.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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 "boosttestsettings.h"
+
+namespace Autotest {
+namespace Internal {
+
+static const char logLevelKey[] = "LogLevel";
+static const char reportLevelKey[] = "ReportLevel";
+static const char seedKey[] = "Seed";
+static const char randomizeKey[] = "Randomize";
+static const char systemErrorsKey[] = "SystemErrors";
+static const char fpExceptionsKey[] = "FPExceptions";
+static const char memLeaksKey[] = "MemoryLeaks";
+
+QString BoostTestSettings::name() const
+{
+ return QString("BoostTest");
+}
+
+void BoostTestSettings::fromFrameworkSettings(const QSettings *s)
+
+{
+ logLevel = LogLevel((s->value(logLevelKey, int(LogLevel::All)).toInt()));
+ reportLevel = ReportLevel((s->value(reportLevelKey, int(ReportLevel::Confirm)).toInt()));
+ systemErrors = s->value(systemErrorsKey, false).toBool();
+ fpExceptions = s->value(fpExceptionsKey, false).toBool();
+ memLeaks = s->value(memLeaksKey, true).toBool();
+ randomize = s->value(randomizeKey, false).toBool();
+ seed = s->value(seedKey, 0).toInt();
+}
+
+void BoostTestSettings::toFrameworkSettings(QSettings *s) const
+{
+ s->setValue(logLevelKey, int(logLevel));
+ s->setValue(reportLevelKey, int(reportLevel));
+ s->setValue(systemErrorsKey, systemErrors);
+ s->setValue(fpExceptionsKey, fpExceptions);
+ s->setValue(memLeaksKey, memLeaks);
+ s->setValue(randomizeKey, randomize);
+ s->setValue(seedKey, seed);
+}
+
+QString BoostTestSettings::logLevelToOption(const LogLevel logLevel)
+{
+ switch (logLevel) {
+ case LogLevel::All: return QString("all");
+ case LogLevel::Success: return QString("success");
+ case LogLevel::TestSuite: return QString("test_suite");
+ case LogLevel::UnitScope: return QString("unit_scope");
+ case LogLevel::Message: return QString("message");
+ case LogLevel::Error: return QString("error");
+ case LogLevel::CppException: return QString("cpp_exception");
+ case LogLevel::SystemError: return QString("system_error");
+ case LogLevel::FatalError: return QString("fatal_error");
+ case LogLevel::Nothing: return QString("nothing");
+ case LogLevel::Warning: return QString("warning");
+ }
+ return QString();
+}
+
+QString BoostTestSettings::reportLevelToOption(const ReportLevel reportLevel)
+{
+ switch (reportLevel) {
+ case ReportLevel::Confirm: return QString("confirm");
+ case ReportLevel::Short: return QString("short");
+ case ReportLevel::Detailed: return QString("detailed");
+ case ReportLevel::No: return QString("no");
+ }
+ return QString();
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttestsettings.h b/src/plugins/autotest/boost/boosttestsettings.h
new file mode 100644
index 0000000000..8e10af856f
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestsettings.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 "../iframeworksettings.h"
+
+namespace Autotest {
+namespace Internal {
+
+enum class LogLevel
+{
+ All,
+ Success,
+ TestSuite,
+ UnitScope,
+ Message,
+ Warning,
+ Error,
+ CppException,
+ SystemError,
+ FatalError,
+ Nothing
+};
+
+enum class ReportLevel
+{
+ Confirm,
+ Short,
+ Detailed,
+ No
+};
+
+class BoostTestSettings : public IFrameworkSettings
+{
+public:
+ BoostTestSettings() = default;
+ QString name() const override;
+ static QString logLevelToOption(const LogLevel logLevel);
+ static QString reportLevelToOption(const ReportLevel reportLevel);
+
+ LogLevel logLevel = LogLevel::Warning;
+ ReportLevel reportLevel = ReportLevel::Confirm;
+ int seed = 0;
+ bool randomize = false;
+ bool systemErrors = false;
+ bool fpExceptions = false;
+ bool memLeaks = true;
+
+protected:
+ void fromFrameworkSettings(const QSettings *s) override;
+ void toFrameworkSettings(QSettings *s) const override;
+};
+
+} // namespace Internal
+} // namespace Autotest
+
+Q_DECLARE_METATYPE(Autotest::Internal::LogLevel)
+Q_DECLARE_METATYPE(Autotest::Internal::ReportLevel)
diff --git a/src/plugins/autotest/boost/boosttestsettingspage.cpp b/src/plugins/autotest/boost/boosttestsettingspage.cpp
new file mode 100644
index 0000000000..99d13a51da
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestsettingspage.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** 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 "boosttestsettingspage.h"
+#include "boosttestconstants.h"
+#include "boosttestsettings.h"
+#include "../testframeworkmanager.h"
+
+#include <coreplugin/icore.h>
+
+namespace Autotest {
+namespace Internal {
+
+BoostTestSettingsWidget::BoostTestSettingsWidget(QWidget *parent) :
+ QWidget(parent)
+{
+ m_ui.setupUi(this);
+ fillComboBoxes();
+ connect(m_ui.randomizeCB, &QCheckBox::toggled, m_ui.seedSB, &QSpinBox::setEnabled);
+}
+
+void BoostTestSettingsWidget::setSettings(const BoostTestSettings &settings)
+{
+ m_ui.logFormatCB->setCurrentIndex(int(settings.logLevel));
+ m_ui.reportLevelCB->setCurrentIndex(int(settings.reportLevel));
+ m_ui.randomizeCB->setChecked(settings.randomize);
+ m_ui.seedSB->setValue(settings.seed);
+ m_ui.systemErrorCB->setChecked(settings.systemErrors);
+ m_ui.fpExceptions->setChecked(settings.fpExceptions);
+ m_ui.memoryLeakCB->setChecked(settings.memLeaks);
+}
+
+BoostTestSettings BoostTestSettingsWidget::settings() const
+{
+ BoostTestSettings result;
+
+ result.logLevel = LogLevel(m_ui.logFormatCB->currentData().toInt());
+ result.reportLevel = ReportLevel(m_ui.reportLevelCB->currentData().toInt());
+ result.randomize = m_ui.randomizeCB->isChecked();
+ result.seed = m_ui.seedSB->value();
+ result.systemErrors = m_ui.systemErrorCB->isChecked();
+ result.fpExceptions = m_ui.fpExceptions->isChecked();
+ result.memLeaks = m_ui.memoryLeakCB->isChecked();
+ return result;
+}
+
+void BoostTestSettingsWidget::fillComboBoxes()
+{
+ m_ui.logFormatCB->addItem("All", QVariant::fromValue(LogLevel::All));
+ m_ui.logFormatCB->addItem("Success", QVariant::fromValue(LogLevel::Success));
+ m_ui.logFormatCB->addItem("Test Suite", QVariant::fromValue(LogLevel::TestSuite));
+ m_ui.logFormatCB->addItem("Unit Scope", QVariant::fromValue(LogLevel::UnitScope));
+ m_ui.logFormatCB->addItem("Message", QVariant::fromValue(LogLevel::Message));
+ m_ui.logFormatCB->addItem("Warning", QVariant::fromValue(LogLevel::Warning));
+ m_ui.logFormatCB->addItem("Error", QVariant::fromValue(LogLevel::Error));
+ m_ui.logFormatCB->addItem("C++ Exception", QVariant::fromValue(LogLevel::CppException));
+ m_ui.logFormatCB->addItem("System Error", QVariant::fromValue(LogLevel::SystemError));
+ m_ui.logFormatCB->addItem("Fatal Error", QVariant::fromValue(LogLevel::FatalError));
+ m_ui.logFormatCB->addItem("Nothing", QVariant::fromValue(LogLevel::Nothing));
+
+ m_ui.reportLevelCB->addItem("Confirm", QVariant::fromValue(ReportLevel::Confirm));
+ m_ui.reportLevelCB->addItem("Short", QVariant::fromValue(ReportLevel::Short));
+ m_ui.reportLevelCB->addItem("Detailed", QVariant::fromValue(ReportLevel::Detailed));
+ m_ui.reportLevelCB->addItem("No", QVariant::fromValue(ReportLevel::No));
+}
+
+BoostTestSettingsPage::BoostTestSettingsPage(QSharedPointer<IFrameworkSettings> settings,
+ const ITestFramework *framework)
+ : ITestSettingsPage(framework),
+ m_settings(qSharedPointerCast<BoostTestSettings>(settings))
+{
+ setDisplayName(QCoreApplication::translate("BoostTestFramework",
+ BoostTest::Constants::FRAMEWORK_SETTINGS_CATEGORY));
+}
+
+QWidget *BoostTestSettingsPage::widget()
+{
+ if (!m_widget) {
+ m_widget = new BoostTestSettingsWidget;
+ m_widget->setSettings(*m_settings);
+ }
+ return m_widget;
+}
+
+void BoostTestSettingsPage::apply()
+{
+ if (!m_widget) // page was not shown at all
+ return;
+
+ *m_settings = m_widget->settings();
+ m_settings->toSettings(Core::ICore::settings());
+}
+
+} // Internal
+} // Autotest
diff --git a/src/plugins/autotest/boost/boosttestsettingspage.h b/src/plugins/autotest/boost/boosttestsettingspage.h
new file mode 100644
index 0000000000..5e0e65f7b9
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestsettingspage.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 "ui_boosttestsettingspage.h"
+#include "../itestsettingspage.h"
+
+#include <QPointer>
+
+namespace Autotest {
+namespace Internal {
+
+class IFrameworkSettings;
+class BoostTestSettings;
+
+class BoostTestSettingsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit BoostTestSettingsWidget(QWidget *parent = nullptr);
+
+ void setSettings(const BoostTestSettings &settings);
+ BoostTestSettings settings() const;
+private:
+ void fillComboBoxes();
+ Ui::BoostSettingsPage m_ui;
+};
+
+class BoostTestSettingsPage : public ITestSettingsPage
+{
+ Q_OBJECT
+public:
+ BoostTestSettingsPage(QSharedPointer<IFrameworkSettings> settings,
+ const ITestFramework *framework);
+
+ QWidget *widget() override;
+ void apply() override;
+
+private:
+ QSharedPointer<BoostTestSettings> m_settings;
+ QPointer<BoostTestSettingsWidget> m_widget;
+};
+
+} // Internal
+} // Autotest
diff --git a/src/plugins/autotest/boost/boosttestsettingspage.ui b/src/plugins/autotest/boost/boosttestsettingspage.ui
new file mode 100644
index 0000000000..1596cd7d41
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttestsettingspage.ui
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BoostSettingsPage</class>
+ <widget class="QWidget" name="BoostSettingsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>309</width>
+ <height>284</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Log format:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="logFormatCB"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Report level:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="reportLevelCB"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="randomizeCB">
+ <property name="toolTip">
+ <string>Randomize execution order.</string>
+ </property>
+ <property name="text">
+ <string>Randomize</string>
+ </property>
+ </widget>
+ </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>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Seed:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="seedSB">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>A seed of 0 means no randomization. A value of 1 uses the current time any other value is used as random seed generator.</string>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="systemErrorCB">
+ <property name="toolTip">
+ <string>Catch or ignore system errors.</string>
+ </property>
+ <property name="text">
+ <string>Catch system errors</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="fpExceptions">
+ <property name="toolTip">
+ <string>Enable floating point exception traps.</string>
+ </property>
+ <property name="text">
+ <string>Floating point exceptions</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="memoryLeakCB">
+ <property name="toolTip">
+ <string>Enable memory leak detection.</string>
+ </property>
+ <property name="text">
+ <string>Detect memory leaks</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </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>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>84</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/autotest/boost/boosttesttreeitem.cpp b/src/plugins/autotest/boost/boosttesttreeitem.cpp
new file mode 100644
index 0000000000..e2e58c28af
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttesttreeitem.cpp
@@ -0,0 +1,365 @@
+/****************************************************************************
+**
+** 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 "boosttesttreeitem.h"
+#include "boosttestconstants.h"
+#include "boosttestconfiguration.h"
+#include "boosttestparser.h"
+#include "../testframeworkmanager.h"
+
+#include <projectexplorer/session.h>
+#include <utils/qtcassert.h>
+
+#include <QFileInfo>
+#include <QRegularExpression>
+
+namespace Autotest {
+namespace Internal {
+
+TestTreeItem *BoostTestTreeItem::copyWithoutChildren()
+{
+ BoostTestTreeItem *copied = new BoostTestTreeItem;
+ copied->copyBasicDataFrom(this);
+ copied->m_state = m_state;
+ copied->m_fullName = m_fullName;
+ return copied;
+}
+
+QVariant BoostTestTreeItem::data(int column, int role) const
+{
+ switch (role) {
+ case Qt::DisplayRole:
+ if (type() == Root)
+ break;
+ return QString(name() + nameSuffix());
+ case Qt::CheckStateRole:
+ return checked();
+ case ItalicRole:
+ return false;
+ case EnabledRole:
+ return enabled();
+ default:
+ break;
+ }
+ return TestTreeItem::data(column, role);
+}
+
+TestTreeItem *BoostTestTreeItem::find(const TestParseResult *result)
+{
+ QTC_ASSERT(result, return nullptr);
+
+ const BoostTestParseResult *bResult = static_cast<const BoostTestParseResult *>(result);
+
+ switch (type()) {
+ case Root:
+ if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) {
+ const QFileInfo fileInfo(bResult->fileName);
+ const QFileInfo base(fileInfo.absolutePath());
+ for (int row = 0; row < childCount(); ++row) {
+ BoostTestTreeItem *group = static_cast<BoostTestTreeItem *>(childAt(row));
+ if (group->filePath() != base.absoluteFilePath())
+ continue;
+ if (auto groupChild = group->findChildByNameStateAndFile(
+ bResult->name, bResult->state, bResult->proFile)) {
+ return groupChild;
+ }
+ }
+ }
+ return findChildByNameStateAndFile(bResult->name, bResult->state, bResult->proFile);
+ case GroupNode:
+ case TestSuite:
+ return findChildByNameStateAndFile(bResult->name, bResult->state, bResult->proFile);
+ default:
+ return nullptr;
+ }
+}
+
+TestTreeItem *BoostTestTreeItem::findChild(const TestTreeItem *other)
+{
+ QTC_ASSERT(other, return nullptr);
+ const Type otherType = other->type();
+
+ switch (type()) {
+ case Root: {
+ TestTreeItem *result = nullptr;
+ if (otherType == GroupNode) {
+ result = findChildByNameAndFile(other->name(), other->filePath());
+ } else if (otherType == TestSuite) {
+ auto bOther = static_cast<const BoostTestTreeItem *>(other);
+ result = findChildByNameStateAndFile(bOther->name(), bOther->state(),
+ bOther->proFile());
+ }
+ return (result && result->type() == otherType) ? result : nullptr;
+ }
+ case GroupNode: {
+ auto bOther = static_cast<const BoostTestTreeItem *>(other);
+ return otherType == TestSuite
+ ? findChildByNameStateAndFile(bOther->name(), bOther->state(), bOther->proFile())
+ : nullptr;
+ }
+ case TestSuite: {
+ if (otherType == TestCase) {
+ return findChildByNameAndFile(other->name(), other->filePath());
+ } else if (otherType == TestSuite) {
+ auto bOther = static_cast<const BoostTestTreeItem *>(other);
+ return findChildByNameStateAndFile(other->name(), bOther->state(), other->proFile());
+ } else {
+ return nullptr;
+ }
+ }
+ default:
+ return nullptr;
+ }
+}
+
+bool BoostTestTreeItem::modify(const TestParseResult *result)
+{
+ QTC_ASSERT(result, return false);
+ return (type() == TestCase || type() == TestSuite)
+ ? modifyTestContent(static_cast<const BoostTestParseResult *>(result))
+ : false;
+}
+
+TestTreeItem *BoostTestTreeItem::createParentGroupNode() const
+{
+ const QFileInfo fileInfo(filePath());
+ const QFileInfo base(fileInfo.absolutePath());
+ return new BoostTestTreeItem(base.baseName(), fileInfo.absolutePath(), TestTreeItem::GroupNode);
+}
+
+QString BoostTestTreeItem::prependWithParentsSuitePaths(const QString &testName) const
+{
+ QString prepend = type() == TestSuite ? m_fullName.left(m_fullName.lastIndexOf('/'))
+ : m_fullName.left(m_fullName.indexOf("::"));
+ if (prepend.startsWith(BoostTest::Constants::BOOST_MASTER_SUITE))
+ prepend = prepend.mid(QString(BoostTest::Constants::BOOST_MASTER_SUITE).length());
+
+ return prepend + '/' + testName;
+}
+
+static QString handleSpecialFunctionNames(const QString &name)
+{
+ static const QRegularExpression function(".*\\((.*),.*\\)");
+ const QRegularExpressionMatch match = function.match(name);
+ if (!match.hasMatch())
+ return name;
+ QString result = match.captured(1);
+ int index = result.lastIndexOf(':');
+ if (index != -1)
+ result = result.mid(index + 1);
+ result.prepend('*').append('*');
+ return result;
+}
+
+QList<TestConfiguration *> BoostTestTreeItem::getAllTestConfigurations() const
+{
+ QList<TestConfiguration *> result;
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ if (!project || type() != Root)
+ return result;
+
+ struct BoostTestCases {
+ int testCases;
+ QSet<QString> internalTargets;
+ };
+
+ // we only need the unique project files (and number of test cases for the progress indicator)
+ QHash<QString, BoostTestCases> testsPerProjectfile;
+ forAllChildren([&testsPerProjectfile](TreeItem *it){
+ auto item = static_cast<BoostTestTreeItem *>(it);
+ if (item->type() != TestSuite)
+ return;
+ int funcChildren = 0;
+ item->forAllChildren([&funcChildren](TreeItem *child){
+ if (static_cast<BoostTestTreeItem *>(child)->type() == TestCase)
+ ++funcChildren;
+ });
+ if (funcChildren) {
+ testsPerProjectfile[item->proFile()].testCases += funcChildren;
+ testsPerProjectfile[item->proFile()].internalTargets.unite(item->internalTargets());
+ }
+ });
+
+ for (auto it = testsPerProjectfile.begin(), end = testsPerProjectfile.end(); it != end; ++it) {
+ BoostTestConfiguration *config = new BoostTestConfiguration;
+ config->setProject(project);
+ config->setProjectFile(it.key());
+ config->setTestCaseCount(it.value().testCases);
+ config->setInternalTargets(it.value().internalTargets);
+ result.append(config);
+ }
+ return result;
+}
+
+QList<TestConfiguration *> BoostTestTreeItem::getSelectedTestConfigurations() const
+{
+ QList<TestConfiguration *> result;
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ if (!project || type() != Root)
+ return result;
+
+ struct BoostTestCases {
+ QStringList testCases;
+ QSet<QString> internalTargets;
+ };
+
+ QHash<QString, BoostTestCases> testCasesForProjectFile;
+ forAllChildren([&testCasesForProjectFile](TreeItem *it){
+ auto item = static_cast<BoostTestTreeItem *>(it);
+ if (item->type() != TestCase)
+ return;
+ if (!item->enabled()) // ignore child tests known to be disabled when using run selected
+ return;
+ if (item->checked() == Qt::Checked) {
+ QString tcName = item->name();
+ if (item->state().testFlag(BoostTestTreeItem::Templated))
+ tcName.append("<*");
+ tcName = handleSpecialFunctionNames(tcName);
+ testCasesForProjectFile[item->proFile()].testCases.append(
+ item->prependWithParentsSuitePaths(tcName));
+ testCasesForProjectFile[item->proFile()].internalTargets.unite(item->internalTargets());
+ }
+ });
+
+ auto end = testCasesForProjectFile.cend();
+ for (auto it = testCasesForProjectFile.cbegin(); it != end; ++it) {
+ BoostTestConfiguration *config = new BoostTestConfiguration;
+ config->setProject(project);
+ config->setProjectFile(it.key());
+ config->setTestCases(it.value().testCases);
+ config->setInternalTargets(it.value().internalTargets);
+ result.append(config);
+ }
+ return result;
+}
+
+TestConfiguration *BoostTestTreeItem::testConfiguration() const
+{
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
+ QTC_ASSERT(project, return nullptr);
+
+ const Type itemType = type();
+ if (itemType == TestSuite || itemType == TestCase) {
+ QStringList testCases;
+ if (itemType == TestSuite) {
+ forFirstLevelChildren([&testCases](TestTreeItem *child) {
+ QTC_ASSERT(child, return);
+ if (auto boostItem = static_cast<BoostTestTreeItem *>(child)) {
+ if (boostItem->enabled()) {
+ QString tcName = handleSpecialFunctionNames(boostItem->name());
+ if (boostItem->type() == TestSuite) // execute everything below a suite
+ tcName.append("/*");
+ else if (boostItem->state().testFlag(BoostTestTreeItem::Templated))
+ tcName.append("<*");
+ testCases.append(boostItem->prependWithParentsSuitePaths(tcName));
+ }
+ }
+ });
+ } else {
+ QString tcName = name();
+ if (state().testFlag(BoostTestTreeItem::Templated))
+ tcName.append("<*");
+ testCases.append(prependWithParentsSuitePaths(handleSpecialFunctionNames(tcName)));
+ }
+
+ BoostTestConfiguration *config = new BoostTestConfiguration;
+ config->setProjectFile(proFile());
+ config->setProject(project);
+ config->setTestCases(testCases);
+ config->setInternalTargets(internalTargets());
+ return config;
+ }
+ return nullptr;
+}
+
+TestConfiguration *BoostTestTreeItem::debugConfiguration() const
+{
+ BoostTestConfiguration *config = static_cast<BoostTestConfiguration *>(testConfiguration());
+ if (config)
+ config->setRunMode(TestRunMode::Debug);
+ return config;
+}
+
+QString BoostTestTreeItem::nameSuffix() const
+{
+ static QString markups[] = {QCoreApplication::translate("BoostTestTreeItem", "parameterized"),
+ QCoreApplication::translate("BoostTestTreeItem", "fixture"),
+ QCoreApplication::translate("BoostTestTreeItem", "templated")};
+ QString suffix;
+ if (m_state & Parameterized)
+ suffix = QString(" [") + markups[0];
+ if (m_state & Fixture)
+ suffix += (suffix.isEmpty() ? QString(" [") : QString(", ")) + markups[1];
+ if (m_state & Templated)
+ suffix += (suffix.isEmpty() ? QString(" [") : QString(", ")) + markups[2];
+ if (!suffix.isEmpty())
+ suffix += ']';
+ return suffix;
+}
+
+bool BoostTestTreeItem::enabled() const
+{
+ if (m_state & ExplicitlyEnabled)
+ return true;
+
+ if (m_state & Disabled)
+ return false;
+
+ const TestTreeItem *parent = parentItem();
+ if (parent && parent->type() == TestSuite) // take test suites into account
+ return static_cast<const BoostTestTreeItem *>(parent)->enabled();
+
+ return true;
+}
+
+TestTreeItem *BoostTestTreeItem::findChildByNameStateAndFile(const QString &name,
+ BoostTestTreeItem::TestStates state,
+ const QString &proFile) const
+{
+ return static_cast<TestTreeItem *>(
+ findAnyChild([name, state, proFile](const Utils::TreeItem *other){
+ const BoostTestTreeItem *boostItem = static_cast<const BoostTestTreeItem *>(other);
+ return boostItem->proFile() == proFile && boostItem->fullName() == name
+ && boostItem->state() == state;
+ }));
+}
+
+bool BoostTestTreeItem::modifyTestContent(const BoostTestParseResult *result)
+{
+ bool hasBeenModified = modifyLineAndColumn(result);
+
+ if (m_state != result->state) {
+ m_state = result->state;
+ hasBeenModified = true;
+ }
+ if (m_fullName != result->name) {
+ m_fullName = result->name;
+ hasBeenModified = true;
+ }
+ return hasBeenModified;
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/boost/boosttesttreeitem.h b/src/plugins/autotest/boost/boosttesttreeitem.h
new file mode 100644
index 0000000000..1149720f9d
--- /dev/null
+++ b/src/plugins/autotest/boost/boosttesttreeitem.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 "../testtreeitem.h"
+
+namespace Autotest {
+namespace Internal {
+
+class BoostTestParseResult;
+
+class BoostTestTreeItem : public TestTreeItem
+{
+public:
+ enum TestState
+ {
+ Enabled = 0x00,
+ Disabled = 0x01,
+ ExplicitlyEnabled = 0x02,
+
+ Parameterized = 0x10,
+ Fixture = 0x20,
+ Templated = 0x40,
+ };
+ Q_FLAGS(TestState)
+ Q_DECLARE_FLAGS(TestStates, TestState)
+
+ explicit BoostTestTreeItem(const QString &name = QString(), const QString &filePath = QString(),
+ Type type = Root) : TestTreeItem(name, filePath, type) {}
+
+public:
+ TestTreeItem *copyWithoutChildren() override;
+ QVariant data(int column, int role) const override;
+ TestTreeItem *find(const TestParseResult *result) override;
+ TestTreeItem *findChild(const TestTreeItem *other) override;
+ bool modify(const TestParseResult *result) override;
+ TestTreeItem *createParentGroupNode() const override;
+
+ void setFullName(const QString &fullName) { m_fullName = fullName; }
+ QString fullName() const { return m_fullName; }
+ void setStates(TestStates states) { m_state = states; }
+ void setState(TestState state) { m_state |= state; }
+ TestStates state() const { return m_state; }
+
+ QList<TestConfiguration *> getAllTestConfigurations() const override;
+ QList<TestConfiguration *> getSelectedTestConfigurations() const override;
+ bool canProvideTestConfiguration() const override { return type() != Root; }
+ bool canProvideDebugConfiguration() const override { return canProvideTestConfiguration(); }
+ TestConfiguration *testConfiguration() const override;
+ TestConfiguration *debugConfiguration() const override;
+
+private:
+ QString nameSuffix() const;
+ bool enabled() const;
+ TestTreeItem *findChildByNameStateAndFile(const QString &name,
+ BoostTestTreeItem::TestStates state,
+ const QString &proFile) const;
+ QString prependWithParentsSuitePaths(const QString &testName) const;
+ bool modifyTestContent(const BoostTestParseResult *result);
+ TestStates m_state = Enabled;
+ QString m_fullName;
+};
+
+struct BoostTestInfo
+{
+ QString fullName; // formatted like UNIX path
+ BoostTestTreeItem::TestStates state;
+ unsigned line;
+};
+
+typedef QVector<BoostTestInfo> BoostTestInfoList;
+
+class BoostTestCodeLocationAndType : public TestCodeLocationAndType
+{
+public:
+ BoostTestTreeItem::TestStates m_state;
+ BoostTestInfoList m_suitesState;
+};
+
+typedef QVector<BoostTestCodeLocationAndType> BoostTestCodeLocationList;
+
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp
index d66ab7700b..f64155ed42 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.cpp
+++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp
@@ -31,7 +31,7 @@
#include <QDir>
#include <QFileInfo>
-#include <QRegExp>
+#include <QRegularExpression>
namespace Autotest {
namespace Internal {
@@ -48,12 +48,11 @@ GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futu
, m_projectFile(projectFile)
{
if (m_testApplication) {
- connect(m_testApplication,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, [this] (int exitCode, QProcess::ExitStatus /*exitStatus*/) {
if (exitCode == 1 && !m_description.isEmpty()) {
createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2")
- .arg(m_description).arg(id()), Result::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)
@@ -64,106 +63,108 @@ GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futu
void GTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLine)
{
- static QRegExp newTestStarts("^\\[-{10}\\] \\d+ tests? from (.*)$");
- static QRegExp testEnds("^\\[-{10}\\] \\d+ tests? from (.*) \\((.*)\\)$");
- static QRegExp newTestSetStarts("^\\[ RUN \\] (.*)$");
- static QRegExp testSetSuccess("^\\[ OK \\] (.*) \\((.*)\\)$");
- static QRegExp testSetFail("^\\[ FAILED \\] (.*) \\((\\d+ ms)\\)$");
- static QRegExp disabledTests("^ YOU HAVE (\\d+) DISABLED TESTS?$");
- static QRegExp failureLocation("^(.*):(\\d+): Failure$");
- static QRegExp errorLocation("^(.*)\\((\\d+)\\): error:.*$");
- static QRegExp iterations("^Repeating all tests \\(iteration (\\d+)\\) \\. \\. \\.$");
+ static const QRegularExpression newTestStarts("^\\[-{10}\\] \\d+ tests? from (.*)$");
+ static const QRegularExpression testEnds("^\\[-{10}\\] \\d+ tests? from (.*) \\((.*)\\)$");
+ static const QRegularExpression newTestSetStarts("^\\[ RUN \\] (.*)$");
+ static const QRegularExpression testSetSuccess("^\\[ OK \\] (.*) \\((.*)\\)$");
+ static const QRegularExpression testSetFail("^\\[ FAILED \\] (.*) \\((\\d+ ms)\\)$");
+ static const QRegularExpression disabledTests("^ YOU HAVE (\\d+) DISABLED TESTS?$");
+ static const QRegularExpression failureLocation("^(.*):(\\d+): Failure$");
+ static const QRegularExpression errorLocation("^(.*)\\((\\d+)\\): error:.*$");
+ static const QRegularExpression iterations("^Repeating all tests "
+ "\\(iteration (\\d+)\\) \\. \\. \\.$");
const QString line = QString::fromLatin1(chopLineBreak(outputLineWithNewLine));
if (line.trimmed().isEmpty())
return;
+ struct ExactMatch : public QRegularExpressionMatch
+ {
+ ExactMatch(const QRegularExpressionMatch &other) : QRegularExpressionMatch(other) {}
+ operator bool() const { return hasMatch(); }
+ };
+
if (!line.startsWith('[')) {
m_description.append(line).append('\n');
- if (iterations.exactMatch(line)) {
- m_iteration = iterations.cap(1).toInt();
+ if (ExactMatch match = iterations.match(line)) {
+ m_iteration = match.captured(1).toInt();
m_description.clear();
} else if (line.startsWith(QStringLiteral("Note:"))) {
m_description = line;
if (m_iteration > 1)
m_description.append(' ' + tr("(iteration %1)").arg(m_iteration));
TestResultPtr testResult = TestResultPtr(new GTestResult(id(), m_projectFile, QString()));
- testResult->setResult(Result::MessageInternal);
+ testResult->setResult(ResultType::MessageInternal);
testResult->setDescription(m_description);
reportResult(testResult);
m_description.clear();
- } else if (disabledTests.exactMatch(line)) {
- TestResultPtr testResult = TestResultPtr(new GTestResult(id(), m_projectFile, QString()));
- testResult->setResult(Result::MessageDisabledTests);
- int disabled = disabledTests.cap(1).toInt();
- testResult->setDescription(tr("You have %n disabled test(s).", nullptr, disabled));
- testResult->setLine(disabled); // misuse line property to hold number of disabled
- reportResult(testResult);
+ } else if (ExactMatch match = disabledTests.match(line)) {
+ m_disabled = match.captured(1).toInt();
m_description.clear();
}
return;
}
- if (testEnds.exactMatch(line)) {
+ if (ExactMatch match = testEnds.match(line)) {
TestResultPtr testResult = createDefaultResult();
- testResult->setResult(Result::MessageTestCaseEnd);
- testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2)));
+ testResult->setResult(ResultType::TestEnd);
+ testResult->setDescription(tr("Test execution took %1").arg(match.captured(2)));
reportResult(testResult);
- m_currentTestName.clear();
- m_currentTestSet.clear();
- } else if (newTestStarts.exactMatch(line)) {
- setCurrentTestName(newTestStarts.cap(1));
+ m_currentTestSuite.clear();
+ m_currentTestCase.clear();
+ } else if (ExactMatch match = newTestStarts.match(line)) {
+ setCurrentTestSuite(match.captured(1));
TestResultPtr testResult = createDefaultResult();
- testResult->setResult(Result::MessageTestCaseStart);
+ testResult->setResult(ResultType::TestStart);
if (m_iteration > 1) {
- testResult->setDescription(tr("Repeating test case %1 (iteration %2)")
- .arg(m_currentTestName).arg(m_iteration));
+ testResult->setDescription(tr("Repeating test suite %1 (iteration %2)")
+ .arg(m_currentTestSuite).arg(m_iteration));
} else {
- testResult->setDescription(tr("Executing test case %1").arg(m_currentTestName));
+ testResult->setDescription(tr("Executing test suite %1").arg(m_currentTestSuite));
}
reportResult(testResult);
- } else if (newTestSetStarts.exactMatch(line)) {
- setCurrentTestSet(newTestSetStarts.cap(1));
- TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
- testResult->setResult(Result::MessageCurrentTest);
- testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet));
+ } else if (ExactMatch match = newTestSetStarts.match(line)) {
+ setCurrentTestCase(match.captured(1));
+ TestResultPtr testResult = TestResultPtr(new GTestResult(QString(), m_projectFile,
+ QString()));
+ testResult->setResult(ResultType::MessageCurrentTest);
+ testResult->setDescription(tr("Entering test case %1").arg(m_currentTestCase));
reportResult(testResult);
m_description.clear();
- } else if (testSetSuccess.exactMatch(line)) {
+ } else if (ExactMatch match = testSetSuccess.match(line)) {
TestResultPtr testResult = createDefaultResult();
- testResult->setResult(Result::Pass);
+ testResult->setResult(ResultType::Pass);
testResult->setDescription(m_description);
reportResult(testResult);
m_description.clear();
testResult = createDefaultResult();
- testResult->setResult(Result::MessageInternal);
- testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2)));
+ testResult->setResult(ResultType::MessageInternal);
+ testResult->setDescription(tr("Execution took %1.").arg(match.captured(2)));
reportResult(testResult);
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
- } else if (testSetFail.exactMatch(line)) {
+ } else if (ExactMatch match = testSetFail.match(line)) {
TestResultPtr testResult = createDefaultResult();
- testResult->setResult(Result::Fail);
+ testResult->setResult(ResultType::Fail);
m_description.chop(1);
QStringList resultDescription;
for (const QString &output : m_description.split('\n')) {
- QRegExp *match = nullptr;
- if (failureLocation.exactMatch(output))
- match = &failureLocation;
- else if (errorLocation.exactMatch(output))
- match = &errorLocation;
- if (!match) {
- resultDescription << output;
- continue;
+ QRegularExpressionMatch innerMatch = failureLocation.match(output);
+ if (!innerMatch.hasMatch()) {
+ innerMatch = errorLocation.match(output);
+ if (!innerMatch.hasMatch()) {
+ resultDescription << output;
+ continue;
+ }
}
testResult->setDescription(resultDescription.join('\n'));
reportResult(testResult);
resultDescription.clear();
testResult = createDefaultResult();
- testResult->setResult(Result::MessageLocation);
- testResult->setLine(match->cap(2).toInt());
- QString file = constructSourceFilePath(m_buildDir, match->cap(1));
+ testResult->setResult(ResultType::MessageLocation);
+ testResult->setLine(innerMatch.captured(2).toInt());
+ QString file = constructSourceFilePath(m_buildDir, innerMatch.captured(1));
if (!file.isEmpty())
testResult->setFileName(file);
resultDescription << output;
@@ -172,8 +173,8 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLin
reportResult(testResult);
m_description.clear();
testResult = createDefaultResult();
- testResult->setResult(Result::MessageInternal);
- testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2)));
+ testResult->setResult(ResultType::MessageInternal);
+ testResult->setDescription(tr("Execution took %1.").arg(match.captured(2)));
reportResult(testResult);
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
}
@@ -181,8 +182,8 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLin
TestResultPtr GTestOutputReader::createDefaultResult() const
{
- GTestResult *result = new GTestResult(id(), m_projectFile, m_currentTestName);
- result->setTestSetName(m_currentTestSet);
+ GTestResult *result = new GTestResult(id(), m_projectFile, m_currentTestSuite);
+ result->setTestCaseName(m_currentTestCase);
result->setIteration(m_iteration);
const TestTreeItem *testItem = result->findTestTreeItem();
@@ -195,14 +196,14 @@ TestResultPtr GTestOutputReader::createDefaultResult() const
return TestResultPtr(result);
}
-void GTestOutputReader::setCurrentTestSet(const QString &testSet)
+void GTestOutputReader::setCurrentTestCase(const QString &testCase)
{
- m_currentTestSet = testSet;
+ m_currentTestCase = testCase;
}
-void GTestOutputReader::setCurrentTestName(const QString &testName)
+void GTestOutputReader::setCurrentTestSuite(const QString &testSuite)
{
- m_currentTestName = testName;
+ m_currentTestSuite = testSuite;
}
} // namespace Internal
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h
index 8f29ae73e1..6684b77f44 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.h
+++ b/src/plugins/autotest/gtest/gtestoutputreader.h
@@ -48,12 +48,12 @@ protected:
TestResultPtr createDefaultResult() const override;
private:
- void setCurrentTestSet(const QString &testSet);
- void setCurrentTestName(const QString &testName);
+ void setCurrentTestCase(const QString &testCase);
+ void setCurrentTestSuite(const QString &testSuite);
QString m_projectFile;
- QString m_currentTestName;
- QString m_currentTestSet;
+ QString m_currentTestSuite;
+ QString m_currentTestCase;
QString m_description;
int m_iteration = 1;
};
diff --git a/src/plugins/autotest/gtest/gtestparser.cpp b/src/plugins/autotest/gtest/gtestparser.cpp
index b21f161f06..f57f774ec0 100644
--- a/src/plugins/autotest/gtest/gtestparser.cpp
+++ b/src/plugins/autotest/gtest/gtestparser.cpp
@@ -36,7 +36,7 @@ namespace Internal {
TestTreeItem *GTestParseResult::createTestTreeItem() const
{
- if (itemType != TestTreeItem::TestCase && itemType != TestTreeItem::TestFunctionOrSet)
+ if (itemType != TestTreeItem::TestSuite && itemType != TestTreeItem::TestCase)
return nullptr;
GTestTreeItem *item = new GTestTreeItem(name, fileName, itemType);
item->setProFile(proFile);
@@ -110,7 +110,7 @@ static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface,
for (const GTestCaseSpec &testSpec : result.keys()) {
GTestParseResult *parseResult = new GTestParseResult(id);
- parseResult->itemType = TestTreeItem::TestCase;
+ parseResult->itemType = TestTreeItem::TestSuite;
parseResult->fileName = filePath;
parseResult->name = testSpec.testCaseName;
parseResult->parameterized = testSpec.parameterized;
@@ -139,12 +139,10 @@ static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface,
bool GTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
const QString &fileName)
{
- if (!m_cppSnapshot.contains(fileName) || !selectedForBuilding(fileName))
+ CPlusPlus::Document::Ptr doc = document(fileName);
+ if (doc.isNull() || !includesGTest(doc, m_cppSnapshot) || !hasGTestNames(doc))
return false;
- CPlusPlus::Document::Ptr document = m_cppSnapshot.find(fileName).value();
- if (!includesGTest(document, m_cppSnapshot) || !hasGTestNames(document))
- return false;
- return handleGTest(futureInterface, document, m_cppSnapshot, id());
+ return handleGTest(futureInterface, doc, m_cppSnapshot, id());
}
} // namespace Internal
diff --git a/src/plugins/autotest/gtest/gtestresult.cpp b/src/plugins/autotest/gtest/gtestresult.cpp
index 645f1af0a8..b2f3aae67b 100644
--- a/src/plugins/autotest/gtest/gtestresult.cpp
+++ b/src/plugins/autotest/gtest/gtestresult.cpp
@@ -30,14 +30,11 @@
#include <coreplugin/id.h>
+#include <QRegularExpression>
+
namespace Autotest {
namespace Internal {
-GTestResult::GTestResult(const QString &projectFile, const QString &name)
- : TestResult(name), m_projectFile(projectFile)
-{
-}
-
GTestResult::GTestResult(const QString &id, const QString &projectFile,
const QString &name)
: TestResult(id, name), m_projectFile(projectFile)
@@ -49,9 +46,9 @@ const QString GTestResult::outputString(bool selected) const
const QString &desc = description();
QString output;
switch (result()) {
- case Result::Pass:
- case Result::Fail:
- output = m_testSetName;
+ case ResultType::Pass:
+ case ResultType::Fail:
+ output = m_testCaseName;
if (selected && !desc.isEmpty())
output.append('\n').append(desc);
break;
@@ -68,22 +65,20 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
if (!TestResult::isDirectParentOf(other, needsIntermediate))
return false;
- if (result() == Result::MessageDisabledTests)
- return false;
const GTestResult *gtOther = static_cast<const GTestResult *>(other);
- if (m_testSetName == gtOther->m_testSetName) {
- const Result::Type otherResult = other->result();
- if (otherResult == Result::MessageInternal || otherResult == Result::MessageLocation)
- return result() != Result::MessageInternal && result() != Result::MessageLocation;
+ if (m_testCaseName == gtOther->m_testCaseName) {
+ const ResultType otherResult = other->result();
+ if (otherResult == ResultType::MessageInternal || otherResult == ResultType::MessageLocation)
+ return result() != ResultType::MessageInternal && result() != ResultType::MessageLocation;
}
if (m_iteration != gtOther->m_iteration)
return false;
- return isTest() && gtOther->isTestSet();
+ return isTestSuite() && gtOther->isTestCase();
}
static QString normalizeName(const QString &name)
{
- static QRegExp parameterIndex("/\\d+");
+ static QRegularExpression parameterIndex("/\\d+");
QString nameWithoutParameterIndices = name;
nameWithoutParameterIndices.remove(parameterIndex);
@@ -117,24 +112,24 @@ bool GTestResult::matches(const TestTreeItem *treeItem) const
if (treeItem->proFile() != m_projectFile)
return false;
- if (isTest())
- return matchesTestCase(treeItem);
+ if (isTestSuite())
+ return matchesTestSuite(treeItem);
- return matchesTestFunctionOrSet(treeItem);
+ return matchesTestCase(treeItem);
}
-bool GTestResult::matchesTestFunctionOrSet(const TestTreeItem *treeItem) const
+bool GTestResult::matchesTestCase(const TestTreeItem *treeItem) const
{
- if (treeItem->type() != TestTreeItem::TestFunctionOrSet)
+ if (treeItem->type() != TestTreeItem::TestCase)
return false;
- const QString testItemTestSet = treeItem->parentItem()->name() + '.' + treeItem->name();
- return testItemTestSet == normalizeName(m_testSetName);
+ const QString testItemTestCase = treeItem->parentItem()->name() + '.' + treeItem->name();
+ return testItemTestCase == normalizeName(m_testCaseName);
}
-bool GTestResult::matchesTestCase(const TestTreeItem *treeItem) const
+bool GTestResult::matchesTestSuite(const TestTreeItem *treeItem) const
{
- if (treeItem->type() != TestTreeItem::TestCase)
+ if (treeItem->type() != TestTreeItem::TestSuite)
return false;
return treeItem->name() == normalizeTestName(name());
diff --git a/src/plugins/autotest/gtest/gtestresult.h b/src/plugins/autotest/gtest/gtestresult.h
index 9e2d2557d8..a792213327 100644
--- a/src/plugins/autotest/gtest/gtestresult.h
+++ b/src/plugins/autotest/gtest/gtestresult.h
@@ -33,24 +33,23 @@ namespace Internal {
class GTestResult : public TestResult
{
public:
- explicit GTestResult(const QString &projectFile, const QString &name = QString());
GTestResult(const QString &id, const QString &projectFile, const QString &name);
const QString outputString(bool selected) const override;
- void setTestSetName(const QString &testSetName) { m_testSetName = testSetName; }
+ void setTestCaseName(const QString &testSetName) { m_testCaseName = testSetName; }
void setIteration(int iteration) { m_iteration = iteration; }
bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override;
virtual const TestTreeItem *findTestTreeItem() const override;
private:
- bool isTest() const { return m_testSetName.isEmpty(); }
- bool isTestSet() const { return !m_testSetName.isEmpty(); }
+ bool isTestSuite() const { return m_testCaseName.isEmpty(); }
+ bool isTestCase() const { return !m_testCaseName.isEmpty(); }
bool matches(const TestTreeItem *item) const;
- bool matchesTestFunctionOrSet(const TestTreeItem *treeItem) const;
bool matchesTestCase(const TestTreeItem *treeItem) const;
+ bool matchesTestSuite(const TestTreeItem *treeItem) const;
- QString m_testSetName;
+ QString m_testCaseName;
QString m_projectFile;
int m_iteration = 1;
};
diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp
index 335979131a..c344669b3c 100644
--- a/src/plugins/autotest/gtest/gtesttreeitem.cpp
+++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp
@@ -37,7 +37,7 @@
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
-#include <QRegExp>
+#include <QRegularExpression>
namespace Autotest {
namespace Internal {
@@ -71,6 +71,20 @@ TestTreeItem *GTestTreeItem::copyWithoutChildren()
return copied;
}
+static QString wildCardPattern(const QString &original)
+{
+ QString pattern = original;
+ pattern.replace('.', "\\.");
+ pattern.replace('$', "\\$");
+ pattern.replace('(', "\\(").replace(')', "\\)");
+ pattern.replace('[', "\\[").replace(']', "\\]");
+ pattern.replace('{', "\\{").replace('}', "\\}");
+ pattern.replace('+', "\\+");
+ pattern.replace('*', ".*");
+ pattern.replace('?', '.');
+ return pattern;
+}
+
static bool matchesFilter(const QString &filter, const QString &fullTestName)
{
QStringList positive;
@@ -88,13 +102,13 @@ static bool matchesFilter(const QString &filter, const QString &fullTestName)
testName.append('.');
for (const QString &curr : negative) {
- QRegExp regex(curr, Qt::CaseSensitive, QRegExp::Wildcard);
- if (regex.exactMatch(testName))
+ QRegularExpression regex(wildCardPattern(curr));
+ if (regex.match(testName).hasMatch())
return false;
}
for (const QString &curr : positive) {
- QRegExp regex(curr, Qt::CaseSensitive, QRegExp::Wildcard);
- if (regex.exactMatch(testName))
+ QRegularExpression regex(wildCardPattern(curr));
+ if (regex.match(testName).hasMatch())
return true;
}
return positive.isEmpty();
@@ -130,8 +144,8 @@ QVariant GTestTreeItem::data(int column, int role) const
switch (type()) {
case Root:
case GroupNode:
+ case TestSuite:
case TestCase:
- case TestFunctionOrSet:
return checked();
default:
return QVariant();
@@ -153,7 +167,7 @@ TestConfiguration *GTestTreeItem::testConfiguration() const
GTestConfiguration *config = nullptr;
switch (type()) {
- case TestCase: {
+ case TestSuite: {
const QString &testSpecifier = gtestFilter(state()).arg(name()).arg('*');
if (int count = childCount()) {
config = new GTestConfiguration;
@@ -164,7 +178,7 @@ TestConfiguration *GTestTreeItem::testConfiguration() const
}
break;
}
- case TestFunctionOrSet: {
+ case TestCase: {
GTestTreeItem *parent = static_cast<GTestTreeItem *>(parentItem());
if (!parent)
return nullptr;
@@ -191,7 +205,7 @@ TestConfiguration *GTestTreeItem::debugConfiguration() const
return config;
}
-struct TestCases
+struct GTestCases
{
QStringList filters;
int testSetCount = 0;
@@ -199,7 +213,7 @@ struct TestCases
};
static void collectTestInfo(const GTestTreeItem *item,
- QHash<QString, TestCases> &testCasesForProFile,
+ QHash<QString, GTestCases> &testCasesForProFile,
bool ignoreCheckState)
{
QTC_ASSERT(item, return);
@@ -212,7 +226,7 @@ static void collectTestInfo(const GTestTreeItem *item,
}
const int childCount = item->childCount();
QTC_ASSERT(childCount != 0, return);
- QTC_ASSERT(item->type() == TestTreeItem::TestCase, return);
+ QTC_ASSERT(item->type() == TestTreeItem::TestSuite, return);
if (ignoreCheckState || item->checked() == Qt::Checked) {
const QString &projectFile = item->childAt(0)->proFile();
testCasesForProFile[projectFile].filters.append(
@@ -221,7 +235,7 @@ static void collectTestInfo(const GTestTreeItem *item,
testCasesForProFile[projectFile].internalTargets.unite(item->internalTargets());
} else if (item->checked() == Qt::PartiallyChecked) {
item->forFirstLevelChildren([&testCasesForProFile, item](TestTreeItem *child){
- QTC_ASSERT(child->type() == TestTreeItem::TestFunctionOrSet, return);
+ QTC_ASSERT(child->type() == TestTreeItem::TestCase, return);
if (child->checked() == Qt::Checked) {
testCasesForProFile[child->proFile()].filters.append(
gtestFilter(item->state()).arg(item->name()).arg(child->name()));
@@ -239,7 +253,7 @@ QList<TestConfiguration *> GTestTreeItem::getTestConfigurations(bool ignoreCheck
if (!project || type() != Root)
return result;
- QHash<QString, TestCases> testCasesForProFile;
+ QHash<QString, GTestCases> testCasesForProFile;
for (int row = 0, count = childCount(); row < count; ++row) {
auto child = static_cast<const GTestTreeItem *>(childAt(row));
collectTestInfo(child, testCasesForProFile, ignoreCheckState);
@@ -271,21 +285,21 @@ QList<TestConfiguration *> GTestTreeItem::getSelectedTestConfigurations() const
return getTestConfigurations(false);
}
-QList<TestConfiguration *> GTestTreeItem::getTestConfigurationsForFile(const Utils::FileName &fileName) const
+QList<TestConfiguration *> GTestTreeItem::getTestConfigurationsForFile(const Utils::FilePath &fileName) const
{
QList<TestConfiguration *> result;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project || type() != Root)
return result;
- QHash<QString, TestCases> testCases;
+ QHash<QString, GTestCases> testCases;
const QString &file = fileName.toString();
forAllChildren([&testCases, &file](TestTreeItem *node) {
- if (node->type() == Type::TestFunctionOrSet && node->filePath() == file) {
+ if (node->type() == Type::TestCase && node->filePath() == file) {
QTC_ASSERT(node->parentItem(), return);
const GTestTreeItem *testCase = static_cast<GTestTreeItem *>(node->parentItem());
- QTC_ASSERT(testCase->type() == Type::TestCase, return);
- TestCases &cases = testCases[testCase->proFile()];
+ QTC_ASSERT(testCase->type() == Type::TestSuite, return);
+ GTestCases &cases = testCases[testCase->proFile()];
cases.filters.append(
gtestFilter(testCase->state()).arg(testCase->name(), node->name()));
cases.internalTargets.unite(node->internalTargets());
@@ -351,7 +365,7 @@ TestTreeItem *GTestTreeItem::find(const TestParseResult *result)
return findChildByNameStateAndFile(parseResult->name, states, parseResult->proFile);
case GroupNode:
return findChildByNameStateAndFile(parseResult->name, states, parseResult->proFile);
- case TestCase:
+ case TestSuite:
return findChildByNameAndFile(result->name, result->fileName);
default:
return nullptr;
@@ -367,7 +381,7 @@ TestTreeItem *GTestTreeItem::findChild(const TestTreeItem *other)
TestTreeItem *result = nullptr;
if (otherType == GroupNode) {
result = findChildByNameAndFile(other->name(), other->filePath());
- } else if (otherType == TestCase) {
+ } else if (otherType == TestSuite) {
auto gtOther = static_cast<const GTestTreeItem *>(other);
result = findChildByNameStateAndFile(gtOther->name(), gtOther->state(),
gtOther->proFile());
@@ -376,12 +390,12 @@ TestTreeItem *GTestTreeItem::findChild(const TestTreeItem *other)
}
case GroupNode: {
auto gtOther = static_cast<const GTestTreeItem *>(other);
- return otherType == TestCase
+ return otherType == TestSuite
? findChildByNameStateAndFile(gtOther->name(), gtOther->state(), gtOther->proFile())
: nullptr;
}
- case TestCase:
- return otherType == TestFunctionOrSet
+ case TestSuite:
+ return otherType == TestCase
? findChildByNameAndFile(other->name(), other->filePath())
: nullptr;
default:
@@ -394,7 +408,7 @@ bool GTestTreeItem::modify(const TestParseResult *result)
QTC_ASSERT(result, return false);
switch (type()) {
- case TestFunctionOrSet:
+ case TestCase:
return modifyTestSetContent(static_cast<const GTestParseResult *>(result));
default:
return false;
@@ -489,11 +503,11 @@ bool GTestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
return QFileInfo(other->filePath()).absolutePath() == filePath();
} else { // GTestFilter
QString fullName;
- if (other->type() == TestCase) {
+ if (other->type() == TestSuite) {
fullName = other->name();
if (other->childCount())
fullName += '.' + other->childAt(0)->name();
- } else if (other->type() == TestFunctionOrSet) {
+ } else if (other->type() == TestCase) {
QTC_ASSERT(other->parentItem(), return false);
fullName = other->parentItem()->name() + '.' + other->name();
} else if (other->type() == GroupNode) { // can happen on a rebuild if only filter changes
@@ -511,12 +525,12 @@ bool GTestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
bool GTestTreeItem::isGroupable() const
{
- return type() == TestCase;
+ return type() == TestSuite;
}
TestTreeItem *GTestTreeItem::applyFilters()
{
- if (type() != TestCase)
+ if (type() != TestSuite)
return nullptr;
if (GTestFramework::groupMode() != GTest::Constants::GTestFilter)
@@ -540,5 +554,10 @@ TestTreeItem *GTestTreeItem::applyFilters()
return filtered;
}
+bool GTestTreeItem::shouldBeAddedAfterFiltering() const
+{
+ return type() == TestTreeItem::TestCase || childCount();
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/gtest/gtesttreeitem.h b/src/plugins/autotest/gtest/gtesttreeitem.h
index 8f1300007f..3b93116ffc 100644
--- a/src/plugins/autotest/gtest/gtesttreeitem.h
+++ b/src/plugins/autotest/gtest/gtesttreeitem.h
@@ -57,7 +57,7 @@ public:
TestConfiguration *debugConfiguration() const override;
QList<TestConfiguration *> getAllTestConfigurations() const override;
QList<TestConfiguration *> getSelectedTestConfigurations() const override;
- QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FileName &fileName) const override;
+ QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FilePath &fileName) const override;
TestTreeItem *find(const TestParseResult *result) override;
TestTreeItem *findChild(const TestTreeItem *other) override;
bool modify(const TestParseResult *result) override;
@@ -74,6 +74,7 @@ public:
bool isGroupNodeFor(const TestTreeItem *other) const override;
bool isGroupable() const override;
TestTreeItem *applyFilters() override;
+ bool shouldBeAddedAfterFiltering() const override;
private:
bool modifyTestSetContent(const GTestParseResult *result);
QList<TestConfiguration *> getTestConfigurations(bool ignoreCheckState) const;
diff --git a/src/plugins/autotest/gtest/gtestvisitors.cpp b/src/plugins/autotest/gtest/gtestvisitors.cpp
index 2cb8a70c31..f7104ff93d 100644
--- a/src/plugins/autotest/gtest/gtestvisitors.cpp
+++ b/src/plugins/autotest/gtest/gtestvisitors.cpp
@@ -78,7 +78,7 @@ bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast)
locationAndType.m_name = testName;
locationAndType.m_line = line;
locationAndType.m_column = column - 1;
- locationAndType.m_type = TestTreeItem::TestFunctionOrSet;
+ locationAndType.m_type = TestTreeItem::TestCase;
locationAndType.m_state = disabled ? GTestTreeItem::Disabled
: GTestTreeItem::Enabled;
GTestCaseSpec spec;
diff --git a/src/plugins/autotest/images/data@2x.png b/src/plugins/autotest/images/data@2x.png
new file mode 100644
index 0000000000..26f71a9ad0
--- /dev/null
+++ b/src/plugins/autotest/images/data@2x.png
Binary files differ
diff --git a/src/plugins/autotest/images/suite.png b/src/plugins/autotest/images/suite.png
new file mode 100644
index 0000000000..91fc50bf32
--- /dev/null
+++ b/src/plugins/autotest/images/suite.png
Binary files differ
diff --git a/src/plugins/autotest/images/suite@2x.png b/src/plugins/autotest/images/suite@2x.png
new file mode 100644
index 0000000000..958480af60
--- /dev/null
+++ b/src/plugins/autotest/images/suite@2x.png
Binary files differ
diff --git a/src/plugins/autotest/itestparser.cpp b/src/plugins/autotest/itestparser.cpp
index 9d06320322..b7e1f15245 100644
--- a/src/plugins/autotest/itestparser.cpp
+++ b/src/plugins/autotest/itestparser.cpp
@@ -78,5 +78,10 @@ void CppParser::release()
m_workingCopy = CppTools::WorkingCopy();
}
+CPlusPlus::Document::Ptr CppParser::document(const QString &fileName)
+{
+ return selectedForBuilding(fileName) ? m_cppSnapshot.document(fileName) : nullptr;
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/itestparser.h b/src/plugins/autotest/itestparser.h
index b79b3c131b..b69b23b253 100644
--- a/src/plugins/autotest/itestparser.h
+++ b/src/plugins/autotest/itestparser.h
@@ -81,6 +81,8 @@ public:
static QByteArray getFileContent(const QString &filePath);
void release() override;
+ CPlusPlus::Document::Ptr document(const QString &fileName);
+
protected:
CPlusPlus::Snapshot m_cppSnapshot;
CppTools::WorkingCopy m_workingCopy;
diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp
index a74c24dccd..d71fd65509 100644
--- a/src/plugins/autotest/qtest/qttestoutputreader.cpp
+++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp
@@ -34,6 +34,8 @@
#include <QFileInfo>
#include <QRegularExpression>
+#include <cctype>
+
namespace Autotest {
namespace Internal {
@@ -188,6 +190,15 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
if (m_className.isEmpty() && outputLine.trimmed().isEmpty())
return;
+ if (m_expectTag) {
+ for (auto ch : outputLine) {
+ if (std::isspace(ch))
+ continue;
+ if (ch != '<')
+ return;
+ break;
+ }
+ }
m_xmlReader.addData(QString::fromUtf8(outputLine));
while (!m_xmlReader.atEnd()) {
if (m_futureInterface.isCanceled())
@@ -221,7 +232,7 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
m_description.clear();
m_duration.clear();
m_file.clear();
- m_result = Result::Invalid;
+ m_result = ResultType::Invalid;
m_lineNumber = 0;
const QXmlStreamAttributes &attributes = m_xmlReader.attributes();
m_result = TestResult::resultFromString(
@@ -237,24 +248,25 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
const int iterations = attributes.value(QStringLiteral("iterations")).toInt();
m_dataTag = attributes.value(QStringLiteral("tag")).toString();
m_description = constructBenchmarkInformation(metric, value, iterations);
- m_result = Result::Benchmark;
+ m_result = ResultType::Benchmark;
} else if (currentTag == QStringLiteral("DataTag")) {
m_cdataMode = DataTag;
} else if (currentTag == QStringLiteral("Description")) {
m_cdataMode = Description;
} else if (currentTag == QStringLiteral("QtVersion")) {
- m_result = Result::MessageInternal;
+ m_result = ResultType::MessageInternal;
m_cdataMode = QtVersion;
} else if (currentTag == QStringLiteral("QtBuild")) {
- m_result = Result::MessageInternal;
+ m_result = ResultType::MessageInternal;
m_cdataMode = QtBuild;
} else if (currentTag == QStringLiteral("QTestVersion")) {
- m_result = Result::MessageInternal;
+ m_result = ResultType::MessageInternal;
m_cdataMode = QTestVersion;
}
break;
}
case QXmlStreamReader::Characters: {
+ m_expectTag = false;
QStringRef text = m_xmlReader.text().trimmed();
if (text.isEmpty())
break;
@@ -285,6 +297,7 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
break;
}
case QXmlStreamReader::EndElement: {
+ m_expectTag = true;
m_cdataMode = None;
const QStringRef currentTag = m_xmlReader.name();
if (currentTag == QStringLiteral("TestFunction")) {
@@ -308,7 +321,7 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
&& m_xmlReader.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
createAndReportResult(tr("XML parsing failed.")
+ QString(" (%1) ").arg(m_xmlReader.error())
- + m_xmlReader.errorString(), Result::MessageFatal);
+ + m_xmlReader.errorString(), ResultType::MessageFatal);
}
break;
}
@@ -317,7 +330,7 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
static QStringList extractFunctionInformation(const QString &testClassName,
const QString &lineWithoutResultType,
- Result::Type resultType)
+ ResultType resultType)
{
static QRegularExpression classInformation("^(.+?)\\((.*?)\\)(.*)$");
QStringList result;
@@ -327,7 +340,7 @@ static QStringList extractFunctionInformation(const QString &testClassName,
QTC_ASSERT(fullQualifiedFunc.startsWith(testClassName + "::"), return result);
fullQualifiedFunc = fullQualifiedFunc.mid(testClassName.length() + 2);
result.append(fullQualifiedFunc);
- if (resultType == Result::Benchmark) { // tag is displayed differently
+ if (resultType == ResultType::Benchmark) { // tag is displayed differently
QString possiblyTag = match.captured(3);
if (!possiblyTag.isEmpty())
possiblyTag = possiblyTag.mid(2, possiblyTag.length() - 4);
@@ -452,7 +465,7 @@ void QtTestOutputReader::processSummaryFinishOutput()
sendFinishMessage(false);
m_className.clear();
m_description.clear();
- m_result = Result::Invalid;
+ m_result = ResultType::Invalid;
m_file.clear();
m_lineNumber = 0;
}
@@ -478,16 +491,16 @@ void QtTestOutputReader::sendCompleteInformation()
void QtTestOutputReader::sendMessageCurrentTest()
{
- TestResultPtr testResult = TestResultPtr(new QtTestResult(m_projectFile, m_testType));
- testResult->setResult(Result::MessageCurrentTest);
+ QtTestResult *testResult = new QtTestResult(QString(), m_projectFile, m_testType, QString());
+ testResult->setResult(ResultType::MessageCurrentTest);
testResult->setDescription(tr("Entering test function %1::%2").arg(m_className, m_testCase));
- reportResult(testResult);
+ reportResult(TestResultPtr(testResult));
}
void QtTestOutputReader::sendStartMessage(bool isFunction)
{
TestResultPtr testResult = createDefaultResult();
- testResult->setResult(Result::MessageTestCaseStart);
+ testResult->setResult(ResultType::TestStart);
testResult->setDescription(isFunction ? tr("Executing test function %1").arg(m_testCase)
: tr("Executing test case %1").arg(m_className));
const TestTreeItem *testItem = testResult->findTestTreeItem();
@@ -501,7 +514,7 @@ void QtTestOutputReader::sendStartMessage(bool isFunction)
void QtTestOutputReader::sendFinishMessage(bool isFunction)
{
TestResultPtr testResult = createDefaultResult();
- testResult->setResult(Result::MessageTestCaseEnd);
+ testResult->setResult(ResultType::TestEnd);
if (!m_duration.isEmpty()) {
testResult->setDescription(isFunction ? tr("Execution took %1 ms.").arg(m_duration)
: tr("Test execution took %1 ms.").arg(m_duration));
@@ -515,15 +528,15 @@ void QtTestOutputReader::sendFinishMessage(bool isFunction)
void QtTestOutputReader::handleAndSendConfigMessage(const QRegularExpressionMatch &config)
{
TestResultPtr testResult = createDefaultResult();
- testResult->setResult(Result::MessageInternal);
+ testResult->setResult(ResultType::MessageInternal);
testResult->setDescription(trQtVersion(config.captured(3)));
reportResult(testResult);
testResult = createDefaultResult();
- testResult->setResult(Result::MessageInternal);
+ testResult->setResult(ResultType::MessageInternal);
testResult->setDescription(trQtBuild(config.captured(2)));
reportResult(testResult);
testResult = createDefaultResult();
- testResult->setResult(Result::MessageInternal);
+ testResult->setResult(ResultType::MessageInternal);
testResult->setDescription(trQtestVersion(config.captured(1)));
reportResult(testResult);
}
diff --git a/src/plugins/autotest/qtest/qttestoutputreader.h b/src/plugins/autotest/qtest/qttestoutputreader.h
index a95a51a662..ce2b35416c 100644
--- a/src/plugins/autotest/qtest/qttestoutputreader.h
+++ b/src/plugins/autotest/qtest/qttestoutputreader.h
@@ -83,7 +83,7 @@ private:
QString m_testCase;
QString m_formerTestCase;
QString m_dataTag;
- Result::Type m_result = Result::Invalid;
+ ResultType m_result = ResultType::Invalid;
QString m_description;
QString m_file;
int m_lineNumber = 0;
@@ -91,7 +91,7 @@ private:
QXmlStreamReader m_xmlReader;
OutputMode m_mode = XML;
TestType m_testType = TestType::QtTest;
-
+ bool m_expectTag = true;
};
} // namespace Internal
diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp
index 234aeca79f..ddedf4dc52 100644
--- a/src/plugins/autotest/qtest/qttestparser.cpp
+++ b/src/plugins/autotest/qtest/qttestparser.cpp
@@ -389,9 +389,9 @@ void QtTestParser::release()
bool QtTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
const QString &fileName)
{
- if (!m_cppSnapshot.contains(fileName) || !selectedForBuilding(fileName))
+ CPlusPlus::Document::Ptr doc = document(fileName);
+ if (doc.isNull())
return false;
- CPlusPlus::Document::Ptr doc = m_cppSnapshot.find(fileName).value();
const QString &oldName = m_testCaseNames.value(fileName);
const QStringList &alternativeFiles = m_alternativeFiles.values(fileName);
if ((!includesQtTest(doc, m_cppSnapshot) || !qtTestLibDefined(fileName)) && oldName.isEmpty())
diff --git a/src/plugins/autotest/qtest/qttestresult.cpp b/src/plugins/autotest/qtest/qttestresult.cpp
index 5cb7fd0402..3e85c36e68 100644
--- a/src/plugins/autotest/qtest/qttestresult.cpp
+++ b/src/plugins/autotest/qtest/qttestresult.cpp
@@ -34,11 +34,6 @@
namespace Autotest {
namespace Internal {
-QtTestResult::QtTestResult(const QString &projectFile, TestType type, const QString &className)
- : TestResult(className), m_projectFile(projectFile), m_type(type)
-{
-}
-
QtTestResult::QtTestResult(const QString &id, const QString &projectFile, TestType type,
const QString &className)
: TestResult(id, className), m_projectFile(projectFile), m_type(type)
@@ -51,12 +46,12 @@ const QString QtTestResult::outputString(bool selected) const
const QString &className = name();
QString output;
switch (result()) {
- case Result::Pass:
- case Result::Fail:
- case Result::ExpectedFail:
- case Result::UnexpectedPass:
- case Result::BlacklistedFail:
- case Result::BlacklistedPass:
+ case ResultType::Pass:
+ case ResultType::Fail:
+ case ResultType::ExpectedFail:
+ case ResultType::UnexpectedPass:
+ case ResultType::BlacklistedFail:
+ case ResultType::BlacklistedPass:
output = className + "::" + m_function;
if (!m_dataTag.isEmpty())
output.append(QString(" (%1)").arg(m_dataTag));
@@ -64,7 +59,7 @@ const QString QtTestResult::outputString(bool selected) const
output.append('\n').append(desc);
}
break;
- case Result::Benchmark:
+ case ResultType::Benchmark:
output = className + "::" + m_function;
if (!m_dataTag.isEmpty())
output.append(QString(" (%1)").arg(m_dataTag));
@@ -89,12 +84,12 @@ bool QtTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermed
return false;
const QtTestResult *qtOther = static_cast<const QtTestResult *>(other);
- if (TestResult::isMessageCaseStart(result())) {
+ if (result() == ResultType::TestStart) {
if (qtOther->isDataTag()) {
if (qtOther->m_function == m_function) {
if (m_dataTag.isEmpty()) {
// avoid adding function's TestCaseEnd to the data tag
- *needsIntermediate = qtOther->result() != Result::MessageTestCaseEnd;
+ *needsIntermediate = qtOther->result() != ResultType::TestEnd;
return true;
}
return qtOther->m_dataTag == m_dataTag;
@@ -164,7 +159,7 @@ bool QtTestResult::matches(const TestTreeItem *item) const
if (item->proFile() != m_projectFile)
return false;
return matchesTestCase(item);
- case TestTreeItem::TestFunctionOrSet:
+ case TestTreeItem::TestFunction:
case TestTreeItem::TestSpecialFunction:
if (!isTestFunction())
return false;
diff --git a/src/plugins/autotest/qtest/qttestresult.h b/src/plugins/autotest/qtest/qttestresult.h
index a0735a90c7..f3f653cd1a 100644
--- a/src/plugins/autotest/qtest/qttestresult.h
+++ b/src/plugins/autotest/qtest/qttestresult.h
@@ -34,7 +34,6 @@ namespace Internal {
class QtTestResult : public TestResult
{
public:
- QtTestResult(const QString &projectFile, TestType type, const QString &className = QString());
QtTestResult(const QString &id, const QString &projectFile, TestType type,
const QString &className);
const QString outputString(bool selected) const override;
diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp
index 3fe96b6f39..7069e29961 100644
--- a/src/plugins/autotest/qtest/qttesttreeitem.cpp
+++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp
@@ -82,7 +82,7 @@ Qt::ItemFlags QtTestTreeItem::flags(int column) const
switch (type()) {
case TestDataTag:
return defaultFlags | Qt::ItemIsUserCheckable;
- case TestFunctionOrSet:
+ case TestFunction:
return defaultFlags | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable;
default:
return TestTreeItem::flags(column);
@@ -93,7 +93,7 @@ bool QtTestTreeItem::canProvideTestConfiguration() const
{
switch (type()) {
case TestCase:
- case TestFunctionOrSet:
+ case TestFunction:
case TestDataTag:
return true;
default:
@@ -119,7 +119,7 @@ TestConfiguration *QtTestTreeItem::testConfiguration() const
config->setProjectFile(proFile());
config->setProject(project);
break;
- case TestFunctionOrSet: {
+ case TestFunction: {
TestTreeItem *parent = parentItem();
config = new QtTestConfiguration();
config->setTestCases(QStringList(name()));
@@ -234,7 +234,7 @@ QList<TestConfiguration *> QtTestTreeItem::getSelectedTestConfigurations() const
return result;
}
-QList<TestConfiguration *> QtTestTreeItem::getTestConfigurationsForFile(const Utils::FileName &fileName) const
+QList<TestConfiguration *> QtTestTreeItem::getTestConfigurationsForFile(const Utils::FilePath &fileName) const
{
QList<TestConfiguration *> result;
@@ -245,7 +245,7 @@ QList<TestConfiguration *> QtTestTreeItem::getTestConfigurationsForFile(const Ut
QHash<TestTreeItem *, QStringList> testFunctions;
const QString &file = fileName.toString();
forAllChildren([&testFunctions, &file](TestTreeItem *node) {
- if (node->type() == Type::TestFunctionOrSet && node->filePath() == file) {
+ if (node->type() == Type::TestFunction && node->filePath() == file) {
QTC_ASSERT(node->parentItem(), return);
TestTreeItem *testCase = node->parentItem();
QTC_ASSERT(testCase->type() == Type::TestCase, return);
@@ -287,7 +287,7 @@ TestTreeItem *QtTestTreeItem::find(const TestParseResult *result)
const QtTestParseResult *qtResult = static_cast<const QtTestParseResult *>(result);
return findChildByNameAndInheritance(qtResult->displayName, qtResult->inherited());
}
- case TestFunctionOrSet:
+ case TestFunction:
case TestDataFunction:
case TestSpecialFunction:
return findChildByName(result->name);
@@ -306,12 +306,12 @@ TestTreeItem *QtTestTreeItem::findChild(const TestTreeItem *other)
case GroupNode:
return otherType == TestCase ? findChildByFile(other->filePath()) : nullptr;
case TestCase: {
- if (otherType != TestFunctionOrSet && otherType != TestDataFunction && otherType != TestSpecialFunction)
+ if (otherType != TestFunction && otherType != TestDataFunction && otherType != TestSpecialFunction)
return nullptr;
auto qtOther = static_cast<const QtTestTreeItem *>(other);
return findChildByNameAndInheritance(other->filePath(), qtOther->inherited());
}
- case TestFunctionOrSet:
+ case TestFunction:
case TestDataFunction:
case TestSpecialFunction:
return otherType == TestDataTag ? findChildByName(other->name()) : nullptr;
@@ -326,8 +326,8 @@ bool QtTestTreeItem::modify(const TestParseResult *result)
switch (type()) {
case TestCase:
- return modifyTestCaseContent(result);
- case TestFunctionOrSet:
+ return modifyTestCaseOrSuiteContent(result);
+ case TestFunction:
case TestDataFunction:
case TestSpecialFunction:
return modifyTestFunctionContent(result);
diff --git a/src/plugins/autotest/qtest/qttesttreeitem.h b/src/plugins/autotest/qtest/qttesttreeitem.h
index 3c7f9c4bd7..97ad853580 100644
--- a/src/plugins/autotest/qtest/qttesttreeitem.h
+++ b/src/plugins/autotest/qtest/qttesttreeitem.h
@@ -45,7 +45,7 @@ public:
TestConfiguration *debugConfiguration() const override;
QList<TestConfiguration *> getAllTestConfigurations() const override;
QList<TestConfiguration *> getSelectedTestConfigurations() const override;
- QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FileName &fileName) const override;
+ QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FilePath &fileName) const override;
TestTreeItem *find(const TestParseResult *result) override;
TestTreeItem *findChild(const TestTreeItem *other) override;
bool modify(const TestParseResult *result) override;
diff --git a/src/plugins/autotest/qtest/qttestvisitors.cpp b/src/plugins/autotest/qtest/qttestvisitors.cpp
index b6d6992e2d..58a69f2dbf 100644
--- a/src/plugins/autotest/qtest/qttestvisitors.cpp
+++ b/src/plugins/autotest/qtest/qttestvisitors.cpp
@@ -82,7 +82,7 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol)
else if (name.endsWith("_data"))
locationAndType.m_type = TestTreeItem::TestDataFunction;
else
- locationAndType.m_type = TestTreeItem::TestFunctionOrSet;
+ locationAndType.m_type = TestTreeItem::TestFunction;
locationAndType.m_inherited = m_inherited;
m_privSlots.insert(className + "::" + name, locationAndType);
}
diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp
index c4f7e7963a..2542325510 100644
--- a/src/plugins/autotest/quick/quicktestparser.cpp
+++ b/src/plugins/autotest/quick/quicktestparser.cpp
@@ -144,7 +144,7 @@ QList<QmlJS::Document::Ptr> QuickTestParser::scanDirectoryForQuickTestQmlFiles(c
// make sure even files not listed in pro file are available inside the snapshot
QFutureInterface<void> future;
QmlJS::PathsAndLanguages paths;
- paths.maybeInsert(Utils::FileName::fromString(srcDir), QmlJS::Dialect::Qml);
+ paths.maybeInsert(Utils::FilePath::fromString(srcDir), QmlJS::Dialect::Qml);
QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), paths, qmlJsMM,
false /*emitDocumentChanges*/, false /*onlyTheLib*/, true /*forceRescan*/ );
@@ -276,7 +276,7 @@ void QuickTestParser::handleDirectoryChanged(const QString &directory)
});
if (timestampChanged) {
QmlJS::PathsAndLanguages paths;
- paths.maybeInsert(Utils::FileName::fromString(directory), QmlJS::Dialect::Qml);
+ paths.maybeInsert(Utils::FilePath::fromString(directory), QmlJS::Dialect::Qml);
QFutureInterface<void> future;
QmlJS::ModelManagerInterface *qmlJsMM = QmlJS::ModelManagerInterface::instance();
QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), paths, qmlJsMM,
diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp
index 6bc57a0e38..52d3796463 100644
--- a/src/plugins/autotest/quick/quicktesttreeitem.cpp
+++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp
@@ -65,7 +65,7 @@ QVariant QuickTestTreeItem::data(int column, int role) const
return QVariant();
case TestCase:
return name().isEmpty() ? QVariant() : checked();
- case TestFunctionOrSet:
+ case TestFunction:
return (parentItem() && !parentItem()->name().isEmpty()) ? checked() : QVariant();
default:
return checked();
@@ -78,7 +78,7 @@ QVariant QuickTestTreeItem::data(int column, int role) const
return true;
case TestCase:
return name().isEmpty();
- case TestFunctionOrSet:
+ case TestFunction:
return parentItem() ? parentItem()->name().isEmpty() : false;
default:
return false;
@@ -97,7 +97,7 @@ Qt::ItemFlags QuickTestTreeItem::flags(int column) const
if (name().isEmpty())
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
- case TestFunctionOrSet:
+ case TestFunction:
if (parentItem()->name().isEmpty())
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
break;
@@ -111,7 +111,7 @@ bool QuickTestTreeItem::canProvideTestConfiguration() const
switch (type()) {
case TestCase:
return !name().isEmpty();
- case TestFunctionOrSet:
+ case TestFunction:
return !parentItem()->name().isEmpty();
default:
return false;
@@ -134,7 +134,7 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const
const QString testName = name();
QStringList testFunctions;
forFirstLevelChildren([&testFunctions, &testName](TestTreeItem *child) {
- if (child->type() == TestTreeItem::TestFunctionOrSet)
+ if (child->type() == TestTreeItem::TestFunction)
testFunctions << testName + "::" + child->name();
});
config = new QuickTestConfiguration;
@@ -143,7 +143,7 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const
config->setProject(project);
break;
}
- case TestFunctionOrSet: {
+ case TestFunction: {
TestTreeItem *parent = parentItem();
QStringList testFunction(parent->name() + "::" + name());
config = new QuickTestConfiguration;
@@ -177,7 +177,7 @@ static void testConfigurationFromCheckState(const TestTreeItem *item,
const QString testName = item->name();
QStringList testFunctions;
item->forFirstLevelChildren([&testFunctions, &testName](TestTreeItem *child) {
- if (child->checked() == Qt::Checked && child->type() == TestTreeItem::TestFunctionOrSet)
+ if (child->checked() == Qt::Checked && child->type() == TestTreeItem::TestFunction)
testFunctions << testName + "::" + child->name();
});
if (foundProFiles.contains(item->proFile())) {
@@ -280,7 +280,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
return result;
}
-QList<TestConfiguration *> QuickTestTreeItem::getTestConfigurationsForFile(const Utils::FileName &fileName) const
+QList<TestConfiguration *> QuickTestTreeItem::getTestConfigurationsForFile(const Utils::FilePath &fileName) const
{
QList<TestConfiguration *> result;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
@@ -290,7 +290,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getTestConfigurationsForFile(const
QHash<TestTreeItem *, QStringList> testFunctions;
const QString &file = fileName.toString();
forAllChildren([&testFunctions, &file](TestTreeItem *node) {
- if (node->type() == Type::TestFunctionOrSet && node->filePath() == file) {
+ if (node->type() == Type::TestFunction && node->filePath() == file) {
QTC_ASSERT(node->parentItem(), return);
TestTreeItem *testCase = node->parentItem();
QTC_ASSERT(testCase->type() == Type::TestCase, return);
@@ -349,7 +349,7 @@ TestTreeItem *QuickTestTreeItem::findChild(const TestTreeItem *other)
case GroupNode:
return findChildByFileAndType(other->filePath(), otherType);
case TestCase:
- if (otherType != TestFunctionOrSet && otherType != TestDataFunction && otherType != TestSpecialFunction)
+ if (otherType != TestFunction && otherType != TestDataFunction && otherType != TestSpecialFunction)
return nullptr;
return name().isEmpty() ? findChildByNameAndFile(other->name(), other->filePath())
: findChildByName(other->name());
@@ -364,8 +364,8 @@ bool QuickTestTreeItem::modify(const TestParseResult *result)
switch (type()) {
case TestCase:
- return result->name.isEmpty() ? false : modifyTestCaseContent(result);
- case TestFunctionOrSet:
+ return result->name.isEmpty() ? false : modifyTestCaseOrSuiteContent(result);
+ case TestFunction:
case TestDataFunction:
case TestSpecialFunction:
return name().isEmpty() ? modifyLineAndColumn(result)
diff --git a/src/plugins/autotest/quick/quicktesttreeitem.h b/src/plugins/autotest/quick/quicktesttreeitem.h
index b1d49065f3..b9f06d6a07 100644
--- a/src/plugins/autotest/quick/quicktesttreeitem.h
+++ b/src/plugins/autotest/quick/quicktesttreeitem.h
@@ -45,7 +45,7 @@ public:
TestConfiguration *debugConfiguration() const override;
QList<TestConfiguration *> getAllTestConfigurations() const override;
QList<TestConfiguration *> getSelectedTestConfigurations() const override;
- QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FileName &fileName) const override;
+ QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FilePath &fileName) const override;
TestTreeItem *find(const TestParseResult *result) override;
TestTreeItem *findChild(const TestTreeItem *other) override;
bool modify(const TestParseResult *result) override;
diff --git a/src/plugins/autotest/quick/quicktestvisitors.cpp b/src/plugins/autotest/quick/quicktestvisitors.cpp
index cbc5f9b2a2..f9934e735d 100644
--- a/src/plugins/autotest/quick/quicktestvisitors.cpp
+++ b/src/plugins/autotest/quick/quicktestvisitors.cpp
@@ -146,7 +146,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
else if (name.endsWith("_data"))
locationAndType.m_type = TestTreeItem::TestDataFunction;
else
- locationAndType.m_type = TestTreeItem::TestFunctionOrSet;
+ locationAndType.m_type = TestTreeItem::TestFunction;
m_testFunctions.insert(name.toString(), locationAndType);
}
diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp
index 1449816fc0..c944073dc7 100644
--- a/src/plugins/autotest/testcodeparser.cpp
+++ b/src/plugins/autotest/testcodeparser.cpp
@@ -171,28 +171,6 @@ void TestCodeParser::updateTestTree(ITestParser *parser)
scanForTests(QStringList(), parser);
}
-static QStringList filterFiles(const QString &projectDir, const QStringList &files)
-{
- const QSharedPointer<TestSettings> &settings = AutotestPlugin::settings();
- const QSet<QString> &filters = settings->whiteListFilters.toSet(); // avoid duplicates
- if (!settings->filterScan || filters.isEmpty())
- return files;
- QStringList finalResult;
- for (const QString &file : files) {
- // apply filter only below project directory if file is part of a project
- const QString &fileToProcess = file.startsWith(projectDir)
- ? file.mid(projectDir.size())
- : file;
- for (const QString &filter : filters) {
- if (fileToProcess.contains(filter)) {
- finalResult.push_back(file);
- break;
- }
- }
- }
- return finalResult;
-}
-
// used internally to indicate a parse that failed due to having triggered a parse for a file that
// is not (yet) part of the CppModelManager's snapshot
static bool parsingHasFailed;
@@ -208,7 +186,7 @@ void TestCodeParser::onDocumentUpdated(const QString &fileName, bool isQmlFile)
if (!project)
return;
// Quick tests: qml files aren't necessarily listed inside project files
- if (!isQmlFile && !project->isKnownFile(Utils::FileName::fromString(fileName)))
+ if (!isQmlFile && !project->isKnownFile(Utils::FilePath::fromString(fileName)))
return;
scanForTests(QStringList(fileName));
@@ -343,7 +321,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars
return;
QStringList list;
if (isFullParse) {
- list = Utils::transform(project->files(Project::SourceFiles), &Utils::FileName::toString);
+ list = Utils::transform(project->files(Project::SourceFiles), &Utils::FilePath::toString);
if (list.isEmpty()) {
// at least project file should be there, but might happen if parsing current project
// takes too long, especially when opening sessions holding multiple projects
@@ -379,7 +357,6 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars
m_model->markForRemoval(filePath);
}
- list = filterFiles(project->projectDirectory().toString(), list);
if (list.isEmpty()) {
if (isFullParse) {
Core::MessageManager::instance()->write(
diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp
index 1f9b73e77c..6f7078eefb 100644
--- a/src/plugins/autotest/testconfiguration.cpp
+++ b/src/plugins/autotest/testconfiguration.cpp
@@ -53,11 +53,10 @@ TestConfiguration::~TestConfiguration()
m_testCases.clear();
}
-static bool isLocal(RunConfiguration *runConfiguration)
+static bool isLocal(Target *target)
{
- Target *target = runConfiguration ? runConfiguration->target() : nullptr;
Kit *kit = target ? target->kit() : nullptr;
- return DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+ return DeviceTypeKitAspect::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
}
static QString ensureExeEnding(const QString& file)
@@ -93,8 +92,7 @@ void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguratio
m_runnable = rc->runnable();
m_displayName = rc->displayName();
- const QString buildKey = rc->buildKey();
- BuildTargetInfo targetInfo = target->applicationTargets().buildTargetInfo(buildKey);
+ BuildTargetInfo targetInfo = rc->buildTargetInfo();
if (!targetInfo.targetFilePath.isEmpty())
m_runnable.executable = ensureExeEnding(targetInfo.targetFilePath.toString());
@@ -142,7 +140,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
const QSet<QString> buildSystemTargets = m_buildTargets;
qCDebug(LOG) << "BuildSystemTargets\n " << buildSystemTargets;
BuildTargetInfo targetInfo
- = Utils::findOrDefault(target->applicationTargets().list,
+ = Utils::findOrDefault(target->applicationTargets(),
[&buildSystemTargets] (const BuildTargetInfo &bti) {
return buildSystemTargets.contains(bti.buildKey);
});
@@ -150,7 +148,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
// there would be no BuildTargetInfo that could match
if (targetInfo.targetFilePath.isEmpty()) {
qCDebug(LOG) << "BuildTargetInfos";
- const QList<BuildTargetInfo> buildTargets = target->applicationTargets().list;
+ const QList<BuildTargetInfo> buildTargets = target->applicationTargets();
// if there is only one build target just use it (but be honest that we're deducing)
if (buildTargets.size() == 1) {
targetInfo = buildTargets.first();
@@ -184,7 +182,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
qCDebug(LOG) << "Iterating run configurations";
for (RunConfiguration *runConfig : target->runConfigurations()) {
qCDebug(LOG) << "RunConfiguration" << runConfig->id();
- if (!isLocal(runConfig)) { // TODO add device support
+ if (!isLocal(target)) { // TODO add device support
qCDebug(LOG) << " Skipped as not being local";
continue;
}
@@ -205,7 +203,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
m_runnable.executable = currentExecutable;
m_displayName = runConfig->displayName();
if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
- m_runConfig = new TestRunConfiguration(runConfig->target(), this);
+ m_runConfig = new TestRunConfiguration(target, this);
break;
}
}
@@ -220,7 +218,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
qCDebug(LOG) << " Fallback";
// we failed to find a valid runconfiguration - but we've got the executable already
if (auto rc = target->activeRunConfiguration()) {
- if (isLocal(rc)) { // FIXME for now only Desktop support
+ if (isLocal(target)) { // FIXME for now only Desktop support
const Runnable runnable = rc->runnable();
m_runnable.environment = runnable.environment;
m_deducedConfiguration = true;
diff --git a/src/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h
index 929731bce3..fcd778c8ec 100644
--- a/src/plugins/autotest/testconfiguration.h
+++ b/src/plugins/autotest/testconfiguration.h
@@ -28,7 +28,7 @@
#include "autotestconstants.h"
#include <projectexplorer/project.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
#include <QFutureInterface>
diff --git a/src/plugins/autotest/testeditormark.cpp b/src/plugins/autotest/testeditormark.cpp
index 61e53ef4bd..29ca484c9c 100644
--- a/src/plugins/autotest/testeditormark.cpp
+++ b/src/plugins/autotest/testeditormark.cpp
@@ -29,7 +29,7 @@
namespace Autotest {
namespace Internal {
-TestEditorMark::TestEditorMark(QPersistentModelIndex item, const Utils::FileName &file, int line)
+TestEditorMark::TestEditorMark(QPersistentModelIndex item, const Utils::FilePath &file, int line)
: TextEditor::TextMark(file, line, Core::Id(Constants::TASK_MARK_ID)),
m_item(item)
{
diff --git a/src/plugins/autotest/testeditormark.h b/src/plugins/autotest/testeditormark.h
index c84e8efb73..458bb4f0c0 100644
--- a/src/plugins/autotest/testeditormark.h
+++ b/src/plugins/autotest/testeditormark.h
@@ -35,7 +35,7 @@ namespace Internal {
class TestEditorMark : public TextEditor::TextMark
{
public:
- TestEditorMark(QPersistentModelIndex item, const Utils::FileName &file, int line);
+ TestEditorMark(QPersistentModelIndex item, const Utils::FilePath &file, int line);
bool isClickable() const override { return true; }
void clicked() override;
diff --git a/src/plugins/autotest/testnavigationwidget.cpp b/src/plugins/autotest/testnavigationwidget.cpp
index 363fd1a3b4..9899fcc32a 100644
--- a/src/plugins/autotest/testnavigationwidget.cpp
+++ b/src/plugins/autotest/testnavigationwidget.cpp
@@ -197,7 +197,6 @@ QList<QToolButton *> TestNavigationWidget::createToolButtons()
m_filterButton->setIcon(Utils::Icons::FILTER.icon());
m_filterButton->setToolTip(tr("Filter Test Tree"));
m_filterButton->setProperty("noArrow", true);
- m_filterButton->setAutoRaise(true);
m_filterButton->setPopupMode(QToolButton::InstantPopup);
m_filterMenu = new QMenu(m_filterButton);
initializeFilterMenu();
@@ -237,7 +236,7 @@ void TestNavigationWidget::onItemActivated(const QModelIndex &index)
void TestNavigationWidget::onSortClicked()
{
if (m_sortAlphabetically) {
- m_sort->setIcon(Icons::SORT_ALPHABETICALLY.icon());
+ m_sort->setIcon(Utils::Icons::SORT_ALPHABETICALLY_TOOLBAR.icon());
m_sort->setToolTip(tr("Sort Alphabetically"));
m_sortFilterModel->setSortMode(TestTreeItem::Naturally);
} else {
diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp
index ff96d10e79..36da35543b 100644
--- a/src/plugins/autotest/testoutputreader.cpp
+++ b/src/plugins/autotest/testoutputreader.cpp
@@ -74,11 +74,11 @@ void TestOutputReader::reportCrash()
{
TestResultPtr result = createDefaultResult();
result->setDescription(tr("Test executable crashed."));
- result->setResult(Result::MessageFatal);
+ result->setResult(ResultType::MessageFatal);
m_futureInterface.reportResult(result);
}
-void TestOutputReader::createAndReportResult(const QString &message, Result::Type type)
+void TestOutputReader::createAndReportResult(const QString &message, ResultType type)
{
TestResultPtr result = createDefaultResult();
result->setDescription(message);
diff --git a/src/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h
index 7c1f7d0f13..87216a2570 100644
--- a/src/plugins/autotest/testoutputreader.h
+++ b/src/plugins/autotest/testoutputreader.h
@@ -45,8 +45,11 @@ public:
void processOutput(const QByteArray &output);
virtual void processStdError(const QByteArray &outputLineWithNewLine);
void reportCrash();
- void createAndReportResult(const QString &message, Result::Type type);
+ void createAndReportResult(const QString &message, ResultType type);
bool hadValidOutput() const { return m_hadValidOutput; }
+ int disabledTests() const { return m_disabled; }
+ bool hasSummary() const { return !m_summary.isEmpty(); }
+ QHash<ResultType, int> summary() const { return m_summary; }
void setId(const QString &id) { m_id = id; }
QString id() const { return m_id; }
@@ -63,6 +66,8 @@ protected:
QProcess *m_testApplication; // not owned
QString m_buildDir;
QString m_id;
+ QHash<ResultType, int> m_summary;
+ int m_disabled = -1;
private:
bool m_hadValidOutput = false;
};
diff --git a/src/plugins/autotest/testresult.cpp b/src/plugins/autotest/testresult.cpp
index ea4261a453..e9ff367ef9 100644
--- a/src/plugins/autotest/testresult.cpp
+++ b/src/plugins/autotest/testresult.cpp
@@ -31,22 +31,6 @@
namespace Autotest {
namespace Internal {
-FaultyTestResult::FaultyTestResult(Result::Type result, const QString &description)
-{
- setResult(result);
- setDescription(description);
-}
-
-TestResult::TestResult()
- : TestResult(QString())
-{
-}
-
-TestResult::TestResult(const QString &name)
- : m_name(name)
-{
-}
-
TestResult::TestResult(const QString &id, const QString &name)
: m_id(id)
, m_name(name)
@@ -55,7 +39,7 @@ TestResult::TestResult(const QString &id, const QString &name)
const QString TestResult::outputString(bool selected) const
{
- if (m_result == Result::Application)
+ if (m_result == ResultType::Application)
return m_id;
return selected ? m_description : m_description.split('\n').first();
}
@@ -65,138 +49,127 @@ const TestTreeItem *TestResult::findTestTreeItem() const
return nullptr;
}
-Result::Type TestResult::resultFromString(const QString &resultString)
+ResultType TestResult::resultFromString(const QString &resultString)
{
if (resultString == "pass")
- return Result::Pass;
+ return ResultType::Pass;
if (resultString == "fail" || resultString == "fail!")
- return Result::Fail;
+ return ResultType::Fail;
if (resultString == "xfail")
- return Result::ExpectedFail;
+ return ResultType::ExpectedFail;
if (resultString == "xpass")
- return Result::UnexpectedPass;
+ return ResultType::UnexpectedPass;
if (resultString == "skip")
- return Result::Skip;
+ return ResultType::Skip;
if (resultString == "result")
- return Result::Benchmark;
+ return ResultType::Benchmark;
if (resultString == "qdebug")
- return Result::MessageDebug;
+ return ResultType::MessageDebug;
if (resultString == "qinfo" || resultString == "info")
- return Result::MessageInfo;
+ return ResultType::MessageInfo;
if (resultString == "warn" || resultString == "qwarn" || resultString == "warning")
- return Result::MessageWarn;
+ return ResultType::MessageWarn;
if (resultString == "qfatal")
- return Result::MessageFatal;
+ return ResultType::MessageFatal;
if ((resultString == "system") || (resultString == "qsystem"))
- return Result::MessageSystem;
+ return ResultType::MessageSystem;
if (resultString == "bpass")
- return Result::BlacklistedPass;
+ return ResultType::BlacklistedPass;
if (resultString == "bfail")
- return Result::BlacklistedFail;
+ return ResultType::BlacklistedFail;
if (resultString == "bxpass")
- return Result::BlacklistedXPass;
+ return ResultType::BlacklistedXPass;
if (resultString == "bxfail")
- return Result::BlacklistedXFail;
+ return ResultType::BlacklistedXFail;
qDebug("Unexpected test result: %s", qPrintable(resultString));
- return Result::Invalid;
+ return ResultType::Invalid;
}
-Result::Type TestResult::toResultType(int rt)
+ResultType TestResult::toResultType(int rt)
{
- if (rt < Result::FIRST_TYPE || rt > Result::LAST_TYPE)
- return Result::Invalid;
+ if (rt < int(ResultType::FIRST_TYPE) || rt > int(ResultType::LAST_TYPE))
+ return ResultType::Invalid;
- return Result::Type(rt);
+ return ResultType(rt);
}
-QString TestResult::resultToString(const Result::Type type)
+QString TestResult::resultToString(const ResultType type)
{
switch (type) {
- case Result::Pass:
- case Result::MessageTestCaseSuccess:
- case Result::MessageTestCaseSuccessWarn:
+ case ResultType::Pass:
return QString("PASS");
- case Result::Fail:
- case Result::MessageTestCaseFail:
- case Result::MessageTestCaseFailWarn:
+ case ResultType::Fail:
return QString("FAIL");
- case Result::ExpectedFail:
+ case ResultType::ExpectedFail:
return QString("XFAIL");
- case Result::UnexpectedPass:
+ case ResultType::UnexpectedPass:
return QString("XPASS");
- case Result::Skip:
+ case ResultType::Skip:
return QString("SKIP");
- case Result::Benchmark:
+ case ResultType::Benchmark:
return QString("BENCH");
- case Result::MessageDebug:
+ case ResultType::MessageDebug:
return QString("DEBUG");
- case Result::MessageInfo:
+ case ResultType::MessageInfo:
return QString("INFO");
- case Result::MessageWarn:
+ case ResultType::MessageWarn:
return QString("WARN");
- case Result::MessageFatal:
+ case ResultType::MessageFatal:
return QString("FATAL");
- case Result::MessageSystem:
+ case ResultType::MessageSystem:
return QString("SYSTEM");
- case Result::BlacklistedPass:
+ case ResultType::BlacklistedPass:
return QString("BPASS");
- case Result::BlacklistedFail:
+ case ResultType::BlacklistedFail:
return QString("BFAIL");
- case Result::BlacklistedXPass:
+ case ResultType::BlacklistedXPass:
return QString("BXPASS");
- case Result::BlacklistedXFail:
+ case ResultType::BlacklistedXFail:
return QString("BXFAIL");
- case Result::MessageLocation:
- case Result::Application:
+ case ResultType::MessageLocation:
+ case ResultType::Application:
return QString();
default:
- if (type >= Result::INTERNAL_MESSAGES_BEGIN && type <= Result::INTERNAL_MESSAGES_END)
+ if (type >= ResultType::INTERNAL_MESSAGES_BEGIN && type <= ResultType::INTERNAL_MESSAGES_END)
return QString();
return QString("UNKNOWN");
}
}
-QColor TestResult::colorForType(const Result::Type type)
+QColor TestResult::colorForType(const ResultType type)
{
- if (type >= Result::INTERNAL_MESSAGES_BEGIN && type <= Result::INTERNAL_MESSAGES_END)
+ if (type >= ResultType::INTERNAL_MESSAGES_BEGIN && type <= ResultType::INTERNAL_MESSAGES_END)
return QColor("transparent");
Utils::Theme *creatorTheme = Utils::creatorTheme();
switch (type) {
- case Result::Pass:
+ case ResultType::Pass:
return creatorTheme->color(Utils::Theme::OutputPanes_TestPassTextColor);
- case Result::Fail:
+ case ResultType::Fail:
return creatorTheme->color(Utils::Theme::OutputPanes_TestFailTextColor);
- case Result::ExpectedFail:
+ case ResultType::ExpectedFail:
return creatorTheme->color(Utils::Theme::OutputPanes_TestXFailTextColor);
- case Result::UnexpectedPass:
+ case ResultType::UnexpectedPass:
return creatorTheme->color(Utils::Theme::OutputPanes_TestXPassTextColor);
- case Result::Skip:
+ case ResultType::Skip:
return creatorTheme->color(Utils::Theme::OutputPanes_TestSkipTextColor);
- case Result::MessageDebug:
- case Result::MessageInfo:
+ case ResultType::MessageDebug:
+ case ResultType::MessageInfo:
return creatorTheme->color(Utils::Theme::OutputPanes_TestDebugTextColor);
- case Result::MessageWarn:
+ case ResultType::MessageWarn:
return creatorTheme->color(Utils::Theme::OutputPanes_TestWarnTextColor);
- case Result::MessageFatal:
- case Result::MessageSystem:
+ case ResultType::MessageFatal:
+ case ResultType::MessageSystem:
return creatorTheme->color(Utils::Theme::OutputPanes_TestFatalTextColor);
- case Result::BlacklistedPass:
- case Result::BlacklistedFail:
- case Result::BlacklistedXPass:
- case Result::BlacklistedXFail:
+ case ResultType::BlacklistedPass:
+ case ResultType::BlacklistedFail:
+ case ResultType::BlacklistedXPass:
+ case ResultType::BlacklistedXFail:
default:
return creatorTheme->color(Utils::Theme::OutputPanes_StdOutTextColor);
}
}
-bool TestResult::isMessageCaseStart(const Result::Type type)
-{
- return type == Result::MessageTestCaseStart || type == Result::MessageTestCaseSuccess
- || type == Result::MessageTestCaseFail || type == Result::MessageTestCaseSuccessWarn
- || type == Result::MessageTestCaseFailWarn || type == Result::MessageIntermediate;
-}
-
bool TestResult::isDirectParentOf(const TestResult *other, bool * /*needsIntermediate*/) const
{
QTC_ASSERT(other, return false);
diff --git a/src/plugins/autotest/testresult.h b/src/plugins/autotest/testresult.h
index a1e1d2e7bf..84fc2c144a 100644
--- a/src/plugins/autotest/testresult.h
+++ b/src/plugins/autotest/testresult.h
@@ -37,8 +37,8 @@ namespace Internal {
class TestTreeItem;
-namespace Result{
-enum Type {
+enum class ResultType {
+ // result types (have icon, color, short text)
Pass, FIRST_TYPE = Pass,
Fail,
ExpectedFail,
@@ -48,37 +48,40 @@ enum Type {
BlacklistedFail,
BlacklistedXPass,
BlacklistedXFail,
+
+ // special (message) types (have icon, color, short text)
Benchmark,
MessageDebug,
MessageInfo,
MessageWarn,
MessageFatal,
MessageSystem,
- MessageLocation,
+ // special message - get's icon (but no color/short text) from parent
+ MessageLocation,
+ // anything below is an internal message (or a pure message without icon)
MessageInternal, INTERNAL_MESSAGES_BEGIN = MessageInternal,
- MessageDisabledTests,
- MessageTestCaseStart,
- MessageTestCaseSuccess,
- MessageTestCaseSuccessWarn,
- MessageTestCaseFail,
- MessageTestCaseFailWarn,
- MessageTestCaseEnd,
- MessageIntermediate,
+ // start item (get icon/short text depending on children)
+ TestStart,
+ // usually no icon/short text - more or less an indicator (and can contain test duration)
+ TestEnd,
+ // special global (temporary) message
MessageCurrentTest, INTERNAL_MESSAGES_END = MessageCurrentTest,
- Application,
-
- Invalid,
+ Application, // special.. not to be used outside of testresultmodel
+ Invalid, // indicator for unknown result items
LAST_TYPE = Invalid
};
+
+inline uint qHash(const ResultType &result)
+{
+ return QT_PREPEND_NAMESPACE(qHash(int(result)));
}
class TestResult
{
public:
- TestResult();
- explicit TestResult(const QString &name);
+ TestResult() = default;
TestResult(const QString &id, const QString &name);
virtual ~TestResult() {}
@@ -87,7 +90,7 @@ public:
QString id() const { return m_id; }
QString name() const { return m_name; }
- Result::Type result() const { return m_result; }
+ ResultType result() const { return m_result; }
QString description() const { return m_description; }
QString fileName() const { return m_file; }
int line() const { return m_line; }
@@ -95,22 +98,20 @@ public:
void setDescription(const QString &description) { m_description = description; }
void setFileName(const QString &fileName) { m_file = fileName; }
void setLine(int line) { m_line = line; }
- void setResult(Result::Type type) { m_result = type; }
+ void setResult(ResultType type) { m_result = type; }
- static Result::Type resultFromString(const QString &resultString);
- static Result::Type toResultType(int rt);
- static QString resultToString(const Result::Type type);
- static QColor colorForType(const Result::Type type);
- static bool isMessageCaseStart(const Result::Type type);
+ static ResultType resultFromString(const QString &resultString);
+ static ResultType toResultType(int rt);
+ static QString resultToString(const ResultType type);
+ static QColor colorForType(const ResultType type);
virtual bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const;
virtual bool isIntermediateFor(const TestResult *other) const;
virtual TestResult *createIntermediateResultFor(const TestResult *other);
-
private:
QString m_id;
QString m_name;
- Result::Type m_result = Result::Invalid;
+ ResultType m_result = ResultType::Invalid; // the real result..
QString m_description;
QString m_file;
int m_line = 0;
@@ -118,14 +119,8 @@ private:
using TestResultPtr = QSharedPointer<TestResult>;
-class FaultyTestResult : public TestResult
-{
-public:
- FaultyTestResult(Result::Type result, const QString &description);
-};
-
} // namespace Internal
} // namespace Autotest
Q_DECLARE_METATYPE(Autotest::Internal::TestResult)
-Q_DECLARE_METATYPE(Autotest::Internal::Result::Type)
+Q_DECLARE_METATYPE(Autotest::Internal::ResultType)
diff --git a/src/plugins/autotest/testresultdelegate.cpp b/src/plugins/autotest/testresultdelegate.cpp
index d70b6fa39e..f5486149af 100644
--- a/src/plugins/autotest/testresultdelegate.cpp
+++ b/src/plugins/autotest/testresultdelegate.cpp
@@ -40,12 +40,6 @@ namespace Internal {
constexpr int outputLimit = 100000;
-static bool isSummaryItem(Result::Type type)
-{
- return type == Result::MessageTestCaseSuccess || type == Result::MessageTestCaseSuccessWarn
- || type == Result::MessageTestCaseFail || type == Result::MessageTestCaseFailWarn;
-}
-
TestResultDelegate::TestResultDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
@@ -89,12 +83,14 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
painter->drawPixmap(positions.left(), positions.top(),
icon.pixmap(window, QSize(positions.iconSize(), positions.iconSize())));
- QString typeStr = TestResult::resultToString(testResult->result());
+ TestResultItem *item = resultFilterModel->itemForIndex(index);
+ QTC_ASSERT(item, painter->restore(); return);
+ const QString typeStr = item->resultString();
if (selected) {
painter->drawText(positions.typeAreaLeft(), positions.top() + fm.ascent(), typeStr);
} else {
QPen tmp = painter->pen();
- if (isSummaryItem(testResult->result()))
+ if (testResult->result() == ResultType::TestStart)
painter->setPen(opt.palette.mid().color());
else
painter->setPen(TestResult::colorForType(testResult->result()));
diff --git a/src/plugins/autotest/testresultdelegate.h b/src/plugins/autotest/testresultdelegate.h
index 5921ebdc92..a3b2cb7c5f 100644
--- a/src/plugins/autotest/testresultdelegate.h
+++ b/src/plugins/autotest/testresultdelegate.h
@@ -65,7 +65,7 @@ private:
m_maxFileLength = srcModel->maxWidthOfFileName(options.font);
m_maxLineLength = srcModel->maxWidthOfLineNumber(options.font);
m_realFileLength = m_maxFileLength;
- m_typeAreaWidth = QFontMetrics(options.font).width("XXXXXXXX");
+ m_typeAreaWidth = QFontMetrics(options.font).horizontalAdvance("XXXXXXXX");
m_indentation = options.widget ? options.widget->style()->pixelMetric(
QStyle::PM_TreeViewIndentation, &options) : 0;
diff --git a/src/plugins/autotest/testresultmodel.cpp b/src/plugins/autotest/testresultmodel.cpp
index deb6e1dfae..a3c6ec28a8 100644
--- a/src/plugins/autotest/testresultmodel.cpp
+++ b/src/plugins/autotest/testresultmodel.cpp
@@ -23,10 +23,11 @@
**
****************************************************************************/
+#include "testresultmodel.h"
#include "autotesticons.h"
#include "autotestplugin.h"
#include "testresultdelegate.h"
-#include "testresultmodel.h"
+#include "testrunner.h"
#include "testsettings.h"
#include <projectexplorer/projectexplorericons.h>
@@ -45,7 +46,7 @@ TestResultItem::TestResultItem(const TestResultPtr &testResult)
{
}
-static QIcon testResultIcon(Result::Type result) {
+static QIcon testResultIcon(ResultType result) {
const static QIcon icons[] = {
Icons::RESULT_PASS.icon(),
Icons::RESULT_FAIL.icon(),
@@ -62,29 +63,27 @@ static QIcon testResultIcon(Result::Type result) {
Icons::RESULT_MESSAGEWARN.icon(),
Icons::RESULT_MESSAGEFATAL.icon(),
Icons::RESULT_MESSAGEFATAL.icon(), // System gets same handling as Fatal for now
- QIcon(),
- Icons::RESULT_MESSAGEPASSWARN.icon(),
- Icons::RESULT_MESSAGEFAILWARN.icon(),
ProjectExplorer::Icons::DESKTOP_DEVICE.icon(), // for now
}; // provide an icon for unknown??
- if (result < 0 || result >= Result::MessageInternal) {
+ if (result < ResultType::FIRST_TYPE || result >= ResultType::MessageInternal) {
switch (result) {
- case Result::MessageTestCaseSuccess:
- return icons[Result::Pass];
- case Result::MessageTestCaseFail:
- return icons[Result::Fail];
- case Result::MessageTestCaseSuccessWarn:
- return icons[16];
- case Result::MessageTestCaseFailWarn:
- return icons[17];
- case Result::Application:
- return icons[18];
+ case ResultType::Application:
+ return icons[15];
default:
return QIcon();
}
}
- return icons[result];
+ return icons[int(result)];
+}
+
+static QIcon testSummaryIcon(const Utils::optional<TestResultItem::SummaryEvaluation> &summary)
+{
+ if (!summary)
+ return QIcon();
+ if (summary->failed)
+ return summary->warnings ? Icons::RESULT_MESSAGEFAILWARN.icon() : Icons::RESULT_FAIL.icon();
+ return summary->warnings ? Icons::RESULT_MESSAGEPASSWARN.icon() : Icons::RESULT_PASS.icon();
}
QVariant TestResultItem::data(int column, int role) const
@@ -93,9 +92,11 @@ QVariant TestResultItem::data(int column, int role) const
case Qt::DecorationRole: {
if (!m_testResult)
return QVariant();
- const Result::Type result = m_testResult->result();
- if (result == Result::MessageLocation && parent())
+ const ResultType result = m_testResult->result();
+ if (result == ResultType::MessageLocation && parent())
return parent()->data(column, role);
+ if (result == ResultType::TestStart)
+ return testSummaryIcon(m_summaryResult);
return testResultIcon(result);
}
case Qt::DisplayRole:
@@ -112,50 +113,72 @@ void TestResultItem::updateDescription(const QString &description)
m_testResult->setDescription(description);
}
-void TestResultItem::updateResult(bool &changed, Result::Type addedChildType)
+static bool isSignificant(ResultType type)
+{
+ switch (type) {
+ case ResultType::Benchmark:
+ case ResultType::MessageInfo:
+ case ResultType::MessageInternal:
+ case ResultType::TestEnd:
+ return false;
+ case ResultType::MessageLocation:
+ case ResultType::MessageCurrentTest:
+ case ResultType::Application:
+ case ResultType::Invalid:
+ QTC_ASSERT_STRING("Got unexpedted type in isSignificant check");
+ return false;
+ default:
+ return true;
+ }
+}
+
+void TestResultItem::updateResult(bool &changed, ResultType addedChildType,
+ const Utils::optional<SummaryEvaluation> &summary)
{
changed = false;
- const Result::Type old = m_testResult->result();
- if (old == Result::MessageTestCaseFailWarn) // can't become worse
+ if (m_testResult->result() != ResultType::TestStart)
return;
- if (!TestResult::isMessageCaseStart(old))
+
+ if (!isSignificant(addedChildType) || (addedChildType == ResultType::TestStart && !summary))
return;
- Result::Type newResult = old;
+ if (m_summaryResult.has_value() && m_summaryResult->failed && m_summaryResult->warnings)
+ return; // can't become worse
+
+ SummaryEvaluation newResult = m_summaryResult.value_or(SummaryEvaluation());
switch (addedChildType) {
- case Result::Fail:
- case Result::MessageFatal:
- case Result::UnexpectedPass:
- case Result::MessageTestCaseFail:
- newResult = (old == Result::MessageTestCaseSuccessWarn) ? Result::MessageTestCaseFailWarn
- : Result::MessageTestCaseFail;
+ case ResultType::Fail:
+ case ResultType::MessageFatal:
+ case ResultType::UnexpectedPass:
+ if (newResult.failed)
+ return;
+ newResult.failed = true;
break;
- case Result::MessageTestCaseFailWarn:
- newResult = Result::MessageTestCaseFailWarn;
+ case ResultType::ExpectedFail:
+ case ResultType::MessageWarn:
+ case ResultType::MessageSystem:
+ case ResultType::Skip:
+ case ResultType::BlacklistedFail:
+ case ResultType::BlacklistedPass:
+ case ResultType::BlacklistedXFail:
+ case ResultType::BlacklistedXPass:
+ if (newResult.warnings)
+ return;
+ newResult.warnings = true;
break;
- case Result::ExpectedFail:
- case Result::MessageWarn:
- case Result::MessageSystem:
- case Result::Skip:
- case Result::BlacklistedFail:
- case Result::BlacklistedPass:
- case Result::BlacklistedXFail:
- case Result::BlacklistedXPass:
- case Result::MessageTestCaseSuccessWarn:
- newResult = (old == Result::MessageTestCaseFail) ? Result::MessageTestCaseFailWarn
- : Result::MessageTestCaseSuccessWarn;
- break;
- case Result::Pass:
- case Result::MessageTestCaseSuccess:
- newResult = (old == Result::MessageIntermediate || old == Result::MessageTestCaseStart)
- ? Result::MessageTestCaseSuccess : old;
+ case ResultType::TestStart:
+ if (summary) {
+ newResult.failed |= summary->failed;
+ newResult.warnings |= summary->warnings;
+ }
break;
default:
break;
}
- changed = old != newResult;
+ changed = !m_summaryResult.has_value() || m_summaryResult.value() != newResult;
+
if (changed)
- m_testResult->setResult(newResult);
+ m_summaryResult.emplace(newResult);
}
TestResultItem *TestResultItem::intermediateFor(const TestResultItem *item) const
@@ -165,7 +188,7 @@ TestResultItem *TestResultItem::intermediateFor(const TestResultItem *item) cons
for (int row = childCount() - 1; row >= 0; --row) {
TestResultItem *child = childAt(row);
const TestResult *testResult = child->testResult();
- if (testResult->result() != Result::MessageIntermediate)
+ if (testResult->result() != ResultType::TestStart)
continue;
if (testResult->isIntermediateFor(otherResult))
return child;
@@ -177,17 +200,30 @@ TestResultItem *TestResultItem::createAndAddIntermediateFor(const TestResultItem
{
TestResultPtr result(m_testResult->createIntermediateResultFor(child->testResult()));
QTC_ASSERT(!result.isNull(), return nullptr);
- result->setResult(Result::MessageIntermediate);
+ result->setResult(ResultType::TestStart);
TestResultItem *intermediate = new TestResultItem(result);
appendChild(intermediate);
return intermediate;
}
+QString TestResultItem::resultString() const
+{
+ if (testResult()->result() != ResultType::TestStart)
+ return TestResult::resultToString(testResult()->result());
+ if (!m_summaryResult)
+ return QString();
+ return m_summaryResult->failed ? QString("FAIL") : QString("PASS");
+}
+
/********************************* TestResultModel *****************************************/
TestResultModel::TestResultModel(QObject *parent)
: Utils::TreeModel<TestResultItem>(new TestResultItem(TestResultPtr()), parent)
{
+ connect(TestRunner::instance(), &TestRunner::reportSummary,
+ this, [this](const QString &id, const QHash<ResultType, int> &summary){
+ m_reportedSummary.insert(id, summary);
+ });
}
void TestResultModel::updateParent(const TestResultItem *item)
@@ -198,7 +234,7 @@ void TestResultModel::updateParent(const TestResultItem *item)
if (parentItem == rootItem()) // do not update invisible root item
return;
bool changed = false;
- parentItem->updateResult(changed, item->testResult()->result());
+ parentItem->updateResult(changed, item->testResult()->result(), item->summaryResult());
if (!changed)
return;
emit dataChanged(parentItem->index(), parentItem->index());
@@ -208,12 +244,12 @@ void TestResultModel::updateParent(const TestResultItem *item)
void TestResultModel::addTestResult(const TestResultPtr &testResult, bool autoExpand)
{
const int lastRow = rootItem()->childCount() - 1;
- if (testResult->result() == Result::MessageCurrentTest) {
+ if (testResult->result() == ResultType::MessageCurrentTest) {
// MessageCurrentTest should always be the last top level item
if (lastRow >= 0) {
TestResultItem *current = rootItem()->childAt(lastRow);
const TestResult *result = current->testResult();
- if (result && result->result() == Result::MessageCurrentTest) {
+ if (result && result->result() == ResultType::MessageCurrentTest) {
current->updateDescription(testResult->description());
emit dataChanged(current->index(), current->index());
return;
@@ -224,12 +260,9 @@ void TestResultModel::addTestResult(const TestResultPtr &testResult, bool autoEx
return;
}
- if (testResult->result() == Result::MessageDisabledTests)
- m_disabled += testResult->line();
- m_testResultCount[testResult->result()]++;
+ m_testResultCount[testResult->id()][testResult->result()]++;
TestResultItem *newItem = new TestResultItem(testResult);
-
TestResultItem *root = nullptr;
if (AutotestPlugin::settings()->displayApplication) {
const QString application = testResult->id();
@@ -241,7 +274,7 @@ void TestResultModel::addTestResult(const TestResultPtr &testResult, bool autoEx
if (!root) {
TestResult *tmpAppResult = new TestResult(application, application);
- tmpAppResult->setResult(Result::Application);
+ tmpAppResult->setResult(ResultType::Application);
root = new TestResultItem(TestResultPtr(tmpAppResult));
if (lastRow >= 0)
rootItem()->insertChild(lastRow, root);
@@ -262,7 +295,7 @@ void TestResultModel::addTestResult(const TestResultPtr &testResult, bool autoEx
if (lastRow >= 0) {
TestResultItem *current = rootItem()->childAt(lastRow);
const TestResult *result = current->testResult();
- if (result && result->result() == Result::MessageCurrentTest) {
+ if (result && result->result() == ResultType::MessageCurrentTest) {
rootItem()->insertChild(current->index().row(), newItem);
return;
}
@@ -275,7 +308,7 @@ void TestResultModel::addTestResult(const TestResultPtr &testResult, bool autoEx
void TestResultModel::removeCurrentTestMessage()
{
TestResultItem *currentMessageItem = rootItem()->findFirstLevelChild([](TestResultItem *it) {
- return (it->testResult()->result() == Result::MessageCurrentTest);
+ return (it->testResult()->result() == ResultType::MessageCurrentTest);
});
if (currentMessageItem)
destroyItem(currentMessageItem);
@@ -285,6 +318,7 @@ void TestResultModel::clearTestResults()
{
clear();
m_testResultCount.clear();
+ m_reportedSummary.clear();
m_disabled = 0;
m_fileNames.clear();
m_maxWidthOfFileName = 0;
@@ -305,7 +339,7 @@ void TestResultModel::recalculateMaxWidthOfFileName(const QFont &font)
m_maxWidthOfFileName = 0;
for (const QString &fileName : m_fileNames) {
int pos = fileName.lastIndexOf('/');
- m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(fileName.mid(pos + 1)));
+ m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.horizontalAdvance(fileName.mid(pos + 1)));
}
}
@@ -313,7 +347,7 @@ void TestResultModel::addFileName(const QString &fileName)
{
const QFontMetrics fm(m_measurementFont);
int pos = fileName.lastIndexOf('/');
- m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(fileName.mid(pos + 1)));
+ m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.horizontalAdvance(fileName.mid(pos + 1)));
m_fileNames.insert(fileName);
}
@@ -329,11 +363,26 @@ int TestResultModel::maxWidthOfLineNumber(const QFont &font)
if (m_widthOfLineNumber == 0 || font != m_measurementFont) {
QFontMetrics fm(font);
m_measurementFont = font;
- m_widthOfLineNumber = fm.width("88888");
+ m_widthOfLineNumber = fm.horizontalAdvance("88888");
}
return m_widthOfLineNumber;
}
+int TestResultModel::resultTypeCount(ResultType type) const
+{
+ int result = 0;
+
+ for (auto resultsForId : m_testResultCount.values())
+ result += resultsForId.value(type, 0);
+
+ for (auto id : m_reportedSummary.keys()) {
+ if (int counted = m_testResultCount.value(id).value(type))
+ result -= counted;
+ result += m_reportedSummary[id].value(type);
+ }
+ return result;
+}
+
TestResultItem *TestResultModel::findParentItemFor(const TestResultItem *item,
const TestResultItem *startItem) const
{
@@ -387,42 +436,39 @@ TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObje
void TestResultFilterModel::enableAllResultTypes(bool enabled)
{
if (enabled) {
- m_enabled << Result::Pass << Result::Fail << Result::ExpectedFail
- << Result::UnexpectedPass << Result::Skip << Result::MessageDebug
- << Result::MessageWarn << Result::MessageInternal << Result::MessageLocation
- << Result::MessageFatal << Result::Invalid << Result::BlacklistedPass
- << Result::BlacklistedFail << Result::BlacklistedXFail << Result::BlacklistedXPass
- << Result::Benchmark << Result::MessageIntermediate
- << Result::MessageCurrentTest << Result::MessageTestCaseStart
- << Result::MessageTestCaseSuccess << Result::MessageTestCaseSuccessWarn
- << Result::MessageTestCaseFail << Result::MessageTestCaseFailWarn
- << Result::MessageTestCaseEnd
- << Result::MessageInfo << Result::MessageSystem << Result::Application;
+ m_enabled << ResultType::Pass << ResultType::Fail << ResultType::ExpectedFail
+ << ResultType::UnexpectedPass << ResultType::Skip << ResultType::MessageDebug
+ << ResultType::MessageWarn << ResultType::MessageInternal << ResultType::MessageLocation
+ << ResultType::MessageFatal << ResultType::Invalid << ResultType::BlacklistedPass
+ << ResultType::BlacklistedFail << ResultType::BlacklistedXFail << ResultType::BlacklistedXPass
+ << ResultType::Benchmark
+ << ResultType::MessageCurrentTest << ResultType::TestStart << ResultType::TestEnd
+ << ResultType::MessageInfo << ResultType::MessageSystem << ResultType::Application;
} else {
m_enabled.clear();
- m_enabled << Result::MessageFatal << Result::MessageSystem;
+ m_enabled << ResultType::MessageFatal << ResultType::MessageSystem;
}
invalidateFilter();
}
-void TestResultFilterModel::toggleTestResultType(Result::Type type)
+void TestResultFilterModel::toggleTestResultType(ResultType type)
{
if (m_enabled.contains(type)) {
m_enabled.remove(type);
- if (type == Result::MessageInternal)
- m_enabled.remove(Result::MessageTestCaseEnd);
- if (type == Result::MessageDebug)
- m_enabled.remove(Result::MessageInfo);
- if (type == Result::MessageWarn)
- m_enabled.remove(Result::MessageSystem);
+ if (type == ResultType::MessageInternal)
+ m_enabled.remove(ResultType::TestEnd);
+ if (type == ResultType::MessageDebug)
+ m_enabled.remove(ResultType::MessageInfo);
+ if (type == ResultType::MessageWarn)
+ m_enabled.remove(ResultType::MessageSystem);
} else {
m_enabled.insert(type);
- if (type == Result::MessageInternal)
- m_enabled.insert(Result::MessageTestCaseEnd);
- if (type == Result::MessageDebug)
- m_enabled.insert(Result::MessageInfo);
- if (type == Result::MessageWarn)
- m_enabled.insert(Result::MessageSystem);
+ if (type == ResultType::MessageInternal)
+ m_enabled.insert(ResultType::TestEnd);
+ if (type == ResultType::MessageDebug)
+ m_enabled.insert(ResultType::MessageInfo);
+ if (type == ResultType::MessageWarn)
+ m_enabled.insert(ResultType::MessageSystem);
}
invalidateFilter();
}
@@ -442,38 +488,41 @@ const TestResult *TestResultFilterModel::testResult(const QModelIndex &index) co
return m_sourceModel->testResult(mapToSource(index));
}
+TestResultItem *TestResultFilterModel::itemForIndex(const QModelIndex &index) const
+{
+ return index.isValid() ? m_sourceModel->itemForIndex(mapToSource(index)) : nullptr;
+}
+
bool TestResultFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
QModelIndex index = m_sourceModel->index(sourceRow, 0, sourceParent);
if (!index.isValid())
return false;
- Result::Type resultType = m_sourceModel->testResult(index)->result();
- switch (resultType) {
- case Result::MessageTestCaseSuccess:
- return m_enabled.contains(Result::Pass);
- case Result::MessageTestCaseFail:
- case Result::MessageTestCaseSuccessWarn:
- case Result::MessageTestCaseFailWarn:
+ ResultType resultType = m_sourceModel->testResult(index)->result();
+ if (resultType == ResultType::TestStart) {
+ TestResultItem *item = m_sourceModel->itemForIndex(index);
+ QTC_ASSERT(item, return false);
+ if (!item->summaryResult())
+ return true;
return acceptTestCaseResult(index);
- default:
- return m_enabled.contains(resultType);
}
+ return m_enabled.contains(resultType);
}
bool TestResultFilterModel::acceptTestCaseResult(const QModelIndex &srcIndex) const
{
for (int row = 0, count = m_sourceModel->rowCount(srcIndex); row < count; ++row) {
const QModelIndex &child = m_sourceModel->index(row, 0, srcIndex);
- Result::Type type = m_sourceModel->testResult(child)->result();
- if (type == Result::MessageTestCaseSuccess)
- type = Result::Pass;
- if (type == Result::MessageTestCaseFail || type == Result::MessageTestCaseFailWarn
- || type == Result::MessageTestCaseSuccessWarn) {
+ TestResultItem *item = m_sourceModel->itemForIndex(child);
+ ResultType type = item->testResult()->result();
+
+ if (type == ResultType::TestStart) {
+ if (!item->summaryResult())
+ return true;
if (acceptTestCaseResult(child))
return true;
- } else if (m_enabled.contains(type)) {
+ } else if (m_enabled.contains(type))
return true;
- }
}
return false;
}
diff --git a/src/plugins/autotest/testresultmodel.h b/src/plugins/autotest/testresultmodel.h
index c240b434bb..6370296ac0 100644
--- a/src/plugins/autotest/testresultmodel.h
+++ b/src/plugins/autotest/testresultmodel.h
@@ -32,6 +32,7 @@
#include <QFont>
#include <QSet>
+#include <utils/optional.h>
#include <utils/treemodel.h>
namespace Autotest {
@@ -44,13 +45,29 @@ public:
QVariant data(int column, int role) const override;
const TestResult *testResult() const { return m_testResult.data(); }
void updateDescription(const QString &description);
- void updateResult(bool &changed, Result::Type addedChildType);
+
+ struct SummaryEvaluation
+ {
+ bool failed = false;
+ bool warnings = false;
+
+ bool operator==(const SummaryEvaluation &other) const
+ { return failed == other.failed && warnings == other.warnings; }
+ bool operator!=(const SummaryEvaluation &other) const
+ { return !(*this == other); }
+ };
+
+ void updateResult(bool &changed, ResultType addedChildType,
+ const Utils::optional<SummaryEvaluation> &summary);
TestResultItem *intermediateFor(const TestResultItem *item) const;
TestResultItem *createAndAddIntermediateFor(const TestResultItem *child);
+ QString resultString() const;
+ Utils::optional<SummaryEvaluation> summaryResult() const { return m_summaryResult; }
private:
TestResultPtr m_testResult;
+ Utils::optional<SummaryEvaluation> m_summaryResult;
};
class TestResultModel : public Utils::TreeModel<TestResultItem>
@@ -67,8 +84,9 @@ public:
int maxWidthOfFileName(const QFont &font);
int maxWidthOfLineNumber(const QFont &font);
- int resultTypeCount(Result::Type type) const { return m_testResultCount.value(type, 0); }
+ int resultTypeCount(ResultType type) const;
int disabledTests() const { return m_disabled; }
+ void raiseDisabledTests(int amount) { m_disabled += amount; }
private:
void recalculateMaxWidthOfFileName(const QFont &font);
@@ -76,7 +94,8 @@ private:
TestResultItem *findParentItemFor(const TestResultItem *item,
const TestResultItem *startItem = nullptr) const;
void updateParent(const TestResultItem *item);
- QMap<Result::Type, int> m_testResultCount;
+ QHash<QString, QMap<ResultType, int>> m_testResultCount;
+ QHash<QString, QHash<ResultType, int>> m_reportedSummary;
int m_widthOfLineNumber = 0;
int m_maxWidthOfFileName = 0;
int m_disabled = 0;
@@ -91,10 +110,11 @@ public:
explicit TestResultFilterModel(TestResultModel *sourceModel, QObject *parent = nullptr);
void enableAllResultTypes(bool enabled);
- void toggleTestResultType(Result::Type type);
+ void toggleTestResultType(ResultType type);
void clearTestResults();
bool hasResults();
const TestResult *testResult(const QModelIndex &index) const;
+ TestResultItem *itemForIndex(const QModelIndex &index) const;
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
@@ -102,7 +122,7 @@ protected:
private:
bool acceptTestCaseResult(const QModelIndex &srcIndex) const;
TestResultModel *m_sourceModel;
- QSet<Result::Type> m_enabled;
+ QSet<ResultType> m_enabled;
};
} // namespace Internal
diff --git a/src/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp
index 24d2ff0383..468cc9e32c 100644
--- a/src/plugins/autotest/testresultspane.cpp
+++ b/src/plugins/autotest/testresultspane.cpp
@@ -157,6 +157,8 @@ TestResultsPane::TestResultsPane(QObject *parent) :
this, &TestResultsPane::onTestRunFinished);
connect(TestRunner::instance(), &TestRunner::testResultReady,
this, &TestResultsPane::addTestResult);
+ connect(TestRunner::instance(), &TestRunner::hadDisabledTests,
+ m_model, &TestResultModel::raiseDisabledTests);
}
void TestResultsPane::createToolButtons()
@@ -192,7 +194,6 @@ void TestResultsPane::createToolButtons()
m_filterButton->setIcon(Utils::Icons::FILTER.icon());
m_filterButton->setToolTip(tr("Filter Test Results"));
m_filterButton->setProperty("noArrow", true);
- m_filterButton->setAutoRaise(true);
m_filterButton->setPopupMode(QToolButton::InstantPopup);
m_filterMenu = new QMenu(m_filterButton);
initializeFilterMenu();
@@ -228,9 +229,9 @@ void TestResultsPane::addTestResult(const TestResultPtr &result)
m_atEnd = scrollBar ? scrollBar->value() == scrollBar->maximum() : true;
m_model->addTestResult(result, m_expandCollapse->isChecked());
- setIconBadgeNumber(m_model->resultTypeCount(Result::Fail)
- + m_model->resultTypeCount(Result::MessageFatal)
- + m_model->resultTypeCount(Result::UnexpectedPass));
+ setIconBadgeNumber(m_model->resultTypeCount(ResultType::Fail)
+ + m_model->resultTypeCount(ResultType::MessageFatal)
+ + m_model->resultTypeCount(ResultType::UnexpectedPass));
flash();
navigateStateChanged();
}
@@ -423,24 +424,24 @@ void TestResultsPane::initializeFilterMenu()
const bool omitIntern = AutotestPlugin::settings()->omitInternalMssg;
// FilterModel has all messages enabled by default
if (omitIntern)
- m_filterModel->toggleTestResultType(Result::MessageInternal);
-
- QMap<Result::Type, QString> textAndType;
- textAndType.insert(Result::Pass, tr("Pass"));
- textAndType.insert(Result::Fail, tr("Fail"));
- textAndType.insert(Result::ExpectedFail, tr("Expected Fail"));
- textAndType.insert(Result::UnexpectedPass, tr("Unexpected Pass"));
- textAndType.insert(Result::Skip, tr("Skip"));
- textAndType.insert(Result::Benchmark, tr("Benchmarks"));
- textAndType.insert(Result::MessageDebug, tr("Debug Messages"));
- textAndType.insert(Result::MessageWarn, tr("Warning Messages"));
- textAndType.insert(Result::MessageInternal, tr("Internal Messages"));
- for (Result::Type result : textAndType.keys()) {
+ m_filterModel->toggleTestResultType(ResultType::MessageInternal);
+
+ QMap<ResultType, QString> textAndType;
+ textAndType.insert(ResultType::Pass, tr("Pass"));
+ textAndType.insert(ResultType::Fail, tr("Fail"));
+ textAndType.insert(ResultType::ExpectedFail, tr("Expected Fail"));
+ textAndType.insert(ResultType::UnexpectedPass, tr("Unexpected Pass"));
+ textAndType.insert(ResultType::Skip, tr("Skip"));
+ textAndType.insert(ResultType::Benchmark, tr("Benchmarks"));
+ textAndType.insert(ResultType::MessageDebug, tr("Debug Messages"));
+ textAndType.insert(ResultType::MessageWarn, tr("Warning Messages"));
+ textAndType.insert(ResultType::MessageInternal, tr("Internal Messages"));
+ for (ResultType result : textAndType.keys()) {
QAction *action = new QAction(m_filterMenu);
action->setText(textAndType.value(result));
action->setCheckable(true);
- action->setChecked(result != Result::MessageInternal || !omitIntern);
- action->setData(result);
+ action->setChecked(result != ResultType::MessageInternal || !omitIntern);
+ action->setData(int(result));
m_filterMenu->addAction(action);
}
m_filterMenu->addSeparator();
@@ -457,26 +458,26 @@ void TestResultsPane::updateSummaryLabel()
QString labelText = QString("<p>");
labelText.append(tr("Test summary"));
labelText.append(":&nbsp;&nbsp; ");
- int count = m_model->resultTypeCount(Result::Pass);
+ int count = m_model->resultTypeCount(ResultType::Pass);
labelText += QString::number(count) + ' ' + tr("passes");
- count = m_model->resultTypeCount(Result::Fail);
+ count = m_model->resultTypeCount(ResultType::Fail);
labelText += ", " + QString::number(count) + ' ' + tr("fails");
- count = m_model->resultTypeCount(Result::UnexpectedPass);
+ count = m_model->resultTypeCount(ResultType::UnexpectedPass);
if (count)
labelText += ", " + QString::number(count) + ' ' + tr("unexpected passes");
- count = m_model->resultTypeCount(Result::ExpectedFail);
+ count = m_model->resultTypeCount(ResultType::ExpectedFail);
if (count)
labelText += ", " + QString::number(count) + ' ' + tr("expected fails");
- count = m_model->resultTypeCount(Result::MessageFatal);
+ count = m_model->resultTypeCount(ResultType::MessageFatal);
if (count)
labelText += ", " + QString::number(count) + ' ' + tr("fatals");
- count = m_model->resultTypeCount(Result::BlacklistedFail)
- + m_model->resultTypeCount(Result::BlacklistedXFail)
- + m_model->resultTypeCount(Result::BlacklistedPass)
- + m_model->resultTypeCount(Result::BlacklistedXPass);
+ count = m_model->resultTypeCount(ResultType::BlacklistedFail)
+ + m_model->resultTypeCount(ResultType::BlacklistedXFail)
+ + m_model->resultTypeCount(ResultType::BlacklistedPass)
+ + m_model->resultTypeCount(ResultType::BlacklistedXPass);
if (count)
labelText += ", " + QString::number(count) + ' ' + tr("blacklisted");
- count = m_model->resultTypeCount(Result::Skip);
+ count = m_model->resultTypeCount(ResultType::Skip);
if (count)
labelText += ", " + QString::number(count) + ' ' + tr("skipped");
count = m_model->disabledTests();
@@ -509,6 +510,13 @@ void TestResultsPane::onTestRunStarted()
m_summaryWidget->setVisible(false);
}
+static bool hasFailedTests(const TestResultModel *model)
+{
+ return (model->resultTypeCount(ResultType::Fail) > 0
+ || model->resultTypeCount(ResultType::MessageFatal) > 0
+ || model->resultTypeCount(ResultType::UnexpectedPass) > 0);
+}
+
void TestResultsPane::onTestRunFinished()
{
m_testRunning = false;
@@ -520,8 +528,10 @@ void TestResultsPane::onTestRunFinished()
m_model->removeCurrentTestMessage();
disconnect(m_treeView->verticalScrollBar(), &QScrollBar::rangeChanged,
this, &TestResultsPane::onScrollBarRangeChanged);
- if (!m_treeView->isVisible())
+ if (AutotestPlugin::settings()->popupOnFinish
+ && (!AutotestPlugin::settings()->popupOnFail || hasFailedTests(m_model))) {
popup(Core::IOutputPane::NoModeSwitch);
+ }
createMarks();
}
@@ -637,7 +647,8 @@ QString TestResultsPane::getWholeOutput(const QModelIndex &parent)
QModelIndex current = m_model->index(row, 0, parent);
const TestResult *result = m_model->testResult(current);
QTC_ASSERT(result, continue);
- output.append(TestResult::resultToString(result->result())).append('\t');
+ if (auto item = m_model->itemForIndex(current))
+ output.append(item->resultString()).append('\t');
output.append(result->outputString(true)).append('\n');
output.append(getWholeOutput(current));
}
@@ -647,8 +658,8 @@ QString TestResultsPane::getWholeOutput(const QModelIndex &parent)
void TestResultsPane::createMarks(const QModelIndex &parent)
{
const TestResult *parentResult = m_model->testResult(parent);
- Result::Type parentType = parentResult ? parentResult->result() : Result::Invalid;
- const QVector<Result::Type> interested{Result::Fail, Result::UnexpectedPass};
+ ResultType parentType = parentResult ? parentResult->result() : ResultType::Invalid;
+ const QVector<ResultType> interested{ResultType::Fail, ResultType::UnexpectedPass};
for (int row = 0, count = m_model->rowCount(parent); row < count; ++row) {
const QModelIndex index = m_model->index(row, 0, parent);
const TestResult *result = m_model->testResult(index);
@@ -657,10 +668,10 @@ void TestResultsPane::createMarks(const QModelIndex &parent)
if (m_model->hasChildren(index))
createMarks(index);
- bool isLocationItem = result->result() == Result::MessageLocation;
+ bool isLocationItem = result->result() == ResultType::MessageLocation;
if (interested.contains(result->result())
|| (isLocationItem && interested.contains(parentType))) {
- const Utils::FileName fileName = Utils::FileName::fromString(result->fileName());
+ const Utils::FilePath fileName = Utils::FilePath::fromString(result->fileName());
TestEditorMark *mark = new TestEditorMark(index, fileName, result->line());
mark->setIcon(index.data(Qt::DecorationRole).value<QIcon>());
mark->setColor(Utils::Theme::OutputPanes_TestFailTextColor);
diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp
index 6792b96cb3..cf432870e3 100644
--- a/src/plugins/autotest/testrunner.cpp
+++ b/src/plugins/autotest/testrunner.cpp
@@ -89,8 +89,7 @@ TestRunner::TestRunner(QObject *parent) :
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::canceled,
this, [this]() {
cancelCurrent(UserCanceled);
- emit testResultReady(TestResultPtr(new FaultyTestResult(
- Result::MessageFatal, tr("Test run canceled by user."))));
+ reportResult(ResultType::MessageFatal, tr("Test run canceled by user."));
});
}
@@ -171,8 +170,8 @@ void TestRunner::scheduleNext()
QString commandFilePath = m_currentConfig->executableFilePath();
if (commandFilePath.isEmpty()) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
- tr("Executable path is empty. (%1)").arg(m_currentConfig->displayName()))));
+ reportResult(ResultType::MessageFatal,
+ tr("Executable path is empty. (%1)").arg(m_currentConfig->displayName()));
delete m_currentConfig;
m_currentConfig = nullptr;
if (m_selectedTests.isEmpty())
@@ -200,8 +199,7 @@ void TestRunner::scheduleNext()
m_currentProcess->setArguments(m_currentConfig->argumentsForTestRunner(&omitted));
if (!omitted.isEmpty()) {
const QString &details = constructOmittedDetailsString(omitted);
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
- details.arg(m_currentConfig->displayName()))));
+ reportResult(ResultType::MessageWarn, details.arg(m_currentConfig->displayName()));
}
m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory());
const Utils::Environment &original = m_currentConfig->environment();
@@ -213,21 +211,20 @@ void TestRunner::scheduleNext()
if (!removedVariables.isEmpty()) {
const QString &details = constructOmittedVariablesDetailsString(removedVariables)
.arg(m_currentConfig->displayName());
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, details)));
+ reportResult(ResultType::MessageWarn, details);
}
m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment());
- connect(m_currentProcess,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_currentProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &TestRunner::onProcessFinished);
const int timeout = AutotestPlugin::settings()->timeout;
QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); });
m_currentProcess->start();
if (!m_currentProcess->waitForStarted()) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
+ reportResult(ResultType::MessageFatal,
tr("Failed to start test for project \"%1\".").arg(m_currentConfig->displayName())
- + processInformation(m_currentProcess) + rcInfo(m_currentConfig))));
+ + processInformation(m_currentProcess) + rcInfo(m_currentConfig));
}
}
@@ -238,14 +235,10 @@ void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
if (m_fakeFutureInterface)
m_fakeFutureInterface->reportCanceled();
- auto reportResult = [this](Result::Type type, const QString &detail){
- emit testResultReady(TestResultPtr(new FaultyTestResult(type, detail)));
- };
-
if (reason == KitChanged)
- reportResult(Result::MessageWarn, tr("Current kit has changed. Canceling test run."));
+ reportResult(ResultType::MessageWarn, tr("Current kit has changed. Canceling test run."));
else if (reason == Timeout)
- reportResult(Result::MessageFatal, tr("Test case canceled due to timeout.\nMaybe raise the timeout?"));
+ reportResult(ResultType::MessageFatal, tr("Test case canceled due to timeout.\nMaybe raise the timeout?"));
// if user or timeout cancels the current run ensure to kill the running process
if (m_currentProcess && m_currentProcess->state() != QProcess::NotRunning) {
@@ -263,17 +256,23 @@ void TestRunner::onProcessFinished()
if (!m_fakeFutureInterface->isCanceled()) {
if (m_currentProcess->exitStatus() == QProcess::CrashExit) {
m_currentOutputReader->reportCrash();
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
+ reportResult(ResultType::MessageFatal,
tr("Test for project \"%1\" crashed.").arg(m_currentConfig->displayName())
- + processInformation(m_currentProcess) + rcInfo(m_currentConfig))));
+ + processInformation(m_currentProcess) + rcInfo(m_currentConfig));
} else if (!m_currentOutputReader->hadValidOutput()) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
+ reportResult(ResultType::MessageFatal,
tr("Test for project \"%1\" did not produce any expected output.")
.arg(m_currentConfig->displayName()) + processInformation(m_currentProcess)
- + rcInfo(m_currentConfig))));
+ + rcInfo(m_currentConfig));
}
}
}
+ const int disabled = m_currentOutputReader->disabledTests();
+ if (disabled > 0)
+ emit hadDisabledTests(disabled);
+ if (m_currentOutputReader->hasSummary())
+ emit reportSummary(m_currentOutputReader->id(), m_currentOutputReader->summary());
+
resetInternalPointers();
if (!m_fakeFutureInterface) {
@@ -315,18 +314,17 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
TestResultsPane::instance()->clearContents();
if (m_selectedTests.empty()) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
- tr("No tests selected. Canceling test run."))));
+ reportResult(ResultType::MessageWarn, tr("No tests selected. Canceling test run."));
onFinished();
return;
}
ProjectExplorer::Project *project = m_selectedTests.at(0)->project();
if (!project) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
+ reportResult(ResultType::MessageWarn,
tr("Project is null. Canceling test run.\n"
- "Only desktop kits are supported. Make sure the "
- "currently active kit is a desktop kit."))));
+ "Only desktop kits are supported. Make sure the "
+ "currently active kit is a desktop kit."));
onFinished();
return;
}
@@ -340,8 +338,8 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
} else if (project->hasActiveBuildSettings()) {
buildProject(project);
} else {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
- tr("Project is not configured. Canceling test run."))));
+ reportResult(ResultType::MessageFatal,
+ tr("Project is not configured. Canceling test run."));
onFinished();
}
}
@@ -414,13 +412,12 @@ int TestRunner::precheckTestConfigurations()
"This might cause trouble during execution.\n"
"(deduced from \"%2\")");
message = message.arg(config->displayName()).arg(config->runConfigDisplayName());
- emit testResultReady(
- TestResultPtr(new FaultyTestResult(Result::MessageWarn, message)));
+ reportResult(ResultType::MessageWarn, message);
}
} else {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
- tr("Project is null for \"%1\". Removing from test run.\n"
- "Check the test environment.").arg(config->displayName()))));
+ reportResult(ResultType::MessageWarn,
+ tr("Project is null for \"%1\". Removing from test run.\n"
+ "Check the test environment.").arg(config->displayName()));
}
}
return testCaseCount;
@@ -450,7 +447,7 @@ void TestRunner::runTests()
QString mssg = projectChanged ? tr("Startup project has changed. Canceling test run.")
: tr("No test cases left for execution. Canceling test run.");
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, mssg)));
+ reportResult(ResultType::MessageWarn, mssg);
onFinished();
return;
}
@@ -465,6 +462,8 @@ void TestRunner::runTests()
m_futureWatcher.setFuture(future);
Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX);
+ if (AutotestPlugin::settings()->popupOnStart)
+ AutotestPlugin::popupResultsPane();
scheduleNext();
}
@@ -514,8 +513,8 @@ void TestRunner::debugTests()
TestConfiguration *config = m_selectedTests.first();
config->completeTestInformation(TestRunMode::Debug);
if (!config->project()) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
- TestRunner::tr("Startup project has changed. Canceling test run."))));
+ reportResult(ResultType::MessageWarn,
+ tr("Startup project has changed. Canceling test run."));
onFinished();
return;
}
@@ -525,28 +524,26 @@ void TestRunner::debugTests()
}
if (!config->runConfiguration()) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
- TestRunner::tr("Failed to get run configuration."))));
+ reportResult(ResultType::MessageFatal, tr("Failed to get run configuration."));
onFinished();
return;
}
const QString &commandFilePath = config->executableFilePath();
if (commandFilePath.isEmpty()) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
- TestRunner::tr("Could not find command \"%1\". (%2)")
- .arg(config->executableFilePath())
- .arg(config->displayName()))));
+ reportResult(ResultType::MessageFatal, tr("Could not find command \"%1\". (%2)")
+ .arg(config->executableFilePath())
+ .arg(config->displayName()));
onFinished();
return;
}
QString errorMessage;
- auto runControl = new ProjectExplorer::RunControl(config->runConfiguration(),
- ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setRunConfiguration(config->runConfiguration());
if (!runControl) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
- TestRunner::tr("Failed to create run configuration.\n%1").arg(errorMessage))));
+ reportResult(ResultType::MessageFatal,
+ tr("Failed to create run configuration.\n%1").arg(errorMessage));
onFinished();
return;
}
@@ -559,8 +556,7 @@ void TestRunner::debugTests()
inferior.commandLineArguments = Utils::QtcProcess::joinArgs(args);
if (!omitted.isEmpty()) {
const QString &details = constructOmittedDetailsString(omitted);
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
- details.arg(config->displayName()))));
+ reportResult(ResultType::MessageWarn, details.arg(config->displayName()));
}
Utils::Environment original(inferior.environment);
inferior.environment = config->filteredEnvironment(original);
@@ -571,7 +567,7 @@ void TestRunner::debugTests()
if (!removedVariables.isEmpty()) {
const QString &details = constructOmittedVariablesDetailsString(removedVariables)
.arg(config->displayName());
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, details)));
+ reportResult(ResultType::MessageWarn, details);
}
auto debugger = new Debugger::DebuggerRunTool(runControl);
debugger->setInferior(inferior);
@@ -579,9 +575,9 @@ void TestRunner::debugTests()
bool useOutputProcessor = true;
if (ProjectExplorer::Target *targ = config->project()->activeTarget()) {
- if (Debugger::DebuggerKitInformation::engineType(targ->kit()) == Debugger::CdbEngineType) {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
- TestRunner::tr("Unable to display test results when using CDB."))));
+ if (Debugger::DebuggerKitAspect::engineType(targ->kit()) == Debugger::CdbEngineType) {
+ reportResult(ResultType::MessageWarn,
+ tr("Unable to display test results when using CDB."));
useOutputProcessor = false;
}
}
@@ -596,9 +592,8 @@ void TestRunner::debugTests()
outputreader->setId(inferior.executable);
connect(outputreader, &TestOutputReader::newOutputAvailable,
TestResultsPane::instance(), &TestResultsPane::addOutput);
- connect(runControl, &ProjectExplorer::RunControl::appendMessageRequested,
- this, [outputreader]
- (ProjectExplorer::RunControl *, const QString &msg, Utils::OutputFormat format) {
+ connect(runControl, &ProjectExplorer::RunControl::appendMessage,
+ this, [outputreader](const QString &msg, Utils::OutputFormat format) {
processOutput(outputreader, msg, format);
});
@@ -611,6 +606,8 @@ void TestRunner::debugTests()
connect(runControl, &ProjectExplorer::RunControl::stopped, this, &TestRunner::onFinished);
ProjectExplorer::ProjectExplorerPlugin::startRunControl(runControl);
+ if (useOutputProcessor && AutotestPlugin::settings()->popupOnStart)
+ AutotestPlugin::popupResultsPane();
}
void TestRunner::runOrDebugTests()
@@ -654,8 +651,7 @@ void TestRunner::buildFinished(bool success)
else if (m_executingTests)
onFinished();
} else {
- emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
- tr("Build failed. Canceling test run."))));
+ reportResult(ResultType::MessageFatal, tr("Build failed. Canceling test run."));
onFinished();
}
}
@@ -673,6 +669,14 @@ void TestRunner::onFinished()
emit testRunFinished();
}
+void TestRunner::reportResult(ResultType type, const QString &description)
+{
+ TestResultPtr result(new TestResult);
+ result->setResult(type);
+ result->setDescription(description);
+ emit testResultReady(result);
+}
+
/*************************************************************************************************/
static QFrame *createLine(QWidget *parent)
diff --git a/src/plugins/autotest/testrunner.h b/src/plugins/autotest/testrunner.h
index b56d797401..5628a6d29e 100644
--- a/src/plugins/autotest/testrunner.h
+++ b/src/plugins/autotest/testrunner.h
@@ -70,6 +70,8 @@ signals:
void testRunFinished();
void requestStopTestRun();
void testResultReady(const TestResultPtr &result);
+ void hadDisabledTests(int disabled);
+ void reportSummary(const QString &id, const QHash<ResultType, int> &summary);
private:
void buildProject(ProjectExplorer::Project *project);
@@ -85,6 +87,7 @@ private:
void runTests();
void debugTests();
void runOrDebugTests();
+ void reportResult(ResultType type, const QString &description);
explicit TestRunner(QObject *parent = nullptr);
QFutureWatcher<TestResultPtr> m_futureWatcher;
diff --git a/src/plugins/autotest/testsettings.cpp b/src/plugins/autotest/testsettings.cpp
index c825ea5573..ddb4f49e81 100644
--- a/src/plugins/autotest/testsettings.cpp
+++ b/src/plugins/autotest/testsettings.cpp
@@ -39,10 +39,11 @@ static const char omitInternalKey[] = "OmitInternal";
static const char omitRunConfigWarnKey[] = "OmitRCWarnings";
static const char limitResultOutputKey[] = "LimitResultOutput";
static const char autoScrollKey[] = "AutoScrollResults";
-static const char filterScanKey[] = "FilterScan";
-static const char filtersKey[] = "WhiteListFilters";
static const char processArgsKey[] = "ProcessArgs";
static const char displayApplicationKey[] = "DisplayApp";
+static const char popupOnStartKey[] = "PopupOnStart";
+static const char popupOnFinishKey[] = "PopupOnFinish";
+static const char popupOnFailKey[] = "PopupOnFail";
static const char groupSuffix[] = ".group";
constexpr int defaultTimeout = 60000;
@@ -62,8 +63,9 @@ void TestSettings::toSettings(QSettings *s) const
s->setValue(autoScrollKey, autoScroll);
s->setValue(processArgsKey, processArgs);
s->setValue(displayApplicationKey, displayApplication);
- s->setValue(filterScanKey, filterScan);
- s->setValue(filtersKey, whiteListFilters);
+ s->setValue(popupOnStartKey, popupOnStart);
+ s->setValue(popupOnFinishKey, popupOnFinish);
+ s->setValue(popupOnFailKey, popupOnFail);
// store frameworks and their current active and grouping state
for (const Core::Id &id : frameworks.keys()) {
s->setValue(QLatin1String(id.name()), frameworks.value(id));
@@ -82,8 +84,9 @@ void TestSettings::fromSettings(QSettings *s)
autoScroll = s->value(autoScrollKey, true).toBool();
processArgs = s->value(processArgsKey, false).toBool();
displayApplication = s->value(displayApplicationKey, false).toBool();
- filterScan = s->value(filterScanKey, false).toBool();
- whiteListFilters = s->value(filtersKey, QStringList()).toStringList();
+ popupOnStart = s->value(popupOnStartKey, true).toBool();
+ popupOnFinish = s->value(popupOnFinishKey, true).toBool();
+ popupOnFail = s->value(popupOnFailKey, false).toBool();
// try to get settings for registered frameworks
TestFrameworkManager *frameworkManager = TestFrameworkManager::instance();
const QList<Core::Id> &registered = frameworkManager->registeredFrameworkIds();
diff --git a/src/plugins/autotest/testsettings.h b/src/plugins/autotest/testsettings.h
index 6eff083e59..92c4ef9933 100644
--- a/src/plugins/autotest/testsettings.h
+++ b/src/plugins/autotest/testsettings.h
@@ -47,12 +47,13 @@ struct TestSettings
bool omitRunConfigWarn = false;
bool limitResultOutput = true;
bool autoScroll = true;
- bool filterScan = false;
bool processArgs = false;
bool displayApplication = false;
+ bool popupOnStart = true;
+ bool popupOnFinish = true;
+ bool popupOnFail = false;
QHash<Core::Id, bool> frameworks;
QHash<Core::Id, bool> frameworksGrouping;
- QStringList whiteListFilters;
};
} // namespace Internal
diff --git a/src/plugins/autotest/testsettingspage.cpp b/src/plugins/autotest/testsettingspage.cpp
index e2bf15ae6c..169bab7320 100644
--- a/src/plugins/autotest/testsettingspage.cpp
+++ b/src/plugins/autotest/testsettingspage.cpp
@@ -32,90 +32,12 @@
#include "autotestplugin.h"
#include <coreplugin/icore.h>
-#include <utils/fancylineedit.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QRegExp>
-
namespace Autotest {
namespace Internal {
-class TestFilterDialog : public QDialog
-{
-public:
- explicit TestFilterDialog(QWidget *parent = nullptr, Qt::WindowFlags f = nullptr);
- QString filterPath() const;
- void setDetailsText(const QString &details) { m_details->setText(details); }
- void setDefaultFilterPath(const QString &defaultPath);
-private:
- static bool validate(Utils::FancyLineEdit *edit, QString * /*errormessage*/);
- QLabel *m_details;
- Utils::FancyLineEdit *m_lineEdit;
- QString m_defaultPath;
-};
-
-TestFilterDialog::TestFilterDialog(QWidget *parent, Qt::WindowFlags f)
- : QDialog(parent, f),
- m_details(new QLabel),
- m_lineEdit(new Utils::FancyLineEdit)
-{
- setModal(true);
- auto layout = new QVBoxLayout(this);
- layout->setSizeConstraint(QLayout::SetFixedSize);
- layout->addWidget(m_details);
- m_lineEdit->setValidationFunction(&validate);
- layout->addWidget(m_lineEdit);
- auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
- auto okButton = buttonBox->button(QDialogButtonBox::Ok);
- auto cancelButton = buttonBox->button(QDialogButtonBox::Cancel);
- okButton->setEnabled(false);
- layout->addWidget(buttonBox);
- setLayout(layout);
- connect(m_lineEdit, &Utils::FancyLineEdit::validChanged, okButton, &QPushButton::setEnabled);
- connect(okButton, &QPushButton::clicked, this, &QDialog::accept);
- connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject);
-}
-
-QString TestFilterDialog::filterPath() const
-{
- static const QRegExp repetition("//+");
- QString path = m_lineEdit->isValid() ? m_lineEdit->text() : m_defaultPath;
- path.replace('\\', '/'); // turn windows separators into forward slashes
- path.replace(repetition, "/"); // avoid duplicated separators
- if (!path.startsWith('/'))
- path.prepend('/');
- if (!path.endsWith('/'))
- path.append('/');
- if (path.length() <= 2) // after surrounding with '/' this should be > 2 if valid
- return QString(); // empty string marks invalid filter
- return path;
-}
-
-void TestFilterDialog::setDefaultFilterPath(const QString &defaultPath)
-{
- m_lineEdit->setText(defaultPath);
- if (m_lineEdit->isValid())
- m_defaultPath = defaultPath;
- else
- m_lineEdit->setText(m_defaultPath);
-}
-
-bool TestFilterDialog::validate(Utils::FancyLineEdit *edit, QString *)
-{
- if (!edit)
- return false;
- const QString &value = edit->text();
- if (value.isEmpty())
- return false;
- // should we distinguish between Windows and UNIX?
- static const QRegExp valid("(\\|/)?([^?*:;\"\'|<>\t\b]+(\\|/)?)+");
- return valid.exactMatch(value);
-}
-/**************************************************************************************************/
-
TestSettingsWidget::TestSettingsWidget(QWidget *parent)
: QWidget(parent)
{
@@ -129,19 +51,10 @@ TestSettingsWidget::TestSettingsWidget(QWidget *parent)
"having at least one active test framework."));
connect(m_ui.frameworkTreeWidget, &QTreeWidget::itemChanged,
this, &TestSettingsWidget::onFrameworkItemChanged);
- connect(m_ui.addFilter, &QPushButton::clicked, this, &TestSettingsWidget::onAddFilterClicked);
- connect(m_ui.editFilter, &QPushButton::clicked, this, &TestSettingsWidget::onEditFilterClicked);
- connect(m_ui.filterTreeWidget, &QTreeWidget::activated,
- this, &TestSettingsWidget::onEditFilterClicked);
- connect(m_ui.removeFilter, &QPushButton::clicked,
- this, &TestSettingsWidget::onRemoveFilterClicked);
- connect(m_ui.filterTreeWidget, &QTreeWidget::itemSelectionChanged, [this] () {
- const bool enable = m_ui.filterTreeWidget->selectionModel()->hasSelection();
- m_ui.editFilter->setEnabled(enable);
- m_ui.removeFilter->setEnabled(enable);
- });
connect(m_ui.resetChoicesButton, &QPushButton::clicked,
this, [] { AutotestPlugin::clearChoiceCache(); });
+ connect(m_ui.openResultsOnFinishCB, &QCheckBox::toggled,
+ m_ui.openResultsOnFailCB, &QCheckBox::setEnabled);
}
void TestSettingsWidget::setSettings(const TestSettings &settings)
@@ -153,9 +66,10 @@ void TestSettingsWidget::setSettings(const TestSettings &settings)
m_ui.autoScrollCB->setChecked(settings.autoScroll);
m_ui.processArgsCB->setChecked(settings.processArgs);
m_ui.displayAppCB->setChecked(settings.displayApplication);
- m_ui.filterGroupBox->setChecked(settings.filterScan);
+ m_ui.openResultsOnStartCB->setChecked(settings.popupOnStart);
+ m_ui.openResultsOnFinishCB->setChecked(settings.popupOnFinish);
+ m_ui.openResultsOnFailCB->setChecked(settings.popupOnFail);
populateFrameworksListWidget(settings.frameworks);
- populateFiltersWidget(settings.whiteListFilters);
}
TestSettings TestSettingsWidget::settings() const
@@ -168,9 +82,10 @@ TestSettings TestSettingsWidget::settings() const
result.autoScroll = m_ui.autoScrollCB->isChecked();
result.processArgs = m_ui.processArgsCB->isChecked();
result.displayApplication = m_ui.displayAppCB->isChecked();
- result.filterScan = m_ui.filterGroupBox->isChecked();
+ result.popupOnStart = m_ui.openResultsOnStartCB->isChecked();
+ result.popupOnFinish = m_ui.openResultsOnFinishCB->isChecked();
+ result.popupOnFail = m_ui.openResultsOnFailCB->isChecked();
frameworkSettings(result);
- result.whiteListFilters = filters();
return result;
}
@@ -196,12 +111,6 @@ void TestSettingsWidget::populateFrameworksListWidget(const QHash<Core::Id, bool
}
}
-void TestSettingsWidget::populateFiltersWidget(const QStringList &filters)
-{
- for (const QString &filter : filters)
- new QTreeWidgetItem(m_ui.filterTreeWidget, {filter} );
-}
-
void TestSettingsWidget::frameworkSettings(TestSettings &settings) const
{
const QAbstractItemModel *model = m_ui.frameworkTreeWidget->model();
@@ -216,16 +125,6 @@ void TestSettingsWidget::frameworkSettings(TestSettings &settings) const
}
}
-QStringList TestSettingsWidget::filters() const
-{
- QStringList result;
- if (QAbstractItemModel *model = m_ui.filterTreeWidget->model()) {
- for (int row = 0, count = model->rowCount(); row < count; ++row)
- result.append(model->index(row, 0).data().toString());
- }
- return result;
-}
-
void TestSettingsWidget::onFrameworkItemChanged()
{
if (QAbstractItemModel *model = m_ui.frameworkTreeWidget->model()) {
@@ -241,45 +140,6 @@ void TestSettingsWidget::onFrameworkItemChanged()
m_ui.frameworksWarnIcon->setVisible(true);
}
-void TestSettingsWidget::onAddFilterClicked()
-{
- TestFilterDialog dialog;
- dialog.setWindowTitle(tr("Add Filter"));
- dialog.setDetailsText("<p>" + tr("Specify a filter expression to be added to the list of filters."
- "<br/>Wildcards are not supported.") + "</p>");
- if (dialog.exec() == QDialog::Accepted) {
- const QString &filter = dialog.filterPath();
- if (!filter.isEmpty())
- new QTreeWidgetItem(m_ui.filterTreeWidget, {filter} );
- }
-}
-
-void TestSettingsWidget::onEditFilterClicked()
-{
- const QList<QTreeWidgetItem *> &selected = m_ui.filterTreeWidget->selectedItems();
- QTC_ASSERT(selected.size() == 1, return);
- const QString &oldFilter = selected.first()->data(0, Qt::DisplayRole).toString();
-
- TestFilterDialog dialog;
- dialog.setWindowTitle(tr("Edit Filter"));
- dialog.setDetailsText("<p>" + tr("Specify a filter expression that will replace \"%1\"."
- "<br/>Wildcards are not supported.").arg(oldFilter) + "</p>");
- dialog.setDefaultFilterPath(oldFilter);
- if (dialog.exec() == QDialog::Accepted) {
- const QString &edited = dialog.filterPath();
- if (!edited.isEmpty() && edited != oldFilter)
- selected.first()->setData(0, Qt::DisplayRole, edited);
- }
-}
-
-void TestSettingsWidget::onRemoveFilterClicked()
-{
- const QList<QTreeWidgetItem *> &selected = m_ui.filterTreeWidget->selectedItems();
- QTC_ASSERT(selected.size() == 1, return);
- m_ui.filterTreeWidget->removeItemWidget(selected.first(), 0);
- delete selected.first();
-}
-
TestSettingsPage::TestSettingsPage(const QSharedPointer<TestSettings> &settings)
: m_settings(settings)
{
@@ -306,8 +166,6 @@ void TestSettingsPage::apply()
return;
const TestSettings newSettings = m_widget->settings();
bool frameworkSyncNecessary = newSettings.frameworks != m_settings->frameworks;
- bool forceReparse = newSettings.filterScan != m_settings->filterScan ||
- newSettings.whiteListFilters.toSet() != m_settings->whiteListFilters.toSet();
const QList<Core::Id> changedIds = Utils::filtered(newSettings.frameworksGrouping.keys(),
[newSettings, this] (const Core::Id &id) {
return newSettings.frameworksGrouping[id] != m_settings->frameworksGrouping[id];
@@ -318,8 +176,6 @@ void TestSettingsPage::apply()
frameworkManager->activateFrameworksFromSettings(m_settings);
if (frameworkSyncNecessary)
TestTreeModel::instance()->syncTestFrameworks();
- else if (forceReparse)
- TestTreeModel::instance()->parser()->emitUpdateTestTree();
else if (!changedIds.isEmpty())
TestTreeModel::instance()->rebuild(changedIds);
}
diff --git a/src/plugins/autotest/testsettingspage.h b/src/plugins/autotest/testsettingspage.h
index 2b1216c9eb..a100500476 100644
--- a/src/plugins/autotest/testsettingspage.h
+++ b/src/plugins/autotest/testsettingspage.h
@@ -47,13 +47,8 @@ public:
private:
void populateFrameworksListWidget(const QHash<Core::Id, bool> &frameworks);
- void populateFiltersWidget(const QStringList &filters);
void frameworkSettings(TestSettings &settings) const;
- QStringList filters() const;
void onFrameworkItemChanged();
- void onAddFilterClicked();
- void onEditFilterClicked();
- void onRemoveFilterClicked();
Ui::TestSettingsPage m_ui;
};
diff --git a/src/plugins/autotest/testsettingspage.ui b/src/plugins/autotest/testsettingspage.ui
index dbdf49842a..cb65055bc3 100644
--- a/src/plugins/autotest/testsettingspage.ui
+++ b/src/plugins/autotest/testsettingspage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>585</width>
- <height>458</height>
+ <width>586</width>
+ <height>429</height>
</rect>
</property>
<property name="windowTitle">
@@ -61,6 +61,59 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="openResultsOnStartCB">
+ <property name="toolTip">
+ <string>Opens the test results pane automatically when tests are started.</string>
+ </property>
+ <property name="text">
+ <string>Open results pane 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>
+ </property>
+ <property name="text">
+ <string>Open results pane when tests finish</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <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>
+ </property>
+ <property name="text">
+ <string>Only for unsuccessful test runs</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
<widget class="QCheckBox" name="autoScrollCB">
<property name="toolTip">
<string>Automatically scrolls down when new items are added and scrollbar is at bottom.</string>
@@ -284,102 +337,6 @@ Warning: this is an experimental feature and might lead to failing to execute th
</layout>
</item>
<item>
- <widget class="QGroupBox" name="filterGroupBox">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="title">
- <string>Global Filters</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QTreeWidget" name="filterTreeWidget">
- <property name="toolTip">
- <string>Filters used on directories when scanning for tests.&lt;br/&gt;If filtering is enabled, only directories that match any of the filters will be scanned.</string>
- </property>
- <property name="uniformRowHeights">
- <bool>true</bool>
- </property>
- <property name="headerHidden">
- <bool>true</bool>
- </property>
- <column>
- <property name="text">
- <string notr="true">1</string>
- </property>
- </column>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QPushButton" name="addFilter">
- <property name="text">
- <string>Add...</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="editFilter">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Edit...</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_5">
- <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>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="removeFilter">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Remove</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_4">
- <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>
- </widget>
- </item>
- <item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp
index e1c1debe9c..bc3c4f16be 100644
--- a/src/plugins/autotest/testtreeitem.cpp
+++ b/src/plugins/autotest/testtreeitem.cpp
@@ -47,8 +47,9 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty
switch (m_type) {
case Root:
case GroupNode:
+ case TestSuite:
case TestCase:
- case TestFunctionOrSet:
+ case TestFunction:
m_checked = Qt::Checked;
break;
default:
@@ -62,6 +63,7 @@ static QIcon testTreeIcon(TestTreeItem::Type type)
static QIcon icons[] = {
QIcon(),
Utils::Icons::OPENFILE.icon(),
+ QIcon(":/autotest/images/suite.png"),
Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Class),
Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::SlotPrivate),
QIcon(":/autotest/images/data.png")
@@ -120,16 +122,17 @@ Qt::ItemFlags TestTreeItem::flags(int /*column*/) const
case Root:
case GroupNode:
return Qt::ItemIsEnabled | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable;
+ case TestSuite:
case TestCase:
return defaultFlags | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable;
- case TestFunctionOrSet:
+ case TestFunction:
return defaultFlags | Qt::ItemIsUserCheckable;
default:
return defaultFlags;
}
}
-bool TestTreeItem::modifyTestCaseContent(const TestParseResult *result)
+bool TestTreeItem::modifyTestCaseOrSuiteContent(const TestParseResult *result)
{
bool hasBeenModified = modifyName(result->name);
hasBeenModified |= modifyLineAndColumn(result);
@@ -170,8 +173,9 @@ Qt::CheckState TestTreeItem::checked() const
switch (m_type) {
case Root:
case GroupNode:
+ case TestSuite:
case TestCase:
- case TestFunctionOrSet:
+ case TestFunction:
case TestDataTag:
return m_checked;
default:
@@ -255,7 +259,7 @@ QList<TestConfiguration *> TestTreeItem::getSelectedTestConfigurations() const
return QList<TestConfiguration *>();
}
-QList<TestConfiguration *> TestTreeItem::getTestConfigurationsForFile(const Utils::FileName &) const
+QList<TestConfiguration *> TestTreeItem::getTestConfigurationsForFile(const Utils::FilePath &) const
{
return QList<TestConfiguration *>();
}
@@ -364,9 +368,9 @@ QSet<QString> TestTreeItem::dependingInternalTargets(CppTools::CppModelManager *
bool wasHeader;
const QString correspondingFile
= CppTools::correspondingHeaderOrSource(file, &wasHeader, CppTools::CacheUsage::ReadOnly);
- const Utils::FileNameList dependingFiles = snapshot.filesDependingOn(
+ const Utils::FilePathList dependingFiles = snapshot.filesDependingOn(
wasHeader ? file : correspondingFile);
- for (const Utils::FileName &fn : dependingFiles) {
+ for (const Utils::FilePath &fn : dependingFiles) {
for (const CppTools::ProjectPart::Ptr &part : cppMM->projectPart(fn))
result.insert(part->buildSystemTarget);
}
diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h
index 74e6c98d8f..e6d47bb820 100644
--- a/src/plugins/autotest/testtreeitem.h
+++ b/src/plugins/autotest/testtreeitem.h
@@ -42,7 +42,7 @@ namespace {
}
namespace CppTools { class CppModelManager; }
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace Autotest {
namespace Internal {
@@ -59,8 +59,9 @@ public:
{
Root,
GroupNode,
+ TestSuite,
TestCase,
- TestFunctionOrSet,
+ TestFunction,
TestDataTag,
TestDataFunction,
TestSpecialFunction
@@ -78,7 +79,7 @@ public:
virtual QVariant data(int column, int role) const override;
virtual bool setData(int column, const QVariant &data, int role) override;
virtual Qt::ItemFlags flags(int column) const override;
- bool modifyTestCaseContent(const TestParseResult *result);
+ bool modifyTestCaseOrSuiteContent(const TestParseResult *result);
bool modifyTestFunctionContent(const TestParseResult *result);
bool modifyDataTagContent(const TestParseResult *result);
bool modifyLineAndColumn(const TestParseResult *result);
@@ -115,7 +116,7 @@ public:
TestConfiguration *asConfiguration(TestRunMode mode) const;
virtual QList<TestConfiguration *> getAllTestConfigurations() const;
virtual QList<TestConfiguration *> getSelectedTestConfigurations() const;
- virtual QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FileName &fileName) const;
+ virtual QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FilePath &fileName) const;
virtual bool lessThan(const TestTreeItem *other, SortMode mode) const;
virtual TestTreeItem *find(const TestParseResult *result) = 0;
virtual TestTreeItem *findChild(const TestTreeItem *other) = 0;
@@ -126,6 +127,8 @@ public:
// based on (internal) filters this will be used to filter out sub items (and remove them)
// returns a copy of the item that contains the filtered out children or nullptr
virtual TestTreeItem *applyFilters() { return nullptr; }
+ // decide whether an item should still be added to the treemodel
+ virtual bool shouldBeAddedAfterFiltering() const { return true; }
virtual QSet<QString> internalTargets() const;
protected:
void copyBasicDataFrom(const TestTreeItem *other);
diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp
index 7e4e577812..953e93dc9c 100644
--- a/src/plugins/autotest/testtreemodel.cpp
+++ b/src/plugins/autotest/testtreemodel.cpp
@@ -158,7 +158,7 @@ QList<TestConfiguration *> TestTreeModel::getSelectedTests() const
return result;
}
-QList<TestConfiguration *> TestTreeModel::getTestsForFile(const Utils::FileName &fileName) const
+QList<TestConfiguration *> TestTreeModel::getTestsForFile(const Utils::FilePath &fileName) const
{
QList<TestConfiguration *> result;
for (Utils::TreeItem *frameworkRoot : *rootItem())
@@ -171,14 +171,14 @@ QList<TestTreeItem *> TestTreeModel::testItemsByName(TestTreeItem *root, const Q
QList<TestTreeItem *> result;
root->forFirstLevelChildren([&testName, &result, this](TestTreeItem *node) {
- if (node->type() == TestTreeItem::TestCase) {
+ if (node->type() == TestTreeItem::TestSuite || node->type() == TestTreeItem::TestCase) {
if (node->name() == testName) {
result << node;
- return; // prioritize Tests over TestCases
+ return; // prioritize test suites and cases over test functions
}
TestTreeItem *testCase = node->findFirstLevelChild([&testName](TestTreeItem *it) {
QTC_ASSERT(it, return false);
- return it->type() == TestTreeItem::TestFunctionOrSet && it->name() == testName;
+ return it->type() == TestTreeItem::TestFunction && it->name() == testName;
}); // collect only actual tests, not special functions like init, cleanup etc.
if (testCase)
result << testCase;
@@ -215,7 +215,7 @@ void TestTreeModel::syncTestFrameworks()
void TestTreeModel::filterAndInsert(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled)
{
TestTreeItem *filtered = item->applyFilters();
- if (item->type() != TestTreeItem::TestCase || item->childCount())
+ if (item->shouldBeAddedAfterFiltering())
insertItemInParent(item, root, groupingEnabled);
else // might be that all children have been filtered out
delete item;
@@ -481,24 +481,30 @@ void TestTreeModel::removeTestRootNodes()
#ifdef WITH_TESTS
// we're inside tests - so use some internal knowledge to make testing easier
-TestTreeItem *qtRootNode()
+static TestTreeItem *qtRootNode()
{
return TestFrameworkManager::instance()->rootNodeForTestFramework(
Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtTest"));
}
-TestTreeItem *quickRootNode()
+static TestTreeItem *quickRootNode()
{
return TestFrameworkManager::instance()->rootNodeForTestFramework(
Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtQuickTest"));
}
-TestTreeItem *gtestRootNode()
+static TestTreeItem *gtestRootNode()
{
return TestFrameworkManager::instance()->rootNodeForTestFramework(
Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("GTest"));
}
+static TestTreeItem *boostTestRootNode()
+{
+ return TestFrameworkManager::instance()->rootNodeForTestFramework(
+ Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("Boost"));
+}
+
int TestTreeModel::autoTestsCount() const
{
TestTreeItem *rootNode = qtRootNode();
@@ -570,6 +576,25 @@ QMultiMap<QString, int> TestTreeModel::gtestNamesAndSets() const
}
return result;
}
+
+int TestTreeModel::boostTestNamesCount() const
+{
+ TestTreeItem *rootNode = boostTestRootNode();
+ return rootNode ? rootNode->childCount() : 0;
+}
+
+QMultiMap<QString, int> TestTreeModel::boostTestSuitesAndTests() const
+{
+ QMultiMap<QString, int> result;
+
+ if (TestTreeItem *rootNode = boostTestRootNode()) {
+ rootNode->forFirstLevelChildren([&result](TestTreeItem *child) {
+ result.insert(child->name(), child->childCount());
+ });
+ }
+ return result;
+}
+
#endif
/***************************** Sort/Filter Model **********************************/
diff --git a/src/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h
index 2945765d47..895a9a582e 100644
--- a/src/plugins/autotest/testtreemodel.h
+++ b/src/plugins/autotest/testtreemodel.h
@@ -56,7 +56,7 @@ public:
bool hasTests() const;
QList<TestConfiguration *> getAllTestCases() const;
QList<TestConfiguration *> getSelectedTests() const;
- QList<TestConfiguration *> getTestsForFile(const Utils::FileName &fileName) const;
+ QList<TestConfiguration *> getTestsForFile(const Utils::FilePath &fileName) const;
QList<TestTreeItem *> testItemsByName(const QString &testName);
void syncTestFrameworks();
void rebuild(const QList<Core::Id> &frameworkIds);
@@ -70,6 +70,8 @@ public:
int dataTagsCount() const;
int gtestNamesCount() const;
QMultiMap<QString, int> gtestNamesAndSets() const;
+ int boostTestNamesCount() const;
+ QMultiMap<QString, int> boostTestSuitesAndTests() const;
#endif
void markAllForRemoval();
diff --git a/src/plugins/autotest/unit_test/simple_boost/simple_boost.pro b/src/plugins/autotest/unit_test/simple_boost/simple_boost.pro
new file mode 100644
index 0000000000..f0f3a156bb
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/simple_boost.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += src tests
diff --git a/src/plugins/autotest/unit_test/simple_boost/simple_boost.qbs b/src/plugins/autotest/unit_test/simple_boost/simple_boost.qbs
new file mode 100644
index 0000000000..413f4f4971
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/simple_boost.qbs
@@ -0,0 +1,5 @@
+import qbs
+Project {
+ name: "SimpleBoost"
+ references: [ "src/src.qbs", "tests/tests.qbs" ]
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/src/main.cpp b/src/plugins/autotest/unit_test/simple_boost/src/main.cpp
new file mode 100644
index 0000000000..bc90974049
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/src/main.cpp
@@ -0,0 +1,6 @@
+#include <iostream>
+int main()
+{
+ std::cout << "Hello BoostWorld!\n";
+ return 0;
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/src/src.pro b/src/plugins/autotest/unit_test/simple_boost/src/src.pro
new file mode 100644
index 0000000000..0393f7894b
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/src/src.pro
@@ -0,0 +1,4 @@
+TEMPLATE = app
+CONFIG -= qt app_bundle
+CONFIG += console
+SOURCES += main.cpp
diff --git a/src/plugins/autotest/unit_test/simple_boost/src/src.qbs b/src/plugins/autotest/unit_test/simple_boost/src/src.qbs
new file mode 100644
index 0000000000..5b24d9d217
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/src/src.qbs
@@ -0,0 +1,6 @@
+import qbs
+CppApplication {
+ type: "application"
+ name: "HelloBoost application"
+ files: [ "main.cpp" ]
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.pro b/src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.pro
new file mode 100644
index 0000000000..0a69f075c2
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+CONFIG -= qt app_bundle
+CONFIG += console
+SOURCES += main.cpp
+HEADERS += enab.h
+
+isEmpty(BOOST_INCLUDE_DIR):BOOST_INCLUDE_DIR=$$(BOOST_INCLUDE_DIR)
+!isEmpty(BOOST_INCLUDE_DIR): INCLUDEPATH *= $$BOOST_INCLUDE_DIR
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.qbs b/src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.qbs
new file mode 100644
index 0000000000..1f53178c05
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/deco/deco.qbs
@@ -0,0 +1,11 @@
+import qbs
+import qbs.File
+CppApplication {
+ name: "Decorators Test"
+ type: "application"
+ Properties {
+ condition: project.boostIncDir && File.exists(project.boostIncDir)
+ cpp.includePaths: [project.boostIncDir];
+ }
+ files: [ "enab.h", "main.cpp" ]
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/deco/enab.h b/src/plugins/autotest/unit_test/simple_boost/tests/deco/enab.h
new file mode 100644
index 0000000000..2090c539eb
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/deco/enab.h
@@ -0,0 +1,23 @@
+#pragma once
+#include <boost/test/included/unit_test.hpp>
+
+namespace utf = boost::unit_test;
+
+BOOST_AUTO_TEST_SUITE(Suite1, * utf::disabled())
+ BOOST_AUTO_TEST_CASE(test1)
+ {
+ BOOST_TEST(1 != 1);
+ }
+ BOOST_AUTO_TEST_CASE(Test2, * utf::enabled())
+ {
+ BOOST_TEST(2 != 2);
+ }
+ BOOST_AUTO_TEST_CASE(TestIo, * utf::enable_if<true>())
+ {
+ BOOST_TEST(3 != 3);
+ }
+ BOOST_AUTO_TEST_CASE(TestDb, * utf::enable_if<false>())
+ {
+ BOOST_TEST(4 != 4);
+ }
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/deco/main.cpp b/src/plugins/autotest/unit_test/simple_boost/tests/deco/main.cpp
new file mode 100644
index 0000000000..aef3d912f3
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/deco/main.cpp
@@ -0,0 +1,21 @@
+#define BOOST_TEST_MODULE Suites and Decorators
+#include <boost/test/included/unit_test.hpp>
+#include "enab.h"
+using boost::unit_test::label;
+
+BOOST_AUTO_TEST_CASE(testWithout1, *label("WO")) { BOOST_TEST (true); }
+BOOST_AUTO_TEST_CASE(testWithout2, *label("WO")) { BOOST_TEST (false); }
+BOOST_AUTO_TEST_SUITE(SuiteOuter)
+ BOOST_AUTO_TEST_SUITE(SuiteInner1)
+ BOOST_AUTO_TEST_CASE(Test1) { BOOST_TEST (true); }
+ BOOST_AUTO_TEST_CASE(Test2) { BOOST_TEST (true); }
+ BOOST_AUTO_TEST_SUITE_END()
+ BOOST_AUTO_TEST_SUITE(SuiteInner2, *boost::unit_test::disabled())
+ BOOST_AUTO_TEST_CASE(Test1, *label("I2")) { BOOST_TEST (false); }
+ BOOST_AUTO_TEST_CASE(Test2, *label("I2")) { BOOST_TEST (false); }
+ BOOST_AUTO_TEST_SUITE_END()
+ BOOST_AUTO_TEST_CASE(Test1, *label("O1")) { BOOST_TEST (true); }
+ BOOST_AUTO_TEST_CASE(Test2) { BOOST_TEST (true); }
+ BOOST_AUTO_TEST_CASE(Test2A) { BOOST_TEST (true); }
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.cpp b/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.cpp
new file mode 100644
index 0000000000..54325e5f25
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.cpp
@@ -0,0 +1,18 @@
+#define BOOST_TEST_MODULE fixture example
+#include <boost/test/included/unit_test.hpp>
+
+struct F {
+ F() : i( 0 ) { BOOST_TEST_MESSAGE( "setup fixture" ); }
+ ~F() { BOOST_TEST_MESSAGE( "teardown fixture" ); }
+ int i;
+};
+
+BOOST_FIXTURE_TEST_CASE( test_case1, F )
+{
+ BOOST_TEST( i++ == 1 );
+}
+
+BOOST_FIXTURE_TEST_CASE( test_case2, F, * boost::unit_test::disabled() )
+{
+ BOOST_CHECK_EQUAL( i, 1 );
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.pro b/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.pro
new file mode 100644
index 0000000000..f070f564b0
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+CONFIG -= qt app_bundle
+CONFIG += console
+SOURCES += fix.cpp
+
+isEmpty(BOOST_INCLUDE_DIR):BOOST_INCLUDE_DIR=$$(BOOST_INCLUDE_DIR)
+!isEmpty(BOOST_INCLUDE_DIR): INCLUDEPATH *= $$BOOST_INCLUDE_DIR
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.qbs b/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.qbs
new file mode 100644
index 0000000000..5aa62d7888
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/fix/fix.qbs
@@ -0,0 +1,11 @@
+import qbs
+import qbs.File
+CppApplication {
+ name: "Fixture Test"
+ type: "application"
+ Properties {
+ condition: project.boostIncDir && File.exists(project.boostIncDir)
+ cpp.includePaths: [project.boostIncDir];
+ }
+ files: [ "fix.cpp" ]
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/params/main.cpp b/src/plugins/autotest/unit_test/simple_boost/tests/params/main.cpp
new file mode 100644
index 0000000000..b0821844db
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/params/main.cpp
@@ -0,0 +1,41 @@
+#include <boost/test/included/unit_test.hpp>
+#include <boost/test/parameterized_test.hpp>
+#include <boost/bind.hpp>
+
+using namespace boost::unit_test;
+
+class TestClass
+{
+public:
+ void testMethod()
+ {
+ BOOST_TEST( true );
+ }
+};
+
+void freeTestFunction()
+{
+ BOOST_TEST( true );
+}
+
+void freeTestFunction2(int i)
+{
+ BOOST_TEST( i < 4 );
+}
+
+test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
+{
+ boost::shared_ptr<TestClass> tester( new TestClass );
+
+ framework::master_test_suite().
+ add( BOOST_TEST_CASE( boost::bind( &TestClass::testMethod, tester )));
+
+ framework::master_test_suite().
+ add( BOOST_TEST_CASE( &freeTestFunction) );
+
+ int params[] = {1, 2, 3, 4, 5, 6};
+ framework::master_test_suite().
+ add( BOOST_PARAM_TEST_CASE( &freeTestFunction2, params, params + 6) );
+
+ return nullptr;
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/params/params.pro b/src/plugins/autotest/unit_test/simple_boost/tests/params/params.pro
new file mode 100644
index 0000000000..efea50f870
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/params/params.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+CONFIG -= qt app_bundle
+CONFIG += console
+SOURCES += main.cpp
+
+isEmpty(BOOST_INCLUDE_DIR):BOOST_INCLUDE_DIR=$$(BOOST_INCLUDE_DIR)
+!isEmpty(BOOST_INCLUDE_DIR): INCLUDEPATH *= $$BOOST_INCLUDE_DIR
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/params/params.qbs b/src/plugins/autotest/unit_test/simple_boost/tests/params/params.qbs
new file mode 100644
index 0000000000..5e4633cdb1
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/params/params.qbs
@@ -0,0 +1,11 @@
+import qbs
+import qbs.File
+CppApplication {
+ name: "Using Test Functions"
+ type: "application"
+ Properties {
+ condition: project.boostIncDir && File.exists(project.boostIncDir)
+ cpp.includePaths: [project.boostIncDir];
+ }
+ files: [ "main.cpp" ]
+}
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/tests.pro b/src/plugins/autotest/unit_test/simple_boost/tests/tests.pro
new file mode 100644
index 0000000000..160045bd75
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/tests.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += fix params deco
diff --git a/src/plugins/autotest/unit_test/simple_boost/tests/tests.qbs b/src/plugins/autotest/unit_test/simple_boost/tests/tests.qbs
new file mode 100644
index 0000000000..2033b5de2e
--- /dev/null
+++ b/src/plugins/autotest/unit_test/simple_boost/tests/tests.qbs
@@ -0,0 +1,11 @@
+import qbs
+import qbs.Environment
+Project {
+ name: "Tests"
+ property string boostIncDir: {
+ if (typeof Environment.getEnv("BOOST_INCLUDE_DIR") !== 'undefined')
+ return Environment.getEnv("BOOST_INCLUDE_DIR");
+ return undefined;
+ }
+ references: [ "deco/deco.qbs", "fix/fix.qbs", "params/params.qbs" ]
+}
diff --git a/src/plugins/autotest/unit_test/simple_gt/tests/common/functions.js b/src/plugins/autotest/unit_test/simple_gt/tests/common/functions.js
index 8ce7f31ad9..89cd648a31 100644
--- a/src/plugins/autotest/unit_test/simple_gt/tests/common/functions.js
+++ b/src/plugins/autotest/unit_test/simple_gt/tests/common/functions.js
@@ -1,8 +1,8 @@
-var FileInfo = loadExtension("qbs.FileInfo")
+var FileInfo = require("qbs.FileInfo")
-function getGTestDir(str) {
+function getGTestDir(Qbs, str) {
if (!str) {
- if (qbs.hostOS.contains("linux"))
+ if (Qbs.hostOS.contains("linux"))
return "/usr/include/gtest";
} else {
return FileInfo.joinPaths(str, "googletest");
@@ -10,9 +10,9 @@ function getGTestDir(str) {
return "";
}
-function getGMockDir(str) {
+function getGMockDir(Qbs, str) {
if (!str) {
- if (qbs.hostOS.contains("linux"))
+ if (Qbs.hostOS.contains("linux"))
return "/usr/include/gmock";
} else {
return FileInfo.joinPaths(str, "googlemock");
@@ -20,29 +20,29 @@ function getGMockDir(str) {
return "";
}
-function getGTestAll(str) {
- var gtest = getGTestDir(str);
+function getGTestAll(Qbs, str) {
+ var gtest = getGTestDir(Qbs, str);
if (!gtest)
return [];
return [FileInfo.joinPaths(gtest, "src/gtest-all.cc")];
}
-function getGMockAll(str) {
- var gmock = getGMockDir(str);
+function getGMockAll(Qbs, str) {
+ var gmock = getGMockDir(Qbs, str);
if (!gmock)
return [];
return [FileInfo.joinPaths(gmock, "src/gmock-all.cc")];
}
-function getGTestIncludes(str) {
- var gtest = getGTestDir(str);
+function getGTestIncludes(Qbs, str) {
+ var gtest = getGTestDir(Qbs, str);
if (!gtest)
return [];
return [gtest, FileInfo.joinPaths(gtest, "include")];
}
-function getGMockIncludes(str) {
- var mock = getGMockDir(str);
+function getGMockIncludes(Qbs, str) {
+ var mock = getGMockDir(Qbs, str);
if (!mock)
return [];
return [mock, FileInfo.joinPaths(mock, "include")];
diff --git a/src/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.qbs b/src/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.qbs
index f560bb41e6..ac59d83da8 100644
--- a/src/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.qbs
+++ b/src/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.qbs
@@ -7,8 +7,8 @@ CppApplication {
type: "application"
name: "googletest1"
- property string gtestDir: googleCommon.getGTestDir(project.googletestDir)
- property string gmockDir: googleCommon.getGMockDir(project.googletestDir)
+ property string gtestDir: googleCommon.getGTestDir(qbs, project.googletestDir)
+ property string gmockDir: googleCommon.getGMockDir(qbs, project.googletestDir)
condition: {
if (File.exists(gtestDir) && File.exists(gmockDir))
@@ -19,8 +19,8 @@ CppApplication {
return false;
}
- cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir))
- .concat(googleCommon.getGMockIncludes(project.googletestDir))
+ cpp.includePaths: [].concat(googleCommon.getGTestIncludes(qbs, project.googletestDir))
+ .concat(googleCommon.getGMockIncludes(qbs, project.googletestDir))
cpp.cxxLanguageVersion: "c++11"
cpp.defines: ["GTEST_LANG_CXX11"]
@@ -30,6 +30,6 @@ CppApplication {
// own stuff
"further.cpp",
"main.cpp",
- ].concat(googleCommon.getGTestAll(project.googletestDir))
- .concat(googleCommon.getGMockAll(project.googletestDir))
+ ].concat(googleCommon.getGTestAll(qbs, project.googletestDir))
+ .concat(googleCommon.getGMockAll(qbs, project.googletestDir))
}
diff --git a/src/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.qbs b/src/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.qbs
index b0a898103f..98fdc1e4c9 100644
--- a/src/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.qbs
+++ b/src/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.qbs
@@ -7,8 +7,8 @@ CppApplication {
type: "application"
name: "googletest2"
- property string gtestDir: googleCommon.getGTestDir(project.googletestDir)
- property string gmockDir: googleCommon.getGMockDir(project.googletestDir)
+ property string gtestDir: googleCommon.getGTestDir(qbs, project.googletestDir)
+ property string gmockDir: googleCommon.getGMockDir(qbs, project.googletestDir)
Depends { name: "Qt.core" }
@@ -21,8 +21,8 @@ CppApplication {
return false;
}
- cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir))
- .concat(googleCommon.getGMockIncludes(project.googletestDir))
+ cpp.includePaths: [].concat(googleCommon.getGTestIncludes(qbs, project.googletestDir))
+ .concat(googleCommon.getGMockIncludes(qbs, project.googletestDir))
cpp.cxxLanguageVersion: "c++11"
cpp.defines: ["GTEST_LANG_CXX11"]
@@ -31,6 +31,6 @@ CppApplication {
// own stuff
"queuetest.h",
"main.cpp",
- ].concat(googleCommon.getGTestAll(project.googletestDir))
- .concat(googleCommon.getGMockAll(project.googletestDir))
+ ].concat(googleCommon.getGTestAll(qbs, project.googletestDir))
+ .concat(googleCommon.getGMockAll(qbs, project.googletestDir))
}
diff --git a/src/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h b/src/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h
index 7fb47e8e62..815db2bab2 100644
--- a/src/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h
+++ b/src/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h
@@ -25,6 +25,7 @@
#pragma once
+#include <gtest/gtest.h>
#include <QQueue>
class QueueTest : public ::testing::Test
diff --git a/src/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.qbs b/src/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.qbs
index 2bd250a588..e41b820594 100644
--- a/src/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.qbs
+++ b/src/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.qbs
@@ -7,8 +7,8 @@ CppApplication {
type: "application"
name: "googletest3"
- property string gtestDir: googleCommon.getGTestDir(project.googletestDir)
- property string gmockDir: googleCommon.getGMockDir(project.googletestDir)
+ property string gtestDir: googleCommon.getGTestDir(qbs, project.googletestDir)
+ property string gmockDir: googleCommon.getGMockDir(qbs, project.googletestDir)
Depends { name: "Qt.core" }
@@ -21,8 +21,8 @@ CppApplication {
return false;
}
- cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir))
- .concat(googleCommon.getGMockIncludes(project.googletestDir))
+ cpp.includePaths: [].concat(googleCommon.getGTestIncludes(qbs, project.googletestDir))
+ .concat(googleCommon.getGMockIncludes(qbs, project.googletestDir))
cpp.cxxLanguageVersion: "c++11"
cpp.defines: ["GTEST_LANG_CXX11"]
@@ -31,6 +31,6 @@ CppApplication {
// own stuff
"dummytest.h",
"main.cpp",
- ].concat(googleCommon.getGTestAll(project.googletestDir))
- .concat(googleCommon.getGMockAll(project.googletestDir))
+ ].concat(googleCommon.getGTestAll(qbs, project.googletestDir))
+ .concat(googleCommon.getGMockAll(qbs, project.googletestDir))
}
diff --git a/src/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp b/src/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp
index 4f048fa177..a7d8591512 100644
--- a/src/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp
+++ b/src/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp
@@ -56,8 +56,8 @@ static QMap<const char *, QStringList> testValuesSec = {
},
};
-INSTANTIATE_TEST_CASE_P(First, DummyTest, ::testing::ValuesIn(testValues.keys()));
-INSTANTIATE_TEST_CASE_P(Second, DummyTest, ::testing::ValuesIn(testValuesSec.keys()));
+INSTANTIATE_TEST_SUITE_P(First, DummyTest, ::testing::ValuesIn(testValues.keys()));
+INSTANTIATE_TEST_SUITE_P(Second, DummyTest, ::testing::ValuesIn(testValuesSec.keys()));
TEST_P(DummyTest, Easy)
{
diff --git a/src/plugins/autotoolsprojectmanager/CMakeLists.txt b/src/plugins/autotoolsprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..ca8765cba9
--- /dev/null
+++ b/src/plugins/autotoolsprojectmanager/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_qtc_plugin(AutotoolsProjectManager
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer QtSupport
+ SOURCES
+ autogenstep.cpp autogenstep.h
+ autoreconfstep.cpp autoreconfstep.h
+ autotoolsbuildconfiguration.cpp autotoolsbuildconfiguration.h
+ autotoolsopenprojectwizard.cpp autotoolsopenprojectwizard.h
+ autotoolsproject.cpp autotoolsproject.h
+ autotoolsprojectconstants.h
+ autotoolsprojectplugin.cpp autotoolsprojectplugin.h
+ configurestep.cpp configurestep.h
+ makefileparser.cpp makefileparser.h
+ makefileparserthread.cpp makefileparserthread.h
+ makestep.cpp makestep.h
+)
diff --git a/src/plugins/autotoolsprojectmanager/autogenstep.cpp b/src/plugins/autotoolsprojectmanager/autogenstep.cpp
index 77f9193b41..fcb6b5c9ac 100644
--- a/src/plugins/autotoolsprojectmanager/autogenstep.cpp
+++ b/src/plugins/autotoolsprojectmanager/autogenstep.cpp
@@ -77,9 +77,8 @@ bool AutogenStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
pp->setEnvironment(bc->environment());
- const QString projectDir(bc->target()->project()->projectDirectory().toString());
- pp->setWorkingDirectory(projectDir);
- pp->setCommand("./autogen.sh");
+ pp->setWorkingDirectory(bc->target()->project()->projectDirectory());
+ pp->setCommand(Utils::FilePath::fromString("./autogen.sh"));
pp->setArguments(m_additionalArgumentsAspect->value());
pp->resolveAll();
@@ -122,9 +121,8 @@ BuildStepConfigWidget *AutogenStep::createConfigWidget()
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
param.setEnvironment(bc->environment());
- const QString projectDir(bc->target()->project()->projectDirectory().toString());
- param.setWorkingDirectory(projectDir);
- param.setCommand("./autogen.sh");
+ param.setWorkingDirectory(bc->target()->project()->projectDirectory());
+ param.setCommand(Utils::FilePath::fromString("./autogen.sh"));
param.setArguments(m_additionalArgumentsAspect->value());
widget->setSummaryText(param.summary(displayName()));
diff --git a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp
index ab9ae1147f..58ee0f383b 100644
--- a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp
+++ b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp
@@ -75,9 +75,8 @@ bool AutoreconfStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
pp->setEnvironment(bc->environment());
- const QString projectDir(bc->target()->project()->projectDirectory().toString());
- pp->setWorkingDirectory(projectDir);
- pp->setCommand("autoreconf");
+ pp->setWorkingDirectory(bc->target()->project()->projectDirectory());
+ pp->setCommand(Utils::FilePath::fromString("autoreconf"));
pp->setArguments(m_additionalArgumentsAspect->value());
pp->resolveAll();
@@ -114,9 +113,8 @@ BuildStepConfigWidget *AutoreconfStep::createConfigWidget()
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
param.setEnvironment(bc->environment());
- const QString projectDir(bc->target()->project()->projectDirectory().toString());
- param.setWorkingDirectory(projectDir);
- param.setCommand("autoreconf");
+ param.setWorkingDirectory(bc->target()->project()->projectDirectory());
+ param.setCommand(Utils::FilePath::fromString("autoreconf"));
param.setArguments(m_additionalArgumentsAspect->value());
widget->setSummaryText(param.summary(displayName()));
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp
index 33ebf0f188..0007ddf447 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp
@@ -26,7 +26,6 @@
****************************************************************************/
#include "autotoolsbuildconfiguration.h"
-#include "autotoolsbuildsettingswidget.h"
#include "makestep.h"
#include "autotoolsproject.h"
#include "autotoolsprojectconstants.h"
@@ -44,15 +43,13 @@
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
-#include <QFileInfo>
-#include <QInputDialog>
-
-using namespace AutotoolsProjectManager;
using namespace AutotoolsProjectManager::Constants;
-using namespace Internal;
using namespace ProjectExplorer;
using namespace ProjectExplorer::Constants;
+using namespace Utils;
+namespace AutotoolsProjectManager {
+namespace Internal {
// AutotoolsBuildConfiguration
@@ -61,7 +58,9 @@ AutotoolsBuildConfiguration::AutotoolsBuildConfiguration(Target *parent, Core::I
{
// /<foobar> is used so the un-changed check in setBuildDirectory() works correctly.
// The leading / is to avoid the relative the path expansion in BuildConfiguration::buildDirectory.
- setBuildDirectory(Utils::FileName::fromString("/<foobar>"));
+ setBuildDirectory(Utils::FilePath::fromString("/<foobar>"));
+ setBuildDirectoryHistoryCompleter("AutoTools.BuildDir.History");
+ setConfigWidgetDisplayName(tr("Autotools Manager"));
}
void AutotoolsBuildConfiguration::initialize(const BuildInfo &info)
@@ -97,11 +96,6 @@ void AutotoolsBuildConfiguration::initialize(const BuildInfo &info)
cleanSteps->appendStep(cleanMakeStep);
}
-NamedWidget *AutotoolsBuildConfiguration::createConfigWidget()
-{
- return new AutotoolsBuildSettingsWidget(this);
-}
-
// AutotoolsBuildConfiguration class
@@ -121,15 +115,15 @@ QList<BuildInfo> AutotoolsBuildConfigurationFactory::availableBuilds(const Targe
QList<BuildInfo> AutotoolsBuildConfigurationFactory::availableSetups(const Kit *k, const QString &projectPath) const
{
- BuildInfo info = createBuildInfo(k,
- Utils::FileName::fromString(AutotoolsProject::defaultBuildDirectory(projectPath)));
+ const QString path = QFileInfo(projectPath).absolutePath();
+ BuildInfo info = createBuildInfo(k, Utils::FilePath::fromString(path));
//: The name of the build configuration created by default for a autotools project.
info.displayName = tr("Default");
return {info};
}
BuildInfo AutotoolsBuildConfigurationFactory::createBuildInfo(const Kit *k,
- const Utils::FileName &buildDir) const
+ const Utils::FilePath &buildDir) const
{
BuildInfo info(this);
info.typeName = tr("Build");
@@ -143,3 +137,6 @@ BuildConfiguration::BuildType AutotoolsBuildConfiguration::buildType() const
// TODO: Should I return something different from Unknown?
return Unknown;
}
+
+} // Internal
+} // AutotoolsProjectManager
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.h b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.h
index 2cd784c235..ec33f6a224 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.h
+++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.h
@@ -29,7 +29,7 @@
#include <projectexplorer/buildconfiguration.h>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace AutotoolsProjectManager {
namespace Internal {
@@ -42,7 +42,6 @@ class AutotoolsBuildConfiguration : public ProjectExplorer::BuildConfiguration
AutotoolsBuildConfiguration(ProjectExplorer::Target *parent, Core::Id id);
void initialize(const ProjectExplorer::BuildInfo &info) override;
- ProjectExplorer::NamedWidget *createConfigWidget() override;
BuildType buildType() const override;
};
@@ -58,7 +57,7 @@ private:
QList<ProjectExplorer::BuildInfo> availableSetups(const ProjectExplorer::Kit *k,
const QString &projectPath) const override;
- ProjectExplorer::BuildInfo createBuildInfo(const ProjectExplorer::Kit *k, const Utils::FileName &buildDir) const;
+ ProjectExplorer::BuildInfo createBuildInfo(const ProjectExplorer::Kit *k, const Utils::FilePath &buildDir) const;
};
} // namespace Internal
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.cpp
deleted file mode 100644
index 08eb39d7ee..0000000000
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Openismus GmbH.
-** Author: Peter Penz (ppenz@openismus.com)
-** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "autotoolsbuildsettingswidget.h"
-#include "autotoolsproject.h"
-#include "autotoolsbuildconfiguration.h"
-
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/target.h>
-
-#include <utils/pathchooser.h>
-
-#include <QGridLayout>
-#include <QLabel>
-#include <QLineEdit>
-#include <QFormLayout>
-#include <QComboBox>
-#include <QPointer>
-
-using namespace AutotoolsProjectManager;
-using namespace AutotoolsProjectManager::Internal;
-using namespace ProjectExplorer;
-
-AutotoolsBuildSettingsWidget::AutotoolsBuildSettingsWidget(AutotoolsBuildConfiguration *bc) :
- m_pathChooser(new Utils::PathChooser),
- m_buildConfiguration(bc)
-{
- auto fl = new QFormLayout(this);
- fl->setContentsMargins(0, 0, 0, 0);
- fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
-
- m_pathChooser->setEnabled(true);
- m_pathChooser->setExpectedKind(Utils::PathChooser::Directory);
- m_pathChooser->setBaseFileName(bc->target()->project()->projectDirectory());
- m_pathChooser->setEnvironment(bc->environment());
- m_pathChooser->setHistoryCompleter(QLatin1String("AutoTools.BuildDir.History"));
- fl->addRow(tr("Build directory:"), m_pathChooser);
- connect(m_pathChooser, &Utils::PathChooser::rawPathChanged,
- this, &AutotoolsBuildSettingsWidget::buildDirectoryChanged);
-
- m_pathChooser->setBaseFileName(bc->target()->project()->projectDirectory());
- m_pathChooser->setPath(m_buildConfiguration->rawBuildDirectory().toString());
- setDisplayName(tr("Autotools Manager"));
-
- connect(bc, &BuildConfiguration::environmentChanged,
- this, &AutotoolsBuildSettingsWidget::environmentHasChanged);
-}
-
-void AutotoolsBuildSettingsWidget::buildDirectoryChanged()
-{
- m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_pathChooser->rawPath()));
-}
-
-void AutotoolsBuildSettingsWidget::environmentHasChanged()
-{
- m_pathChooser->setEnvironment(m_buildConfiguration->environment());
-}
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.h b/src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.h
deleted file mode 100644
index 8419a57962..0000000000
--- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsettingswidget.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Openismus GmbH.
-** Author: Peter Penz (ppenz@openismus.com)
-** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/namedwidget.h>
-
-QT_BEGIN_NAMESPACE
-class QComboBox;
-QT_END_NAMESPACE
-
-namespace Utils { class PathChooser; }
-
-namespace AutotoolsProjectManager {
-namespace Internal {
-
-class AutotoolsBuildConfiguration;
-
-/**
- * @brief Implementation of ProjectExplorer::BuildConfigWidget interface.
- *
- * Provides an editor to configure the build directory and build steps.
- */
-class AutotoolsBuildSettingsWidget : public ProjectExplorer::NamedWidget
-{
- Q_OBJECT
-
-public:
- AutotoolsBuildSettingsWidget(AutotoolsBuildConfiguration *bc);
-
-private:
- void buildDirectoryChanged();
- void environmentHasChanged();
-
- Utils::PathChooser *m_pathChooser;
- AutotoolsBuildConfiguration *m_buildConfiguration;
-};
-
-} // namespace Internal
-} // namespace AutotoolsProjectManager
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp
index a4f0b40433..baafa22bfa 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp
@@ -28,7 +28,6 @@
#include "autotoolsproject.h"
#include "autotoolsbuildconfiguration.h"
#include "autotoolsprojectconstants.h"
-#include "autotoolsprojectnode.h"
#include "autotoolsopenprojectwizard.h"
#include "makestep.h"
#include "makefileparserthread.h"
@@ -40,6 +39,7 @@
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectnodes.h>
#include <projectexplorer/target.h>
#include <projectexplorer/headerpath.h>
#include <extensionsystem/pluginmanager.h>
@@ -68,7 +68,7 @@ using namespace AutotoolsProjectManager;
using namespace AutotoolsProjectManager::Internal;
using namespace ProjectExplorer;
-AutotoolsProject::AutotoolsProject(const Utils::FileName &fileName) :
+AutotoolsProject::AutotoolsProject(const Utils::FilePath &fileName) :
Project(Constants::MAKEFILE_MIMETYPE, fileName),
m_fileWatcher(new Utils::FileSystemWatcher(this)),
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
@@ -91,11 +91,6 @@ AutotoolsProject::~AutotoolsProject()
}
}
-QString AutotoolsProject::defaultBuildDirectory(const QString &projectPath)
-{
- return QFileInfo(projectPath).absolutePath();
-}
-
// This function, is called at the very beginning, to
// restore the settings if there are some stored.
Project::RestoreResult AutotoolsProject::fromMap(const QVariantMap &map, QString *errorMessage)
@@ -172,8 +167,7 @@ void AutotoolsProject::makefileParsingFinished()
// Remove file watches for the current project state.
// The file watches will be added again after the parsing.
- foreach (const QString& watchedFile, m_watchedFiles)
- m_fileWatcher->removeFile(watchedFile);
+ m_fileWatcher->removeFiles(m_watchedFiles);
m_files.clear();
m_watchedFiles.clear();
@@ -208,11 +202,11 @@ void AutotoolsProject::makefileParsingFinished()
m_watchedFiles.append(absConfigureAc);
}
- auto newRoot = std::make_unique<AutotoolsProjectNode>(projectDirectory());
+ auto newRoot = std::make_unique<ProjectNode>(projectDirectory());
for (const QString &f : m_files) {
- const Utils::FileName path = Utils::FileName::fromString(f);
- newRoot->addNestedNode(std::make_unique<FileNode>(path, FileNode::fileTypeForFileName(path),
- false));
+ const Utils::FilePath path = Utils::FilePath::fromString(f);
+ newRoot->addNestedNode(std::make_unique<FileNode>(path,
+ FileNode::fileTypeForFileName(path)));
}
setRootProjectNode(std::move(newRoot));
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.h b/src/plugins/autotoolsprojectmanager/autotoolsproject.h
index b9016bdcc0..fcd81d093b 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsproject.h
+++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.h
@@ -53,16 +53,17 @@ class AutotoolsProject : public ProjectExplorer::Project
Q_OBJECT
public:
- explicit AutotoolsProject(const Utils::FileName &fileName);
+ explicit AutotoolsProject(const Utils::FilePath &fileName);
~AutotoolsProject() override;
- static QString defaultBuildDirectory(const QString &projectPath);
QStringList buildTargets() const;
protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
private:
+ bool hasMakeInstallEquivalent() const override { return true; }
+
/**
* Loads the project tree by parsing the makefiles.
*/
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro
index a58d556dda..92b6dd8e7d 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro
+++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro
@@ -2,9 +2,7 @@ include(../../qtcreatorplugin.pri)
HEADERS = autotoolsprojectplugin.h\
autotoolsopenprojectwizard.h\
- autotoolsprojectnode.h\
autotoolsproject.h\
- autotoolsbuildsettingswidget.h\
autotoolsbuildconfiguration.h\
autotoolsprojectconstants.h\
makestep.h\
@@ -13,11 +11,10 @@ HEADERS = autotoolsprojectplugin.h\
configurestep.h\
makefileparserthread.h\
makefileparser.h
+
SOURCES = autotoolsprojectplugin.cpp\
autotoolsopenprojectwizard.cpp\
- autotoolsprojectnode.cpp\
autotoolsproject.cpp\
- autotoolsbuildsettingswidget.cpp\
autotoolsbuildconfiguration.cpp\
makestep.cpp\
autogenstep.cpp\
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs
index 02ab46557c..a6e4a2721b 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs
+++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs
@@ -18,15 +18,11 @@ QtcPlugin {
"autoreconfstep.h",
"autotoolsbuildconfiguration.cpp",
"autotoolsbuildconfiguration.h",
- "autotoolsbuildsettingswidget.cpp",
- "autotoolsbuildsettingswidget.h",
"autotoolsopenprojectwizard.cpp",
"autotoolsopenprojectwizard.h",
"autotoolsproject.cpp",
"autotoolsproject.h",
"autotoolsprojectconstants.h",
- "autotoolsprojectnode.cpp",
- "autotoolsprojectnode.h",
"autotoolsprojectplugin.cpp",
"autotoolsprojectplugin.h",
"configurestep.cpp",
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectnode.cpp b/src/plugins/autotoolsprojectmanager/autotoolsprojectnode.cpp
deleted file mode 100644
index 793d63a762..0000000000
--- a/src/plugins/autotoolsprojectmanager/autotoolsprojectnode.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Openismus GmbH.
-** Author: Peter Penz (ppenz@openismus.com)
-** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "autotoolsprojectnode.h"
-#include "autotoolsproject.h"
-
-#include <coreplugin/idocument.h>
-
-using namespace AutotoolsProjectManager;
-using namespace AutotoolsProjectManager::Internal;
-using namespace ProjectExplorer;
-
-AutotoolsProjectNode::AutotoolsProjectNode(const Utils::FileName &projectDirectory) :
- ProjectNode(projectDirectory)
-{ }
-
-bool AutotoolsProjectNode::showInSimpleTree() const
-{
- return true;
-}
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectnode.h b/src/plugins/autotoolsprojectmanager/autotoolsprojectnode.h
deleted file mode 100644
index a60479eb8c..0000000000
--- a/src/plugins/autotoolsprojectmanager/autotoolsprojectnode.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Openismus GmbH.
-** Author: Peter Penz (ppenz@openismus.com)
-** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/projectnodes.h>
-
-namespace Core { class IDocument; }
-
-namespace AutotoolsProjectManager {
-namespace Internal {
-
-class AutotoolsProject;
-
-/**
- * @brief Implementation of the ProjectExplorer::ProjectNode interface.
- *
- * A project node represents a file or a folder of the project tree.
- * No special operations (addFiles(), removeFiles(), renameFile(), ..)
- * are offered.
- *
- * @see AutotoolsProject
- */
-class AutotoolsProjectNode : public ProjectExplorer::ProjectNode
-{
-public:
- AutotoolsProjectNode(const Utils::FileName &projectDirectory);
-
- bool showInSimpleTree() const override;
-};
-
-} // namespace Internal
-} // namespace AutotoolsProjectManager
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp
index b18e276730..5b3643dcd3 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp
@@ -39,7 +39,7 @@
namespace AutotoolsProjectManager {
namespace Internal {
-class AutotoolsProjectPluginRunData
+class AutotoolsProjectPluginPrivate
{
public:
AutotoolsBuildConfigurationFactory buildConfigurationFactory;
@@ -51,7 +51,7 @@ public:
AutotoolsProjectPlugin::~AutotoolsProjectPlugin()
{
- delete m_runData;
+ delete d;
}
void AutotoolsProjectPlugin::extensionsInitialized()
@@ -63,7 +63,7 @@ bool AutotoolsProjectPlugin::initialize(const QStringList &arguments,
Q_UNUSED(arguments)
Q_UNUSED(errorString)
- m_runData = new AutotoolsProjectPluginRunData;
+ d = new AutotoolsProjectPluginPrivate;
ProjectExplorer::ProjectManager::registerProjectType<AutotoolsProject>(Constants::MAKEFILE_MIMETYPE);
return true;
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h
index 5e710ff050..dd08cbd1c8 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h
+++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h
@@ -60,8 +60,6 @@ namespace Internal {
* be executed in the build process)
*/
-class AutotoolsProjectPluginRunData;
-
class AutotoolsProjectPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -72,7 +70,7 @@ class AutotoolsProjectPlugin : public ExtensionSystem::IPlugin
void extensionsInitialized() final;
bool initialize(const QStringList &arguments, QString *errorString) final;
- AutotoolsProjectPluginRunData *m_runData;
+ class AutotoolsProjectPluginPrivate *d;
};
} // namespace Internal
diff --git a/src/plugins/autotoolsprojectmanager/configurestep.cpp b/src/plugins/autotoolsprojectmanager/configurestep.cpp
index 66fcbc03e3..91b72eb4af 100644
--- a/src/plugins/autotoolsprojectmanager/configurestep.cpp
+++ b/src/plugins/autotoolsprojectmanager/configurestep.cpp
@@ -97,8 +97,8 @@ bool ConfigureStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
pp->setEnvironment(bc->environment());
- pp->setWorkingDirectory(bc->buildDirectory().toString());
- pp->setCommand(projectDirRelativeToBuildDir(bc) + "configure");
+ pp->setWorkingDirectory(bc->buildDirectory());
+ pp->setCommand(Utils::FilePath::fromString(projectDirRelativeToBuildDir(bc) + "configure"));
pp->setArguments(m_additionalArgumentsAspect->value());
pp->resolveAll();
@@ -158,8 +158,8 @@ void ConfigureStep::updateDetails()
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
param.setEnvironment(bc->environment());
- param.setWorkingDirectory(bc->buildDirectory().toString());
- param.setCommand(projectDirRelativeToBuildDir(bc) + "configure");
+ param.setWorkingDirectory(bc->buildDirectory());
+ param.setCommand(Utils::FilePath::fromString(projectDirRelativeToBuildDir(bc) + "configure"));
param.setArguments(m_additionalArgumentsAspect->value());
m_widget->setSummaryText(param.summaryInWorkdir(displayName()));
diff --git a/src/plugins/baremetal/CMakeLists.txt b/src/plugins/baremetal/CMakeLists.txt
new file mode 100644
index 0000000000..f9d9bc0dc5
--- /dev/null
+++ b/src/plugins/baremetal/CMakeLists.txt
@@ -0,0 +1,30 @@
+add_qtc_plugin(BareMetal
+ DEPENDS QtcSsh
+ PLUGIN_DEPENDS Core Debugger ProjectExplorer
+ SOURCES
+ baremetal.qrc
+ baremetalconstants.h
+ baremetalcustomrunconfiguration.cpp baremetalcustomrunconfiguration.h
+ baremetaldebugsupport.cpp baremetaldebugsupport.h
+ baremetaldevice.cpp baremetaldevice.h
+ baremetaldeviceconfigurationwidget.cpp baremetaldeviceconfigurationwidget.h
+ baremetaldeviceconfigurationwizard.cpp baremetaldeviceconfigurationwizard.h
+ baremetaldeviceconfigurationwizardpages.cpp baremetaldeviceconfigurationwizardpages.h
+ baremetalgdbcommandsdeploystep.cpp baremetalgdbcommandsdeploystep.h
+ baremetalplugin.cpp baremetalplugin.h
+ baremetalrunconfiguration.cpp baremetalrunconfiguration.h
+ defaultgdbserverprovider.cpp defaultgdbserverprovider.h
+ gdbserverprovider.cpp gdbserverprovider.h
+ gdbserverproviderchooser.cpp gdbserverproviderchooser.h
+ gdbserverprovidermanager.cpp gdbserverprovidermanager.h
+ gdbserverproviderprocess.cpp gdbserverproviderprocess.h
+ gdbserverproviderssettingspage.cpp gdbserverproviderssettingspage.h
+ iarewparser.cpp iarewparser.h
+ iarewtoolchain.cpp iarewtoolchain.h
+ keilparser.cpp keilparser.h
+ keiltoolchain.cpp keiltoolchain.h
+ sdccparser.cpp sdccparser.h
+ sdcctoolchain.cpp sdcctoolchain.h
+ openocdgdbserverprovider.cpp openocdgdbserverprovider.h
+ stlinkutilgdbserverprovider.cpp stlinkutilgdbserverprovider.h
+)
diff --git a/src/plugins/baremetal/baremetal.pro b/src/plugins/baremetal/baremetal.pro
index 886cc98284..ac49b0041f 100644
--- a/src/plugins/baremetal/baremetal.pro
+++ b/src/plugins/baremetal/baremetal.pro
@@ -11,7 +11,6 @@ SOURCES += baremetalplugin.cpp \
baremetaldeviceconfigurationwizardpages.cpp \
baremetaldeviceconfigurationwizard.cpp \
baremetaldeviceconfigurationwidget.cpp \
- baremetaldeviceconfigurationfactory.cpp \
baremetaldebugsupport.cpp \
gdbserverproviderprocess.cpp \
gdbserverproviderssettingspage.cpp \
@@ -20,7 +19,13 @@ SOURCES += baremetalplugin.cpp \
gdbserverprovidermanager.cpp \
openocdgdbserverprovider.cpp \
defaultgdbserverprovider.cpp \
- stlinkutilgdbserverprovider.cpp
+ stlinkutilgdbserverprovider.cpp \
+ iarewtoolchain.cpp \
+ keiltoolchain.cpp \
+ sdcctoolchain.cpp \
+ iarewparser.cpp \
+ keilparser.cpp \
+ sdccparser.cpp \
HEADERS += baremetalplugin.h \
baremetalconstants.h \
@@ -28,7 +33,6 @@ HEADERS += baremetalplugin.h \
baremetaldevice.h \
baremetalrunconfiguration.h \
baremetalgdbcommandsdeploystep.h \
- baremetaldeviceconfigurationfactory.h \
baremetaldeviceconfigurationwidget.h \
baremetaldeviceconfigurationwizard.h \
baremetaldeviceconfigurationwizardpages.h \
@@ -40,7 +44,13 @@ HEADERS += baremetalplugin.h \
gdbserverprovidermanager.h \
openocdgdbserverprovider.h \
defaultgdbserverprovider.h \
- stlinkutilgdbserverprovider.h
+ stlinkutilgdbserverprovider.h \
+ iarewtoolchain.h \
+ keiltoolchain.h \
+ sdcctoolchain.h \
+ iarewparser.h \
+ keilparser.h \
+ sdccparser.h \
RESOURCES += \
baremetal.qrc
diff --git a/src/plugins/baremetal/baremetal.qbs b/src/plugins/baremetal/baremetal.qbs
index 04c1b228b1..018c2dc23b 100644
--- a/src/plugins/baremetal/baremetal.qbs
+++ b/src/plugins/baremetal/baremetal.qbs
@@ -10,13 +10,13 @@ QtcPlugin {
Depends { name: "Core" }
Depends { name: "Debugger" }
Depends { name: "ProjectExplorer" }
+ Depends { name: "TextEditor" }
files: [
"baremetal.qrc",
"baremetalconstants.h",
"baremetalcustomrunconfiguration.cpp", "baremetalcustomrunconfiguration.h",
"baremetaldevice.cpp", "baremetaldevice.h",
- "baremetaldeviceconfigurationfactory.cpp", "baremetaldeviceconfigurationfactory.h",
"baremetaldeviceconfigurationwidget.cpp", "baremetaldeviceconfigurationwidget.h",
"baremetaldeviceconfigurationwizard.cpp", "baremetaldeviceconfigurationwizard.h",
"baremetaldeviceconfigurationwizardpages.cpp", "baremetaldeviceconfigurationwizardpages.h",
@@ -32,5 +32,11 @@ QtcPlugin {
"openocdgdbserverprovider.cpp", "openocdgdbserverprovider.h",
"defaultgdbserverprovider.cpp", "defaultgdbserverprovider.h",
"stlinkutilgdbserverprovider.cpp", "stlinkutilgdbserverprovider.h",
+ "iarewtoolchain.cpp", "iarewtoolchain.h",
+ "keiltoolchain.cpp", "keiltoolchain.h",
+ "sdcctoolchain.cpp", "sdcctoolchain.h",
+ "iarewparser.cpp", "iarewparser.h",
+ "keilparser.cpp", "keilparser.h",
+ "sdccparser.cpp", "sdccparser.h",
]
}
diff --git a/src/plugins/baremetal/baremetalconstants.h b/src/plugins/baremetal/baremetalconstants.h
index def7271577..9f8a08cc50 100644
--- a/src/plugins/baremetal/baremetalconstants.h
+++ b/src/plugins/baremetal/baremetalconstants.h
@@ -41,5 +41,10 @@ const char OPENOCD_PROVIDER_ID[] = "BareMetal.GdbServerProvider.OpenOcd";
const char DEFAULT_PROVIDER_ID[] = "BareMetal.GdbServerProvider.Default";
const char STLINK_UTIL_PROVIDER_ID[] = "BareMetal.GdbServerProvider.STLinkUtil";
+// Toolchain types.
+const char IAREW_TOOLCHAIN_TYPEID[] = "BareMetal.ToolChain.Iar";
+const char KEIL_TOOLCHAIN_TYPEID[] = "BareMetal.ToolChain.Keil";
+const char SDCC_TOOLCHAIN_TYPEID[] = "BareMetal.ToolChain.Sdcc";
+
} // namespace BareMetal
} // namespace Constants
diff --git a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp
index 14b957d5e4..db4aac7622 100644
--- a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp
+++ b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp
@@ -24,11 +24,10 @@
****************************************************************************/
#include "baremetalcustomrunconfiguration.h"
-
#include "baremetalconstants.h"
-#include <projectexplorer/target.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/target.h>
#include <qtsupport/qtoutputformatter.h>
@@ -38,10 +37,12 @@ using namespace ProjectExplorer;
namespace BareMetal {
namespace Internal {
+// BareMetalCustomRunConfiguration
+
BareMetalCustomRunConfiguration::BareMetalCustomRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- auto exeAspect = addAspect<ExecutableAspect>();
+ const auto exeAspect = addAspect<ExecutableAspect>();
exeAspect->setSettingsKey("BareMetal.CustomRunConfig.Executable");
exeAspect->setPlaceHolderText(tr("Unknown"));
exeAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
@@ -49,7 +50,7 @@ BareMetalCustomRunConfiguration::BareMetalCustomRunConfiguration(Target *target,
exeAspect->setExpectedKind(PathChooser::Any);
addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>(nullptr);
+ addAspect<WorkingDirectoryAspect>();
setDefaultDisplayName(RunConfigurationFactory::decoratedTargetName(tr("Custom Executable"), target));
}
diff --git a/src/plugins/baremetal/baremetalcustomrunconfiguration.h b/src/plugins/baremetal/baremetalcustomrunconfiguration.h
index 72b1500511..a7ccd48233 100644
--- a/src/plugins/baremetal/baremetalcustomrunconfiguration.h
+++ b/src/plugins/baremetal/baremetalcustomrunconfiguration.h
@@ -30,23 +30,29 @@
namespace BareMetal {
namespace Internal {
-class BareMetalCustomRunConfiguration : public ProjectExplorer::RunConfiguration
+// BareMetalCustomRunConfiguration
+
+class BareMetalCustomRunConfiguration final
+ : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
public:
- BareMetalCustomRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
+ explicit BareMetalCustomRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
public:
static const char *Id;
- bool isConfigured() const override;
- ConfigurationState ensureConfigured(QString *errorMessage) override;
+ bool isConfigured() const final;
+ ConfigurationState ensureConfigured(QString *errorMessage) final;
};
-class BareMetalCustomRunConfigurationFactory : public ProjectExplorer::FixedRunConfigurationFactory
+// BareMetalCustomRunConfigurationFactory
+
+class BareMetalCustomRunConfigurationFactory final
+ : public ProjectExplorer::FixedRunConfigurationFactory
{
public:
- BareMetalCustomRunConfigurationFactory();
+ explicit BareMetalCustomRunConfigurationFactory();
};
} // namespace Internal
diff --git a/src/plugins/baremetal/baremetaldebugsupport.cpp b/src/plugins/baremetal/baremetaldebugsupport.cpp
index ab8783a446..cda24139df 100644
--- a/src/plugins/baremetal/baremetaldebugsupport.cpp
+++ b/src/plugins/baremetal/baremetaldebugsupport.cpp
@@ -30,8 +30,8 @@
#include "gdbserverprovider.h"
#include "gdbserverprovidermanager.h"
-#include <debugger/debuggerruncontrol.h>
#include <debugger/debuggerkitinformation.h>
+#include <debugger/debuggerruncontrol.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsteplist.h>
@@ -52,10 +52,12 @@ using namespace ProjectExplorer;
namespace BareMetal {
namespace Internal {
+// BareMetalDebugSupport
+
BareMetalDebugSupport::BareMetalDebugSupport(RunControl *runControl)
: Debugger::DebuggerRunTool(runControl)
{
- auto dev = qSharedPointerCast<const BareMetalDevice>(device());
+ const auto dev = qSharedPointerCast<const BareMetalDevice>(device());
if (!dev) {
reportFailure(tr("Cannot debug: Kit has no device."));
return;
@@ -70,11 +72,9 @@ BareMetalDebugSupport::BareMetalDebugSupport(RunControl *runControl)
if (p->startupMode() == GdbServerProvider::StartupOnNetwork) {
Runnable r;
- r.executable = p->executable();
- // We need to wrap the command arguments depending on a host OS,
- // as the bare metal's GDB servers are launched on a host,
- // but not on a target.
- r.commandLineArguments = Utils::QtcProcess::joinArgs(p->arguments(), Utils::HostOsInfo::hostOs());
+ r.setCommandLine(p->command());
+ // Command arguments are in host OS style as the bare metal's GDB servers are launched
+ // on the host, not on that target.
m_gdbServer = new SimpleTargetRunner(runControl);
m_gdbServer->setRunnable(r);
addStartDependency(m_gdbServer);
@@ -83,9 +83,7 @@ BareMetalDebugSupport::BareMetalDebugSupport(RunControl *runControl)
void BareMetalDebugSupport::start()
{
- const auto rc = runControl()->runConfiguration();
- QTC_ASSERT(rc, reportFailure(); return);
- const auto exeAspect = rc->aspect<ExecutableAspect>();
+ const auto exeAspect = runControl()->aspect<ExecutableAspect>();
QTC_ASSERT(exeAspect, reportFailure(); return);
const QString bin = exeAspect->executable().toString();
@@ -98,10 +96,10 @@ void BareMetalDebugSupport::start()
return;
}
- const Target *target = rc->target();
+ const Target *target = runControl()->target();
QTC_ASSERT(target, reportFailure(); return);
- auto dev = qSharedPointerCast<const BareMetalDevice>(device());
+ const auto dev = qSharedPointerCast<const BareMetalDevice>(device());
QTC_ASSERT(dev, reportFailure(); return);
const GdbServerProvider *p = GdbServerProviderManager::findProvider(dev->gdbServerProviderId());
QTC_ASSERT(p, reportFailure(); return);
@@ -112,7 +110,7 @@ void BareMetalDebugSupport::start()
QString commands;
if (const BuildConfiguration *bc = target->activeBuildConfiguration()) {
if (BuildStepList *bsl = bc->stepList(BareMetalGdbCommandsDeployStep::stepId())) {
- foreach (const BareMetalGdbCommandsDeployStep *bs, bsl->allOfType<BareMetalGdbCommandsDeployStep>()) {
+ for (const BareMetalGdbCommandsDeployStep *bs : bsl->allOfType<BareMetalGdbCommandsDeployStep>()) {
if (!commands.endsWith("\n"))
commands.append("\n");
commands.append(bs->gdbCommands());
@@ -124,8 +122,8 @@ void BareMetalDebugSupport::start()
Runnable inferior;
inferior.executable = bin;
- if (auto aspect = rc->aspect<ArgumentsAspect>())
- inferior.commandLineArguments = aspect->arguments(rc->macroExpander());
+ if (const auto aspect = runControl()->aspect<ArgumentsAspect>())
+ inferior.commandLineArguments = aspect->arguments(runControl()->macroExpander());
setInferior(inferior);
setSymbolFile(bin);
setStartMode(AttachToRemoteServer);
@@ -133,6 +131,7 @@ void BareMetalDebugSupport::start()
setCommandsForReset(p->resetCommands());
setRemoteChannel(p->channel());
setUseContinueInsteadOfRun(true);
+ setUseExtendedRemote(p->useExtendedRemote());
DebuggerRunTool::start();
}
diff --git a/src/plugins/baremetal/baremetaldebugsupport.h b/src/plugins/baremetal/baremetaldebugsupport.h
index 2de31c467e..3a59343a9e 100644
--- a/src/plugins/baremetal/baremetaldebugsupport.h
+++ b/src/plugins/baremetal/baremetaldebugsupport.h
@@ -30,15 +30,17 @@
namespace BareMetal {
namespace Internal {
-class BareMetalDebugSupport : public Debugger::DebuggerRunTool
+// BareMetalDebugSupport
+
+class BareMetalDebugSupport final : public Debugger::DebuggerRunTool
{
Q_OBJECT
public:
- BareMetalDebugSupport(ProjectExplorer::RunControl *runControl);
+ explicit BareMetalDebugSupport(ProjectExplorer::RunControl *runControl);
private:
- void start() override;
+ void start() final;
ProjectExplorer::SimpleTargetRunner *m_gdbServer = nullptr;
};
diff --git a/src/plugins/baremetal/baremetaldevice.cpp b/src/plugins/baremetal/baremetaldevice.cpp
index 2be3a4dadd..340ca1a229 100644
--- a/src/plugins/baremetal/baremetaldevice.cpp
+++ b/src/plugins/baremetal/baremetaldevice.cpp
@@ -24,9 +24,13 @@
**
****************************************************************************/
+#include "baremetalconstants.h"
#include "baremetaldevice.h"
#include "baremetaldeviceconfigurationwidget.h"
+#include "baremetaldeviceconfigurationwizard.h"
+
#include "defaultgdbserverprovider.h"
+
#include "gdbserverprovidermanager.h"
#include "gdbserverproviderprocess.h"
@@ -44,6 +48,8 @@ namespace Internal {
const char gdbServerProviderIdKeyC[] = "GdbServerProviderId";
+// BareMetalDevice
+
BareMetalDevice::~BareMetalDevice()
{
if (GdbServerProvider *provider = GdbServerProviderManager::findProvider(m_gdbServerProviderId))
@@ -104,7 +110,7 @@ void BareMetalDevice::fromMap(const QVariantMap &map)
gdbServerProvider = provider->id();
} else {
const QSsh::SshConnectionParameters sshParams = sshParameters();
- auto newProvider = new DefaultGdbServerProvider;
+ const auto newProvider = new DefaultGdbServerProvider;
newProvider->setDisplayName(name);
newProvider->m_host = sshParams.host();
newProvider->m_port = sshParams.port();
@@ -124,11 +130,6 @@ QVariantMap BareMetalDevice::toMap() const
return map;
}
-BareMetalDevice::IDevice::Ptr BareMetalDevice::clone() const
-{
- return Ptr(new BareMetalDevice(*this));
-}
-
DeviceProcessSignalOperation::Ptr BareMetalDevice::signalOperation() const
{
return DeviceProcessSignalOperation::Ptr();
@@ -154,10 +155,24 @@ DeviceProcess *BareMetalDevice::createProcess(QObject *parent) const
return new GdbServerProviderProcess(sharedFromThis(), parent);
}
-BareMetalDevice::BareMetalDevice(const BareMetalDevice &other)
- : IDevice(other)
+// Factory
+
+BareMetalDeviceFactory::BareMetalDeviceFactory()
+ : IDeviceFactory(Constants::BareMetalOsType)
+{
+ setDisplayName(tr("Bare Metal Device"));
+ setCombinedIcon(":/baremetal/images/baremetaldevicesmall.png",
+ ":/baremetal/images/baremetaldevice.png");
+ setCanCreate(true);
+ setConstructionFunction(&BareMetalDevice::create);
+}
+
+IDevice::Ptr BareMetalDeviceFactory::create() const
{
- setGdbServerProviderId(other.gdbServerProviderId());
+ BareMetalDeviceConfigurationWizard wizard;
+ if (wizard.exec() != QDialog::Accepted)
+ return {};
+ return wizard.device();
}
} //namespace Internal
diff --git a/src/plugins/baremetal/baremetaldevice.h b/src/plugins/baremetal/baremetaldevice.h
index 50f099f8e4..b4d1b3afce 100644
--- a/src/plugins/baremetal/baremetaldevice.h
+++ b/src/plugins/baremetal/baremetaldevice.h
@@ -27,47 +27,59 @@
#pragma once
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefactory.h>
namespace BareMetal {
namespace Internal {
class GdbServerProvider;
-class BareMetalDevice : public ProjectExplorer::IDevice
+// BareMetalDevice
+
+class BareMetalDevice final : public ProjectExplorer::IDevice
{
public:
using Ptr = QSharedPointer<BareMetalDevice>;
using ConstPtr = QSharedPointer<const BareMetalDevice>;
static Ptr create() { return Ptr(new BareMetalDevice); }
- ~BareMetalDevice() override;
+ ~BareMetalDevice() final;
- QString displayType() const override;
- ProjectExplorer::IDeviceWidget *createWidget() override;
- Utils::OsType osType() const override;
- ProjectExplorer::IDevice::Ptr clone() const override;
+ QString displayType() const final;
+ ProjectExplorer::IDeviceWidget *createWidget() final;
+ Utils::OsType osType() const final;
- ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override;
+ ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const final;
- bool canCreateProcess() const override { return true; }
- ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const override;
+ bool canCreateProcess() const final { return true; }
+ ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const final;
QString gdbServerProviderId() const;
void setGdbServerProviderId(const QString &id);
void unregisterProvider(GdbServerProvider *provider);
void providerUpdated(GdbServerProvider *provider);
- void fromMap(const QVariantMap &map) override;
- QVariantMap toMap() const override;
+ void fromMap(const QVariantMap &map) final;
+ QVariantMap toMap() const final;
private:
- BareMetalDevice() = default;
- BareMetalDevice(const BareMetalDevice &other);
+ explicit BareMetalDevice() = default;
void setChannelByServerProvider(GdbServerProvider *provider);
- BareMetalDevice &operator=(const BareMetalDevice &);
QString m_gdbServerProviderId;
};
+// BareMetalDeviceFactory
+
+class BareMetalDeviceFactory final : public ProjectExplorer::IDeviceFactory
+{
+ Q_OBJECT
+
+public:
+ explicit BareMetalDeviceFactory();
+
+ ProjectExplorer::IDevice::Ptr create() const final;
+};
+
} //namespace Internal
} //namespace BareMetal
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationfactory.cpp b/src/plugins/baremetal/baremetaldeviceconfigurationfactory.cpp
deleted file mode 100644
index 779f9305ad..0000000000
--- a/src/plugins/baremetal/baremetaldeviceconfigurationfactory.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Tim Sander <tim@krieglstein.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "baremetaldeviceconfigurationfactory.h"
-
-#include "baremetaldeviceconfigurationwizard.h"
-#include "baremetalconstants.h"
-#include "baremetaldevice.h"
-
-#include <utils/qtcassert.h>
-
-using namespace ProjectExplorer;
-
-namespace BareMetal {
-namespace Internal {
-
-BareMetalDeviceConfigurationFactory::BareMetalDeviceConfigurationFactory()
- : IDeviceFactory(Constants::BareMetalOsType)
-{
- setDisplayName(tr("Bare Metal Device"));
- setCombinedIcon(":/baremetal/images/baremetaldevicesmall.png",
- ":/baremetal/images/baremetaldevice.png");
- setCanCreate(true);
- setConstructionFunction(&BareMetalDevice::create);
-}
-
-IDevice::Ptr BareMetalDeviceConfigurationFactory::create() const
-{
- BareMetalDeviceConfigurationWizard wizard;
- if (wizard.exec() != QDialog::Accepted)
- return IDevice::Ptr();
- return wizard.device();
-}
-
-} // namespace Internal
-} // namespace BareMetal
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationfactory.h b/src/plugins/baremetal/baremetaldeviceconfigurationfactory.h
deleted file mode 100644
index 5415491d90..0000000000
--- a/src/plugins/baremetal/baremetaldeviceconfigurationfactory.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Tim Sander <tim@krieglstein.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/idevicefactory.h>
-
-namespace BareMetal {
-namespace Internal {
-
-class BareMetalDeviceConfigurationFactory
- : public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-
-public:
- BareMetalDeviceConfigurationFactory();
-
- ProjectExplorer::IDevice::Ptr create() const override;
-};
-
-} // namespace Internal
-} // namespace BareMetal
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp
index b1074323e2..a528bd4b8e 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp
@@ -24,11 +24,11 @@
**
****************************************************************************/
-#include "baremetaldeviceconfigurationwidget.h"
#include "baremetaldevice.h"
+#include "baremetaldeviceconfigurationwidget.h"
-#include "gdbserverproviderchooser.h"
#include "gdbserverprovider.h"
+#include "gdbserverproviderchooser.h"
#include <utils/qtcassert.h>
@@ -37,6 +37,8 @@
namespace BareMetal {
namespace Internal {
+// BareMetalDeviceConfigurationWidget
+
BareMetalDeviceConfigurationWidget::BareMetalDeviceConfigurationWidget(
const ProjectExplorer::IDevice::Ptr &deviceConfig, QWidget *parent)
: IDeviceWidget(deviceConfig, parent)
@@ -44,7 +46,7 @@ BareMetalDeviceConfigurationWidget::BareMetalDeviceConfigurationWidget(
const auto dev = qSharedPointerCast<const BareMetalDevice>(device());
QTC_ASSERT(dev, return);
- auto formLayout = new QFormLayout(this);
+ const auto formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
m_gdbServerProviderChooser = new GdbServerProviderChooser(true, this);
@@ -58,7 +60,7 @@ BareMetalDeviceConfigurationWidget::BareMetalDeviceConfigurationWidget(
void BareMetalDeviceConfigurationWidget::gdbServerProviderChanged()
{
- auto dev = qSharedPointerCast<BareMetalDevice>(device());
+ const auto dev = qSharedPointerCast<BareMetalDevice>(device());
QTC_ASSERT(dev, return);
dev->setGdbServerProviderId(m_gdbServerProviderChooser->currentProviderId());
}
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h
index e56e7e76ce..ad8017f53f 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwidget.h
@@ -33,7 +33,9 @@ namespace Internal {
class GdbServerProviderChooser;
-class BareMetalDeviceConfigurationWidget
+// BareMetalDeviceConfigurationWidget
+
+class BareMetalDeviceConfigurationWidget final
: public ProjectExplorer::IDeviceWidget
{
Q_OBJECT
@@ -44,9 +46,9 @@ public:
private:
void gdbServerProviderChanged();
- void updateDeviceFromUi() override;
+ void updateDeviceFromUi() final;
- GdbServerProviderChooser *m_gdbServerProviderChooser;
+ GdbServerProviderChooser *m_gdbServerProviderChooser = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp
index 36a563ae88..7a4b05928b 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp
@@ -24,16 +24,18 @@
**
****************************************************************************/
+#include "baremetalconstants.h"
+#include "baremetaldevice.h"
#include "baremetaldeviceconfigurationwizard.h"
#include "baremetaldeviceconfigurationwizardpages.h"
-#include "baremetaldevice.h"
-#include "baremetalconstants.h"
namespace BareMetal {
namespace Internal {
enum PageId { SetupPageId };
+// BareMetalDeviceConfigurationWizard
+
BareMetalDeviceConfigurationWizard::BareMetalDeviceConfigurationWizard(QWidget *parent) :
Utils::Wizard(parent),
m_setupPage(new BareMetalDeviceConfigurationWizardSetupPage(this))
@@ -45,7 +47,7 @@ BareMetalDeviceConfigurationWizard::BareMetalDeviceConfigurationWizard(QWidget *
ProjectExplorer::IDevice::Ptr BareMetalDeviceConfigurationWizard::device() const
{
- auto dev = BareMetalDevice::create();
+ const auto dev = BareMetalDevice::create();
dev->setupId(ProjectExplorer::IDevice::ManuallyAdded, Core::Id());
dev->setDisplayName(m_setupPage->configurationName());
dev->setType(Constants::BareMetalOsType);
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h
index 4663516fd9..79ada6a0a8 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwizard.h
@@ -33,17 +33,19 @@ namespace Internal {
class BareMetalDeviceConfigurationWizardSetupPage;
-class BareMetalDeviceConfigurationWizard : public Utils::Wizard
+// BareMetalDeviceConfigurationWizard
+
+class BareMetalDeviceConfigurationWizard final : public Utils::Wizard
{
Q_OBJECT
public:
- BareMetalDeviceConfigurationWizard(QWidget *parent = nullptr);
+ explicit BareMetalDeviceConfigurationWizard(QWidget *parent = nullptr);
ProjectExplorer::IDevice::Ptr device() const;
private:
- BareMetalDeviceConfigurationWizardSetupPage *m_setupPage;
+ BareMetalDeviceConfigurationWizardSetupPage *m_setupPage = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.cpp b/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.cpp
index 2c41e361a3..4e0e69b4f8 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.cpp
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.cpp
@@ -24,8 +24,8 @@
**
****************************************************************************/
-#include "baremetaldeviceconfigurationwizardpages.h"
#include "baremetaldevice.h"
+#include "baremetaldeviceconfigurationwizardpages.h"
#include "gdbserverproviderchooser.h"
@@ -38,13 +38,15 @@
namespace BareMetal {
namespace Internal {
+// BareMetalDeviceConfigurationWizardSetupPage
+
BareMetalDeviceConfigurationWizardSetupPage::BareMetalDeviceConfigurationWizardSetupPage(
QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Set up GDB Server or Hardware Debugger"));
- auto formLayout = new QFormLayout(this);
+ const auto formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
m_nameLineEdit = new QLineEdit(this);
formLayout->addRow(tr("Name:"), m_nameLineEdit);
diff --git a/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.h b/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.h
index f47c8a79e9..27ac808108 100644
--- a/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.h
+++ b/src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.h
@@ -37,23 +37,25 @@ namespace Internal {
class GdbServerProviderChooser;
-class BareMetalDeviceConfigurationWizardSetupPage : public QWizardPage
+// BareMetalDeviceConfigurationWizardSetupPage
+
+class BareMetalDeviceConfigurationWizardSetupPage final : public QWizardPage
{
Q_OBJECT
public:
explicit BareMetalDeviceConfigurationWizardSetupPage(QWidget *parent = nullptr);
- void initializePage() override;
- bool isComplete() const override;
+ void initializePage() final;
+ bool isComplete() const final;
QString configurationName() const;
QString gdbServerProviderId() const;
virtual QString defaultConfigurationName() const;
private:
- QLineEdit *m_nameLineEdit;
- GdbServerProviderChooser *m_gdbServerProviderChooser;
+ QLineEdit *m_nameLineEdit = nullptr;
+ GdbServerProviderChooser *m_gdbServerProviderChooser = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/baremetalgdbcommandsdeploystep.cpp b/src/plugins/baremetal/baremetalgdbcommandsdeploystep.cpp
index fd79faf4bd..60f34a47e7 100644
--- a/src/plugins/baremetal/baremetalgdbcommandsdeploystep.cpp
+++ b/src/plugins/baremetal/baremetalgdbcommandsdeploystep.cpp
@@ -34,10 +34,12 @@ namespace Internal {
const char GdbCommandsKey[] = "BareMetal.GdbCommandsStep.Commands";
+// BareMetalGdbCommandsDeployStepWidget
+
BareMetalGdbCommandsDeployStepWidget::BareMetalGdbCommandsDeployStepWidget(BareMetalGdbCommandsDeployStep &step)
: BuildStepConfigWidget(&step), m_step(step)
{
- auto fl = new QFormLayout(this);
+ const auto fl = new QFormLayout(this);
fl->setMargin(0);
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
setLayout(fl);
@@ -62,6 +64,8 @@ QString BareMetalGdbCommandsDeployStepWidget::summaryText() const
return displayName();
}
+// BareMetalGdbCommandsDeployStep
+
BareMetalGdbCommandsDeployStep::BareMetalGdbCommandsDeployStep(BuildStepList *bsl)
: BuildStep(bsl, stepId())
{
diff --git a/src/plugins/baremetal/baremetalgdbcommandsdeploystep.h b/src/plugins/baremetal/baremetalgdbcommandsdeploystep.h
index 3507bbcb49..b5c85466be 100644
--- a/src/plugins/baremetal/baremetalgdbcommandsdeploystep.h
+++ b/src/plugins/baremetal/baremetalgdbcommandsdeploystep.h
@@ -27,23 +27,25 @@
#include <projectexplorer/buildstep.h>
-#include <QVariantMap>
#include <QPlainTextEdit>
+#include <QVariantMap>
namespace BareMetal {
namespace Internal {
-class BareMetalGdbCommandsDeployStep : public ProjectExplorer::BuildStep
+// BareMetalGdbCommandsDeployStep
+
+class BareMetalGdbCommandsDeployStep final : public ProjectExplorer::BuildStep
{
Q_OBJECT
public:
explicit BareMetalGdbCommandsDeployStep(ProjectExplorer::BuildStepList *bsl);
- bool fromMap(const QVariantMap &map) override;
- QVariantMap toMap() const override;
+ bool fromMap(const QVariantMap &map) final;
+ QVariantMap toMap() const final;
- ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
+ ProjectExplorer::BuildStepConfigWidget *createConfigWidget() final;
static Core::Id stepId();
static QString displayName();
@@ -52,13 +54,16 @@ public:
QString gdbCommands() const;
private:
- bool init() override;
- void doRun() override;
+ bool init() final;
+ void doRun() final;
QString m_gdbCommands;
};
-class BareMetalGdbCommandsDeployStepWidget: public ProjectExplorer::BuildStepConfigWidget
+// BareMetalGdbCommandsDeployStepWidget
+
+class BareMetalGdbCommandsDeployStepWidget final
+ : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
@@ -71,7 +76,7 @@ private:
QString summaryText() const;
BareMetalGdbCommandsDeployStep &m_step;
- QPlainTextEdit *m_commands;
+ QPlainTextEdit *m_commands = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/baremetalplugin.cpp b/src/plugins/baremetal/baremetalplugin.cpp
index 42290772e4..0ce4c51835 100644
--- a/src/plugins/baremetal/baremetalplugin.cpp
+++ b/src/plugins/baremetal/baremetalplugin.cpp
@@ -24,46 +24,52 @@
**
****************************************************************************/
-#include "baremetalplugin.h"
#include "baremetalconstants.h"
#include "baremetalcustomrunconfiguration.h"
-#include "baremetaldeviceconfigurationfactory.h"
#include "baremetaldebugsupport.h"
+#include "baremetaldevice.h"
+#include "baremetalplugin.h"
#include "baremetalrunconfiguration.h"
-#include "gdbserverproviderssettingspage.h"
#include "gdbserverprovidermanager.h"
+#include "gdbserverproviderssettingspage.h"
-#include <coreplugin/icore.h>
-#include <coreplugin/icontext.h>
+#include "iarewtoolchain.h"
+#include "keiltoolchain.h"
+#include "sdcctoolchain.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
using namespace ProjectExplorer;
namespace BareMetal {
namespace Internal {
-class BareMetalPluginRunData
+// BareMetalPluginPrivate
+
+class BareMetalPluginPrivate
{
public:
- BareMetalDeviceConfigurationFactory deviceConfigurationFactory;
+ IarToolChainFactory iarToolChainFactory;
+ KeilToolchainFactory keilToolChainFactory;
+ SdccToolChainFactory sdccToolChainFactory;
+ BareMetalDeviceFactory deviceFactory;
BareMetalRunConfigurationFactory runConfigurationFactory;
BareMetalCustomRunConfigurationFactory customRunConfigurationFactory;
GdbServerProvidersSettingsPage gdbServerProviderSettinsPage;
GdbServerProviderManager gdbServerProviderManager;
};
-BareMetalPlugin::BareMetalPlugin()
-{
- setObjectName(QLatin1String("BareMetalPlugin"));
-}
+// BareMetalPlugin
BareMetalPlugin::~BareMetalPlugin()
{
- delete m_runData;
+ delete d;
}
bool BareMetalPlugin::initialize(const QStringList &arguments, QString *errorString)
@@ -71,7 +77,7 @@ bool BareMetalPlugin::initialize(const QStringList &arguments, QString *errorStr
Q_UNUSED(arguments)
Q_UNUSED(errorString)
- m_runData = new BareMetalPluginRunData;
+ d = new BareMetalPluginPrivate;
auto constraint = [](RunConfiguration *runConfig) {
const QByteArray idStr = runConfig->id().name();
diff --git a/src/plugins/baremetal/baremetalplugin.h b/src/plugins/baremetal/baremetalplugin.h
index 17ecbcc85d..a9ced735db 100644
--- a/src/plugins/baremetal/baremetalplugin.h
+++ b/src/plugins/baremetal/baremetalplugin.h
@@ -31,23 +31,29 @@
namespace BareMetal {
namespace Internal {
-class BareMetalPluginRunData;
+// BareMetalPlugin
-class BareMetalPlugin : public ExtensionSystem::IPlugin
+class BareMetalPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "BareMetal.json")
-public:
- BareMetalPlugin();
-
-private:
~BareMetalPlugin() final;
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final;
- BareMetalPluginRunData *m_runData;
+ class BareMetalPluginPrivate *d = nullptr;
+
+#ifdef WITH_TESTS
+private slots:
+ void testIarOutputParsers_data();
+ void testIarOutputParsers();
+ void testKeilOutputParsers_data();
+ void testKeilOutputParsers();
+ void testSdccOutputParsers_data();
+ void testSdccOutputParsers();
+#endif // WITH_TESTS
};
} // namespace Internal
diff --git a/src/plugins/baremetal/baremetalrunconfiguration.cpp b/src/plugins/baremetal/baremetalrunconfiguration.cpp
index cdfa2ddca6..8ba44b9343 100644
--- a/src/plugins/baremetal/baremetalrunconfiguration.cpp
+++ b/src/plugins/baremetal/baremetalrunconfiguration.cpp
@@ -23,9 +23,8 @@
**
****************************************************************************/
-#include "baremetalrunconfiguration.h"
-
#include "baremetalconstants.h"
+#include "baremetalrunconfiguration.h"
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/project.h>
@@ -43,7 +42,7 @@ namespace Internal {
BareMetalRunConfiguration::BareMetalRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- auto exeAspect = addAspect<ExecutableAspect>();
+ const auto exeAspect = addAspect<ExecutableAspect>();
exeAspect->setDisplayStyle(BaseStringAspect::LabelDisplay);
exeAspect->setPlaceHolderText(tr("Unknown"));
@@ -62,7 +61,7 @@ BareMetalRunConfiguration::BareMetalRunConfiguration(Target *target, Core::Id id
void BareMetalRunConfiguration::updateTargetInformation()
{
- const BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(buildKey());
+ const BuildTargetInfo bti = buildTargetInfo();
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
emit enabledChanged();
}
diff --git a/src/plugins/baremetal/baremetalrunconfiguration.h b/src/plugins/baremetal/baremetalrunconfiguration.h
index 9699bae1ea..dfc426e8c2 100644
--- a/src/plugins/baremetal/baremetalrunconfiguration.h
+++ b/src/plugins/baremetal/baremetalrunconfiguration.h
@@ -30,12 +30,14 @@
namespace BareMetal {
namespace Internal {
-class BareMetalRunConfiguration : public ProjectExplorer::RunConfiguration
+// BareMetalRunConfiguration
+
+class BareMetalRunConfiguration final : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
public:
- BareMetalRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
+ explicit BareMetalRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
static const char *IdPrefix;
@@ -43,10 +45,13 @@ private:
void updateTargetInformation();
};
-class BareMetalRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
+// BareMetalRunConfigurationFactory
+
+class BareMetalRunConfigurationFactory final
+ : public ProjectExplorer::RunConfigurationFactory
{
public:
- BareMetalRunConfigurationFactory();
+ explicit BareMetalRunConfigurationFactory();
};
} // namespace Internal
diff --git a/src/plugins/baremetal/defaultgdbserverprovider.cpp b/src/plugins/baremetal/defaultgdbserverprovider.cpp
index 10ade87396..49d126479d 100644
--- a/src/plugins/baremetal/defaultgdbserverprovider.cpp
+++ b/src/plugins/baremetal/defaultgdbserverprovider.cpp
@@ -23,14 +23,15 @@
**
****************************************************************************/
-#include "defaultgdbserverprovider.h"
#include "baremetalconstants.h"
+#include "defaultgdbserverprovider.h"
#include "gdbserverprovidermanager.h"
#include <utils/qtcassert.h>
#include <coreplugin/variablechooser.h>
+#include <QCheckBox>
#include <QFormLayout>
#include <QPlainTextEdit>
@@ -40,10 +41,10 @@ namespace Internal {
static const char hostKeyC[] = "BareMetal.DefaultGdbServerProvider.Host";
static const char portKeyC[] = "BareMetal.DefaultGdbServerProvider.Port";
+// DefaultGdbServerProvider
+
DefaultGdbServerProvider::DefaultGdbServerProvider()
: GdbServerProvider(QLatin1String(Constants::DEFAULT_PROVIDER_ID))
- , m_host(QLatin1String("localhost"))
- , m_port(3333)
{
}
@@ -132,6 +133,8 @@ GdbServerProviderConfigWidget *DefaultGdbServerProvider::configurationWidget()
return new DefaultGdbServerProviderConfigWidget(this);
}
+// DefaultGdbServerProviderFactory
+
DefaultGdbServerProviderFactory::DefaultGdbServerProviderFactory()
{
setId(QLatin1String(Constants::DEFAULT_PROVIDER_ID));
@@ -152,14 +155,16 @@ bool DefaultGdbServerProviderFactory::canRestore(const QVariantMap &data) const
GdbServerProvider *DefaultGdbServerProviderFactory::restore(const QVariantMap &data)
{
- auto p = new DefaultGdbServerProvider;
- auto updated = data;
+ const auto p = new DefaultGdbServerProvider;
+ const auto updated = data;
if (p->fromMap(updated))
return p;
delete p;
return nullptr;
}
+// GdbServerProviderConfigWidget
+
DefaultGdbServerProviderConfigWidget::DefaultGdbServerProviderConfigWidget(
DefaultGdbServerProvider *provider)
: GdbServerProviderConfigWidget(provider)
@@ -169,6 +174,9 @@ DefaultGdbServerProviderConfigWidget::DefaultGdbServerProviderConfigWidget(
m_hostWidget = new HostWidget(this);
m_mainLayout->addRow(tr("Host:"), m_hostWidget);
+ m_useExtendedRemoteCheckBox = new QCheckBox(this);
+ m_useExtendedRemoteCheckBox->setToolTip("Use GDB target extended-remote");
+ m_mainLayout->addRow(tr("Extended mode:"), m_useExtendedRemoteCheckBox);
m_initCommandsTextEdit = new QPlainTextEdit(this);
m_initCommandsTextEdit->setToolTip(defaultInitCommandsTooltip());
m_mainLayout->addRow(tr("Init commands:"), m_initCommandsTextEdit);
@@ -179,12 +187,14 @@ DefaultGdbServerProviderConfigWidget::DefaultGdbServerProviderConfigWidget(
addErrorLabel();
setFromProvider();
- auto chooser = new Core::VariableChooser(this);
+ const auto chooser = new Core::VariableChooser(this);
chooser->addSupportedWidget(m_initCommandsTextEdit);
chooser->addSupportedWidget(m_resetCommandsTextEdit);
connect(m_hostWidget, &HostWidget::dataChanged,
this, &GdbServerProviderConfigWidget::dirty);
+ connect(m_useExtendedRemoteCheckBox, &QCheckBox::stateChanged,
+ this, &GdbServerProviderConfigWidget::dirty);
connect(m_initCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_resetCommandsTextEdit, &QPlainTextEdit::textChanged,
@@ -198,6 +208,7 @@ void DefaultGdbServerProviderConfigWidget::applyImpl()
p->setHost(m_hostWidget->host());
p->setPort(m_hostWidget->port());
+ p->setUseExtendedRemote(m_useExtendedRemoteCheckBox->isChecked());
p->setInitCommands(m_initCommandsTextEdit->toPlainText());
p->setResetCommands(m_resetCommandsTextEdit->toPlainText());
}
@@ -212,9 +223,10 @@ void DefaultGdbServerProviderConfigWidget::setFromProvider()
const auto p = static_cast<DefaultGdbServerProvider *>(provider());
Q_ASSERT(p);
- QSignalBlocker blocker(this);
+ const QSignalBlocker blocker(this);
m_hostWidget->setHost(p->m_host);
m_hostWidget->setPort(p->m_port);
+ m_useExtendedRemoteCheckBox->setChecked(p->useExtendedRemote());
m_initCommandsTextEdit->setPlainText(p->initCommands());
m_resetCommandsTextEdit->setPlainText(p->resetCommands());
}
diff --git a/src/plugins/baremetal/defaultgdbserverprovider.h b/src/plugins/baremetal/defaultgdbserverprovider.h
index f5cb1dd3db..82b7e78160 100644
--- a/src/plugins/baremetal/defaultgdbserverprovider.h
+++ b/src/plugins/baremetal/defaultgdbserverprovider.h
@@ -33,7 +33,9 @@ namespace Internal {
class DefaultGdbServerProviderConfigWidget;
class DefaultGdbServerProviderFactory;
-class DefaultGdbServerProvider : public GdbServerProvider
+// DefaultGdbServerProvider
+
+class DefaultGdbServerProvider final : public GdbServerProvider
{
public:
QString typeDisplayName() const final;
@@ -60,15 +62,17 @@ private:
explicit DefaultGdbServerProvider();
explicit DefaultGdbServerProvider(const DefaultGdbServerProvider &);
- QString m_host;
- quint16 m_port;
+ QString m_host = QLatin1String("localhost");
+ quint16 m_port = 3333;
friend class DefaultGdbServerProviderConfigWidget;
friend class DefaultGdbServerProviderFactory;
friend class BareMetalDevice;
};
-class DefaultGdbServerProviderFactory : public GdbServerProviderFactory
+// DefaultGdbServerProviderFactory
+
+class DefaultGdbServerProviderFactory final : public GdbServerProviderFactory
{
Q_OBJECT
@@ -81,7 +85,9 @@ public:
GdbServerProvider *restore(const QVariantMap &data) final;
};
-class DefaultGdbServerProviderConfigWidget : public GdbServerProviderConfigWidget
+// DefaultGdbServerProviderConfigWidget
+
+class DefaultGdbServerProviderConfigWidget final : public GdbServerProviderConfigWidget
{
Q_OBJECT
@@ -94,9 +100,10 @@ private:
void setFromProvider();
- HostWidget *m_hostWidget;
- QPlainTextEdit *m_initCommandsTextEdit;
- QPlainTextEdit *m_resetCommandsTextEdit;
+ HostWidget *m_hostWidget = nullptr;
+ QCheckBox *m_useExtendedRemoteCheckBox = nullptr;
+ QPlainTextEdit *m_initCommandsTextEdit = nullptr;
+ QPlainTextEdit *m_resetCommandsTextEdit = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/gdbserverprovider.cpp b/src/plugins/baremetal/gdbserverprovider.cpp
index cf633d8602..520e8fb30f 100644
--- a/src/plugins/baremetal/gdbserverprovider.cpp
+++ b/src/plugins/baremetal/gdbserverprovider.cpp
@@ -23,22 +23,21 @@
**
****************************************************************************/
+#include "baremetaldevice.h"
#include "gdbserverprovider.h"
#include "gdbserverprovidermanager.h"
-#include "baremetaldevice.h"
-#include <utils/qtcassert.h>
#include <utils/environment.h>
+#include <utils/qtcassert.h>
+#include <QComboBox>
#include <QCoreApplication>
-#include <QUuid>
-
#include <QFormLayout>
-#include <QLineEdit>
#include <QLabel>
-#include <QComboBox>
-#include <QSpinBox>
+#include <QLineEdit>
#include <QPlainTextEdit>
+#include <QSpinBox>
+#include <QUuid>
namespace BareMetal {
namespace Internal {
@@ -48,6 +47,7 @@ const char displayNameKeyC[] = "BareMetal.GdbServerProvider.DisplayName";
const char startupModeKeyC[] = "BareMetal.GdbServerProvider.Mode";
const char initCommandsKeyC[] = "BareMetal.GdbServerProvider.InitCommands";
const char resetCommandsKeyC[] = "BareMetal.GdbServerProvider.ResetCommands";
+const char useExtendedRemoteKeyC[] = "BareMetal.GdbServerProvider.UseExtendedRemote";
static QString createId(const QString &id)
{
@@ -56,9 +56,10 @@ static QString createId(const QString &id)
return newId;
}
+// GdbServerProvider
+
GdbServerProvider::GdbServerProvider(const QString &id)
: m_id(createId(id))
- , m_startupMode(NoStartup)
{
}
@@ -67,6 +68,7 @@ GdbServerProvider::GdbServerProvider(const GdbServerProvider &other)
, m_startupMode(other.m_startupMode)
, m_initCommands(other.m_initCommands)
, m_resetCommands(other.m_resetCommands)
+ , m_useExtendedRemote(other.useExtendedRemote())
{
m_displayName = QCoreApplication::translate(
"BareMetal::GdbServerProvider", "Clone of %1")
@@ -121,6 +123,16 @@ void GdbServerProvider::setInitCommands(const QString &cmds)
m_initCommands = cmds;
}
+bool GdbServerProvider::useExtendedRemote() const
+{
+ return m_useExtendedRemote;
+}
+
+void GdbServerProvider::setUseExtendedRemote(bool useExtendedRemote)
+{
+ m_useExtendedRemote = useExtendedRemote;
+}
+
QString GdbServerProvider::resetCommands() const
{
return m_resetCommands;
@@ -131,14 +143,9 @@ void GdbServerProvider::setResetCommands(const QString &cmds)
m_resetCommands = cmds;
}
-QString GdbServerProvider::executable() const
+Utils::CommandLine GdbServerProvider::command() const
{
- return QString();
-}
-
-QStringList GdbServerProvider::arguments() const
-{
- return QStringList();
+ return {};
}
bool GdbServerProvider::operator==(const GdbServerProvider &other) const
@@ -153,7 +160,8 @@ bool GdbServerProvider::operator==(const GdbServerProvider &other) const
return thisId == otherId
&& m_startupMode == other.m_startupMode
&& m_initCommands == other.m_initCommands
- && m_resetCommands == other.m_resetCommands;
+ && m_resetCommands == other.m_resetCommands
+ && m_useExtendedRemote == other.m_useExtendedRemote;
}
QVariantMap GdbServerProvider::toMap() const
@@ -163,7 +171,8 @@ QVariantMap GdbServerProvider::toMap() const
{QLatin1String(displayNameKeyC), m_displayName},
{QLatin1String(startupModeKeyC), m_startupMode},
{QLatin1String(initCommandsKeyC), m_initCommands},
- {QLatin1String(resetCommandsKeyC), m_resetCommands}
+ {QLatin1String(resetCommandsKeyC), m_resetCommands},
+ {QLatin1String(useExtendedRemoteKeyC), m_useExtendedRemote},
};
}
@@ -201,9 +210,12 @@ bool GdbServerProvider::fromMap(const QVariantMap &data)
m_startupMode = static_cast<StartupMode>(data.value(QLatin1String(startupModeKeyC)).toInt());
m_initCommands = data.value(QLatin1String(initCommandsKeyC)).toString();
m_resetCommands = data.value(QLatin1String(resetCommandsKeyC)).toString();
+ m_useExtendedRemote = data.value(QLatin1String(useExtendedRemoteKeyC)).toBool();
return true;
}
+// GdbServerProviderFactory
+
QString GdbServerProviderFactory::id() const
{
return m_id;
@@ -234,6 +246,8 @@ void GdbServerProviderFactory::idToMap(QVariantMap &data, const QString &id)
data.insert(QLatin1String(idKeyC), id);
}
+// GdbServerProviderConfigWidget
+
GdbServerProviderConfigWidget::GdbServerProviderConfigWidget(
GdbServerProvider *provider)
: m_provider(provider)
@@ -258,7 +272,7 @@ GdbServerProviderConfigWidget::GdbServerProviderConfigWidget(
connect(m_nameLineEdit, &QLineEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_startupModeComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &GdbServerProviderConfigWidget::dirty);
}
@@ -354,7 +368,7 @@ void GdbServerProviderConfigWidget::clearErrorMessage()
void GdbServerProviderConfigWidget::setFromProvider()
{
- QSignalBlocker blocker(this);
+ const QSignalBlocker blocker(this);
m_nameLineEdit->setText(m_provider->displayName());
setStartupMode(m_provider->startupMode());
}
@@ -373,6 +387,8 @@ QString GdbServerProviderConfigWidget::defaultResetCommandsTooltip()
"The MCU should be halted after these commands.");
}
+// HostWidget
+
HostWidget::HostWidget(QWidget *parent)
: QWidget(parent)
{
@@ -383,20 +399,20 @@ HostWidget::HostWidget(QWidget *parent)
m_portSpinBox->setRange(0, 65535);
m_portSpinBox->setToolTip(tr("Enter TCP/IP port which will be listened by "
"the GDB server provider."));
- auto layout = new QHBoxLayout(this);
+ const auto layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_hostLineEdit);
layout->addWidget(m_portSpinBox);
connect(m_hostLineEdit, &QLineEdit::textChanged,
this, &HostWidget::dataChanged);
- connect(m_portSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_portSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &HostWidget::dataChanged);
}
void HostWidget::setHost(const QString &host)
{
- QSignalBlocker blocker(this);
+ const QSignalBlocker blocker(this);
m_hostLineEdit->setText(host);
}
@@ -407,7 +423,7 @@ QString HostWidget::host() const
void HostWidget::setPort(const quint16 &port)
{
- QSignalBlocker blocker(this);
+ const QSignalBlocker blocker(this);
m_portSpinBox->setValue(port);
}
diff --git a/src/plugins/baremetal/gdbserverprovider.h b/src/plugins/baremetal/gdbserverprovider.h
index 8ca0777ea7..8d91408a2e 100644
--- a/src/plugins/baremetal/gdbserverprovider.h
+++ b/src/plugins/baremetal/gdbserverprovider.h
@@ -33,12 +33,13 @@
#include <utils/fileutils.h>
QT_BEGIN_NAMESPACE
+class QCheckBox;
+class QComboBox;
class QFormLayout;
-class QLineEdit;
class QLabel;
-class QComboBox;
-class QSpinBox;
+class QLineEdit;
class QPlainTextEdit;
+class QSpinBox;
QT_END_NAMESPACE
namespace BareMetal {
@@ -48,6 +49,8 @@ class BareMetalDevice;
class GdbServerProviderConfigWidget;
class GdbServerProviderManager;
+// GdbServerProvider
+
class GdbServerProvider
{
public:
@@ -68,6 +71,7 @@ public:
StartupMode startupMode() const;
QString initCommands() const;
QString resetCommands() const;
+ bool useExtendedRemote() const;
virtual bool operator==(const GdbServerProvider &) const;
@@ -80,8 +84,7 @@ public:
virtual QVariantMap toMap() const;
- virtual QString executable() const;
- virtual QStringList arguments() const;
+ virtual Utils::CommandLine command() const;
virtual bool isValid() const;
virtual bool canStartupMode(StartupMode) const;
@@ -96,6 +99,7 @@ protected:
void setStartupMode(StartupMode);
void setInitCommands(const QString &);
void setResetCommands(const QString &);
+ void setUseExtendedRemote(bool);
void providerUpdated();
@@ -104,14 +108,17 @@ protected:
private:
QString m_id;
mutable QString m_displayName;
- StartupMode m_startupMode;
+ StartupMode m_startupMode = NoStartup;
QString m_initCommands;
QString m_resetCommands;
QSet<BareMetalDevice *> m_devices;
+ bool m_useExtendedRemote = false;
friend class GdbServerProviderConfigWidget;
};
+// GdbServerProviderFactory
+
class GdbServerProviderFactory : public QObject
{
Q_OBJECT
@@ -137,6 +144,8 @@ private:
QString m_id;
};
+// GdbServerProviderConfigWidget
+
class GdbServerProviderConfigWidget : public QWidget
{
Q_OBJECT
@@ -166,18 +175,20 @@ protected:
static QString defaultInitCommandsTooltip();
static QString defaultResetCommandsTooltip();
- QFormLayout *m_mainLayout;
- QLineEdit *m_nameLineEdit;
- QComboBox *m_startupModeComboBox;
+ QFormLayout *m_mainLayout = nullptr;
+ QLineEdit *m_nameLineEdit = nullptr;
+ QComboBox *m_startupModeComboBox = nullptr;
private:
void setFromProvider();
- GdbServerProvider *m_provider;
+ GdbServerProvider *m_provider = nullptr;
QLabel *m_errorLabel = nullptr;
};
-class HostWidget : public QWidget
+// HostWidget
+
+class HostWidget final : public QWidget
{
Q_OBJECT
@@ -193,8 +204,8 @@ signals:
void dataChanged();
private:
- QLineEdit *m_hostLineEdit;
- QSpinBox *m_portSpinBox;
+ QLineEdit *m_hostLineEdit = nullptr;
+ QSpinBox *m_portSpinBox = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/gdbserverproviderchooser.cpp b/src/plugins/baremetal/gdbserverproviderchooser.cpp
index 043d71bd2f..764a9ee0cd 100644
--- a/src/plugins/baremetal/gdbserverproviderchooser.cpp
+++ b/src/plugins/baremetal/gdbserverproviderchooser.cpp
@@ -23,11 +23,11 @@
**
****************************************************************************/
-#include "gdbserverproviderchooser.h"
+#include "baremetalconstants.h"
-#include "gdbserverprovidermanager.h"
#include "gdbserverprovider.h"
-#include "baremetalconstants.h"
+#include "gdbserverproviderchooser.h"
+#include "gdbserverprovidermanager.h"
#include <coreplugin/icore.h>
@@ -39,6 +39,8 @@
namespace BareMetal {
namespace Internal {
+// GdbServerProviderChooser
+
GdbServerProviderChooser::GdbServerProviderChooser(
bool useManageButton, QWidget *parent)
: QWidget(parent)
@@ -49,13 +51,13 @@ GdbServerProviderChooser::GdbServerProviderChooser(
m_manageButton->setEnabled(useManageButton);
m_manageButton->setVisible(useManageButton);
- auto layout = new QHBoxLayout(this);
+ const auto layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_chooser);
layout->addWidget(m_manageButton);
setFocusProxy(m_manageButton);
- connect(m_chooser, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_chooser, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &GdbServerProviderChooser::currentIndexChanged);
connect(m_manageButton, &QAbstractButton::clicked,
this, &GdbServerProviderChooser::manageButtonClicked);
@@ -101,14 +103,14 @@ QString GdbServerProviderChooser::providerText(const GdbServerProvider *provider
void GdbServerProviderChooser::populate()
{
- QSignalBlocker blocker(m_chooser);
+ const QSignalBlocker blocker(m_chooser);
m_chooser->clear();
m_chooser->addItem(tr("None"));
for (const GdbServerProvider *p : GdbServerProviderManager::providers()) {
if (!providerMatches(p))
continue;
- m_chooser->addItem(providerText(p), qVariantFromValue(p->id()));
+ m_chooser->addItem(providerText(p), QVariant::fromValue(p->id()));
}
}
diff --git a/src/plugins/baremetal/gdbserverproviderchooser.h b/src/plugins/baremetal/gdbserverproviderchooser.h
index c2827921ca..a53f228a0c 100644
--- a/src/plugins/baremetal/gdbserverproviderchooser.h
+++ b/src/plugins/baremetal/gdbserverproviderchooser.h
@@ -39,7 +39,9 @@ namespace Internal {
class GdbServerProvider;
-class GdbServerProviderChooser : public QWidget
+// GdbServerProviderChooser
+
+class GdbServerProviderChooser final : public QWidget
{
Q_OBJECT
@@ -60,8 +62,8 @@ private:
bool providerMatches(const GdbServerProvider *) const;
QString providerText(const GdbServerProvider *) const;
- QComboBox *m_chooser;
- QPushButton *m_manageButton;
+ QComboBox *m_chooser = nullptr;
+ QPushButton *m_manageButton = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/gdbserverprovidermanager.cpp b/src/plugins/baremetal/gdbserverprovidermanager.cpp
index e08b9bb30f..16758ee30c 100644
--- a/src/plugins/baremetal/gdbserverprovidermanager.cpp
+++ b/src/plugins/baremetal/gdbserverprovidermanager.cpp
@@ -23,11 +23,11 @@
**
****************************************************************************/
-#include "gdbserverprovidermanager.h"
#include "gdbserverprovider.h"
+#include "gdbserverprovidermanager.h"
-#include "openocdgdbserverprovider.h"
#include "defaultgdbserverprovider.h"
+#include "openocdgdbserverprovider.h"
#include "stlinkutilgdbserverprovider.h"
#include <coreplugin/icore.h>
@@ -35,8 +35,8 @@
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
#include <utils/persistentsettings.h>
+#include <utils/qtcassert.h>
#include <QDir>
@@ -50,8 +50,10 @@ const char fileNameKeyC[] = "/gdbserverproviders.xml";
static GdbServerProviderManager *m_instance = nullptr;
+// GdbServerProviderManager
+
GdbServerProviderManager::GdbServerProviderManager()
- : m_configFile(Utils::FileName::fromString(Core::ICore::userResourcePath() + fileNameKeyC))
+ : m_configFile(Utils::FilePath::fromString(Core::ICore::userResourcePath() + fileNameKeyC))
, m_factories({new DefaultGdbServerProviderFactory,
new OpenOcdGdbServerProviderFactory,
new StLinkUtilGdbServerProviderFactory})
@@ -103,7 +105,7 @@ void GdbServerProviderManager::restoreProviders()
const QVariantMap map = data.value(key).toMap();
bool restored = false;
- foreach (GdbServerProviderFactory *f, m_factories) {
+ for (GdbServerProviderFactory *f : qAsConst(m_factories)) {
if (f->canRestore(map)) {
if (GdbServerProvider *p = f->restore(map)) {
registerProvider(p);
@@ -127,7 +129,7 @@ void GdbServerProviderManager::saveProviders()
data.insert(QLatin1String(fileVersionKeyC), 1);
int count = 0;
- foreach (const GdbServerProvider *p, m_providers) {
+ for (const GdbServerProvider *p : qAsConst(m_providers)) {
if (p->isValid()) {
const QVariantMap tmp = p->toMap();
if (tmp.isEmpty())
diff --git a/src/plugins/baremetal/gdbserverprovidermanager.h b/src/plugins/baremetal/gdbserverprovidermanager.h
index 8a6ed109ba..64bd6df409 100644
--- a/src/plugins/baremetal/gdbserverprovidermanager.h
+++ b/src/plugins/baremetal/gdbserverprovidermanager.h
@@ -25,8 +25,8 @@
#pragma once
-#include <QObject>
#include <QList>
+#include <QObject>
#include <utils/fileutils.h>
@@ -36,17 +36,19 @@ namespace BareMetal {
namespace Internal {
class BareMetalPlugin;
-class BareMetalPluginRunData;
+class BareMetalPluginPrivate;
class GdbServerProvider;
class GdbServerProviderFactory;
-class GdbServerProviderManager : public QObject
+// GdbServerProviderManager
+
+class GdbServerProviderManager final : public QObject
{
Q_OBJECT
public:
static GdbServerProviderManager *instance();
- ~GdbServerProviderManager() override;
+ ~GdbServerProviderManager() final;
static QList<GdbServerProvider *> providers();
static QList<GdbServerProviderFactory *> factories();
@@ -69,13 +71,13 @@ private:
void restoreProviders();
static void notifyAboutUpdate(GdbServerProvider *);
- Utils::PersistentSettingsWriter *m_writer;
+ Utils::PersistentSettingsWriter *m_writer = nullptr;
QList<GdbServerProvider *> m_providers;
- const Utils::FileName m_configFile;
+ const Utils::FilePath m_configFile;
const QList<GdbServerProviderFactory *> m_factories;
friend class BareMetalPlugin; // for restoreProviders
- friend class BareMetalPluginRunData; // for constructor
+ friend class BareMetalPluginPrivate; // for constructor
friend class GdbServerProvider;
};
diff --git a/src/plugins/baremetal/gdbserverproviderprocess.cpp b/src/plugins/baremetal/gdbserverproviderprocess.cpp
index 45d14d57e0..d893e5fae4 100644
--- a/src/plugins/baremetal/gdbserverproviderprocess.cpp
+++ b/src/plugins/baremetal/gdbserverproviderprocess.cpp
@@ -26,16 +26,19 @@
#include "gdbserverproviderprocess.h"
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
-#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
using namespace ProjectExplorer;
namespace BareMetal {
namespace Internal {
+// GdbServerProviderProcess
+
GdbServerProviderProcess::GdbServerProviderProcess(
const QSharedPointer<const ProjectExplorer::IDevice> &device,
QObject *parent)
@@ -46,7 +49,7 @@ GdbServerProviderProcess::GdbServerProviderProcess(
m_process->setUseCtrlCStub(true);
connect(m_process, &QProcess::errorOccurred, this, &GdbServerProviderProcess::error);
- connect(m_process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &GdbServerProviderProcess::finished);
connect(m_process, &QProcess::readyReadStandardOutput,
@@ -60,7 +63,7 @@ GdbServerProviderProcess::GdbServerProviderProcess(
void GdbServerProviderProcess::start(const ProjectExplorer::Runnable &runnable)
{
QTC_ASSERT(m_process->state() == QProcess::NotRunning, return);
- m_process->setCommand(runnable.executable, runnable.commandLineArguments);
+ m_process->setCommand(runnable.commandLine());
m_process->start();
}
diff --git a/src/plugins/baremetal/gdbserverproviderprocess.h b/src/plugins/baremetal/gdbserverproviderprocess.h
index 8640db5aef..bddb59fdcd 100644
--- a/src/plugins/baremetal/gdbserverproviderprocess.h
+++ b/src/plugins/baremetal/gdbserverproviderprocess.h
@@ -32,7 +32,9 @@ namespace Utils { class QtcProcess; }
namespace BareMetal {
namespace Internal {
-class GdbServerProviderProcess : public ProjectExplorer::DeviceProcess
+// GdbServerProviderProcess
+
+class GdbServerProviderProcess final : public ProjectExplorer::DeviceProcess
{
Q_OBJECT
public:
@@ -40,23 +42,23 @@ public:
const QSharedPointer<const ProjectExplorer::IDevice> &device,
QObject *parent = nullptr);
- void start(const ProjectExplorer::Runnable &runnable) override;
- void interrupt() override;
- void terminate() override;
- void kill() override;
+ void start(const ProjectExplorer::Runnable &runnable) final;
+ void interrupt() final;
+ void terminate() final;
+ void kill() final;
- QProcess::ProcessState state() const override;
- QProcess::ExitStatus exitStatus() const override;
- int exitCode() const override;
- QString errorString() const override;
+ QProcess::ProcessState state() const final;
+ QProcess::ExitStatus exitStatus() const final;
+ int exitCode() const final;
+ QString errorString() const final;
- QByteArray readAllStandardOutput() override;
- QByteArray readAllStandardError() override;
+ QByteArray readAllStandardOutput() final;
+ QByteArray readAllStandardError() final;
- qint64 write(const QByteArray &data) override;
+ qint64 write(const QByteArray &data) final;
private:
- Utils::QtcProcess *m_process;
+ Utils::QtcProcess *m_process = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/gdbserverproviderssettingspage.cpp b/src/plugins/baremetal/gdbserverproviderssettingspage.cpp
index 60af0a9d2b..b538ebce33 100644
--- a/src/plugins/baremetal/gdbserverproviderssettingspage.cpp
+++ b/src/plugins/baremetal/gdbserverproviderssettingspage.cpp
@@ -23,21 +23,23 @@
**
****************************************************************************/
-#include "gdbserverproviderssettingspage.h"
-#include "gdbserverprovider.h"
#include "baremetalconstants.h"
+
+#include "gdbserverprovider.h"
#include "gdbserverprovidermanager.h"
+#include "gdbserverproviderssettingspage.h"
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <utils/algorithm.h>
#include <utils/detailswidget.h>
#include <utils/qtcassert.h>
-#include <utils/algorithm.h>
-#include <QApplication>
#include <QAction>
+#include <QApplication>
+#include <QGroupBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QItemSelectionModel>
@@ -48,22 +50,23 @@
#include <QTextStream>
#include <QTreeView>
#include <QVBoxLayout>
-#include <QGroupBox>
using namespace Utils;
namespace BareMetal {
namespace Internal {
-class GdbServerProviderNode : public TreeItem
+// GdbServerProviderNode
+
+class GdbServerProviderNode final : public TreeItem
{
public:
- GdbServerProviderNode(GdbServerProvider *provider, bool changed = false)
+ explicit GdbServerProviderNode(GdbServerProvider *provider, bool changed = false)
: provider(provider), changed(changed)
{
}
- QVariant data(int column, int role) const override
+ QVariant data(int column, int role) const final
{
if (role == Qt::FontRole) {
QFont f = QApplication::font();
@@ -77,7 +80,7 @@ public:
}
// FIXME: Need to handle ToolTipRole role?
- return QVariant();
+ return {};
}
GdbServerProvider *provider = nullptr;
@@ -85,6 +88,8 @@ public:
bool changed = false;
};
+// GdbServerProviderModel
+
GdbServerProviderModel::GdbServerProviderModel()
{
setHeader({tr("Name"), tr("Type")});
@@ -102,7 +107,7 @@ GdbServerProviderModel::GdbServerProviderModel()
GdbServerProvider *GdbServerProviderModel::provider(const QModelIndex &index) const
{
- if (GdbServerProviderNode *node = nodeForIndex(index))
+ if (const GdbServerProviderNode *node = nodeForIndex(index))
return node->provider;
return nullptr;
@@ -119,13 +124,13 @@ GdbServerProviderNode *GdbServerProviderModel::nodeForIndex(const QModelIndex &i
void GdbServerProviderModel::apply()
{
// Remove unused providers
- foreach (GdbServerProvider *provider, m_providersToRemove)
+ for (GdbServerProvider *provider : qAsConst(m_providersToRemove))
GdbServerProviderManager::deregisterProvider(provider);
QTC_ASSERT(m_providersToRemove.isEmpty(), m_providersToRemove.clear());
// Update providers
for (TreeItem *item : *rootItem()) {
- auto n = static_cast<GdbServerProviderNode *>(item);
+ const auto n = static_cast<GdbServerProviderNode *>(item);
if (!n->changed)
continue;
@@ -139,7 +144,7 @@ void GdbServerProviderModel::apply()
// Add new (and already updated) providers
QStringList skippedProviders;
- foreach (GdbServerProvider *provider, m_providersToAdd) {
+ for (GdbServerProvider *provider: qAsConst(m_providersToAdd)) {
if (!GdbServerProviderManager::registerProvider(provider))
skippedProviders << provider->displayName();
}
@@ -167,7 +172,7 @@ GdbServerProviderNode *GdbServerProviderModel::findNode(const GdbServerProvider
QModelIndex GdbServerProviderModel::indexForProvider(GdbServerProvider *provider) const
{
- GdbServerProviderNode *n = findNode(provider);
+ const GdbServerProviderNode *n = findNode(provider);
return n ? indexForItem(n) : QModelIndex();
}
@@ -195,7 +200,7 @@ void GdbServerProviderModel::markForAddition(GdbServerProvider *provider)
GdbServerProviderNode *GdbServerProviderModel::createNode(
GdbServerProvider *provider, bool changed)
{
- auto node = new GdbServerProviderNode(provider, changed);
+ const auto node = new GdbServerProviderNode(provider, changed);
node->widget = provider->configurationWidget();
connect(node->widget, &GdbServerProviderConfigWidget::dirty, this, [node] {
node->changed = true;
@@ -223,12 +228,14 @@ void GdbServerProviderModel::removeProvider(GdbServerProvider *provider)
emit providerStateChanged();
}
-class GdbServerProvidersSettingsWidget : public QWidget
+// GdbServerProvidersSettingsWidget
+
+class GdbServerProvidersSettingsWidget final : public QWidget
{
Q_DECLARE_TR_FUNCTIONS(BareMetal::Internal::GdbServerProvidersSettingsPage)
public:
- GdbServerProvidersSettingsWidget(GdbServerProvidersSettingsPage *page);
+ explicit GdbServerProvidersSettingsWidget(GdbServerProvidersSettingsPage *page);
void providerSelectionChanged();
void removeProvider();
@@ -238,14 +245,14 @@ public:
QModelIndex currentIndex() const;
public:
- GdbServerProvidersSettingsPage *m_page;
+ GdbServerProvidersSettingsPage *m_page = nullptr;
GdbServerProviderModel m_model;
- QItemSelectionModel *m_selectionModel;
- QTreeView *m_providerView;
- Utils::DetailsWidget *m_container;
- QPushButton *m_addButton;
- QPushButton *m_cloneButton;
- QPushButton *m_delButton;
+ QItemSelectionModel *m_selectionModel = nullptr;
+ QTreeView *m_providerView = nullptr;
+ Utils::DetailsWidget *m_container = nullptr;
+ QPushButton *m_addButton = nullptr;
+ QPushButton *m_cloneButton = nullptr;
+ QPushButton *m_delButton = nullptr;
};
GdbServerProvidersSettingsWidget::GdbServerProvidersSettingsWidget
@@ -265,27 +272,27 @@ GdbServerProvidersSettingsWidget::GdbServerProvidersSettingsWidget
m_container->setMinimumWidth(500);
m_container->setVisible(false);
- auto buttonLayout = new QHBoxLayout();
+ const auto buttonLayout = new QHBoxLayout;
buttonLayout->setSpacing(6);
buttonLayout->setContentsMargins(0, 0, 0, 0);
buttonLayout->addWidget(m_addButton);
buttonLayout->addWidget(m_cloneButton);
buttonLayout->addWidget(m_delButton);
- auto spacerItem = new QSpacerItem(40, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ const auto spacerItem = new QSpacerItem(40, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);
buttonLayout->addItem(spacerItem);
- auto verticalLayout = new QVBoxLayout();
+ const auto verticalLayout = new QVBoxLayout;
verticalLayout->addWidget(m_providerView);
verticalLayout->addLayout(buttonLayout);
- auto horizontalLayout = new QHBoxLayout();
+ const auto horizontalLayout = new QHBoxLayout;
horizontalLayout->addLayout(verticalLayout);
horizontalLayout->addWidget(m_container);
- auto groupBox = new QGroupBox(tr("GDB Server Providers"), this);
+ const auto groupBox = new QGroupBox(tr("GDB Server Providers"), this);
groupBox->setLayout(horizontalLayout);
- auto topLayout = new QVBoxLayout(this);
+ const auto topLayout = new QVBoxLayout(this);
topLayout->addWidget(groupBox);
connect(&m_model, &GdbServerProviderModel::providerStateChanged,
@@ -293,7 +300,7 @@ GdbServerProvidersSettingsWidget::GdbServerProvidersSettingsWidget
m_providerView->setModel(&m_model);
- auto headerView = m_providerView->header();
+ const auto headerView = m_providerView->header();
headerView->setSectionResizeMode(0, QHeaderView::ResizeToContents);
headerView->setSectionResizeMode(1, QHeaderView::Stretch);
m_providerView->expandAll();
@@ -307,10 +314,10 @@ GdbServerProvidersSettingsWidget::GdbServerProvidersSettingsWidget
this, &GdbServerProvidersSettingsWidget::providerSelectionChanged);
// Set up add menu:
- auto addMenu = new QMenu(m_addButton);
+ const auto addMenu = new QMenu(m_addButton);
for (const auto f : GdbServerProviderManager::factories()) {
- auto action = new QAction(addMenu);
+ const auto action = new QAction(addMenu);
action->setText(f->displayName());
connect(action, &QAction::triggered, this, [this, f] { createProvider(f); });
addMenu->addAction(action);
@@ -335,7 +342,7 @@ void GdbServerProvidersSettingsWidget::providerSelectionChanged()
if (w)
w->setVisible(false);
- GdbServerProviderNode *node = m_model.nodeForIndex(current);
+ const GdbServerProviderNode *node = m_model.nodeForIndex(current);
w = node ? node->widget : nullptr;
m_container->setWidget(w);
m_container->setVisible(w != nullptr);
@@ -346,7 +353,7 @@ void GdbServerProvidersSettingsWidget::createProvider(GdbServerProviderFactory *
{
GdbServerProvider *provider = nullptr;
if (!f) {
- GdbServerProvider *old = m_model.provider(currentIndex());
+ const GdbServerProvider *old = m_model.provider(currentIndex());
if (!old)
return;
provider = old->clone();
@@ -390,11 +397,11 @@ void GdbServerProvidersSettingsWidget::updateState()
QModelIndex GdbServerProvidersSettingsWidget::currentIndex() const
{
if (!m_selectionModel)
- return QModelIndex();
+ return {};
const QModelIndexList rows = m_selectionModel->selectedRows();
if (rows.count() != 1)
- return QModelIndex();
+ return {};
return rows.at(0);
}
diff --git a/src/plugins/baremetal/gdbserverproviderssettingspage.h b/src/plugins/baremetal/gdbserverproviderssettingspage.h
index d1b6119fd9..a68515526e 100644
--- a/src/plugins/baremetal/gdbserverproviderssettingspage.h
+++ b/src/plugins/baremetal/gdbserverproviderssettingspage.h
@@ -46,13 +46,15 @@ class GdbServerProviderFactory;
class GdbServerProviderNode;
class GdbServerProvidersSettingsWidget;
-class GdbServerProviderModel
+// GdbServerProviderModel
+
+class GdbServerProviderModel final
: public Utils::TreeModel<Utils::TypedTreeItem<GdbServerProviderNode>, GdbServerProviderNode>
{
Q_OBJECT
public:
- GdbServerProviderModel();
+ explicit GdbServerProviderModel();
GdbServerProvider *provider(const QModelIndex &) const;
GdbServerProviderConfigWidget *widget(const QModelIndex &) const;
@@ -78,7 +80,9 @@ private:
QList<GdbServerProvider *> m_providersToRemove;
};
-class GdbServerProvidersSettingsPage : public Core::IOptionsPage
+// GdbServerProvidersSettingsPage
+
+class GdbServerProvidersSettingsPage final : public Core::IOptionsPage
{
Q_OBJECT
@@ -86,9 +90,9 @@ public:
explicit GdbServerProvidersSettingsPage(QObject *parent = nullptr);
private:
- QWidget *widget() override;
- void apply() override;
- void finish() override;
+ QWidget *widget() final;
+ void apply() final;
+ void finish() final;
GdbServerProvidersSettingsWidget *m_configWidget = nullptr;
};
diff --git a/src/plugins/baremetal/iarewparser.cpp b/src/plugins/baremetal/iarewparser.cpp
new file mode 100644
index 0000000000..50e25706ca
--- /dev/null
+++ b/src/plugins/baremetal/iarewparser.cpp
@@ -0,0 +1,450 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "iarewparser.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/task.h>
+
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorsettings.h>
+
+#include <QRegularExpression>
+
+using namespace ProjectExplorer;
+
+namespace BareMetal {
+namespace Internal {
+
+// Helpers:
+
+static Task::TaskType taskType(const QString &msgType)
+{
+ if (msgType == "Warning")
+ return Task::TaskType::Warning;
+ else if (msgType == "Error" || msgType == "Fatal error")
+ return Task::TaskType::Error;
+ return Task::TaskType::Unknown;
+}
+
+// IarParser
+
+IarParser::IarParser()
+{
+ setObjectName("IarParser");
+}
+
+Core::Id IarParser::id()
+{
+ return "BareMetal.OutputParser.Iar";
+}
+
+void IarParser::newTask(const Task &task)
+{
+ doFlush();
+ m_lastTask = task;
+ m_lines = 1;
+}
+
+void IarParser::amendDescription()
+{
+ while (!m_descriptionParts.isEmpty())
+ m_lastTask.description.append(m_descriptionParts.takeFirst());
+
+ while (!m_snippets.isEmpty()) {
+ const QString snippet = m_snippets.takeFirst();
+ const int start = m_lastTask.description.count() + 1;
+ m_lastTask.description.append(QLatin1Char('\n'));
+ m_lastTask.description.append(snippet);
+
+ QTextLayout::FormatRange fr;
+ fr.start = start;
+ fr.length = m_lastTask.description.count() + 1;
+ fr.format.setFont(TextEditor::TextEditorSettings::fontSettings().font());
+ fr.format.setFontStyleHint(QFont::Monospace);
+ m_lastTask.formats.append(fr);
+
+ ++m_lines;
+ }
+}
+
+void IarParser::amendFilePath()
+{
+ if (m_filePathParts.isEmpty())
+ return;
+ QString filePath;
+ while (!m_filePathParts.isEmpty())
+ filePath.append(m_filePathParts.takeFirst().trimmed());
+ m_lastTask.setFile(Utils::FilePath::fromUserInput(filePath));
+ m_expectFilePath = false;
+}
+
+void IarParser::stdError(const QString &line)
+{
+ IOutputParser::stdError(line);
+
+ const QString lne = rightTrimmed(line);
+
+ QRegularExpression re;
+ QRegularExpressionMatch match;
+
+ re.setPattern("^(Error|Fatal error)\\[(.+)\\]:\\s(.+)\\s\\[(.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex,
+ DescriptionIndex, FilepathBeginIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = QString("[%1]: %2").arg(match.captured(MessageCodeIndex),
+ match.captured(DescriptionIndex));
+ // This task has a file path, but this patch are split on
+ // some lines, which will be received later.
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ // Prepare first part of a file path.
+ QString firstPart = match.captured(FilepathBeginIndex);
+ firstPart.remove("referenced from ");
+ m_filePathParts.push_back(firstPart);
+ m_expectFilePath = true;
+ m_expectSnippet = false;
+ return;
+ }
+
+ re.setPattern("^.*(Error|Fatal error)\\[(.+)\\]:\\s(.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex,
+ DescriptionIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = QString("[%1]: %2").arg(match.captured(MessageCodeIndex),
+ match.captured(DescriptionIndex));
+ // This task has not a file path. The description details
+ // will be received later on the next lines.
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ m_expectSnippet = true;
+ m_expectFilePath = false;
+ m_expectDescription = false;
+ return;
+ }
+
+ re.setPattern("^\"(.+)\",(\\d+)?\\s+(Warning|Error|Fatal error)\\[(.+)\\].+$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
+ MessageTypeIndex, MessageCodeIndex };
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
+ match.captured(FilePathIndex));
+ const int lineno = match.captured(LineNumberIndex).toInt();
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ // A full description will be received later on next lines.
+ const Task task(type, {}, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ const QString firstPart = QString("[%1]: ").arg(match.captured(MessageCodeIndex));
+ m_descriptionParts.append(firstPart);
+ m_expectDescription = true;
+ m_expectSnippet = false;
+ m_expectFilePath = false;
+ return;
+ }
+
+ if (lne.isEmpty()) {
+ //
+ } else if (!lne.startsWith(QLatin1Char(' '))) {
+ return;
+ } else if (m_expectFilePath) {
+ if (lne.endsWith(QLatin1Char(']'))) {
+ const QString lastPart = lne.left(lne.size() - 1);
+ m_filePathParts.push_back(lastPart);
+ } else {
+ m_filePathParts.push_back(lne);
+ return;
+ }
+ } else if (m_expectSnippet) {
+ if (!lne.endsWith("Fatal error detected, aborting.")) {
+ m_snippets.push_back(lne);
+ return;
+ }
+ } else if (m_expectDescription) {
+ if (!lne.startsWith(" ")) {
+ m_descriptionParts.push_back(lne.trimmed());
+ return;
+ }
+ }
+
+ doFlush();
+}
+
+void IarParser::stdOutput(const QString &line)
+{
+ IOutputParser::stdOutput(line);
+
+ const QString lne = rightTrimmed(line);
+ if (!lne.startsWith("Error in command line"))
+ return;
+
+ const Task task(Task::TaskType::Error, line.trimmed(), {},
+ -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ doFlush();
+}
+
+void IarParser::doFlush()
+{
+ if (m_lastTask.isNull())
+ return;
+
+ amendDescription();
+ amendFilePath();
+
+ m_expectSnippet = true;
+ m_expectFilePath = false;
+ m_expectDescription = false;
+
+ Task t = m_lastTask;
+ m_lastTask.clear();
+ emit addTask(t, m_lines, 1);
+ m_lines = 0;
+}
+
+} // namespace Internal
+} // namespace BareMetal
+
+// Unit tests:
+
+#ifdef WITH_TESTS
+#include "baremetalplugin.h"
+#include <projectexplorer/outputparser_test.h>
+#include <QTest>
+
+namespace BareMetal {
+namespace Internal {
+
+void BareMetalPlugin::testIarOutputParsers_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<OutputParserTester::Channel>("inputChannel");
+ QTest::addColumn<QString>("childStdOutLines");
+ QTest::addColumn<QString>("childStdErrLines");
+ QTest::addColumn<Tasks >("tasks");
+ QTest::addColumn<QString>("outputLines");
+
+ QTest::newRow("pass-through stdout")
+ << "Sometext" << OutputParserTester::STDOUT
+ << "Sometext\n" << QString()
+ << Tasks()
+ << QString();
+ QTest::newRow("pass-through stderr")
+ << "Sometext" << OutputParserTester::STDERR
+ << QString() << "Sometext\n"
+ << Tasks()
+ << QString();
+
+ const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
+
+ // For std out.
+ QTest::newRow("Error in command line")
+ << QString::fromLatin1("Error in command line: Some error")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("Error in command line: Some error\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("Error in command line: Some error"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ // For std error.
+ QTest::newRow("No details warning")
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
+ " Some warning \"foo\" bar")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
+ " Some warning \"foo\" bar\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("[Pe223]: Some warning \"foo\" bar"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Details warning")
+ << QString::fromLatin1(" some_detail;\n"
+ " ^\n"
+ "\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
+ " Some warning")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1(" some_detail;\n"
+ " ^\n"
+ "\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
+ " Some warning\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("[Pe223]: Some warning\n"
+ " some_detail;\n"
+ " ^"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("No details split-description warning")
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
+ " Some warning\n"
+ " , split")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
+ " Some warning\n"
+ " , split\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("[Pe223]: Some warning, split"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("No details error")
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
+ " Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
+ " Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("[Pe223]: Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Details error")
+ << QString::fromLatin1(" some_detail;\n"
+ " ^\n"
+ "\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
+ " Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1(" some_detail;\n"
+ " ^\n"
+ "\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
+ " Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("[Pe223]: Some error\n"
+ " some_detail;\n"
+ " ^"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("No details split-description error")
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
+ " Some error\n"
+ " , split")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
+ " Some error\n"
+ " , split\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("[Pe223]: Some error, split"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("No definition for")
+ << QString::fromLatin1("Error[Li005]: Some error \"foo\" [referenced from c:\\fo\n"
+ " o\\bar\\mai\n"
+ " n.c.o\n"
+ "]")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("Error[Li005]: Some error \"foo\" [referenced from c:\\fo\n"
+ " o\\bar\\mai\n"
+ " n.c.o\n"
+ "]\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("[Li005]: Some error \"foo\""),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\bar\\main.c.o")),
+ -1,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("More than one source file specified")
+ << QString::fromLatin1("Fatal error[Su011]: Some error:\n"
+ " c:\\foo.c\n"
+ " c:\\bar.c\n"
+ "Fatal error detected, aborting.")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("Fatal error[Su011]: Some error:\n"
+ " c:\\foo.c\n"
+ " c:\\bar.c\n"
+ "Fatal error detected, aborting.\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("[Su011]: Some error:\n"
+ " c:\\foo.c\n"
+ " c:\\bar.c"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("At end of source")
+ << QString::fromLatin1("At end of source Error[Pe040]: Some error \";\"")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("At end of source Error[Pe040]: Some error \";\"\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("[Pe040]: Some error \";\""),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+}
+
+void BareMetalPlugin::testIarOutputParsers()
+{
+ OutputParserTester testbench;
+ testbench.appendOutputParser(new IarParser);
+ QFETCH(QString, input);
+ QFETCH(OutputParserTester::Channel, inputChannel);
+ QFETCH(Tasks, tasks);
+ QFETCH(QString, childStdOutLines);
+ QFETCH(QString, childStdErrLines);
+ QFETCH(QString, outputLines);
+
+ testbench.testParsing(input, inputChannel,
+ tasks, childStdOutLines, childStdErrLines,
+ outputLines);
+}
+
+} // namespace Internal
+} // namespace BareMetal
+
+#endif // WITH_TESTS
diff --git a/src/plugins/baremetal/iarewparser.h b/src/plugins/baremetal/iarewparser.h
new file mode 100644
index 0000000000..48348d4f6f
--- /dev/null
+++ b/src/plugins/baremetal/iarewparser.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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/ioutputparser.h>
+#include <projectexplorer/task.h>
+
+namespace BareMetal {
+namespace Internal {
+
+// IarParser
+
+class IarParser final : public ProjectExplorer::IOutputParser
+{
+ Q_OBJECT
+
+public:
+ explicit IarParser();
+ static Core::Id id();
+
+private:
+ void newTask(const ProjectExplorer::Task &task);
+ void amendDescription();
+ void amendFilePath();
+
+ void stdError(const QString &line) final;
+ void stdOutput(const QString &line) final;
+ void doFlush() final;
+
+ ProjectExplorer::Task m_lastTask;
+ int m_lines = 0;
+ bool m_expectSnippet = true;
+ bool m_expectFilePath = false;
+ bool m_expectDescription = false;
+ QStringList m_snippets;
+ QStringList m_filePathParts;
+ QStringList m_descriptionParts;
+};
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/iarewtoolchain.cpp b/src/plugins/baremetal/iarewtoolchain.cpp
new file mode 100644
index 0000000000..1955a0fec7
--- /dev/null
+++ b/src/plugins/baremetal/iarewtoolchain.cpp
@@ -0,0 +1,594 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "baremetalconstants.h"
+
+#include "iarewparser.h"
+#include "iarewtoolchain.h"
+
+#include <projectexplorer/abiwidget.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectmacro.h>
+#include <projectexplorer/toolchainmanager.h>
+
+#include <utils/algorithm.h>
+#include <utils/environment.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+#include <utils/synchronousprocess.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QFormLayout>
+#include <QLineEdit>
+#include <QPlainTextEdit>
+#include <QSettings>
+#include <QTemporaryFile>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace BareMetal {
+namespace Internal {
+
+// Helpers:
+
+static const char compilerCommandKeyC[] = "BareMetal.IarToolChain.CompilerPath";
+static const char targetAbiKeyC[] = "BareMetal.IarToolChain.TargetAbi";
+
+static bool compilerExists(const FilePath &compilerPath)
+{
+ const QFileInfo fi = compilerPath.toFileInfo();
+ return fi.exists() && fi.isExecutable() && fi.isFile();
+}
+
+static Macros dumpPredefinedMacros(const FilePath &compiler, const Core::Id languageId,
+ const QStringList &env)
+{
+ if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable())
+ return {};
+
+ // IAR compiler requires an input and output files.
+
+ QTemporaryFile fakeIn;
+ if (!fakeIn.open())
+ return {};
+ fakeIn.close();
+
+ const QString outpath = fakeIn.fileName() + ".tmp";
+
+ SynchronousProcess cpp;
+ cpp.setEnvironment(env);
+ cpp.setTimeoutS(10);
+
+ QStringList arguments;
+ arguments.push_back(fakeIn.fileName());
+ if (languageId == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
+ arguments.push_back("--ec++");
+ arguments.push_back("--predef_macros");
+ arguments.push_back(outpath);
+
+ const SynchronousProcessResponse response = cpp.runBlocking(compiler.toString(), arguments);
+ if (response.result != SynchronousProcessResponse::Finished
+ || response.exitCode != 0) {
+ qWarning() << response.exitMessage(compiler.toString(), 10);
+ return {};
+ }
+
+ QByteArray output;
+ QFile fakeOut(outpath);
+ if (fakeOut.open(QIODevice::ReadOnly))
+ output = fakeOut.readAll();
+ fakeOut.remove();
+
+ return Macro::toMacros(output);
+}
+
+static HeaderPaths dumpHeaderPaths(const FilePath &compiler, const Core::Id languageId,
+ const QStringList &env)
+{
+ if (!compiler.exists())
+ return {};
+
+ // Seems, that IAR compiler has not options to show a list of system
+ // include directories. But, we can use the following trick to enumerate
+ // this directories. We need to specify the '--preinclude' option with
+ // the wrong value (e.g. a dot). In this case the compiler fails and its
+ // error output will contains a mention about the using search directories
+ // in a form of tokens, like: ' searched: "<path/to/include>" '. Where are
+ // the resulting paths are escaped with a quotes.
+
+ QTemporaryFile fakeIn;
+ if (!fakeIn.open())
+ return {};
+ fakeIn.close();
+
+ SynchronousProcess cpp;
+ cpp.setEnvironment(env);
+ cpp.setTimeoutS(10);
+
+ QStringList arguments;
+ arguments.push_back(fakeIn.fileName());
+ if (languageId == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
+ arguments.push_back("--ec++");
+ arguments.push_back("--preinclude");
+ arguments.push_back(".");
+
+ // Note: Response should retutn an error, just don't check on errors.
+ const SynchronousProcessResponse response = cpp.runBlocking(compiler.toString(),
+ arguments);
+
+ HeaderPaths headerPaths;
+
+ const QByteArray output = response.allOutput().toUtf8();
+ for (auto pos = 0; pos < output.size(); ++pos) {
+ const int searchIndex = output.indexOf("searched:", pos);
+ if (searchIndex == -1)
+ break;
+ const int startQuoteIndex = output.indexOf('"', searchIndex + 1);
+ if (startQuoteIndex == -1)
+ break;
+ const int endQuoteIndex = output.indexOf('"', startQuoteIndex + 1);
+ if (endQuoteIndex == -1)
+ break;
+
+ const QByteArray candidate = output.mid(startQuoteIndex + 1,
+ endQuoteIndex - startQuoteIndex - 1)
+ .simplified();
+
+ const QString headerPath = QFileInfo(QFile::decodeName(candidate))
+ .canonicalFilePath();
+
+ // Ignore the QtC binary directory path.
+ if (headerPath != QCoreApplication::applicationDirPath())
+ headerPaths.append({headerPath, HeaderPathType::BuiltIn});
+
+ pos = endQuoteIndex + 1;
+ }
+
+ return headerPaths;
+}
+
+static Abi::Architecture guessArchitecture(const Macros &macros)
+{
+ for (const Macro &macro : macros) {
+ if (macro.key == "__ICCARM__")
+ return Abi::Architecture::ArmArchitecture;
+ if (macro.key == "__ICC8051__")
+ return Abi::Architecture::Mcs51Architecture;
+ if (macro.key == "__ICCAVR__")
+ return Abi::Architecture::AvrArchitecture;
+ }
+ return Abi::Architecture::UnknownArchitecture;
+}
+
+static unsigned char guessWordWidth(const Macros &macros)
+{
+ const Macro sizeMacro = Utils::findOrDefault(macros, [](const Macro &m) {
+ return m.key == "__INT_SIZE__";
+ });
+ if (sizeMacro.isValid() && sizeMacro.type == MacroType::Define)
+ return sizeMacro.value.toInt() * 8;
+ return 0;
+}
+
+static Abi::BinaryFormat guessFormat(Abi::Architecture arch)
+{
+ if (arch == Abi::Architecture::ArmArchitecture)
+ return Abi::BinaryFormat::ElfFormat;
+ if (arch == Abi::Architecture::Mcs51Architecture
+ || arch == Abi::Architecture::AvrArchitecture) {
+ return Abi::BinaryFormat::UbrofFormat;
+ }
+ return Abi::BinaryFormat::UnknownFormat;
+}
+
+static Abi guessAbi(const Macros &macros)
+{
+ const auto arch = guessArchitecture(macros);
+ return {arch, Abi::OS::BareMetalOS, Abi::OSFlavor::GenericFlavor,
+ guessFormat(arch), guessWordWidth(macros)};
+}
+
+static QString buildDisplayName(Abi::Architecture arch, Core::Id language,
+ const QString &version)
+{
+ const auto archName = Abi::toString(arch);
+ const auto langName = ToolChainManager::displayNameOfLanguageId(language);
+ return IarToolChain::tr("IAREW %1 (%2, %3)")
+ .arg(version, langName, archName);
+}
+
+// IarToolChain
+
+IarToolChain::IarToolChain() :
+ ToolChain(Constants::IAREW_TOOLCHAIN_TYPEID)
+{ }
+
+QString IarToolChain::typeDisplayName() const
+{
+ return Internal::IarToolChainFactory::tr("IAREW");
+}
+
+void IarToolChain::setTargetAbi(const Abi &abi)
+{
+ if (abi == m_targetAbi)
+ return;
+ m_targetAbi = abi;
+ toolChainUpdated();
+}
+
+Abi IarToolChain::targetAbi() const
+{
+ return m_targetAbi;
+}
+
+bool IarToolChain::isValid() const
+{
+ return true;
+}
+
+ToolChain::MacroInspectionRunner IarToolChain::createMacroInspectionRunner() const
+{
+ Environment env = Environment::systemEnvironment();
+ addToEnvironment(env);
+
+ const Utils::FilePath compilerCommand = m_compilerCommand;
+ const Core::Id languageId = language();
+
+ MacrosCache macrosCache = predefinedMacrosCache();
+
+ return [env, compilerCommand,
+ macrosCache,
+ languageId]
+ (const QStringList &flags) {
+ Q_UNUSED(flags)
+
+ const Macros macros = dumpPredefinedMacros(compilerCommand, languageId,
+ env.toStringList());
+ const auto languageVersion = ToolChain::languageVersion(languageId, macros);
+ const auto report = MacroInspectionReport{macros, languageVersion};
+ macrosCache->insert({}, report);
+
+ return report;
+ };
+}
+
+Macros IarToolChain::predefinedMacros(const QStringList &cxxflags) const
+{
+ return createMacroInspectionRunner()(cxxflags).macros;
+}
+
+Utils::LanguageExtensions IarToolChain::languageExtensions(const QStringList &) const
+{
+ return LanguageExtension::None;
+}
+
+WarningFlags IarToolChain::warningFlags(const QStringList &cxxflags) const
+{
+ Q_UNUSED(cxxflags);
+ return WarningFlags::Default;
+}
+
+ToolChain::BuiltInHeaderPathsRunner IarToolChain::createBuiltInHeaderPathsRunner() const
+{
+ Environment env = Environment::systemEnvironment();
+ addToEnvironment(env);
+
+ const Utils::FilePath compilerCommand = m_compilerCommand;
+ const Core::Id languageId = language();
+
+ HeaderPathsCache headerPaths = headerPathsCache();
+
+ return [env, compilerCommand, headerPaths, languageId](const QStringList &flags,
+ const QString &fileName,
+ const QString &) {
+ Q_UNUSED(flags)
+ Q_UNUSED(fileName)
+
+ const HeaderPaths paths = dumpHeaderPaths(compilerCommand, languageId, env.toStringList());
+ headerPaths->insert({}, paths);
+
+ return paths;
+ };
+}
+
+HeaderPaths IarToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
+ const FilePath &fileName) const
+{
+ return createBuiltInHeaderPathsRunner()(cxxFlags, fileName.toString(), "");
+}
+
+void IarToolChain::addToEnvironment(Environment &env) const
+{
+ if (!m_compilerCommand.isEmpty()) {
+ const FilePath path = m_compilerCommand.parentDir();
+ env.prependOrSetPath(path.toString());
+ }
+}
+
+IOutputParser *IarToolChain::outputParser() const
+{
+ return new IarParser;
+}
+
+QVariantMap IarToolChain::toMap() const
+{
+ QVariantMap data = ToolChain::toMap();
+ data.insert(compilerCommandKeyC, m_compilerCommand.toString());
+ data.insert(targetAbiKeyC, m_targetAbi.toString());
+ return data;
+}
+
+bool IarToolChain::fromMap(const QVariantMap &data)
+{
+ if (!ToolChain::fromMap(data))
+ return false;
+ m_compilerCommand = FilePath::fromString(data.value(compilerCommandKeyC).toString());
+ m_targetAbi = Abi::fromString(data.value(targetAbiKeyC).toString());
+ return true;
+}
+
+std::unique_ptr<ToolChainConfigWidget> IarToolChain::createConfigurationWidget()
+{
+ return std::make_unique<IarToolChainConfigWidget>(this);
+}
+
+bool IarToolChain::operator==(const ToolChain &other) const
+{
+ if (!ToolChain::operator==(other))
+ return false;
+
+ const auto customTc = static_cast<const IarToolChain *>(&other);
+ return m_compilerCommand == customTc->m_compilerCommand
+ && m_targetAbi == customTc->m_targetAbi
+ ;
+}
+
+void IarToolChain::setCompilerCommand(const FilePath &file)
+{
+ if (file == m_compilerCommand)
+ return;
+ m_compilerCommand = file;
+ toolChainUpdated();
+}
+
+FilePath IarToolChain::compilerCommand() const
+{
+ return m_compilerCommand;
+}
+
+FilePath IarToolChain::makeCommand(const Environment &env) const
+{
+ Q_UNUSED(env)
+ return {};
+}
+
+// IarToolChainFactory
+
+IarToolChainFactory::IarToolChainFactory()
+{
+ setDisplayName(tr("IAREW"));
+ setSupportedToolChainType(Constants::IAREW_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID,
+ ProjectExplorer::Constants::CXX_LANGUAGE_ID});
+ setToolchainConstructor([] { return new IarToolChain; });
+ setUserCreatable(true);
+}
+
+QList<ToolChain *> IarToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
+{
+ Candidates candidates;
+
+#ifdef Q_OS_WIN
+
+#ifdef Q_OS_WIN64
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\IAR Systems\\Embedded Workbench";
+#else
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\IAR Systems\\Embedded Workbench";
+#endif
+
+ // Dictionary for know toolchains.
+ static const struct Entry {
+ QString registryKey;
+ QString subExePath;
+ } knowToolchains[] = {
+ {"EWARM", "\\arm\\bin\\iccarm.exe"},
+ {"EWAVR", "\\avr\\bin\\iccavr.exe"},
+ {"EW8051", "\\8051\\bin\\icc8051.exe"},
+ };
+
+ QSettings registry(kRegistryNode, QSettings::NativeFormat);
+ const auto oneLevelGroups = registry.childGroups();
+ for (const QString &oneLevelKey : oneLevelGroups) {
+ registry.beginGroup(oneLevelKey);
+ const auto twoLevelGroups = registry.childGroups();
+ for (const Entry &entry : knowToolchains) {
+ if (twoLevelGroups.contains(entry.registryKey)) {
+ registry.beginGroup(entry.registryKey);
+ const auto threeLevelGroups = registry.childGroups();
+ for (const QString &threeLevelKey : threeLevelGroups) {
+ registry.beginGroup(threeLevelKey);
+ QString compilerPath = registry.value("InstallPath").toString();
+ if (!compilerPath.isEmpty()) {
+ // Build full compiler path.
+ compilerPath += entry.subExePath;
+ const FileName fn = FileName::fromString(compilerPath);
+ if (compilerExists(fn)) {
+ // Note: threeLevelKey is a guessed toolchain version.
+ candidates.push_back({fn, threeLevelKey});
+ }
+ }
+ registry.endGroup();
+ }
+ registry.endGroup();
+ }
+ }
+ registry.endGroup();
+ }
+
+#endif // Q_OS_WIN
+
+ return autoDetectToolchains(candidates, alreadyKnown);
+}
+
+QList<ToolChain *> IarToolChainFactory::autoDetectToolchains(
+ const Candidates &candidates, const QList<ToolChain *> &alreadyKnown) const
+{
+ QList<ToolChain *> result;
+
+ for (const Candidate &candidate : qAsConst(candidates)) {
+ const QList<ToolChain *> filtered = Utils::filtered(
+ alreadyKnown, [candidate](ToolChain *tc) {
+ return tc->typeId() == Constants::IAREW_TOOLCHAIN_TYPEID
+ && tc->compilerCommand() == candidate.compilerPath
+ && (tc->language() == ProjectExplorer::Constants::C_LANGUAGE_ID
+ || tc->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ });
+
+ if (!filtered.isEmpty()) {
+ result << filtered;
+ continue;
+ }
+
+ // Create toolchains for both C and C++ languages.
+ result << autoDetectToolchain(candidate, ProjectExplorer::Constants::C_LANGUAGE_ID);
+ result << autoDetectToolchain(candidate, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ }
+
+ return result;
+}
+
+QList<ToolChain *> IarToolChainFactory::autoDetectToolchain(
+ const Candidate &candidate, Core::Id languageId) const
+{
+ const auto env = Environment::systemEnvironment();
+ const Macros macros = dumpPredefinedMacros(candidate.compilerPath, languageId,
+ env.toStringList());
+ if (macros.isEmpty())
+ return {};
+ const Abi abi = guessAbi(macros);
+
+ const auto tc = new IarToolChain;
+ tc->setDetection(ToolChain::AutoDetection);
+ tc->setLanguage(languageId);
+ tc->setCompilerCommand(candidate.compilerPath);
+ tc->setTargetAbi(abi);
+ tc->setDisplayName(buildDisplayName(abi.architecture(), languageId,
+ candidate.compilerVersion));
+
+ const auto languageVersion = ToolChain::languageVersion(languageId, macros);
+ tc->predefinedMacrosCache()->insert({}, {macros, languageVersion});
+ return {tc};
+}
+
+// IarToolChainConfigWidget
+
+IarToolChainConfigWidget::IarToolChainConfigWidget(IarToolChain *tc) :
+ ToolChainConfigWidget(tc),
+ m_compilerCommand(new PathChooser),
+ m_abiWidget(new AbiWidget)
+{
+ m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
+ m_compilerCommand->setHistoryCompleter("PE.IAREW.Command.History");
+ m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
+ m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
+
+ m_abiWidget->setEnabled(false);
+
+ addErrorLabel();
+ setFromToolchain();
+
+ connect(m_compilerCommand, &PathChooser::rawPathChanged,
+ this, &IarToolChainConfigWidget::handleCompilerCommandChange);
+ connect(m_abiWidget, &AbiWidget::abiChanged,
+ this, &ToolChainConfigWidget::dirty);
+}
+
+void IarToolChainConfigWidget::applyImpl()
+{
+ if (toolChain()->isAutoDetected())
+ return;
+
+ const auto tc = static_cast<IarToolChain *>(toolChain());
+ const QString displayName = tc->displayName();
+ tc->setCompilerCommand(m_compilerCommand->fileName());
+ tc->setTargetAbi(m_abiWidget->currentAbi());
+ tc->setDisplayName(displayName);
+
+ if (m_macros.isEmpty())
+ return;
+
+ const auto languageVersion = ToolChain::languageVersion(tc->language(), m_macros);
+ tc->predefinedMacrosCache()->insert({}, {m_macros, languageVersion});
+
+ setFromToolchain();
+}
+
+bool IarToolChainConfigWidget::isDirtyImpl() const
+{
+ const auto tc = static_cast<IarToolChain *>(toolChain());
+ return m_compilerCommand->fileName() != tc->compilerCommand()
+ || m_abiWidget->currentAbi() != tc->targetAbi()
+ ;
+}
+
+void IarToolChainConfigWidget::makeReadOnlyImpl()
+{
+ m_compilerCommand->setReadOnly(true);
+ m_abiWidget->setEnabled(false);
+}
+
+void IarToolChainConfigWidget::setFromToolchain()
+{
+ const QSignalBlocker blocker(this);
+ const auto tc = static_cast<IarToolChain *>(toolChain());
+ m_compilerCommand->setFileName(tc->compilerCommand());
+ m_abiWidget->setAbis({}, tc->targetAbi());
+ const bool haveCompiler = compilerExists(m_compilerCommand->fileName());
+ m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected());
+}
+
+void IarToolChainConfigWidget::handleCompilerCommandChange()
+{
+ const FilePath compilerPath = m_compilerCommand->fileName();
+ const bool haveCompiler = compilerExists(compilerPath);
+ if (haveCompiler) {
+ const auto env = Environment::systemEnvironment();
+ const auto languageId = toolChain()->language();
+ m_macros = dumpPredefinedMacros(compilerPath, languageId,
+ env.toStringList());
+ const Abi guessed = guessAbi(m_macros);
+ m_abiWidget->setAbis({}, guessed);
+ }
+
+ m_abiWidget->setEnabled(haveCompiler);
+ emit dirty();
+}
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/iarewtoolchain.h b/src/plugins/baremetal/iarewtoolchain.h
new file mode 100644
index 0000000000..019c9e7185
--- /dev/null
+++ b/src/plugins/baremetal/iarewtoolchain.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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/abi.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchainconfigwidget.h>
+
+QT_BEGIN_NAMESPACE
+class QPlainTextEdit;
+class QPushButton;
+class QTextEdit;
+QT_END_NAMESPACE
+
+namespace Utils {
+class FilePath;
+class PathChooser;
+}
+
+namespace ProjectExplorer { class AbiWidget; }
+
+namespace BareMetal {
+namespace Internal {
+
+// IarToolChain
+
+class IarToolChain final : public ProjectExplorer::ToolChain
+{
+ Q_DECLARE_TR_FUNCTIONS(IarToolChain)
+
+public:
+ QString typeDisplayName() const final;
+
+ void setTargetAbi(const ProjectExplorer::Abi &abi);
+ ProjectExplorer::Abi targetAbi() const final;
+
+ bool isValid() const final;
+
+ MacroInspectionRunner createMacroInspectionRunner() const final;
+ ProjectExplorer::Macros predefinedMacros(const QStringList &cxxflags) const final;
+
+ Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const final;
+ ProjectExplorer::WarningFlags warningFlags(const QStringList &cxxflags) const final;
+
+ BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const final;
+ ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
+ const Utils::FilePath &) const final;
+ void addToEnvironment(Utils::Environment &env) const final;
+ ProjectExplorer::IOutputParser *outputParser() const final;
+
+ QVariantMap toMap() const final;
+ bool fromMap(const QVariantMap &data) final;
+
+ std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() final;
+
+ bool operator ==(const ToolChain &other) const final;
+
+ void setCompilerCommand(const Utils::FilePath &file);
+ Utils::FilePath compilerCommand() const final;
+
+ Utils::FilePath makeCommand(const Utils::Environment &env) const final;
+
+private:
+ IarToolChain();
+
+ ProjectExplorer::Abi m_targetAbi;
+ Utils::FilePath m_compilerCommand;
+
+ friend class IarToolChainFactory;
+ friend class IarToolChainConfigWidget;
+};
+
+// IarToolChainFactory
+
+class IarToolChainFactory final : public ProjectExplorer::ToolChainFactory
+{
+ Q_OBJECT
+
+public:
+ IarToolChainFactory();
+
+ QList<ProjectExplorer::ToolChain *> autoDetect(
+ const QList<ProjectExplorer::ToolChain *> &alreadyKnown) final;
+
+private:
+ QList<ProjectExplorer::ToolChain *> autoDetectToolchains(const Candidates &candidates,
+ const QList<ProjectExplorer::ToolChain *> &alreadyKnown) const;
+ QList<ProjectExplorer::ToolChain *> autoDetectToolchain(
+ const Candidate &candidate, Core::Id languageId) const;
+};
+
+// IarToolChainConfigWidget
+
+class IarToolChainConfigWidget final : public ProjectExplorer::ToolChainConfigWidget
+{
+ Q_OBJECT
+
+public:
+ explicit IarToolChainConfigWidget(IarToolChain *tc);
+
+private:
+ void applyImpl() final;
+ void discardImpl() final { setFromToolchain(); }
+ bool isDirtyImpl() const final;
+ void makeReadOnlyImpl() final;
+
+ void setFromToolchain();
+ void handleCompilerCommandChange();
+
+ Utils::PathChooser *m_compilerCommand = nullptr;
+ ProjectExplorer::AbiWidget *m_abiWidget = nullptr;
+ ProjectExplorer::Macros m_macros;
+};
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/keilparser.cpp b/src/plugins/baremetal/keilparser.cpp
new file mode 100644
index 0000000000..c1f8c34731
--- /dev/null
+++ b/src/plugins/baremetal/keilparser.cpp
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "keilparser.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/task.h>
+
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorsettings.h>
+
+#include <QRegularExpression>
+
+using namespace ProjectExplorer;
+
+namespace BareMetal {
+namespace Internal {
+
+// Helpers:
+
+static Task::TaskType taskType(const QString &msgType)
+{
+ if (msgType == "Warning" || msgType == "WARNING") {
+ return Task::TaskType::Warning;
+ } else if (msgType == "Error" || msgType == "ERROR"
+ || msgType == "Fatal error" || msgType == "FATAL ERROR") {
+ return Task::TaskType::Error;
+ }
+ return Task::TaskType::Unknown;
+}
+
+// KeilParser
+
+KeilParser::KeilParser()
+{
+ setObjectName("KeilParser");
+}
+
+Core::Id KeilParser::id()
+{
+ return "BareMetal.OutputParser.Keil";
+}
+
+void KeilParser::newTask(const Task &task)
+{
+ doFlush();
+ m_lastTask = task;
+ m_lines = 1;
+}
+
+void KeilParser::amendDescription(const QString &desc)
+{
+ const int start = m_lastTask.description.count() + 1;
+ m_lastTask.description.append(QLatin1Char('\n'));
+ m_lastTask.description.append(desc);
+
+ QTextLayout::FormatRange fr;
+ fr.start = start;
+ fr.length = m_lastTask.description.count() + 1;
+ fr.format.setFont(TextEditor::TextEditorSettings::fontSettings().font());
+ fr.format.setFontStyleHint(QFont::Monospace);
+ m_lastTask.formats.append(fr);
+
+ ++m_lines;
+}
+
+void KeilParser::stdError(const QString &line)
+{
+ IOutputParser::stdError(line);
+
+ const QString lne = rightTrimmed(line);
+
+ QRegularExpression re;
+ QRegularExpressionMatch match;
+
+ // ARM compiler specific patterns.
+
+ re.setPattern("^\"(.+)\", line (\\d+).*:\\s+(Warning|Error):(\\s+|.+)([#|L].+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
+ MessageTypeIndex, MessageNoteIndex, DescriptionIndex };
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
+ match.captured(FilePathIndex));
+ const int lineno = match.captured(LineNumberIndex).toInt();
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = match.captured(DescriptionIndex);
+ const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ re.setPattern("^(Error|Fatal error):\\s(.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageTypeIndex = 1, DescriptionIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = match.captured(DescriptionIndex);
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ if (lne.startsWith(QLatin1Char(' '))) {
+ amendDescription(lne);
+ return;
+ }
+
+ doFlush();
+}
+
+void KeilParser::stdOutput(const QString &line)
+{
+ IOutputParser::stdOutput(line);
+
+ const QString lne = rightTrimmed(line);
+
+ QRegularExpression re;
+ QRegularExpressionMatch match;
+
+ // MSC51 compiler specific patterns.
+
+ re.setPattern("^\\*{3} (WARNING|ERROR) (\\w+) IN LINE (\\d+) OF (.+\\.\\S+): (.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
+ FilePathIndex, MessageTextIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const int lineno = match.captured(LineNumberIndex).toInt();
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
+ match.captured(FilePathIndex));
+ const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
+ match.captured(MessageTextIndex));
+ const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ }
+
+ re.setPattern("^\\*{3} (WARNING|ERROR) (#\\w+) IN (\\d+) \\((.+), LINE \\d+\\): (.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
+ FilePathIndex, MessageTextIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const int lineno = match.captured(LineNumberIndex).toInt();
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
+ match.captured(FilePathIndex));
+ const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
+ match.captured(MessageTextIndex));
+ const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ }
+
+ re.setPattern("^\\*{3} (FATAL ERROR) (.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageTypeIndex = 1, MessageDescriptionIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = match.captured(MessageDescriptionIndex);
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ re.setPattern("^(A|C)51 FATAL[ |-]ERROR");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ const QString key = match.captured(1);
+ QString descr;
+ if (key == QLatin1Char('A'))
+ descr = "Assembler fatal error";
+ else if (key == QLatin1Char('C'))
+ descr = "Compiler fatal error";
+ const Task task(Task::TaskType::Error, descr, {}, -1,
+ Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ if (lne.startsWith(QLatin1Char(' '))) {
+ amendDescription(lne);
+ return;
+ }
+
+ doFlush();
+}
+
+void KeilParser::doFlush()
+{
+ if (m_lastTask.isNull())
+ return;
+
+ Task t = m_lastTask;
+ m_lastTask.clear();
+ emit addTask(t, m_lines, 1);
+ m_lines = 0;
+}
+
+} // namespace Internal
+} // namespace BareMetal
+
+// Unit tests:
+
+#ifdef WITH_TESTS
+#include "baremetalplugin.h"
+#include <projectexplorer/outputparser_test.h>
+#include <QTest>
+
+namespace BareMetal {
+namespace Internal {
+
+void BareMetalPlugin::testKeilOutputParsers_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<OutputParserTester::Channel>("inputChannel");
+ QTest::addColumn<QString>("childStdOutLines");
+ QTest::addColumn<QString>("childStdErrLines");
+ QTest::addColumn<Tasks >("tasks");
+ QTest::addColumn<QString>("outputLines");
+
+ QTest::newRow("pass-through stdout")
+ << "Sometext" << OutputParserTester::STDOUT
+ << "Sometext\n" << QString()
+ << Tasks()
+ << QString();
+ QTest::newRow("pass-through stderr")
+ << "Sometext" << OutputParserTester::STDERR
+ << QString() << "Sometext\n"
+ << Tasks()
+ << QString();
+
+ const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
+
+ // ARM compiler specific patterns.
+
+ QTest::newRow("ARM: No details warning")
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("#1234: Some warning"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("ARM: Details warning")
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning\n"
+ " int f;\n"
+ " ^")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning\n"
+ " int f;\n"
+ " ^\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("#1234: Some warning\n"
+ " int f;\n"
+ " ^"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("ARM: No details error")
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("#1234: Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("ARM: No details error with column")
+ << QString::fromLatin1("\"flash.sct\", line 51 (column 20): Error: L1234: Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"flash.sct\", line 51 (column 20): Error: L1234: Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("L1234: Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("flash.sct")),
+ 51,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("ARM: Details error")
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error\n"
+ " int f;\n"
+ " ^")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error\n"
+ " int f;\n"
+ " ^\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("#1234: Some error\n"
+ " int f;\n"
+ " ^"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("ARM: At end of source")
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 71: Error: At end of source: #40: Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("\"c:\\foo\\main.c\", line 71: Error: At end of source: #40: Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("#40: Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 71,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("ARM: Starts with error")
+ << QString::fromLatin1("Error: L6226E: Some error.")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("Error: L6226E: Some error.\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("L6226E: Some error."),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ // MCS51 compiler specific patterns.
+
+ // Assembler messages.
+ QTest::newRow("MCS51: Assembler simple warning")
+ << QString::fromLatin1("*** WARNING #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some warning")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** WARNING #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some warning\n")
+ << QString()
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("#A9: Some warning"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\dscr.a51")),
+ 15,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("MCS51: Assembler simple error")
+ << QString::fromLatin1("*** ERROR #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some error")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** ERROR #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some error\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("#A9: Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\dscr.a51")),
+ 15,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("MCS51: Assembler fatal error")
+ << QString::fromLatin1("A51 FATAL ERROR -\n"
+ " Some detail 1\n"
+ " Some detail N")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("A51 FATAL ERROR -\n"
+ " Some detail 1\n"
+ " Some detail N\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("Assembler fatal error\n"
+ " Some detail 1\n"
+ " Some detail N"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ // Compiler messages.
+ QTest::newRow("MCS51: Compiler simple warning")
+ << QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning\n")
+ << QString()
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("C123: Some warning"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo.c")),
+ 13,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("MCS51: Compiler extended warning")
+ << QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning : 'extended text'")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning : 'extended text'\n")
+ << QString()
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("C123: Some warning : 'extended text'"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo.c")),
+ 13,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("MCS51: Compiler simple error")
+ << QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("C123: Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo.c")),
+ 13,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("MCS51: Compiler extended error")
+ << QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error : 'extended text'")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error : 'extended text'\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("C123: Some error : 'extended text'"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo.c")),
+ 13,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("MCS51: Compiler fatal error")
+ << QString::fromLatin1("C51 FATAL-ERROR -\n"
+ " Some detail 1\n"
+ " Some detail N")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("C51 FATAL-ERROR -\n"
+ " Some detail 1\n"
+ " Some detail N\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("Compiler fatal error\n"
+ " Some detail 1\n"
+ " Some detail N"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ // Linker messages.
+ QTest::newRow("MCS51: Linker simple fatal error")
+ << QString::fromLatin1("*** FATAL ERROR L456: Some error")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** FATAL ERROR L456: Some error\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("L456: Some error"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("MCS51: Linker extended fatal error")
+ << QString::fromLatin1("*** FATAL ERROR L456: Some error\n"
+ " Some detail 1\n"
+ " Some detail N")
+ << OutputParserTester::STDOUT
+ << QString::fromLatin1("*** FATAL ERROR L456: Some error\n"
+ " Some detail 1\n"
+ " Some detail N\n")
+ << QString()
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("L456: Some error\n"
+ " Some detail 1\n"
+ " Some detail N"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+}
+
+void BareMetalPlugin::testKeilOutputParsers()
+{
+ OutputParserTester testbench;
+ testbench.appendOutputParser(new KeilParser);
+ QFETCH(QString, input);
+ QFETCH(OutputParserTester::Channel, inputChannel);
+ QFETCH(Tasks, tasks);
+ QFETCH(QString, childStdOutLines);
+ QFETCH(QString, childStdErrLines);
+ QFETCH(QString, outputLines);
+
+ testbench.testParsing(input, inputChannel,
+ tasks, childStdOutLines, childStdErrLines,
+ outputLines);
+}
+
+} // namespace Internal
+} // namespace BareMetal
+
+#endif // WITH_TESTS
diff --git a/src/plugins/baremetal/keilparser.h b/src/plugins/baremetal/keilparser.h
new file mode 100644
index 0000000000..d8e9bdfd7d
--- /dev/null
+++ b/src/plugins/baremetal/keilparser.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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/ioutputparser.h>
+#include <projectexplorer/task.h>
+
+namespace BareMetal {
+namespace Internal {
+
+// KeilParser
+
+class KeilParser final : public ProjectExplorer::IOutputParser
+{
+ Q_OBJECT
+
+public:
+ explicit KeilParser();
+ static Core::Id id();
+
+private:
+ void newTask(const ProjectExplorer::Task &task);
+ void amendDescription(const QString &desc);
+
+ void stdError(const QString &line) final;
+ void stdOutput(const QString &line) final;
+ void doFlush() final;
+
+ ProjectExplorer::Task m_lastTask;
+ int m_lines = 0;
+};
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp
new file mode 100644
index 0000000000..303efa3440
--- /dev/null
+++ b/src/plugins/baremetal/keiltoolchain.cpp
@@ -0,0 +1,596 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "baremetalconstants.h"
+
+#include "keilparser.h"
+#include "keiltoolchain.h"
+
+#include <projectexplorer/abiwidget.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectmacro.h>
+#include <projectexplorer/toolchainmanager.h>
+
+#include <utils/algorithm.h>
+#include <utils/environment.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+#include <utils/synchronousprocess.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QFileInfo>
+#include <QFormLayout>
+#include <QLineEdit>
+#include <QPlainTextEdit>
+#include <QSettings>
+#include <QTemporaryFile>
+#include <QTextStream>
+
+#include <array>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace BareMetal {
+namespace Internal {
+
+// Helpers:
+
+static const char compilerCommandKeyC[] = "BareMetal.KeilToolchain.CompilerPath";
+static const char targetAbiKeyC[] = "BareMetal.KeilToolchain.TargetAbi";
+
+static bool compilerExists(const FilePath &compilerPath)
+{
+ const QFileInfo fi = compilerPath.toFileInfo();
+ return fi.exists() && fi.isExecutable() && fi.isFile();
+}
+
+static Abi::Architecture guessArchitecture(const FilePath &compilerPath)
+{
+ const QFileInfo fi = compilerPath.toFileInfo();
+ const QString bn = fi.baseName().toLower();
+ if (bn == "c51" || bn == "cx51")
+ return Abi::Architecture::Mcs51Architecture;
+ if (bn == "armcc")
+ return Abi::Architecture::ArmArchitecture;
+ return Abi::Architecture::UnknownArchitecture;
+}
+
+// Note: The KEIL 8051 compiler does not support the predefined
+// macros dumping. So, we do it with following trick where we try
+// to compile a temporary file and to parse the console output.
+static Macros dumpC51PredefinedMacros(const FilePath &compiler, const QStringList &env)
+{
+ QTemporaryFile fakeIn;
+ if (!fakeIn.open())
+ return {};
+ fakeIn.write("#define VALUE_TO_STRING(x) #x\n");
+ fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n");
+ fakeIn.write("#define VAR_NAME_VALUE(var) \"\"\"|\"#var\"|\"VALUE(var)\n");
+ fakeIn.write("#ifdef __C51__\n");
+ fakeIn.write("#pragma message(VAR_NAME_VALUE(__C51__))\n");
+ fakeIn.write("#endif\n");
+ fakeIn.write("#ifdef __CX51__\n");
+ fakeIn.write("#pragma message(VAR_NAME_VALUE(__CX51__))\n");
+ fakeIn.write("#endif\n");
+ fakeIn.close();
+
+ SynchronousProcess cpp;
+ cpp.setEnvironment(env);
+ cpp.setTimeoutS(10);
+
+ QStringList arguments;
+ arguments.push_back(fakeIn.fileName());
+
+ const SynchronousProcessResponse response = cpp.runBlocking(compiler.toString(), arguments);
+ if (response.result != SynchronousProcessResponse::Finished
+ || response.exitCode != 0) {
+ qWarning() << response.exitMessage(compiler.toString(), 10);
+ return {};
+ }
+
+ QString output = response.allOutput();
+ Macros macros;
+ QTextStream stream(&output);
+ QString line;
+ while (stream.readLineInto(&line)) {
+ const QStringList parts = line.split("\"|\"");
+ if (parts.count() != 3)
+ continue;
+ macros.push_back({parts.at(1).toUtf8(), parts.at(2).toUtf8()});
+ }
+ return macros;
+}
+
+static Macros dumpArmPredefinedMacros(const FilePath &compiler, const QStringList &env)
+{
+ SynchronousProcess cpp;
+ cpp.setEnvironment(env);
+ cpp.setTimeoutS(10);
+
+ QStringList arguments;
+ arguments.push_back("-E");
+ arguments.push_back("--list-macros");
+
+ const SynchronousProcessResponse response = cpp.runBlocking(compiler.toString(), arguments);
+ if (response.result != SynchronousProcessResponse::Finished
+ || response.exitCode != 0) {
+ qWarning() << response.exitMessage(compiler.toString(), 10);
+ return {};
+ }
+
+ const QByteArray output = response.allOutput().toUtf8();
+ return Macro::toMacros(output);
+}
+
+static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &env)
+{
+ if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable())
+ return {};
+
+ const Abi::Architecture arch = guessArchitecture(compiler);
+ switch (arch) {
+ case Abi::Architecture::Mcs51Architecture:
+ return dumpC51PredefinedMacros(compiler, env);
+ case Abi::Architecture::ArmArchitecture:
+ return dumpArmPredefinedMacros(compiler, env);
+ default:
+ return {};
+ }
+}
+
+static HeaderPaths dumpHeaderPaths(const FilePath &compiler)
+{
+ if (!compiler.exists())
+ return {};
+
+ QDir toolkitDir(compiler.parentDir().toString());
+ if (!toolkitDir.cdUp())
+ return {};
+
+ HeaderPaths headerPaths;
+
+ const Abi::Architecture arch = guessArchitecture(compiler);
+ if (arch == Abi::Architecture::Mcs51Architecture) {
+ QDir includeDir(toolkitDir);
+ if (includeDir.cd("inc"))
+ headerPaths.push_back({includeDir.canonicalPath(), HeaderPathType::BuiltIn});
+ } else if (arch == Abi::Architecture::ArmArchitecture) {
+ QDir includeDir(toolkitDir);
+ if (includeDir.cd("include"))
+ headerPaths.push_back({includeDir.canonicalPath(), HeaderPathType::BuiltIn});
+ }
+
+ return headerPaths;
+}
+
+static Abi::Architecture guessArchitecture(const Macros &macros)
+{
+ for (const Macro &macro : macros) {
+ if (macro.key == "__CC_ARM")
+ return Abi::Architecture::ArmArchitecture;
+ if (macro.key == "__C51__" || macro.key == "__CX51__")
+ return Abi::Architecture::Mcs51Architecture;
+ }
+ return Abi::Architecture::UnknownArchitecture;
+}
+
+static unsigned char guessWordWidth(const Macros &macros, Abi::Architecture arch)
+{
+ // Check for C51 compiler first.
+ if (arch == Abi::Architecture::Mcs51Architecture)
+ return 16; // C51 always have 16-bit word width.
+
+ const Macro sizeMacro = Utils::findOrDefault(macros, [](const Macro &m) {
+ return m.key == "__sizeof_int";
+ });
+ if (sizeMacro.isValid() && sizeMacro.type == MacroType::Define)
+ return sizeMacro.value.toInt() * 8;
+ return 0;
+}
+
+static Abi::BinaryFormat guessFormat(Abi::Architecture arch)
+{
+ if (arch == Abi::Architecture::ArmArchitecture)
+ return Abi::BinaryFormat::ElfFormat;
+ if (arch == Abi::Architecture::Mcs51Architecture)
+ return Abi::BinaryFormat::OmfFormat;
+ return Abi::BinaryFormat::UnknownFormat;
+}
+
+static Abi guessAbi(const Macros &macros)
+{
+ const auto arch = guessArchitecture(macros);
+ return {arch, Abi::OS::BareMetalOS, Abi::OSFlavor::GenericFlavor,
+ guessFormat(arch), guessWordWidth(macros, arch)};
+}
+
+static QString buildDisplayName(Abi::Architecture arch, Core::Id language,
+ const QString &version)
+{
+ const auto archName = Abi::toString(arch);
+ const auto langName = ToolChainManager::displayNameOfLanguageId(language);
+ return KeilToolchain::tr("KEIL %1 (%2, %3)")
+ .arg(version, langName, archName);
+}
+
+// KeilToolchain
+
+KeilToolchain::KeilToolchain() :
+ ToolChain(Constants::KEIL_TOOLCHAIN_TYPEID)
+{ }
+
+QString KeilToolchain::typeDisplayName() const
+{
+ return Internal::KeilToolchainFactory::tr("KEIL");
+}
+
+void KeilToolchain::setTargetAbi(const Abi &abi)
+{
+ if (abi == m_targetAbi)
+ return;
+ m_targetAbi = abi;
+ toolChainUpdated();
+}
+
+Abi KeilToolchain::targetAbi() const
+{
+ return m_targetAbi;
+}
+
+bool KeilToolchain::isValid() const
+{
+ return true;
+}
+
+ToolChain::MacroInspectionRunner KeilToolchain::createMacroInspectionRunner() const
+{
+ Environment env = Environment::systemEnvironment();
+ addToEnvironment(env);
+
+ const Utils::FilePath compilerCommand = m_compilerCommand;
+ const Core::Id lang = language();
+
+ MacrosCache macroCache = predefinedMacrosCache();
+
+ return [env, compilerCommand, macroCache, lang]
+ (const QStringList &flags) {
+ Q_UNUSED(flags)
+
+ const Macros macros = dumpPredefinedMacros(compilerCommand, env.toStringList());
+ const auto report = MacroInspectionReport{macros, languageVersion(lang, macros)};
+ macroCache->insert({}, report);
+
+ return report;
+ };
+}
+
+Macros KeilToolchain::predefinedMacros(const QStringList &cxxflags) const
+{
+ return createMacroInspectionRunner()(cxxflags).macros;
+}
+
+Utils::LanguageExtensions KeilToolchain::languageExtensions(const QStringList &) const
+{
+ return LanguageExtension::None;
+}
+
+WarningFlags KeilToolchain::warningFlags(const QStringList &cxxflags) const
+{
+ Q_UNUSED(cxxflags);
+ return WarningFlags::Default;
+}
+
+ToolChain::BuiltInHeaderPathsRunner KeilToolchain::createBuiltInHeaderPathsRunner() const
+{
+ const Utils::FilePath compilerCommand = m_compilerCommand;
+
+ HeaderPathsCache headerPaths = headerPathsCache();
+
+ return [compilerCommand,
+ headerPaths](const QStringList &flags, const QString &fileName, const QString &) {
+ Q_UNUSED(flags)
+ Q_UNUSED(fileName)
+
+ const HeaderPaths paths = dumpHeaderPaths(compilerCommand);
+ headerPaths->insert({}, paths);
+
+ return paths;
+ };
+}
+
+HeaderPaths KeilToolchain::builtInHeaderPaths(const QStringList &cxxFlags,
+ const FilePath &fileName) const
+{
+ return createBuiltInHeaderPathsRunner()(cxxFlags, fileName.toString(), "");
+}
+
+void KeilToolchain::addToEnvironment(Environment &env) const
+{
+ if (!m_compilerCommand.isEmpty()) {
+ const FilePath path = m_compilerCommand.parentDir();
+ env.prependOrSetPath(path.toString());
+ }
+}
+
+IOutputParser *KeilToolchain::outputParser() const
+{
+ return new KeilParser;
+}
+
+QVariantMap KeilToolchain::toMap() const
+{
+ QVariantMap data = ToolChain::toMap();
+ data.insert(compilerCommandKeyC, m_compilerCommand.toString());
+ data.insert(targetAbiKeyC, m_targetAbi.toString());
+ return data;
+}
+
+bool KeilToolchain::fromMap(const QVariantMap &data)
+{
+ if (!ToolChain::fromMap(data))
+ return false;
+ m_compilerCommand = FilePath::fromString(data.value(compilerCommandKeyC).toString());
+ m_targetAbi = Abi::fromString(data.value(targetAbiKeyC).toString());
+ return true;
+}
+
+std::unique_ptr<ToolChainConfigWidget> KeilToolchain::createConfigurationWidget()
+{
+ return std::make_unique<KeilToolchainConfigWidget>(this);
+}
+
+bool KeilToolchain::operator ==(const ToolChain &other) const
+{
+ if (!ToolChain::operator ==(other))
+ return false;
+
+ const auto customTc = static_cast<const KeilToolchain *>(&other);
+ return m_compilerCommand == customTc->m_compilerCommand
+ && m_targetAbi == customTc->m_targetAbi
+ ;
+}
+
+void KeilToolchain::setCompilerCommand(const FilePath &file)
+{
+ if (file == m_compilerCommand)
+ return;
+ m_compilerCommand = file;
+ toolChainUpdated();
+}
+
+FilePath KeilToolchain::compilerCommand() const
+{
+ return m_compilerCommand;
+}
+
+FilePath KeilToolchain::makeCommand(const Environment &env) const
+{
+ Q_UNUSED(env)
+ return {};
+}
+
+// KeilToolchainFactory
+
+KeilToolchainFactory::KeilToolchainFactory()
+{
+ setDisplayName(tr("KEIL"));
+ setSupportedToolChainType(Constants::KEIL_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID,
+ ProjectExplorer::Constants::CXX_LANGUAGE_ID});
+ setToolchainConstructor([] { return new KeilToolchain; });
+ setUserCreatable(true);
+}
+
+QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
+{
+#ifdef Q_OS_WIN64
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Keil\\Products";
+#else
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Keil\\Products";
+#endif
+
+ struct Entry {
+ QString productKey;
+ QString subExePath;
+ };
+
+ // Dictionary for know toolchains.
+ static const std::array<Entry, 2> knowToolchains = {{
+ {QString("MDK"), QString("\\ARMCC\\bin\\armcc.exe")},
+ {QString("C51"), QString("\\BIN\\c51.exe")},
+ }};
+
+ Candidates candidates;
+
+ QSettings registry(kRegistryNode, QSettings::NativeFormat);
+ const auto productGroups = registry.childGroups();
+ for (const QString &productKey : productGroups) {
+ const Entry entry = Utils::findOrDefault(knowToolchains,
+ [productKey](const Entry &entry) {
+ return entry.productKey == productKey; });
+
+ if (entry.productKey.isEmpty())
+ continue;
+
+ registry.beginGroup(productKey);
+ QString compilerPath = registry.value("Path").toString();
+ if (!compilerPath.isEmpty()) {
+ // Build full compiler path.
+ compilerPath += entry.subExePath;
+ const FilePath fn = FilePath::fromString(compilerPath);
+ if (compilerExists(fn)) {
+ QString version = registry.value("Version").toString();
+ if (version.startsWith('V'))
+ version.remove(0, 1);
+ candidates.push_back({fn, version});
+ }
+ }
+ registry.endGroup();
+ }
+
+ return autoDetectToolchains(candidates, alreadyKnown);
+}
+
+QList<ToolChain *> KeilToolchainFactory::autoDetectToolchains(
+ const Candidates &candidates, const QList<ToolChain *> &alreadyKnown) const
+{
+ QList<ToolChain *> result;
+
+ for (const Candidate &candidate : qAsConst(candidates)) {
+ const QList<ToolChain *> filtered = Utils::filtered(
+ alreadyKnown, [candidate](ToolChain *tc) {
+ return tc->typeId() == Constants::IAREW_TOOLCHAIN_TYPEID
+ && tc->compilerCommand() == candidate.compilerPath
+ && (tc->language() == ProjectExplorer::Constants::C_LANGUAGE_ID
+ || tc->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ });
+
+ if (!filtered.isEmpty()) {
+ result << filtered;
+ continue;
+ }
+
+ // Create toolchains for both C and C++ languages.
+ result << autoDetectToolchain(candidate, ProjectExplorer::Constants::C_LANGUAGE_ID);
+ result << autoDetectToolchain(candidate, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ }
+
+ return result;
+}
+
+QList<ToolChain *> KeilToolchainFactory::autoDetectToolchain(
+ const Candidate &candidate, Core::Id language) const
+{
+ const auto env = Environment::systemEnvironment();
+ const Macros macros = dumpPredefinedMacros(candidate.compilerPath, env.toStringList());
+ if (macros.isEmpty())
+ return {};
+
+ const Abi abi = guessAbi(macros);
+ const Abi::Architecture arch = abi.architecture();
+ if (arch == Abi::Architecture::Mcs51Architecture
+ && language == ProjectExplorer::Constants::CXX_LANGUAGE_ID) {
+ // KEIL C51 compiler does not support C++ language.
+ return {};
+ }
+
+ const auto tc = new KeilToolchain;
+ tc->setDetection(ToolChain::AutoDetection);
+ tc->setLanguage(language);
+ tc->setCompilerCommand(candidate.compilerPath);
+ tc->setTargetAbi(abi);
+ tc->setDisplayName(buildDisplayName(abi.architecture(), language, candidate.compilerVersion));
+
+ const auto languageVersion = ToolChain::languageVersion(language, macros);
+ tc->predefinedMacrosCache()->insert({}, {macros, languageVersion});
+ return {tc};
+}
+
+// KeilToolchainConfigWidget
+
+KeilToolchainConfigWidget::KeilToolchainConfigWidget(KeilToolchain *tc) :
+ ToolChainConfigWidget(tc),
+ m_compilerCommand(new PathChooser),
+ m_abiWidget(new AbiWidget)
+{
+ m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
+ m_compilerCommand->setHistoryCompleter("PE.KEIL.Command.History");
+ m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
+ m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
+
+ m_abiWidget->setEnabled(false);
+
+ addErrorLabel();
+ setFromToolchain();
+
+ connect(m_compilerCommand, &PathChooser::rawPathChanged,
+ this, &KeilToolchainConfigWidget::handleCompilerCommandChange);
+ connect(m_abiWidget, &AbiWidget::abiChanged,
+ this, &ToolChainConfigWidget::dirty);
+}
+
+void KeilToolchainConfigWidget::applyImpl()
+{
+ if (toolChain()->isAutoDetected())
+ return;
+
+ const auto tc = static_cast<KeilToolchain *>(toolChain());
+ const QString displayName = tc->displayName();
+ tc->setCompilerCommand(m_compilerCommand->fileName());
+ tc->setTargetAbi(m_abiWidget->currentAbi());
+ tc->setDisplayName(displayName);
+
+ if (m_macros.isEmpty())
+ return;
+
+ const auto languageVersion = ToolChain::languageVersion(tc->language(), m_macros);
+ tc->predefinedMacrosCache()->insert({}, {m_macros, languageVersion});
+
+ setFromToolchain();
+}
+
+bool KeilToolchainConfigWidget::isDirtyImpl() const
+{
+ const auto tc = static_cast<KeilToolchain *>(toolChain());
+ return m_compilerCommand->fileName() != tc->compilerCommand()
+ || m_abiWidget->currentAbi() != tc->targetAbi()
+ ;
+}
+
+void KeilToolchainConfigWidget::makeReadOnlyImpl()
+{
+ m_compilerCommand->setReadOnly(true);
+ m_abiWidget->setEnabled(false);
+}
+
+void KeilToolchainConfigWidget::setFromToolchain()
+{
+ const QSignalBlocker blocker(this);
+ const auto tc = static_cast<KeilToolchain *>(toolChain());
+ m_compilerCommand->setFileName(tc->compilerCommand());
+ m_abiWidget->setAbis({}, tc->targetAbi());
+ const bool haveCompiler = compilerExists(m_compilerCommand->fileName());
+ m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected());
+}
+
+void KeilToolchainConfigWidget::handleCompilerCommandChange()
+{
+ const FilePath compilerPath = m_compilerCommand->fileName();
+ const bool haveCompiler = compilerExists(compilerPath);
+ if (haveCompiler) {
+ const auto env = Environment::systemEnvironment();
+ m_macros = dumpPredefinedMacros(compilerPath, env.toStringList());
+ const Abi guessed = guessAbi(m_macros);
+ m_abiWidget->setAbis({}, guessed);
+ }
+
+ m_abiWidget->setEnabled(haveCompiler);
+ emit dirty();
+}
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/keiltoolchain.h b/src/plugins/baremetal/keiltoolchain.h
new file mode 100644
index 0000000000..5ccf9e05ff
--- /dev/null
+++ b/src/plugins/baremetal/keiltoolchain.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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/abi.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchainconfigwidget.h>
+
+QT_BEGIN_NAMESPACE
+class QPlainTextEdit;
+class QPushButton;
+class QTextEdit;
+QT_END_NAMESPACE
+
+namespace Utils {
+class FilePath;
+class PathChooser;
+}
+
+namespace ProjectExplorer { class AbiWidget; }
+
+namespace BareMetal {
+namespace Internal {
+
+// KeilToolchain
+
+class KeilToolchain final : public ProjectExplorer::ToolChain
+{
+ Q_DECLARE_TR_FUNCTIONS(KeilToolchain)
+
+public:
+ QString typeDisplayName() const final;
+
+ void setTargetAbi(const ProjectExplorer::Abi &abi);
+ ProjectExplorer::Abi targetAbi() const final;
+
+ bool isValid() const final;
+
+ MacroInspectionRunner createMacroInspectionRunner() const final;
+ ProjectExplorer::Macros predefinedMacros(const QStringList &cxxflags) const final;
+
+ Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const final;
+ ProjectExplorer::WarningFlags warningFlags(const QStringList &cxxflags) const final;
+
+ BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const final;
+ ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
+ const Utils::FilePath &) const final;
+ void addToEnvironment(Utils::Environment &env) const final;
+ ProjectExplorer::IOutputParser *outputParser() const final;
+
+ QVariantMap toMap() const final;
+ bool fromMap(const QVariantMap &data) final;
+
+ std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() final;
+
+ bool operator ==(const ToolChain &other) const final;
+
+ void setCompilerCommand(const Utils::FilePath &file);
+ Utils::FilePath compilerCommand() const final;
+
+ Utils::FilePath makeCommand(const Utils::Environment &env) const final;
+
+private:
+ KeilToolchain();
+
+ ProjectExplorer::Abi m_targetAbi;
+ Utils::FilePath m_compilerCommand;
+
+ friend class KeilToolchainFactory;
+ friend class KeilToolchainConfigWidget;
+};
+
+// KeilToolchainFactory
+
+class KeilToolchainFactory final : public ProjectExplorer::ToolChainFactory
+{
+ Q_OBJECT
+
+public:
+ KeilToolchainFactory();
+
+ QList<ProjectExplorer::ToolChain *> autoDetect(
+ const QList<ProjectExplorer::ToolChain *> &alreadyKnown) final;
+
+private:
+ QList<ProjectExplorer::ToolChain *> autoDetectToolchains(const Candidates &candidates,
+ const QList<ProjectExplorer::ToolChain *> &alreadyKnown) const;
+ QList<ProjectExplorer::ToolChain *> autoDetectToolchain(
+ const Candidate &candidate, Core::Id language) const;
+};
+
+// KeilToolchainConfigWidget
+
+class KeilToolchainConfigWidget final : public ProjectExplorer::ToolChainConfigWidget
+{
+ Q_OBJECT
+
+public:
+ explicit KeilToolchainConfigWidget(KeilToolchain *tc);
+
+private:
+ void applyImpl() final;
+ void discardImpl() final { setFromToolchain(); }
+ bool isDirtyImpl() const final;
+ void makeReadOnlyImpl() final;
+
+ void setFromToolchain();
+ void handleCompilerCommandChange();
+
+ Utils::PathChooser *m_compilerCommand = nullptr;
+ ProjectExplorer::AbiWidget *m_abiWidget = nullptr;
+ ProjectExplorer::Macros m_macros;
+};
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/openocdgdbserverprovider.cpp b/src/plugins/baremetal/openocdgdbserverprovider.cpp
index 33d05c88a2..b7044defe0 100644
--- a/src/plugins/baremetal/openocdgdbserverprovider.cpp
+++ b/src/plugins/baremetal/openocdgdbserverprovider.cpp
@@ -23,25 +23,26 @@
**
****************************************************************************/
-#include "openocdgdbserverprovider.h"
#include "baremetalconstants.h"
+
#include "gdbserverprovidermanager.h"
+#include "openocdgdbserverprovider.h"
+#include <utils/fileutils.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
#include <utils/qtcprocess.h>
#include <coreplugin/variablechooser.h>
-#include <QString>
+#include <QComboBox>
#include <QFileInfo>
-
#include <QFormLayout>
#include <QLineEdit>
-#include <QComboBox>
#include <QPlainTextEdit>
+using namespace Utils;
+
namespace BareMetal {
namespace Internal {
@@ -52,11 +53,10 @@ const char rootScriptsDirKeyC[] = "BareMetal.OpenOcdGdbServerProvider.RootScript
const char configurationFileKeyC[] = "BareMetal.OpenOcdGdbServerProvider.ConfigurationPath";
const char additionalArgumentsKeyC[] = "BareMetal.OpenOcdGdbServerProvider.AdditionalArguments";
+// OpenOcdGdbServerProvider
+
OpenOcdGdbServerProvider::OpenOcdGdbServerProvider()
: GdbServerProvider(QLatin1String(Constants::OPENOCD_PROVIDER_ID))
- , m_host(QLatin1String("localhost"))
- , m_port(3333)
- , m_executableFile(QLatin1String("openocd"))
{
setInitCommands(defaultInitCommands());
setResetCommands(defaultResetCommands());
@@ -93,48 +93,43 @@ QString OpenOcdGdbServerProvider::channel() const
// Just return as "host:port" form.
return m_host + QLatin1Char(':') + QString::number(m_port);
case StartupOnPipe: {
- QStringList args;
// In the pipe mode need to add quotes to each item of arguments;
// otherwise running will be stuck.
- foreach (const QString &a, arguments()) {
- if (a.startsWith(QLatin1Char('\"')) && a.endsWith(QLatin1Char('\"')))
- continue;
- args << (QLatin1Char('\"') + a + QLatin1Char('\"'));
+ CommandLine cmd = command();
+ QStringList args = {"|", cmd.executable().toString()};
+ for (const QString &a : QtcProcess::splitArgs(cmd.arguments())) {
+ if (a.startsWith('\"') && a.endsWith('\"'))
+ args << a;
+ else
+ args << ('\"' + a + '\"');
}
- args.prepend(executable());
- args.prepend(QLatin1String("|"));
- return args.join(QLatin1Char(' '));
+ return args.join(' ');
}
default: // wrong
- return QString();
+ return {};
}
}
-QString OpenOcdGdbServerProvider::executable() const
-{
- return m_executableFile;
-}
-
-QStringList OpenOcdGdbServerProvider::arguments() const
+CommandLine OpenOcdGdbServerProvider::command() const
{
- QStringList args;
+ CommandLine cmd{m_executableFile, {}};
- args << QLatin1String("-c");
+ cmd.addArg("-c");
if (startupMode() == StartupOnPipe)
- args << QLatin1String("gdb_port pipe");
+ cmd.addArg("gdb_port pipe");
else
- args << (QLatin1String("gdb_port ") + QString::number(m_port));
+ cmd.addArg("gdb_port " + QString::number(m_port));
if (!m_rootScriptsDir.isEmpty())
- args << QLatin1String("-s") << m_rootScriptsDir;
+ cmd.addArgs({"-s", m_rootScriptsDir});
if (!m_configurationFile.isEmpty())
- args << QLatin1String("-f") << m_configurationFile;
+ cmd.addArgs({"-f", m_configurationFile});
if (!m_additionalArguments.isEmpty())
- args << Utils::QtcProcess::splitArgs(m_additionalArguments);
+ cmd.addArgs(m_additionalArguments);
- return args;
+ return cmd;
}
bool OpenOcdGdbServerProvider::canStartupMode(StartupMode m) const
@@ -172,7 +167,7 @@ QVariantMap OpenOcdGdbServerProvider::toMap() const
QVariantMap data = GdbServerProvider::toMap();
data.insert(QLatin1String(hostKeyC), m_host);
data.insert(QLatin1String(portKeyC), m_port);
- data.insert(QLatin1String(executableFileKeyC), m_executableFile);
+ data.insert(QLatin1String(executableFileKeyC), m_executableFile.toVariant());
data.insert(QLatin1String(rootScriptsDirKeyC), m_rootScriptsDir);
data.insert(QLatin1String(configurationFileKeyC), m_configurationFile);
data.insert(QLatin1String(additionalArgumentsKeyC), m_additionalArguments);
@@ -186,7 +181,7 @@ bool OpenOcdGdbServerProvider::fromMap(const QVariantMap &data)
m_host = data.value(QLatin1String(hostKeyC)).toString();
m_port = data.value(QLatin1String(portKeyC)).toInt();
- m_executableFile = data.value(QLatin1String(executableFileKeyC)).toString();
+ m_executableFile = FilePath::fromVariant(data.value(QLatin1String(executableFileKeyC)));
m_rootScriptsDir = data.value(QLatin1String(rootScriptsDirKeyC)).toString();
m_configurationFile = data.value(QLatin1String(configurationFileKeyC)).toString();
m_additionalArguments = data.value(QLatin1String(additionalArgumentsKeyC)).toString();
@@ -212,6 +207,8 @@ GdbServerProviderConfigWidget *OpenOcdGdbServerProvider::configurationWidget()
return new OpenOcdGdbServerProviderConfigWidget(this);
}
+// OpenOcdGdbServerProviderFactory
+
OpenOcdGdbServerProviderFactory::OpenOcdGdbServerProviderFactory()
{
setId(QLatin1String(Constants::OPENOCD_PROVIDER_ID));
@@ -232,14 +229,16 @@ bool OpenOcdGdbServerProviderFactory::canRestore(const QVariantMap &data) const
GdbServerProvider *OpenOcdGdbServerProviderFactory::restore(const QVariantMap &data)
{
- auto p = new OpenOcdGdbServerProvider;
- auto updated = data;
+ const auto p = new OpenOcdGdbServerProvider;
+ const auto updated = data;
if (p->fromMap(updated))
return p;
delete p;
return nullptr;
}
+// OpenOcdGdbServerProviderConfigWidget
+
OpenOcdGdbServerProviderConfigWidget::OpenOcdGdbServerProviderConfigWidget(
OpenOcdGdbServerProvider *p)
: GdbServerProviderConfigWidget(p)
@@ -276,7 +275,7 @@ OpenOcdGdbServerProviderConfigWidget::OpenOcdGdbServerProviderConfigWidget(
addErrorLabel();
setFromProvider();
- auto chooser = new Core::VariableChooser(this);
+ const auto chooser = new Core::VariableChooser(this);
chooser->addSupportedWidget(m_initCommandsTextEdit);
chooser->addSupportedWidget(m_resetCommandsTextEdit);
@@ -295,7 +294,7 @@ OpenOcdGdbServerProviderConfigWidget::OpenOcdGdbServerProviderConfigWidget(
connect(m_resetCommandsTextEdit, &QPlainTextEdit::textChanged,
this, &GdbServerProviderConfigWidget::dirty);
- connect(m_startupModeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_startupModeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &OpenOcdGdbServerProviderConfigWidget::startupModeChanged);
}
@@ -318,12 +317,12 @@ void OpenOcdGdbServerProviderConfigWidget::startupModeChanged()
void OpenOcdGdbServerProviderConfigWidget::applyImpl()
{
- auto p = static_cast<OpenOcdGdbServerProvider *>(provider());
+ const auto p = static_cast<OpenOcdGdbServerProvider *>(provider());
Q_ASSERT(p);
p->m_host = m_hostWidget->host();
p->m_port = m_hostWidget->port();
- p->m_executableFile = m_executableFileChooser->fileName().toString();
+ p->m_executableFile = m_executableFileChooser->fileName();
p->m_rootScriptsDir = m_rootScriptsDirChooser->fileName().toString();
p->m_configurationFile = m_configurationFileChooser->fileName().toString();
p->m_additionalArguments = m_additionalArgumentsLineEdit->text();
@@ -341,13 +340,13 @@ void OpenOcdGdbServerProviderConfigWidget::setFromProvider()
const auto p = static_cast<OpenOcdGdbServerProvider *>(provider());
Q_ASSERT(p);
- QSignalBlocker blocker(this);
+ const QSignalBlocker blocker(this);
startupModeChanged();
m_hostWidget->setHost(p->m_host);
m_hostWidget->setPort(p->m_port);
- m_executableFileChooser->setFileName(Utils::FileName::fromString(p->m_executableFile));
- m_rootScriptsDirChooser->setFileName(Utils::FileName::fromString(p->m_rootScriptsDir));
- m_configurationFileChooser->setFileName(Utils::FileName::fromString(p->m_configurationFile));
+ m_executableFileChooser->setFileName(p->m_executableFile);
+ m_rootScriptsDirChooser->setFileName(Utils::FilePath::fromString(p->m_rootScriptsDir));
+ m_configurationFileChooser->setFileName(Utils::FilePath::fromString(p->m_configurationFile));
m_additionalArgumentsLineEdit->setText(p->m_additionalArguments);
m_initCommandsTextEdit->setPlainText(p->initCommands());
m_resetCommandsTextEdit->setPlainText(p->resetCommands());
diff --git a/src/plugins/baremetal/openocdgdbserverprovider.h b/src/plugins/baremetal/openocdgdbserverprovider.h
index 94481775ed..229b12bf61 100644
--- a/src/plugins/baremetal/openocdgdbserverprovider.h
+++ b/src/plugins/baremetal/openocdgdbserverprovider.h
@@ -35,7 +35,9 @@ namespace Internal {
class OpenOcdGdbServerProviderConfigWidget;
class OpenOcdGdbServerProviderFactory;
-class OpenOcdGdbServerProvider : public GdbServerProvider
+// OpenOcdGdbServerProvider
+
+class OpenOcdGdbServerProvider final : public GdbServerProvider
{
public:
QString typeDisplayName() const final;
@@ -49,8 +51,7 @@ public:
GdbServerProvider *clone() const final;
QString channel() const final;
- QString executable() const final;
- QStringList arguments() const final;
+ Utils::CommandLine command() const final;
bool canStartupMode(StartupMode mode) const final;
bool isValid() const final;
@@ -62,9 +63,9 @@ private:
static QString defaultInitCommands();
static QString defaultResetCommands();
- QString m_host;
- quint16 m_port;
- QString m_executableFile;
+ QString m_host = QLatin1String("localhost");
+ quint16 m_port = 3333;
+ Utils::FilePath m_executableFile = Utils::FilePath::fromString("openocd");
QString m_rootScriptsDir;
QString m_configurationFile;
QString m_additionalArguments;
@@ -73,7 +74,9 @@ private:
friend class OpenOcdGdbServerProviderFactory;
};
-class OpenOcdGdbServerProviderFactory : public GdbServerProviderFactory
+// OpenOcdGdbServerProviderFactory
+
+class OpenOcdGdbServerProviderFactory final : public GdbServerProviderFactory
{
Q_OBJECT
@@ -88,7 +91,9 @@ public:
GdbServerProviderConfigWidget *configurationWidget(GdbServerProvider *);
};
-class OpenOcdGdbServerProviderConfigWidget : public GdbServerProviderConfigWidget
+// OpenOcdGdbServerProviderConfigWidget
+
+class OpenOcdGdbServerProviderConfigWidget final : public GdbServerProviderConfigWidget
{
Q_OBJECT
@@ -103,13 +108,13 @@ private:
void setFromProvider();
- HostWidget *m_hostWidget;
- Utils::PathChooser *m_executableFileChooser;
- Utils::PathChooser *m_rootScriptsDirChooser;
- Utils::PathChooser *m_configurationFileChooser;
- QLineEdit *m_additionalArgumentsLineEdit;
- QPlainTextEdit *m_initCommandsTextEdit;
- QPlainTextEdit *m_resetCommandsTextEdit;
+ HostWidget *m_hostWidget = nullptr;
+ Utils::PathChooser *m_executableFileChooser = nullptr;
+ Utils::PathChooser *m_rootScriptsDirChooser = nullptr;
+ Utils::PathChooser *m_configurationFileChooser = nullptr;
+ QLineEdit *m_additionalArgumentsLineEdit = nullptr;
+ QPlainTextEdit *m_initCommandsTextEdit = nullptr;
+ QPlainTextEdit *m_resetCommandsTextEdit = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/baremetal/sdccparser.cpp b/src/plugins/baremetal/sdccparser.cpp
new file mode 100644
index 0000000000..e84021dd7b
--- /dev/null
+++ b/src/plugins/baremetal/sdccparser.cpp
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sdccparser.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/task.h>
+
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorsettings.h>
+
+#include <QRegularExpression>
+
+using namespace ProjectExplorer;
+
+namespace BareMetal {
+namespace Internal {
+
+// Helpers:
+
+static Task::TaskType taskType(const QString &msgType)
+{
+ if (msgType == "warning" || msgType == "Warning") {
+ return Task::TaskType::Warning;
+ } else if (msgType == "error" || msgType == "Error"
+ || msgType == "syntax error") {
+ return Task::TaskType::Error;
+ }
+ return Task::TaskType::Unknown;
+}
+
+// SdccParser
+
+SdccParser::SdccParser()
+{
+ setObjectName("SdccParser");
+}
+
+Core::Id SdccParser::id()
+{
+ return "BareMetal.OutputParser.Sdcc";
+}
+
+void SdccParser::newTask(const Task &task)
+{
+ doFlush();
+ m_lastTask = task;
+ m_lines = 1;
+}
+
+void SdccParser::amendDescription(const QString &desc)
+{
+ const int start = m_lastTask.description.count() + 1;
+ m_lastTask.description.append(QLatin1Char('\n'));
+ m_lastTask.description.append(desc);
+
+ QTextLayout::FormatRange fr;
+ fr.start = start;
+ fr.length = m_lastTask.description.count() + 1;
+ fr.format.setFont(TextEditor::TextEditorSettings::fontSettings().font());
+ fr.format.setFontStyleHint(QFont::Monospace);
+ m_lastTask.formats.append(fr);
+
+ ++m_lines;
+}
+
+void SdccParser::stdError(const QString &line)
+{
+ IOutputParser::stdError(line);
+
+ const QString lne = rightTrimmed(line);
+
+ QRegularExpression re;
+ QRegularExpressionMatch match;
+
+ re.setPattern("^(.+\\.\\S+):(\\d+): (warning|error) (\\d+): (.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
+ MessageTypeIndex, MessageCodeIndex, MessageTextIndex };
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
+ match.captured(FilePathIndex));
+ const int lineno = match.captured(LineNumberIndex).toInt();
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = match.captured(MessageTextIndex);
+ const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ re.setPattern("^(.+\\.\\S+):(\\d+): (syntax error): (.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
+ MessageTypeIndex, MessageTextIndex };
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
+ match.captured(FilePathIndex));
+ const int lineno = match.captured(LineNumberIndex).toInt();
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = match.captured(MessageTextIndex);
+ const Task task(type, descr, fileName, lineno, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ re.setPattern("^at (\\d+): (error) \\d+: (.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageCodeIndex = 1, MessageTypeIndex, MessageTextIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = match.captured(MessageTextIndex);
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ re.setPattern("^\\?ASlink-(Warning|Error)-(.+)$");
+ match = re.match(lne);
+ if (match.hasMatch()) {
+ enum CaptureIndex { MessageTypeIndex = 1, MessageTextIndex };
+ const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
+ const QString descr = match.captured(MessageTextIndex);
+ const Task task(type, descr, {}, -1, Constants::TASK_CATEGORY_COMPILE);
+ newTask(task);
+ return;
+ }
+
+ if (!m_lastTask.isNull()) {
+ amendDescription(lne);
+ return;
+ }
+
+ doFlush();
+}
+
+void SdccParser::stdOutput(const QString &line)
+{
+ IOutputParser::stdOutput(line);
+}
+
+void SdccParser::doFlush()
+{
+ if (m_lastTask.isNull())
+ return;
+
+ Task t = m_lastTask;
+ m_lastTask.clear();
+ emit addTask(t, m_lines, 1);
+ m_lines = 0;
+}
+
+} // namespace Internal
+} // namespace BareMetal
+
+// Unit tests:
+
+#ifdef WITH_TESTS
+#include "baremetalplugin.h"
+#include <projectexplorer/outputparser_test.h>
+#include <QTest>
+
+namespace BareMetal {
+namespace Internal {
+
+void BareMetalPlugin::testSdccOutputParsers_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<OutputParserTester::Channel>("inputChannel");
+ QTest::addColumn<QString>("childStdOutLines");
+ QTest::addColumn<QString>("childStdErrLines");
+ QTest::addColumn<Tasks >("tasks");
+ QTest::addColumn<QString>("outputLines");
+
+ QTest::newRow("pass-through stdout")
+ << "Sometext" << OutputParserTester::STDOUT
+ << "Sometext\n" << QString()
+ << Tasks()
+ << QString();
+ QTest::newRow("pass-through stderr")
+ << "Sometext" << OutputParserTester::STDERR
+ << QString() << "Sometext\n"
+ << Tasks()
+ << QString();
+
+ const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
+
+ // Compiler messages.
+
+ QTest::newRow("Compiler single line warning")
+ << QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("Some warning"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Compiler multi line warning")
+ << QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning\n"
+ "details #1\n"
+ " details #2")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning\n"
+ "details #1\n"
+ " details #2\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("Some warning\n"
+ "details #1\n"
+ " details #2"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Compiler single line error")
+ << QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Compiler multi line error")
+ << QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error\n"
+ "details #1\n"
+ " details #2")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error\n"
+ "details #1\n"
+ " details #2\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("Some error\n"
+ "details #1\n"
+ " details #2"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Compiler syntax error")
+ << QString::fromLatin1("c:\\foo\\main.c:63: syntax error: Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("c:\\foo\\main.c:63: syntax error: Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("Some error"),
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\foo\\main.c")),
+ 63,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Compiler bad option error")
+ << QString::fromLatin1("at 1: error 123: Some error")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("at 1: error 123: Some error\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("Some error"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Linker warning")
+ << QString::fromLatin1("?ASlink-Warning-Couldn't find library 'foo.lib'")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("?ASlink-Warning-Couldn't find library 'foo.lib'\n")
+ << (Tasks() << Task(Task::Warning,
+ QLatin1String("Couldn't find library 'foo.lib'"),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+
+ QTest::newRow("Linker error")
+ << QString::fromLatin1("?ASlink-Error-<cannot open> : \"foo.rel\"")
+ << OutputParserTester::STDERR
+ << QString()
+ << QString::fromLatin1("?ASlink-Error-<cannot open> : \"foo.rel\"\n")
+ << (Tasks() << Task(Task::Error,
+ QLatin1String("<cannot open> : \"foo.rel\""),
+ Utils::FilePath(),
+ -1,
+ categoryCompile))
+ << QString();
+}
+
+void BareMetalPlugin::testSdccOutputParsers()
+{
+ OutputParserTester testbench;
+ testbench.appendOutputParser(new SdccParser);
+ QFETCH(QString, input);
+ QFETCH(OutputParserTester::Channel, inputChannel);
+ QFETCH(Tasks, tasks);
+ QFETCH(QString, childStdOutLines);
+ QFETCH(QString, childStdErrLines);
+ QFETCH(QString, outputLines);
+
+ testbench.testParsing(input, inputChannel,
+ tasks, childStdOutLines, childStdErrLines,
+ outputLines);
+}
+
+} // namespace Internal
+} // namespace BareMetal
+
+#endif // WITH_TESTS
diff --git a/src/plugins/baremetal/sdccparser.h b/src/plugins/baremetal/sdccparser.h
new file mode 100644
index 0000000000..fb7866c879
--- /dev/null
+++ b/src/plugins/baremetal/sdccparser.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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/ioutputparser.h>
+#include <projectexplorer/task.h>
+
+namespace BareMetal {
+namespace Internal {
+
+// SdccParser
+
+class SdccParser final : public ProjectExplorer::IOutputParser
+{
+ Q_OBJECT
+
+public:
+ explicit SdccParser();
+ static Core::Id id();
+
+private:
+ void newTask(const ProjectExplorer::Task &task);
+ void amendDescription(const QString &desc);
+
+ void stdError(const QString &line) final;
+ void stdOutput(const QString &line) final;
+ void doFlush() final;
+
+ ProjectExplorer::Task m_lastTask;
+ int m_lines = 0;
+};
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/sdcctoolchain.cpp b/src/plugins/baremetal/sdcctoolchain.cpp
new file mode 100644
index 0000000000..b839a68fe8
--- /dev/null
+++ b/src/plugins/baremetal/sdcctoolchain.cpp
@@ -0,0 +1,564 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "baremetalconstants.h"
+
+#include "sdccparser.h"
+#include "sdcctoolchain.h"
+
+#include <projectexplorer/abiwidget.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/projectmacro.h>
+#include <projectexplorer/toolchainmanager.h>
+
+#include <utils/algorithm.h>
+#include <utils/environment.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+#include <utils/synchronousprocess.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QFormLayout>
+#include <QLineEdit>
+#include <QPlainTextEdit>
+#include <QSettings>
+#include <QTemporaryFile>
+#include <QTextStream>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace BareMetal {
+namespace Internal {
+
+// Helpers:
+
+static const char compilerCommandKeyC[] = "BareMetal.SdccToolChain.CompilerPath";
+static const char targetAbiKeyC[] = "BareMetal.SdccToolChain.TargetAbi";
+
+static bool compilerExists(const FilePath &compilerPath)
+{
+ const QFileInfo fi = compilerPath.toFileInfo();
+ return fi.exists() && fi.isExecutable() && fi.isFile();
+}
+
+static QString compilerTargetFlag(const Abi &abi)
+{
+ switch (abi.architecture()) {
+ case Abi::Architecture::Mcs51Architecture:
+ return QString("-mmcs51");
+ default:
+ return {};
+ }
+}
+
+static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &env,
+ const Abi &abi)
+{
+ if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable())
+ return {};
+
+ QTemporaryFile fakeIn("XXXXXX.c");
+ if (!fakeIn.open())
+ return {};
+ fakeIn.close();
+
+ SynchronousProcess cpp;
+ cpp.setEnvironment(env);
+ cpp.setTimeoutS(10);
+
+ QStringList arguments;
+ arguments.push_back(compilerTargetFlag(abi));
+ arguments.push_back("-dM");
+ arguments.push_back("-E");
+ arguments.push_back(fakeIn.fileName());
+
+ const SynchronousProcessResponse response = cpp.runBlocking(compiler.toString(), arguments);
+ if (response.result != SynchronousProcessResponse::Finished
+ || response.exitCode != 0) {
+ qWarning() << response.exitMessage(compiler.toString(), 10);
+ return {};
+ }
+
+ const QByteArray output = response.allOutput().toUtf8();
+ return Macro::toMacros(output);
+}
+
+static HeaderPaths dumpHeaderPaths(const FilePath &compiler, const QStringList &env,
+ const Abi &abi)
+{
+ if (!compiler.exists())
+ return {};
+
+ SynchronousProcess cpp;
+ cpp.setEnvironment(env);
+ cpp.setTimeoutS(10);
+
+ QStringList arguments;
+ arguments.push_back(compilerTargetFlag(abi));
+ arguments.push_back("--print-search-dirs");
+
+ const SynchronousProcessResponse response = cpp.runBlocking(compiler.toString(), arguments);
+ if (response.result != SynchronousProcessResponse::Finished
+ || response.exitCode != 0) {
+ qWarning() << response.exitMessage(compiler.toString(), 10);
+ return {};
+ }
+
+ QString output = response.allOutput();
+ HeaderPaths headerPaths;
+ QTextStream in(&output);
+ QString line;
+ bool synchronized = false;
+ while (in.readLineInto(&line)) {
+ if (!synchronized) {
+ if (line.startsWith("includedir:"))
+ synchronized = true;
+ } else {
+ if (line.startsWith("programs:") || line.startsWith("datadir:")
+ || line.startsWith("libdir:") || line.startsWith("libpath:")) {
+ break;
+ } else {
+ const QString headerPath = QFileInfo(line.trimmed())
+ .canonicalFilePath();
+ headerPaths.append({headerPath, HeaderPathType::BuiltIn});
+ }
+ }
+ }
+ return headerPaths;
+}
+
+static QString findMacroValue(const Macros &macros, const QByteArray &key)
+{
+ for (const Macro &macro : macros) {
+ if (macro.key == key)
+ return QString::fromLocal8Bit(macro.value);
+ }
+ return {};
+}
+
+static QString guessVersion(const Macros &macros)
+{
+ const QString major = findMacroValue(macros, "__SDCC_VERSION_MAJOR");
+ const QString minor = findMacroValue(macros, "__SDCC_VERSION_MINOR");
+ const QString patch = findMacroValue(macros, "__SDCC_VERSION_PATCH");
+ return QString("%1.%2.%3").arg(major, minor, patch);
+}
+
+static Abi::Architecture guessArchitecture(const Macros &macros)
+{
+ for (const Macro &macro : macros) {
+ if (macro.key == "__SDCC_mcs51")
+ return Abi::Architecture::Mcs51Architecture;
+ }
+ return Abi::Architecture::UnknownArchitecture;
+}
+
+static unsigned char guessWordWidth(const Macros &macros)
+{
+ Q_UNUSED(macros)
+ // SDCC always have 16-bit word width.
+ return 16;
+}
+
+static Abi::BinaryFormat guessFormat(Abi::Architecture arch)
+{
+ Q_UNUSED(arch)
+ return Abi::BinaryFormat::UnknownFormat;
+}
+
+static Abi guessAbi(const Macros &macros)
+{
+ const auto arch = guessArchitecture(macros);
+ return {arch, Abi::OS::BareMetalOS, Abi::OSFlavor::GenericFlavor,
+ guessFormat(arch), guessWordWidth(macros)};
+}
+
+static QString buildDisplayName(Abi::Architecture arch, Core::Id language,
+ const QString &version)
+{
+ const auto archName = Abi::toString(arch);
+ const auto langName = ToolChainManager::displayNameOfLanguageId(language);
+ return SdccToolChain::tr("SDCC %1 (%2, %3)")
+ .arg(version, langName, archName);
+}
+
+static Utils::FilePath compilerPathFromEnvironment(const QString &compilerName)
+{
+ const Environment systemEnvironment = Environment::systemEnvironment();
+ return systemEnvironment.searchInPath(compilerName);
+}
+
+// SdccToolChain
+
+SdccToolChain::SdccToolChain() :
+ ToolChain(Constants::SDCC_TOOLCHAIN_TYPEID)
+{ }
+
+QString SdccToolChain::typeDisplayName() const
+{
+ return Internal::SdccToolChainFactory::tr("SDCC");
+}
+
+void SdccToolChain::setTargetAbi(const Abi &abi)
+{
+ if (abi == m_targetAbi)
+ return;
+ m_targetAbi = abi;
+ toolChainUpdated();
+}
+
+Abi SdccToolChain::targetAbi() const
+{
+ return m_targetAbi;
+}
+
+bool SdccToolChain::isValid() const
+{
+ return true;
+}
+
+ToolChain::MacroInspectionRunner SdccToolChain::createMacroInspectionRunner() const
+{
+ Environment env = Environment::systemEnvironment();
+ addToEnvironment(env);
+
+ const Utils::FilePath compilerCommand = m_compilerCommand;
+ const Core::Id lang = language();
+ const Abi abi = m_targetAbi;
+
+ MacrosCache macrosCache = predefinedMacrosCache();
+
+ return [env, compilerCommand, macrosCache, lang, abi]
+ (const QStringList &flags) {
+ Q_UNUSED(flags)
+
+ const Macros macros = dumpPredefinedMacros(compilerCommand, env.toStringList(),
+ abi);
+ const auto report = MacroInspectionReport{macros, languageVersion(lang, macros)};
+ macrosCache->insert({}, report);
+
+ return report;
+ };
+}
+
+Macros SdccToolChain::predefinedMacros(const QStringList &cxxflags) const
+{
+ return createMacroInspectionRunner()(cxxflags).macros;
+}
+
+Utils::LanguageExtensions SdccToolChain::languageExtensions(const QStringList &) const
+{
+ return LanguageExtension::None;
+}
+
+WarningFlags SdccToolChain::warningFlags(const QStringList &cxxflags) const
+{
+ Q_UNUSED(cxxflags);
+ return WarningFlags::Default;
+}
+
+ToolChain::BuiltInHeaderPathsRunner SdccToolChain::createBuiltInHeaderPathsRunner() const
+{
+ Environment env = Environment::systemEnvironment();
+ addToEnvironment(env);
+
+ const Utils::FilePath compilerCommand = m_compilerCommand;
+ const Core::Id languageId = language();
+ const Abi abi = m_targetAbi;
+
+ HeaderPathsCache headerPaths = headerPathsCache();
+
+ return [env, compilerCommand, headerPaths, languageId, abi](const QStringList &flags,
+ const QString &fileName,
+ const QString &) {
+ Q_UNUSED(flags)
+ Q_UNUSED(fileName)
+
+ const HeaderPaths paths = dumpHeaderPaths(compilerCommand, env.toStringList(), abi);
+ headerPaths->insert({}, paths);
+
+ return paths;
+ };
+}
+
+HeaderPaths SdccToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
+ const FilePath &fileName) const
+{
+ return createBuiltInHeaderPathsRunner()(cxxFlags, fileName.toString(), "");
+}
+
+void SdccToolChain::addToEnvironment(Environment &env) const
+{
+ if (!m_compilerCommand.isEmpty()) {
+ const FilePath path = m_compilerCommand.parentDir();
+ env.prependOrSetPath(path.toString());
+ }
+}
+
+IOutputParser *SdccToolChain::outputParser() const
+{
+ return new SdccParser;
+}
+
+QVariantMap SdccToolChain::toMap() const
+{
+ QVariantMap data = ToolChain::toMap();
+ data.insert(compilerCommandKeyC, m_compilerCommand.toString());
+ data.insert(targetAbiKeyC, m_targetAbi.toString());
+ return data;
+}
+
+bool SdccToolChain::fromMap(const QVariantMap &data)
+{
+ if (!ToolChain::fromMap(data))
+ return false;
+ m_compilerCommand = FilePath::fromString(data.value(compilerCommandKeyC).toString());
+ m_targetAbi = Abi::fromString(data.value(targetAbiKeyC).toString());
+ return true;
+}
+
+std::unique_ptr<ToolChainConfigWidget> SdccToolChain::createConfigurationWidget()
+{
+ return std::make_unique<SdccToolChainConfigWidget>(this);
+}
+
+bool SdccToolChain::operator==(const ToolChain &other) const
+{
+ if (!ToolChain::operator==(other))
+ return false;
+
+ const auto customTc = static_cast<const SdccToolChain *>(&other);
+ return m_compilerCommand == customTc->m_compilerCommand
+ && m_targetAbi == customTc->m_targetAbi
+ ;
+}
+
+void SdccToolChain::setCompilerCommand(const FilePath &file)
+{
+ if (file == m_compilerCommand)
+ return;
+ m_compilerCommand = file;
+ toolChainUpdated();
+}
+
+FilePath SdccToolChain::compilerCommand() const
+{
+ return m_compilerCommand;
+}
+
+FilePath SdccToolChain::makeCommand(const Environment &env) const
+{
+ Q_UNUSED(env)
+ return {};
+}
+
+// SdccToolChainFactory
+
+SdccToolChainFactory::SdccToolChainFactory()
+{
+ setDisplayName(tr("SDCC"));
+ setSupportedToolChainType(Constants::SDCC_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID});
+ setToolchainConstructor([] { return new SdccToolChain; });
+ setUserCreatable(true);
+}
+
+QList<ToolChain *> SdccToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
+{
+ Candidates candidates;
+
+ if (Utils::HostOsInfo::isWindowsHost()) {
+
+#ifdef Q_OS_WIN64
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\SDCC";
+#else
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\SDCC";
+#endif
+
+ QSettings registry(kRegistryNode, QSettings::NativeFormat);
+ QString compilerPath = registry.value("Default").toString();
+ if (!compilerPath.isEmpty()) {
+ // Build full compiler path.
+ compilerPath += "\\bin\\sdcc.exe";
+ const FilePath fn = FilePath::fromString(
+ QFileInfo(compilerPath).absoluteFilePath());
+ if (compilerExists(fn)) {
+ // Build compiler version.
+ const QString version = QString("%1.%2.%3").arg(
+ registry.value("VersionMajor").toString(),
+ registry.value("VersionMinor").toString(),
+ registry.value("VersionRevision").toString());
+ candidates.push_back({fn, version});
+ }
+ }
+ }
+
+ const FilePath fn = compilerPathFromEnvironment("sdcc");
+ if (fn.exists()) {
+ const auto env = Environment::systemEnvironment();
+ const auto macros = dumpPredefinedMacros(fn, env.toStringList(), {});
+ const QString version = guessVersion(macros);
+ const Candidate candidate = {fn, version};
+ if (!candidates.contains(candidate))
+ candidates.push_back(candidate);
+ }
+
+ return autoDetectToolchains(candidates, alreadyKnown);
+}
+
+QList<ToolChain *> SdccToolChainFactory::autoDetectToolchains(
+ const Candidates &candidates, const QList<ToolChain *> &alreadyKnown) const
+{
+ QList<ToolChain *> result;
+
+ for (const Candidate &candidate : qAsConst(candidates)) {
+ const QList<ToolChain *> filtered = Utils::filtered(
+ alreadyKnown, [candidate](ToolChain *tc) {
+ return tc->typeId() == Constants::SDCC_TOOLCHAIN_TYPEID
+ && tc->compilerCommand() == candidate.compilerPath
+ && (tc->language() == ProjectExplorer::Constants::C_LANGUAGE_ID);
+ });
+
+ if (!filtered.isEmpty()) {
+ result << filtered;
+ continue;
+ }
+
+ // Create toolchain only for C language (because SDCC does not support C++).
+ result << autoDetectToolchain(candidate, ProjectExplorer::Constants::C_LANGUAGE_ID);
+ }
+
+ return result;
+}
+
+QList<ToolChain *> SdccToolChainFactory::autoDetectToolchain(
+ const Candidate &candidate, Core::Id language) const
+{
+ const auto env = Environment::systemEnvironment();
+ const Macros macros = dumpPredefinedMacros(candidate.compilerPath, env.toStringList(), {});
+ if (macros.isEmpty())
+ return {};
+ const Abi abi = guessAbi(macros);
+
+ const auto tc = new SdccToolChain;
+ tc->setDetection(ToolChain::AutoDetection);
+ tc->setLanguage(language);
+ tc->setCompilerCommand(candidate.compilerPath);
+ tc->setTargetAbi(abi);
+ tc->setDisplayName(buildDisplayName(abi.architecture(), language, candidate.compilerVersion));
+
+ const auto languageVersion = ToolChain::languageVersion(language, macros);
+ tc->predefinedMacrosCache()->insert({}, {macros, languageVersion});
+ return {tc};
+}
+
+// SdccToolChainConfigWidget
+
+SdccToolChainConfigWidget::SdccToolChainConfigWidget(SdccToolChain *tc) :
+ ToolChainConfigWidget(tc),
+ m_compilerCommand(new PathChooser),
+ m_abiWidget(new AbiWidget)
+{
+ m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
+ m_compilerCommand->setHistoryCompleter("PE.SDCC.Command.History");
+ m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
+ m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
+
+ m_abiWidget->setEnabled(false);
+
+ addErrorLabel();
+ setFromToolchain();
+
+ connect(m_compilerCommand, &PathChooser::rawPathChanged,
+ this, &SdccToolChainConfigWidget::handleCompilerCommandChange);
+ connect(m_abiWidget, &AbiWidget::abiChanged,
+ this, &ToolChainConfigWidget::dirty);
+}
+
+void SdccToolChainConfigWidget::applyImpl()
+{
+ if (toolChain()->isAutoDetected())
+ return;
+
+ const auto tc = static_cast<SdccToolChain *>(toolChain());
+ const QString displayName = tc->displayName();
+ tc->setCompilerCommand(m_compilerCommand->fileName());
+ tc->setTargetAbi(m_abiWidget->currentAbi());
+ tc->setDisplayName(displayName);
+
+ if (m_macros.isEmpty())
+ return;
+
+ const auto languageVersion = ToolChain::languageVersion(tc->language(), m_macros);
+ tc->predefinedMacrosCache()->insert({}, {m_macros, languageVersion});
+
+ setFromToolchain();
+}
+
+bool SdccToolChainConfigWidget::isDirtyImpl() const
+{
+ const auto tc = static_cast<SdccToolChain *>(toolChain());
+ return m_compilerCommand->fileName() != tc->compilerCommand()
+ || m_abiWidget->currentAbi() != tc->targetAbi()
+ ;
+}
+
+void SdccToolChainConfigWidget::makeReadOnlyImpl()
+{
+ m_compilerCommand->setReadOnly(true);
+ m_abiWidget->setEnabled(false);
+}
+
+void SdccToolChainConfigWidget::setFromToolchain()
+{
+ const QSignalBlocker blocker(this);
+ const auto tc = static_cast<SdccToolChain *>(toolChain());
+ m_compilerCommand->setFileName(tc->compilerCommand());
+ m_abiWidget->setAbis({}, tc->targetAbi());
+ const bool haveCompiler = compilerExists(m_compilerCommand->fileName());
+ m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected());
+}
+
+void SdccToolChainConfigWidget::handleCompilerCommandChange()
+{
+ const FilePath compilerPath = m_compilerCommand->fileName();
+ const bool haveCompiler = compilerExists(compilerPath);
+ if (haveCompiler) {
+ const auto env = Environment::systemEnvironment();
+ m_macros = dumpPredefinedMacros(compilerPath, env.toStringList(), {});
+ const Abi guessed = guessAbi(m_macros);
+ m_abiWidget->setAbis({}, guessed);
+ }
+
+ m_abiWidget->setEnabled(haveCompiler);
+ emit dirty();
+}
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/sdcctoolchain.h b/src/plugins/baremetal/sdcctoolchain.h
new file mode 100644
index 0000000000..15ed599524
--- /dev/null
+++ b/src/plugins/baremetal/sdcctoolchain.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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/abi.h>
+#include <projectexplorer/toolchain.h>
+#include <projectexplorer/toolchainconfigwidget.h>
+
+QT_BEGIN_NAMESPACE
+class QPlainTextEdit;
+class QPushButton;
+class QTextEdit;
+QT_END_NAMESPACE
+
+namespace Utils {
+class FilePath;
+class PathChooser;
+}
+
+namespace ProjectExplorer { class AbiWidget; }
+
+namespace BareMetal {
+namespace Internal {
+
+// SdccToolChain
+
+class SdccToolChain final : public ProjectExplorer::ToolChain
+{
+ Q_DECLARE_TR_FUNCTIONS(SdccToolChain)
+
+public:
+ QString typeDisplayName() const final;
+
+ void setTargetAbi(const ProjectExplorer::Abi &abi);
+ ProjectExplorer::Abi targetAbi() const final;
+
+ bool isValid() const final;
+
+ MacroInspectionRunner createMacroInspectionRunner() const final;
+ ProjectExplorer::Macros predefinedMacros(const QStringList &cxxflags) const final;
+
+ Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const final;
+ ProjectExplorer::WarningFlags warningFlags(const QStringList &cxxflags) const final;
+
+ BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const final;
+ ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
+ const Utils::FilePath &) const final;
+ void addToEnvironment(Utils::Environment &env) const final;
+ ProjectExplorer::IOutputParser *outputParser() const final;
+
+ QVariantMap toMap() const final;
+ bool fromMap(const QVariantMap &data) final;
+
+ std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() final;
+
+ bool operator ==(const ToolChain &other) const final;
+
+ void setCompilerCommand(const Utils::FilePath &file);
+ Utils::FilePath compilerCommand() const final;
+
+ Utils::FilePath makeCommand(const Utils::Environment &env) const final;
+
+private:
+ SdccToolChain();
+
+ ProjectExplorer::Abi m_targetAbi;
+ Utils::FilePath m_compilerCommand;
+
+ friend class SdccToolChainFactory;
+ friend class SdccToolChainConfigWidget;
+};
+
+// SdccToolChainFactory
+
+class SdccToolChainFactory final : public ProjectExplorer::ToolChainFactory
+{
+ Q_OBJECT
+
+public:
+ SdccToolChainFactory();
+
+ QList<ProjectExplorer::ToolChain *> autoDetect(
+ const QList<ProjectExplorer::ToolChain *> &alreadyKnown) final;
+
+private:
+ QList<ProjectExplorer::ToolChain *> autoDetectToolchains(const Candidates &candidates,
+ const QList<ProjectExplorer::ToolChain *> &alreadyKnown) const;
+ QList<ProjectExplorer::ToolChain *> autoDetectToolchain(
+ const Candidate &candidate, Core::Id language) const;
+};
+
+// SdccToolChainConfigWidget
+
+class SdccToolChainConfigWidget final : public ProjectExplorer::ToolChainConfigWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SdccToolChainConfigWidget(SdccToolChain *tc);
+
+private:
+ void applyImpl() final;
+ void discardImpl() final { setFromToolchain(); }
+ bool isDirtyImpl() const final;
+ void makeReadOnlyImpl() final;
+
+ void setFromToolchain();
+ void handleCompilerCommandChange();
+
+ Utils::PathChooser *m_compilerCommand = nullptr;
+ ProjectExplorer::AbiWidget *m_abiWidget = nullptr;
+ ProjectExplorer::Macros m_macros;
+};
+
+} // namespace Internal
+} // namespace BareMetal
diff --git a/src/plugins/baremetal/stlinkutilgdbserverprovider.cpp b/src/plugins/baremetal/stlinkutilgdbserverprovider.cpp
index 146f826e26..552f890c80 100644
--- a/src/plugins/baremetal/stlinkutilgdbserverprovider.cpp
+++ b/src/plugins/baremetal/stlinkutilgdbserverprovider.cpp
@@ -23,25 +23,26 @@
**
****************************************************************************/
-#include "stlinkutilgdbserverprovider.h"
#include "baremetalconstants.h"
+
#include "gdbserverprovidermanager.h"
+#include "stlinkutilgdbserverprovider.h"
+#include <utils/fileutils.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
-#include <utils/fileutils.h>
#include <coreplugin/variablechooser.h>
-#include <QString>
+#include <QCheckBox>
+#include <QComboBox>
#include <QFileInfo>
-
#include <QFormLayout>
#include <QLineEdit>
-#include <QComboBox>
-#include <QSpinBox>
-#include <QCheckBox>
#include <QPlainTextEdit>
+#include <QSpinBox>
+
+using namespace Utils;
namespace BareMetal {
namespace Internal {
@@ -54,15 +55,10 @@ const char extendedModeKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.ExtendedM
const char resetBoardKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.ResetBoard";
const char transportLayerKeyC[] = "BareMetal.StLinkUtilGdbServerProvider.TransportLayer";
+// StLinkUtilGdbServerProvider
+
StLinkUtilGdbServerProvider::StLinkUtilGdbServerProvider()
: GdbServerProvider(QLatin1String(Constants::STLINK_UTIL_PROVIDER_ID))
- , m_host(QLatin1String("localhost"))
- , m_port(4242)
- , m_executableFile(QLatin1String("st-util"))
- , m_verboseLevel(0)
- , m_extendedMode(false)
- , m_resetBoard(true)
- , m_transport(RawUsb)
{
setInitCommands(defaultInitCommands());
setResetCommands(defaultResetCommands());
@@ -88,7 +84,7 @@ QString StLinkUtilGdbServerProvider::defaultInitCommands()
QString StLinkUtilGdbServerProvider::defaultResetCommands()
{
- return QLatin1String("");
+ return {};
}
QString StLinkUtilGdbServerProvider::typeDisplayName() const
@@ -106,32 +102,27 @@ QString StLinkUtilGdbServerProvider::channel() const
return m_host + QLatin1Char(':') + QString::number(m_port);
case StartupOnPipe:
// Unsupported mode
- return QString();
+ return {};
default: // wrong
- return QString();
+ return {};
}
}
-QString StLinkUtilGdbServerProvider::executable() const
-{
- return m_executableFile;
-}
-
-QStringList StLinkUtilGdbServerProvider::arguments() const
+CommandLine StLinkUtilGdbServerProvider::command() const
{
- QStringList args;
+ CommandLine cmd{m_executableFile, {}};
if (m_extendedMode)
- args << QLatin1String("--multi");
+ cmd.addArg("--multi");
if (!m_resetBoard)
- args << QLatin1String("--no-reset");
+ cmd.addArg("--no-reset");
- args << (QLatin1String("--stlink_version=") + QString::number(m_transport));
- args << (QLatin1String("--listen_port=") + QString::number(m_port));
- args << (QLatin1String("--verbose=") + QString::number(m_verboseLevel));
+ cmd.addArg("--stlink_version=" + QString::number(m_transport));
+ cmd.addArg("--listen_port=" + QString::number(m_port));
+ cmd.addArg("--verbose=" + QString::number(m_verboseLevel));
- return args;
+ return cmd;
}
bool StLinkUtilGdbServerProvider::canStartupMode(StartupMode m) const
@@ -169,7 +160,7 @@ QVariantMap StLinkUtilGdbServerProvider::toMap() const
QVariantMap data = GdbServerProvider::toMap();
data.insert(QLatin1String(hostKeyC), m_host);
data.insert(QLatin1String(portKeyC), m_port);
- data.insert(QLatin1String(executableFileKeyC), m_executableFile);
+ data.insert(QLatin1String(executableFileKeyC), m_executableFile.toVariant());
data.insert(QLatin1String(verboseLevelKeyC), m_verboseLevel);
data.insert(QLatin1String(extendedModeKeyC), m_extendedMode);
data.insert(QLatin1String(resetBoardKeyC), m_resetBoard);
@@ -184,7 +175,7 @@ bool StLinkUtilGdbServerProvider::fromMap(const QVariantMap &data)
m_host = data.value(QLatin1String(hostKeyC)).toString();
m_port = data.value(QLatin1String(portKeyC)).toInt();
- m_executableFile = data.value(QLatin1String(executableFileKeyC)).toString();
+ m_executableFile = FileName::fromVariant(data.value(QLatin1String(executableFileKeyC)));
m_verboseLevel = data.value(QLatin1String(verboseLevelKeyC)).toInt();
m_extendedMode = data.value(QLatin1String(extendedModeKeyC)).toBool();
m_resetBoard = data.value(QLatin1String(resetBoardKeyC)).toBool();
@@ -213,6 +204,8 @@ GdbServerProviderConfigWidget *StLinkUtilGdbServerProvider::configurationWidget(
return new StLinkUtilGdbServerProviderConfigWidget(this);
}
+// StLinkUtilGdbServerProviderFactory
+
StLinkUtilGdbServerProviderFactory::StLinkUtilGdbServerProviderFactory()
{
setId(QLatin1String(Constants::STLINK_UTIL_PROVIDER_ID));
@@ -233,14 +226,16 @@ bool StLinkUtilGdbServerProviderFactory::canRestore(const QVariantMap &data) con
GdbServerProvider *StLinkUtilGdbServerProviderFactory::restore(const QVariantMap &data)
{
- auto p = new StLinkUtilGdbServerProvider;
- auto updated = data;
+ const auto p = new StLinkUtilGdbServerProvider;
+ const auto updated = data;
if (p->fromMap(updated))
return p;
delete p;
return nullptr;
}
+// StLinkUtilGdbServerProviderConfigWidget
+
StLinkUtilGdbServerProviderConfigWidget::StLinkUtilGdbServerProviderConfigWidget(
StLinkUtilGdbServerProvider *p)
: GdbServerProviderConfigWidget(p)
@@ -283,7 +278,7 @@ StLinkUtilGdbServerProviderConfigWidget::StLinkUtilGdbServerProviderConfigWidget
addErrorLabel();
setFromProvider();
- auto chooser = new Core::VariableChooser(this);
+ const auto chooser = new Core::VariableChooser(this);
chooser->addSupportedWidget(m_initCommandsTextEdit);
chooser->addSupportedWidget(m_resetCommandsTextEdit);
@@ -293,14 +288,14 @@ StLinkUtilGdbServerProviderConfigWidget::StLinkUtilGdbServerProviderConfigWidget
this, &GdbServerProviderConfigWidget::dirty);
connect(m_verboseLevelSpinBox,
- static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ QOverload<int>::of(&QSpinBox::valueChanged),
this, &GdbServerProviderConfigWidget::dirty);
connect(m_extendedModeCheckBox, &QAbstractButton::clicked,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_resetBoardCheckBox, &QAbstractButton::clicked,
this, &GdbServerProviderConfigWidget::dirty);
connect(m_transportLayerComboBox,
- static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &GdbServerProviderConfigWidget::dirty);
connect(m_initCommandsTextEdit, &QPlainTextEdit::textChanged,
@@ -309,11 +304,10 @@ StLinkUtilGdbServerProviderConfigWidget::StLinkUtilGdbServerProviderConfigWidget
this, &GdbServerProviderConfigWidget::dirty);
connect(m_startupModeComboBox,
- static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &StLinkUtilGdbServerProviderConfigWidget::startupModeChanged);
}
-
void StLinkUtilGdbServerProviderConfigWidget::startupModeChanged()
{
const GdbServerProvider::StartupMode m = startupMode();
@@ -332,12 +326,12 @@ void StLinkUtilGdbServerProviderConfigWidget::startupModeChanged()
void StLinkUtilGdbServerProviderConfigWidget::applyImpl()
{
- auto p = static_cast<StLinkUtilGdbServerProvider *>(provider());
+ const auto p = static_cast<StLinkUtilGdbServerProvider *>(provider());
Q_ASSERT(p);
p->m_host = m_hostWidget->host();
p->m_port = m_hostWidget->port();
- p->m_executableFile = m_executableFileChooser->fileName().toString();
+ p->m_executableFile = m_executableFileChooser->fileName();
p->m_verboseLevel = m_verboseLevelSpinBox->value();
p->m_extendedMode = m_extendedModeCheckBox->isChecked();
p->m_resetBoard = m_resetBoardCheckBox->isChecked();
@@ -391,11 +385,11 @@ void StLinkUtilGdbServerProviderConfigWidget::setFromProvider()
const auto p = static_cast<StLinkUtilGdbServerProvider *>(provider());
Q_ASSERT(p);
- QSignalBlocker blocker(this);
+ const QSignalBlocker blocker(this);
startupModeChanged();
m_hostWidget->setHost(p->m_host);
m_hostWidget->setPort(p->m_port);
- m_executableFileChooser->setFileName(Utils::FileName::fromString(p->m_executableFile));
+ m_executableFileChooser->setFileName(p->m_executableFile);
m_verboseLevelSpinBox->setValue(p->m_verboseLevel);
m_extendedModeCheckBox->setChecked(p->m_extendedMode);
m_resetBoardCheckBox->setChecked(p->m_resetBoard);
diff --git a/src/plugins/baremetal/stlinkutilgdbserverprovider.h b/src/plugins/baremetal/stlinkutilgdbserverprovider.h
index 900e408028..18b75ad405 100644
--- a/src/plugins/baremetal/stlinkutilgdbserverprovider.h
+++ b/src/plugins/baremetal/stlinkutilgdbserverprovider.h
@@ -39,7 +39,9 @@ namespace Internal {
class StLinkUtilGdbServerProviderConfigWidget;
class StLinkUtilGdbServerProviderFactory;
-class StLinkUtilGdbServerProvider : public GdbServerProvider
+// StLinkUtilGdbServerProvider
+
+class StLinkUtilGdbServerProvider final : public GdbServerProvider
{
public:
enum TransportLayer { ScsiOverUsb = 1, RawUsb = 2 };
@@ -54,8 +56,7 @@ public:
GdbServerProvider *clone() const final;
QString channel() const final;
- QString executable() const final;
- QStringList arguments() const final;
+ Utils::CommandLine command() const final;
bool canStartupMode(StartupMode mode) const final;
bool isValid() const final;
@@ -67,19 +68,21 @@ private:
static QString defaultInitCommands();
static QString defaultResetCommands();
- QString m_host;
- quint16 m_port;
- QString m_executableFile;
- int m_verboseLevel; // 0..99
- bool m_extendedMode; // Listening for connections after disconnect
- bool m_resetBoard;
- TransportLayer m_transport;
+ QString m_host = QLatin1String("localhost");
+ quint16 m_port = 4242;
+ Utils::FilePath m_executableFile = Utils::FilePath::fromString("st-util");
+ int m_verboseLevel = 0; // 0..99
+ bool m_extendedMode = false; // Listening for connections after disconnect
+ bool m_resetBoard = true;
+ TransportLayer m_transport = RawUsb;
friend class StLinkUtilGdbServerProviderConfigWidget;
friend class StLinkUtilGdbServerProviderFactory;
};
-class StLinkUtilGdbServerProviderFactory : public GdbServerProviderFactory
+// StLinkUtilGdbServerProviderFactory
+
+class StLinkUtilGdbServerProviderFactory final : public GdbServerProviderFactory
{
Q_OBJECT
@@ -94,7 +97,10 @@ public:
GdbServerProviderConfigWidget *configurationWidget(GdbServerProvider *);
};
-class StLinkUtilGdbServerProviderConfigWidget : public GdbServerProviderConfigWidget
+// StLinkUtilGdbServerProviderConfigWidget
+
+class StLinkUtilGdbServerProviderConfigWidget final
+ : public GdbServerProviderConfigWidget
{
Q_OBJECT
@@ -114,14 +120,14 @@ private:
void populateTransportLayers();
void setFromProvider();
- HostWidget *m_hostWidget;
- Utils::PathChooser *m_executableFileChooser;
- QSpinBox *m_verboseLevelSpinBox;
- QCheckBox *m_extendedModeCheckBox;
- QCheckBox *m_resetBoardCheckBox;
- QComboBox *m_transportLayerComboBox;
- QPlainTextEdit *m_initCommandsTextEdit;
- QPlainTextEdit *m_resetCommandsTextEdit;
+ HostWidget *m_hostWidget = nullptr;
+ Utils::PathChooser *m_executableFileChooser = nullptr;
+ QSpinBox *m_verboseLevelSpinBox = nullptr;
+ QCheckBox *m_extendedModeCheckBox = nullptr;
+ QCheckBox *m_resetBoardCheckBox = nullptr;
+ QComboBox *m_transportLayerComboBox = nullptr;
+ QPlainTextEdit *m_initCommandsTextEdit = nullptr;
+ QPlainTextEdit *m_resetCommandsTextEdit = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/bazaar/CMakeLists.txt b/src/plugins/bazaar/CMakeLists.txt
new file mode 100644
index 0000000000..145323c42a
--- /dev/null
+++ b/src/plugins/bazaar/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_qtc_plugin(Bazaar
+ PLUGIN_DEPENDS Core TextEditor VcsBase
+ SOURCES
+ annotationhighlighter.cpp annotationhighlighter.h
+ bazaarclient.cpp bazaarclient.h
+ bazaarcommitpanel.ui
+ bazaarcommitwidget.cpp bazaarcommitwidget.h
+ bazaarcontrol.cpp bazaarcontrol.h
+ bazaareditor.cpp bazaareditor.h
+ bazaarplugin.cpp bazaarplugin.h
+ bazaarsettings.cpp bazaarsettings.h
+ branchinfo.cpp branchinfo.h
+ commiteditor.cpp commiteditor.h
+ constants.h
+ optionspage.cpp optionspage.h optionspage.ui
+ pullorpushdialog.cpp pullorpushdialog.h pullorpushdialog.ui
+ revertdialog.ui
+ uncommitdialog.cpp uncommitdialog.h uncommitdialog.ui
+)
diff --git a/src/plugins/bazaar/bazaarclient.cpp b/src/plugins/bazaar/bazaarclient.cpp
index f9941b2966..a60c7f331e 100644
--- a/src/plugins/bazaar/bazaarclient.cpp
+++ b/src/plugins/bazaar/bazaarclient.cpp
@@ -178,7 +178,7 @@ VcsBaseEditorWidget *BazaarClient::annotate(
QStringList(extraOptions) << QLatin1String("--long"));
}
-bool BazaarClient::isVcsDirectory(const FileName &fileName) const
+bool BazaarClient::isVcsDirectory(const FilePath &fileName) const
{
return fileName.toFileInfo().isDir()
&& !fileName.fileName().compare(Constants::BAZAARREPO, HostOsInfo::fileNameCaseSensitivity());
diff --git a/src/plugins/bazaar/bazaarclient.h b/src/plugins/bazaar/bazaarclient.h
index 21750daf22..78d1ca5b35 100644
--- a/src/plugins/bazaar/bazaarclient.h
+++ b/src/plugins/bazaar/bazaarclient.h
@@ -52,7 +52,7 @@ public:
VcsBase::VcsBaseEditorWidget *annotate(
const QString &workingDir, const QString &file, const QString &revision = QString(),
int lineNumber = -1, const QStringList &extraOptions = QStringList()) override;
- bool isVcsDirectory(const Utils::FileName &fileName) const;
+ bool isVcsDirectory(const Utils::FilePath &fileName) const;
QString findTopLevelForFile(const QFileInfo &file) const override;
bool managesFile(const QString &workingDirectory, const QString &fileName) const;
void view(const QString &source, const QString &id,
diff --git a/src/plugins/bazaar/bazaarcontrol.cpp b/src/plugins/bazaar/bazaarcontrol.cpp
index 3db806cf0c..7b38aa971c 100644
--- a/src/plugins/bazaar/bazaarcontrol.cpp
+++ b/src/plugins/bazaar/bazaarcontrol.cpp
@@ -52,7 +52,7 @@ Core::Id BazaarControl::id() const
return Core::Id(VcsBase::Constants::VCS_ID_BAZAAR);
}
-bool BazaarControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
+bool BazaarControl::isVcsFileOrDirectory(const Utils::FilePath &fileName) const
{
return m_bazaarClient->isVcsDirectory(fileName);
}
@@ -73,7 +73,7 @@ bool BazaarControl::managesFile(const QString &workingDirectory, const QString &
bool BazaarControl::isConfigured() const
{
- const Utils::FileName binary = m_bazaarClient->vcsBinary();
+ const Utils::FilePath binary = m_bazaarClient->vcsBinary();
if (binary.isEmpty())
return false;
QFileInfo fi = binary.toFileInfo();
@@ -139,7 +139,7 @@ bool BazaarControl::vcsAnnotate(const QString &file, int line)
}
Core::ShellCommand *BazaarControl::createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs)
{
diff --git a/src/plugins/bazaar/bazaarcontrol.h b/src/plugins/bazaar/bazaarcontrol.h
index ced12c9a79..d0d5b514d6 100644
--- a/src/plugins/bazaar/bazaarcontrol.h
+++ b/src/plugins/bazaar/bazaarcontrol.h
@@ -48,7 +48,7 @@ public:
QString displayName() const final;
Core::Id id() const final;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final;
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final;
bool managesDirectory(const QString &filename, QString *topLevel = nullptr) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
@@ -62,7 +62,7 @@ public:
bool vcsAnnotate(const QString &file, int line) final;
Core::ShellCommand *createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs) final;
diff --git a/src/plugins/beautifier/CMakeLists.txt b/src/plugins/beautifier/CMakeLists.txt
new file mode 100644
index 0000000000..f9955105ad
--- /dev/null
+++ b/src/plugins/beautifier/CMakeLists.txt
@@ -0,0 +1,27 @@
+add_qtc_plugin(Beautifier
+ DEPENDS Qt5::Xml
+ PLUGIN_DEPENDS Core CppEditor DiffEditor ProjectExplorer TextEditor
+ SOURCES
+ abstractsettings.cpp abstractsettings.h
+ artisticstyle/artisticstyle.cpp artisticstyle/artisticstyle.h
+ artisticstyle/artisticstyleconstants.h
+ artisticstyle/artisticstyleoptionspage.cpp artisticstyle/artisticstyleoptionspage.h artisticstyle/artisticstyleoptionspage.ui
+ artisticstyle/artisticstylesettings.cpp artisticstyle/artisticstylesettings.h
+ beautifier.qrc
+ beautifierabstracttool.h
+ beautifierconstants.h
+ beautifierplugin.cpp beautifierplugin.h
+ clangformat/clangformat.cpp clangformat/clangformat.h
+ clangformat/clangformatconstants.h
+ clangformat/clangformatoptionspage.cpp clangformat/clangformatoptionspage.h clangformat/clangformatoptionspage.ui
+ clangformat/clangformatsettings.cpp clangformat/clangformatsettings.h
+ configurationdialog.cpp configurationdialog.h configurationdialog.ui
+ configurationeditor.cpp configurationeditor.h
+ configurationpanel.cpp configurationpanel.h configurationpanel.ui
+ generaloptionspage.cpp generaloptionspage.h generaloptionspage.ui
+ generalsettings.cpp generalsettings.h
+ uncrustify/uncrustify.cpp uncrustify/uncrustify.h
+ uncrustify/uncrustifyconstants.h
+ uncrustify/uncrustifyoptionspage.cpp uncrustify/uncrustifyoptionspage.h uncrustify/uncrustifyoptionspage.ui
+ uncrustify/uncrustifysettings.cpp uncrustify/uncrustifysettings.h
+)
diff --git a/src/plugins/beautifier/abstractsettings.cpp b/src/plugins/beautifier/abstractsettings.cpp
index 4d47a756d5..c7c091df90 100644
--- a/src/plugins/beautifier/abstractsettings.cpp
+++ b/src/plugins/beautifier/abstractsettings.cpp
@@ -32,6 +32,7 @@
#include <coreplugin/idocument.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
+#include <utils/genericconstants.h>
#include <utils/mimetypes/mimedatabase.h>
#include <QFile>
@@ -204,7 +205,7 @@ void AbstractSettings::save()
{
// Save settings, except styles
QSettings *s = Core::ICore::settings();
- s->beginGroup(Constants::SETTINGS_GROUP);
+ s->beginGroup(Utils::Constants::BEAUTIFIER_SETTINGS_GROUP);
s->beginGroup(m_name);
QMap<QString, QVariant>::const_iterator iSettings = m_settings.constBegin();
while (iSettings != m_settings.constEnd()) {
@@ -276,7 +277,7 @@ void AbstractSettings::read()
// Read settings, except styles
QSettings *s = Core::ICore::settings();
- s->beginGroup(Constants::SETTINGS_GROUP);
+ s->beginGroup(Utils::Constants::BEAUTIFIER_SETTINGS_GROUP);
s->beginGroup(m_name);
const QStringList keys = s->allKeys();
for (const QString &key : keys) {
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
index 4a7ee4ec54..2788214fee 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
+++ b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
@@ -29,7 +29,6 @@
#include "artisticstyleconstants.h"
#include "artisticstyleoptionspage.h"
-#include "artisticstylesettings.h"
#include "../beautifierconstants.h"
#include "../beautifierplugin.h"
@@ -58,16 +57,6 @@ namespace Internal {
namespace ArtisticStyle {
ArtisticStyle::ArtisticStyle()
- : m_settings(new ArtisticStyleSettings)
-{
-}
-
-ArtisticStyle::~ArtisticStyle()
-{
- delete m_settings;
-}
-
-bool ArtisticStyle::initialize()
{
Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::ArtisticStyle::MENU_ID);
menu->menu()->setTitle(tr("&Artistic Style"));
@@ -79,12 +68,10 @@ bool ArtisticStyle::initialize()
Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
- connect(m_settings, &ArtisticStyleSettings::supportedMimeTypesChanged,
+ connect(&m_settings, &ArtisticStyleSettings::supportedMimeTypesChanged,
[this] { updateActions(Core::EditorManager::currentEditor()); });
- new ArtisticStyleOptionsPage(m_settings, this);
-
- return true;
+ new ArtisticStyleOptionsPage(&m_settings, this);
}
QString ArtisticStyle::id() const
@@ -94,7 +81,7 @@ QString ArtisticStyle::id() const
void ArtisticStyle::updateActions(Core::IEditor *editor)
{
- m_formatFile->setEnabled(editor && m_settings->isApplicable(editor->document()));
+ m_formatFile->setEnabled(editor && m_settings.isApplicable(editor->document()));
}
void ArtisticStyle::formatFile()
@@ -110,14 +97,14 @@ void ArtisticStyle::formatFile()
QString ArtisticStyle::configurationFile() const
{
- if (m_settings->useCustomStyle())
- return m_settings->styleFileName(m_settings->customStyle());
+ if (m_settings.useCustomStyle())
+ return m_settings.styleFileName(m_settings.customStyle());
- if (m_settings->useOtherFiles()) {
+ if (m_settings.useOtherFiles()) {
if (const ProjectExplorer::Project *project
= ProjectExplorer::ProjectTree::currentProject()) {
- const Utils::FileNameList files = project->files(ProjectExplorer::Project::AllFiles);
- for (const Utils::FileName &file : files) {
+ const Utils::FilePathList files = project->files(ProjectExplorer::Project::AllFiles);
+ for (const Utils::FilePath &file : files) {
if (!file.endsWith(".astylerc"))
continue;
const QFileInfo fi = file.toFileInfo();
@@ -127,13 +114,13 @@ QString ArtisticStyle::configurationFile() const
}
}
- if (m_settings->useSpecificConfigFile()) {
- const Utils::FileName file = m_settings->specificConfigFile();
+ if (m_settings.useSpecificConfigFile()) {
+ const Utils::FilePath file = m_settings.specificConfigFile();
if (file.exists())
return file.toUserOutput();
}
- if (m_settings->useHomeFile()) {
+ if (m_settings.useHomeFile()) {
const QDir homeDirectory = QDir::home();
QString file = homeDirectory.filePath(".astylerc");
if (QFile::exists(file))
@@ -154,17 +141,17 @@ Command ArtisticStyle::command() const
bool ArtisticStyle::isApplicable(const Core::IDocument *document) const
{
- return m_settings->isApplicable(document);
+ return m_settings.isApplicable(document);
}
Command ArtisticStyle::command(const QString &cfgFile) const
{
Command command;
- command.setExecutable(m_settings->command());
+ command.setExecutable(m_settings.command());
command.addOption("-q");
command.addOption("--options=" + cfgFile);
- const int version = m_settings->version();
+ const int version = m_settings.version();
if (version > ArtisticStyleSettings::Version_2_03) {
command.setProcessing(Command::PipeProcessing);
if (version == ArtisticStyleSettings::Version_2_04)
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.h b/src/plugins/beautifier/artisticstyle/artisticstyle.h
index 5927814489..0e2b566da2 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstyle.h
+++ b/src/plugins/beautifier/artisticstyle/artisticstyle.h
@@ -27,23 +27,21 @@
#include "../beautifierabstracttool.h"
+#include "artisticstylesettings.h"
+
QT_FORWARD_DECLARE_CLASS(QAction)
namespace Beautifier {
namespace Internal {
namespace ArtisticStyle {
-class ArtisticStyleSettings;
-
class ArtisticStyle : public BeautifierAbstractTool
{
Q_OBJECT
public:
ArtisticStyle();
- ~ArtisticStyle() override;
- bool initialize() override;
QString id() const override;
void updateActions(Core::IEditor *editor) override;
TextEditor::Command command() const override;
@@ -52,7 +50,7 @@ public:
private:
void formatFile();
QAction *m_formatFile = nullptr;
- ArtisticStyleSettings *m_settings;
+ ArtisticStyleSettings m_settings;
QString configurationFile() const;
TextEditor::Command command(const QString &cfgFile) const;
};
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
index c6b9c60f07..41ba9270aa 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
@@ -131,12 +131,12 @@ void ArtisticStyleSettings::setUseSpecificConfigFile(bool useSpecificConfigFile)
m_settings.insert(USE_SPECIFIC_CONFIG_FILE, QVariant(useSpecificConfigFile));
}
-Utils::FileName ArtisticStyleSettings::specificConfigFile() const
+Utils::FilePath ArtisticStyleSettings::specificConfigFile() const
{
- return Utils::FileName::fromString(m_settings.value(SPECIFIC_CONFIG_FILE).toString());
+ return Utils::FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE).toString());
}
-void ArtisticStyleSettings::setSpecificConfigFile(const Utils::FileName &specificConfigFile)
+void ArtisticStyleSettings::setSpecificConfigFile(const Utils::FilePath &specificConfigFile)
{
m_settings.insert(SPECIFIC_CONFIG_FILE, QVariant(specificConfigFile.toString()));
}
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.h b/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
index 9e3c60e435..50deba87d6 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
@@ -56,8 +56,8 @@ public:
bool useSpecificConfigFile() const;
void setUseSpecificConfigFile(bool useSpecificConfigFile);
- Utils::FileName specificConfigFile() const;
- void setSpecificConfigFile(const Utils::FileName &specificConfigFile);
+ Utils::FilePath specificConfigFile() const;
+ void setSpecificConfigFile(const Utils::FilePath &specificConfigFile);
bool useHomeFile() const;
void setUseHomeFile(bool useHomeFile);
diff --git a/src/plugins/beautifier/beautifierabstracttool.h b/src/plugins/beautifier/beautifierabstracttool.h
index 813f37ac7f..d48ee0f576 100644
--- a/src/plugins/beautifier/beautifierabstracttool.h
+++ b/src/plugins/beautifier/beautifierabstracttool.h
@@ -45,7 +45,6 @@ public:
BeautifierAbstractTool() = default;
virtual QString id() const = 0;
- virtual bool initialize() = 0;
virtual void updateActions(Core::IEditor *editor) = 0;
/**
diff --git a/src/plugins/beautifier/beautifierconstants.h b/src/plugins/beautifier/beautifierconstants.h
index 4430e62f6e..269f41bc84 100644
--- a/src/plugins/beautifier/beautifierconstants.h
+++ b/src/plugins/beautifier/beautifierconstants.h
@@ -34,7 +34,6 @@ const char ACTION_ID[] = "Beautifier.Action";
const char MENU_ID[] = "Beautifier.Menu";
const char OPTION_CATEGORY[] = "II.Beautifier";
const char OPTION_GENERAL_ID[] = "aaa.General";
-const char SETTINGS_GROUP[] = "Beautifier";
const char SETTINGS_DIRNAME[] = "beautifier";
const char DOCUMENTATION_DIRNAME[] = "documentation";
const char DOCUMENTATION_XMLROOT[] = "beautifier_documentation";
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
index 90db34df1c..6e4cb079f2 100644
--- a/src/plugins/beautifier/beautifierplugin.cpp
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -129,10 +129,8 @@ BeautifierPluginPrivate::BeautifierPluginPrivate()
{
QStringList toolIds;
toolIds.reserve(m_tools.count());
- for (BeautifierAbstractTool *tool : m_tools) {
+ for (BeautifierAbstractTool *tool : m_tools)
toolIds << tool->id();
- tool->initialize();
- }
m_generalSettings.reset(new GeneralSettings);
new GeneralOptionsPage(m_generalSettings, toolIds, this);
diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp
index ee2e9ad770..a6f7f8e198 100644
--- a/src/plugins/beautifier/clangformat/clangformat.cpp
+++ b/src/plugins/beautifier/clangformat/clangformat.cpp
@@ -29,7 +29,6 @@
#include "clangformatconstants.h"
#include "clangformatoptionspage.h"
-#include "clangformatsettings.h"
#include "../beautifierconstants.h"
#include "../beautifierplugin.h"
@@ -58,21 +57,6 @@ namespace Internal {
namespace ClangFormat {
ClangFormat::ClangFormat()
- : m_settings(new ClangFormatSettings)
-{
-}
-
-ClangFormat::~ClangFormat()
-{
- delete m_settings;
-}
-
-QString ClangFormat::id() const
-{
- return QLatin1String(Constants::ClangFormat::DISPLAY_NAME);
-}
-
-bool ClangFormat::initialize()
{
Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::ClangFormat::MENU_ID);
menu->menu()->setTitle(tr("&ClangFormat"));
@@ -100,17 +84,20 @@ bool ClangFormat::initialize()
Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
- connect(m_settings, &ClangFormatSettings::supportedMimeTypesChanged,
+ connect(&m_settings, &ClangFormatSettings::supportedMimeTypesChanged,
[this] { updateActions(Core::EditorManager::currentEditor()); });
- new ClangFormatOptionsPage(m_settings, this);
+ new ClangFormatOptionsPage(&m_settings, this);
+}
- return true;
+QString ClangFormat::id() const
+{
+ return QLatin1String(Constants::ClangFormat::DISPLAY_NAME);
}
void ClangFormat::updateActions(Core::IEditor *editor)
{
- const bool enabled = editor && m_settings->isApplicable(editor->document());
+ const bool enabled = editor && m_settings.isApplicable(editor->document());
m_formatFile->setEnabled(enabled);
m_formatRange->setEnabled(enabled);
}
@@ -180,14 +167,14 @@ void ClangFormat::disableFormattingSelectedText()
Command ClangFormat::command() const
{
Command command;
- command.setExecutable(m_settings->command());
+ command.setExecutable(m_settings.command());
command.setProcessing(Command::PipeProcessing);
- if (m_settings->usePredefinedStyle()) {
- const QString predefinedStyle = m_settings->predefinedStyle();
+ if (m_settings.usePredefinedStyle()) {
+ const QString predefinedStyle = m_settings.predefinedStyle();
command.addOption("-style=" + predefinedStyle);
if (predefinedStyle == "File") {
- const QString fallbackStyle = m_settings->fallbackStyle();
+ const QString fallbackStyle = m_settings.fallbackStyle();
if (fallbackStyle != "Default")
command.addOption("-fallback-style=" + fallbackStyle);
}
@@ -196,7 +183,7 @@ Command ClangFormat::command() const
} else {
command.addOption("-style=file");
const QString path =
- QFileInfo(m_settings->styleFileName(m_settings->customStyle())).absolutePath();
+ QFileInfo(m_settings.styleFileName(m_settings.customStyle())).absolutePath();
command.addOption("-assume-filename=" + path + QDir::separator() + "%filename");
}
@@ -205,7 +192,7 @@ Command ClangFormat::command() const
bool ClangFormat::isApplicable(const Core::IDocument *document) const
{
- return m_settings->isApplicable(document);
+ return m_settings.isApplicable(document);
}
Command ClangFormat::command(int offset, int length) const
diff --git a/src/plugins/beautifier/clangformat/clangformat.h b/src/plugins/beautifier/clangformat/clangformat.h
index 4d69d2e9e5..ecacd7d8cb 100644
--- a/src/plugins/beautifier/clangformat/clangformat.h
+++ b/src/plugins/beautifier/clangformat/clangformat.h
@@ -27,24 +27,22 @@
#include "../beautifierabstracttool.h"
+#include "clangformatsettings.h"
+
QT_FORWARD_DECLARE_CLASS(QAction)
namespace Beautifier {
namespace Internal {
namespace ClangFormat {
-class ClangFormatSettings;
-
class ClangFormat : public BeautifierAbstractTool
{
Q_OBJECT
public:
ClangFormat();
- ~ClangFormat() override;
QString id() const override;
- bool initialize() override;
void updateActions(Core::IEditor *editor) override;
TextEditor::Command command() const override;
bool isApplicable(const Core::IDocument *document) const override;
@@ -53,11 +51,12 @@ private:
void formatFile();
void formatAtCursor();
void disableFormattingSelectedText();
+ TextEditor::Command command(int offset, int length) const;
+
QAction *m_formatFile = nullptr;
QAction *m_formatRange = nullptr;
QAction *m_disableFormattingSelectedText = nullptr;
- ClangFormatSettings *m_settings;
- TextEditor::Command command(int offset, int length) const;
+ ClangFormatSettings m_settings;
};
} // namespace ClangFormat
diff --git a/src/plugins/beautifier/configurationeditor.cpp b/src/plugins/beautifier/configurationeditor.cpp
index 7c98602892..179864b0b9 100644
--- a/src/plugins/beautifier/configurationeditor.cpp
+++ b/src/plugins/beautifier/configurationeditor.cpp
@@ -98,7 +98,7 @@ ConfigurationEditor::ConfigurationEditor(QWidget *parent) :
m_completer->setCaseSensitivity(Qt::CaseInsensitive);
m_completer->popup()->installEventFilter(this);
- connect(m_completer, static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::activated),
+ connect(m_completer, QOverload<const QString &>::of(&QCompleter::activated),
this, &ConfigurationEditor::insertCompleterText);
connect(this, &ConfigurationEditor::cursorPositionChanged,
this, &ConfigurationEditor::updateDocumentation);
diff --git a/src/plugins/beautifier/configurationpanel.cpp b/src/plugins/beautifier/configurationpanel.cpp
index 1e5a8dfaa9..a693d42b99 100644
--- a/src/plugins/beautifier/configurationpanel.cpp
+++ b/src/plugins/beautifier/configurationpanel.cpp
@@ -40,7 +40,7 @@ ConfigurationPanel::ConfigurationPanel(QWidget *parent) :
connect(ui->add, &QPushButton::clicked, this, &ConfigurationPanel::add);
connect(ui->edit, &QPushButton::clicked, this, &ConfigurationPanel::edit);
connect(ui->remove, &QPushButton::clicked, this, &ConfigurationPanel::remove);
- connect(ui->configurations, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(ui->configurations, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ConfigurationPanel::updateButtons);
}
diff --git a/src/plugins/beautifier/generalsettings.cpp b/src/plugins/beautifier/generalsettings.cpp
index a3018950d1..9546ec5d25 100644
--- a/src/plugins/beautifier/generalsettings.cpp
+++ b/src/plugins/beautifier/generalsettings.cpp
@@ -29,14 +29,13 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
+#include <utils/genericconstants.h>
#include <utils/mimetypes/mimedatabase.h>
namespace Beautifier {
namespace Internal {
namespace {
-const char GROUP[] = "General";
-const char AUTO_FORMAT_ON_SAVE[] = "autoFormatOnSave";
const char AUTO_FORMAT_TOOL[] = "autoFormatTool";
const char AUTO_FORMAT_MIME[] = "autoFormatMime";
const char AUTO_FORMAT_ONLY_CURRENT_PROJECT[] = "autoFormatOnlyCurrentProject";
@@ -50,9 +49,9 @@ GeneralSettings::GeneralSettings()
void GeneralSettings::read()
{
QSettings *s = Core::ICore::settings();
- s->beginGroup(Constants::SETTINGS_GROUP);
- s->beginGroup(GROUP);
- m_autoFormatOnSave = s->value(AUTO_FORMAT_ON_SAVE, false).toBool();
+ s->beginGroup(Utils::Constants::BEAUTIFIER_SETTINGS_GROUP);
+ s->beginGroup(Utils::Constants::BEAUTIFIER_GENERAL_GROUP);
+ m_autoFormatOnSave = s->value(Utils::Constants::BEAUTIFIER_AUTO_FORMAT_ON_SAVE, false).toBool();
m_autoFormatTool = s->value(AUTO_FORMAT_TOOL, QString()).toString();
setAutoFormatMime(s->value(AUTO_FORMAT_MIME, "text/x-c++src;text/x-c++hdr").toString());
m_autoFormatOnlyCurrentProject = s->value(AUTO_FORMAT_ONLY_CURRENT_PROJECT, true).toBool();
@@ -63,9 +62,9 @@ void GeneralSettings::read()
void GeneralSettings::save()
{
QSettings *s = Core::ICore::settings();
- s->beginGroup(Constants::SETTINGS_GROUP);
- s->beginGroup(GROUP);
- s->setValue(AUTO_FORMAT_ON_SAVE, m_autoFormatOnSave);
+ s->beginGroup(Utils::Constants::BEAUTIFIER_SETTINGS_GROUP);
+ s->beginGroup(Utils::Constants::BEAUTIFIER_GENERAL_GROUP);
+ s->setValue(Utils::Constants::BEAUTIFIER_AUTO_FORMAT_ON_SAVE, m_autoFormatOnSave);
s->setValue(AUTO_FORMAT_TOOL, m_autoFormatTool);
s->setValue(AUTO_FORMAT_MIME, autoFormatMimeAsString());
s->setValue(AUTO_FORMAT_ONLY_CURRENT_PROJECT, m_autoFormatOnlyCurrentProject);
diff --git a/src/plugins/beautifier/uncrustify/uncrustify.cpp b/src/plugins/beautifier/uncrustify/uncrustify.cpp
index daeffdf2df..f6a36eadc0 100644
--- a/src/plugins/beautifier/uncrustify/uncrustify.cpp
+++ b/src/plugins/beautifier/uncrustify/uncrustify.cpp
@@ -29,7 +29,6 @@
#include "uncrustifyconstants.h"
#include "uncrustifyoptionspage.h"
-#include "uncrustifysettings.h"
#include "../beautifierconstants.h"
#include "../beautifierplugin.h"
@@ -58,16 +57,6 @@ namespace Internal {
namespace Uncrustify {
Uncrustify::Uncrustify()
- : m_settings(new UncrustifySettings)
-{
-}
-
-Uncrustify::~Uncrustify()
-{
- delete m_settings;
-}
-
-bool Uncrustify::initialize()
{
Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::Uncrustify::MENU_ID);
menu->menu()->setTitle(tr("&Uncrustify"));
@@ -87,12 +76,10 @@ bool Uncrustify::initialize()
Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
- connect(m_settings, &UncrustifySettings::supportedMimeTypesChanged,
+ connect(&m_settings, &UncrustifySettings::supportedMimeTypesChanged,
[this] { updateActions(Core::EditorManager::currentEditor()); });
- new UncrustifyOptionsPage(m_settings, this);
-
- return true;
+ new UncrustifyOptionsPage(&m_settings, this);
}
QString Uncrustify::id() const
@@ -102,7 +89,7 @@ QString Uncrustify::id() const
void Uncrustify::updateActions(Core::IEditor *editor)
{
- const bool enabled = editor && m_settings->isApplicable(editor->document());
+ const bool enabled = editor && m_settings.isApplicable(editor->document());
m_formatFile->setEnabled(enabled);
m_formatRange->setEnabled(enabled);
}
@@ -144,21 +131,21 @@ void Uncrustify::formatSelectedText()
tc.movePosition(QTextCursor::EndOfLine);
const int endPos = tc.position();
formatCurrentFile(command(cfgFileName, true), startPos, endPos);
- } else if (m_settings->formatEntireFileFallback()) {
+ } else if (m_settings.formatEntireFileFallback()) {
formatFile();
}
}
QString Uncrustify::configurationFile() const
{
- if (m_settings->useCustomStyle())
- return m_settings->styleFileName(m_settings->customStyle());
+ if (m_settings.useCustomStyle())
+ return m_settings.styleFileName(m_settings.customStyle());
- if (m_settings->useOtherFiles()) {
+ if (m_settings.useOtherFiles()) {
if (const ProjectExplorer::Project *project
= ProjectExplorer::ProjectTree::currentProject()) {
- const Utils::FileNameList files = project->files(ProjectExplorer::Project::AllFiles);
- for (const Utils::FileName &file : files) {
+ const Utils::FilePathList files = project->files(ProjectExplorer::Project::AllFiles);
+ for (const Utils::FilePath &file : files) {
if (!file.endsWith("cfg"))
continue;
const QFileInfo fi = file.toFileInfo();
@@ -168,13 +155,13 @@ QString Uncrustify::configurationFile() const
}
}
- if (m_settings->useSpecificConfigFile()) {
- const Utils::FileName file = m_settings->specificConfigFile();
+ if (m_settings.useSpecificConfigFile()) {
+ const Utils::FilePath file = m_settings.specificConfigFile();
if (file.exists())
return file.toString();
}
- if (m_settings->useHomeFile()) {
+ if (m_settings.useHomeFile()) {
const QString file = QDir::home().filePath("uncrustify.cfg");
if (QFile::exists(file))
return file;
@@ -191,15 +178,15 @@ Command Uncrustify::command() const
bool Uncrustify::isApplicable(const Core::IDocument *document) const
{
- return m_settings->isApplicable(document);
+ return m_settings.isApplicable(document);
}
Command Uncrustify::command(const QString &cfgFile, bool fragment) const
{
Command command;
- command.setExecutable(m_settings->command());
+ command.setExecutable(m_settings.command());
command.setProcessing(Command::PipeProcessing);
- if (m_settings->version() >= 62) {
+ if (m_settings.version() >= 62) {
command.addOption("--assume");
command.addOption("%file");
} else {
diff --git a/src/plugins/beautifier/uncrustify/uncrustify.h b/src/plugins/beautifier/uncrustify/uncrustify.h
index e35434fc81..ece235fb8b 100644
--- a/src/plugins/beautifier/uncrustify/uncrustify.h
+++ b/src/plugins/beautifier/uncrustify/uncrustify.h
@@ -27,22 +27,21 @@
#include "../beautifierabstracttool.h"
+#include "uncrustifysettings.h"
+
QT_FORWARD_DECLARE_CLASS(QAction)
namespace Beautifier {
namespace Internal {
namespace Uncrustify {
-class UncrustifySettings;
-
class Uncrustify : public BeautifierAbstractTool
{
Q_OBJECT
public:
Uncrustify();
- ~Uncrustify() override;
- bool initialize() override;
+
QString id() const override;
void updateActions(Core::IEditor *editor) override;
TextEditor::Command command() const override;
@@ -53,7 +52,7 @@ private:
void formatSelectedText();
QAction *m_formatFile = nullptr;
QAction *m_formatRange = nullptr;
- UncrustifySettings *m_settings;
+ UncrustifySettings m_settings;
QString configurationFile() const;
TextEditor::Command command(const QString &cfgFile, bool fragment = false) const;
};
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
index 20b134d122..7d7954ceb7 100644
--- a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
@@ -56,8 +56,7 @@ const char FORMAT_ENTIRE_FILE_FALLBACK[] = "formatEntireFileFallback";
UncrustifySettings::UncrustifySettings() :
AbstractSettings(Constants::Uncrustify::SETTINGS_NAME, ".cfg")
{
- connect(&m_versionProcess,
- static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_versionProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &UncrustifySettings::parseVersionProcessResult);
setCommand("uncrustify");
@@ -91,12 +90,12 @@ void UncrustifySettings::setUseHomeFile(bool useHomeFile)
m_settings.insert(USE_HOME_FILE, QVariant(useHomeFile));
}
-Utils::FileName UncrustifySettings::specificConfigFile() const
+Utils::FilePath UncrustifySettings::specificConfigFile() const
{
- return Utils::FileName::fromString(m_settings.value(SPECIFIC_CONFIG_FILE_PATH).toString());
+ return Utils::FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE_PATH).toString());
}
-void UncrustifySettings::setSpecificConfigFile(const Utils::FileName &filePath)
+void UncrustifySettings::setSpecificConfigFile(const Utils::FilePath &filePath)
{
m_settings.insert(SPECIFIC_CONFIG_FILE_PATH, QVariant(filePath.toString()));
}
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.h b/src/plugins/beautifier/uncrustify/uncrustifysettings.h
index 8b21db84f9..07798ef1e1 100644
--- a/src/plugins/beautifier/uncrustify/uncrustifysettings.h
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.h
@@ -60,8 +60,8 @@ public:
void updateVersion() override;
- Utils::FileName specificConfigFile() const;
- void setSpecificConfigFile(const Utils::FileName &filePath);
+ Utils::FilePath specificConfigFile() const;
+ void setSpecificConfigFile(const Utils::FilePath &filePath);
bool useSpecificConfigFile() const;
void setUseSpecificConfigFile(bool useConfigFile);
diff --git a/src/plugins/bineditor/CMakeLists.txt b/src/plugins/bineditor/CMakeLists.txt
new file mode 100644
index 0000000000..fda0791388
--- /dev/null
+++ b/src/plugins/bineditor/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_qtc_plugin(BinEditor
+ PLUGIN_DEPENDS Core TextEditor
+ SOURCES
+ bineditor_global.h
+ bineditorconstants.h
+ bineditorplugin.cpp bineditorplugin.h
+ bineditorservice.h
+ bineditorwidget.cpp bineditorwidget.h
+ markup.cpp markup.h
+)
diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp
index 7ca01958d0..9fbba5c7f8 100644
--- a/src/plugins/bineditor/bineditorplugin.cpp
+++ b/src/plugins/bineditor/bineditorplugin.cpp
@@ -234,7 +234,7 @@ public:
bool save(QString *errorString, const QString &fn, bool autoSave) override
{
QTC_ASSERT(!autoSave, return true); // bineditor does not support autosave - it would be a bit expensive
- const FileName fileNameToUse = fn.isEmpty() ? filePath() : FileName::fromString(fn);
+ const FilePath fileNameToUse = fn.isEmpty() ? filePath() : FilePath::fromString(fn);
if (m_widget->save(errorString, filePath().toString(), fileNameToUse.toString())) {
setFilePath(fileNameToUse);
return true;
@@ -275,7 +275,7 @@ public:
}
if (offset >= size)
return OpenResult::CannotHandle;
- setFilePath(FileName::fromString(fileName));
+ setFilePath(FilePath::fromString(fileName));
m_widget->setSizes(offset, file.size());
return OpenResult::Success;
}
@@ -290,7 +290,7 @@ public:
void provideData(quint64 address)
{
- const FileName fn = filePath();
+ const FilePath fn = filePath();
if (fn.isEmpty())
return;
QFile file(fn.toString());
@@ -324,7 +324,7 @@ public:
}
bool isFileReadOnly() const override {
- const FileName fn = filePath();
+ const FilePath fn = filePath();
if (fn.isEmpty())
return false;
return !fn.toFileInfo().isWritable();
diff --git a/src/plugins/bineditor/bineditorplugin.h b/src/plugins/bineditor/bineditorplugin.h
index 8db7761c2c..14460d8287 100644
--- a/src/plugins/bineditor/bineditorplugin.h
+++ b/src/plugins/bineditor/bineditorplugin.h
@@ -38,8 +38,6 @@ class BinEditorPlugin : public ExtensionSystem::IPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "BinEditor.json")
-public:
- BinEditorPlugin() = default;
~BinEditorPlugin() override;
bool initialize(const QStringList &arguments, QString *errorMessage) final;
diff --git a/src/plugins/bineditor/bineditorwidget.cpp b/src/plugins/bineditor/bineditorwidget.cpp
index 89ab6f634b..2d17786453 100644
--- a/src/plugins/bineditor/bineditorwidget.cpp
+++ b/src/plugins/bineditor/bineditorwidget.cpp
@@ -185,35 +185,35 @@ void BinEditorWidget::init()
m_descent = fm.descent();
m_ascent = fm.ascent();
m_lineHeight = fm.lineSpacing();
- m_charWidth = fm.width(QChar(QLatin1Char('M')));
+ m_charWidth = fm.horizontalAdvance(QChar(QLatin1Char('M')));
m_margin = m_charWidth;
- m_columnWidth = 2 * m_charWidth + fm.width(QChar(QLatin1Char(' ')));
+ m_columnWidth = 2 * m_charWidth + fm.horizontalAdvance(QChar(QLatin1Char(' ')));
m_numLines = m_size / m_bytesPerLine + 1;
m_numVisibleLines = viewport()->height() / m_lineHeight;
m_textWidth = m_bytesPerLine * m_charWidth + m_charWidth;
- int numberWidth = fm.width(QChar(QLatin1Char('9')));
+ int numberWidth = fm.horizontalAdvance(QChar(QLatin1Char('9')));
m_labelWidth = 2*m_addressBytes * numberWidth + (m_addressBytes - 1)/2 * m_charWidth;
int expectedCharWidth = m_columnWidth / 3;
const char *hex = "0123456789abcdef";
m_isMonospacedFont = true;
while (*hex) {
- if (fm.width(QLatin1Char(*hex)) != expectedCharWidth) {
+ if (fm.horizontalAdvance(QLatin1Char(*hex)) != expectedCharWidth) {
m_isMonospacedFont = false;
break;
}
++hex;
}
- if (m_isMonospacedFont && fm.width(QLatin1String("M M ")) != m_charWidth * 4) {
+ if (m_isMonospacedFont && fm.horizontalAdvance(QLatin1String("M M ")) != m_charWidth * 4) {
// On Qt/Mac, monospace font widths may have a fractional component
// This breaks the assumption that width("MMM") == width('M') * 3
m_isMonospacedFont = false;
- m_columnWidth = fm.width(QLatin1String("MMM"));
+ m_columnWidth = fm.horizontalAdvance(QLatin1String("MMM"));
m_labelWidth = m_addressBytes == 4
- ? fm.width(QLatin1String("MMMM:MMMM"))
- : fm.width(QLatin1String("MMMM:MMMM:MMMM:MMMM"));
+ ? fm.horizontalAdvance(QLatin1String("MMMM:MMMM"))
+ : fm.horizontalAdvance(QLatin1String("MMMM:MMMM:MMMM:MMMM"));
}
horizontalScrollBar()->setRange(0, 2 * m_margin + m_bytesPerLine * m_columnWidth
@@ -568,7 +568,7 @@ Utils::optional<qint64> BinEditorWidget::posAt(const QPoint &pos, bool includeEm
QChar qc(QLatin1Char(dataAt(dataPos)));
if (!qc.isPrint())
qc = 0xB7;
- x -= fontMetrics().width(qc);
+ x -= fontMetrics().horizontalAdvance(qc);
if (x <= 0)
break;
}
@@ -913,18 +913,18 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
if (color.isValid()) {
painter.fillRect(item_x - m_charWidth/2, y-m_ascent, m_columnWidth, m_lineHeight, color);
int printable_item_x = -xoffset + m_margin + m_labelWidth + m_bytesPerLine * m_columnWidth + m_charWidth
- + fm.width(printable.left(c));
+ + fm.horizontalAdvance(printable.left(c));
painter.fillRect(printable_item_x, y-m_ascent,
- fm.width(printable.at(c)),
+ fm.horizontalAdvance(printable.at(c)),
m_lineHeight, color);
}
if (!isFullySelected && pos >= selStart && pos <= selEnd) {
selectionRect |= QRect(item_x - m_charWidth/2, y-m_ascent, m_columnWidth, m_lineHeight);
int printable_item_x = -xoffset + m_margin + m_labelWidth + m_bytesPerLine * m_columnWidth + m_charWidth
- + fm.width(printable.left(c));
+ + fm.horizontalAdvance(printable.left(c));
printableSelectionRect |= QRect(printable_item_x, y-m_ascent,
- fm.width(printable.at(c)),
+ fm.horizontalAdvance(printable.at(c)),
m_lineHeight);
}
}
@@ -958,7 +958,7 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
paintCursorBorder(&painter, cursorRect);
if (m_hexCursor && m_cursorVisible) {
if (m_lowNibble)
- cursorRect.adjust(fm.width(itemString.left(1)), 0, 0, 0);
+ cursorRect.adjust(fm.horizontalAdvance(itemString.left(1)), 0, 0, 0);
painter.fillRect(cursorRect, Qt::red);
painter.save();
painter.setClipRect(cursorRect);
@@ -972,7 +972,7 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
if (isFullySelected) {
painter.save();
- painter.fillRect(text_x, y-m_ascent, fm.width(printable), m_lineHeight,
+ painter.fillRect(text_x, y-m_ascent, fm.horizontalAdvance(printable), m_lineHeight,
palette().highlight());
painter.setPen(palette().highlightedText().color());
painter.drawText(text_x, y, printable);
@@ -990,9 +990,9 @@ void BinEditorWidget::paintEvent(QPaintEvent *e)
}
if (cursor >= 0 && !printable.isEmpty()) {
- QRect cursorRect(text_x + fm.width(printable.left(cursor)),
+ QRect cursorRect(text_x + fm.horizontalAdvance(printable.left(cursor)),
y-m_ascent,
- fm.width(printable.at(cursor)),
+ fm.horizontalAdvance(printable.at(cursor)),
m_lineHeight);
if (m_hexCursor || !m_cursorVisible) {
paintCursorBorder(&painter, cursorRect);
diff --git a/src/plugins/bookmarks/CMakeLists.txt b/src/plugins/bookmarks/CMakeLists.txt
new file mode 100644
index 0000000000..2c6847cffc
--- /dev/null
+++ b/src/plugins/bookmarks/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_qtc_plugin(Bookmarks
+ PLUGIN_DEPENDS Core ProjectExplorer TextEditor
+ SOURCES
+ bookmark.cpp bookmark.h
+ bookmarkfilter.cpp bookmarkfilter.h
+ bookmarkmanager.cpp bookmarkmanager.h
+ bookmarks_global.h
+ bookmarksplugin.cpp bookmarksplugin.h
+)
diff --git a/src/plugins/bookmarks/bookmark.cpp b/src/plugins/bookmarks/bookmark.cpp
index cf591035d7..1e5d0d2c0d 100644
--- a/src/plugins/bookmarks/bookmark.cpp
+++ b/src/plugins/bookmarks/bookmark.cpp
@@ -37,7 +37,7 @@ using namespace Bookmarks::Internal;
using namespace Utils;
Bookmark::Bookmark(int lineNumber, BookmarkManager *manager) :
- TextMark(FileName(), lineNumber, Constants::BOOKMARKS_TEXT_MARK_CATEGORY),
+ TextMark(FilePath(), lineNumber, Constants::BOOKMARKS_TEXT_MARK_CATEGORY),
m_manager(manager)
{
setColor(Utils::Theme::Bookmarks_TextMarkColor);
@@ -87,9 +87,9 @@ void Bookmark::updateBlock(const QTextBlock &block)
}
}
-void Bookmark::updateFileName(const FileName &fileName)
+void Bookmark::updateFileName(const FilePath &fileName)
{
- const FileName &oldFileName = this->fileName();
+ const FilePath &oldFileName = this->fileName();
TextMark::updateFileName(fileName);
m_manager->updateBookmarkFileName(this, oldFileName.toString());
}
diff --git a/src/plugins/bookmarks/bookmark.h b/src/plugins/bookmarks/bookmark.h
index 1dceba433c..b6d3cef26c 100644
--- a/src/plugins/bookmarks/bookmark.h
+++ b/src/plugins/bookmarks/bookmark.h
@@ -40,7 +40,7 @@ public:
void updateLineNumber(int lineNumber) override;
void move(int line) override;
void updateBlock(const QTextBlock &block) override;
- void updateFileName(const Utils::FileName &fileName) override;
+ void updateFileName(const Utils::FilePath &fileName) override;
void removedFromEditor() override;
bool isDraggable() const override;
diff --git a/src/plugins/bookmarks/bookmarkmanager.cpp b/src/plugins/bookmarks/bookmarkmanager.cpp
index c3b061a05b..89bb911de7 100644
--- a/src/plugins/bookmarks/bookmarkmanager.cpp
+++ b/src/plugins/bookmarks/bookmarkmanager.cpp
@@ -119,7 +119,7 @@ void BookmarkDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
painter->save();
QFontMetrics fm(opt.font);
- static int lwidth = fm.width(QLatin1String("8888")) + 18;
+ static int lwidth = fm.horizontalAdvance(QLatin1String("8888")) + 18;
QColor backgroundColor;
QColor textColor;
@@ -155,13 +155,14 @@ void BookmarkDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
QString topRight = index.data(BookmarkManager::LineNumber).toString();
// Check whether we need to be fancy and paint some background
- int fwidth = fm.width(topLeft);
+ int fwidth = fm.horizontalAdvance(topLeft);
if (fwidth + lwidth > opt.rect.width()) {
int left = opt.rect.right() - lwidth;
painter->drawPixmap(left, opt.rect.top(), selected ? m_selectedPixmap : m_normalPixmap);
}
// topRight
- painter->drawText(opt.rect.right() - fm.width(topRight) - 6 , 2 + opt.rect.top() + fm.ascent(), topRight);
+ painter->drawText(opt.rect.right() - fm.horizontalAdvance(topRight) - 6,
+ 2 + opt.rect.top() + fm.ascent(), topRight);
// Directory
QColor mix;
@@ -330,7 +331,7 @@ QItemSelectionModel *BookmarkManager::selectionModel() const
return m_selectionModel;
}
-bool BookmarkManager::hasBookmarkInPosition(const Utils::FileName &fileName, int lineNumber)
+bool BookmarkManager::hasBookmarkInPosition(const Utils::FilePath &fileName, int lineNumber)
{
return findBookmark(fileName, lineNumber);
}
@@ -413,7 +414,7 @@ QMimeData *BookmarkManager::mimeData(const QModelIndexList &indexes) const
return data;
}
-void BookmarkManager::toggleBookmark(const FileName &fileName, int lineNumber)
+void BookmarkManager::toggleBookmark(const FilePath &fileName, int lineNumber)
{
if (lineNumber <= 0 || fileName.isEmpty())
return;
@@ -449,7 +450,7 @@ void BookmarkManager::updateBookmarkFileName(Bookmark *bookmark, const QString &
if (oldFileName == bookmark->fileName().toString())
return;
- m_bookmarksMap[Utils::FileName::fromString(oldFileName)].removeAll(bookmark);
+ m_bookmarksMap[Utils::FilePath::fromString(oldFileName)].removeAll(bookmark);
m_bookmarksMap[bookmark->fileName()].append(bookmark);
updateBookmark(bookmark);
}
@@ -516,7 +517,7 @@ void BookmarkManager::documentPrevNext(bool next)
if (editorLine <= 0)
return;
- const FileName filePath = editor->document()->filePath();
+ const FilePath filePath = editor->document()->filePath();
if (!m_bookmarksMap.contains(filePath))
return;
@@ -663,7 +664,7 @@ void BookmarkManager::moveDown()
saveBookmarks();
}
-void BookmarkManager::editByFileAndLine(const FileName &fileName, int lineNumber)
+void BookmarkManager::editByFileAndLine(const FilePath &fileName, int lineNumber)
{
Bookmark *b = findBookmark(fileName, lineNumber);
QModelIndex current = selectionModel()->currentIndex();
@@ -702,7 +703,7 @@ void BookmarkManager::edit()
}
/* Returns the bookmark at the given file and line number, or 0 if no such bookmark exists. */
-Bookmark *BookmarkManager::findBookmark(const FileName &filePath, int lineNumber)
+Bookmark *BookmarkManager::findBookmark(const FilePath &filePath, int lineNumber)
{
return Utils::findOrDefault(m_bookmarksMap.value(filePath),
Utils::equal(&Bookmark::lineNumber, lineNumber));
@@ -748,9 +749,9 @@ void BookmarkManager::addBookmark(const QString &s)
const QString &filePath = s.mid(index1+1, index2-index1-1);
const QString &note = s.mid(index3 + 1);
const int lineNumber = s.midRef(index2 + 1, index3 - index2 - 1).toInt();
- if (!filePath.isEmpty() && !findBookmark(FileName::fromString(filePath), lineNumber)) {
+ if (!filePath.isEmpty() && !findBookmark(FilePath::fromString(filePath), lineNumber)) {
auto b = new Bookmark(lineNumber, this);
- b->updateFileName(FileName::fromString(filePath));
+ b->updateFileName(FilePath::fromString(filePath));
b->setNote(note);
addBookmark(b, false);
}
diff --git a/src/plugins/bookmarks/bookmarkmanager.h b/src/plugins/bookmarks/bookmarkmanager.h
index c1cbef10f3..24ff63742b 100644
--- a/src/plugins/bookmarks/bookmarkmanager.h
+++ b/src/plugins/bookmarks/bookmarkmanager.h
@@ -77,7 +77,7 @@ public:
// this QItemSelectionModel is shared by all views
QItemSelectionModel *selectionModel() const;
- bool hasBookmarkInPosition(const Utils::FileName &fileName, int lineNumber);
+ bool hasBookmarkInPosition(const Utils::FilePath &fileName, int lineNumber);
enum Roles {
Filename = Qt::UserRole,
@@ -87,7 +87,7 @@ public:
Note = Qt::UserRole + 4
};
- void toggleBookmark(const Utils::FileName &fileName, int lineNumber);
+ void toggleBookmark(const Utils::FilePath &fileName, int lineNumber);
void nextInDocument();
void prevInDocument();
void next();
@@ -95,7 +95,7 @@ public:
void moveUp();
void moveDown();
void edit();
- void editByFileAndLine(const Utils::FileName &fileName, int lineNumber);
+ void editByFileAndLine(const Utils::FilePath &fileName, int lineNumber);
bool gotoBookmark(const Bookmark *bookmark) const;
signals:
@@ -109,14 +109,14 @@ private:
void documentPrevNext(bool next);
- Bookmark *findBookmark(const Utils::FileName &filePath, int lineNumber);
+ Bookmark *findBookmark(const Utils::FilePath &filePath, int lineNumber);
void insertBookmark(int index, Bookmark *bookmark, bool userset = true);
void addBookmark(Bookmark *bookmark, bool userset = true);
void addBookmark(const QString &s);
static QString bookmarkToString(const Bookmark *b);
void saveBookmarks();
- QMap<Utils::FileName, QVector<Bookmark *>> m_bookmarksMap;
+ QMap<Utils::FilePath, QVector<Bookmark *>> m_bookmarksMap;
QList<Bookmark *> m_bookmarksList;
QItemSelectionModel *m_selectionModel;
diff --git a/src/plugins/bookmarks/bookmarksplugin.cpp b/src/plugins/bookmarks/bookmarksplugin.cpp
index 344313d8f0..06eb6b49c9 100644
--- a/src/plugins/bookmarks/bookmarksplugin.cpp
+++ b/src/plugins/bookmarks/bookmarksplugin.cpp
@@ -54,10 +54,10 @@ using namespace Bookmarks::Constants;
namespace Bookmarks {
namespace Internal {
-class BookmarksPluginRunData : public QObject
+class BookmarksPluginPrivate : public QObject
{
public:
- BookmarksPluginRunData();
+ BookmarksPluginPrivate();
void updateActions(bool enableToggle, int stateMask);
void editorOpened(Core::IEditor *editor);
@@ -79,21 +79,21 @@ public:
QAction m_bookmarkMarginAction{BookmarksPlugin::tr("Toggle Bookmark"), nullptr};
int m_marginActionLineNumber = 0;
- Utils::FileName m_marginActionFileName;
+ Utils::FilePath m_marginActionFileName;
};
BookmarksPlugin::~BookmarksPlugin()
{
- delete m_runData;
+ delete d;
}
bool BookmarksPlugin::initialize(const QStringList &, QString *)
{
- m_runData = new BookmarksPluginRunData;
+ d = new BookmarksPluginPrivate;
return true;
}
-BookmarksPluginRunData::BookmarksPluginRunData()
+BookmarksPluginPrivate::BookmarksPluginPrivate()
: m_bookmarkFilter(&m_bookmarkManager)
, m_bookmarkViewFactory(&m_bookmarkManager)
{
@@ -162,7 +162,7 @@ BookmarksPluginRunData::BookmarksPluginRunData()
});
connect(&m_bookmarkManager, &BookmarkManager::updateActions,
- this, &BookmarksPluginRunData::updateActions);
+ this, &BookmarksPluginPrivate::updateActions);
updateActions(false, m_bookmarkManager.state());
connect(&m_bookmarkMarginAction, &QAction::triggered, this, [this] {
@@ -171,12 +171,12 @@ BookmarksPluginRunData::BookmarksPluginRunData()
// EditorManager
connect(EditorManager::instance(), &EditorManager::editorAboutToClose,
- this, &BookmarksPluginRunData::editorAboutToClose);
+ this, &BookmarksPluginPrivate::editorAboutToClose);
connect(EditorManager::instance(), &EditorManager::editorOpened,
- this, &BookmarksPluginRunData::editorOpened);
+ this, &BookmarksPluginPrivate::editorOpened);
}
-void BookmarksPluginRunData::updateActions(bool enableToggle, int state)
+void BookmarksPluginPrivate::updateActions(bool enableToggle, int state)
{
const bool hasbm = state >= BookmarkManager::HasBookMarks;
const bool hasdocbm = state == BookmarkManager::HasBookmarksInDocument;
@@ -188,7 +188,7 @@ void BookmarksPluginRunData::updateActions(bool enableToggle, int state)
m_docNextAction.setEnabled(hasdocbm);
}
-void BookmarksPluginRunData::editorOpened(IEditor *editor)
+void BookmarksPluginPrivate::editorOpened(IEditor *editor)
{
if (auto widget = qobject_cast<TextEditorWidget *>(editor->widget())) {
connect(widget, &TextEditorWidget::markRequested,
@@ -198,19 +198,19 @@ void BookmarksPluginRunData::editorOpened(IEditor *editor)
});
connect(widget, &TextEditorWidget::markContextMenuRequested,
- this, &BookmarksPluginRunData::requestContextMenu);
+ this, &BookmarksPluginPrivate::requestContextMenu);
}
}
-void BookmarksPluginRunData::editorAboutToClose(IEditor *editor)
+void BookmarksPluginPrivate::editorAboutToClose(IEditor *editor)
{
if (auto widget = qobject_cast<TextEditorWidget *>(editor->widget())) {
disconnect(widget, &TextEditorWidget::markContextMenuRequested,
- this, &BookmarksPluginRunData::requestContextMenu);
+ this, &BookmarksPluginPrivate::requestContextMenu);
}
}
-void BookmarksPluginRunData::requestContextMenu(TextEditorWidget *widget,
+void BookmarksPluginPrivate::requestContextMenu(TextEditorWidget *widget,
int lineNumber, QMenu *menu)
{
if (widget->textDocument()->isTemporary())
diff --git a/src/plugins/bookmarks/bookmarksplugin.h b/src/plugins/bookmarks/bookmarksplugin.h
index 348bbd2328..2d97e823ff 100644
--- a/src/plugins/bookmarks/bookmarksplugin.h
+++ b/src/plugins/bookmarks/bookmarksplugin.h
@@ -30,22 +30,17 @@
namespace Bookmarks {
namespace Internal {
-class BookmarksPluginRunData;
-
class BookmarksPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Bookmarks.json")
-public:
- BookmarksPlugin() = default;
~BookmarksPlugin() final;
-private:
bool initialize(const QStringList &arguments, QString *errorMessage) final;
void extensionsInitialized() final {}
- BookmarksPluginRunData *m_runData = nullptr;
+ class BookmarksPluginPrivate *d = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/CMakeLists.txt b/src/plugins/clangcodemodel/CMakeLists.txt
new file mode 100644
index 0000000000..56ee68416d
--- /dev/null
+++ b/src/plugins/clangcodemodel/CMakeLists.txt
@@ -0,0 +1,57 @@
+if (WITH_TESTS)
+ set(TST_COMPONENT CppEditor QmakeProjectManager)
+endif()
+
+add_qtc_plugin(ClangCodeModel
+ CONDITION TARGET libclang
+ DEPENDS ClangSupport CPlusPlus
+ PLUGIN_DEPENDS Core CppTools TextEditor ${TST_COMPONENT}
+ 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
+ clangdiagnosticfilter.cpp clangdiagnosticfilter.h
+ clangdiagnosticmanager.cpp clangdiagnosticmanager.h
+ clangdiagnostictooltipwidget.cpp clangdiagnostictooltipwidget.h
+ clangeditordocumentparser.cpp clangeditordocumentparser.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
+ EXPLICIT_MOC clangcodemodelplugin.h
+)
+
+extend_qtc_plugin(ClangCodeModel
+ CONDITION WITH_TESTS
+ SOURCES
+ test/clangautomationutils.cpp test/clangautomationutils.h
+ test/clangbatchfileprocessor.cpp test/clangbatchfileprocessor.h
+ test/clangcodecompletion_test.cpp test/clangcodecompletion_test.h
+ test/data/clangtestdata.qrc
+)
diff --git a/src/plugins/clangcodemodel/a.cmd b/src/plugins/clangcodemodel/a.cmd
new file mode 100644
index 0000000000..95eb37f90a
--- /dev/null
+++ b/src/plugins/clangcodemodel/a.cmd
@@ -0,0 +1,4 @@
+git checkout -- clangcodemodelplugin.h
+git checkout -- clangcompletionassistinterface.cpp
+git checkout -- clangcompletionassistinterface.h
+git checkout -- clangcompletionassistprocessor.cpp
diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp
index 79638b0b98..7c28952389 100644
--- a/src/plugins/clangcodemodel/clangassistproposalitem.cpp
+++ b/src/plugins/clangcodemodel/clangassistproposalitem.cpp
@@ -151,6 +151,19 @@ static bool skipParenForFunctionLikeSnippet(const std::vector<int> &placeholderP
&& 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
{
@@ -232,8 +245,12 @@ void ClangAssistProposalItem::apply(TextDocumentManipulatorInterface &manipulato
cursor.setPosition(basePosition);
abandonParen = QString("(;,{}").contains(prevChar);
}
- if (!abandonParen)
- abandonParen = isAtUsingDeclaration(manipulator, basePosition);
+ 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();
@@ -489,6 +506,17 @@ QString ClangAssistProposalItem::detail() const
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;
diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.h b/src/plugins/clangcodemodel/clangassistproposalitem.h
index 5867b94fcb..64eb8789b3 100644
--- a/src/plugins/clangcodemodel/clangassistproposalitem.h
+++ b/src/plugins/clangcodemodel/clangassistproposalitem.h
@@ -47,6 +47,8 @@ public:
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;
diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
index a4a1591cf4..6c5ae3cb4b 100644
--- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
+++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
@@ -36,6 +36,8 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/messagemanager.h>
+#include <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/cppmodelmanager.h>
@@ -71,9 +73,11 @@ void ClangCodeModelPlugin::generateCompilationDB() {
if (!project || !project->activeTarget())
return;
- m_generatorWatcher.setFuture(
- QtConcurrent::run(&Utils::generateCompilationDB,
- CppModelManager::instance()->projectInfo(project)));
+ QFuture<Utils::GenerateCompilationDbResult> task
+ = QtConcurrent::run(&Utils::generateCompilationDB,
+ CppModelManager::instance()->projectInfo(project));
+ Core::ProgressManager::addTask(task, tr("Generating Compilation DB"), "generate compilation db");
+ m_generatorWatcher.setFuture(task);
}
static bool isDBGenerationEnabled(ProjectExplorer::Project *project)
@@ -133,7 +137,17 @@ void ClangCodeModelPlugin::createCompilationDBButton()
command->setDescription(m_generateCompilationDBAction->text());
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
- connect(&m_generatorWatcher, &QFutureWatcher<void>::finished, this, [this] () {
+ connect(&m_generatorWatcher, &QFutureWatcher<Utils::GenerateCompilationDbResult>::finished,
+ this, [this] () {
+ const Utils::GenerateCompilationDbResult result = m_generatorWatcher.result();
+ QString message;
+ if (result.error.isEmpty()) {
+ message = tr("Clang compilation database generated at \"%1\".")
+ .arg(QDir::toNativeSeparators(result.filePath));
+ } else {
+ message = tr("Generating Clang compilation database failed: %1").arg(result.error);
+ }
+ Core::MessageManager::write(message, Core::MessageManager::Flash);
m_generateCompilationDBAction->setEnabled(
isDBGenerationEnabled(ProjectExplorer::SessionManager::startupProject()));
});
@@ -187,7 +201,7 @@ void ClangCodeModelPlugin::maybeHandleBatchFileAndExit() const
}
#ifdef WITH_TESTS
-QList<QObject *> ClangCodeModelPlugin::createTestObjects() const
+QVector<QObject *> ClangCodeModelPlugin::createTestObjects() const
{
return {
new Tests::ClangCodeCompletionTest,
diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.h b/src/plugins/clangcodemodel/clangcodemodelplugin.h
index 375007f9c7..7504cdbc54 100644
--- a/src/plugins/clangcodemodel/clangcodemodelplugin.h
+++ b/src/plugins/clangcodemodel/clangcodemodelplugin.h
@@ -26,6 +26,7 @@
#pragma once
#include "clangmodelmanagersupport.h"
+#include "clangutils.h"
#include <extensionsystem/iplugin.h>
@@ -54,10 +55,10 @@ private:
void createCompilationDBButton();
ClangModelManagerSupportProvider m_modelManagerSupportProvider;
- Utils::ParameterAction *m_generateCompilationDBAction = nullptr;
- QFutureWatcher<void> m_generatorWatcher;
+ ::Utils::ParameterAction *m_generateCompilationDBAction = nullptr;
+ QFutureWatcher<Utils::GenerateCompilationDbResult> m_generatorWatcher;
#ifdef WITH_TESTS
- QList<QObject *> createTestObjects() const override;
+ QVector<QObject *> createTestObjects() const override;
#endif
};
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
index 5af48386bd..ad5ee50476 100644
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp
@@ -47,7 +47,7 @@ void CompletionChunksToTextConverter::parseChunks(
m_codeCompletionChunks.cend(),
[this] (const ClangBackEnd::CodeCompletionChunk &chunk)
{
- parseDependendOnTheOptionalState(chunk);
+ parseDependentOnTheOptionalState(chunk);
m_previousCodeCompletionChunk = chunk;
});
}
@@ -200,7 +200,7 @@ void CompletionChunksToTextConverter::parse(
}
}
-void CompletionChunksToTextConverter::parseDependendOnTheOptionalState(
+void CompletionChunksToTextConverter::parseDependentOnTheOptionalState(
const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
{
wrapInCursiveTagIfOptional(codeCompletionChunk);
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
index 88654ed3fd..09ad15e30f 100644
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
+++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
@@ -75,7 +75,7 @@ public:
private:
void parse(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
- void parseDependendOnTheOptionalState(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);
diff --git a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp
index 702d4557b6..cd90c29fb4 100644
--- a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp
+++ b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp
@@ -76,7 +76,7 @@ static Core::LocatorFilterEntry makeEntry(Core::ILocatorFilter *filter,
const ClangBackEnd::ExtraInfo &extraInfo = info.extraInfo;
QString displayName = extraInfo.token;
::Utils::LineColumn lineColumn(static_cast<int>(info.line), static_cast<int>(info.column));
- Core::LocatorFilterEntry entry(filter, displayName, qVariantFromValue(lineColumn));
+ Core::LocatorFilterEntry entry(filter, displayName, QVariant::fromValue(lineColumn));
QString extra;
ClangBackEnd::HighlightingType mainType = info.types.mainHighlightingType;
if (mainType == ClangBackEnd::HighlightingType::VirtualFunction
diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
index 8fcbe3477b..6e1873c4b5 100644
--- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
+++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
@@ -301,10 +301,10 @@ void ClangDiagnosticManager::generateFixItAvailableMarkers()
static void addTask(const ClangBackEnd::DiagnosticContainer &diagnostic, bool isChild = false)
{
using namespace ProjectExplorer;
- using ::Utils::FileName;
+ using ::Utils::FilePath;
Task::TaskType taskType = ProjectExplorer::Task::TaskType::Unknown;
- FileName iconPath;
+ FilePath iconPath;
QIcon icon;
if (!isChild) {
@@ -325,7 +325,7 @@ static void addTask(const ClangBackEnd::DiagnosticContainer &diagnostic, bool is
TaskHub::addTask(Task(taskType,
Utils::diagnosticCategoryPrefixRemoved(diagnostic.text.toString()),
- FileName::fromString(diagnostic.location.filePath.toString()),
+ FilePath::fromString(diagnostic.location.filePath.toString()),
diagnostic.location.line,
Constants::TASK_CATEGORY_DIAGNOSTICS,
icon,
@@ -452,7 +452,7 @@ void ClangDiagnosticManager::addClangTextMarks(
m_clangTextMarks.erase(it, m_clangTextMarks.end());
delete mark;
};
- auto textMark = new ClangTextMark(::Utils::FileName::fromString(filePath()),
+ auto textMark = new ClangTextMark(::Utils::FilePath::fromString(filePath()),
diagnostic,
onMarkRemoved,
m_fullVisualization);
diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
index f2e52c1fd0..5151279a28 100644
--- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
+++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
@@ -387,14 +387,10 @@ private:
static int widthLimit()
{
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
auto screen = QGuiApplication::screenAt(QCursor::pos());
if (!screen)
screen = QGuiApplication::primaryScreen();
return screen->availableGeometry().width() / 2;
-#else
- return QApplication::desktop()->availableGeometry(QCursor::pos()).width() / 2;
-#endif
}
private:
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
index 706c5101a3..8fd2508315 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -527,14 +527,14 @@ private:
return;
m_options.append(CppTools::XclangArgs({"-add-plugin",
- "clang-lazy",
- "-plugin-arg-clang-lazy",
+ "clazy",
+ "-plugin-arg-clazy",
"enable-all-fixits",
- "-plugin-arg-clang-lazy",
+ "-plugin-arg-clazy",
"no-autowrite-fixits",
- "-plugin-arg-clang-lazy",
+ "-plugin-arg-clazy",
checks,
- "-plugin-arg-clang-lazy",
+ "-plugin-arg-clazy",
"ignore-included-files"}));
}
diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp
index f1113de164..e03a2b904c 100644
--- a/src/plugins/clangcodemodel/clangfollowsymbol.cpp
+++ b/src/plugins/clangcodemodel/clangfollowsymbol.cpp
@@ -159,7 +159,7 @@ static ::Utils::ProcessLinkCallback extendedCallback(::Utils::ProcessLinkCallbac
};
}
-static bool isSameInvocationContext(const Utils::FileName &filePath)
+static bool isSameInvocationContext(const Utils::FilePath &filePath)
{
return TextEditor::BaseTextEditor::currentTextEditor()->editorWidget()->isVisible()
&& Core::EditorManager::currentDocument()->filePath() == filePath;
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index f629e743bc..7907abdfed 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -154,7 +154,7 @@ void ClangModelManagerSupport::onCurrentEditorChanged(Core::IEditor *editor)
if (!editor || !editor->document() || !cppModelManager()->isCppEditor(editor))
return;
- const ::Utils::FileName filePath = editor->document()->filePath();
+ const ::Utils::FilePath filePath = editor->document()->filePath();
if (auto processor = ClangEditorDocumentProcessor::get(filePath.toString()))
processor->generateTaskHubIssues();
}
diff --git a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp
index 72c6c2dd09..1d7a5d96f9 100644
--- a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp
+++ b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp
@@ -131,6 +131,11 @@ QString ClangPreprocessorAssistProposalItem::detail() const
return QString();
}
+Qt::TextFormat ClangPreprocessorAssistProposalItem::detailFormat() const
+{
+ return Qt::RichText;
+}
+
bool ClangPreprocessorAssistProposalItem::isSnippet() const
{
return false;
diff --git a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h
index 1a5ee440a0..86073211be 100644
--- a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h
+++ b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h
@@ -51,6 +51,8 @@ public:
void setDetail(const QString &detail);
QString detail() const final;
+ Qt::TextFormat detailFormat() const final;
+
bool isSnippet() const final;
bool isValid() const final;
diff --git a/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp b/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp
index 09caba4a2d..a4bd50e546 100644
--- a/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp
+++ b/src/plugins/clangcodemodel/clangprojectsettingswidget.cpp
@@ -68,7 +68,7 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project
connect(m_ui.delayedTemplateParseCheckBox, &QCheckBox::toggled,
this, &ClangProjectSettingsWidget::onDelayedTemplateParseClicked);
connect(m_ui.globalOrCustomComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ClangProjectSettingsWidget::onGlobalCustomChanged);
connect(project, &ProjectExplorer::Project::aboutToSaveSettings,
this, &ClangProjectSettingsWidget::onAboutToSaveProjectSettings);
diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp
index f756acf2d3..905682cd0f 100644
--- a/src/plugins/clangcodemodel/clangtextmark.cpp
+++ b/src/plugins/clangcodemodel/clangtextmark.cpp
@@ -209,7 +209,7 @@ void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticConta
} // anonymous namespace
-ClangTextMark::ClangTextMark(const FileName &fileName,
+ClangTextMark::ClangTextMark(const FilePath &fileName,
const ClangBackEnd::DiagnosticContainer &diagnostic,
const RemovedFromEditorHandler &removedHandler,
bool fullVisualization)
diff --git a/src/plugins/clangcodemodel/clangtextmark.h b/src/plugins/clangcodemodel/clangtextmark.h
index ae67bcef86..2ac2df1e91 100644
--- a/src/plugins/clangcodemodel/clangtextmark.h
+++ b/src/plugins/clangcodemodel/clangtextmark.h
@@ -40,7 +40,7 @@ class ClangTextMark : public TextEditor::TextMark
public:
using RemovedFromEditorHandler = std::function<void(ClangTextMark *)>;
- ClangTextMark(const ::Utils::FileName &fileName,
+ ClangTextMark(const ::Utils::FilePath &fileName,
const ClangBackEnd::DiagnosticContainer &diagnostic,
const RemovedFromEditorHandler &removedHandler,
bool fullVisualization);
diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp
index 599b561011..e7d7de420a 100644
--- a/src/plugins/clangcodemodel/clangutils.cpp
+++ b/src/plugins/clangcodemodel/clangutils.cpp
@@ -301,27 +301,27 @@ QString diagnosticCategoryPrefixRemoved(const QString &text)
return text;
}
-static ::Utils::FileName compilerPath(const CppTools::ProjectPart &projectPart)
+static ::Utils::FilePath compilerPath(const CppTools::ProjectPart &projectPart)
{
ProjectExplorer::Target *target = projectPart.project->activeTarget();
if (!target)
- return ::Utils::FileName();
+ return ::Utils::FilePath();
- ProjectExplorer::ToolChain *toolchain = ProjectExplorer::ToolChainKitInformation::toolChain(
+ ProjectExplorer::ToolChain *toolchain = ProjectExplorer::ToolChainKitAspect::toolChain(
target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
return toolchain->compilerCommand();
}
-static ::Utils::FileName buildDirectory(const ProjectExplorer::Project &project)
+static ::Utils::FilePath buildDirectory(const ProjectExplorer::Project &project)
{
ProjectExplorer::Target *target = project.activeTarget();
if (!target)
- return ::Utils::FileName();
+ return ::Utils::FilePath();
ProjectExplorer::BuildConfiguration *buildConfig = target->activeBuildConfiguration();
if (!buildConfig)
- return ::Utils::FileName();
+ return ::Utils::FilePath();
return buildConfig->buildDirectory();
}
@@ -356,7 +356,7 @@ static QStringList projectPartArguments(const ProjectPart &projectPart)
return args;
}
-static QJsonObject createFileObject(const ::Utils::FileName &buildDir,
+static QJsonObject createFileObject(const ::Utils::FilePath &buildDir,
const QStringList &arguments,
const ProjectPart &projectPart,
const ProjectFile &projFile)
@@ -386,18 +386,22 @@ static QJsonObject createFileObject(const ::Utils::FileName &buildDir,
return fileObject;
}
-void generateCompilationDB(CppTools::ProjectInfo projectInfo)
+GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo)
{
- const ::Utils::FileName buildDir = buildDirectory(*projectInfo.project());
- QTC_ASSERT(!buildDir.isEmpty(), return;);
+ const ::Utils::FilePath buildDir = buildDirectory(*projectInfo.project());
+ QTC_ASSERT(!buildDir.isEmpty(), return GenerateCompilationDbResult(QString(),
+ QCoreApplication::translate("ClangUtils", "Could not retrieve build directory.")));
QDir dir(buildDir.toString());
if (!dir.exists())
dir.mkpath(dir.path());
QFile compileCommandsFile(buildDir.toString() + "/compile_commands.json");
const bool fileOpened = compileCommandsFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
- if (!fileOpened)
- return;
+ if (!fileOpened) {
+ return GenerateCompilationDbResult(QString(),
+ QCoreApplication::translate("ClangUtils", "Could not create \"%1\": %2")
+ .arg(compileCommandsFile.fileName(), compileCommandsFile.errorString()));
+ }
compileCommandsFile.write("[");
for (ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
@@ -412,6 +416,7 @@ void generateCompilationDB(CppTools::ProjectInfo projectInfo)
compileCommandsFile.write("\n]");
compileCommandsFile.close();
+ return GenerateCompilationDbResult(compileCommandsFile.fileName(), QString());
}
QString currentCppEditorDocumentFilePath()
diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h
index 8ced14f5ad..98b31f0e23 100644
--- a/src/plugins/clangcodemodel/clangutils.h
+++ b/src/plugins/clangcodemodel/clangutils.h
@@ -42,7 +42,7 @@ class ProjectInfo;
}
namespace Utils {
-class FileName;
+class FilePath;
}
namespace ClangBackEnd { class TokenInfoContainer; }
@@ -70,7 +70,19 @@ QString diagnosticCategoryPrefixRemoved(const QString &text);
::Utils::CodeModelIcon::Type iconTypeForToken(const ClangBackEnd::TokenInfoContainer &token);
-void generateCompilationDB(CppTools::ProjectInfo projectInfo);
+class GenerateCompilationDbResult
+{
+public:
+ GenerateCompilationDbResult() = default;
+ GenerateCompilationDbResult(const QString &filePath, const QString &error)
+ : filePath(filePath), error(error)
+ {}
+
+ QString filePath;
+ QString error;
+};
+
+GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo);
class DiagnosticTextInfo
{
diff --git a/src/plugins/clangformat/CMakeLists.txt b/src/plugins/clangformat/CMakeLists.txt
new file mode 100644
index 0000000000..3edaead757
--- /dev/null
+++ b/src/plugins/clangformat/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_qtc_plugin(ClangFormat
+ CONDITION TARGET libclang
+ DEPENDS Utils Qt5::Widgets clangFormat
+ INCLUDES "${CLANG_INCLUDE_DIRS}"
+ PLUGIN_DEPENDS Core TextEditor CppEditor CppTools ProjectExplorer
+ SOURCES
+ clangformatbaseindenter.cpp clangformatbaseindenter.h
+ clangformatchecks.ui
+ clangformatconfigwidget.cpp clangformatconfigwidget.h clangformatconfigwidget.ui
+ clangformatconstants.h
+ clangformatindenter.cpp clangformatindenter.h
+ clangformatplugin.cpp clangformatplugin.h
+ clangformatsettings.cpp clangformatsettings.h
+ clangformatutils.cpp clangformatutils.h
+)
diff --git a/src/plugins/clangformat/clangformat.pro b/src/plugins/clangformat/clangformat.pro
index 653dacdaba..e1ccdb98dc 100644
--- a/src/plugins/clangformat/clangformat.pro
+++ b/src/plugins/clangformat/clangformat.pro
@@ -16,8 +16,6 @@ INCLUDEPATH += $$LLVM_INCLUDEPATH
QMAKE_CXXFLAGS_WARN_ON *= $$LLVM_CXXFLAGS_WARNINGS
QMAKE_CXXFLAGS *= $$LLVM_CXXFLAGS
-# clang/Format/Format.h has intentional multiline comments
-gcc:QMAKE_CXXFLAGS *= -Wno-comment
unix:!macos:QMAKE_LFLAGS += -Wl,--exclude-libs,ALL
SOURCES += \
@@ -35,4 +33,5 @@ HEADERS += \
clangformatutils.h
FORMS += \
+ clangformatchecks.ui \
clangformatconfigwidget.ui
diff --git a/src/plugins/clangformat/clangformat.qbs b/src/plugins/clangformat/clangformat.qbs
index e5510b4630..5726412f5a 100644
--- a/src/plugins/clangformat/clangformat.qbs
+++ b/src/plugins/clangformat/clangformat.qbs
@@ -19,13 +19,7 @@ QtcPlugin {
&& libclang.llvmFormattingLibs.length
&& (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches)
- cpp.cxxFlags: {
- var res = base.concat(libclang.llvmToolingCxxFlags);
- if (qbs.toolchain.contains("gcc"))
- res.push("-Wno-comment"); // clang/Format/Format.h has intentional multiline comments
- return res;
- }
- cpp.defines: base.concat("CLANGPCHMANAGER_LIB")
+ cpp.cxxFlags: base.concat(libclang.llvmToolingCxxFlags)
cpp.includePaths: base.concat(libclang.llvmIncludeDir)
cpp.libraryPaths: base.concat(libclang.llvmLibDir)
cpp.dynamicLibraries: base.concat(libclang.llvmFormattingLibs)
@@ -34,6 +28,7 @@ QtcPlugin {
files: [
"clangformatbaseindenter.h",
"clangformatbaseindenter.cpp",
+ "clangformatchecks.ui",
"clangformatconfigwidget.cpp",
"clangformatconfigwidget.h",
"clangformatconfigwidget.ui",
diff --git a/src/plugins/clangformat/clangformatchecks.ui b/src/plugins/clangformat/clangformatchecks.ui
new file mode 100644
index 0000000000..56b1c54f48
--- /dev/null
+++ b/src/plugins/clangformat/clangformatchecks.ui
@@ -0,0 +1,3299 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClangFormat::ClangFormatChecksWidget</class>
+ <widget class="QWidget" name="ClangFormat::ClangFormatChecksWidget">
+ <property name="maximumSize">
+ <size>
+ <width>480</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <layout class="QGridLayout" name="checksLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelBasedOnStyle">
+ <property name="text">
+ <string notr="true">BasedOnStyle</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="BasedOnStyle">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">LLVM</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Google</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Chromium</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Mozilla</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">WebKit</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelAccessModifierOffset">
+ <property name="text">
+ <string notr="true">AccessModifierOffset</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="AccessModifierOffset">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setAccessModifierOffset">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="labelAlignAfterOpenBracket">
+ <property name="text">
+ <string notr="true">AlignAfterOpenBracket</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="AlignAfterOpenBracket">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Align</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">DontAlign</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">AlwaysBreak</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="labelAlignConsecutiveAssignments">
+ <property name="text">
+ <string notr="true">AlignConsecutiveAssignments</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="AlignConsecutiveAssignments">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="labelAlignConsecutiveDeclarations">
+ <property name="text">
+ <string notr="true">AlignConsecutiveDeclarations</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="AlignConsecutiveDeclarations">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="labelAlignEscapedNewlines">
+ <property name="text">
+ <string notr="true">AlignEscapedNewlines</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="AlignEscapedNewlines">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">DontAlign</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Left</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Right</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="labelAlignOperands">
+ <property name="text">
+ <string notr="true">AlignOperands</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="AlignOperands">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="labelAlignTrailingComments">
+ <property name="text">
+ <string notr="true">AlignTrailingComments</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QComboBox" name="AlignTrailingComments">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="labelAllowAllParametersOfDeclarationOnNextLine">
+ <property name="text">
+ <string notr="true">AllowAllParametersOfDeclarationOnNextLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QComboBox" name="AllowAllParametersOfDeclarationOnNextLine">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="9" column="0">
+ <widget class="QLabel" name="labelAllowShortBlocksOnASingleLine">
+ <property name="text">
+ <string notr="true">AllowShortBlocksOnASingleLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QComboBox" name="AllowShortBlocksOnASingleLine">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="10" column="0">
+ <widget class="QLabel" name="labelAllowShortCaseLabelsOnASingleLine">
+ <property name="text">
+ <string notr="true">AllowShortCaseLabelsOnASingleLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="1">
+ <widget class="QComboBox" name="AllowShortCaseLabelsOnASingleLine">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <widget class="QLabel" name="labelAllowShortFunctionsOnASingleLine">
+ <property name="text">
+ <string notr="true">AllowShortFunctionsOnASingleLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="1">
+ <widget class="QComboBox" name="AllowShortFunctionsOnASingleLine">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">InlineOnly</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Empty</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Inline</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">All</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="12" column="0">
+ <widget class="QLabel" name="labelAllowShortIfStatementsOnASingleLine">
+ <property name="text">
+ <string notr="true">AllowShortIfStatementsOnASingleLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="1">
+ <widget class="QComboBox" name="AllowShortIfStatementsOnASingleLine">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="13" column="0">
+ <widget class="QLabel" name="labelAllowShortLoopsOnASingleLine">
+ <property name="text">
+ <string notr="true">AllowShortLoopsOnASingleLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="1">
+ <widget class="QComboBox" name="AllowShortLoopsOnASingleLine">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="14" column="0">
+ <widget class="QLabel" name="labelAlwaysBreakAfterDefinitionReturnType">
+ <property name="text">
+ <string notr="true">AlwaysBreakAfterDefinitionReturnType</string>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="1">
+ <widget class="QComboBox" name="AlwaysBreakAfterDefinitionReturnType">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">All</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">TopLevel</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="15" column="0">
+ <widget class="QLabel" name="labelAlwaysBreakAfterReturnType">
+ <property name="text">
+ <string notr="true">AlwaysBreakAfterReturnType</string>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="1">
+ <widget class="QComboBox" name="AlwaysBreakAfterReturnType">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">All</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">TopLevel</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">AllDefinitions</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">TopLevelDefinitions</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="16" column="0">
+ <widget class="QLabel" name="labelAlwaysBreakBeforeMultilineStrings">
+ <property name="text">
+ <string notr="true">AlwaysBreakBeforeMultilineStrings</string>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="1">
+ <widget class="QComboBox" name="AlwaysBreakBeforeMultilineStrings">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="17" column="0">
+ <widget class="QLabel" name="labelAlwaysBreakTemplateDeclarations">
+ <property name="text">
+ <string notr="true">AlwaysBreakTemplateDeclarations</string>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="1">
+ <widget class="QComboBox" name="AlwaysBreakTemplateDeclarations">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">No</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">MultiLine</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Yes</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="18" column="0">
+ <widget class="QLabel" name="labelBinPackArguments">
+ <property name="text">
+ <string notr="true">BinPackArguments</string>
+ </property>
+ </widget>
+ </item>
+ <item row="18" column="1">
+ <widget class="QComboBox" name="BinPackArguments">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="19" column="0">
+ <widget class="QLabel" name="labelBinPackParameters">
+ <property name="text">
+ <string notr="true">BinPackParameters</string>
+ </property>
+ </widget>
+ </item>
+ <item row="19" column="1">
+ <widget class="QComboBox" name="BinPackParameters">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="20" column="0">
+ <widget class="QLabel" name="labelBraceWrapping">
+ <property name="text">
+ <string notr="true">BraceWrapping</string>
+ </property>
+ </widget>
+ </item>
+ <item row="21" column="0">
+ <widget class="QLabel" name="labelAfterClass">
+ <property name="text">
+ <string notr="true"> AfterClass</string>
+ </property>
+ </widget>
+ </item>
+ <item row="21" column="1">
+ <widget class="QComboBox" name="AfterClass">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="22" column="0">
+ <widget class="QLabel" name="labelAfterControlStatement">
+ <property name="text">
+ <string notr="true"> AfterControlStatement</string>
+ </property>
+ </widget>
+ </item>
+ <item row="22" column="1">
+ <widget class="QComboBox" name="AfterControlStatement">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="23" column="0">
+ <widget class="QLabel" name="labelAfterEnum">
+ <property name="text">
+ <string notr="true"> AfterEnum</string>
+ </property>
+ </widget>
+ </item>
+ <item row="23" column="1">
+ <widget class="QComboBox" name="AfterEnum">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="24" column="0">
+ <widget class="QLabel" name="labelAfterFunction">
+ <property name="text">
+ <string notr="true"> AfterFunction</string>
+ </property>
+ </widget>
+ </item>
+ <item row="24" column="1">
+ <widget class="QComboBox" name="AfterFunction">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="25" column="0">
+ <widget class="QLabel" name="labelAfterNamespace">
+ <property name="text">
+ <string notr="true"> AfterNamespace</string>
+ </property>
+ </widget>
+ </item>
+ <item row="25" column="1">
+ <widget class="QComboBox" name="AfterNamespace">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="26" column="0">
+ <widget class="QLabel" name="labelAfterObjCDeclaration">
+ <property name="text">
+ <string notr="true"> AfterObjCDeclaration</string>
+ </property>
+ </widget>
+ </item>
+ <item row="26" column="1">
+ <widget class="QComboBox" name="AfterObjCDeclaration">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="27" column="0">
+ <widget class="QLabel" name="labelAfterStruct">
+ <property name="text">
+ <string notr="true"> AfterStruct</string>
+ </property>
+ </widget>
+ </item>
+ <item row="27" column="1">
+ <widget class="QComboBox" name="AfterStruct">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="28" column="0">
+ <widget class="QLabel" name="labelAfterUnion">
+ <property name="text">
+ <string notr="true"> AfterUnion</string>
+ </property>
+ </widget>
+ </item>
+ <item row="28" column="1">
+ <widget class="QComboBox" name="AfterUnion">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="29" column="0">
+ <widget class="QLabel" name="labelAfterExternBlock">
+ <property name="text">
+ <string notr="true"> AfterExternBlock</string>
+ </property>
+ </widget>
+ </item>
+ <item row="29" column="1">
+ <widget class="QComboBox" name="AfterExternBlock">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="30" column="0">
+ <widget class="QLabel" name="labelBeforeCatch">
+ <property name="text">
+ <string notr="true"> BeforeCatch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="30" column="1">
+ <widget class="QComboBox" name="BeforeCatch">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="31" column="0">
+ <widget class="QLabel" name="labelBeforeElse">
+ <property name="text">
+ <string notr="true"> BeforeElse</string>
+ </property>
+ </widget>
+ </item>
+ <item row="31" column="1">
+ <widget class="QComboBox" name="BeforeElse">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="32" column="0">
+ <widget class="QLabel" name="labelIndentBraces">
+ <property name="text">
+ <string notr="true"> IndentBraces</string>
+ </property>
+ </widget>
+ </item>
+ <item row="32" column="1">
+ <widget class="QComboBox" name="IndentBraces">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="33" column="0">
+ <widget class="QLabel" name="labelSplitEmptyFunction">
+ <property name="text">
+ <string notr="true"> SplitEmptyFunction</string>
+ </property>
+ </widget>
+ </item>
+ <item row="33" column="1">
+ <widget class="QComboBox" name="SplitEmptyFunction">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="34" column="0">
+ <widget class="QLabel" name="labelSplitEmptyRecord">
+ <property name="text">
+ <string notr="true"> SplitEmptyRecord</string>
+ </property>
+ </widget>
+ </item>
+ <item row="34" column="1">
+ <widget class="QComboBox" name="SplitEmptyRecord">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="35" column="0">
+ <widget class="QLabel" name="labelSplitEmptyNamespace">
+ <property name="text">
+ <string notr="true"> SplitEmptyNamespace</string>
+ </property>
+ </widget>
+ </item>
+ <item row="35" column="1">
+ <widget class="QComboBox" name="SplitEmptyNamespace">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="36" column="0">
+ <widget class="QLabel" name="labelBreakAfterJavaFieldAnnotations">
+ <property name="text">
+ <string notr="true">BreakAfterJavaFieldAnnotations</string>
+ </property>
+ </widget>
+ </item>
+ <item row="36" column="1">
+ <widget class="QComboBox" name="BreakAfterJavaFieldAnnotations">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="37" column="0">
+ <widget class="QLabel" name="labelBreakBeforeBinaryOperators">
+ <property name="text">
+ <string notr="true">BreakBeforeBinaryOperators</string>
+ </property>
+ </widget>
+ </item>
+ <item row="37" column="1">
+ <widget class="QComboBox" name="BreakBeforeBinaryOperators">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">NonAssignment</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">All</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="38" column="0">
+ <widget class="QLabel" name="labelBreakBeforeBraces">
+ <property name="text">
+ <string notr="true">BreakBeforeBraces</string>
+ </property>
+ </widget>
+ </item>
+ <item row="38" column="1">
+ <widget class="QComboBox" name="BreakBeforeBraces">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Attach</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Linux</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Mozilla</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Stroustrup</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Allman</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">GNU</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">WebKit</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Custom</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="39" column="0">
+ <widget class="QLabel" name="labelBreakBeforeTernaryOperators">
+ <property name="text">
+ <string notr="true">BreakBeforeTernaryOperators</string>
+ </property>
+ </widget>
+ </item>
+ <item row="39" column="1">
+ <widget class="QComboBox" name="BreakBeforeTernaryOperators">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="40" column="0">
+ <widget class="QLabel" name="labelBreakConstructorInitializers">
+ <property name="text">
+ <string notr="true">BreakConstructorInitializers</string>
+ </property>
+ </widget>
+ </item>
+ <item row="40" column="1">
+ <widget class="QComboBox" name="BreakConstructorInitializers">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">BeforeColon</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">BeforeComma</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">AfterColon</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="41" column="0">
+ <widget class="QLabel" name="labelBreakInheritanceList">
+ <property name="text">
+ <string notr="true">BreakInheritanceList</string>
+ </property>
+ </widget>
+ </item>
+ <item row="41" column="1">
+ <widget class="QComboBox" name="BreakInheritanceList">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">BeforeColon</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">BeforeComma</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">AfterColon</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="42" column="0">
+ <widget class="QLabel" name="labelBreakStringLiterals">
+ <property name="text">
+ <string notr="true">BreakStringLiterals</string>
+ </property>
+ </widget>
+ </item>
+ <item row="42" column="1">
+ <widget class="QComboBox" name="BreakStringLiterals">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="43" column="0">
+ <widget class="QLabel" name="labelColumnLimit">
+ <property name="text">
+ <string notr="true">ColumnLimit</string>
+ </property>
+ </widget>
+ </item>
+ <item row="43" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="ColumnLimit">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setColumnLimit">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="44" column="0">
+ <widget class="QLabel" name="labelCommentPragmas">
+ <property name="text">
+ <string notr="true">CommentPragmas</string>
+ </property>
+ </widget>
+ </item>
+ <item row="44" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="CommentPragmas">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setCommentPragmas">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="45" column="0">
+ <widget class="QLabel" name="labelCompactNamespaces">
+ <property name="text">
+ <string notr="true">CompactNamespaces</string>
+ </property>
+ </widget>
+ </item>
+ <item row="45" column="1">
+ <widget class="QComboBox" name="CompactNamespaces">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="46" column="0">
+ <widget class="QLabel" name="labelConstructorInitializerAllOnOneLineOrOnePerLine">
+ <property name="text">
+ <string notr="true">ConstructorInitializerAllOnOneLineOrOnePerLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="46" column="1">
+ <widget class="QComboBox" name="ConstructorInitializerAllOnOneLineOrOnePerLine">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="47" column="0">
+ <widget class="QLabel" name="labelConstructorInitializerIndentWidth">
+ <property name="text">
+ <string notr="true">ConstructorInitializerIndentWidth</string>
+ </property>
+ </widget>
+ </item>
+ <item row="47" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="ConstructorInitializerIndentWidth">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setConstructorInitializerIndentWidth">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="48" column="0">
+ <widget class="QLabel" name="labelContinuationIndentWidth">
+ <property name="text">
+ <string notr="true">ContinuationIndentWidth</string>
+ </property>
+ </widget>
+ </item>
+ <item row="48" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="ContinuationIndentWidth">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setContinuationIndentWidth">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="49" column="0">
+ <widget class="QLabel" name="labelCpp11BracedListStyle">
+ <property name="text">
+ <string notr="true">Cpp11BracedListStyle</string>
+ </property>
+ </widget>
+ </item>
+ <item row="49" column="1">
+ <widget class="QComboBox" name="Cpp11BracedListStyle">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="50" column="0">
+ <widget class="QLabel" name="labelDerivePointerAlignment">
+ <property name="text">
+ <string notr="true">DerivePointerAlignment</string>
+ </property>
+ </widget>
+ </item>
+ <item row="50" column="1">
+ <widget class="QComboBox" name="DerivePointerAlignment">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="51" column="0">
+ <widget class="QLabel" name="labelDisableFormat">
+ <property name="text">
+ <string notr="true">DisableFormat</string>
+ </property>
+ </widget>
+ </item>
+ <item row="51" column="1">
+ <widget class="QComboBox" name="DisableFormat">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="52" column="0">
+ <widget class="QLabel" name="labelExperimentalAutoDetectBinPacking">
+ <property name="text">
+ <string notr="true">ExperimentalAutoDetectBinPacking</string>
+ </property>
+ </widget>
+ </item>
+ <item row="52" column="1">
+ <widget class="QComboBox" name="ExperimentalAutoDetectBinPacking">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="53" column="0">
+ <widget class="QLabel" name="labelFixNamespaceComments">
+ <property name="text">
+ <string notr="true">FixNamespaceComments</string>
+ </property>
+ </widget>
+ </item>
+ <item row="53" column="1">
+ <widget class="QComboBox" name="FixNamespaceComments">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="54" column="0">
+ <widget class="QLabel" name="labelForEachMacros">
+ <property name="text">
+ <string notr="true">ForEachMacros</string>
+ </property>
+ </widget>
+ </item>
+ <item row="54" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPlainTextEdit" name="ForEachMacros">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setForEachMacros">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="55" column="0">
+ <widget class="QLabel" name="labelIncludeBlocks">
+ <property name="text">
+ <string notr="true">IncludeBlocks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="55" column="1">
+ <widget class="QComboBox" name="IncludeBlocks">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Preserve</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Merge</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Regroup</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="56" column="0">
+ <widget class="QLabel" name="labelIncludeCategories">
+ <property name="text">
+ <string notr="true">IncludeCategories</string>
+ </property>
+ </widget>
+ </item>
+ <item row="56" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPlainTextEdit" name="IncludeCategories">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setIncludeCategories">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="57" column="0">
+ <widget class="QLabel" name="labelIncludeIsMainRegex">
+ <property name="text">
+ <string notr="true">IncludeIsMainRegex</string>
+ </property>
+ </widget>
+ </item>
+ <item row="57" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="IncludeIsMainRegex">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setIncludeIsMainRegex">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="58" column="0">
+ <widget class="QLabel" name="labelIndentCaseLabels">
+ <property name="text">
+ <string notr="true">IndentCaseLabels</string>
+ </property>
+ </widget>
+ </item>
+ <item row="58" column="1">
+ <widget class="QComboBox" name="IndentCaseLabels">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="59" column="0">
+ <widget class="QLabel" name="labelIndentPPDirectives">
+ <property name="text">
+ <string notr="true">IndentPPDirectives</string>
+ </property>
+ </widget>
+ </item>
+ <item row="59" column="1">
+ <widget class="QComboBox" name="IndentPPDirectives">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">AfterHash</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="60" column="0">
+ <widget class="QLabel" name="labelIndentWidth">
+ <property name="text">
+ <string notr="true">IndentWidth</string>
+ </property>
+ </widget>
+ </item>
+ <item row="60" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="IndentWidth">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setIndentWidth">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="61" column="0">
+ <widget class="QLabel" name="labelIndentWrappedFunctionNames">
+ <property name="text">
+ <string notr="true">IndentWrappedFunctionNames</string>
+ </property>
+ </widget>
+ </item>
+ <item row="61" column="1">
+ <widget class="QComboBox" name="IndentWrappedFunctionNames">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="62" column="0">
+ <widget class="QLabel" name="labelJavaImportGroups">
+ <property name="text">
+ <string notr="true">JavaImportGroups</string>
+ </property>
+ </widget>
+ </item>
+ <item row="62" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPlainTextEdit" name="JavaImportGroups">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setJavaImportGroups">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="63" column="0">
+ <widget class="QLabel" name="labelJavaScriptQuotes">
+ <property name="text">
+ <string notr="true">JavaScriptQuotes</string>
+ </property>
+ </widget>
+ </item>
+ <item row="63" column="1">
+ <widget class="QComboBox" name="JavaScriptQuotes">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Leave</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Single</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Double</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="64" column="0">
+ <widget class="QLabel" name="labelJavaScriptWrapImports">
+ <property name="text">
+ <string notr="true">JavaScriptWrapImports</string>
+ </property>
+ </widget>
+ </item>
+ <item row="64" column="1">
+ <widget class="QComboBox" name="JavaScriptWrapImports">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="65" column="0">
+ <widget class="QLabel" name="labelKeepEmptyLinesAtTheStartOfBlocks">
+ <property name="text">
+ <string notr="true">KeepEmptyLinesAtTheStartOfBlocks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="65" column="1">
+ <widget class="QComboBox" name="KeepEmptyLinesAtTheStartOfBlocks">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="66" column="0">
+ <widget class="QLabel" name="labelLanguage">
+ <property name="text">
+ <string notr="true">Language</string>
+ </property>
+ </widget>
+ </item>
+ <item row="66" column="1">
+ <widget class="QComboBox" name="Language">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Cpp</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Java</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">JavaScript</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">ObjC</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Proto</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">TableGen</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">TextProto</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="67" column="0">
+ <widget class="QLabel" name="labelMacroBlockBegin">
+ <property name="text">
+ <string notr="true">MacroBlockBegin</string>
+ </property>
+ </widget>
+ </item>
+ <item row="67" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="MacroBlockBegin">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setMacroBlockBegin">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="68" column="0">
+ <widget class="QLabel" name="labelMacroBlockEnd">
+ <property name="text">
+ <string notr="true">MacroBlockEnd</string>
+ </property>
+ </widget>
+ </item>
+ <item row="68" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="MacroBlockEnd">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setMacroBlockEnd">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="69" column="0">
+ <widget class="QLabel" name="labelMaxEmptyLinesToKeep">
+ <property name="text">
+ <string notr="true">MaxEmptyLinesToKeep</string>
+ </property>
+ </widget>
+ </item>
+ <item row="69" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="MaxEmptyLinesToKeep">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setMaxEmptyLinesToKeep">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="70" column="0">
+ <widget class="QLabel" name="labelNamespaceIndentation">
+ <property name="text">
+ <string notr="true">NamespaceIndentation</string>
+ </property>
+ </widget>
+ </item>
+ <item row="70" column="1">
+ <widget class="QComboBox" name="NamespaceIndentation">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Inner</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">All</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="71" column="0">
+ <widget class="QLabel" name="labelObjCBinPackProtocolList">
+ <property name="text">
+ <string notr="true">ObjCBinPackProtocolList</string>
+ </property>
+ </widget>
+ </item>
+ <item row="71" column="1">
+ <widget class="QComboBox" name="ObjCBinPackProtocolList">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Auto</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Always</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Never</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="72" column="0">
+ <widget class="QLabel" name="labelObjCBlockIndentWidth">
+ <property name="text">
+ <string notr="true">ObjCBlockIndentWidth</string>
+ </property>
+ </widget>
+ </item>
+ <item row="72" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="ObjCBlockIndentWidth">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setObjCBlockIndentWidth">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="73" column="0">
+ <widget class="QLabel" name="labelObjCSpaceAfterProperty">
+ <property name="text">
+ <string notr="true">ObjCSpaceAfterProperty</string>
+ </property>
+ </widget>
+ </item>
+ <item row="73" column="1">
+ <widget class="QComboBox" name="ObjCSpaceAfterProperty">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="74" column="0">
+ <widget class="QLabel" name="labelObjCSpaceBeforeProtocolList">
+ <property name="text">
+ <string notr="true">ObjCSpaceBeforeProtocolList</string>
+ </property>
+ </widget>
+ </item>
+ <item row="74" column="1">
+ <widget class="QComboBox" name="ObjCSpaceBeforeProtocolList">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="75" column="0">
+ <widget class="QLabel" name="labelPenaltyBreakAssignment">
+ <property name="text">
+ <string notr="true">PenaltyBreakAssignment</string>
+ </property>
+ </widget>
+ </item>
+ <item row="75" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyBreakAssignment">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyBreakAssignment">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="76" column="0">
+ <widget class="QLabel" name="labelPenaltyBreakBeforeFirstCallParameter">
+ <property name="text">
+ <string notr="true">PenaltyBreakBeforeFirstCallParameter</string>
+ </property>
+ </widget>
+ </item>
+ <item row="76" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyBreakBeforeFirstCallParameter">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyBreakBeforeFirstCallParameter">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="77" column="0">
+ <widget class="QLabel" name="labelPenaltyBreakComment">
+ <property name="text">
+ <string notr="true">PenaltyBreakComment</string>
+ </property>
+ </widget>
+ </item>
+ <item row="77" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyBreakComment">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyBreakComment">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="78" column="0">
+ <widget class="QLabel" name="labelPenaltyBreakFirstLessLess">
+ <property name="text">
+ <string notr="true">PenaltyBreakFirstLessLess</string>
+ </property>
+ </widget>
+ </item>
+ <item row="78" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyBreakFirstLessLess">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyBreakFirstLessLess">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="79" column="0">
+ <widget class="QLabel" name="labelPenaltyBreakString">
+ <property name="text">
+ <string notr="true">PenaltyBreakString</string>
+ </property>
+ </widget>
+ </item>
+ <item row="79" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyBreakString">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyBreakString">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="80" column="0">
+ <widget class="QLabel" name="labelPenaltyBreakTemplateDeclaration">
+ <property name="text">
+ <string notr="true">PenaltyBreakTemplateDeclaration</string>
+ </property>
+ </widget>
+ </item>
+ <item row="80" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyBreakTemplateDeclaration">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyBreakTemplateDeclaration">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="81" column="0">
+ <widget class="QLabel" name="labelPenaltyExcessCharacter">
+ <property name="text">
+ <string notr="true">PenaltyExcessCharacter</string>
+ </property>
+ </widget>
+ </item>
+ <item row="81" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyExcessCharacter">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyExcessCharacter">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="82" column="0">
+ <widget class="QLabel" name="labelPenaltyReturnTypeOnItsOwnLine">
+ <property name="text">
+ <string notr="true">PenaltyReturnTypeOnItsOwnLine</string>
+ </property>
+ </widget>
+ </item>
+ <item row="82" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="PenaltyReturnTypeOnItsOwnLine">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setPenaltyReturnTypeOnItsOwnLine">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="83" column="0">
+ <widget class="QLabel" name="labelPointerAlignment">
+ <property name="text">
+ <string notr="true">PointerAlignment</string>
+ </property>
+ </widget>
+ </item>
+ <item row="83" column="1">
+ <widget class="QComboBox" name="PointerAlignment">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Left</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Right</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Middle</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="84" column="0">
+ <widget class="QLabel" name="labelRawStringFormats">
+ <property name="text">
+ <string notr="true">RawStringFormats</string>
+ </property>
+ </widget>
+ </item>
+ <item row="84" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPlainTextEdit" name="RawStringFormats">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setRawStringFormats">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="85" column="0">
+ <widget class="QLabel" name="labelReflowComments">
+ <property name="text">
+ <string notr="true">ReflowComments</string>
+ </property>
+ </widget>
+ </item>
+ <item row="85" column="1">
+ <widget class="QComboBox" name="ReflowComments">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="86" column="0">
+ <widget class="QLabel" name="labelSortIncludes">
+ <property name="text">
+ <string notr="true">SortIncludes</string>
+ </property>
+ </widget>
+ </item>
+ <item row="86" column="1">
+ <widget class="QComboBox" name="SortIncludes">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="87" column="0">
+ <widget class="QLabel" name="labelSortUsingDeclarations">
+ <property name="text">
+ <string notr="true">SortUsingDeclarations</string>
+ </property>
+ </widget>
+ </item>
+ <item row="87" column="1">
+ <widget class="QComboBox" name="SortUsingDeclarations">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="88" column="0">
+ <widget class="QLabel" name="labelSpaceAfterCStyleCast">
+ <property name="text">
+ <string notr="true">SpaceAfterCStyleCast</string>
+ </property>
+ </widget>
+ </item>
+ <item row="88" column="1">
+ <widget class="QComboBox" name="SpaceAfterCStyleCast">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="89" column="0">
+ <widget class="QLabel" name="labelSpaceAfterTemplateKeyword">
+ <property name="text">
+ <string notr="true">SpaceAfterTemplateKeyword</string>
+ </property>
+ </widget>
+ </item>
+ <item row="89" column="1">
+ <widget class="QComboBox" name="SpaceAfterTemplateKeyword">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="90" column="0">
+ <widget class="QLabel" name="labelSpaceBeforeAssignmentOperators">
+ <property name="text">
+ <string notr="true">SpaceBeforeAssignmentOperators</string>
+ </property>
+ </widget>
+ </item>
+ <item row="90" column="1">
+ <widget class="QComboBox" name="SpaceBeforeAssignmentOperators">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="91" column="0">
+ <widget class="QLabel" name="labelSpaceBeforeCpp11BracedList">
+ <property name="text">
+ <string notr="true">SpaceBeforeCpp11BracedList</string>
+ </property>
+ </widget>
+ </item>
+ <item row="91" column="1">
+ <widget class="QComboBox" name="SpaceBeforeCpp11BracedList">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="92" column="0">
+ <widget class="QLabel" name="labelSpaceBeforeCtorInitializerColon">
+ <property name="text">
+ <string notr="true">SpaceBeforeCtorInitializerColon</string>
+ </property>
+ </widget>
+ </item>
+ <item row="92" column="1">
+ <widget class="QComboBox" name="SpaceBeforeCtorInitializerColon">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="93" column="0">
+ <widget class="QLabel" name="labelSpaceBeforeInheritanceColon">
+ <property name="text">
+ <string notr="true">SpaceBeforeInheritanceColon</string>
+ </property>
+ </widget>
+ </item>
+ <item row="93" column="1">
+ <widget class="QComboBox" name="SpaceBeforeInheritanceColon">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="94" column="0">
+ <widget class="QLabel" name="labelSpaceBeforeParens">
+ <property name="text">
+ <string notr="true">SpaceBeforeParens</string>
+ </property>
+ </widget>
+ </item>
+ <item row="94" column="1">
+ <widget class="QComboBox" name="SpaceBeforeParens">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Never</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">ControlStatements</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Always</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="95" column="0">
+ <widget class="QLabel" name="labelSpaceBeforeRangeBasedForLoopColon">
+ <property name="text">
+ <string notr="true">SpaceBeforeRangeBasedForLoopColon</string>
+ </property>
+ </widget>
+ </item>
+ <item row="95" column="1">
+ <widget class="QComboBox" name="SpaceBeforeRangeBasedForLoopColon">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="96" column="0">
+ <widget class="QLabel" name="labelSpaceInEmptyParentheses">
+ <property name="text">
+ <string notr="true">SpaceInEmptyParentheses</string>
+ </property>
+ </widget>
+ </item>
+ <item row="96" column="1">
+ <widget class="QComboBox" name="SpaceInEmptyParentheses">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="97" column="0">
+ <widget class="QLabel" name="labelSpacesBeforeTrailingComments">
+ <property name="text">
+ <string notr="true">SpacesBeforeTrailingComments</string>
+ </property>
+ </widget>
+ </item>
+ <item row="97" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="SpacesBeforeTrailingComments">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setSpacesBeforeTrailingComments">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="98" column="0">
+ <widget class="QLabel" name="labelSpacesInAngles">
+ <property name="text">
+ <string notr="true">SpacesInAngles</string>
+ </property>
+ </widget>
+ </item>
+ <item row="98" column="1">
+ <widget class="QComboBox" name="SpacesInAngles">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="99" column="0">
+ <widget class="QLabel" name="labelSpacesInCStyleCastParentheses">
+ <property name="text">
+ <string notr="true">SpacesInCStyleCastParentheses</string>
+ </property>
+ </widget>
+ </item>
+ <item row="99" column="1">
+ <widget class="QComboBox" name="SpacesInCStyleCastParentheses">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="100" column="0">
+ <widget class="QLabel" name="labelSpacesInContainerLiterals">
+ <property name="text">
+ <string notr="true">SpacesInContainerLiterals</string>
+ </property>
+ </widget>
+ </item>
+ <item row="100" column="1">
+ <widget class="QComboBox" name="SpacesInContainerLiterals">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="101" column="0">
+ <widget class="QLabel" name="labelSpacesInParentheses">
+ <property name="text">
+ <string notr="true">SpacesInParentheses</string>
+ </property>
+ </widget>
+ </item>
+ <item row="101" column="1">
+ <widget class="QComboBox" name="SpacesInParentheses">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="102" column="0">
+ <widget class="QLabel" name="labelSpacesInSquareBrackets">
+ <property name="text">
+ <string notr="true">SpacesInSquareBrackets</string>
+ </property>
+ </widget>
+ </item>
+ <item row="102" column="1">
+ <widget class="QComboBox" name="SpacesInSquareBrackets">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">true</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">false</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="103" column="0">
+ <widget class="QLabel" name="labelStandard">
+ <property name="text">
+ <string notr="true">Standard</string>
+ </property>
+ </widget>
+ </item>
+ <item row="103" column="1">
+ <widget class="QComboBox" name="Standard">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Cpp03</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Cpp11</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Auto</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="104" column="0">
+ <widget class="QLabel" name="labelStatementMacros">
+ <property name="text">
+ <string notr="true">StatementMacros</string>
+ </property>
+ </widget>
+ </item>
+ <item row="104" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPlainTextEdit" name="StatementMacros">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setStatementMacros">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="105" column="0">
+ <widget class="QLabel" name="labelTabWidth">
+ <property name="text">
+ <string notr="true">TabWidth</string>
+ </property>
+ </widget>
+ </item>
+ <item row="105" column="1">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLineEdit" name="TabWidth">
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setTabWidth">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="106" column="0">
+ <widget class="QLabel" name="labelUseTab">
+ <property name="text">
+ <string notr="true">UseTab</string>
+ </property>
+ </widget>
+ </item>
+ <item row="106" column="1">
+ <widget class="QComboBox" name="UseTab">
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Never</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">ForIndentation</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">ForContinuationAndIndentation</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Always</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp
index 4f2d77a6f7..f419780a3e 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.cpp
+++ b/src/plugins/clangformat/clangformatconfigwidget.cpp
@@ -29,6 +29,7 @@
#include "clangformatindenter.h"
#include "clangformatsettings.h"
#include "clangformatutils.h"
+#include "ui_clangformatchecks.h"
#include "ui_clangformatconfigwidget.h"
#include <clang/Format/Format.h>
@@ -36,12 +37,17 @@
#include <coreplugin/icore.h>
#include <cppeditor/cpphighlighter.h>
#include <cpptools/cppcodestylesnippets.h>
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/pluginspec.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <texteditor/displaysettings.h>
#include <texteditor/snippets/snippeteditor.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h>
+#include <utils/executeondestruction.h>
+#include <utils/qtcassert.h>
+#include <utils/genericconstants.h>
#include <QFile>
#include <QMessageBox>
@@ -52,32 +58,161 @@ 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)) {
+ event->ignore();
+ return true;
+ }
+ 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)
: CodeStyleEditorWidget(parent)
, m_project(project)
+ , m_checks(std::make_unique<Ui::ClangFormatChecksWidget>())
, m_ui(std::make_unique<Ui::ClangFormatConfigWidget>())
{
m_ui->setupUi(this);
- m_preview = new TextEditor::SnippetEditorWidget(this);
- m_ui->horizontalLayout_2->addWidget(m_preview);
+ initChecksAndPreview();
+
if (m_project) {
m_ui->applyButton->show();
hideGlobalCheckboxes();
+ m_ui->fallbackConfig->hide();
m_ui->overrideDefault->setChecked(
m_project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool());
} else {
m_ui->applyButton->hide();
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, [this](bool checked) {
- if (checked)
- createStyleFileIfNeeded(!m_project);
- initialize();
+ showOrHideWidgets();
});
- initialize();
+ showOrHideWidgets();
+
+ fillTable();
+ updatePreview();
+
+ connectChecks();
+}
+
+void ClangFormatConfigWidget::initChecksAndPreview()
+{
+ m_checksScrollArea = new QScrollArea();
+ m_checksWidget = new QWidget;
+ m_checks->setupUi(m_checksWidget);
+ m_checksScrollArea->setWidget(m_checksWidget);
+ m_checksScrollArea->setMaximumWidth(500);
+
+ m_ui->horizontalLayout_2->addWidget(m_checksScrollArea);
+
+ m_preview = new TextEditor::SnippetEditorWidget(this);
+ m_ui->horizontalLayout_2->addWidget(m_preview);
+
+ TextEditor::DisplaySettings displaySettings = m_preview->displaySettings();
+ displaySettings.m_visualizeWhitespace = true;
+ m_preview->setDisplaySettings(displaySettings);
+ m_preview->setPlainText(QLatin1String(CppTools::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
+ m_preview->textDocument()->setIndenter(new ClangFormatIndenter(m_preview->document()));
+ m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
+ m_preview->textDocument()->setSyntaxHighlighter(new CppEditor::CppHighlighter);
+
+ Utils::FilePath fileName;
+ if (m_project) {
+ connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply);
+ fileName = m_project->projectFilePath().pathAppended("snippet.cpp");
+ } else {
+ fileName = Utils::FilePath::fromString(Core::ICore::userResourcePath())
+ .pathAppended("snippet.cpp");
+ }
+ m_preview->textDocument()->indenter()->setFileName(fileName);
+}
+
+void ClangFormatConfigWidget::connectChecks()
+{
+ for (QObject *child : m_checksWidget->children()) {
+ auto comboBox = qobject_cast<QComboBox *>(child);
+ if (comboBox != nullptr) {
+ connect(comboBox,
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this,
+ &ClangFormatConfigWidget::onTableChanged);
+ comboBox->installEventFilter(this);
+ continue;
+ }
+
+ auto button = qobject_cast<QPushButton *>(child);
+ if (button != nullptr)
+ connect(button, &QPushButton::clicked, this, &ClangFormatConfigWidget::onTableChanged);
+ }
+}
+
+void ClangFormatConfigWidget::onTableChanged()
+{
+ if (m_disableTableUpdate)
+ return;
+
+ const std::string newConfig = tableToString(sender());
+ if (newConfig.empty())
+ return;
+ const std::string oldConfig = m_project ? currentProjectConfigText()
+ : currentGlobalConfigText();
+ saveConfig(newConfig);
+ fillTable();
+ updatePreview();
+ saveConfig(oldConfig);
}
void ClangFormatConfigWidget::hideGlobalCheckboxes()
@@ -97,55 +232,44 @@ void ClangFormatConfigWidget::showGlobalCheckboxes()
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));
+ }
}
static bool projectConfigExists()
{
- return Utils::FileName::fromString(Core::ICore::userResourcePath())
- .appendPath("clang-format")
- .appendPath(currentProjectUniqueId())
- .appendPath((Constants::SETTINGS_FILE_NAME))
+ return Utils::FilePath::fromString(Core::ICore::userResourcePath())
+ .pathAppended("clang-format")
+ .pathAppended(currentProjectUniqueId())
+ .pathAppended((Constants::SETTINGS_FILE_NAME))
.exists();
}
-void ClangFormatConfigWidget::initialize()
+void ClangFormatConfigWidget::showOrHideWidgets()
{
m_ui->projectHasClangFormat->hide();
- m_preview->setPlainText(QLatin1String(CppTools::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
- m_preview->textDocument()->setIndenter(new ClangFormatIndenter(m_preview->document()));
- m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
- m_preview->textDocument()->setSyntaxHighlighter(new CppEditor::CppHighlighter);
-
- TextEditor::DisplaySettings displaySettings = m_preview->displaySettings();
- displaySettings.m_visualizeWhitespace = true;
- m_preview->setDisplaySettings(displaySettings);
-
QLayoutItem *lastItem = m_ui->verticalLayout->itemAt(m_ui->verticalLayout->count() - 1);
if (lastItem->spacerItem())
m_ui->verticalLayout->removeItem(lastItem);
- m_ui->clangFormatOptionsTable->setEnabled(true);
- if (!m_ui->overrideDefault->isChecked()) {
- if (m_project) {
- m_ui->clangFormatOptionsTable->hide();
- m_preview->hide();
- m_ui->verticalLayout->addStretch(1);
- return;
- } else {
- // Show the fallback configuration only globally.
- m_ui->clangFormatOptionsTable->setEnabled(false);
- }
+ if (!m_ui->overrideDefault->isChecked() && m_project) {
+ // Show the fallback configuration only globally.
+ m_checksScrollArea->hide();
+ m_preview->hide();
+ m_ui->verticalLayout->addStretch(1);
+ return;
}
- m_ui->clangFormatOptionsTable->show();
+ createStyleFileIfNeeded(!m_project);
+ m_checksScrollArea->show();
m_preview->show();
- Utils::FileName fileName;
if (m_project) {
m_ui->projectHasClangFormat->hide();
- connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply);
- fileName = m_project->projectFilePath().appendPath("snippet.cpp");
} else {
const Project *currentProject = SessionManager::startupProject();
if (!currentProject || !projectConfigExists()) {
@@ -156,13 +280,7 @@ void ClangFormatConfigWidget::initialize()
tr("Current project has its own overridden .clang-format file "
"and can be configured in Projects > Code Style > C++."));
}
- fileName = Utils::FileName::fromString(Core::ICore::userResourcePath())
- .appendPath("snippet.cpp");
}
-
- m_preview->textDocument()->indenter()->setFileName(fileName);
- fillTable();
- updatePreview();
}
void ClangFormatConfigWidget::updatePreview()
@@ -173,12 +291,163 @@ void ClangFormatConfigWidget::updatePreview()
m_preview->textDocument()->autoFormatOrIndent(cursor);
}
+static inline void ltrim(std::string &s)
+{
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); }));
+}
+
+static inline void rtrim(std::string &s)
+{
+ s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(),
+ s.end());
+}
+
+static inline void trim(std::string &s)
+{
+ ltrim(s);
+ rtrim(s);
+}
+
+static void fillPlainText(QPlainTextEdit *plainText, const std::string &text, size_t index)
+{
+ if (index == std::string::npos) {
+ plainText->setPlainText("");
+ return;
+ }
+ size_t valueStart = text.find('\n', index + 1);
+ size_t valueEnd;
+ std::string value;
+ QTC_ASSERT(valueStart != std::string::npos, return;);
+ do {
+ valueEnd = text.find('\n', valueStart + 1);
+ if (valueEnd == std::string::npos)
+ break;
+ // Skip also 2 spaces - start with valueStart + 1 + 2.
+ std::string line = text.substr(valueStart + 3, valueEnd - valueStart - 3);
+ rtrim(line);
+ value += value.empty() ? line : '\n' + line;
+ valueStart = valueEnd;
+ } while (valueEnd < text.size() - 1 && text.at(valueEnd + 1) == ' ');
+ plainText->setPlainText(QString::fromStdString(value));
+}
+
+static void fillComboBoxOrLineEdit(QObject *object, const std::string &text, size_t index)
+{
+ auto *comboBox = qobject_cast<QComboBox *>(object);
+ auto *lineEdit = qobject_cast<QLineEdit *>(object);
+ if (index == std::string::npos) {
+ if (comboBox)
+ comboBox->setCurrentIndex(0);
+ else
+ lineEdit->setText("");
+ return;
+ }
+
+ const size_t valueStart = text.find(':', index + 1);
+ QTC_ASSERT(valueStart != std::string::npos, return;);
+ const size_t valueEnd = text.find('\n', valueStart + 1);
+ QTC_ASSERT(valueEnd != std::string::npos, return;);
+ std::string value = text.substr(valueStart + 1, valueEnd - valueStart - 1);
+ trim(value);
+
+ if (comboBox)
+ comboBox->setCurrentText(QString::fromStdString(value));
+ else
+ lineEdit->setText(QString::fromStdString(value));
+}
+
void ClangFormatConfigWidget::fillTable()
{
- clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle();
+ Utils::ExecuteOnDestruction executeOnDestruction([this]() { m_disableTableUpdate = false; });
+ m_disableTableUpdate = true;
+
+ const std::string configText = m_project ? currentProjectConfigText()
+ : currentGlobalConfigText();
+
+ for (QObject *child : m_checksWidget->children()) {
+ if (!qobject_cast<QComboBox *>(child) && !qobject_cast<QLineEdit *>(child)
+ && !qobject_cast<QPlainTextEdit *>(child)) {
+ continue;
+ }
+
+ size_t index = configText.find('\n' + child->objectName().toStdString());
+ if (index == std::string::npos)
+ index = configText.find("\n " + child->objectName().toStdString());
+
+ if (qobject_cast<QPlainTextEdit *>(child))
+ fillPlainText(qobject_cast<QPlainTextEdit *>(child), configText, index);
+ else
+ fillComboBoxOrLineEdit(child, configText, index);
+ }
+}
+
+std::string ClangFormatConfigWidget::tableToString(QObject *sender)
+{
+ std::stringstream content;
+ content << "---";
+
+ if (sender->objectName() == "BasedOnStyle") {
+ auto *basedOnStyle = m_checksWidget->findChild<QComboBox *>("BasedOnStyle");
+ content << "\nBasedOnStyle: " << basedOnStyle->currentText().toStdString() << '\n';
+ } else {
+ for (QObject *child : m_checksWidget->children()) {
+ auto *label = qobject_cast<QLabel *>(child);
+ if (!label)
+ continue;
+
+ QWidget *valueWidget = m_checksWidget->findChild<QWidget *>(label->text().trimmed());
+ if (!valueWidget) {
+ // Currently BraceWrapping only.
+ content << '\n' << label->text().toStdString() << ":";
+ continue;
+ }
+
+ if (!qobject_cast<QComboBox *>(valueWidget) && !qobject_cast<QLineEdit *>(valueWidget)
+ && !qobject_cast<QPlainTextEdit *>(valueWidget)) {
+ continue;
+ }
+
+ auto *plainText = qobject_cast<QPlainTextEdit *>(valueWidget);
+ if (plainText) {
+ if (plainText->toPlainText().trimmed().isEmpty())
+ continue;
+
+ content << '\n' << label->text().toStdString() << ":";
+ QStringList list = plainText->toPlainText().split('\n');
+ for (const QString &line : list)
+ content << "\n " << line.toStdString();
+ } else {
+ auto *comboBox = qobject_cast<QComboBox *>(valueWidget);
+ std::string text;
+ if (comboBox) {
+ text = comboBox->currentText().toStdString();
+ } else {
+ auto *lineEdit = qobject_cast<QLineEdit *>(valueWidget);
+ QTC_ASSERT(lineEdit, continue;);
+ text = lineEdit->text().toStdString();
+ }
+
+ if (!text.empty() && text != "Default")
+ content << '\n' << label->text().toStdString() << ": " << text;
+ }
+ }
+ content << '\n';
+ }
- const std::string configText = clang::format::configurationAsText(style);
- m_ui->clangFormatOptionsTable->setPlainText(QString::fromStdString(configText));
+ std::string text = content.str();
+ clang::format::FormatStyle style;
+ style.Language = clang::format::FormatStyle::LK_Cpp;
+ const std::error_code error = clang::format::parseConfiguration(text, &style);
+ if (error.value() != static_cast<int>(clang::format::ParseError::Success)) {
+ QMessageBox::warning(this,
+ tr("Error in ClangFormat configuration"),
+ QString::fromStdString(error.message()));
+ fillTable();
+ updatePreview();
+ return std::string();
+ }
+
+ return text;
}
ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
@@ -196,24 +465,20 @@ void ClangFormatConfigWidget::apply()
}
settings.write();
- if (!m_ui->clangFormatOptionsTable->isVisible())
+ if (!m_checksWidget->isVisible())
return;
- const QString text = m_ui->clangFormatOptionsTable->toPlainText();
- clang::format::FormatStyle style;
- style.Language = clang::format::FormatStyle::LK_Cpp;
- const std::error_code error = clang::format::parseConfiguration(text.toStdString(), &style);
- if (error.value() != static_cast<int>(clang::format::ParseError::Success)) {
- QMessageBox::warning(this,
- tr("Error in ClangFormat configuration"),
- QString::fromStdString(error.message()));
- if (m_ui->overrideDefault->isChecked()) {
- fillTable();
- updatePreview();
- }
+ const std::string config = tableToString(this);
+ if (config.empty())
return;
- }
+ saveConfig(config);
+ fillTable();
+ updatePreview();
+}
+
+void ClangFormatConfigWidget::saveConfig(const std::string &text) const
+{
QString filePath = Core::ICore::userResourcePath();
if (m_project)
filePath += "/clang-format/" + currentProjectUniqueId();
@@ -223,11 +488,8 @@ void ClangFormatConfigWidget::apply()
if (!file.open(QFile::WriteOnly))
return;
- file.write(text.toUtf8());
+ file.write(text.c_str());
file.close();
-
- if (m_ui->overrideDefault->isChecked())
- updatePreview();
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h
index 58570d9bf6..869ddeccb7 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.h
+++ b/src/plugins/clangformat/clangformatconfigwidget.h
@@ -27,6 +27,8 @@
#include <texteditor/icodestylepreferencesfactory.h>
+#include <QScrollArea>
+
#include <memory>
namespace ProjectExplorer {
@@ -40,6 +42,7 @@ namespace ClangFormat {
namespace Ui {
class ClangFormatConfigWidget;
+class ClangFormatChecksWidget;
}
class ClangFormatConfigWidget : public TextEditor::CodeStyleEditorWidget
@@ -53,17 +56,31 @@ public:
void apply() override;
private:
- void initialize();
+ void onTableChanged();
+
+ bool eventFilter(QObject *object, QEvent *event) override;
+ void showEvent(QShowEvent *event) override;
+
+ void showOrHideWidgets();
+ void initChecksAndPreview();
+ void connectChecks();
+
void fillTable();
+ std::string tableToString(QObject *sender);
void hideGlobalCheckboxes();
void showGlobalCheckboxes();
+ void saveConfig(const std::string &text) const;
void updatePreview();
ProjectExplorer::Project *m_project;
+ QWidget *m_checksWidget;
+ QScrollArea *m_checksScrollArea;
TextEditor::SnippetEditorWidget *m_preview;
+ std::unique_ptr<Ui::ClangFormatChecksWidget> m_checks;
std::unique_ptr<Ui::ClangFormatConfigWidget> m_ui;
+ bool m_disableTableUpdate = false;
};
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui
index c8225981f5..45b9801d7f 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.ui
+++ b/src/plugins/clangformat/clangformatconfigwidget.ui
@@ -41,11 +41,35 @@
</widget>
</item>
<item>
- <widget class="QCheckBox" name="formatOnSave">
- <property name="text">
- <string>Format edited code on file save</string>
- </property>
- </widget>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <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="fileSaveWarning">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </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>
<widget class="QLabel" name="projectHasClangFormat">
@@ -62,10 +86,14 @@
</widget>
</item>
<item>
+ <widget class="QLabel" name="fallbackConfig">
+ <property name="text">
+ <string>Fallback configuration</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QPlainTextEdit" name="clangFormatOptionsTable"/>
- </item>
</layout>
</item>
<item>
diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp
index fe381a1181..49f4fe049f 100644
--- a/src/plugins/clangformat/clangformatplugin.cpp
+++ b/src/plugins/clangformat/clangformatplugin.cpp
@@ -72,9 +72,6 @@ using namespace ProjectExplorer;
namespace ClangFormat {
-ClangFormatPlugin::ClangFormatPlugin() = default;
-ClangFormatPlugin::~ClangFormatPlugin() = default;
-
#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
class ClangFormatStyleFactory : public CppTools::CppCodeStylePreferencesFactory
{
@@ -155,8 +152,13 @@ bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorS
openClangFormatConfigAction->setData(doc->filePath().toString());
});
}
-#endif
return true;
+#else
+ *errorString = "Disabling ClangFormat plugin as it is not built against a suitable version of "
+ "Clang's libFormat. For more information, see the Qt Creator README at "
+ "https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/README.md";
+ return false;
+#endif
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatplugin.h b/src/plugins/clangformat/clangformatplugin.h
index e8c81179a0..c453f7c6f6 100644
--- a/src/plugins/clangformat/clangformatplugin.h
+++ b/src/plugins/clangformat/clangformatplugin.h
@@ -34,11 +34,6 @@ class ClangFormatPlugin : public ExtensionSystem::IPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangFormat.json")
-public:
- ClangFormatPlugin();
- ~ClangFormatPlugin();
-
-private:
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final {}
};
diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp
index 09a3150c89..14d59a757c 100644
--- a/src/plugins/clangformat/clangformatutils.cpp
+++ b/src/plugins/clangformat/clangformatutils.cpp
@@ -165,21 +165,21 @@ static bool useProjectOverriddenSettings()
return project ? project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool() : false;
}
-static Utils::FileName globalPath()
+static Utils::FilePath globalPath()
{
- return Utils::FileName::fromString(Core::ICore::userResourcePath());
+ return Utils::FilePath::fromString(Core::ICore::userResourcePath());
}
-static Utils::FileName projectPath()
+static Utils::FilePath projectPath()
{
const Project *project = SessionManager::startupProject();
if (project)
- return globalPath().appendPath("clang-format").appendPath(currentProjectUniqueId());
+ return globalPath().pathAppended("clang-format/" + currentProjectUniqueId());
- return Utils::FileName();
+ return Utils::FilePath();
}
-static QString findConfig(Utils::FileName fileName)
+static QString findConfig(Utils::FilePath fileName)
{
QDir parentDir(fileName.parentDir().toString());
while (!parentDir.exists(Constants::SETTINGS_FILE_NAME)
@@ -193,7 +193,7 @@ static QString findConfig(Utils::FileName fileName)
return parentDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
}
-static QString configForFile(Utils::FileName fileName, bool checkForSettings)
+static QString configForFile(Utils::FilePath fileName, bool checkForSettings)
{
QDir overrideDir;
if (!checkForSettings || useProjectOverriddenSettings()) {
@@ -211,15 +211,15 @@ static QString configForFile(Utils::FileName fileName, bool checkForSettings)
return findConfig(fileName);
}
-QString configForFile(Utils::FileName fileName)
+QString configForFile(Utils::FilePath fileName)
{
return configForFile(fileName, true);
}
-Utils::FileName assumedPathForConfig(const QString &configFile)
+Utils::FilePath assumedPathForConfig(const QString &configFile)
{
- Utils::FileName fileName = Utils::FileName::fromString(configFile);
- return fileName.parentDir().appendPath("test.cpp");
+ Utils::FilePath fileName = Utils::FilePath::fromString(configFile);
+ return fileName.parentDir().pathAppended("test.cpp");
}
static clang::format::FormatStyle constructStyle(const QByteArray &baseStyle = QByteArray())
@@ -243,16 +243,16 @@ static clang::format::FormatStyle constructStyle(const QByteArray &baseStyle = Q
void createStyleFileIfNeeded(bool isGlobal)
{
- Utils::FileName path = isGlobal ? globalPath() : projectPath();
- const QString configFile = path.appendPath(Constants::SETTINGS_FILE_NAME).toString();
+ const Utils::FilePath path = isGlobal ? globalPath() : projectPath();
+ const QString configFile = path.pathAppended(Constants::SETTINGS_FILE_NAME).toString();
if (QFile::exists(configFile))
return;
- QDir().mkpath(path.parentDir().toString());
+ QDir().mkpath(path.toString());
if (!isGlobal) {
const Project *project = SessionManager::startupProject();
- Utils::FileName possibleProjectConfig = project->rootProjectDirectory().appendPath(
+ Utils::FilePath possibleProjectConfig = project->rootProjectDirectory().pathAppended(
Constants::SETTINGS_FILE_NAME);
if (possibleProjectConfig.exists()) {
// Just copy th .clang-format if current project has one.
@@ -290,13 +290,13 @@ static QByteArray configBaseStyleName(const QString &configFile)
.trimmed();
}
-static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool checkForSettings)
+static clang::format::FormatStyle styleForFile(Utils::FilePath fileName, bool checkForSettings)
{
QString configFile = configForFile(fileName, checkForSettings);
if (configFile.isEmpty()) {
// If no configuration is found create a global one (if it does not yet exist) and use it.
createStyleFileIfNeeded(true);
- configFile = globalPath().appendPath(Constants::SETTINGS_FILE_NAME).toString();
+ configFile = globalPath().pathAppended(Constants::SETTINGS_FILE_NAME).toString();
}
fileName = assumedPathForConfig(configFile);
@@ -313,18 +313,44 @@ static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool ch
return constructStyle(configBaseStyleName(configFile));
}
-clang::format::FormatStyle styleForFile(Utils::FileName fileName)
+clang::format::FormatStyle styleForFile(Utils::FilePath fileName)
{
return styleForFile(fileName, true);
}
+static std::string readFile(const QString &path)
+{
+ QFile file(path);
+ if (!file.open(QFile::ReadOnly)) {
+ clang::format::FormatStyle defaultStyle = qtcStyle();
+ return clang::format::configurationAsText(defaultStyle);
+ }
+
+ const QByteArray content = file.readAll();
+ file.close();
+
+ return content.toStdString();
+}
+
+std::string currentProjectConfigText()
+{
+ const QString configPath = projectPath().pathAppended(Constants::SETTINGS_FILE_NAME).toString();
+ return readFile(configPath);
+}
+
+std::string currentGlobalConfigText()
+{
+ const QString configPath = globalPath().pathAppended(Constants::SETTINGS_FILE_NAME).toString();
+ return readFile(configPath);
+}
+
clang::format::FormatStyle currentProjectStyle()
{
- return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
+ return styleForFile(projectPath().pathAppended(Constants::SAMPLE_FILE_NAME), false);
}
clang::format::FormatStyle currentGlobalStyle()
{
- return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
+ return styleForFile(globalPath().pathAppended(Constants::SAMPLE_FILE_NAME), false);
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatutils.h b/src/plugins/clangformat/clangformatutils.h
index bd53076943..e8c21bbcf6 100644
--- a/src/plugins/clangformat/clangformatutils.h
+++ b/src/plugins/clangformat/clangformatutils.h
@@ -40,11 +40,14 @@ void createStyleFileIfNeeded(bool isGlobal);
QString currentProjectUniqueId();
+std::string currentProjectConfigText();
+std::string currentGlobalConfigText();
+
clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle();
// Is the style from the matching .clang-format file or global one if it's not found.
-QString configForFile(Utils::FileName fileName);
-clang::format::FormatStyle styleForFile(Utils::FileName fileName);
+QString configForFile(Utils::FilePath fileName);
+clang::format::FormatStyle styleForFile(Utils::FilePath fileName);
}
diff --git a/src/plugins/clangpchmanager/CMakeLists.txt b/src/plugins/clangpchmanager/CMakeLists.txt
new file mode 100644
index 0000000000..6b36a88060
--- /dev/null
+++ b/src/plugins/clangpchmanager/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_qtc_plugin(ClangPchManager
+ CONDITION TARGET libclang
+ DEPENDS ClangSupport CPlusPlus
+ DEFINES CLANGPCHMANAGER_LIB
+ PLUGIN_DEPENDS Core CppTools
+ SOURCES
+ clangpchmanager_global.h
+ clangpchmanagerplugin.cpp clangpchmanagerplugin.h
+ pchmanagerclient.cpp pchmanagerclient.h
+ pchmanagerconnectionclient.cpp pchmanagerconnectionclient.h
+ pchmanagernotifierinterface.cpp pchmanagernotifierinterface.h
+ pchmanagerprojectupdater.cpp pchmanagerprojectupdater.h
+ progressmanager.h
+ progressmanagerinterface.h
+ projectupdater.cpp projectupdater.h
+ qtcreatorprojectupdater.cpp qtcreatorprojectupdater.h
+)
diff --git a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp
index cf5aae1bde..c50a4db7b9 100644
--- a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp
+++ b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp
@@ -96,6 +96,8 @@ ClangPchManagerPlugin::~ClangPchManagerPlugin() = default;
bool ClangPchManagerPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorMessage*/)
{
+ QDir{}.mkpath(Core::ICore::cacheResourcePath());
+
d = std::make_unique<ClangPchManagerPluginData>();
startBackend();
diff --git a/src/plugins/clangpchmanager/pchmanagerclient.cpp b/src/plugins/clangpchmanager/pchmanagerclient.cpp
index c26b871f50..04d1d4a0bf 100644
--- a/src/plugins/clangpchmanager/pchmanagerclient.cpp
+++ b/src/plugins/clangpchmanager/pchmanagerclient.cpp
@@ -43,11 +43,8 @@ void PchManagerClient::alive()
void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message)
{
- for (ClangBackEnd::ProjectPartPch &projectPartPch : message.takeProjectPartPchs()) {
- const QString pchPath{projectPartPch.pchPath};
- addProjectPartPch(std::move(projectPartPch));
- precompiledHeaderUpdated(projectPartPch.projectPartId, pchPath, projectPartPch.lastModified);
- }
+ for (ClangBackEnd::ProjectPartId &projectPartId : message.takeProjectPartIds())
+ precompiledHeaderUpdated(projectPartId);
}
void PchManagerClient::progress(ClangBackEnd::ProgressMessage &&message)
@@ -66,10 +63,8 @@ void PchManagerClient::progress(ClangBackEnd::ProgressMessage &&message)
void PchManagerClient::precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId)
{
- for (auto notifier : m_notifiers) {
- removeProjectPartPch(projectPartId);
+ for (auto notifier : m_notifiers)
notifier->precompiledHeaderRemoved(projectPartId);
- }
}
void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectionClient)
@@ -77,22 +72,6 @@ void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectio
m_connectionClient = connectionClient;
}
-Utils::optional<ClangBackEnd::ProjectPartPch> PchManagerClient::projectPartPch(
- ClangBackEnd::ProjectPartId projectPartId) const
-{
- auto found = std::lower_bound(m_projectPartPchs.cbegin(),
- m_projectPartPchs.cend(),
- projectPartId,
- [] (const auto &projectPartPch, auto projectPartId) {
- return projectPartId < projectPartPch.projectPartId;
- });
-
- if (found != m_projectPartPchs.end() && found->projectPartId == projectPartId)
- return *found;
-
- return Utils::nullopt;
-}
-
void PchManagerClient::attach(PchManagerNotifierInterface *notifier)
{
m_notifiers.push_back(notifier);
@@ -109,47 +88,15 @@ void PchManagerClient::detach(PchManagerNotifierInterface *notifierToBeDeleted)
m_notifiers.erase(newEnd, m_notifiers.end());
}
-void PchManagerClient::removeProjectPartPch(ClangBackEnd::ProjectPartId projectPartId)
-{
- auto found = std::lower_bound(m_projectPartPchs.begin(),
- m_projectPartPchs.end(),
- projectPartId,
- [] (const auto &projectPartPch, auto projectPartId) {
- return projectPartId < projectPartPch.projectPartId;
- });
-
- if (found != m_projectPartPchs.end() && found->projectPartId == projectPartId) {
- *found = std::move(m_projectPartPchs.back());
- m_projectPartPchs.pop_back();
- }
-}
-
-void PchManagerClient::addProjectPartPch(ClangBackEnd::ProjectPartPch &&projectPartPch)
-{
- auto found = std::lower_bound(m_projectPartPchs.begin(),
- m_projectPartPchs.end(),
- projectPartPch.projectPartId,
- [] (const auto &projectPartPch, auto projectPartId) {
- return projectPartId < projectPartPch.projectPartId;
- });
-
- if (found != m_projectPartPchs.end() && found->projectPartId == projectPartPch.projectPartId)
- *found = std::move(projectPartPch);
- else
- m_projectPartPchs.insert(found, std::move(projectPartPch));
-}
-
const std::vector<PchManagerNotifierInterface *> &PchManagerClient::notifiers() const
{
return m_notifiers;
}
-void PchManagerClient::precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
- const QString &pchFilePath,
- long long lastModified)
+void PchManagerClient::precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId)
{
for (auto notifier : m_notifiers)
- notifier->precompiledHeaderUpdated(projectPartId, pchFilePath, lastModified);
+ notifier->precompiledHeaderUpdated(projectPartId);
}
} // namespace ClangPchManager
diff --git a/src/plugins/clangpchmanager/pchmanagerclient.h b/src/plugins/clangpchmanager/pchmanagerclient.h
index 308370356e..7d986a0ab6 100644
--- a/src/plugins/clangpchmanager/pchmanagerclient.h
+++ b/src/plugins/clangpchmanager/pchmanagerclient.h
@@ -28,7 +28,7 @@
#include "clangpchmanager_global.h"
#include <pchmanagerclientinterface.h>
-#include <projectpartpchproviderinterface.h>
+#include <projectpartid.h>
#include <vector>
@@ -37,8 +37,7 @@ class PchManagerConnectionClient;
class ProgressManagerInterface;
class PchManagerNotifierInterface;
-class CLANGPCHMANAGER_EXPORT PchManagerClient final : public ClangBackEnd::PchManagerClientInterface,
- public ClangBackEnd::ProjectPartPchProviderInterface
+class CLANGPCHMANAGER_EXPORT PchManagerClient final : public ClangBackEnd::PchManagerClientInterface
{
friend class PchManagerNotifierInterface;
public:
@@ -56,27 +55,13 @@ public:
void setConnectionClient(PchManagerConnectionClient *connectionClient);
- Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch(
- ClangBackEnd::ProjectPartId projectPartId) const override;
-
- const ClangBackEnd::ProjectPartPchs &projectPartPchs() const override
- {
- return m_projectPartPchs;
- }
-
unittest_public : const std::vector<PchManagerNotifierInterface *> &notifiers() const;
- void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
- const QString &pchFilePath,
- long long lastModified);
+ void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId);
void attach(PchManagerNotifierInterface *notifier);
void detach(PchManagerNotifierInterface *notifier);
- void addProjectPartPch(ClangBackEnd::ProjectPartPch &&projectPartPch);
- void removeProjectPartPch(ClangBackEnd::ProjectPartId projectPartId);
-
private:
- ClangBackEnd::ProjectPartPchs m_projectPartPchs;
std::vector<PchManagerNotifierInterface*> m_notifiers;
PchManagerConnectionClient *m_connectionClient=nullptr;
ProgressManagerInterface &m_pchCreationProgressManager;
diff --git a/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp b/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp
index a8e7e7a2ef..536d80bfb3 100644
--- a/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp
+++ b/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp
@@ -56,7 +56,8 @@ ClangPchManager::PchManagerConnectionClient::PchManagerConnectionClient(
pchsDirectory.cd("pchs");
m_processCreator.setArguments({connectionName(),
Core::ICore::cacheResourcePath() + "/symbol-experimental-v1.db",
- pchsDirectory.absolutePath()});
+ pchsDirectory.absolutePath(),
+ Core::ICore::resourcePath()});
stdErrPrefixer().setPrefix("PchManagerConnectionClient.stderr: ");
stdOutPrefixer().setPrefix("PchManagerConnectionClient.stdout: ");
diff --git a/src/plugins/clangpchmanager/pchmanagernotifierinterface.h b/src/plugins/clangpchmanager/pchmanagernotifierinterface.h
index 04461186d6..780ec5a2cd 100644
--- a/src/plugins/clangpchmanager/pchmanagernotifierinterface.h
+++ b/src/plugins/clangpchmanager/pchmanagernotifierinterface.h
@@ -42,10 +42,7 @@ public:
PchManagerNotifierInterface(const PchManagerNotifierInterface &) = delete;
PchManagerNotifierInterface &operator=(const PchManagerNotifierInterface &) = delete;
- virtual void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
- const QString &pchFilePath,
- long long lastModified)
- = 0;
+ virtual void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId) = 0;
virtual void precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId) = 0;
PchManagerClient &m_pchManagerClient;
diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp
index fc8db5bc07..3d340aea88 100644
--- a/src/plugins/clangpchmanager/projectupdater.cpp
+++ b/src/plugins/clangpchmanager/projectupdater.cpp
@@ -153,10 +153,10 @@ QStringList ProjectUpdater::toolChainArguments(CppTools::ProjectPart *projectPar
CompilerOptionsBuilder builder(*projectPart, CppTools::UseSystemHeader::Yes);
builder.addWordWidth();
- builder.addPicIfCompilerFlagsContainsIt();
- builder.addTargetTriple();
+ // builder.addTargetTriple(); TODO resarch why target triples are different
builder.addExtraCodeModelFlags();
builder.undefineClangVersionMacrosForMsvc();
+
builder.undefineCppLanguageFeatureMacrosForMsvc2015();
builder.addProjectConfigFileInclude();
builder.addMsvcCompatibilityVersion();
@@ -164,6 +164,19 @@ QStringList ProjectUpdater::toolChainArguments(CppTools::ProjectPart *projectPar
return builder.options();
}
+namespace {
+void cleanupMacros(ClangBackEnd::CompilerMacros &macros)
+{
+ auto newEnd = std::partition(macros.begin(),
+ macros.end(),
+ [](const ClangBackEnd::CompilerMacro &macro) {
+ return macro.key != "QT_TESTCASE_BUILDDIR";
+ });
+
+ macros.erase(newEnd, macros.end());
+}
+} // namespace
+
ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros(const ProjectExplorer::Macros &projectMacros)
{
int index = 0;
@@ -172,6 +185,8 @@ ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros(const ProjectE
return ClangBackEnd::CompilerMacro{macro.key, macro.value, ++index};
});
+ cleanupMacros(macros);
+
std::sort(macros.begin(), macros.end());
return macros;
diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
index a53bbc678a..1cdef70b79 100644
--- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
+++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
@@ -95,10 +95,10 @@ public:
protected:
void newExtraCompiler(const ProjectExplorer::Project *,
- const Utils::FileName &,
- const Utils::FileNameList &targets) override
+ const Utils::FilePath &,
+ const Utils::FilePathList &targets) override
{
- for (const Utils::FileName &target : targets)
+ for (const Utils::FilePath &target : targets)
abstractEditorUpdated(target.toString(), {});
}
diff --git a/src/plugins/clangrefactoring/CMakeLists.txt b/src/plugins/clangrefactoring/CMakeLists.txt
new file mode 100644
index 0000000000..1e20afad9b
--- /dev/null
+++ b/src/plugins/clangrefactoring/CMakeLists.txt
@@ -0,0 +1,40 @@
+add_qtc_plugin(ClangRefactoring
+ CONDITION TARGET libclang
+ DEPENDS ClangSupport CPlusPlus
+ PLUGIN_DEPENDS Core CppTools TextEditor ClangPchManager
+ SOURCES ${TEST_SOURCES}
+ baseclangquerytexteditorwidget.cpp baseclangquerytexteditorwidget.h
+ clangqueryexamplehighlighter.cpp clangqueryexamplehighlighter.h
+ clangqueryexamplehighlightmarker.h
+ clangqueryexampletexteditorwidget.cpp clangqueryexampletexteditorwidget.h
+ clangqueryhighlighter.cpp clangqueryhighlighter.h
+ clangqueryhighlightmarker.h
+ clangqueryhoverhandler.cpp clangqueryhoverhandler.h
+ clangqueryprojectsfindfilter.cpp clangqueryprojectsfindfilter.h clangqueryprojectsfindfilter.ui
+ clangqueryprojectsfindfilterwidget.cpp clangqueryprojectsfindfilterwidget.h
+ clangquerytexteditorwidget.cpp clangquerytexteditorwidget.h
+ clangrefactoringplugin.cpp clangrefactoringplugin.h
+ editormanagerinterface.h
+ locatorfilter.cpp locatorfilter.h
+ projectpartproviderinterface.h
+ projectpartutilities.cpp projectpartutilities.h
+ qtcreatorclangqueryfindfilter.cpp qtcreatorclangqueryfindfilter.h
+ qtcreatoreditormanager.cpp qtcreatoreditormanager.h
+ qtcreatorrefactoringprojectupdater.cpp qtcreatorrefactoringprojectupdater.h
+ qtcreatorsearch.cpp qtcreatorsearch.h
+ qtcreatorsearchhandle.cpp qtcreatorsearchhandle.h
+ qtcreatorsymbolsfindfilter.cpp qtcreatorsymbolsfindfilter.h
+ querysqlitestatementfactory.h
+ refactoringclient.cpp refactoringclient.h
+ refactoringconnectionclient.cpp refactoringconnectionclient.h
+ refactoringengine.cpp refactoringengine.h
+ refactoringprojectupdater.cpp refactoringprojectupdater.h
+ searchhandle.cpp searchhandle.h
+ searchinterface.h
+ sourcelocations.h
+ symbol.h
+ symbolquery.h
+ symbolqueryinterface.h
+ symbolsfindfilter.cpp symbolsfindfilter.h
+ symbolsfindfilterconfigwidget.cpp symbolsfindfilterconfigwidget.h
+)
diff --git a/src/plugins/clangrefactoring/clangrefactoring.qbs b/src/plugins/clangrefactoring/clangrefactoring.qbs
index af92d01aec..ec8c4c6a24 100644
--- a/src/plugins/clangrefactoring/clangrefactoring.qbs
+++ b/src/plugins/clangrefactoring/clangrefactoring.qbs
@@ -17,7 +17,6 @@ QtcPlugin {
Depends { name: "ProjectExplorer" }
Depends { name: "TextEditor" }
- cpp.defines: base.concat("CLANGPCHMANAGER_LIB")
cpp.includePaths: ["."]
files: [
@@ -50,6 +49,8 @@ QtcPlugin {
"qtcreatorclangqueryfindfilter.h",
"qtcreatoreditormanager.cpp",
"qtcreatoreditormanager.h",
+ "qtcreatorrefactoringprojectupdater.cpp",
+ "qtcreatorrefactoringprojectupdater.h",
"qtcreatorsearch.cpp",
"qtcreatorsearch.h",
"qtcreatorsearchhandle.cpp",
@@ -70,11 +71,11 @@ QtcPlugin {
"searchinterface.h",
"sourcelocations.h",
"symbol.h",
+ "symbolquery.h",
+ "symbolqueryinterface.h",
"symbolsfindfilter.cpp",
"symbolsfindfilter.h",
"symbolsfindfilterconfigwidget.cpp",
"symbolsfindfilterconfigwidget.h",
- "symbolquery.h",
- "symbolqueryinterface.h"
]
}
diff --git a/src/plugins/clangrefactoring/locatorfilter.cpp b/src/plugins/clangrefactoring/locatorfilter.cpp
index 15ecbb73d2..c8fcfcaec3 100644
--- a/src/plugins/clangrefactoring/locatorfilter.cpp
+++ b/src/plugins/clangrefactoring/locatorfilter.cpp
@@ -31,8 +31,6 @@
namespace ClangRefactoring {
-
-
QList<Core::LocatorFilterEntry> LocatorFilter::matchesFor(
QFutureInterface<Core::LocatorFilterEntry> &, const QString &searchTerm)
{
diff --git a/src/plugins/clangrefactoring/refactoringconnectionclient.cpp b/src/plugins/clangrefactoring/refactoringconnectionclient.cpp
index a42ed38a16..e94e8a311f 100644
--- a/src/plugins/clangrefactoring/refactoringconnectionclient.cpp
+++ b/src/plugins/clangrefactoring/refactoringconnectionclient.cpp
@@ -48,8 +48,9 @@ RefactoringConnectionClient::RefactoringConnectionClient(RefactoringClientInterf
, m_serverProxy(client)
{
m_processCreator.setTemporaryDirectoryPattern("clangrefactoringbackend-XXXXXX");
- m_processCreator.setArguments(
- {connectionName(), Core::ICore::cacheResourcePath() + "/symbol-experimental-v1.db"});
+ m_processCreator.setArguments({connectionName(),
+ Core::ICore::cacheResourcePath() + "/symbol-experimental-v1.db",
+ Core::ICore::resourcePath()});
stdErrPrefixer().setPrefix("RefactoringConnectionClient.stderr: ");
stdOutPrefixer().setPrefix("RefactoringConnectionClient.stdout: ");
diff --git a/src/plugins/clangrefactoring/refactoringprojectupdater.cpp b/src/plugins/clangrefactoring/refactoringprojectupdater.cpp
index 8cfd5b942a..20a9fce730 100644
--- a/src/plugins/clangrefactoring/refactoringprojectupdater.cpp
+++ b/src/plugins/clangrefactoring/refactoringprojectupdater.cpp
@@ -30,9 +30,7 @@
namespace ClangRefactoring {
-void RefactoringProjectUpdater::precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
- const QString &,
- long long)
+void RefactoringProjectUpdater::precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId)
{
const QString projectPartName = fetchProjectPartName(projectPartId);
diff --git a/src/plugins/clangrefactoring/refactoringprojectupdater.h b/src/plugins/clangrefactoring/refactoringprojectupdater.h
index a9559ef94e..0986e35cb0 100644
--- a/src/plugins/clangrefactoring/refactoringprojectupdater.h
+++ b/src/plugins/clangrefactoring/refactoringprojectupdater.h
@@ -47,9 +47,7 @@ public:
{
}
- void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
- const QString &pchFilePath,
- long long lastModified) override;
+ void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId) override;
void precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId) override;
private:
diff --git a/src/plugins/clangtools/CMakeLists.txt b/src/plugins/clangtools/CMakeLists.txt
new file mode 100644
index 0000000000..9e767418f0
--- /dev/null
+++ b/src/plugins/clangtools/CMakeLists.txt
@@ -0,0 +1,41 @@
+if (WITH_TESTS)
+ set(TST_COMPONENT QmakeProjectManager)
+endif()
+
+add_qtc_plugin(ClangTools
+ CONDITION TARGET libclang
+ DEPENDS ClangSupport libclang
+ PLUGIN_DEPENDS Core Debugger CppTools ${TST_COMPONENT}
+ INCLUDES ${CLANG_INCLUDE_DIRS}
+ SOURCES
+ clangfileinfo.h
+ clangfixitsrefactoringchanges.cpp clangfixitsrefactoringchanges.h
+ clangselectablefilesdialog.cpp clangselectablefilesdialog.h clangselectablefilesdialog.ui
+ clangtidyclazyruncontrol.cpp clangtidyclazyruncontrol.h
+ clangtidyclazyrunner.cpp clangtidyclazyrunner.h
+ clangtidyclazytool.cpp clangtidyclazytool.h
+ clangtool.cpp clangtool.h
+ clangtoolruncontrol.cpp clangtoolruncontrol.h
+ clangtoolrunner.cpp clangtoolrunner.h
+ clangtools_global.h
+ clangtoolsbasicsettings.cpp clangtoolsbasicsettings.h clangtoolsbasicsettings.ui
+ clangtoolsconfigwidget.cpp clangtoolsconfigwidget.h clangtoolsconfigwidget.ui
+ clangtoolsconstants.h
+ clangtoolsdiagnostic.cpp clangtoolsdiagnostic.h
+ clangtoolsdiagnosticmodel.cpp clangtoolsdiagnosticmodel.h
+ clangtoolsdiagnosticview.cpp clangtoolsdiagnosticview.h
+ clangtoolslogfilereader.cpp clangtoolslogfilereader.h
+ clangtoolsplugin.cpp clangtoolsplugin.h
+ clangtoolsprojectsettings.cpp clangtoolsprojectsettings.h
+ clangtoolsprojectsettingswidget.cpp clangtoolsprojectsettingswidget.h clangtoolsprojectsettingswidget.ui
+ clangtoolssettings.cpp clangtoolssettings.h
+ clangtoolsutils.cpp clangtoolsutils.h
+)
+
+extend_qtc_plugin(ClangTools
+ CONDITION WITH_TESTS
+ SOURCES
+ clangtoolspreconfiguredsessiontests.cpp clangtoolspreconfiguredsessiontests.h
+ clangtoolsunittests.cpp clangtoolsunittests.h
+ clangtoolsunittests.qrc
+)
diff --git a/src/plugins/clangtools/clangfileinfo.h b/src/plugins/clangtools/clangfileinfo.h
index 735028a1f9..eaeaecce12 100644
--- a/src/plugins/clangtools/clangfileinfo.h
+++ b/src/plugins/clangtools/clangfileinfo.h
@@ -37,14 +37,14 @@ class FileInfo
{
public:
FileInfo() = default;
- FileInfo(Utils::FileName file,
+ FileInfo(Utils::FilePath file,
CppTools::ProjectFile::Kind kind,
CppTools::ProjectPart::Ptr projectPart)
: file(std::move(file))
, kind(kind)
, projectPart(projectPart)
{}
- Utils::FileName file;
+ Utils::FilePath file;
CppTools::ProjectFile::Kind kind;
CppTools::ProjectPart::Ptr projectPart;
};
diff --git a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp
index c3b6f4ac3e..e32553f976 100644
--- a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp
+++ b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp
@@ -109,7 +109,7 @@ bool FixitsRefactoringFile::apply()
format(*indenter, doc, operationsForFile, i);
operationsForFile.clear();
indenter = std::unique_ptr<TextEditor::Indenter>(factory->createIndenter(doc));
- indenter->setFileName(Utils::FileName::fromString(op.fileName));
+ indenter->setFileName(Utils::FilePath::fromString(op.fileName));
}
QTextCursor cursor(doc);
diff --git a/src/plugins/clangtools/clangselectablefilesdialog.cpp b/src/plugins/clangtools/clangselectablefilesdialog.cpp
index 22c8d150c1..c6ad76ff0a 100644
--- a/src/plugins/clangtools/clangselectablefilesdialog.cpp
+++ b/src/plugins/clangtools/clangselectablefilesdialog.cpp
@@ -71,7 +71,7 @@ static void linkFileNode(Tree *parentNode, Tree *childNode)
parentNode->visibleFiles.append(childNode);
}
-static Tree *createDirNode(const QString &name, const FileName &filePath = FileName())
+static Tree *createDirNode(const QString &name, const FilePath &filePath = FilePath())
{
auto node = new Tree;
node->name = name;
@@ -106,7 +106,7 @@ public:
//
// For example, if a directory node if fully checked, there is no need to
// save all the children of that node.
- void minimalSelection(QSet<FileName> &checkedDirs, QSet<FileName> &checkedFiles) const
+ void minimalSelection(QSet<FilePath> &checkedDirs, QSet<FilePath> &checkedFiles) const
{
traverse(index(0, 0, QModelIndex()), [&](const QModelIndex &index){
auto node = static_cast<Tree *>(index.internalPointer());
@@ -124,7 +124,7 @@ public:
});
}
- void restoreMinimalSelection(const QSet<FileName> &dirs, const QSet<FileName> &files)
+ void restoreMinimalSelection(const QSet<FilePath> &dirs, const QSet<FilePath> &files)
{
if (dirs.isEmpty() && files.isEmpty())
return;
@@ -211,20 +211,20 @@ private:
// Add files outside of the base directory to a separate node
Tree *externalFilesNode = createDirNode(SelectableFilesDialog::tr(
"Files outside of the base directory"),
- FileName::fromString("/"));
+ FilePath::fromString("/"));
linkDirNode(m_root, externalFilesNode);
for (const FileInfo &fileInfo : outOfBaseDirFiles)
linkFileNode(externalFilesNode, createFileNode(fileInfo, true));
}
}
- Tree *buildProjectDirTree(const FileName &projectDir,
+ Tree *buildProjectDirTree(const FilePath &projectDir,
const FileInfos &fileInfos,
FileInfos &outOfBaseDirFiles) const
{
Tree *projectDirNode = createDirNode(projectDir.fileName(), projectDir);
- QHash<FileName, Tree *> dirsToNode;
+ QHash<FilePath, Tree *> dirsToNode;
dirsToNode.insert(projectDirNode->fullPath, projectDirNode);
for (const FileInfo &fileInfo : fileInfos) {
@@ -234,7 +234,7 @@ private:
}
// Find or create parent nodes
- FileName parentDir = fileInfo.file.parentDir();
+ FilePath parentDir = fileInfo.file.parentDir();
Tree *parentNode = dirsToNode[parentDir];
if (!parentNode) {
// Find nearest existing node
@@ -246,9 +246,9 @@ private:
}
// Create needed extra dir nodes
- FileName currentDirPath = parentDir;
+ FilePath currentDirPath = parentDir;
for (const QString &dirName : dirsToCreate) {
- currentDirPath.appendPath(dirName);
+ currentDirPath = currentDirPath.pathAppended(dirName);
Tree *newDirNode = createDirNode(dirName, currentDirPath);
linkDirNode(parentNode, newDirNode);
@@ -295,6 +295,7 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
CppTools::ClangDiagnosticConfigsSelectionWidget *diagnosticConfigsSelectionWidget
= m_ui->clangToolsBasicSettings->ui()->clangDiagnosticConfigsSelectionWidget;
QCheckBox *buildBeforeAnalysis = m_ui->clangToolsBasicSettings->ui()->buildBeforeAnalysis;
+ buildBeforeAnalysis->setToolTip(hintAboutBuildBeforeAnalysis());
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
m_customDiagnosticConfig = diagnosticConfiguration(settings);
@@ -316,7 +317,7 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
}
connect(m_ui->globalOrCustom,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
[=](int index){
m_ui->clangToolsBasicSettings->setEnabled(index == CustomSettings);
if (index == CustomSettings) {
@@ -337,6 +338,8 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
m_customDiagnosticConfig = currentConfigId;
});
connect(buildBeforeAnalysis, &QCheckBox::toggled, [this](bool checked) {
+ if (!checked)
+ showHintAboutBuildBeforeAnalysis();
if (m_ui->globalOrCustom->currentIndex() == CustomSettings)
m_buildBeforeAnalysis = checked;
});
@@ -380,8 +383,8 @@ void SelectableFilesDialog::accept()
settings->setBuildBeforeAnalysis(m_buildBeforeAnalysis);
// Save selection
- QSet<FileName> checkedDirs;
- QSet<FileName> checkedFiles;
+ QSet<FilePath> checkedDirs;
+ QSet<FilePath> checkedFiles;
m_filesModel->minimalSelection(checkedDirs, checkedFiles);
settings->setSelectedDirs(checkedDirs);
settings->setSelectedFiles(checkedFiles);
diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp
index a580704243..2bb0caf3aa 100644
--- a/src/plugins/clangtools/clangtidyclazyrunner.cpp
+++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp
@@ -86,12 +86,12 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis
const QString clazyChecks = m_diagnosticConfig.clazyChecks();
if (!clazyChecks.isEmpty()) {
arguments << XclangArgs({"-add-plugin",
- "clang-lazy",
- "-plugin-arg-clang-lazy",
+ "clazy",
+ "-plugin-arg-clazy",
"enable-all-fixits",
- "-plugin-arg-clang-lazy",
+ "-plugin-arg-clazy",
"no-autowrite-fixits",
- "-plugin-arg-clang-lazy",
+ "-plugin-arg-clazy",
m_diagnosticConfig.clazyChecks()});
}
diff --git a/src/plugins/clangtools/clangtidyclazytool.cpp b/src/plugins/clangtools/clangtidyclazytool.cpp
index 6d10e8d5f5..f07fdcd3f7 100644
--- a/src/plugins/clangtools/clangtidyclazytool.cpp
+++ b/src/plugins/clangtools/clangtidyclazytool.cpp
@@ -364,7 +364,7 @@ static ClangDiagnosticConfig getDiagnosticConfig(Project *project)
void ClangTidyClazyTool::startTool(bool askUserForFileSelection)
{
- auto runControl = new RunControl(nullptr, Constants::CLANGTIDYCLAZY_RUN_MODE);
+ auto runControl = new RunControl(Constants::CLANGTIDYCLAZY_RUN_MODE);
runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
@@ -423,7 +423,7 @@ void ClangTidyClazyTool::updateRunActions()
Target *target = project ? project->activeTarget() : nullptr;
const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
bool canRun = target && project->projectLanguages().contains(cxx)
- && ToolChainKitInformation::toolChain(target->kit(), cxx);
+ && ToolChainKitAspect::toolChain(target->kit(), cxx);
if (!canRun)
toolTip = tr("This is not a C++ project.");
@@ -464,7 +464,7 @@ void ClangTidyClazyTool::handleStateUpdate()
}
QList<Diagnostic> ClangTidyClazyTool::read(const QString &filePath,
- const Utils::FileName &projectRootDir,
+ const Utils::FilePath &projectRootDir,
const QString &logFilePath,
QString *errorMessage) const
{
diff --git a/src/plugins/clangtools/clangtidyclazytool.h b/src/plugins/clangtools/clangtidyclazytool.h
index 24aac6673b..c0765dc6a9 100644
--- a/src/plugins/clangtools/clangtidyclazytool.h
+++ b/src/plugins/clangtools/clangtidyclazytool.h
@@ -54,7 +54,7 @@ public:
void startTool(bool askUserForFileSelection) final;
QList<Diagnostic> read(const QString &filePath,
- const Utils::FileName &projectRootDir,
+ const Utils::FilePath &projectRootDir,
const QString &logFilePath,
QString *errorMessage) const final;
diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp
index 52746080c1..10295ed28b 100644
--- a/src/plugins/clangtools/clangtool.cpp
+++ b/src/plugins/clangtools/clangtool.cpp
@@ -79,7 +79,7 @@ static FileInfos sortedFileInfos(const QVector<CppTools::ProjectPart::Ptr> &proj
continue;
if (file.active && CppTools::ProjectFile::isSource(file.kind)) {
- fileInfos.emplace_back(Utils::FileName::fromString(file.path),
+ fileInfos.emplace_back(Utils::FilePath::fromString(file.path),
file.kind,
projectPart);
}
diff --git a/src/plugins/clangtools/clangtool.h b/src/plugins/clangtools/clangtool.h
index 65dde58009..0f322feb47 100644
--- a/src/plugins/clangtools/clangtool.h
+++ b/src/plugins/clangtools/clangtool.h
@@ -31,7 +31,7 @@
#include <cpptools/projectinfo.h>
namespace Debugger { class DetailedErrorView; }
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ClangTools {
namespace Internal {
@@ -50,7 +50,7 @@ public:
virtual void startTool(bool askUserForFileSelection) = 0;
virtual QList<Diagnostic> read(const QString &filePath,
- const Utils::FileName &projectRootDir,
+ const Utils::FilePath &projectRootDir,
const QString &logFilePath,
QString *errorMessage) const = 0;
diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp
index 26669dce5a..cc8dd24971 100644
--- a/src/plugins/clangtools/clangtoolruncontrol.cpp
+++ b/src/plugins/clangtools/clangtoolruncontrol.cpp
@@ -258,7 +258,7 @@ void ClangToolRunControl::init()
QTC_ASSERT(buildConfiguration, return);
m_environment = buildConfiguration->environment();
- ToolChain *toolChain = ToolChainKitInformation::toolChain(m_target->kit(),
+ ToolChain *toolChain = ToolChainKitAspect::toolChain(m_target->kit(),
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
QTC_ASSERT(toolChain, return);
m_targetTriple = toolChain->originalTargetTriple();
@@ -299,7 +299,7 @@ void ClangToolRunControl::start()
return;
}
- const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath();
+ const Utils::FilePath projectFile = m_projectInfo.project()->projectFilePath();
appendMessage(tr("Running %1 on %2").arg(toolName).arg(projectFile.toUserOutput()),
Utils::NormalMessageFormat);
@@ -386,13 +386,13 @@ void ClangToolRunControl::analyzeNextFile()
QTC_ASSERT(runner->run(unit.file, unit.arguments), return);
appendMessage(tr("Analyzing \"%1\".").arg(
- Utils::FileName::fromString(unit.file).toUserOutput()),
+ Utils::FilePath::fromString(unit.file).toUserOutput()),
Utils::StdOutFormat);
}
-static Utils::FileName cleanPath(const Utils::FileName &filePath)
+static Utils::FilePath cleanPath(const Utils::FilePath &filePath)
{
- return Utils::FileName::fromString(QDir::cleanPath(filePath.toString()));
+ return Utils::FilePath::fromString(QDir::cleanPath(filePath.toString()));
}
void ClangToolRunControl::onRunnerFinishedWithSuccess(const QString &filePath)
@@ -401,7 +401,7 @@ void ClangToolRunControl::onRunnerFinishedWithSuccess(const QString &filePath)
qCDebug(LOG) << "onRunnerFinishedWithSuccess:" << logFilePath;
QTC_ASSERT(m_projectInfo.project(), return);
- const Utils::FileName projectRootDir = cleanPath(m_projectInfo.project()->projectDirectory());
+ const Utils::FilePath projectRootDir = cleanPath(m_projectInfo.project()->projectDirectory());
QString errorMessage;
const QList<Diagnostic> diagnostics = tool()->read(filePath,
@@ -477,6 +477,16 @@ void ClangToolRunControl::finalize()
if (m_filesNotAnalyzed != 0) {
QString msg = tr("%1: Not all files could be analyzed.").arg(toolName);
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
+ if (m_target && !m_target->activeBuildConfiguration()->buildDirectory().exists()
+ && !ClangToolsProjectSettingsManager::getSettings(m_target->project())
+ ->buildBeforeAnalysis()) {
+ msg = tr("%1: You might need to build the project to generate or update source "
+ "files. To build automatically, enable \"Build the project before starting "
+ "analysis\".")
+ .arg(toolName);
+ TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
+ }
+
TaskHub::requestPopup();
}
diff --git a/src/plugins/clangtools/clangtoolruncontrol.h b/src/plugins/clangtools/clangtoolruncontrol.h
index ee4f8fe8ef..92ecb5e2b2 100644
--- a/src/plugins/clangtools/clangtoolruncontrol.h
+++ b/src/plugins/clangtools/clangtoolruncontrol.h
@@ -27,7 +27,7 @@
#include "clangfileinfo.h"
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <cpptools/projectinfo.h>
#include <utils/environment.h>
#include <utils/temporarydirectory.h>
diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp
index 227a94c50d..c02d59a7da 100644
--- a/src/plugins/clangtools/clangtoolrunner.cpp
+++ b/src/plugins/clangtools/clangtoolrunner.cpp
@@ -75,7 +75,7 @@ ClangToolRunner::ClangToolRunner(const QString &clangExecutable,
m_process.setProcessEnvironment(environment.toProcessEnvironment());
m_process.setWorkingDirectory(m_clangLogFileDir); // Current clang-cl puts log file into working dir.
connect(&m_process, &QProcess::started, this, &ClangToolRunner::onProcessStarted);
- connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &ClangToolRunner::onProcessFinished);
connect(&m_process, &QProcess::errorOccurred, this, &ClangToolRunner::onProcessError);
connect(&m_process, &QProcess::readyRead, this, &ClangToolRunner::onProcessOutput);
diff --git a/src/plugins/clangtools/clangtools.qbs b/src/plugins/clangtools/clangtools.qbs
index 7eb7e6c7c7..c7c34dd583 100644
--- a/src/plugins/clangtools/clangtools.qbs
+++ b/src/plugins/clangtools/clangtools.qbs
@@ -24,7 +24,6 @@ QtcPlugin {
condition: libclang.present
- cpp.defines: base.concat("CLANGPCHMANAGER_LIB")
cpp.includePaths: base.concat(libclang.llvmIncludeDir)
cpp.libraryPaths: base.concat(libclang.llvmLibDir)
cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
diff --git a/src/plugins/clangtools/clangtoolsconfigwidget.cpp b/src/plugins/clangtools/clangtoolsconfigwidget.cpp
index c42ed9fb47..b634875f97 100644
--- a/src/plugins/clangtools/clangtoolsconfigwidget.cpp
+++ b/src/plugins/clangtools/clangtoolsconfigwidget.cpp
@@ -52,13 +52,16 @@ ClangToolsConfigWidget::ClangToolsConfigWidget(
m_ui->simultaneousProccessesSpinBox->setMinimum(1);
m_ui->simultaneousProccessesSpinBox->setMaximum(QThread::idealThreadCount());
connect(m_ui->simultaneousProccessesSpinBox,
- static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ QOverload<int>::of(&QSpinBox::valueChanged),
[settings](int count) { settings->setSimultaneousProcesses(count); });
QCheckBox *buildBeforeAnalysis = m_ui->clangToolsBasicSettings->ui()->buildBeforeAnalysis;
+ buildBeforeAnalysis->setToolTip(hintAboutBuildBeforeAnalysis());
buildBeforeAnalysis->setCheckState(settings->savedBuildBeforeAnalysis()
? Qt::Checked : Qt::Unchecked);
connect(buildBeforeAnalysis, &QCheckBox::toggled, [settings](bool checked) {
+ if (!checked)
+ showHintAboutBuildBeforeAnalysis();
settings->setBuildBeforeAnalysis(checked);
});
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
index c0d64664bf..e5a97fea29 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
+++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
@@ -162,7 +162,7 @@ private:
void handleSuppressedDiagnosticsChanged();
QPointer<ProjectExplorer::Project> m_project;
- Utils::FileName m_lastProjectDirectory;
+ Utils::FilePath m_lastProjectDirectory;
SuppressedDiagnosticsList m_suppressedDiagnostics;
};
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticview.cpp b/src/plugins/clangtools/clangtoolsdiagnosticview.cpp
index 33b002ced2..e59b1f22f3 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticview.cpp
+++ b/src/plugins/clangtools/clangtoolsdiagnosticview.cpp
@@ -205,8 +205,8 @@ void DiagnosticView::suppressCurrentDiagnostic()
auto * const filterModel = static_cast<DiagnosticFilterModel *>(model());
ProjectExplorer::Project * const project = filterModel->project();
if (project) {
- Utils::FileName filePath = Utils::FileName::fromString(diag.location.filePath);
- const Utils::FileName relativeFilePath
+ Utils::FilePath filePath = Utils::FilePath::fromString(diag.location.filePath);
+ const Utils::FilePath relativeFilePath
= filePath.relativeChildPath(project->projectDirectory());
if (!relativeFilePath.isEmpty())
filePath = relativeFilePath;
diff --git a/src/plugins/clangtools/clangtoolslogfilereader.cpp b/src/plugins/clangtools/clangtoolslogfilereader.cpp
index e8a6fbcc96..63751181ee 100644
--- a/src/plugins/clangtools/clangtoolslogfilereader.cpp
+++ b/src/plugins/clangtools/clangtoolslogfilereader.cpp
@@ -122,7 +122,7 @@ static ExplainingStep buildFixIt(const CXDiagnostic cxDiagnostic, unsigned index
}
static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic,
- const Utils::FileName &projectRootDir,
+ const Utils::FilePath &projectRootDir,
const QString &nativeFilePath)
{
Diagnostic diagnostic;
@@ -135,7 +135,7 @@ static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic,
return diagnostic;
diagnostic.location = diagLocationFromSourceLocation(cxLocation);
- const auto diagnosticFilePath = Utils::FileName::fromString(diagnostic.location.filePath);
+ const auto diagnosticFilePath = Utils::FilePath::fromString(diagnostic.location.filePath);
if (!diagnosticFilePath.isChildOf(projectRootDir))
return diagnostic;
@@ -183,7 +183,7 @@ static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic,
}
static QList<Diagnostic> readSerializedDiagnostics_helper(const QString &filePath,
- const Utils::FileName &projectRootDir,
+ const Utils::FilePath &projectRootDir,
const QString &logFilePath)
{
QList<Diagnostic> list;
@@ -232,7 +232,7 @@ static bool checkFilePath(const QString &filePath, QString *errorMessage)
}
QList<Diagnostic> readSerializedDiagnostics(const QString &filePath,
- const Utils::FileName &projectRootDir,
+ const Utils::FilePath &projectRootDir,
const QString &logFilePath,
QString *errorMessage)
{
diff --git a/src/plugins/clangtools/clangtoolslogfilereader.h b/src/plugins/clangtools/clangtoolslogfilereader.h
index 3d8a776932..c95ce645ae 100644
--- a/src/plugins/clangtools/clangtoolslogfilereader.h
+++ b/src/plugins/clangtools/clangtoolslogfilereader.h
@@ -29,13 +29,13 @@
#include <QList>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ClangTools {
namespace Internal {
QList<Diagnostic> readSerializedDiagnostics(const QString &filePath,
- const Utils::FileName &projectRootDir,
+ const Utils::FilePath &projectRootDir,
const QString &logFilePath,
QString *errorMessage);
diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp
index 02dec92e37..fa0d6589d2 100644
--- a/src/plugins/clangtools/clangtoolsplugin.cpp
+++ b/src/plugins/clangtools/clangtoolsplugin.cpp
@@ -132,9 +132,9 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt
return true;
}
-QList<QObject *> ClangToolsPlugin::createTestObjects() const
+QVector<QObject *> ClangToolsPlugin::createTestObjects() const
{
- QList<QObject *> tests;
+ QVector<QObject *> tests;
#ifdef WITH_TESTS
tests << new PreconfiguredSessionTests;
tests << new ClangToolsUnitTests;
diff --git a/src/plugins/clangtools/clangtoolsplugin.h b/src/plugins/clangtools/clangtoolsplugin.h
index 1f14b0f455..7f24d79f4b 100644
--- a/src/plugins/clangtools/clangtoolsplugin.h
+++ b/src/plugins/clangtools/clangtoolsplugin.h
@@ -42,7 +42,7 @@ public:
private:
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final {}
- QList<QObject *> createTestObjects() const final;
+ QVector<QObject *> createTestObjects() const final;
class ClangToolsPluginPrivate *d = nullptr;
};
diff --git a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
index e31522f371..d4b4e03272 100644
--- a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
+++ b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
@@ -43,7 +43,7 @@
#include <utils/fileutils.h>
#include <QSignalSpy>
-#include <QTimer>
+#include <QElapsedTimer>
#include <QtTest>
#include <QVariant>
@@ -54,10 +54,10 @@ using namespace ProjectExplorer;
static bool processEventsUntil(const std::function<bool()> condition, int timeOutInMs = 30000)
{
- QTime t;
+ QElapsedTimer t;
t.start();
- forever {
+ while (true) {
if (t.elapsed() > timeOutInMs)
return false;
@@ -166,7 +166,7 @@ static QList<Target *> validTargets(Project *project)
return false;
}
- const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ const ToolChain * const toolchain = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
QTC_ASSERT(toolchain, return false);
if (Core::ICore::clangExecutable(CLANG_BINDIR).isEmpty()) {
diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.cpp b/src/plugins/clangtools/clangtoolsprojectsettings.cpp
index 9f2bad1999..55573c8ee6 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettings.cpp
+++ b/src/plugins/clangtools/clangtoolsprojectsettings.cpp
@@ -87,9 +87,11 @@ void ClangToolsProjectSettings::load()
m_useGlobalSettings = useGlobalVariant.isValid() ? useGlobalVariant.toBool() : true;
m_diagnosticConfig = Core::Id::fromSetting(
m_project->namedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG));
- m_buildBeforeAnalysis = m_project->namedSettings(SETTINGS_KEY_BUILD_BEFORE_ANALYSIS).toBool();
- auto toFileName = [](const QString &s) { return Utils::FileName::fromString(s); };
+ const QVariant value = m_project->namedSettings(SETTINGS_KEY_BUILD_BEFORE_ANALYSIS);
+ m_buildBeforeAnalysis = value.isValid() ? value.toBool() : true;
+
+ auto toFileName = [](const QString &s) { return Utils::FilePath::fromString(s); };
const QStringList dirs = m_project->namedSettings(SETTINGS_KEY_SELECTED_DIRS).toStringList();
m_selectedDirs = Utils::transform<QSet>(dirs, toFileName);
@@ -106,17 +108,15 @@ void ClangToolsProjectSettings::load()
const QString message = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_MESSAGE).toString();
if (message.isEmpty())
continue;
- Utils::FileName fullPath = Utils::FileName::fromString(fp);
- if (fullPath.toFileInfo().isRelative()) {
- fullPath = m_project->projectDirectory();
- fullPath.appendPath(fp);
- }
+ Utils::FilePath fullPath = Utils::FilePath::fromString(fp);
+ if (fullPath.toFileInfo().isRelative())
+ fullPath = m_project->projectDirectory().pathAppended(fp);
if (!fullPath.exists())
continue;
const QString contextKind = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_CONTEXTKIND).toString();
const QString context = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_CONTEXT).toString();
const int uniquifier = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_UNIQIFIER).toInt();
- m_suppressedDiagnostics << SuppressedDiagnostic(Utils::FileName::fromString(fp), message,
+ m_suppressedDiagnostics << SuppressedDiagnostic(Utils::FilePath::fromString(fp), message,
contextKind, context, uniquifier);
}
emit suppressedDiagnosticsChanged();
@@ -128,10 +128,10 @@ void ClangToolsProjectSettings::store()
m_project->setNamedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG, m_diagnosticConfig.toSetting());
m_project->setNamedSettings(SETTINGS_KEY_BUILD_BEFORE_ANALYSIS, m_buildBeforeAnalysis);
- const QStringList dirs = Utils::transform(m_selectedDirs.toList(), &Utils::FileName::toString);
+ const QStringList dirs = Utils::transform(m_selectedDirs.toList(), &Utils::FilePath::toString);
m_project->setNamedSettings(SETTINGS_KEY_SELECTED_DIRS, dirs);
- const QStringList files = Utils::transform(m_selectedFiles.toList(), &Utils::FileName::toString);
+ const QStringList files = Utils::transform(m_selectedFiles.toList(), &Utils::FilePath::toString);
m_project->setNamedSettings(SETTINGS_KEY_SELECTED_FILES, files);
QVariantList list;
@@ -201,7 +201,7 @@ void ClangToolsProjectSettingsManager::handleProjectToBeRemoved(ProjectExplorer:
ClangToolsProjectSettingsManager::SettingsMap ClangToolsProjectSettingsManager::m_settings;
SuppressedDiagnostic::SuppressedDiagnostic(const Diagnostic &diag)
- : filePath(Utils::FileName::fromString(diag.location.filePath))
+ : filePath(Utils::FilePath::fromString(diag.location.filePath))
, description(diag.description)
, contextKind(diag.issueContextKind)
, context(diag.issueContext)
diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.h b/src/plugins/clangtools/clangtoolsprojectsettings.h
index fb52862966..757140bc2c 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettings.h
+++ b/src/plugins/clangtools/clangtoolsprojectsettings.h
@@ -39,7 +39,7 @@ class Diagnostic;
class SuppressedDiagnostic
{
public:
- SuppressedDiagnostic(const Utils::FileName &filePath, const QString &description,
+ SuppressedDiagnostic(const Utils::FilePath &filePath, const QString &description,
const QString &contextKind, const QString &context, int uniquifier)
: filePath(filePath)
, description(description)
@@ -51,7 +51,7 @@ public:
SuppressedDiagnostic(const Diagnostic &diag);
- Utils::FileName filePath; // Relative for files in project, absolute otherwise.
+ Utils::FilePath filePath; // Relative for files in project, absolute otherwise.
QString description;
QString contextKind;
QString context;
@@ -84,11 +84,11 @@ public:
bool buildBeforeAnalysis() const;
void setBuildBeforeAnalysis(bool build);
- QSet<Utils::FileName> selectedDirs() const { return m_selectedDirs; }
- void setSelectedDirs(const QSet<Utils::FileName> &value) { m_selectedDirs = value; }
+ QSet<Utils::FilePath> selectedDirs() const { return m_selectedDirs; }
+ void setSelectedDirs(const QSet<Utils::FilePath> &value) { m_selectedDirs = value; }
- QSet<Utils::FileName> selectedFiles() const { return m_selectedFiles; }
- void setSelectedFiles(const QSet<Utils::FileName> &value) { m_selectedFiles = value; }
+ QSet<Utils::FilePath> selectedFiles() const { return m_selectedFiles; }
+ void setSelectedFiles(const QSet<Utils::FilePath> &value) { m_selectedFiles = value; }
SuppressedDiagnosticsList suppressedDiagnostics() const { return m_suppressedDiagnostics; }
void addSuppressedDiagnostic(const SuppressedDiagnostic &diag);
@@ -105,8 +105,8 @@ private:
ProjectExplorer::Project *m_project;
bool m_useGlobalSettings = true;
Core::Id m_diagnosticConfig;
- QSet<Utils::FileName> m_selectedDirs;
- QSet<Utils::FileName> m_selectedFiles;
+ QSet<Utils::FilePath> m_selectedDirs;
+ QSet<Utils::FilePath> m_selectedFiles;
SuppressedDiagnosticsList m_suppressedDiagnostics;
bool m_buildBeforeAnalysis = true;
};
diff --git a/src/plugins/clangtools/clangtoolsunittests.cpp b/src/plugins/clangtools/clangtoolsunittests.cpp
index 3e5d716116..ff1e7ab77c 100644
--- a/src/plugins/clangtools/clangtoolsunittests.cpp
+++ b/src/plugins/clangtools/clangtoolsunittests.cpp
@@ -58,7 +58,7 @@ void ClangToolsUnitTests::initTestCase()
const QList<Kit *> allKits = KitManager::kits();
if (allKits.count() != 1)
QSKIP("This test requires exactly one kit to be present");
- const ToolChain * const toolchain = ToolChainKitInformation::toolChain(allKits.first(),
+ const ToolChain * const toolchain = ToolChainKitAspect::toolChain(allKits.first(),
Constants::CXX_LANGUAGE_ID);
if (!toolchain)
QSKIP("This test requires that there is a kit with a toolchain.");
@@ -94,8 +94,8 @@ void ClangToolsUnitTests::testProject()
QFETCH(int, expectedDiagCount);
if (projectFilePath.contains("mingw")) {
const ToolChain * const toolchain
- = ToolChainKitInformation::toolChain(KitManager::kits().constFirst(),
- Constants::CXX_LANGUAGE_ID);
+ = ToolChainKitAspect::toolChain(KitManager::kits().constFirst(),
+ Constants::CXX_LANGUAGE_ID);
if (toolchain->typeId() != ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID)
QSKIP("This test is mingw specific, does not run for other toolchains");
}
diff --git a/src/plugins/clangtools/clangtoolsutils.cpp b/src/plugins/clangtools/clangtoolsutils.cpp
index 3e811500ac..173d97e31d 100644
--- a/src/plugins/clangtools/clangtoolsutils.cpp
+++ b/src/plugins/clangtools/clangtoolsutils.cpp
@@ -25,6 +25,7 @@
#include "clangtoolsutils.h"
+#include "clangtool.h"
#include "clangtoolsdiagnostic.h"
#include "clangtoolssettings.h"
@@ -32,8 +33,9 @@
#include <projectexplorer/projectexplorerconstants.h>
-#include <utils/hostosinfo.h>
+#include <utils/checkablemessagebox.h>
#include <utils/environment.h>
+#include <utils/hostosinfo.h>
#include <utils/synchronousprocess.h>
#include <QCoreApplication>
@@ -49,5 +51,24 @@ QString createFullLocationString(const Debugger::DiagnosticLocation &location)
+ QLatin1Char(':') + QString::number(location.column);
}
+QString hintAboutBuildBeforeAnalysis()
+{
+ return ClangTool::tr(
+ "In general, the project should be built before starting the analysis to ensure that the "
+ "code to analyze is valid.<br/><br/>"
+ "Building the project might also run code generators that update the source files as "
+ "necessary.");
+}
+
+void showHintAboutBuildBeforeAnalysis()
+{
+ Utils::CheckableMessageBox::doNotShowAgainInformation(
+ Core::ICore::dialogParent(),
+ ClangTool::tr("Info About Build the Project Before Analysis"),
+ hintAboutBuildBeforeAnalysis(),
+ Core::ICore::settings(),
+ "ClangToolsDisablingBuildBeforeAnalysisHint");
+}
+
} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/clangtools/clangtoolsutils.h b/src/plugins/clangtools/clangtoolsutils.h
index 6d3a7a90ca..05acb953c5 100644
--- a/src/plugins/clangtools/clangtoolsutils.h
+++ b/src/plugins/clangtools/clangtoolsutils.h
@@ -41,5 +41,8 @@ namespace Internal {
QString createFullLocationString(const Debugger::DiagnosticLocation &location);
+QString hintAboutBuildBeforeAnalysis();
+void showHintAboutBuildBeforeAnalysis();
+
} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/classview/CMakeLists.txt b/src/plugins/classview/CMakeLists.txt
new file mode 100644
index 0000000000..4861690e57
--- /dev/null
+++ b/src/plugins/classview/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_qtc_plugin(ClassView
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer TextEditor
+ SOURCES
+ classviewconstants.h
+ classviewmanager.cpp classviewmanager.h
+ classviewnavigationwidget.cpp classviewnavigationwidget.h
+ classviewnavigationwidgetfactory.cpp classviewnavigationwidgetfactory.h
+ classviewparser.cpp classviewparser.h
+ classviewparsertreeitem.cpp classviewparsertreeitem.h
+ classviewplugin.cpp classviewplugin.h
+ classviewsymbolinformation.cpp classviewsymbolinformation.h
+ classviewsymbollocation.cpp classviewsymbollocation.h
+ classviewtreeitemmodel.cpp classviewtreeitemmodel.h
+ classviewutils.cpp classviewutils.h
+)
diff --git a/src/plugins/classview/classviewparser.cpp b/src/plugins/classview/classviewparser.cpp
index 14034b46a3..34b6de2950 100644
--- a/src/plugins/classview/classviewparser.cpp
+++ b/src/plugins/classview/classviewparser.cpp
@@ -634,12 +634,12 @@ void Parser::resetData(const CPlusPlus::Snapshot &snapshot)
d->docLocker.unlock();
// recalculate file list
- ::Utils::FileNameList fileList;
+ ::Utils::FilePathList fileList;
// check all projects
for (const Project *prj : SessionManager::projects())
fileList += prj->files(Project::SourceFiles);
- setFileList(::Utils::transform(fileList, &::Utils::FileName::toString));
+ setFileList(::Utils::transform(fileList, &::Utils::FilePath::toString));
emit resetDataDone();
}
@@ -721,7 +721,7 @@ QStringList Parser::addProjectTree(const ParserTreeItem::Ptr &item, const Projec
if (cit != d->cachedPrjFileLists.constEnd()) {
fileList = cit.value();
} else {
- fileList = ::Utils::transform(project->files(Project::SourceFiles), &::Utils::FileName::toString);
+ fileList = ::Utils::transform(project->files(Project::SourceFiles), &::Utils::FilePath::toString);
d->cachedPrjFileLists[projectPath] = fileList;
}
if (fileList.count() > 0) {
@@ -746,7 +746,7 @@ QStringList Parser::getAllFiles(const Project *project)
if (cit != d->cachedPrjFileLists.constEnd()) {
fileList = cit.value();
} else {
- fileList = ::Utils::transform(project->files(Project::SourceFiles), &::Utils::FileName::toString);
+ fileList = ::Utils::transform(project->files(Project::SourceFiles), &::Utils::FilePath::toString);
d->cachedPrjFileLists[nodePath] = fileList;
}
return fileList;
diff --git a/src/plugins/clearcase/CMakeLists.txt b/src/plugins/clearcase/CMakeLists.txt
new file mode 100644
index 0000000000..08f09f0021
--- /dev/null
+++ b/src/plugins/clearcase/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_qtc_plugin(ClearCase
+ PLUGIN_DEPENDS Core ProjectExplorer TextEditor VcsBase
+ SOURCES
+ activityselector.cpp activityselector.h
+ annotationhighlighter.cpp annotationhighlighter.h
+ checkoutdialog.cpp checkoutdialog.h checkoutdialog.ui
+ clearcaseconstants.h
+ clearcasecontrol.cpp clearcasecontrol.h
+ clearcaseeditor.cpp clearcaseeditor.h
+ clearcaseplugin.cpp clearcaseplugin.h
+ clearcasesettings.cpp clearcasesettings.h
+ clearcasesubmiteditor.cpp clearcasesubmiteditor.h
+ clearcasesubmiteditorwidget.cpp clearcasesubmiteditorwidget.h
+ clearcasesync.cpp clearcasesync.h
+ settingspage.cpp settingspage.h settingspage.ui
+ undocheckout.ui
+ versionselector.cpp versionselector.h versionselector.ui
+)
diff --git a/src/plugins/clearcase/ClearCase.mimetypes.xml b/src/plugins/clearcase/ClearCase.mimetypes.xml
deleted file mode 100644
index c8979ed1d2..0000000000
--- a/src/plugins/clearcase/ClearCase.mimetypes.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0"?>
-<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
- <mime-type type="application/vnd.audc.text.clearcase.submit">
- <comment>ClearCase submit template</comment>
- <sub-class-of type="text/plain"/>
- </mime-type>
-</mime-info>
diff --git a/src/plugins/clearcase/activityselector.cpp b/src/plugins/clearcase/activityselector.cpp
index 8ef25aef40..8847f6416a 100644
--- a/src/plugins/clearcase/activityselector.cpp
+++ b/src/plugins/clearcase/activityselector.cpp
@@ -66,7 +66,7 @@ ActivitySelector::ActivitySelector(QWidget *parent) : QWidget(parent),
connect(btnAdd, &QToolButton::clicked, this, &ActivitySelector::newActivity);
refresh();
- connect(m_cmbActivity, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_cmbActivity, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ActivitySelector::userChanged);
}
@@ -103,10 +103,10 @@ void ActivitySelector::setActivity(const QString &act)
{
int index = m_cmbActivity->findData(act);
if (index != -1) {
- disconnect(m_cmbActivity, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ disconnect(m_cmbActivity, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ActivitySelector::userChanged);
m_cmbActivity->setCurrentIndex(index);
- connect(m_cmbActivity, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_cmbActivity, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ActivitySelector::userChanged);
}
}
diff --git a/src/plugins/clearcase/clearcasecontrol.cpp b/src/plugins/clearcase/clearcasecontrol.cpp
index ef18e6d62d..c3fdbc8d64 100644
--- a/src/plugins/clearcase/clearcasecontrol.cpp
+++ b/src/plugins/clearcase/clearcasecontrol.cpp
@@ -49,7 +49,7 @@ Core::Id ClearCaseControl::id() const
return Constants::VCS_ID_CLEARCASE;
}
-bool ClearCaseControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
+bool ClearCaseControl::isVcsFileOrDirectory(const Utils::FilePath &fileName) const
{
Q_UNUSED(fileName);
return false; // ClearCase has no files/directories littering the sources
diff --git a/src/plugins/clearcase/clearcasecontrol.h b/src/plugins/clearcase/clearcasecontrol.h
index 757ea34486..6a77fe592e 100644
--- a/src/plugins/clearcase/clearcasecontrol.h
+++ b/src/plugins/clearcase/clearcasecontrol.h
@@ -42,7 +42,7 @@ public:
QString displayName() const final;
Core::Id id() const final;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final;
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final;
bool managesDirectory(const QString &directory, QString *topLevel = nullptr) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index 6223bedd4b..f33fa88639 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -353,7 +353,7 @@ QString ClearCasePlugin::ccManagesDirectory(const QString &directory) const
foreach (const QString &relativeVobDir, vobs) {
const QString vobPath = QDir::cleanPath(rootDir + QDir::fromNativeSeparators(relativeVobDir));
const bool isManaged = (vobPath == directory)
- || FileName::fromString(directory).isChildOf(FileName::fromString(vobPath));
+ || FilePath::fromString(directory).isChildOf(FilePath::fromString(vobPath));
if (isManaged)
return vobPath;
}
@@ -390,7 +390,7 @@ QString ClearCasePlugin::findTopLevel(const QString &directory) const
// Do not check again if we've already tested that the dir is managed,
// or if it is a child of a managed dir (top level).
if ((directory == m_topLevel) ||
- FileName::fromString(directory).isChildOf(FileName::fromString(m_topLevel)))
+ FilePath::fromString(directory).isChildOf(FilePath::fromString(m_topLevel)))
return m_topLevel;
return ccManagesDirectory(directory);
@@ -1452,7 +1452,7 @@ ClearCasePlugin::runCleartool(const QString &workingDir,
}
const SynchronousProcessResponse sp_resp =
- VcsBasePlugin::runVcs(workingDir, FileName::fromUserInput(executable),
+ VcsBasePlugin::runVcs(workingDir, FilePath::fromUserInput(executable),
arguments, timeOutS,
flags, outputCodec);
@@ -2027,7 +2027,7 @@ void ClearCasePlugin::updateIndex()
return;
m_checkInAllAction->setEnabled(false);
m_statusMap->clear();
- QFuture<void> result = Utils::runAsync(sync, transform(project->files(Project::SourceFiles), &FileName::toString));
+ QFuture<void> result = Utils::runAsync(sync, transform(project->files(Project::SourceFiles), &FilePath::toString));
if (!m_settings.disableIndexer)
ProgressManager::addTask(result, tr("Updating ClearCase Index"), ClearCase::Constants::TASK_INDEX);
}
diff --git a/src/plugins/cmakeprojectmanager/CMakeLists.txt b/src/plugins/cmakeprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..6062e40d53
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/CMakeLists.txt
@@ -0,0 +1,42 @@
+add_qtc_plugin(CMakeProjectManager
+ DEPENDS qmljs
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer TextEditor QtSupport
+ PLUGIN_RECOMMENDS Designer
+ SOURCES
+ builddirmanager.cpp builddirmanager.h
+ builddirparameters.cpp builddirparameters.h
+ builddirreader.cpp builddirreader.h
+ cmake_global.h
+ cmakeautocompleter.cpp cmakeautocompleter.h
+ cmakebuildconfiguration.cpp cmakebuildconfiguration.h
+ cmakebuildsettingswidget.cpp cmakebuildsettingswidget.h
+ cmakebuildstep.cpp cmakebuildstep.h
+ cmakebuildtarget.h
+ cmakecbpparser.cpp cmakecbpparser.h
+ cmakeconfigitem.cpp cmakeconfigitem.h
+ cmakeeditor.cpp cmakeeditor.h
+ cmakefilecompletionassist.cpp cmakefilecompletionassist.h
+ cmakeindenter.cpp cmakeindenter.h
+ cmakekitinformation.cpp cmakekitinformation.h
+ cmakelocatorfilter.cpp cmakelocatorfilter.h
+ cmakeparser.cpp cmakeparser.h
+ cmakeproject.cpp cmakeproject.h
+ cmakeproject.qrc
+ cmakeprojectconstants.h
+ cmakeprojectimporter.cpp cmakeprojectimporter.h
+ cmakeprojectmanager.cpp cmakeprojectmanager.h
+ cmakeprojectnodes.cpp cmakeprojectnodes.h
+ cmakeprojectplugin.cpp cmakeprojectplugin.h
+ cmakerunconfiguration.cpp cmakerunconfiguration.h
+ cmakesettingspage.cpp cmakesettingspage.h
+ cmakespecificsettings.cpp cmakespecificsettings.h
+ cmakespecificsettingspage.cpp cmakespecificsettingspage.h cmakespecificsettingspage.ui
+ cmaketool.cpp cmaketool.h
+ cmaketoolmanager.cpp cmaketoolmanager.h
+ cmaketoolsettingsaccessor.cpp cmaketoolsettingsaccessor.h
+ configmodel.cpp configmodel.h
+ configmodelitemdelegate.cpp configmodelitemdelegate.h
+ servermode.cpp servermode.h
+ servermodereader.cpp servermodereader.h
+ tealeafreader.cpp tealeafreader.h
+)
diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp
index f17e356509..490082d517 100644
--- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp
@@ -50,6 +50,7 @@
#include <QSet>
using namespace ProjectExplorer;
+using namespace Utils;
namespace CMakeProjectManager {
namespace Internal {
@@ -61,9 +62,9 @@ namespace Internal {
BuildDirManager::BuildDirManager() = default;
BuildDirManager::~BuildDirManager() = default;
-Utils::FileName BuildDirManager::workDirectory(const BuildDirParameters &parameters) const
+Utils::FilePath BuildDirManager::workDirectory(const BuildDirParameters &parameters) const
{
- const Utils::FileName bdir = parameters.buildDirectory;
+ const Utils::FilePath bdir = parameters.buildDirectory;
const CMakeTool *cmake = parameters.cmakeTool();
if (bdir.exists()) {
m_buildDirToTempDir.erase(bdir);
@@ -87,7 +88,7 @@ Utils::FileName BuildDirManager::workDirectory(const BuildDirParameters &paramet
return bdir;
}
}
- return Utils::FileName::fromString(tmpDirIt->second->path());
+ return Utils::FilePath::fromString(tmpDirIt->second->path());
}
void BuildDirManager::emitDataAvailable()
@@ -260,7 +261,7 @@ bool BuildDirManager::persistCMakeState()
if (m_parameters.workDirectory == m_parameters.buildDirectory)
return false;
- const Utils::FileName buildDir = m_parameters.buildDirectory;
+ const Utils::FilePath buildDir = m_parameters.buildDirectory;
QDir dir(buildDir.toString());
dir.mkpath(buildDir.toString());
@@ -310,8 +311,8 @@ void BuildDirManager::clearCache()
QTC_ASSERT(m_parameters.isValid(), return);
QTC_ASSERT(!m_isHandlingError, return);
- auto cmakeCache = m_parameters.workDirectory.appendPath("CMakeCache.txt");
- auto cmakeFiles = m_parameters.workDirectory.appendPath("CMakeFiles");
+ const FilePath cmakeCache = m_parameters.workDirectory.pathAppended("CMakeCache.txt");
+ const FilePath cmakeFiles = m_parameters.workDirectory.pathAppended("CMakeFiles");
const bool mustCleanUp = cmakeCache.exists() || cmakeFiles.exists();
if (!mustCleanUp)
@@ -366,7 +367,7 @@ CMakeConfig BuildDirManager::takeCMakeConfiguration() const
return result;
}
-CMakeConfig BuildDirManager::parseCMakeConfiguration(const Utils::FileName &cacheFile,
+CMakeConfig BuildDirManager::parseCMakeConfiguration(const Utils::FilePath &cacheFile,
QString *errorMessage)
{
if (!cacheFile.exists()) {
@@ -413,7 +414,7 @@ bool BuildDirManager::checkConfiguration()
QStringList keyList = changedKeys.keys();
Utils::sort(keyList);
QString table = QString::fromLatin1("<table><tr><th>%1</th><th>%2</th><th>%3</th></tr>")
- .arg(tr("Key")).arg(tr("CMake")).arg(tr("Project"));
+ .arg(tr("Key")).arg(tr("CMakeCache.txt")).arg(tr("Project"));
foreach (const QString &k, keyList) {
const QPair<QString, QString> data = changedKeys.value(k);
table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td><td>%3</td></tr>")
@@ -426,7 +427,7 @@ bool BuildDirManager::checkConfiguration()
QPointer<QMessageBox> box = new QMessageBox(Core::ICore::mainWindow());
box->setText(tr("CMake configuration has changed on disk."));
box->setInformativeText(table);
- auto *defaultButton = box->addButton(tr("Overwrite Changes in CMake"), QMessageBox::RejectRole);
+ auto *defaultButton = box->addButton(tr("Overwrite Changes in CMakeCache.txt"), QMessageBox::RejectRole);
auto *applyButton = box->addButton(tr("Apply Changes to Project"), QMessageBox::ApplyRole);
box->setDefaultButton(defaultButton);
diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h
index d55e05aed2..e2f9b8ff05 100644
--- a/src/plugins/cmakeprojectmanager/builddirmanager.h
+++ b/src/plugins/cmakeprojectmanager/builddirmanager.h
@@ -81,7 +81,7 @@ public:
QList<CMakeBuildTarget> takeBuildTargets() const;
CMakeConfig takeCMakeConfiguration() const;
- static CMakeConfig parseCMakeConfiguration(const Utils::FileName &cacheFile,
+ static CMakeConfig parseCMakeConfiguration(const Utils::FilePath &cacheFile,
QString *errorMessage);
enum ReparseParameters { REPARSE_DEFAULT = 0, // use defaults
@@ -104,7 +104,7 @@ private:
void emitErrorOccured(const QString &message) const;
bool checkConfiguration();
- Utils::FileName workDirectory(const BuildDirParameters &parameters) const;
+ Utils::FilePath workDirectory(const BuildDirParameters &parameters) const;
void updateReaderType(const BuildDirParameters &p, std::function<void()> todo);
@@ -114,7 +114,7 @@ private:
void becameDirty();
BuildDirParameters m_parameters;
- mutable std::unordered_map<Utils::FileName, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir;
+ mutable std::unordered_map<Utils::FilePath, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir;
mutable std::unique_ptr<BuildDirReader> m_reader;
mutable bool m_isHandlingError = false;
};
diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.cpp b/src/plugins/cmakeprojectmanager/builddirparameters.cpp
index f4377d42ae..160b50bef1 100644
--- a/src/plugins/cmakeprojectmanager/builddirparameters.cpp
+++ b/src/plugins/cmakeprojectmanager/builddirparameters.cpp
@@ -61,25 +61,25 @@ BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
if (Utils::HostOsInfo::isAnyUnixHost())
environment.set("ICECC", "no");
- cmakeToolId = CMakeKitInformation::cmakeToolId(k);
+ cmakeToolId = CMakeKitAspect::cmakeToolId(k);
- auto tc = ToolChainKitInformation::toolChain(k, Constants::CXX_LANGUAGE_ID);
+ auto tc = ToolChainKitAspect::toolChain(k, Constants::CXX_LANGUAGE_ID);
if (tc)
cxxToolChainId = tc->id();
- tc = ToolChainKitInformation::toolChain(k, Constants::C_LANGUAGE_ID);
+ tc = ToolChainKitAspect::toolChain(k, Constants::C_LANGUAGE_ID);
if (tc)
cToolChainId = tc->id();
- sysRoot = SysRootKitInformation::sysRoot(k);
+ sysRoot = SysRootKitAspect::sysRoot(k);
expander = k->macroExpander();
configuration = bc->configurationForCMake();
- generator = CMakeGeneratorKitInformation::generator(k);
- extraGenerator = CMakeGeneratorKitInformation::extraGenerator(k);
- platform = CMakeGeneratorKitInformation::platform(k);
- toolset = CMakeGeneratorKitInformation::toolset(k);
- generatorArguments = CMakeGeneratorKitInformation::generatorArguments(k);
+ generator = CMakeGeneratorKitAspect::generator(k);
+ extraGenerator = CMakeGeneratorKitAspect::extraGenerator(k);
+ platform = CMakeGeneratorKitAspect::platform(k);
+ toolset = CMakeGeneratorKitAspect::toolset(k);
+ generatorArguments = CMakeGeneratorKitAspect::generatorArguments(k);
}
bool BuildDirParameters::isValid() const { return buildConfiguration && cmakeTool(); }
@@ -90,6 +90,7 @@ CMakeTool *BuildDirParameters::cmakeTool() const
}
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 92f5f16eee..d0bd9dd783 100644
--- a/src/plugins/cmakeprojectmanager/builddirparameters.h
+++ b/src/plugins/cmakeprojectmanager/builddirparameters.h
@@ -44,6 +44,7 @@ public:
BuildDirParameters();
BuildDirParameters(CMakeBuildConfiguration *bc);
BuildDirParameters(const BuildDirParameters &other);
+ BuildDirParameters &operator=(const BuildDirParameters &other);
bool isValid() const;
CMakeTool *cmakeTool() const;
@@ -51,16 +52,16 @@ public:
CMakeBuildConfiguration *buildConfiguration = nullptr;
QString projectName;
- Utils::FileName sourceDirectory;
- Utils::FileName buildDirectory;
- Utils::FileName workDirectory; // either buildDirectory or a QTemporaryDirectory!
+ Utils::FilePath sourceDirectory;
+ Utils::FilePath buildDirectory;
+ Utils::FilePath workDirectory; // either buildDirectory or a QTemporaryDirectory!
Utils::Environment environment;
Core::Id cmakeToolId;
QByteArray cxxToolChainId;
QByteArray cToolChainId;
- Utils::FileName sysRoot;
+ Utils::FilePath sysRoot;
Utils::MacroExpander *expander = nullptr;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
index 1deb85b1d1..f7cfa7f33f 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
@@ -34,6 +34,8 @@
#include "cmakeprojectmanager.h"
#include "cmakeprojectnodes.h"
+#include <android/androidconstants.h>
+
#include <coreplugin/icore.h>
#include <projectexplorer/buildinfo.h>
@@ -91,6 +93,37 @@ void CMakeBuildConfiguration::initialize(const BuildInfo &info)
BuildStepList *buildSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
buildSteps->appendStep(new CMakeBuildStep(buildSteps));
+ if (DeviceTypeKitAspect::deviceTypeId(target()->kit())
+ == Android::Constants::ANDROID_DEVICE_TYPE) {
+ buildSteps->appendStep(Android::Constants::ANDROID_BUILD_APK_ID);
+ const auto &bs = buildSteps->steps().constLast();
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_NATIVE_API_LEVEL",
+ CMakeProjectManager::CMakeConfigItem::Type::STRING,
+ "Android native API level",
+ bs->data(Android::Constants::AndroidNdkPlatform).toString().toUtf8()});
+ auto ndkLocation = bs->data(Android::Constants::NdkLocation).value<FilePath>();
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_NDK",
+ CMakeProjectManager::CMakeConfigItem::Type::PATH,
+ "Android NDK PATH",
+ ndkLocation.toUserOutput().toUtf8()});
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_TOOLCHAIN_FILE",
+ CMakeProjectManager::CMakeConfigItem::Type::PATH,
+ "Android CMake toolchain file",
+ ndkLocation.pathAppended("build/cmake/android.toolchain.cmake").toUserOutput().toUtf8()});
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_ABI",
+ CMakeProjectManager::CMakeConfigItem::Type::STRING,
+ "Android ABI",
+ bs->data(Android::Constants::AndroidABI).toString().toUtf8()});
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"ANDROID_STL",
+ CMakeProjectManager::CMakeConfigItem::Type::STRING,
+ "Android STL",
+ "c++_shared"});
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_PROGRAM", "BOTH"});
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY", "BOTH"});
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_INCLUDE", "BOTH"});
+ m_initialConfiguration.prepend(CMakeProjectManager::CMakeConfigItem{"CMAKE_FIND_ROOT_PATH_MODE_PACKAGE", "BOTH"});
+ }
+
BuildStepList *cleanSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN);
cleanSteps->appendStep(new CMakeBuildStep(cleanSteps));
@@ -159,23 +192,22 @@ bool CMakeBuildConfiguration::isParsing() const
return project()->isParsing() && isActive();
}
-BuildTargetInfoList CMakeBuildConfiguration::appTargets() const
+const QList<BuildTargetInfo> CMakeBuildConfiguration::appTargets() const
{
- BuildTargetInfoList appTargetList;
-
+ QList<BuildTargetInfo> appTargetList;
+ bool forAndroid = DeviceTypeKitAspect::deviceTypeId(target()->kit()) == Android::Constants::ANDROID_DEVICE_TYPE;
for (const CMakeBuildTarget &ct : m_buildTargets) {
if (ct.targetType == UtilityType)
continue;
- if (ct.targetType == ExecutableType) {
+ if (ct.targetType == ExecutableType || (forAndroid && ct.targetType == DynamicLibraryType)) {
BuildTargetInfo bti;
bti.displayName = ct.title;
bti.targetFilePath = ct.executable;
- bti.projectFilePath = ct.sourceDirectory;
- bti.projectFilePath.appendString('/');
+ bti.projectFilePath = ct.sourceDirectory.stringAppended("/");
bti.workingDirectory = ct.workingDirectory;
- bti.buildKey = ct.title + QChar('\n') + bti.projectFilePath.toString();
- appTargetList.list.append(bti);
+ bti.buildKey = CMakeTargetNode::generateId(ct.sourceDirectory, ct.title);
+ appTargetList.append(bti);
}
}
@@ -197,11 +229,11 @@ DeploymentData CMakeBuildConfiguration::deploymentData() const
deploymentFilePath = buildDir.filePath("QtCreatorDeployment.txt");
hasDeploymentFile = QFileInfo::exists(deploymentFilePath);
}
- if (hasDeploymentFile) {
- deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath,
- sourceDir.absolutePath());
- }
+ if (!hasDeploymentFile)
+ return result;
+ deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath,
+ sourceDir.absolutePath());
for (const CMakeBuildTarget &ct : m_buildTargets) {
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) {
if (!ct.executable.isEmpty()
@@ -221,20 +253,25 @@ QStringList CMakeBuildConfiguration::buildTargetTitles() const
return transform(m_buildTargets, &CMakeBuildTarget::title);
}
-FileName CMakeBuildConfiguration::shadowBuildDirectory(const FileName &projectFilePath,
+const QList<CMakeBuildTarget> &CMakeBuildConfiguration::buildTargets() const
+{
+ return m_buildTargets;
+}
+
+FilePath CMakeBuildConfiguration::shadowBuildDirectory(const FilePath &projectFilePath,
const Kit *k,
const QString &bcName,
BuildConfiguration::BuildType buildType)
{
if (projectFilePath.isEmpty())
- return FileName();
+ return FilePath();
const QString projectName = projectFilePath.parentDir().fileName();
ProjectMacroExpander expander(projectFilePath.toString(), projectName, k, bcName, buildType);
QDir projectDir = QDir(Project::projectDirectory(projectFilePath).toString());
QString buildPath = expander.expand(ProjectExplorerPlugin::buildDirectoryTemplate());
buildPath.replace(" ", "-");
- return FileName::fromUserInput(projectDir.absoluteFilePath(buildPath));
+ return FilePath::fromUserInput(projectDir.absoluteFilePath(buildPath));
}
void CMakeBuildConfiguration::buildTarget(const QString &buildTarget)
@@ -342,10 +379,14 @@ static CMakeConfig removeDuplicates(const CMakeConfig &config)
void CMakeBuildConfiguration::setConfigurationForCMake(const CMakeConfig &config)
{
- m_configurationForCMake = removeDuplicates(config);
+ auto configs = removeDuplicates(config);
+ if (m_configurationForCMake.isEmpty())
+ m_configurationForCMake = removeDuplicates(configs + m_initialConfiguration);
+ else
+ m_configurationForCMake = configs;
const Kit *k = target()->kit();
- CMakeConfig kitConfig = CMakeConfigurationKitInformation::configuration(k);
+ CMakeConfig kitConfig = CMakeConfigurationKitAspect::configuration(k);
bool hasKitOverride = false;
foreach (const CMakeConfigItem &i, m_configurationForCMake) {
const QString b = CMakeConfigItem::expandedValueOf(k, i.key, kitConfig);
@@ -365,7 +406,7 @@ void CMakeBuildConfiguration::setConfigurationForCMake(const CMakeConfig &config
CMakeConfig CMakeBuildConfiguration::configurationForCMake() const
{
- return removeDuplicates(CMakeConfigurationKitInformation::configuration(target()->kit()) + m_configurationForCMake);
+ return removeDuplicates(CMakeConfigurationKitAspect::configuration(target()->kit()) + m_configurationForCMake);
}
void CMakeBuildConfiguration::setError(const QString &message)
@@ -455,17 +496,12 @@ QList<BuildInfo> CMakeBuildConfigurationFactory::availableBuilds(const Target *p
QList<BuildInfo> CMakeBuildConfigurationFactory::availableSetups(const Kit *k, const QString &projectPath) const
{
QList<BuildInfo> result;
- const FileName projectPathName = FileName::fromString(projectPath);
- for (int type = BuildTypeNone; type != BuildTypeLast; ++type) {
+ const FilePath projectPathName = FilePath::fromString(projectPath);
+ for (int type = BuildTypeDebug; type != BuildTypeLast; ++type) {
BuildInfo info = createBuildInfo(k,
ProjectExplorer::Project::projectDirectory(projectPathName).toString(),
BuildType(type));
- if (type == BuildTypeNone) {
- //: The name of the build configuration created by default for a cmake project.
- info.displayName = tr("Default");
- } else {
- info.displayName = info.typeName;
- }
+ info.displayName = info.typeName;
info.buildDirectory
= CMakeBuildConfiguration::shadowBuildDirectory(projectPathName, k,
info.displayName, info.buildType);
@@ -517,10 +553,10 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(const Kit *k,
if (!buildTypeItem.isNull())
extra.configuration.append(buildTypeItem);
- const QString sysRoot = SysRootKitInformation::sysRoot(k).toString();
+ const QString sysRoot = SysRootKitAspect::sysRoot(k).toString();
if (!sysRoot.isEmpty()) {
extra.configuration.append(CMakeConfigItem("CMAKE_SYSROOT", sysRoot.toUtf8()));
- ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(
+ ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitAspect::toolChain(
k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (tc) {
const QByteArray targetTriple = tc->originalTargetTriple().toUtf8();
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
index 587666b0bf..050dd6f084 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
@@ -63,16 +63,16 @@ public:
QString warning() const;
QStringList buildTargetTitles() const;
- ProjectExplorer::BuildTargetInfoList appTargets() const;
+ const QList<CMakeBuildTarget> &buildTargets() const;
+ const QList<ProjectExplorer::BuildTargetInfo> appTargets() const;
ProjectExplorer::DeploymentData deploymentData() const;
- static Utils::FileName
- shadowBuildDirectory(const Utils::FileName &projectFilePath, const ProjectExplorer::Kit *k,
+ static Utils::FilePath
+ shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k,
const QString &bcName, BuildConfiguration::BuildType buildType);
// Context menu action:
void buildTarget(const QString &buildTarget);
-
signals:
void errorOccured(const QString &message);
void warningOccured(const QString &message);
@@ -104,6 +104,7 @@ private:
void setWarning(const QString &message);
CMakeConfig m_configurationForCMake;
+ CMakeConfig m_initialConfiguration;
QString m_error;
QString m_warning;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
index 192d3b0af5..cf94cbf23d 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
@@ -111,7 +111,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(buildDirChooser, &Utils::PathChooser::rawPathChanged, this,
[this](const QString &path) {
m_configModel->flush(); // clear out config cache...
- m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(path));
+ m_buildConfiguration->setBuildDirectory(Utils::FilePath::fromString(path));
});
int row = 0;
@@ -385,7 +385,7 @@ void CMakeBuildSettingsWidget::updateAdvancedCheckBox()
void CMakeBuildSettingsWidget::updateFromKit()
{
const ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit();
- const CMakeConfig config = CMakeConfigurationKitInformation::configuration(k);
+ const CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
QHash<QString, QString> configHash;
for (const CMakeConfigItem &i : config)
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
index 40a809f581..364337308b 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
@@ -160,16 +160,16 @@ bool CMakeBuildStep::init()
emit addTask(Task(Task::Error,
QCoreApplication::translate("CMakeProjectManager::CMakeBuildStep",
"The build configuration is currently disabled."),
- Utils::FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
canInit = false;
}
- CMakeTool *tool = CMakeKitInformation::cmakeTool(target()->kit());
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(target()->kit());
if (!tool || !tool->isValid()) {
emit addTask(Task(Task::Error,
tr("A CMake tool must be set up for building. "
"Configure a CMake tool in the kit options."),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
canInit = false;
}
@@ -181,7 +181,7 @@ bool CMakeBuildStep::init()
"You asked to build the current Run Configuration's build target only, "
"but it is not associated with a build target. "
"Update the Make Step in your build settings."),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
canInit = false;
}
@@ -192,23 +192,19 @@ bool CMakeBuildStep::init()
}
// Warn if doing out-of-source builds with a CMakeCache.txt is the source directory
- const Utils::FileName projectDirectory = bc->target()->project()->projectDirectory();
+ const Utils::FilePath projectDirectory = bc->target()->project()->projectDirectory();
if (bc->buildDirectory() != projectDirectory) {
- Utils::FileName cmc = projectDirectory;
- cmc.appendPath("CMakeCache.txt");
- if (cmc.exists()) {
+ if (projectDirectory.pathAppended("CMakeCache.txt").exists()) {
emit addTask(Task(Task::Warning,
tr("There is a CMakeCache.txt file in \"%1\", which suggest an "
"in-source build was done before. You are now building in \"%2\", "
"and the CMakeCache.txt file might confuse CMake.")
.arg(projectDirectory.toUserOutput(), bc->buildDirectory().toUserOutput()),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
- QString arguments = allArguments(rc);
-
setIgnoreReturnValue(m_buildTarget == CMakeBuildStep::cleanTarget());
ProcessParameters *pp = processParameters();
@@ -218,9 +214,8 @@ bool CMakeBuildStep::init()
if (!env.value("NINJA_STATUS").startsWith(m_ninjaProgressString))
env.set("NINJA_STATUS", m_ninjaProgressString + "%o/sec] ");
pp->setEnvironment(env);
- pp->setWorkingDirectory(bc->buildDirectory().toString());
- pp->setCommand(cmakeCommand());
- pp->setArguments(arguments);
+ pp->setWorkingDirectory(bc->buildDirectory());
+ pp->setCommandLine(cmakeCommand(rc));
pp->resolveAll();
setOutputParser(new CMakeParser);
@@ -344,12 +339,12 @@ void CMakeBuildStep::setToolArguments(const QString &list)
m_toolArguments = list;
}
-QString CMakeBuildStep::allArguments(const CMakeRunConfiguration *rc) const
+Utils::CommandLine CMakeBuildStep::cmakeCommand(CMakeRunConfiguration *rc) const
{
- QString arguments;
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(target()->kit());
- Utils::QtcProcess::addArg(&arguments, "--build");
- Utils::QtcProcess::addArg(&arguments, ".");
+ Utils::CommandLine cmd(tool ? tool->cmakeExecutable() : Utils::FilePath(), {});
+ cmd.addArgs({"--build", "."});
QString target;
@@ -362,21 +357,14 @@ QString CMakeBuildStep::allArguments(const CMakeRunConfiguration *rc) const
target = m_buildTarget;
}
- Utils::QtcProcess::addArg(&arguments, "--target");
- Utils::QtcProcess::addArg(&arguments, target);
+ cmd.addArgs({"--target", target});
if (!m_toolArguments.isEmpty()) {
- Utils::QtcProcess::addArg(&arguments, "--");
- arguments += ' ' + m_toolArguments;
+ cmd.addArg("--");
+ cmd.addArgs(m_toolArguments);
}
- return arguments;
-}
-
-QString CMakeBuildStep::cmakeCommand() const
-{
- CMakeTool *tool = CMakeKitInformation::cmakeTool(target()->kit());
- return tool ? tool->cmakeExecutable().toString() : QString();
+ return cmd;
}
QString CMakeBuildStep::cleanTarget()
@@ -531,9 +519,8 @@ void CMakeBuildStepConfigWidget::updateDetails()
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
param.setEnvironment(bc->environment());
- param.setWorkingDirectory(bc->buildDirectory().toString());
- param.setCommand(m_buildStep->cmakeCommand());
- param.setArguments(m_buildStep->allArguments(nullptr));
+ param.setWorkingDirectory(bc->buildDirectory());
+ param.setCommandLine(m_buildStep->cmakeCommand(nullptr));
setSummaryText(param.summary(displayName()));
}
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
index 9e76889d28..9b906f883f 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
@@ -35,7 +35,10 @@ class QListWidget;
class QListWidgetItem;
QT_END_NAMESPACE
-namespace Utils { class PathChooser; }
+namespace Utils {
+class CommandLine;
+class PathChooser;
+} // Utils
namespace ProjectExplorer { class ToolChain; }
@@ -64,9 +67,7 @@ public:
QString toolArguments() const;
void setToolArguments(const QString &list);
- QString allArguments(const CMakeRunConfiguration *rc) const;
-
- QString cmakeCommand() const;
+ Utils::CommandLine cmakeCommand(CMakeRunConfiguration *rc) const;
QVariantMap toMap() const override;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp
deleted file mode 100644
index 357f66f6a5..0000000000
--- a/src/plugins/cmakeprojectmanager/cmakebuildtarget.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 "cmakebuildtarget.h"
-
-using namespace Utils;
-
-namespace CMakeProjectManager {
-
-void CMakeBuildTarget::clear()
-{
- executable.clear();
- makeCommand.clear();
- workingDirectory.clear();
- sourceDirectory.clear();
- title.clear();
- targetType = UtilityType;
- includeFiles.clear();
- compilerOptions.clear();
- macros.clear();
- files.clear();
-}
-
-} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildtarget.h b/src/plugins/cmakeprojectmanager/cmakebuildtarget.h
index 1b3f5fb700..e46394bef5 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildtarget.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildtarget.h
@@ -46,19 +46,17 @@ class CMAKE_EXPORT CMakeBuildTarget
{
public:
QString title;
- Utils::FileName executable; // TODO: rename to output?
+ Utils::FilePath executable; // TODO: rename to output?
TargetType targetType = UtilityType;
- Utils::FileName workingDirectory;
- Utils::FileName sourceDirectory;
- Utils::FileName makeCommand;
+ Utils::FilePath workingDirectory;
+ Utils::FilePath sourceDirectory;
+ Utils::FilePath makeCommand;
// code model
- QList<Utils::FileName> includeFiles;
+ QList<Utils::FilePath> includeFiles;
QStringList compilerOptions;
ProjectExplorer::Macros macros;
- QList<Utils::FileName> files;
-
- void clear();
+ QList<Utils::FilePath> files;
};
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp
index e5344df26f..b257d78619 100644
--- a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp
@@ -46,7 +46,7 @@ namespace Internal {
////
namespace {
-int distance(const FileName &targetDirectory, const FileName &fileName)
+int distance(const FilePath &targetDirectory, const FilePath &fileName)
{
const QString commonParent = commonPath(QStringList({targetDirectory.toString(), fileName.toString()}));
return targetDirectory.toString().midRef(commonParent.size()).count('/')
@@ -61,12 +61,12 @@ int distance(const FileName &targetDirectory, const FileName &fileName)
void CMakeCbpParser::sortFiles()
{
QLoggingCategory log("qtc.cmakeprojectmanager.filetargetmapping", QtWarningMsg);
- FileNameList fileNames = transform<QList>(m_fileList, &FileNode::filePath);
+ FilePathList fileNames = transform<QList>(m_fileList, &FileNode::filePath);
sort(fileNames);
CMakeBuildTarget *last = nullptr;
- FileName parentDirectory;
+ FilePath parentDirectory;
qCDebug(log) << "###############";
qCDebug(log) << "# Pre Dump #";
@@ -96,7 +96,7 @@ void CMakeCbpParser::sortFiles()
qCDebug(log) << "# Sorting #";
qCDebug(log) << "###############";
- foreach (const FileName &fileName, fileNames) {
+ foreach (const FilePath &fileName, fileNames) {
qCDebug(log) << fileName;
const QStringList unitTargets = m_unitTargetMap[fileName];
if (!unitTargets.isEmpty()) {
@@ -160,12 +160,12 @@ void CMakeCbpParser::sortFiles()
<< target.files << "\n";
}
-bool CMakeCbpParser::parseCbpFile(CMakeTool::PathMapper mapper, const FileName &fileName,
- const FileName &sourceDirectory)
+bool CMakeCbpParser::parseCbpFile(CMakeTool::PathMapper mapper, const FilePath &fileName,
+ const FilePath &sourceDirectory)
{
m_pathMapper = mapper;
- m_buildDirectory = FileName::fromString(fileName.toFileInfo().absolutePath());
+ m_buildDirectory = FilePath::fromString(fileName.toFileInfo().absolutePath());
m_sourceDirectory = sourceDirectory;
QFile fi(fileName.toString());
@@ -234,7 +234,7 @@ void CMakeCbpParser::parseBuild()
void CMakeCbpParser::parseBuildTarget()
{
- m_buildTarget.clear();
+ m_buildTarget = CMakeBuildTarget();
if (attributes().hasAttribute("title"))
m_buildTarget.title = attributes().value("title").toString();
@@ -263,7 +263,7 @@ void CMakeCbpParser::parseBuildTarget()
void CMakeCbpParser::parseBuildTargetOption()
{
if (attributes().hasAttribute("output")) {
- m_buildTarget.executable = m_pathMapper(FileName::fromString(attributes().value("output").toString()));
+ m_buildTarget.executable = m_pathMapper(FilePath::fromString(attributes().value("output").toString()));
} else if (attributes().hasAttribute("type")) {
const QStringRef value = attributes().value("type");
if (value == "0" || value == "1")
@@ -275,7 +275,7 @@ void CMakeCbpParser::parseBuildTargetOption()
else
m_buildTarget.targetType = UtilityType;
} else if (attributes().hasAttribute("working_dir")) {
- m_buildTarget.workingDirectory = FileName::fromUserInput(attributes().value("working_dir").toString());
+ m_buildTarget.workingDirectory = FilePath::fromUserInput(attributes().value("working_dir").toString());
QFile cmakeSourceInfoFile(m_buildTarget.workingDirectory.toString()
+ QStringLiteral("/CMakeFiles/CMakeDirectoryInformation.cmake"));
@@ -287,7 +287,7 @@ void CMakeCbpParser::parseBuildTargetOption()
if (lineTopSource.startsWith(searchSource, Qt::CaseInsensitive)) {
QString src = lineTopSource.mid(searchSource.size());
src.chop(2);
- m_buildTarget.sourceDirectory = FileName::fromString(src);
+ m_buildTarget.sourceDirectory = FilePath::fromString(src);
break;
}
}
@@ -296,8 +296,7 @@ void CMakeCbpParser::parseBuildTargetOption()
if (m_buildTarget.sourceDirectory.isEmpty()) {
QDir dir(m_buildDirectory.toString());
const QString relative = dir.relativeFilePath(m_buildTarget.workingDirectory.toString());
- m_buildTarget.sourceDirectory = m_sourceDirectory;
- m_buildTarget.sourceDirectory.appendPath(relative).toString();
+ m_buildTarget.sourceDirectory = m_sourceDirectory.pathAppended(relative);
}
}
while (!atEnd()) {
@@ -349,7 +348,7 @@ void CMakeCbpParser::parseMakeCommands()
void CMakeCbpParser::parseBuildTargetBuild()
{
if (attributes().hasAttribute("command"))
- m_buildTarget.makeCommand = m_pathMapper(FileName::fromUserInput(attributes().value("command").toString()));
+ m_buildTarget.makeCommand = m_pathMapper(FilePath::fromUserInput(attributes().value("command").toString()));
while (!atEnd()) {
readNext();
if (isEndElement())
@@ -388,8 +387,8 @@ void CMakeCbpParser::parseAdd()
// CMake only supports <Add option=\> and <Add directory=\>
const QXmlStreamAttributes addAttributes = attributes();
- FileName includeDirectory
- = m_pathMapper(FileName::fromString(addAttributes.value("directory").toString()));
+ FilePath includeDirectory
+ = m_pathMapper(FilePath::fromString(addAttributes.value("directory").toString()));
// allow adding multiple times because order happens
if (!includeDirectory.isEmpty())
@@ -417,8 +416,8 @@ void CMakeCbpParser::parseAdd()
void CMakeCbpParser::parseUnit()
{
- FileName fileName =
- m_pathMapper(FileName::fromUserInput(attributes().value("filename").toString()));
+ FilePath fileName =
+ m_pathMapper(FilePath::fromUserInput(attributes().value("filename").toString()));
m_parsingCMakeUnit = false;
m_unitTargets.clear();
@@ -429,7 +428,7 @@ void CMakeCbpParser::parseUnit()
// Now check whether we found a virtual element beneath
if (m_parsingCMakeUnit) {
m_cmakeFileList.emplace_back(
- std::make_unique<FileNode>(fileName, FileType::Project, false));
+ std::make_unique<FileNode>(fileName, FileType::Project));
} else {
bool generated = false;
QString onlyFileName = fileName.fileName();
@@ -440,13 +439,12 @@ void CMakeCbpParser::parseUnit()
if (fileName.endsWith(".qrc")) {
m_fileList.emplace_back(
- std::make_unique<FileNode>(fileName, FileType::Resource,
- generated));
+ std::make_unique<FileNode>(fileName, FileType::Resource));
} else {
m_fileList.emplace_back(
- std::make_unique<FileNode>(fileName, FileType::Source,
- generated));
+ std::make_unique<FileNode>(fileName, FileType::Source));
}
+ m_fileList.back()->setIsGenerated(generated);
}
m_unitTargetMap.insert(fileName, m_unitTargets);
m_processedUnits.insert(fileName);
diff --git a/src/plugins/cmakeprojectmanager/cmakecbpparser.h b/src/plugins/cmakeprojectmanager/cmakecbpparser.h
index 44da473bcf..8a8d5fbe7f 100644
--- a/src/plugins/cmakeprojectmanager/cmakecbpparser.h
+++ b/src/plugins/cmakeprojectmanager/cmakecbpparser.h
@@ -46,8 +46,8 @@ namespace Internal {
class CMakeCbpParser : public QXmlStreamReader
{
public:
- bool parseCbpFile(CMakeTool::PathMapper mapper, const Utils::FileName &fileName,
- const Utils::FileName &sourceDirectory);
+ bool parseCbpFile(CMakeTool::PathMapper mapper, const Utils::FilePath &fileName,
+ const Utils::FilePath &sourceDirectory);
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> &&
takeFileList() { return std::move(m_fileList); }
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> &&
@@ -74,19 +74,19 @@ private:
void parseUnknownElement();
void sortFiles();
- QMap<Utils::FileName, QStringList> m_unitTargetMap;
+ QMap<Utils::FilePath, QStringList> m_unitTargetMap;
CMakeTool::PathMapper m_pathMapper;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_fileList;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_cmakeFileList;
- QSet<Utils::FileName> m_processedUnits;
+ QSet<Utils::FilePath> m_processedUnits;
bool m_parsingCMakeUnit = false;
CMakeBuildTarget m_buildTarget;
QList<CMakeBuildTarget> m_buildTargets;
QString m_projectName;
QString m_compiler;
- Utils::FileName m_sourceDirectory;
- Utils::FileName m_buildDirectory;
+ Utils::FilePath m_sourceDirectory;
+ Utils::FilePath m_buildDirectory;
QStringList m_unitTargets;
};
diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp
index 082b2816c9..c3e27c001b 100644
--- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.cpp
@@ -42,12 +42,6 @@ namespace CMakeProjectManager {
CMakeConfigItem::CMakeConfigItem() = default;
-CMakeConfigItem::CMakeConfigItem(const CMakeConfigItem &other) : // What about inCMakeCache?
- key(other.key), type(other.type), isAdvanced(other.isAdvanced),
- isUnset(other.isUnset), value(other.value),
- documentation(other.documentation), values(other.values)
-{}
-
CMakeConfigItem::CMakeConfigItem(const QByteArray &k, Type t,
const QByteArray &d, const QByteArray &v) :
key(k), type(t), value(v), documentation(d)
@@ -249,7 +243,7 @@ static QByteArrayList splitCMakeCacheLine(const QByteArray &line) {
<< line.mid(equalPos + 1);
}
-QList<CMakeConfigItem> CMakeConfigItem::itemsFromFile(const Utils::FileName &cacheFile, QString *errorMessage)
+QList<CMakeConfigItem> CMakeConfigItem::itemsFromFile(const Utils::FilePath &cacheFile, QString *errorMessage)
{
CMakeConfig result;
QFile cache(cacheFile.toString());
diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigitem.h b/src/plugins/cmakeprojectmanager/cmakeconfigitem.h
index 07409d9a36..16bc8acea3 100644
--- a/src/plugins/cmakeprojectmanager/cmakeconfigitem.h
+++ b/src/plugins/cmakeprojectmanager/cmakeconfigitem.h
@@ -32,7 +32,7 @@
namespace ProjectExplorer { class Kit; }
namespace Utils {
-class FileName;
+class FilePath;
class MacroExpander;
} // namespace Utils
@@ -42,7 +42,6 @@ class CMakeConfigItem {
public:
enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC };
CMakeConfigItem();
- CMakeConfigItem(const CMakeConfigItem &other);
CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v);
CMakeConfigItem(const QByteArray &k, const QByteArray &v);
@@ -58,7 +57,7 @@ public:
static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator();
static CMakeConfigItem fromString(const QString &s);
- static QList<CMakeConfigItem> itemsFromFile(const Utils::FileName &input, QString *errorMessage);
+ static QList<CMakeConfigItem> itemsFromFile(const Utils::FilePath &input, QString *errorMessage);
QString toString(const Utils::MacroExpander *expander = nullptr) const;
QString toArgument(const Utils::MacroExpander *expander = nullptr) const;
diff --git a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp
index 2a5cf769a8..07f350caf1 100644
--- a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp
@@ -55,6 +55,7 @@ CMakeFileCompletionAssist::CMakeFileCompletionAssist() :
KeywordsCompletionAssistProcessor(Keywords())
{
setSnippetGroup(Constants::CMAKE_SNIPPETS_GROUP_ID);
+ setDynamicCompletionFunction(&TextEditor::pathComplete);
}
IAssistProposal *CMakeFileCompletionAssist::perform(const AssistInterface *interface)
@@ -62,9 +63,9 @@ IAssistProposal *CMakeFileCompletionAssist::perform(const AssistInterface *inter
Keywords kw;
QString fileName = interface->fileName();
if (!fileName.isEmpty() && QFileInfo(fileName).isFile()) {
- Project *p = SessionManager::projectForFile(Utils::FileName::fromString(fileName));
+ Project *p = SessionManager::projectForFile(Utils::FilePath::fromString(fileName));
if (p && p->activeTarget()) {
- CMakeTool *cmake = CMakeKitInformation::cmakeTool(p->activeTarget()->kit());
+ CMakeTool *cmake = CMakeKitAspect::cmakeTool(p->activeTarget()->kit());
if (cmake && cmake->isValid())
kw = cmake->keywords();
}
diff --git a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h
index 387addeac1..220ed6ce26 100644
--- a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h
+++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h
@@ -31,7 +31,6 @@
namespace CMakeProjectManager {
namespace Internal {
-
class CMakeFileCompletionAssist : public TextEditor::KeywordsCompletionAssistProcessor
{
public:
diff --git a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp
deleted file mode 100644
index d264f1324f..0000000000
--- a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "cmakeprojectconstants.h"
-#include "cmakekitconfigwidget.h"
-#include "cmakekitinformation.h"
-#include "cmaketoolmanager.h"
-#include "cmaketool.h"
-
-#include <coreplugin/icore.h>
-#include <coreplugin/variablechooser.h>
-#include <projectexplorer/kit.h>
-#include <projectexplorer/projectexplorerconstants.h>
-
-#include <utils/algorithm.h>
-#include <utils/elidinglabel.h>
-#include <utils/qtcassert.h>
-
-#include <QBoxLayout>
-#include <QComboBox>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QLabel>
-#include <QLineEdit>
-#include <QPlainTextEdit>
-#include <QPointer>
-#include <QPushButton>
-
-using namespace ProjectExplorer;
-
-namespace CMakeProjectManager {
-namespace Internal {
-
-// --------------------------------------------------------------------
-// CMakeKitConfigWidget:
-// --------------------------------------------------------------------
-
-CMakeKitConfigWidget::CMakeKitConfigWidget(Kit *kit,
- const KitInformation *ki) :
- KitConfigWidget(kit, ki),
- m_comboBox(new QComboBox),
- m_manageButton(new QPushButton(KitConfigWidget::msgManage()))
-{
- m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
- m_comboBox->setEnabled(false);
- m_comboBox->setToolTip(toolTip());
-
- foreach (CMakeTool *tool, CMakeToolManager::cmakeTools())
- cmakeToolAdded(tool->id());
-
- updateComboBox();
-
- refresh();
- connect(m_comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &CMakeKitConfigWidget::currentCMakeToolChanged);
-
- m_manageButton->setContentsMargins(0, 0, 0, 0);
- connect(m_manageButton, &QPushButton::clicked,
- this, &CMakeKitConfigWidget::manageCMakeTools);
-
- CMakeToolManager *cmakeMgr = CMakeToolManager::instance();
- connect(cmakeMgr, &CMakeToolManager::cmakeAdded,
- this, &CMakeKitConfigWidget::cmakeToolAdded);
- connect(cmakeMgr, &CMakeToolManager::cmakeRemoved,
- this, &CMakeKitConfigWidget::cmakeToolRemoved);
- connect(cmakeMgr, &CMakeToolManager::cmakeUpdated,
- this, &CMakeKitConfigWidget::cmakeToolUpdated);
-}
-
-CMakeKitConfigWidget::~CMakeKitConfigWidget()
-{
- delete m_comboBox;
- delete m_manageButton;
-}
-
-QString CMakeKitConfigWidget::displayName() const
-{
- return tr("CMake Tool");
-}
-
-void CMakeKitConfigWidget::makeReadOnly()
-{
- m_comboBox->setEnabled(false);
-}
-
-void CMakeKitConfigWidget::refresh()
-{
- CMakeTool *tool = CMakeKitInformation::cmakeTool(m_kit);
- m_comboBox->setCurrentIndex(tool ? indexOf(tool->id()) : -1);
-}
-
-QWidget *CMakeKitConfigWidget::mainWidget() const
-{
- return m_comboBox;
-}
-
-QWidget *CMakeKitConfigWidget::buttonWidget() const
-{
- return m_manageButton;
-}
-
-QString CMakeKitConfigWidget::toolTip() const
-{
- return tr("The CMake Tool to use when building a project with CMake.<br>"
- "This setting is ignored when using other build systems.");
-}
-
-int CMakeKitConfigWidget::indexOf(const Core::Id &id)
-{
- for (int i = 0; i < m_comboBox->count(); ++i) {
- if (id == Core::Id::fromSetting(m_comboBox->itemData(i)))
- return i;
- }
- return -1;
-}
-
-void CMakeKitConfigWidget::cmakeToolAdded(const Core::Id &id)
-{
- const CMakeTool *tool = CMakeToolManager::findById(id);
- QTC_ASSERT(tool, return);
-
- m_comboBox->addItem(tool->displayName(), tool->id().toSetting());
- updateComboBox();
- refresh();
-}
-
-void CMakeKitConfigWidget::cmakeToolUpdated(const Core::Id &id)
-{
- const int pos = indexOf(id);
- QTC_ASSERT(pos >= 0, return);
-
- const CMakeTool *tool = CMakeToolManager::findById(id);
- QTC_ASSERT(tool, return);
-
- m_comboBox->setItemText(pos, tool->displayName());
-}
-
-void CMakeKitConfigWidget::cmakeToolRemoved(const Core::Id &id)
-{
- const int pos = indexOf(id);
- QTC_ASSERT(pos >= 0, return);
-
- // do not handle the current index changed signal
- m_removingItem = true;
- m_comboBox->removeItem(pos);
- m_removingItem = false;
-
- // update the checkbox and set the current index
- updateComboBox();
- refresh();
-}
-
-void CMakeKitConfigWidget::updateComboBox()
-{
- // remove unavailable cmake tool:
- int pos = indexOf(Core::Id());
- if (pos >= 0)
- m_comboBox->removeItem(pos);
-
- if (m_comboBox->count() == 0) {
- m_comboBox->addItem(tr("<No CMake Tool available>"),
- Core::Id().toSetting());
- m_comboBox->setEnabled(false);
- } else {
- m_comboBox->setEnabled(true);
- }
-}
-
-void CMakeKitConfigWidget::currentCMakeToolChanged(int index)
-{
- if (m_removingItem)
- return;
-
- const Core::Id id = Core::Id::fromSetting(m_comboBox->itemData(index));
- CMakeKitInformation::setCMakeTool(m_kit, id);
-}
-
-void CMakeKitConfigWidget::manageCMakeTools()
-{
- Core::ICore::showOptionsDialog(Constants::CMAKE_SETTINGSPAGE_ID,
- buttonWidget());
-}
-
-// --------------------------------------------------------------------
-// CMakeGeneratorKitConfigWidget:
-// --------------------------------------------------------------------
-
-
-CMakeGeneratorKitConfigWidget::CMakeGeneratorKitConfigWidget(Kit *kit,
- const KitInformation *ki) :
- KitConfigWidget(kit, ki),
- m_label(new QLabel),
- m_changeButton(new QPushButton)
-{
- m_label->setToolTip(toolTip());
- m_changeButton->setText(tr("Change..."));
-
- refresh();
- connect(m_changeButton, &QPushButton::clicked,
- this, &CMakeGeneratorKitConfigWidget::changeGenerator);
-}
-
-CMakeGeneratorKitConfigWidget::~CMakeGeneratorKitConfigWidget()
-{
- delete m_label;
- delete m_changeButton;
-}
-
-QString CMakeGeneratorKitConfigWidget::displayName() const
-{
- return tr("CMake generator");
-}
-
-void CMakeGeneratorKitConfigWidget::makeReadOnly()
-{
- m_changeButton->setEnabled(false);
-}
-
-void CMakeGeneratorKitConfigWidget::refresh()
-{
- if (m_ignoreChange)
- return;
-
- CMakeTool *const tool = CMakeKitInformation::cmakeTool(m_kit);
- if (tool != m_currentTool)
- m_currentTool = tool;
-
- m_changeButton->setEnabled(m_currentTool);
- const QString generator = CMakeGeneratorKitInformation::generator(kit());
- const QString extraGenerator = CMakeGeneratorKitInformation::extraGenerator(kit());
- const QString platform = CMakeGeneratorKitInformation::platform(kit());
- const QString toolset = CMakeGeneratorKitInformation::toolset(kit());
-
- const QString message = tr("%1 - %2, Platform: %3, Toolset: %4")
- .arg(extraGenerator.isEmpty() ? tr("<none>") : extraGenerator)
- .arg(generator.isEmpty() ? tr("<none>") : generator)
- .arg(platform.isEmpty() ? tr("<none>") : platform)
- .arg(toolset.isEmpty() ? tr("<none>") : toolset);
- m_label->setText(message);
-}
-
-QWidget *CMakeGeneratorKitConfigWidget::mainWidget() const
-{
- return m_label;
-}
-
-QWidget *CMakeGeneratorKitConfigWidget::buttonWidget() const
-{
- return m_changeButton;
-}
-
-QString CMakeGeneratorKitConfigWidget::toolTip() const
-{
- return tr("CMake generator defines how a project is built when using CMake.<br>"
- "This setting is ignored when using other build systems.");
-}
-
-void CMakeGeneratorKitConfigWidget::changeGenerator()
-{
- QPointer<QDialog> changeDialog = new QDialog(m_changeButton);
-
- // Disable help button in titlebar on windows:
- Qt::WindowFlags flags = changeDialog->windowFlags();
- flags &= ~Qt::WindowContextHelpButtonHint;
- flags |= Qt::MSWindowsFixedSizeDialogHint;
- changeDialog->setWindowFlags(flags);
-
- changeDialog->setWindowTitle(tr("CMake Generator"));
-
- auto *layout = new QGridLayout(changeDialog);
- layout->setSizeConstraint(QLayout::SetFixedSize);
-
- auto *cmakeLabel = new QLabel;
- cmakeLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
-
- auto *generatorCombo = new QComboBox;
- auto *extraGeneratorCombo = new QComboBox;
- auto *platformEdit = new QLineEdit;
- auto *toolsetEdit = new QLineEdit;
-
- int row = 0;
- layout->addWidget(new QLabel(QLatin1String("Executable:")));
- layout->addWidget(cmakeLabel, row, 1);
-
- ++row;
- layout->addWidget(new QLabel(tr("Generator:")), row, 0);
- layout->addWidget(generatorCombo, row, 1);
-
- ++row;
- layout->addWidget(new QLabel(tr("Extra generator:")), row, 0);
- layout->addWidget(extraGeneratorCombo, row, 1);
-
- ++row;
- layout->addWidget(new QLabel(tr("Platform:")), row, 0);
- layout->addWidget(platformEdit, row, 1);
-
- ++row;
- layout->addWidget(new QLabel(tr("Toolset:")), row, 0);
- layout->addWidget(toolsetEdit, row, 1);
-
- ++row;
- auto *bb = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- layout->addWidget(bb, row, 0, 1, 2);
-
- connect(bb, &QDialogButtonBox::accepted, changeDialog.data(), &QDialog::accept);
- connect(bb, &QDialogButtonBox::rejected, changeDialog.data(), &QDialog::reject);
-
- cmakeLabel->setText(m_currentTool->cmakeExecutable().toUserOutput());
-
- QList<CMakeTool::Generator> generatorList = m_currentTool->supportedGenerators();
- Utils::sort(generatorList, &CMakeTool::Generator::name);
-
- for (auto it = generatorList.constBegin(); it != generatorList.constEnd(); ++it)
- generatorCombo->addItem(it->name);
-
- auto updateDialog = [&generatorList, generatorCombo, extraGeneratorCombo,
- platformEdit, toolsetEdit](const QString &name) {
- auto it = std::find_if(generatorList.constBegin(), generatorList.constEnd(),
- [name](const CMakeTool::Generator &g) { return g.name == name; });
- QTC_ASSERT(it != generatorList.constEnd(), return);
- generatorCombo->setCurrentText(name);
-
- extraGeneratorCombo->clear();
- extraGeneratorCombo->addItem(tr("<none>"), QString());
- foreach (const QString &eg, it->extraGenerators)
- extraGeneratorCombo->addItem(eg, eg);
- extraGeneratorCombo->setEnabled(extraGeneratorCombo->count() > 1);
-
- platformEdit->setEnabled(it->supportsPlatform);
- toolsetEdit->setEnabled(it->supportsToolset);
- };
-
- updateDialog(CMakeGeneratorKitInformation::generator(kit()));
-
- generatorCombo->setCurrentText(CMakeGeneratorKitInformation::generator(kit()));
- extraGeneratorCombo->setCurrentText(CMakeGeneratorKitInformation::extraGenerator(kit()));
- platformEdit->setText(platformEdit->isEnabled() ? CMakeGeneratorKitInformation::platform(kit()) : QLatin1String("<unsupported>"));
- toolsetEdit->setText(toolsetEdit->isEnabled() ? CMakeGeneratorKitInformation::toolset(kit()) : QLatin1String("<unsupported>"));
-
- connect(generatorCombo, &QComboBox::currentTextChanged, updateDialog);
-
- if (changeDialog->exec() == QDialog::Accepted) {
- if (!changeDialog)
- return;
-
- CMakeGeneratorKitInformation::set(kit(), generatorCombo->currentText(),
- extraGeneratorCombo->currentData().toString(),
- platformEdit->isEnabled() ? platformEdit->text() : QString(),
- toolsetEdit->isEnabled() ? toolsetEdit->text() : QString());
- }
-}
-
-// --------------------------------------------------------------------
-// CMakeConfigurationKitConfigWidget:
-// --------------------------------------------------------------------
-
-CMakeConfigurationKitConfigWidget::CMakeConfigurationKitConfigWidget(Kit *kit,
- const KitInformation *ki) :
- KitConfigWidget(kit, ki),
- m_summaryLabel(new Utils::ElidingLabel),
- m_manageButton(new QPushButton)
-{
- refresh();
- m_manageButton->setText(tr("Change..."));
- connect(m_manageButton, &QAbstractButton::clicked,
- this, &CMakeConfigurationKitConfigWidget::editConfigurationChanges);
-}
-
-QString CMakeConfigurationKitConfigWidget::displayName() const
-{
- return tr("CMake Configuration");
-}
-
-void CMakeConfigurationKitConfigWidget::makeReadOnly()
-{
- m_manageButton->setEnabled(false);
- if (m_dialog)
- m_dialog->reject();
-}
-
-void CMakeConfigurationKitConfigWidget::refresh()
-{
- const QStringList current = CMakeConfigurationKitInformation::toStringList(kit());
-
- m_summaryLabel->setText(current.join("; "));
- if (m_editor)
- m_editor->setPlainText(current.join('\n'));
-}
-
-QWidget *CMakeConfigurationKitConfigWidget::mainWidget() const
-{
- return m_summaryLabel;
-}
-
-QWidget *CMakeConfigurationKitConfigWidget::buttonWidget() const
-{
- return m_manageButton;
-}
-
-QString CMakeConfigurationKitConfigWidget::toolTip() const
-{
- return tr("Default configuration passed to CMake when setting up a project.");
-}
-
-void CMakeConfigurationKitConfigWidget::editConfigurationChanges()
-{
- if (m_dialog) {
- m_dialog->activateWindow();
- m_dialog->raise();
- return;
- }
-
- QTC_ASSERT(!m_editor, return);
-
- m_dialog = new QDialog(m_summaryLabel->window());
- m_dialog->setWindowTitle(tr("Edit CMake Configuration"));
- auto layout = new QVBoxLayout(m_dialog);
- m_editor = new QPlainTextEdit;
- m_editor->setToolTip(tr("Enter one variable per line with the variable name "
- "separated from the variable value by \"=\".<br>"
- "You may provide a type hint by adding \":TYPE\" before the \"=\"."));
- m_editor->setMinimumSize(800, 200);
-
- auto chooser = new Core::VariableChooser(m_dialog);
- chooser->addSupportedWidget(m_editor);
- chooser->addMacroExpanderProvider([this]() { return kit()->macroExpander(); });
-
- auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Apply
- |QDialogButtonBox::Reset|QDialogButtonBox::Cancel);
-
- layout->addWidget(m_editor);
- layout->addWidget(buttons);
-
- connect(buttons, &QDialogButtonBox::accepted, m_dialog, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, m_dialog, &QDialog::reject);
- connect(buttons, &QDialogButtonBox::clicked, m_dialog, [buttons, this](QAbstractButton *button) {
- if (button != buttons->button(QDialogButtonBox::Reset))
- return;
- CMakeConfigurationKitInformation::setConfiguration(kit(),
- CMakeConfigurationKitInformation::defaultConfiguration(kit()));
- });
- connect(m_dialog, &QDialog::accepted, this, &CMakeConfigurationKitConfigWidget::acceptChangesDialog);
- connect(m_dialog, &QDialog::rejected, this, &CMakeConfigurationKitConfigWidget::closeChangesDialog);
- connect(buttons->button(QDialogButtonBox::Apply), &QAbstractButton::clicked,
- this, &CMakeConfigurationKitConfigWidget::applyChanges);
-
- refresh();
- m_dialog->show();
-}
-
-void CMakeConfigurationKitConfigWidget::applyChanges()
-{
- QTC_ASSERT(m_editor, return);
- CMakeConfigurationKitInformation::fromStringList(kit(), m_editor->toPlainText().split(QLatin1Char('\n')));
-}
-
-void CMakeConfigurationKitConfigWidget::closeChangesDialog()
-{
- m_dialog->deleteLater();
- m_dialog = nullptr;
- m_editor = nullptr;
-}
-
-void CMakeConfigurationKitConfigWidget::acceptChangesDialog()
-{
- applyChanges();
- closeChangesDialog();
-}
-
-} // namespace Internal
-} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h
deleted file mode 100644
index 3839750f66..0000000000
--- a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/kitconfigwidget.h>
-
-QT_BEGIN_NAMESPACE
-class QComboBox;
-class QDialog;
-class QLabel;
-class QPlainTextEdit;
-class QPushButton;
-QT_END_NAMESPACE
-
-namespace ProjectExplorer {
- class Kit;
- class KitInformation;
-} // namespace ProjectExplorer
-
-namespace CMakeProjectManager {
-
-class CMakeTool;
-
-namespace Internal {
-
-// --------------------------------------------------------------------
-// CMakeKitConfigWidget:
-// --------------------------------------------------------------------
-
-class CMakeKitConfigWidget : public ProjectExplorer::KitConfigWidget
-{
- Q_OBJECT
-public:
- CMakeKitConfigWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki);
- ~CMakeKitConfigWidget() override;
-
- // KitConfigWidget interface
- QString displayName() const override;
- void makeReadOnly() override;
- void refresh() override;
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
- QString toolTip() const override;
-
-private:
- int indexOf(const Core::Id &id);
- void updateComboBox();
- void cmakeToolAdded(const Core::Id &id);
- void cmakeToolUpdated(const Core::Id &id);
- void cmakeToolRemoved(const Core::Id &id);
- void currentCMakeToolChanged(int index);
- void manageCMakeTools();
-
- bool m_removingItem = false;
- QComboBox *m_comboBox;
- QPushButton *m_manageButton;
-};
-
-// --------------------------------------------------------------------
-// CMakeGeneratorKitConfigWidget:
-// --------------------------------------------------------------------
-
-class CMakeGeneratorKitConfigWidget : public ProjectExplorer::KitConfigWidget
-{
- Q_OBJECT
-public:
- CMakeGeneratorKitConfigWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki);
- ~CMakeGeneratorKitConfigWidget() override;
-
- // KitConfigWidget interface
- QString displayName() const override;
- void makeReadOnly() override;
- void refresh() override;
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
- QString toolTip() const override;
-
-private:
- void changeGenerator();
-
- bool m_ignoreChange = false;
- QLabel *m_label;
- QPushButton *m_changeButton;
- CMakeTool *m_currentTool = nullptr;
-};
-
-// --------------------------------------------------------------------
-// CMakeConfigurationKitConfigWidget:
-// --------------------------------------------------------------------
-
-class CMakeConfigurationKitConfigWidget : public ProjectExplorer::KitConfigWidget
-{
- Q_OBJECT
-public:
- CMakeConfigurationKitConfigWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki);
-
- // KitConfigWidget interface
- QString displayName() const override;
- void makeReadOnly() override;
- void refresh() override;
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
- QString toolTip() const override;
-
-private:
- void editConfigurationChanges();
-
- void applyChanges();
- void closeChangesDialog();
- void acceptChangesDialog();
-
- QLabel *m_summaryLabel;
- QPushButton *m_manageButton;
- QDialog *m_dialog = nullptr;
- QPlainTextEdit *m_editor = nullptr;
-};
-
-} // namespace Internal
-} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
index 4dc49ce630..efe0dccc57 100644
--- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
@@ -24,12 +24,13 @@
****************************************************************************/
#include "cmakekitinformation.h"
-#include "cmakekitconfigwidget.h"
#include "cmakeprojectconstants.h"
#include "cmaketoolmanager.h"
#include "cmaketool.h"
#include <app/app_version.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/variablechooser.h>
#include <projectexplorer/task.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/kit.h>
@@ -37,18 +38,28 @@
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
-
#include <utils/algorithm.h>
+#include <utils/elidinglabel.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>
+#include <QComboBox>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QGridLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPlainTextEdit>
+#include <QPointer>
+#include <QPushButton>
#include <QVariant>
using namespace ProjectExplorer;
namespace CMakeProjectManager {
+namespace Internal {
// --------------------------------------------------------------------
-// CMakeKitInformation:
+// CMakeKitAspect:
// --------------------------------------------------------------------
static Core::Id defaultCMakeToolId()
@@ -59,14 +70,145 @@ static Core::Id defaultCMakeToolId()
static const char TOOL_ID[] = "CMakeProjectManager.CMakeKitInformation";
-// --------------------------------------------------------------------
-// CMakeKitInformation:
-// --------------------------------------------------------------------
+class CMakeKitAspectWidget : public KitAspectWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeKitAspect)
+public:
+ CMakeKitAspectWidget(Kit *kit, const KitAspect *ki) : KitAspectWidget(kit, ki),
+ m_comboBox(new QComboBox),
+ m_manageButton(new QPushButton(KitAspectWidget::msgManage()))
+ {
+ m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
+ m_comboBox->setEnabled(false);
+ m_comboBox->setToolTip(ki->description());
+
+ foreach (CMakeTool *tool, CMakeToolManager::cmakeTools())
+ cmakeToolAdded(tool->id());
+
+ updateComboBox();
+ refresh();
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &CMakeKitAspectWidget::currentCMakeToolChanged);
+
+ m_manageButton->setContentsMargins(0, 0, 0, 0);
+ connect(m_manageButton, &QPushButton::clicked,
+ this, &CMakeKitAspectWidget::manageCMakeTools);
+
+ CMakeToolManager *cmakeMgr = CMakeToolManager::instance();
+ connect(cmakeMgr, &CMakeToolManager::cmakeAdded,
+ this, &CMakeKitAspectWidget::cmakeToolAdded);
+ connect(cmakeMgr, &CMakeToolManager::cmakeRemoved,
+ this, &CMakeKitAspectWidget::cmakeToolRemoved);
+ connect(cmakeMgr, &CMakeToolManager::cmakeUpdated,
+ this, &CMakeKitAspectWidget::cmakeToolUpdated);
+ }
+
+ ~CMakeKitAspectWidget() override
+ {
+ delete m_comboBox;
+ delete m_manageButton;
+ }
+
+private:
+ // KitAspectWidget interface
+ void makeReadOnly() override { m_comboBox->setEnabled(false); }
+ QWidget *mainWidget() const override { return m_comboBox; }
+ QWidget *buttonWidget() const override { return m_manageButton; }
+
+ void refresh() override
+ {
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(m_kit);
+ m_comboBox->setCurrentIndex(tool ? indexOf(tool->id()) : -1);
+ }
+
+ int indexOf(const Core::Id &id)
+ {
+ for (int i = 0; i < m_comboBox->count(); ++i) {
+ if (id == Core::Id::fromSetting(m_comboBox->itemData(i)))
+ return i;
+ }
+ return -1;
+ }
+
+ void updateComboBox()
+ {
+ // remove unavailable cmake tool:
+ int pos = indexOf(Core::Id());
+ if (pos >= 0)
+ m_comboBox->removeItem(pos);
+
+ if (m_comboBox->count() == 0) {
+ m_comboBox->addItem(tr("<No CMake Tool available>"),
+ Core::Id().toSetting());
+ m_comboBox->setEnabled(false);
+ } else {
+ m_comboBox->setEnabled(true);
+ }
+ }
+
+ void cmakeToolAdded(const Core::Id &id)
+ {
+ const CMakeTool *tool = CMakeToolManager::findById(id);
+ QTC_ASSERT(tool, return);
+
+ m_comboBox->addItem(tool->displayName(), tool->id().toSetting());
+ updateComboBox();
+ refresh();
+ }
+
+ void cmakeToolUpdated(const Core::Id &id)
+ {
+ const int pos = indexOf(id);
+ QTC_ASSERT(pos >= 0, return);
+
+ const CMakeTool *tool = CMakeToolManager::findById(id);
+ QTC_ASSERT(tool, return);
+
+ m_comboBox->setItemText(pos, tool->displayName());
+ }
-CMakeKitInformation::CMakeKitInformation()
+ void cmakeToolRemoved(const Core::Id &id)
+ {
+ const int pos = indexOf(id);
+ QTC_ASSERT(pos >= 0, return);
+
+ // do not handle the current index changed signal
+ m_removingItem = true;
+ m_comboBox->removeItem(pos);
+ m_removingItem = false;
+
+ // update the checkbox and set the current index
+ updateComboBox();
+ refresh();
+ }
+
+ void currentCMakeToolChanged(int index)
+ {
+ if (m_removingItem)
+ return;
+
+ const Core::Id id = Core::Id::fromSetting(m_comboBox->itemData(index));
+ CMakeKitAspect::setCMakeTool(m_kit, id);
+ }
+
+ void manageCMakeTools()
+ {
+ Core::ICore::showOptionsDialog(Constants::CMAKE_SETTINGSPAGE_ID,
+ buttonWidget());
+ }
+
+ bool m_removingItem = false;
+ QComboBox *m_comboBox;
+ QPushButton *m_manageButton;
+};
+
+CMakeKitAspect::CMakeKitAspect()
{
- setObjectName(QLatin1String("CMakeKitInformation"));
+ setObjectName(QLatin1String("CMakeKitAspect"));
setId(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."));
setPriority(20000);
//make sure the default value is set if a selected CMake is removed
@@ -78,24 +220,24 @@ CMakeKitInformation::CMakeKitInformation()
[this]() { foreach (Kit *k, KitManager::kits()) fix(k); });
}
-Core::Id CMakeKitInformation::id()
+Core::Id CMakeKitAspect::id()
{
return TOOL_ID;
}
-Core::Id CMakeKitInformation::cmakeToolId(const Kit *k)
+Core::Id CMakeKitAspect::cmakeToolId(const Kit *k)
{
if (!k)
return {};
return Core::Id::fromSetting(k->value(TOOL_ID));
}
-CMakeTool *CMakeKitInformation::cmakeTool(const Kit *k)
+CMakeTool *CMakeKitAspect::cmakeTool(const Kit *k)
{
return CMakeToolManager::findById(cmakeToolId(k));
}
-void CMakeKitInformation::setCMakeTool(Kit *k, const Core::Id id)
+void CMakeKitAspect::setCMakeTool(Kit *k, const Core::Id id)
{
const Core::Id toSet = id.isValid() ? id : defaultCMakeToolId();
QTC_ASSERT(!id.isValid() || CMakeToolManager::findById(toSet), return);
@@ -103,63 +245,56 @@ void CMakeKitInformation::setCMakeTool(Kit *k, const Core::Id id)
k->setValue(TOOL_ID, toSet.toSetting());
}
-QVariant CMakeKitInformation::defaultValue(const Kit *k) const
-{
- const Core::Id id = k ? defaultCMakeToolId() : Core::Id();
- return id.toSetting();
-}
-
-QList<Task> CMakeKitInformation::validate(const Kit *k) const
+Tasks CMakeKitAspect::validate(const Kit *k) const
{
- QList<Task> result;
- CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
+ Tasks result;
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(k);
if (tool) {
CMakeTool::Version version = tool->version();
if (version.major < 3) {
result << Task(Task::Warning, tr("CMake version %1 is unsupported. Please update to "
"version 3.0 or later.").arg(QString::fromUtf8(version.fullVersion)),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
return result;
}
-void CMakeKitInformation::setup(Kit *k)
+void CMakeKitAspect::setup(Kit *k)
{
- CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(k);
if (!tool)
setCMakeTool(k, defaultCMakeToolId());
}
-void CMakeKitInformation::fix(Kit *k)
+void CMakeKitAspect::fix(Kit *k)
{
- if (!CMakeKitInformation::cmakeTool(k))
- setup(k);
+ setup(k);
}
-KitInformation::ItemList CMakeKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList CMakeKitAspect::toUserOutput(const Kit *k) const
{
const CMakeTool *const tool = cmakeTool(k);
- return ItemList() << qMakePair(tr("CMake"), tool ? tool->displayName() : tr("Unconfigured"));
+ return {{tr("CMake"), tool ? tool->displayName() : tr("Unconfigured")}};
}
-KitConfigWidget *CMakeKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *CMakeKitAspect::createConfigWidget(Kit *k) const
{
QTC_ASSERT(k, return nullptr);
- return new Internal::CMakeKitConfigWidget(k, this);
+ return new CMakeKitAspectWidget(k, this);
}
-void CMakeKitInformation::addToMacroExpander(Kit *k, Utils::MacroExpander *expander) const
+void CMakeKitAspect::addToMacroExpander(Kit *k, Utils::MacroExpander *expander) const
{
QTC_ASSERT(k, return);
expander->registerFileVariables("CMake:Executable", tr("Path to the cmake executable"),
[k]() -> QString {
- CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(k);
return tool ? tool->cmakeExecutable().toString() : QString();
});
}
-QSet<Core::Id> CMakeKitInformation::availableFeatures(const Kit *k) const
+QSet<Core::Id> CMakeKitAspect::availableFeatures(const Kit *k) const
{
if (cmakeTool(k))
return { CMakeProjectManager::Constants::CMAKE_FEATURE_ID };
@@ -167,7 +302,7 @@ QSet<Core::Id> CMakeKitInformation::availableFeatures(const Kit *k) const
}
// --------------------------------------------------------------------
-// CMakeGeneratorKitInformation:
+// CMakeGeneratorKitAspect:
// --------------------------------------------------------------------
static const char GENERATOR_ID[] = "CMake.GeneratorKitInformation";
@@ -177,6 +312,158 @@ static const char EXTRA_GENERATOR_KEY[] = "ExtraGenerator";
static const char PLATFORM_KEY[] = "Platform";
static const char TOOLSET_KEY[] = "Toolset";
+class CMakeGeneratorKitAspectWidget : public KitAspectWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeGeneratorKitAspect)
+public:
+ CMakeGeneratorKitAspectWidget(Kit *kit, const ::KitAspect *ki)
+ : KitAspectWidget(kit, ki),
+ m_label(new QLabel),
+ m_changeButton(new QPushButton)
+ {
+ m_label->setToolTip(ki->description());
+ m_changeButton->setText(tr("Change..."));
+ refresh();
+ connect(m_changeButton, &QPushButton::clicked,
+ this, &CMakeGeneratorKitAspectWidget::changeGenerator);
+ }
+
+ ~CMakeGeneratorKitAspectWidget() override
+ {
+ delete m_label;
+ delete m_changeButton;
+ }
+
+private:
+ // KitAspectWidget interface
+ void makeReadOnly() override { m_changeButton->setEnabled(false); }
+ QWidget *mainWidget() const override { return m_label; }
+ QWidget *buttonWidget() const override { return m_changeButton; }
+
+ void refresh() override
+ {
+ if (m_ignoreChange)
+ return;
+
+ CMakeTool *const tool = CMakeKitAspect::cmakeTool(m_kit);
+ if (tool != m_currentTool)
+ m_currentTool = tool;
+
+ m_changeButton->setEnabled(m_currentTool);
+ const QString generator = CMakeGeneratorKitAspect::generator(kit());
+ const QString extraGenerator = CMakeGeneratorKitAspect::extraGenerator(kit());
+ const QString platform = CMakeGeneratorKitAspect::platform(kit());
+ const QString toolset = CMakeGeneratorKitAspect::toolset(kit());
+
+ const QString message = tr("%1 - %2, Platform: %3, Toolset: %4")
+ .arg(extraGenerator.isEmpty() ? tr("<none>") : extraGenerator)
+ .arg(generator.isEmpty() ? tr("<none>") : generator)
+ .arg(platform.isEmpty() ? tr("<none>") : platform)
+ .arg(toolset.isEmpty() ? tr("<none>") : toolset);
+ m_label->setText(message);
+ }
+
+ void changeGenerator()
+ {
+ QPointer<QDialog> changeDialog = new QDialog(m_changeButton);
+
+ // Disable help button in titlebar on windows:
+ Qt::WindowFlags flags = changeDialog->windowFlags();
+ flags &= ~Qt::WindowContextHelpButtonHint;
+ flags |= Qt::MSWindowsFixedSizeDialogHint;
+ changeDialog->setWindowFlags(flags);
+
+ changeDialog->setWindowTitle(tr("CMake Generator"));
+
+ auto *layout = new QGridLayout(changeDialog);
+ layout->setSizeConstraint(QLayout::SetFixedSize);
+
+ auto *cmakeLabel = new QLabel;
+ cmakeLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ auto *generatorCombo = new QComboBox;
+ auto *extraGeneratorCombo = new QComboBox;
+ auto *platformEdit = new QLineEdit;
+ auto *toolsetEdit = new QLineEdit;
+
+ int row = 0;
+ layout->addWidget(new QLabel(QLatin1String("Executable:")));
+ layout->addWidget(cmakeLabel, row, 1);
+
+ ++row;
+ layout->addWidget(new QLabel(tr("Generator:")), row, 0);
+ layout->addWidget(generatorCombo, row, 1);
+
+ ++row;
+ layout->addWidget(new QLabel(tr("Extra generator:")), row, 0);
+ layout->addWidget(extraGeneratorCombo, row, 1);
+
+ ++row;
+ layout->addWidget(new QLabel(tr("Platform:")), row, 0);
+ layout->addWidget(platformEdit, row, 1);
+
+ ++row;
+ layout->addWidget(new QLabel(tr("Toolset:")), row, 0);
+ layout->addWidget(toolsetEdit, row, 1);
+
+ ++row;
+ auto *bb = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ layout->addWidget(bb, row, 0, 1, 2);
+
+ connect(bb, &QDialogButtonBox::accepted, changeDialog.data(), &QDialog::accept);
+ connect(bb, &QDialogButtonBox::rejected, changeDialog.data(), &QDialog::reject);
+
+ cmakeLabel->setText(m_currentTool->cmakeExecutable().toUserOutput());
+
+ QList<CMakeTool::Generator> generatorList = m_currentTool->supportedGenerators();
+ Utils::sort(generatorList, &CMakeTool::Generator::name);
+
+ for (auto it = generatorList.constBegin(); it != generatorList.constEnd(); ++it)
+ generatorCombo->addItem(it->name);
+
+ auto updateDialog = [&generatorList, generatorCombo, extraGeneratorCombo,
+ platformEdit, toolsetEdit](const QString &name) {
+ auto it = std::find_if(generatorList.constBegin(), generatorList.constEnd(),
+ [name](const CMakeTool::Generator &g) { return g.name == name; });
+ QTC_ASSERT(it != generatorList.constEnd(), return);
+ generatorCombo->setCurrentText(name);
+
+ extraGeneratorCombo->clear();
+ extraGeneratorCombo->addItem(tr("<none>"), QString());
+ foreach (const QString &eg, it->extraGenerators)
+ extraGeneratorCombo->addItem(eg, eg);
+ extraGeneratorCombo->setEnabled(extraGeneratorCombo->count() > 1);
+
+ platformEdit->setEnabled(it->supportsPlatform);
+ toolsetEdit->setEnabled(it->supportsToolset);
+ };
+
+ updateDialog(CMakeGeneratorKitAspect::generator(kit()));
+
+ generatorCombo->setCurrentText(CMakeGeneratorKitAspect::generator(kit()));
+ extraGeneratorCombo->setCurrentText(CMakeGeneratorKitAspect::extraGenerator(kit()));
+ platformEdit->setText(platformEdit->isEnabled() ? CMakeGeneratorKitAspect::platform(kit()) : QLatin1String("<unsupported>"));
+ toolsetEdit->setText(toolsetEdit->isEnabled() ? CMakeGeneratorKitAspect::toolset(kit()) : QLatin1String("<unsupported>"));
+
+ connect(generatorCombo, &QComboBox::currentTextChanged, updateDialog);
+
+ if (changeDialog->exec() == QDialog::Accepted) {
+ if (!changeDialog)
+ return;
+
+ CMakeGeneratorKitAspect::set(kit(), generatorCombo->currentText(),
+ extraGeneratorCombo->currentData().toString(),
+ platformEdit->isEnabled() ? platformEdit->text() : QString(),
+ toolsetEdit->isEnabled() ? toolsetEdit->text() : QString());
+ }
+ }
+
+ bool m_ignoreChange = false;
+ QLabel *m_label;
+ QPushButton *m_changeButton;
+ CMakeTool *m_currentTool = nullptr;
+};
+
namespace {
struct GeneratorInfo {
@@ -222,62 +509,65 @@ static void setGeneratorInfo(Kit *k, const GeneratorInfo &info)
k->setValue(GENERATOR_ID, info.toVariant());
}
-CMakeGeneratorKitInformation::CMakeGeneratorKitInformation()
+CMakeGeneratorKitAspect::CMakeGeneratorKitAspect()
{
- setObjectName(QLatin1String("CMakeGeneratorKitInformation"));
+ setObjectName(QLatin1String("CMakeGeneratorKitAspect"));
setId(GENERATOR_ID);
+ setDisplayName(tr("CMake generator"));
+ setDescription(tr("CMake generator defines how a project is built when using CMake.<br>"
+ "This setting is ignored when using other build systems."));
setPriority(19000);
}
-QString CMakeGeneratorKitInformation::generator(const Kit *k)
+QString CMakeGeneratorKitAspect::generator(const Kit *k)
{
return generatorInfo(k).generator;
}
-QString CMakeGeneratorKitInformation::extraGenerator(const Kit *k)
+QString CMakeGeneratorKitAspect::extraGenerator(const Kit *k)
{
return generatorInfo(k).extraGenerator;
}
-QString CMakeGeneratorKitInformation::platform(const Kit *k)
+QString CMakeGeneratorKitAspect::platform(const Kit *k)
{
return generatorInfo(k).platform;
}
-QString CMakeGeneratorKitInformation::toolset(const Kit *k)
+QString CMakeGeneratorKitAspect::toolset(const Kit *k)
{
return generatorInfo(k).toolset;
}
-void CMakeGeneratorKitInformation::setGenerator(Kit *k, const QString &generator)
+void CMakeGeneratorKitAspect::setGenerator(Kit *k, const QString &generator)
{
GeneratorInfo info = generatorInfo(k);
info.generator = generator;
setGeneratorInfo(k, info);
}
-void CMakeGeneratorKitInformation::setExtraGenerator(Kit *k, const QString &extraGenerator)
+void CMakeGeneratorKitAspect::setExtraGenerator(Kit *k, const QString &extraGenerator)
{
GeneratorInfo info = generatorInfo(k);
info.extraGenerator = extraGenerator;
setGeneratorInfo(k, info);
}
-void CMakeGeneratorKitInformation::setPlatform(Kit *k, const QString &platform)
+void CMakeGeneratorKitAspect::setPlatform(Kit *k, const QString &platform)
{
GeneratorInfo info = generatorInfo(k);
info.platform = platform;
setGeneratorInfo(k, info);
}
-void CMakeGeneratorKitInformation::setToolset(Kit *k, const QString &toolset)
+void CMakeGeneratorKitAspect::setToolset(Kit *k, const QString &toolset)
{
GeneratorInfo info = generatorInfo(k);
info.toolset = toolset;
setGeneratorInfo(k, info);
}
-void CMakeGeneratorKitInformation::set(Kit *k,
+void CMakeGeneratorKitAspect::set(Kit *k,
const QString &generator, const QString &extraGenerator,
const QString &platform, const QString &toolset)
{
@@ -285,7 +575,7 @@ void CMakeGeneratorKitInformation::set(Kit *k,
setGeneratorInfo(k, info);
}
-QStringList CMakeGeneratorKitInformation::generatorArguments(const Kit *k)
+QStringList CMakeGeneratorKitAspect::generatorArguments(const Kit *k)
{
QStringList result;
GeneratorInfo info = generatorInfo(k);
@@ -307,11 +597,11 @@ QStringList CMakeGeneratorKitInformation::generatorArguments(const Kit *k)
return result;
}
-QVariant CMakeGeneratorKitInformation::defaultValue(const Kit *k) const
+QVariant CMakeGeneratorKitAspect::defaultValue(const Kit *k) const
{
QTC_ASSERT(k, return QVariant());
- CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(k);
if (!tool)
return QVariant();
@@ -325,14 +615,14 @@ QVariant CMakeGeneratorKitInformation::defaultValue(const Kit *k) const
if (it != known.constEnd()) {
Utils::Environment env = Utils::Environment::systemEnvironment();
k->addToEnvironment(env);
- const Utils::FileName ninjaExec = env.searchInPath(QLatin1String("ninja"));
+ const Utils::FilePath ninjaExec = env.searchInPath(QLatin1String("ninja"));
if (!ninjaExec.isEmpty())
return GeneratorInfo({QString("Ninja"), extraGenerator, QString(), QString()}).toVariant();
}
if (Utils::HostOsInfo::isWindowsHost()) {
// *sigh* Windows with its zoo of incompatible stuff again...
- ToolChain *tc = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (tc && tc->typeId() == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) {
it = std::find_if(known.constBegin(), known.constEnd(),
[extraGenerator](const CMakeTool::Generator &g) {
@@ -360,16 +650,16 @@ QVariant CMakeGeneratorKitInformation::defaultValue(const Kit *k) const
return GeneratorInfo({it->name, extraGenerator, QString(), QString()}).toVariant();
}
-QList<Task> CMakeGeneratorKitInformation::validate(const Kit *k) const
+Tasks CMakeGeneratorKitAspect::validate(const Kit *k) const
{
- CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(k);
GeneratorInfo info = generatorInfo(k);
- QList<Task> result;
+ Tasks result;
if (tool) {
if (!tool->isValid()) {
result << Task(Task::Warning, tr("CMake Tool is unconfigured, CMake generator will be ignored."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
} else {
QList<CMakeTool::Generator> known = tool->supportedGenerators();
auto it = std::find_if(known.constBegin(), known.constEnd(), [info](const CMakeTool::Generator &g) {
@@ -377,15 +667,15 @@ QList<Task> CMakeGeneratorKitInformation::validate(const Kit *k) const
});
if (it == known.constEnd()) {
result << Task(Task::Warning, tr("CMake Tool does not support the configured generator."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
} else {
if (!it->supportsPlatform && !info.platform.isEmpty()) {
result << Task(Task::Warning, tr("Platform is not supported by the selected CMake generator."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
if (!it->supportsToolset && !info.toolset.isEmpty()) {
result << Task(Task::Warning, tr("Toolset is not supported by the selected CMake generator."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
if (!tool->hasServerMode() && info.extraGenerator != "CodeBlocks") {
@@ -393,23 +683,25 @@ QList<Task> CMakeGeneratorKitInformation::validate(const Kit *k) const
"generator does not generate a CodeBlocks file. "
"%1 will not be able to parse CMake projects.")
.arg(Core::Constants::IDE_DISPLAY_NAME),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
}
return result;
}
-void CMakeGeneratorKitInformation::setup(Kit *k)
+void CMakeGeneratorKitAspect::setup(Kit *k)
{
+ if (!k || k->hasValue(id()))
+ return;
GeneratorInfo info;
info.fromVariant(defaultValue(k));
setGeneratorInfo(k, info);
}
-void CMakeGeneratorKitInformation::fix(Kit *k)
+void CMakeGeneratorKitAspect::fix(Kit *k)
{
- const CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
+ const CMakeTool *tool = CMakeKitAspect::cmakeTool(k);
const GeneratorInfo info = generatorInfo(k);
if (!tool)
@@ -431,7 +723,7 @@ void CMakeGeneratorKitInformation::fix(Kit *k)
}
}
-void CMakeGeneratorKitInformation::upgrade(Kit *k)
+void CMakeGeneratorKitAspect::upgrade(Kit *k)
{
QTC_ASSERT(k, return);
@@ -450,7 +742,7 @@ void CMakeGeneratorKitInformation::upgrade(Kit *k)
}
}
-KitInformation::ItemList CMakeGeneratorKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList CMakeGeneratorKitAspect::toUserOutput(const Kit *k) const
{
const GeneratorInfo info = generatorInfo(k);
QString message;
@@ -463,16 +755,16 @@ KitInformation::ItemList CMakeGeneratorKitInformation::toUserOutput(const Kit *k
if (!info.toolset.isEmpty())
message += "<br/>" + tr("Toolset: %1").arg(info.toolset);
}
- return ItemList() << qMakePair(tr("CMake Generator"), message);
+ return {{tr("CMake Generator"), message}};
}
-KitConfigWidget *CMakeGeneratorKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *CMakeGeneratorKitAspect::createConfigWidget(Kit *k) const
{
- return new Internal::CMakeGeneratorKitConfigWidget(k, this);
+ return new CMakeGeneratorKitAspectWidget(k, this);
}
// --------------------------------------------------------------------
-// CMakeConfigurationKitInformation:
+// CMakeConfigurationKitAspect:
// --------------------------------------------------------------------
static const char CONFIGURATION_ID[] = "CMake.ConfigurationKitInformation";
@@ -482,14 +774,122 @@ static const char CMAKE_CXX_TOOLCHAIN_KEY[] = "CMAKE_CXX_COMPILER";
static const char CMAKE_QMAKE_KEY[] = "QT_QMAKE_EXECUTABLE";
static const char CMAKE_PREFIX_PATH_KEY[] = "CMAKE_PREFIX_PATH";
-CMakeConfigurationKitInformation::CMakeConfigurationKitInformation()
+class CMakeConfigurationKitAspectWidget : public KitAspectWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeConfigurationKitAspect)
+public:
+ CMakeConfigurationKitAspectWidget(Kit *kit, const KitAspect *ki)
+ : KitAspectWidget(kit, ki),
+ m_summaryLabel(new Utils::ElidingLabel),
+ m_manageButton(new QPushButton)
+ {
+ refresh();
+ m_manageButton->setText(tr("Change..."));
+ connect(m_manageButton, &QAbstractButton::clicked,
+ this, &CMakeConfigurationKitAspectWidget::editConfigurationChanges);
+ }
+
+private:
+ // KitAspectWidget interface
+ QWidget *mainWidget() const override { return m_summaryLabel; }
+ QWidget *buttonWidget() const override { return m_manageButton; }
+
+ void makeReadOnly() override
+ {
+ m_manageButton->setEnabled(false);
+ if (m_dialog)
+ m_dialog->reject();
+ }
+
+ void refresh() override
+ {
+ const QStringList current = CMakeConfigurationKitAspect::toStringList(kit());
+
+ m_summaryLabel->setText(current.join("; "));
+ if (m_editor)
+ m_editor->setPlainText(current.join('\n'));
+ }
+
+ void editConfigurationChanges()
+ {
+ if (m_dialog) {
+ m_dialog->activateWindow();
+ m_dialog->raise();
+ return;
+ }
+
+ QTC_ASSERT(!m_editor, return);
+
+ m_dialog = new QDialog(m_summaryLabel->window());
+ m_dialog->setWindowTitle(tr("Edit CMake Configuration"));
+ auto layout = new QVBoxLayout(m_dialog);
+ m_editor = new QPlainTextEdit;
+ m_editor->setToolTip(tr("Enter one variable per line with the variable name "
+ "separated from the variable value by \"=\".<br>"
+ "You may provide a type hint by adding \":TYPE\" before the \"=\"."));
+ m_editor->setMinimumSize(800, 200);
+
+ auto chooser = new Core::VariableChooser(m_dialog);
+ chooser->addSupportedWidget(m_editor);
+ chooser->addMacroExpanderProvider([this]() { return kit()->macroExpander(); });
+
+ auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Apply
+ |QDialogButtonBox::Reset|QDialogButtonBox::Cancel);
+
+ layout->addWidget(m_editor);
+ layout->addWidget(buttons);
+
+ connect(buttons, &QDialogButtonBox::accepted, m_dialog, &QDialog::accept);
+ connect(buttons, &QDialogButtonBox::rejected, m_dialog, &QDialog::reject);
+ connect(buttons, &QDialogButtonBox::clicked, m_dialog, [buttons, this](QAbstractButton *button) {
+ if (button != buttons->button(QDialogButtonBox::Reset))
+ return;
+ CMakeConfigurationKitAspect::setConfiguration(kit(),
+ CMakeConfigurationKitAspect::defaultConfiguration(kit()));
+ });
+ connect(m_dialog, &QDialog::accepted, this, &CMakeConfigurationKitAspectWidget::acceptChangesDialog);
+ connect(m_dialog, &QDialog::rejected, this, &CMakeConfigurationKitAspectWidget::closeChangesDialog);
+ connect(buttons->button(QDialogButtonBox::Apply), &QAbstractButton::clicked,
+ this, &CMakeConfigurationKitAspectWidget::applyChanges);
+
+ refresh();
+ m_dialog->show();
+ }
+
+ void applyChanges()
+ {
+ QTC_ASSERT(m_editor, return);
+ CMakeConfigurationKitAspect::fromStringList(kit(), m_editor->toPlainText().split(QLatin1Char('\n')));
+ }
+ void closeChangesDialog()
+ {
+ m_dialog->deleteLater();
+ m_dialog = nullptr;
+ m_editor = nullptr;
+ }
+ void acceptChangesDialog()
+ {
+ applyChanges();
+ closeChangesDialog();
+ }
+
+ QLabel *m_summaryLabel;
+ QPushButton *m_manageButton;
+ QDialog *m_dialog = nullptr;
+ QPlainTextEdit *m_editor = nullptr;
+};
+
+
+CMakeConfigurationKitAspect::CMakeConfigurationKitAspect()
{
- setObjectName(QLatin1String("CMakeConfigurationKitInformation"));
+ setObjectName(QLatin1String("CMakeConfigurationKitAspect"));
setId(CONFIGURATION_ID);
+ setDisplayName(tr("CMake Configuration"));
+ setDescription(tr("Default configuration passed to CMake when setting up a project."));
setPriority(18000);
}
-CMakeConfig CMakeConfigurationKitInformation::configuration(const Kit *k)
+CMakeConfig CMakeConfigurationKitAspect::configuration(const Kit *k)
{
if (!k)
return CMakeConfig();
@@ -497,7 +897,7 @@ CMakeConfig CMakeConfigurationKitInformation::configuration(const Kit *k)
return Utils::transform(tmp, &CMakeConfigItem::fromString);
}
-void CMakeConfigurationKitInformation::setConfiguration(Kit *k, const CMakeConfig &config)
+void CMakeConfigurationKitAspect::setConfiguration(Kit *k, const CMakeConfig &config)
{
if (!k)
return;
@@ -505,17 +905,17 @@ void CMakeConfigurationKitInformation::setConfiguration(Kit *k, const CMakeConfi
k->setValue(CONFIGURATION_ID, tmp);
}
-QStringList CMakeConfigurationKitInformation::toStringList(const Kit *k)
+QStringList CMakeConfigurationKitAspect::toStringList(const Kit *k)
{
QStringList current
- = Utils::transform(CMakeConfigurationKitInformation::configuration(k),
+ = Utils::transform(CMakeConfigurationKitAspect::configuration(k),
[](const CMakeConfigItem &i) { return i.toString(); });
current = Utils::filtered(current, [](const QString &s) { return !s.isEmpty(); });
Utils::sort(current);
return current;
}
-void CMakeConfigurationKitInformation::fromStringList(Kit *k, const QStringList &in)
+void CMakeConfigurationKitAspect::fromStringList(Kit *k, const QStringList &in)
{
CMakeConfig result;
foreach (const QString &s, in) {
@@ -526,7 +926,7 @@ void CMakeConfigurationKitInformation::fromStringList(Kit *k, const QStringList
setConfiguration(k, result);
}
-CMakeConfig CMakeConfigurationKitInformation::defaultConfiguration(const Kit *k)
+CMakeConfig CMakeConfigurationKitAspect::defaultConfiguration(const Kit *k)
{
Q_UNUSED(k);
CMakeConfig config;
@@ -541,7 +941,7 @@ CMakeConfig CMakeConfigurationKitInformation::defaultConfiguration(const Kit *k)
return config;
}
-QVariant CMakeConfigurationKitInformation::defaultValue(const Kit *k) const
+QVariant CMakeConfigurationKitAspect::defaultValue(const Kit *k) const
{
Q_UNUSED(k);
@@ -552,24 +952,24 @@ QVariant CMakeConfigurationKitInformation::defaultValue(const Kit *k) const
return tmp;
}
-QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const
+Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const
{
- QTC_ASSERT(k, return QList<Task>());
+ QTC_ASSERT(k, return Tasks());
- const QtSupport::BaseQtVersion *const version = QtSupport::QtKitInformation::qtVersion(k);
- const ToolChain *const tcC = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID);
- const ToolChain *const tcCxx = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ const QtSupport::BaseQtVersion *const version = QtSupport::QtKitAspect::qtVersion(k);
+ const ToolChain *const tcC = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID);
+ const ToolChain *const tcCxx = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
const CMakeConfig config = configuration(k);
const bool isQt4 = version && version->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0);
- Utils::FileName qmakePath;
+ Utils::FilePath qmakePath;
QStringList qtInstallDirs;
- Utils::FileName tcCPath;
- Utils::FileName tcCxxPath;
+ Utils::FilePath tcCPath;
+ Utils::FilePath tcCxxPath;
foreach (const CMakeConfigItem &i, config) {
// Do not use expand(QByteArray) as we cannot be sure the input is latin1
- const Utils::FileName expandedValue
- = Utils::FileName::fromString(k->macroExpander()->expand(QString::fromUtf8(i.value)));
+ const Utils::FilePath expandedValue
+ = Utils::FilePath::fromString(k->macroExpander()->expand(QString::fromUtf8(i.value)));
if (i.key == CMAKE_QMAKE_KEY)
qmakePath = expandedValue;
else if (i.key == CMAKE_C_TOOLCHAIN_KEY)
@@ -580,31 +980,31 @@ QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const
qtInstallDirs = CMakeConfigItem::cmakeSplitValue(expandedValue.toString());
}
- QList<Task> result;
+ Tasks result;
// Validate Qt:
if (qmakePath.isEmpty()) {
if (version && version->isValid() && isQt4) {
result << Task(Task::Warning, tr("CMake configuration has no path to qmake binary set, "
"even though the kit has a valid Qt version."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
} else {
if (!version || !version->isValid()) {
result << Task(Task::Warning, tr("CMake configuration has a path to a qmake binary set, "
"even though the kit has no valid Qt version."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
} else if (qmakePath != version->qmakeCommand() && isQt4) {
result << Task(Task::Warning, tr("CMake configuration has a path to a qmake binary set "
"that does not match the qmake binary path "
"configured in the Qt version."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
if (version && !qtInstallDirs.contains(version->qmakeProperty("QT_INSTALL_PREFIX")) && !isQt4) {
if (version->isValid()) {
result << Task(Task::Warning, tr("CMake configuration has no CMAKE_PREFIX_PATH set "
"that points to the kit Qt version."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
@@ -613,18 +1013,18 @@ QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const
if (tcC && tcC->isValid()) {
result << Task(Task::Warning, tr("CMake configuration has no path to a C compiler set, "
"even though the kit has a valid tool chain."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
} else {
if (!tcC || !tcC->isValid()) {
result << Task(Task::Warning, tr("CMake configuration has a path to a C compiler set, "
"even though the kit has no valid tool chain."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
} else if (tcCPath != tcC->compilerCommand()) {
result << Task(Task::Warning, 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."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
@@ -632,46 +1032,46 @@ QList<Task> CMakeConfigurationKitInformation::validate(const Kit *k) const
if (tcCxx && tcCxx->isValid()) {
result << Task(Task::Warning, tr("CMake configuration has no path to a C++ compiler set, "
"even though the kit has a valid tool chain."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
} else {
if (!tcCxx || !tcCxx->isValid()) {
result << Task(Task::Warning, tr("CMake configuration has a path to a C++ compiler set, "
"even though the kit has no valid tool chain."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
} else if (tcCxxPath != tcCxx->compilerCommand()) {
result << Task(Task::Warning, 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."),
- Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
return result;
}
-void CMakeConfigurationKitInformation::setup(Kit *k)
+void CMakeConfigurationKitAspect::setup(Kit *k)
{
if (k && !k->hasValue(CONFIGURATION_ID))
k->setValue(CONFIGURATION_ID, defaultValue(k));
}
-void CMakeConfigurationKitInformation::fix(Kit *k)
+void CMakeConfigurationKitAspect::fix(Kit *k)
{
Q_UNUSED(k);
}
-KitInformation::ItemList CMakeConfigurationKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList CMakeConfigurationKitAspect::toUserOutput(const Kit *k) const
{
- const QStringList current = toStringList(k);
- return ItemList() << qMakePair(tr("CMake Configuration"), current.join(QLatin1String("<br>")));
+ return {{tr("CMake Configuration"), toStringList(k).join("<br>")}};
}
-KitConfigWidget *CMakeConfigurationKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *CMakeConfigurationKitAspect::createConfigWidget(Kit *k) const
{
if (!k)
return nullptr;
- return new Internal::CMakeConfigurationKitConfigWidget(k, this);
+ return new CMakeConfigurationKitAspectWidget(k, this);
}
+} // namespace Internal
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.h b/src/plugins/cmakeprojectmanager/cmakekitinformation.h
index 3da3f7d7b2..7920cc1a27 100644
--- a/src/plugins/cmakeprojectmanager/cmakekitinformation.h
+++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.h
@@ -25,21 +25,20 @@
#pragma once
-#include "cmake_global.h"
-
#include "cmakeconfigitem.h"
#include <projectexplorer/kitmanager.h>
namespace CMakeProjectManager {
-
class CMakeTool;
-class CMAKE_EXPORT CMakeKitInformation : public ProjectExplorer::KitInformation
+namespace Internal {
+
+class CMakeKitAspect : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- CMakeKitInformation();
+ CMakeKitAspect();
static Core::Id id();
@@ -47,24 +46,23 @@ public:
static CMakeTool *cmakeTool(const ProjectExplorer::Kit *k);
static void setCMakeTool(ProjectExplorer::Kit *k, const Core::Id id);
- // KitInformation interface
- QVariant defaultValue(const ProjectExplorer::Kit *k) const final;
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const final;
+ // KitAspect interface
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const final;
void setup(ProjectExplorer::Kit *k) final;
void fix(ProjectExplorer::Kit *k) final;
ItemList toUserOutput(const ProjectExplorer::Kit *k) const final;
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const final;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const final;
void addToMacroExpander(ProjectExplorer::Kit *k, Utils::MacroExpander *expander) const final;
QSet<Core::Id> availableFeatures(const ProjectExplorer::Kit *k) const final;
};
-class CMAKE_EXPORT CMakeGeneratorKitInformation : public ProjectExplorer::KitInformation
+class CMakeGeneratorKitAspect : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- CMakeGeneratorKitInformation();
+ CMakeGeneratorKitAspect();
static QString generator(const ProjectExplorer::Kit *k);
static QString extraGenerator(const ProjectExplorer::Kit *k);
@@ -78,21 +76,23 @@ public:
const QString &extraGenerator, const QString &platform, const QString &toolset);
static QStringList generatorArguments(const ProjectExplorer::Kit *k);
- // KitInformation interface
- QVariant defaultValue(const ProjectExplorer::Kit *k) const final;
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const final;
+ // KitAspect interface
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const final;
void setup(ProjectExplorer::Kit *k) final;
void fix(ProjectExplorer::Kit *k) final;
void upgrade(ProjectExplorer::Kit *k) final;
ItemList toUserOutput(const ProjectExplorer::Kit *k) const final;
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const final;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const final;
+
+private:
+ QVariant defaultValue(const ProjectExplorer::Kit *k) const;
};
-class CMAKE_EXPORT CMakeConfigurationKitInformation : public ProjectExplorer::KitInformation
+class CMakeConfigurationKitAspect : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- CMakeConfigurationKitInformation();
+ CMakeConfigurationKitAspect();
static CMakeConfig configuration(const ProjectExplorer::Kit *k);
static void setConfiguration(ProjectExplorer::Kit *k, const CMakeConfig &config);
@@ -102,13 +102,16 @@ public:
static CMakeConfig defaultConfiguration(const ProjectExplorer::Kit *k);
- // KitInformation interface
- QVariant defaultValue(const ProjectExplorer::Kit *k) const final;
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const final;
+ // KitAspect interface
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const final;
void setup(ProjectExplorer::Kit *k) final;
void fix(ProjectExplorer::Kit *k) final;
ItemList toUserOutput(const ProjectExplorer::Kit *k) const final;
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const final;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const final;
+
+private:
+ QVariant defaultValue(const ProjectExplorer::Kit *k) const;
};
+} // namespace Internal
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp b/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp
index 19f80d66cc..47c8219c06 100644
--- a/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakelocatorfilter.cpp
@@ -70,7 +70,7 @@ void CMakeLocatorFilter::prepareSearch(const QString &entry)
const int index = title.indexOf(entry);
if (index >= 0) {
Core::LocatorFilterEntry filterEntry(this, title, cmakeProject->projectFilePath().toString());
- filterEntry.extraInfo = FileUtils::shortNativePath(cmakeProject->projectFilePath());
+ filterEntry.extraInfo = cmakeProject->projectFilePath().shortNativePath();
filterEntry.highlightInfo = {index, entry.length()};
m_result.append(filterEntry);
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.cpp b/src/plugins/cmakeprojectmanager/cmakeparser.cpp
index a06a68f684..be67db464f 100644
--- a/src/plugins/cmakeprojectmanager/cmakeparser.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeparser.cpp
@@ -67,12 +67,12 @@ void CMakeParser::stdError(const QString &line)
m_skippedFirstEmptyLine = false;
if (m_commonError.indexIn(trimmedLine) != -1) {
- m_lastTask = Task(Task::Error, QString(), Utils::FileName::fromUserInput(m_commonError.cap(1)),
+ m_lastTask = Task(Task::Error, QString(), Utils::FilePath::fromUserInput(m_commonError.cap(1)),
m_commonError.cap(2).toInt(), Constants::TASK_CATEGORY_BUILDSYSTEM);
m_lines = 1;
return;
} else if (m_nextSubError.indexIn(trimmedLine) != -1) {
- m_lastTask = Task(Task::Error, QString(), Utils::FileName::fromUserInput(m_nextSubError.cap(1)), -1,
+ m_lastTask = Task(Task::Error, QString(), Utils::FilePath::fromUserInput(m_nextSubError.cap(1)), -1,
Constants::TASK_CATEGORY_BUILDSYSTEM);
m_lines = 1;
return;
@@ -86,11 +86,11 @@ void CMakeParser::stdError(const QString &line)
m_expectTripleLineErrorData = LINE_LOCATION;
doFlush();
m_lastTask = Task(trimmedLine.contains(QLatin1String("Error")) ? Task::Error : Task::Warning,
- QString(), Utils::FileName(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM);
+ QString(), Utils::FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM);
return;
} else if (trimmedLine.startsWith("CMake Error: ")) {
m_lastTask = Task(Task::Error, trimmedLine.mid(13),
- Utils::FileName(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM);
+ Utils::FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM);
m_lines = 1;
return;
}
@@ -100,7 +100,7 @@ void CMakeParser::stdError(const QString &line)
{
QRegularExpressionMatch m = m_locationLine.match(trimmedLine);
QTC_CHECK(m.hasMatch());
- m_lastTask.file = Utils::FileName::fromUserInput(trimmedLine.mid(0, m.capturedStart()));
+ m_lastTask.file = Utils::FilePath::fromUserInput(trimmedLine.mid(0, m.capturedStart()));
m_lastTask.line = m.captured(1).toInt();
m_expectTripleLineErrorData = LINE_DESCRIPTION;
}
@@ -146,7 +146,7 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
+ QTest::addColumn<Tasks>("tasks");
QTest::addColumn<QString>("outputLines");
const Core::Id categoryBuild = Constants::TASK_CATEGORY_BUILDSYSTEM;
@@ -155,12 +155,12 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
QTest::newRow("pass-through stdout")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<ProjectExplorer::Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<ProjectExplorer::Task>()
+ << Tasks()
<< QString();
// positive tests
@@ -177,14 +177,14 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
" .hxx .in .txx\n\n")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("Cannot find source file: unknownFile.qml Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx"),
- Utils::FileName::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), 70,
+ Utils::FilePath::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), 70,
categoryBuild)
<< Task(Task::Error,
QLatin1String("Cannot find source file: CMakeLists.txt2 Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx"),
- Utils::FileName::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("src/1/app/CMakeLists.txt")), -1,
categoryBuild))
<< QString();
@@ -193,10 +193,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
" add_subdirectory given source \"app1\" which is not an existing directory.\n\n")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("add_subdirectory given source \"app1\" which is not an existing directory."),
- Utils::FileName::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8,
categoryBuild))
<< QString();
@@ -205,10 +205,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
" Unknown CMake command \"i_am_wrong_command\".\n\n")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("Unknown CMake command \"i_am_wrong_command\"."),
- Utils::FileName::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8,
categoryBuild))
<< QString();
@@ -217,10 +217,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
" message called with incorrect number of arguments\n\n")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("message called with incorrect number of arguments"),
- Utils::FileName::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("src/1/CMakeLists.txt")), 8,
categoryBuild))
<< QString();
@@ -231,10 +231,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
"\".")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("Parse error. Expected \"(\", got newline with text \"\n\"."),
- Utils::FileName::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9,
+ Utils::FilePath::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9,
categoryBuild))
<< QString();
@@ -244,10 +244,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
"CMAKE_MAKE_PROGRAM\n")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Missing variable is:\nCMAKE_MAKE_PROGRAM\n")
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("Error required internal CMake variable not set, cmake may be not be built correctly."),
- Utils::FileName(), -1, categoryBuild))
+ Utils::FilePath(), -1, categoryBuild))
<< QString();
QTest::newRow("cmake error at")
@@ -257,10 +257,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
" \".\n")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("Parse error. Expected \"(\", got newline with text \" \"."),
- Utils::FileName::fromUserInput(QLatin1String("CMakeLists.txt")), 4,
+ Utils::FilePath::fromUserInput(QLatin1String("CMakeLists.txt")), 4,
categoryBuild))
<< QString();
@@ -270,10 +270,10 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
"Argument not separated from preceding token by whitespace.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("Argument not separated from preceding token by whitespace."),
- Utils::FileName::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9,
+ Utils::FilePath::fromUserInput(QLatin1String("/test/path/CMakeLists.txt")), 9,
categoryBuild))
<< QString();
}
@@ -284,7 +284,7 @@ void Internal::CMakeProjectPlugin::testCMakeParser()
testbench.appendOutputParser(new CMakeParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index a9d4d76b96..a3e7ca3c37 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -26,6 +26,7 @@
#include "cmakeproject.h"
#include "cmakebuildconfiguration.h"
+#include "cmakebuildstep.h"
#include "cmakekitinformation.h"
#include "cmakeprojectconstants.h"
#include "cmakeprojectnodes.h"
@@ -37,6 +38,7 @@
#include <cpptools/generatedcodemodelsupport.h>
#include <cpptools/projectinfo.h>
#include <cpptools/cpptoolsconstants.h>
+#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/headerpath.h>
@@ -52,6 +54,7 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <utils/hostosinfo.h>
@@ -78,7 +81,7 @@ static CMakeBuildConfiguration *activeBc(const CMakeProject *p)
/*!
\class CMakeProject
*/
-CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEMIMETYPE, fileName),
+CMakeProject::CMakeProject(const FilePath &fileName) : Project(Constants::CMAKEMIMETYPE, fileName),
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
{
setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
@@ -211,7 +214,7 @@ CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEM
// TreeScanner:
connect(&m_treeScanner, &TreeScanner::finished, this, &CMakeProject::handleTreeScanningFinished);
- m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FileName &fn) {
+ m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FilePath &fn) {
// Mime checks requires more resources, so keep it last in check list
auto isIgnored =
fn.toString().startsWith(projectFilePath().toString() + ".user") ||
@@ -231,7 +234,7 @@ CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEM
return isIgnored;
});
- m_treeScanner.setTypeFactory([](const Utils::MimeType &mimeType, const Utils::FileName &fn) {
+ m_treeScanner.setTypeFactory([](const Utils::MimeType &mimeType, const Utils::FilePath &fn) {
auto type = TreeScanner::genericFileType(mimeType, fn);
if (type == FileType::Unknown) {
if (mimeType.isValid()) {
@@ -265,13 +268,57 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
QTC_ASSERT(bc == aBc, return);
QTC_ASSERT(m_treeScanner.isFinished() && !m_buildDirManager.isParsing(), return);
- bc->setBuildTargets(m_buildDirManager.takeBuildTargets());
- bc->setConfigurationFromCMake(m_buildDirManager.takeCMakeConfiguration());
+ const QList<CMakeBuildTarget> buildTargets = m_buildDirManager.takeBuildTargets();
+ bc->setBuildTargets(buildTargets);
+ const CMakeConfig cmakeConfig = m_buildDirManager.takeCMakeConfiguration();
+ bc->setConfigurationFromCMake(cmakeConfig);
+
+ CMakeConfig patchedConfig = cmakeConfig;
+ {
+ CMakeConfigItem settingFileItem;
+ settingFileItem.key = "ANDROID_DEPLOYMENT_SETTINGS_FILE";
+ settingFileItem.value = bc->buildDirectory()
+ .pathAppended("android_deployment_settings.json").toString().toUtf8();
+ patchedConfig.append(settingFileItem);
+ }
+
+ QSet<QString> res;
+ QStringList apps;
+ for (const auto &target : bc->buildTargets()) {
+ if (target.targetType == CMakeProjectManager::DynamicLibraryType) {
+ res.insert(target.executable.parentDir().toString());
+ apps.push_back(target.executable.toUserOutput());
+ }
+ // ### shall we add also the ExecutableType ?
+ }
+ {
+ CMakeConfigItem paths;
+ paths.key = "ANDROID_SO_LIBS_PATHS";
+ paths.values = res.toList();
+ patchedConfig.append(paths);
+ }
+
+ apps.sort();
+ {
+ CMakeConfigItem appsPaths;
+ appsPaths.key = "TARGETS_BUILD_PATH";
+ appsPaths.values = apps;
+ patchedConfig.append(appsPaths);
+ }
+
auto newRoot = generateProjectTree(m_allFiles);
if (newRoot) {
setDisplayName(newRoot->displayName());
setRootProjectNode(std::move(newRoot));
+
+ for (const CMakeBuildTarget &bt : buildTargets) {
+ const QString buildKey = CMakeTargetNode::generateId(bt.sourceDirectory, bt.title);
+ if (ProjectNode *node = findNodeForBuildKey(buildKey)) {
+ if (auto targetNode = dynamic_cast<CMakeTargetNode *>(node))
+ targetNode->setConfig(patchedConfig);
+ }
+ }
}
Target *t = bc->target();
@@ -334,7 +381,7 @@ void CMakeProject::updateQmlJSCodeModel()
}
foreach (const QString &cmakeImport, CMakeConfigItem::cmakeSplitValue(cmakeImports))
- projectInfo.importPaths.maybeInsert(FileName::fromString(cmakeImport), QmlJS::Dialect::Qml);
+ projectInfo.importPaths.maybeInsert(FilePath::fromString(cmakeImport), QmlJS::Dialect::Qml);
modelManager->updateProjectInfo(projectInfo, this);
}
@@ -355,13 +402,13 @@ bool CMakeProject::knowsAllBuildExecutables() const
return false;
}
-QList<Task> CMakeProject::projectIssues(const Kit *k) const
+Tasks CMakeProject::projectIssues(const Kit *k) const
{
- QList<Task> result = Project::projectIssues(k);
+ Tasks result = Project::projectIssues(k);
- if (!CMakeKitInformation::cmakeTool(k))
+ if (!CMakeKitAspect::cmakeTool(k))
result.append(createProjectTask(Task::TaskType::Error, tr("No cmake tool set.")));
- if (ToolChainKitInformation::toolChains(k).isEmpty())
+ if (ToolChainKitAspect::toolChains(k).isEmpty())
result.append(createProjectTask(Task::TaskType::Warning, tr("No compilers set in kit.")));
return result;
@@ -541,17 +588,16 @@ QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const
if (!activeTarget())
return QStringList();
QFileInfo fi(sourceFile);
- FileName project = projectDirectory();
- FileName baseDirectory = FileName::fromString(fi.absolutePath());
+ FilePath project = projectDirectory();
+ FilePath baseDirectory = FilePath::fromString(fi.absolutePath());
while (baseDirectory.isChildOf(project)) {
- FileName cmakeListsTxt = baseDirectory;
- cmakeListsTxt.appendPath("CMakeLists.txt");
+ const FilePath cmakeListsTxt = baseDirectory.pathAppended("CMakeLists.txt");
if (cmakeListsTxt.exists())
break;
QDir dir(baseDirectory.toString());
dir.cdUp();
- baseDirectory = FileName::fromString(dir.absolutePath());
+ baseDirectory = FilePath::fromString(dir.absolutePath());
}
QDir srcDirRoot = QDir(project.toString());
@@ -575,6 +621,29 @@ QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const
}
}
+ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const
+{
+ return contains(files(AllFiles), [](const FilePath &f) {
+ return f.fileName() == "QtCreatorDeployment.txt";
+ }) ? DeploymentKnowledge::Approximative : 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->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
+ ->firstOfType<CMakeBuildStep>()) {
+ if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target->kit()))
+ cmd.command = tool->cmakeExecutable();
+ }
+ }
+ cmd.arguments << "--build" << "." << "--target" << "install";
+ cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot));
+ return cmd;
+}
+
bool CMakeProject::mustUpdateCMakeStateBeforeBuild()
{
return m_delayedParsingTimer.isActive();
@@ -590,7 +659,7 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeProject::findExtraCompilers() const
= Utils::transform<QSet>(factories, &ExtraCompilerFactory::sourceTag);
// Find all files generated by any of the extra compilers, in a rather crude way.
- const FileNameList fileList = files([&fileExtensions](const Node *n) {
+ const FilePathList fileList = files([&fileExtensions](const Node *n) {
if (!SourceFiles(n))
return false;
const QString fp = n->filePath().toString();
@@ -599,7 +668,7 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeProject::findExtraCompilers() const
});
// Generate the necessary information:
- for (const FileName &file : fileList) {
+ for (const FilePath &file : fileList) {
ExtraCompilerFactory *factory = Utils::findOrDefault(factories, [&file](const ExtraCompilerFactory *f) {
return file.endsWith('.' + f->sourceTag());
});
@@ -609,9 +678,9 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeProject::findExtraCompilers() const
if (generated.isEmpty())
continue;
- const FileNameList fileNames
+ const FilePathList fileNames
= transform(generated,
- [](const QString &s) { return FileName::fromString(s); });
+ [](const QString &s) { return FilePath::fromString(s); });
extraCompilers.append(factory->create(this, file, fileNames));
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index 686d93996f..3af409f1b6 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -30,11 +30,11 @@
#include "builddirmanager.h"
#include "cmakebuildtarget.h"
#include "cmakeprojectimporter.h"
-#include "treescanner.h"
#include <projectexplorer/extracompiler.h>
-#include <projectexplorer/projectmacro.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/projectmacro.h>
+#include <projectexplorer/treescanner.h>
#include <utils/fileutils.h>
@@ -60,14 +60,14 @@ class CMAKE_EXPORT CMakeProject : public ProjectExplorer::Project
Q_OBJECT
public:
- explicit CMakeProject(const Utils::FileName &filename);
+ explicit CMakeProject(const Utils::FilePath &filename);
~CMakeProject() final;
QStringList buildTargetTitles() const;
bool knowsAllBuildExecutables() const final;
- QList<ProjectExplorer::Task> projectIssues(const ProjectExplorer::Kit *k) const final;
+ ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
void runCMake();
void runCMakeAndScanProjectTree();
@@ -103,12 +103,17 @@ private:
QList<ProjectExplorer::ExtraCompiler *> findExtraCompilers() const;
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+ bool hasMakeInstallEquivalent() const override { return true; }
+ ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target,
+ const QString &installRoot) override;
+
// TODO probably need a CMake specific node structure
QList<CMakeBuildTarget> m_buildTargets;
CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
- Internal::TreeScanner m_treeScanner;
+ ProjectExplorer::TreeScanner m_treeScanner;
Internal::BuildDirManager m_buildDirManager;
bool m_waitingForScan = false;
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h
index e1e1a0114e..8714f04111 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h
@@ -38,6 +38,8 @@ const char RUNCMAKE[] = "CMakeProject.RunCMake";
const char CLEARCMAKECACHE[] = "CMakeProject.ClearCache";
const char RESCANPROJECT[] = "CMakeProject.RescanProject";
const char RUNCMAKECONTEXTMENU[] = "CMakeProject.RunCMakeContextMenu";
+const char BUILDFILECONTEXTMENU[] = "CMakeProject.BuildFileContextMenu";
+const char BUILDFILE[] = "CMakeProject.BuildFile";
// Project
const char CMAKEPROJECT_ID[] = "CMakeProjectManager.CMakeProject";
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
index 170e52e933..e647692439 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp
@@ -47,6 +47,7 @@
using namespace ProjectExplorer;
using namespace QtSupport;
+using namespace Utils;
namespace {
@@ -55,7 +56,7 @@ Q_LOGGING_CATEGORY(cmInputLog, "qtc.cmake.import", QtWarningMsg);
struct CMakeToolChainData
{
QByteArray languageId;
- Utils::FileName compilerPath;
+ Utils::FilePath compilerPath;
Core::Id mapLanguageIdToQtC() const
{
const QByteArray li = languageId.toLower();
@@ -72,10 +73,10 @@ struct DirectoryData
{
// Project Stuff:
QByteArray cmakeBuildType;
- Utils::FileName buildDirectory;
+ Utils::FilePath buildDirectory;
// Kit Stuff
- Utils::FileName cmakeBinary;
+ Utils::FilePath cmakeBinary;
QByteArray generator;
QByteArray extraGenerator;
QByteArray platform;
@@ -105,9 +106,9 @@ static QStringList scanDirectory(const QString &path, const QString &prefix)
namespace CMakeProjectManager {
namespace Internal {
-CMakeProjectImporter::CMakeProjectImporter(const Utils::FileName &path) : QtProjectImporter(path)
+CMakeProjectImporter::CMakeProjectImporter(const Utils::FilePath &path) : QtProjectImporter(path)
{
- useTemporaryKitInformation(CMakeKitInformation::id(),
+ useTemporaryKitAspect(CMakeKitAspect::id(),
[this](Kit *k, const QVariantList &vl) { cleanupTemporaryCMake(k, vl); },
[this](Kit *k, const QVariantList &vl) { persistTemporaryCMake(k, vl); });
@@ -130,24 +131,24 @@ QStringList CMakeProjectImporter::importCandidates()
return finalists;
}
-static Utils::FileName qmakeFromCMakeCache(const CMakeConfig &config)
+static Utils::FilePath qmakeFromCMakeCache(const CMakeConfig &config)
{
// Qt4 way to define things (more convenient for us, so try this first;-)
- Utils::FileName qmake
- = Utils::FileName::fromUtf8(CMakeConfigItem::valueOf(QByteArray("QT_QMAKE_EXECUTABLE"), config));
+ Utils::FilePath qmake
+ = Utils::FilePath::fromUtf8(CMakeConfigItem::valueOf(QByteArray("QT_QMAKE_EXECUTABLE"), config));
qCDebug(cmInputLog()) << "QT_QMAKE_EXECUTABLE=" << qmake.toUserOutput();
if (!qmake.isEmpty())
return qmake;
// Check Qt5 settings: oh, the horror!
- const Utils::FileName qtCMakeDir
- = Utils::FileName::fromUtf8(CMakeConfigItem::valueOf(QByteArray("Qt5Core_DIR"), config));
+ const Utils::FilePath qtCMakeDir
+ = Utils::FilePath::fromUtf8(CMakeConfigItem::valueOf(QByteArray("Qt5Core_DIR"), config));
qCDebug(cmInputLog()) << "Qt5Core_DIR=" << qtCMakeDir.toUserOutput();
- const Utils::FileName canQtCMakeDir = Utils::FileName::fromString(qtCMakeDir.toFileInfo().canonicalFilePath());
+ const Utils::FilePath canQtCMakeDir = Utils::FilePath::fromString(qtCMakeDir.toFileInfo().canonicalFilePath());
qCInfo(cmInputLog()) << "Qt5Core_DIR (canonical)=" << canQtCMakeDir.toUserOutput();
if (qtCMakeDir.isEmpty())
- return Utils::FileName();
- const Utils::FileName baseQtDir = canQtCMakeDir.parentDir().parentDir().parentDir(); // Up 3 levels...
+ return Utils::FilePath();
+ const Utils::FilePath baseQtDir = canQtCMakeDir.parentDir().parentDir().parentDir(); // Up 3 levels...
qCDebug(cmInputLog()) << "BaseQtDir:" << baseQtDir.toUserOutput();
// "Parse" Qt5Core/Qt5CoreConfigExtras.cmake:
@@ -166,7 +167,7 @@ static Utils::FileName qmakeFromCMakeCache(const CMakeConfig &config)
QFile extras(qtCMakeDir.toString() + "/Qt5CoreConfigExtras.cmake");
if (!extras.open(QIODevice::ReadOnly))
- return Utils::FileName();
+ return Utils::FilePath();
QByteArray data;
bool inQmakeSection = false;
@@ -201,22 +202,20 @@ static Utils::FileName qmakeFromCMakeCache(const CMakeConfig &config)
const int sp = origLine.indexOf('}');
const int ep = origLine.lastIndexOf('"');
- QTC_ASSERT(sp > 0, return Utils::FileName());
- QTC_ASSERT(ep > sp + 2, return Utils::FileName());
- QTC_ASSERT(ep < origLine.count(), return Utils::FileName());
+ QTC_ASSERT(sp > 0, return Utils::FilePath());
+ QTC_ASSERT(ep > sp + 2, return Utils::FilePath());
+ QTC_ASSERT(ep < origLine.count(), return Utils::FilePath());
// Eat the leading "}/" and trailing "
const QByteArray locationPart = origLine.mid(sp + 2, ep - 2 - sp);
- Utils::FileName result = baseQtDir;
- result.appendPath(QString::fromUtf8(locationPart));
- return result;
+ return baseQtDir.pathAppended(QString::fromUtf8(locationPart));
}
}
}
}
// Now try to make sense of .../Qt5CoreConfig.cmake:
- return Utils::FileName();
+ return Utils::FilePath();
}
QVector<CMakeToolChainData> extractToolChainsFromCache(const CMakeConfig &config)
@@ -226,16 +225,15 @@ QVector<CMakeToolChainData> extractToolChainsFromCache(const CMakeConfig &config
if (!i.key.startsWith("CMAKE_") || !i.key.endsWith("_COMPILER"))
continue;
const QByteArray language = i.key.mid(6, i.key.count() - 6 - 9); // skip "CMAKE_" and "_COMPILER"
- result.append({language, Utils::FileName::fromUtf8(i.value)});
+ result.append({language, Utils::FilePath::fromUtf8(i.value)});
}
return result;
}
-QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &importPath) const
+QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FilePath &importPath) const
{
qCInfo(cmInputLog()) << "Examining directory:" << importPath.toUserOutput();
- Utils::FileName cacheFile = importPath;
- cacheFile.appendPath("CMakeCache.txt");
+ const FilePath cacheFile = importPath.pathAppended("CMakeCache.txt");
if (!cacheFile.exists()) {
qCDebug(cmInputLog()) << cacheFile.toUserOutput() << "does not exist, returning.";
@@ -249,8 +247,8 @@ QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &impo
return { };
}
const auto homeDir
- = Utils::FileName::fromUserInput(QString::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", config)));
- const Utils::FileName canonicalProjectDirectory = Utils::FileUtils::canonicalPath(projectDirectory());
+ = Utils::FilePath::fromUserInput(QString::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", config)));
+ const Utils::FilePath canonicalProjectDirectory = projectDirectory().canonicalPath();
if (homeDir != canonicalProjectDirectory) {
qCDebug(cmInputLog()) << "Wrong source directory:" << homeDir.toUserOutput()
<< "expected:" << canonicalProjectDirectory.toUserOutput();
@@ -262,7 +260,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &impo
data->cmakeBuildType = CMakeConfigItem::valueOf("CMAKE_BUILD_TYPE", config);
data->cmakeBinary
- = Utils::FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_COMMAND", config));
+ = Utils::FilePath::fromUtf8(CMakeConfigItem::valueOf("CMAKE_COMMAND", config));
data->generator = CMakeConfigItem::valueOf("CMAKE_GENERATOR", config);
data->extraGenerator = CMakeConfigItem::valueOf("CMAKE_EXTRA_GENERATOR", config);
data->platform = CMakeConfigItem::valueOf("CMAKE_GENERATOR_PLATFORM", config);
@@ -271,7 +269,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &impo
data->sysroot = CMakeConfigItem::valueOf("CMAKE_SYSROOT", config);
// Qt:
- const Utils::FileName qmake = qmakeFromCMakeCache(config);
+ const Utils::FilePath qmake = qmakeFromCMakeCache(config);
if (!qmake.isEmpty())
data->qt = findOrCreateQtVersion(qmake);
@@ -286,24 +284,24 @@ bool CMakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
{
const DirectoryData *data = static_cast<DirectoryData *>(directoryData);
- CMakeTool *cm = CMakeKitInformation::cmakeTool(k);
+ CMakeTool *cm = CMakeKitAspect::cmakeTool(k);
if (!cm || cm->cmakeExecutable() != data->cmakeBinary)
return false;
- if (CMakeGeneratorKitInformation::generator(k) != QString::fromUtf8(data->generator)
- || CMakeGeneratorKitInformation::extraGenerator(k) != QString::fromUtf8(data->extraGenerator)
- || CMakeGeneratorKitInformation::platform(k) != QString::fromUtf8(data->platform)
- || CMakeGeneratorKitInformation::toolset(k) != QString::fromUtf8(data->toolset))
+ if (CMakeGeneratorKitAspect::generator(k) != QString::fromUtf8(data->generator)
+ || CMakeGeneratorKitAspect::extraGenerator(k) != QString::fromUtf8(data->extraGenerator)
+ || CMakeGeneratorKitAspect::platform(k) != QString::fromUtf8(data->platform)
+ || CMakeGeneratorKitAspect::toolset(k) != QString::fromUtf8(data->toolset))
return false;
- if (SysRootKitInformation::sysRoot(k) != Utils::FileName::fromUtf8(data->sysroot))
+ if (SysRootKitAspect::sysRoot(k) != Utils::FilePath::fromUtf8(data->sysroot))
return false;
- if (data->qt.qt && QtSupport::QtKitInformation::qtVersionId(k) != data->qt.qt->uniqueId())
+ if (data->qt.qt && QtSupport::QtKitAspect::qtVersionId(k) != data->qt.qt->uniqueId())
return false;
for (const CMakeToolChainData &tcd : data->toolChains) {
- ToolChain *tc = ToolChainKitInformation::toolChain(k, tcd.mapLanguageIdToQtC());
+ ToolChain *tc = ToolChainKitAspect::toolChain(k, tcd.mapLanguageIdToQtC());
if (!tc || tc->compilerCommand() != tcd.compilerPath)
return false;
}
@@ -321,14 +319,14 @@ Kit *CMakeProjectImporter::createKit(void *directoryData) const
const CMakeToolData cmtd = findOrCreateCMakeTool(data->cmakeBinary);
QTC_ASSERT(cmtd.cmakeTool, return);
if (cmtd.isTemporary)
- addTemporaryData(CMakeKitInformation::id(), cmtd.cmakeTool->id().toSetting(), k);
+ addTemporaryData(CMakeKitAspect::id(), cmtd.cmakeTool->id().toSetting(), k);
- CMakeGeneratorKitInformation::setGenerator(k, QString::fromUtf8(data->generator));
- CMakeGeneratorKitInformation::setExtraGenerator(k, QString::fromUtf8(data->extraGenerator));
- CMakeGeneratorKitInformation::setPlatform(k, QString::fromUtf8(data->platform));
- CMakeGeneratorKitInformation::setToolset(k, QString::fromUtf8(data->toolset));
+ CMakeGeneratorKitAspect::setGenerator(k, QString::fromUtf8(data->generator));
+ CMakeGeneratorKitAspect::setExtraGenerator(k, QString::fromUtf8(data->extraGenerator));
+ CMakeGeneratorKitAspect::setPlatform(k, QString::fromUtf8(data->platform));
+ CMakeGeneratorKitAspect::setToolset(k, QString::fromUtf8(data->toolset));
- SysRootKitInformation::setSysRoot(k, Utils::FileName::fromUtf8(data->sysroot));
+ SysRootKitAspect::setSysRoot(k, Utils::FilePath::fromUtf8(data->sysroot));
for (const CMakeToolChainData &cmtcd : data->toolChains) {
const ToolChainData tcd
@@ -337,10 +335,10 @@ Kit *CMakeProjectImporter::createKit(void *directoryData) const
if (tcd.areTemporary) {
for (ToolChain *tc : tcd.tcs)
- addTemporaryData(ToolChainKitInformation::id(), tc->id(), k);
+ addTemporaryData(ToolChainKitAspect::id(), tc->id(), k);
}
- ToolChainKitInformation::setToolChain(k, tcd.tcs.at(0));
+ ToolChainKitAspect::setToolChain(k, tcd.tcs.at(0));
}
qCInfo(cmInputLog()) << "Temporary Kit created.";
@@ -366,7 +364,7 @@ const QList<BuildInfo> CMakeProjectImporter::buildInfoListForKit(const Kit *k, v
}
CMakeProjectImporter::CMakeToolData
-CMakeProjectImporter::findOrCreateCMakeTool(const Utils::FileName &cmakeToolPath) const
+CMakeProjectImporter::findOrCreateCMakeTool(const Utils::FilePath &cmakeToolPath) const
{
CMakeToolData result;
result.cmakeTool = CMakeToolManager::findByCommand(cmakeToolPath);
@@ -388,7 +386,7 @@ void CMakeProjectImporter::cleanupTemporaryCMake(Kit *k, const QVariantList &vl)
if (vl.isEmpty())
return; // No temporary CMake
QTC_ASSERT(vl.count() == 1, return);
- CMakeKitInformation::setCMakeTool(k, Core::Id()); // Always mark Kit as not using this Qt
+ CMakeKitAspect::setCMakeTool(k, Core::Id()); // Always mark Kit as not using this Qt
CMakeToolManager::deregisterCMakeTool(Core::Id::fromSetting(vl.at(0)));
qCDebug(cmInputLog()) << "Temporary CMake tool cleaned up.";
}
@@ -400,7 +398,7 @@ void CMakeProjectImporter::persistTemporaryCMake(Kit *k, const QVariantList &vl)
QTC_ASSERT(vl.count() == 1, return);
const QVariant data = vl.at(0);
CMakeTool *tmpCmake = CMakeToolManager::findById(Core::Id::fromSetting(data));
- CMakeTool *actualCmake = CMakeKitInformation::cmakeTool(k);
+ CMakeTool *actualCmake = CMakeKitAspect::cmakeTool(k);
// User changed Kit away from temporary CMake that was set up:
if (tmpCmake && actualCmake != tmpCmake)
@@ -450,7 +448,7 @@ void CMakeProjectPlugin::testCMakeProjectImporterQt()
config.append(CMakeConfigItem(key.toUtf8(), value.toUtf8()));
}
- Utils::FileName realQmake = qmakeFromCMakeCache(config);
+ Utils::FilePath realQmake = qmakeFromCMakeCache(config);
QCOMPARE(realQmake.toString(), expectedQmake);
}
void CMakeProjectPlugin::testCMakeProjectImporterToolChain_data()
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
index c86fe77041..9940da3723 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.h
@@ -36,12 +36,12 @@ namespace Internal {
class CMakeProjectImporter : public QtSupport::QtProjectImporter
{
public:
- CMakeProjectImporter(const Utils::FileName &path);
+ CMakeProjectImporter(const Utils::FilePath &path);
QStringList importCandidates() final;
private:
- QList<void *> examineDirectory(const Utils::FileName &importPath) const final;
+ QList<void *> examineDirectory(const Utils::FilePath &importPath) const final;
bool matchKit(void *directoryData, const ProjectExplorer::Kit *k) const final;
ProjectExplorer::Kit *createKit(void *directoryData) const final;
const QList<ProjectExplorer::BuildInfo> buildInfoListForKit(const ProjectExplorer::Kit *k,
@@ -51,7 +51,7 @@ private:
bool isTemporary = false;
CMakeTool *cmakeTool = nullptr;
};
- CMakeToolData findOrCreateCMakeTool(const Utils::FileName &cmakeToolPath) const;
+ CMakeToolData findOrCreateCMakeTool(const Utils::FilePath &cmakeToolPath) const;
void deleteDirectoryData(void *directoryData) const final;
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
index 63fe9c5fbb..21be7d1995 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
@@ -30,11 +30,14 @@
#include "cmakeproject.h"
#include "cmakesettingspage.h"
#include "cmaketoolmanager.h"
+#include "cmakeprojectnodes.h"
#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -42,6 +45,8 @@
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
+#include <utils/parameteraction.h>
+
#include <QAction>
#include <QDateTime>
#include <QIcon>
@@ -61,6 +66,8 @@ CMakeManager::CMakeManager() :
Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT);
Core::ActionContainer *msubproject =
Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);
+ Core::ActionContainer *mfile =
+ Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FILECONTEXT);
const Core::Context projectContext(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
const Core::Context globalContext(Core::Constants::C_GLOBAL);
@@ -90,6 +97,14 @@ CMakeManager::CMakeManager() :
runCMake(ProjectTree::currentProject());
});
+ m_buildFileContextMenu = new QAction(tr("Build"), this);
+ command = Core::ActionManager::registerAction(m_buildFileContextMenu,
+ Constants::BUILDFILECONTEXTMENU, projectContext);
+ command->setAttribute(Core::Command::CA_Hide);
+ mfile->addAction(command, ProjectExplorer::Constants::G_FILE_OTHER);
+ connect(m_buildFileContextMenu, &QAction::triggered,
+ this, &CMakeManager::buildFileContextMenu);
+
command = Core::ActionManager::registerAction(m_rescanProjectAction,
Constants::RESCANPROJECT, globalContext);
command->setAttribute(Core::Command::CA_Hide);
@@ -98,10 +113,24 @@ CMakeManager::CMakeManager() :
rescanProject(ProjectTree::currentProject());
});
+ m_buildFileAction = new Utils::ParameterAction(tr("Build File"), tr("Build File \"%1\""),
+ Utils::ParameterAction::AlwaysEnabled, this);
+ command = Core::ActionManager::registerAction(m_buildFileAction, Constants::BUILDFILE);
+ command->setAttribute(Core::Command::CA_Hide);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDescription(m_buildFileAction->text());
+ command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+B")));
+ mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
+ connect(m_buildFileAction, &QAction::triggered, this, [this] { buildFile(); });
+
connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
this, &CMakeManager::updateCmakeActions);
connect(BuildManager::instance(), &BuildManager::buildStateChanged,
this, &CMakeManager::updateCmakeActions);
+ connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
+ this, &CMakeManager::updateBuildFileAction);
+ connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged,
+ this, &CMakeManager::updateCmakeActions);
updateCmakeActions();
}
@@ -113,6 +142,7 @@ void CMakeManager::updateCmakeActions()
m_runCMakeAction->setVisible(visible);
m_clearCMakeCacheAction->setVisible(visible);
m_rescanProjectAction->setVisible(visible);
+ enableBuildFileMenus(ProjectTree::currentNode());
}
void CMakeManager::clearCMakeCache(Project *project)
@@ -144,3 +174,89 @@ void CMakeManager::rescanProject(Project *project)
cmakeProject->runCMakeAndScanProjectTree();// by my experience: every rescan run requires cmake run too
}
+
+void CMakeManager::updateBuildFileAction()
+{
+ Node *node = nullptr;
+ if (Core::IDocument *currentDocument = Core::EditorManager::currentDocument())
+ node = ProjectTree::nodeForFile(currentDocument->filePath());
+ enableBuildFileMenus(node);
+}
+
+void CMakeManager::enableBuildFileMenus(Node *node)
+{
+ m_buildFileAction->setVisible(false);
+ m_buildFileAction->setEnabled(false);
+ m_buildFileAction->setParameter(QString());
+ m_buildFileContextMenu->setEnabled(false);
+
+ if (!node)
+ return;
+ Project *project = ProjectTree::projectForNode(node);
+ if (!project)
+ return;
+ Target *target = project->activeTarget();
+ if (!target)
+ return;
+ const QString generator = CMakeGeneratorKitAspect::generator(target->kit());
+ if (generator != "Ninja" && !generator.contains("Makefiles"))
+ return;
+
+ if (const FileNode *fileNode = node->asFileNode()) {
+ const FileType type = fileNode->fileType();
+ const bool visible = qobject_cast<CMakeProject *>(project)
+ && dynamic_cast<CMakeTargetNode *>(node->parentProjectNode())
+ && (type == FileType::Source || type == FileType::Header);
+
+ const bool enabled = visible && !BuildManager::isBuilding(project);
+ m_buildFileAction->setVisible(visible);
+ m_buildFileAction->setEnabled(enabled);
+ m_buildFileAction->setParameter(node->filePath().fileName());
+ m_buildFileContextMenu->setEnabled(enabled);
+ }
+}
+
+void CMakeManager::buildFile(Node *node)
+{
+ if (!node) {
+ Core::IDocument *currentDocument= Core::EditorManager::currentDocument();
+ if (!currentDocument)
+ return;
+ const Utils::FilePath file = currentDocument->filePath();
+ node = ProjectTree::nodeForFile(file);
+ }
+ FileNode *fileNode = node ? node->asFileNode() : nullptr;
+ if (!fileNode)
+ return;
+ Project *project = ProjectTree::projectForNode(fileNode);
+ if (!project)
+ return;
+ CMakeTargetNode *targetNode = dynamic_cast<CMakeTargetNode *>(fileNode->parentProjectNode());
+ if (!targetNode)
+ return;
+ auto cmakeProject = static_cast<CMakeProject *>(project);
+ Target *target = cmakeProject->activeTarget();
+ const QString generator = CMakeGeneratorKitAspect::generator(target->kit());
+ const QString relativeSource = fileNode->filePath().relativeChildPath(targetNode->filePath()).toString();
+ const QString objExtension = Utils::HostOsInfo::isWindowsHost() ? QString(".obj") : QString(".o");
+ Utils::FilePath targetBase;
+ if (generator == "Ninja") {
+ BuildConfiguration *bc = target->activeBuildConfiguration();
+ const Utils::FilePath relativeBuildDir = targetNode->buildDirectory().relativeChildPath(
+ bc->buildDirectory());
+ targetBase = relativeBuildDir
+ .pathAppended("CMakeFiles")
+ .pathAppended(targetNode->displayName() + ".dir");
+ } else if (!generator.contains("Makefiles")) {
+ Core::MessageManager::write(tr("Build File is not supported for generator \"%1\"")
+ .arg(generator));
+ return;
+ }
+ cmakeProject->buildCMakeTarget(targetBase.pathAppended(relativeSource).toString() + objExtension);
+}
+
+void CMakeManager::buildFileContextMenu()
+{
+ if (Node *node = ProjectTree::currentNode())
+ buildFile(node);
+}
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
index 0a045c19c0..eab78b190a 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
@@ -27,6 +27,8 @@
#include <projectexplorer/project.h>
+namespace Utils { class ParameterAction; }
+
QT_BEGIN_NAMESPACE
class QAction;
QT_END_NAMESPACE
@@ -34,7 +36,6 @@ QT_END_NAMESPACE
namespace CMakeProjectManager {
namespace Internal {
-
class CMakeManager : public QObject
{
Q_OBJECT
@@ -47,11 +48,17 @@ private:
void clearCMakeCache(ProjectExplorer::Project *project);
void runCMake(ProjectExplorer::Project *project);
void rescanProject(ProjectExplorer::Project *project);
+ void buildFileContextMenu();
+ void buildFile(ProjectExplorer::Node *node = nullptr);
+ void updateBuildFileAction();
+ void enableBuildFileMenus(ProjectExplorer::Node *node);
QAction *m_runCMakeAction;
QAction *m_clearCMakeCacheAction;
QAction *m_runCMakeActionContextMenu;
QAction *m_rescanProjectAction;
+ QAction *m_buildFileContextMenu;
+ Utils::ParameterAction *m_buildFileAction;
};
} // namespace Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
index 641c53bb25..dc4e30223b 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
@@ -25,7 +25,6 @@ HEADERS = builddirmanager.h \
cmaketoolmanager.h \
cmake_global.h \
cmakekitinformation.h \
- cmakekitconfigwidget.h \
cmakecbpparser.h \
cmakebuildsettingswidget.h \
cmakeindenter.h \
@@ -36,14 +35,12 @@ HEADERS = builddirmanager.h \
configmodelitemdelegate.h \
servermode.h \
servermodereader.h \
- tealeafreader.h \
- treescanner.h
+ tealeafreader.h
SOURCES = builddirmanager.cpp \
builddirparameters.cpp \
builddirreader.cpp \
cmakebuildstep.cpp \
- cmakebuildtarget.cpp \
cmakeconfigitem.cpp \
cmakeproject.cpp \
cmakeprojectimporter.cpp \
@@ -61,7 +58,6 @@ SOURCES = builddirmanager.cpp \
cmakesettingspage.cpp \
cmaketoolmanager.cpp \
cmakekitinformation.cpp \
- cmakekitconfigwidget.cpp \
cmakecbpparser.cpp \
cmakebuildsettingswidget.cpp \
cmakeindenter.cpp \
@@ -72,8 +68,7 @@ SOURCES = builddirmanager.cpp \
configmodelitemdelegate.cpp \
servermode.cpp \
servermodereader.cpp \
- tealeafreader.cpp \
- treescanner.cpp \
+ tealeafreader.cpp
RESOURCES += cmakeproject.qrc
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
index cfa9b36e30..e31c42886a 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
@@ -32,7 +32,6 @@ QtcPlugin {
"cmakebuildsettingswidget.h",
"cmakebuildstep.cpp",
"cmakebuildstep.h",
- "cmakebuildtarget.cpp",
"cmakebuildtarget.h",
"cmakecbpparser.cpp",
"cmakecbpparser.h",
@@ -42,8 +41,6 @@ QtcPlugin {
"cmakeeditor.h",
"cmakefilecompletionassist.cpp",
"cmakefilecompletionassist.h",
- "cmakekitconfigwidget.h",
- "cmakekitconfigwidget.cpp",
"cmakekitinformation.h",
"cmakekitinformation.cpp",
"cmakelocatorfilter.cpp",
@@ -90,8 +87,6 @@ QtcPlugin {
"servermodereader.cpp",
"servermodereader.h",
"tealeafreader.cpp",
- "tealeafreader.h",
- "treescanner.cpp",
- "treescanner.h"
+ "tealeafreader.h"
]
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
index 64541593b9..f14f627b34 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
@@ -25,22 +25,31 @@
#include "cmakeprojectnodes.h"
+#include "cmakeconfigitem.h"
#include "cmakeprojectconstants.h"
#include "cmakeprojectplugin.h"
+
+#include <android/androidconstants.h>
+
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <cpptools/cpptoolsconstants.h>
+
+#include <projectexplorer/target.h>
+
#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/optional.h>
-
+#include <utils/qtcassert.h>
#include <QClipboard>
#include <QDir>
#include <QGuiApplication>
#include <QMessageBox>
+using namespace ProjectExplorer;
+
using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal;
@@ -106,8 +115,8 @@ void noAutoAdditionNotify(const QStringList &filePaths, const ProjectExplorer::P
}
-CMakeInputsNode::CMakeInputsNode(const Utils::FileName &cmakeLists) :
- ProjectExplorer::ProjectNode(cmakeLists, generateId(cmakeLists))
+CMakeInputsNode::CMakeInputsNode(const Utils::FilePath &cmakeLists) :
+ ProjectExplorer::ProjectNode(cmakeLists)
{
setPriority(Node::DefaultPriority - 10); // Bottom most!
setDisplayName(QCoreApplication::translate("CMakeFilesProjectNode", "CMake Modules"));
@@ -115,17 +124,7 @@ CMakeInputsNode::CMakeInputsNode(const Utils::FileName &cmakeLists) :
setListInProject(false);
}
-QByteArray CMakeInputsNode::generateId(const Utils::FileName &inputFile)
-{
- return inputFile.toString().toUtf8() + "/cmakeInputs";
-}
-
-bool CMakeInputsNode::showInSimpleTree() const
-{
- return true;
-}
-
-CMakeListsNode::CMakeListsNode(const Utils::FileName &cmakeListPath) :
+CMakeListsNode::CMakeListsNode(const Utils::FilePath &cmakeListPath) :
ProjectExplorer::ProjectNode(cmakeListPath)
{
static QIcon folderIcon = Core::FileIconProvider::directoryIcon(Constants::FILEOVERLAY_CMAKE);
@@ -143,13 +142,12 @@ bool CMakeListsNode::supportsAction(ProjectExplorer::ProjectAction action, const
return action == ProjectExplorer::ProjectAction::AddNewFile;
}
-Utils::optional<Utils::FileName> CMakeListsNode::visibleAfterAddFileAction() const
+Utils::optional<Utils::FilePath> CMakeListsNode::visibleAfterAddFileAction() const
{
- Utils::FileName projFile{filePath()};
- return projFile.appendPath("CMakeLists.txt");
+ return filePath().pathAppended("CMakeLists.txt");
}
-CMakeProjectNode::CMakeProjectNode(const Utils::FileName &directory) :
+CMakeProjectNode::CMakeProjectNode(const Utils::FilePath &directory) :
ProjectExplorer::ProjectNode(directory)
{
setPriority(Node::DefaultProjectPriority + 1000);
@@ -157,11 +155,6 @@ CMakeProjectNode::CMakeProjectNode(const Utils::FileName &directory) :
setListInProject(false);
}
-bool CMakeProjectNode::showInSimpleTree() const
-{
- return true;
-}
-
QString CMakeProjectNode::tooltip() const
{
return QString();
@@ -173,22 +166,19 @@ bool CMakeProjectNode::addFiles(const QStringList &filePaths, QStringList *)
return true; // Return always true as autoadd is not supported!
}
-CMakeTargetNode::CMakeTargetNode(const Utils::FileName &directory, const QString &target) :
- ProjectExplorer::ProjectNode(directory, generateId(directory, target))
+CMakeTargetNode::CMakeTargetNode(const Utils::FilePath &directory, const QString &target) :
+ ProjectExplorer::ProjectNode(directory)
{
+ m_target = target;
setPriority(Node::DefaultProjectPriority + 900);
setIcon(QIcon(":/projectexplorer/images/build.png")); // TODO: Use proper icon!
setListInProject(false);
+ setIsProduct();
}
-QByteArray CMakeTargetNode::generateId(const Utils::FileName &directory, const QString &target)
+QString CMakeTargetNode::generateId(const Utils::FilePath &directory, const QString &target)
{
- return directory.toString().toUtf8() + "///::///" + target.toUtf8();
-}
-
-bool CMakeTargetNode::showInSimpleTree() const
-{
- return true;
+ return directory.toString() + "///::///" + target;
}
QString CMakeTargetNode::tooltip() const
@@ -198,7 +188,63 @@ QString CMakeTargetNode::tooltip() const
QString CMakeTargetNode::buildKey() const
{
- return QString::fromUtf8(id());
+ return generateId(filePath(), m_target);
+}
+
+Utils::FilePath CMakeTargetNode::buildDirectory() const
+{
+ return m_buildDirectory;
+}
+
+void CMakeTargetNode::setBuildDirectory(const Utils::FilePath &directory)
+{
+ m_buildDirectory = directory;
+}
+
+QVariant CMakeTargetNode::data(Core::Id role) const
+{
+ auto value = [this](const QByteArray &key) -> QVariant {
+ for (const CMakeConfigItem &configItem : m_config) {
+ if (configItem.key == key)
+ return configItem.value;
+ }
+ return {};
+ };
+
+ auto values = [this](const QByteArray &key) -> QVariant {
+ for (const CMakeConfigItem &configItem : m_config) {
+ if (configItem.key == key)
+ return configItem.values;
+ }
+ return {};
+ };
+
+ if (role == Android::Constants::AndroidPackageSourceDir)
+ return value("ANDROID_PACKAGE_SOURCE_DIR");
+
+ if (role == Android::Constants::AndroidDeploySettingsFile)
+ return value("ANDROID_DEPLOYMENT_SETTINGS_FILE");
+
+ if (role == Android::Constants::AndroidExtraLibs)
+ return value("ANDROID_EXTRA_LIBS");
+
+ if (role == Android::Constants::AndroidArch)
+ return value("ANDROID_ABI");
+
+ if (role == Android::Constants::AndroidSoLibPath)
+ return values("ANDROID_SO_LIBS_PATHS");
+
+ if (role == Android::Constants::AndroidTargets)
+ return values("TARGETS_BUILD_PATH");
+
+ QTC_CHECK(false);
+ // Better guess than "not present".
+ return value(role.toString().toUtf8());
+}
+
+void CMakeTargetNode::setConfig(const CMakeConfig &config)
+{
+ m_config = config;
}
bool CMakeTargetNode::supportsAction(ProjectExplorer::ProjectAction action,
@@ -213,20 +259,19 @@ bool CMakeTargetNode::addFiles(const QStringList &filePaths, QStringList *)
return true; // Return always true as autoadd is not supported!
}
-Utils::optional<Utils::FileName> CMakeTargetNode::visibleAfterAddFileAction() const
+Utils::optional<Utils::FilePath> CMakeTargetNode::visibleAfterAddFileAction() const
{
- Utils::FileName projFile{filePath()};
- return projFile.appendPath("CMakeLists.txt");
+ return filePath().pathAppended("CMakeLists.txt");
}
-void CMakeTargetNode::setTargetInformation(const QList<Utils::FileName> &artifacts,
+void CMakeTargetNode::setTargetInformation(const QList<Utils::FilePath> &artifacts,
const QString &type)
{
m_tooltip = QCoreApplication::translate("CMakeTargetNode", "Target type: ") + type + "<br>";
if (artifacts.isEmpty()) {
m_tooltip += QCoreApplication::translate("CMakeTargetNode", "No build artifacts");
} else {
- const QStringList tmp = Utils::transform(artifacts, &Utils::FileName::toUserOutput);
+ const QStringList tmp = Utils::transform(artifacts, &Utils::FilePath::toUserOutput);
m_tooltip += QCoreApplication::translate("CMakeTargetNode", "Build artifacts:") + "<br>"
+ tmp.join("<br>");
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h
index 0c8174c10e..5a61737925 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h
@@ -25,6 +25,8 @@
#pragma once
+#include "cmakeconfigitem.h"
+
#include <projectexplorer/projectnodes.h>
namespace CMakeProjectManager {
@@ -33,29 +35,24 @@ namespace Internal {
class CMakeInputsNode : public ProjectExplorer::ProjectNode
{
public:
- CMakeInputsNode(const Utils::FileName &cmakeLists);
-
- static QByteArray generateId(const Utils::FileName &inputFile);
-
- bool showInSimpleTree() const final;
+ CMakeInputsNode(const Utils::FilePath &cmakeLists);
};
class CMakeListsNode : public ProjectExplorer::ProjectNode
{
public:
- CMakeListsNode(const Utils::FileName &cmakeListPath);
+ CMakeListsNode(const Utils::FilePath &cmakeListPath);
bool showInSimpleTree() const final;
bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
- Utils::optional<Utils::FileName> visibleAfterAddFileAction() const override;
+ Utils::optional<Utils::FilePath> visibleAfterAddFileAction() const override;
};
class CMakeProjectNode : public ProjectExplorer::ProjectNode
{
public:
- CMakeProjectNode(const Utils::FileName &directory);
+ CMakeProjectNode(const Utils::FilePath &directory);
- bool showInSimpleTree() const final;
QString tooltip() const final;
bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
@@ -64,22 +61,28 @@ public:
class CMakeTargetNode : public ProjectExplorer::ProjectNode
{
public:
- CMakeTargetNode(const Utils::FileName &directory, const QString &target);
+ CMakeTargetNode(const Utils::FilePath &directory, const QString &target);
- static QByteArray generateId(const Utils::FileName &directory, const QString &target);
+ static QString generateId(const Utils::FilePath &directory, const QString &target);
- void setTargetInformation(const QList<Utils::FileName> &artifacts, const QString &type);
+ void setTargetInformation(const QList<Utils::FilePath> &artifacts, const QString &type);
- bool showInSimpleTree() const final;
QString tooltip() const final;
QString buildKey() const final;
+ Utils::FilePath buildDirectory() const;
+ void setBuildDirectory(const Utils::FilePath &directory);
bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
- Utils::optional<Utils::FileName> visibleAfterAddFileAction() const override;
+ Utils::optional<Utils::FilePath> visibleAfterAddFileAction() const override;
+
+ QVariant data(Core::Id role) const override;
+ void setConfig(const CMakeConfig &config);
private:
QString m_tooltip;
+ Utils::FilePath m_buildDirectory;
+ CMakeConfig m_config;
};
} // namespace Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
index ebd5d44d42..53825f4d7c 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
@@ -43,9 +43,12 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
+
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
+#include <projectexplorer/runcontrol.h>
+
#include <texteditor/snippets/snippetprovider.h>
#include <utils/parameteraction.h>
@@ -59,6 +62,8 @@ namespace Internal {
class CMakeProjectPluginPrivate
{
public:
+ CMakeToolManager cmakeToolManager; // have that before the first CMakeKitAspect
+
Utils::ParameterAction *m_buildTargetContextAction = nullptr;
QMetaObject::Connection m_actionConnect;
@@ -67,9 +72,14 @@ public:
CMakeManager manager;
CMakeBuildStepFactory buildStepFactory;
CMakeRunConfigurationFactory runConfigFactory;
+ SimpleRunWorkerFactory<SimpleTargetRunner, CMakeRunConfiguration> runWorkerFactory;
CMakeBuildConfigurationFactory buildConfigFactory;
CMakeEditorFactory editorFactor;
CMakeLocatorFilter locatorFiler;
+
+ CMakeKitAspect cmakeKitAspect;
+ CMakeGeneratorKitAspect cmakeGeneratorKitAspect;
+ CMakeConfigurationKitAspect cmakeConfigurationKitAspect;
};
const std::unique_ptr<CMakeSpecificSettings>
@@ -104,12 +114,6 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString *
tr("CMake", "SnippetProvider"));
ProjectManager::registerProjectType<CMakeProject>(Constants::CMAKEPROJECTMIMETYPE);
- new CMakeToolManager(this);
-
- KitManager::registerKitInformation<CMakeKitInformation>();
- KitManager::registerKitInformation<CMakeGeneratorKitInformation>();
- KitManager::registerKitInformation<CMakeConfigurationKitInformation>();
-
//menus
ActionContainer *msubproject =
ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);
@@ -143,7 +147,7 @@ void CMakeProjectPlugin::extensionsInitialized()
void CMakeProjectPlugin::updateContextActions()
{
Project *project = ProjectTree::currentProject();
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
auto targetNode = dynamic_cast<const CMakeTargetNode *>(node);
// as targetNode can be deleted while the menu is open, we keep only the
const QString targetDisplayName = targetNode ? targetNode->displayName() : QString();
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h
index 4652078d74..c8a50219f4 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h
@@ -26,8 +26,9 @@
#pragma once
#include "cmakespecificsettingspage.h"
+
#include <extensionsystem/iplugin.h>
-#include <memory>
+
namespace CMakeProjectManager {
namespace Internal {
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
index 3872fe90f4..30514b70a5 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
@@ -33,9 +33,11 @@
#include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/project.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
using namespace ProjectExplorer;
+using namespace Utils;
namespace CMakeProjectManager {
namespace Internal {
@@ -43,27 +45,28 @@ namespace Internal {
CMakeRunConfiguration::CMakeRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- // Workaround for QTCREATORBUG-19354:
- auto cmakeRunEnvironmentModifier = [target](Utils::Environment &env) {
- if (!Utils::HostOsInfo::isWindowsHost())
- return;
+ auto envAspect = addAspect<LocalEnvironmentAspect>(target);
- const Kit *k = target->kit();
- const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(k);
- if (qt)
- env.prependOrSetPath(qt->qmakeProperty("QT_INSTALL_BINS"));
- };
- auto envAspect = addAspect<LocalEnvironmentAspect>(target, cmakeRunEnvironmentModifier);
+ // Workaround for QTCREATORBUG-19354:
+ if (HostOsInfo::isWindowsHost()) {
+ envAspect->addModifier([target](Environment &env) {
+ const Kit *k = target->kit();
+ if (const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(k)) {
+ const QString installBinPath = qt->qmakeProperty("QT_INSTALL_BINS");
+ env.prependOrSetPath(installBinPath);
+ }
+ });
+ }
addAspect<ExecutableAspect>();
addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>(envAspect);
+ addAspect<WorkingDirectoryAspect>();
addAspect<TerminalAspect>();
connect(target->project(), &Project::parsingFinished,
this, &CMakeRunConfiguration::updateTargetInformation);
- if (QtSupport::QtKitInformation::qtVersion(target->kit()))
+ if (QtSupport::QtKitAspect::qtVersion(target->kit()))
setOutputFormatter<QtSupport::QtOutputFormatter>();
}
@@ -75,7 +78,7 @@ void CMakeRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo
bool CMakeRunConfiguration::isBuildTargetValid() const
{
- return Utils::anyOf(target()->applicationTargets().list, [this](const BuildTargetInfo &bti) {
+ return Utils::anyOf(target()->applicationTargets(), [this](const BuildTargetInfo &bti) {
return bti.buildKey == buildKey();
});
}
@@ -97,14 +100,13 @@ QString CMakeRunConfiguration::disabledReason() const
void CMakeRunConfiguration::updateTargetInformation()
{
- BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(buildKey());
+ BuildTargetInfo bti = buildTargetInfo();
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
aspect<LocalEnvironmentAspect>()->buildEnvironmentHasChanged();
auto terminalAspect = aspect<TerminalAspect>();
- if (!terminalAspect->isUserSet())
- terminalAspect->setUseTerminal(bti.usesTerminal);
+ terminalAspect->setUseTerminalHint(bti.usesTerminal);
}
// Factory
@@ -113,8 +115,6 @@ CMakeRunConfigurationFactory::CMakeRunConfigurationFactory()
registerRunConfiguration<CMakeRunConfiguration>("CMakeProjectManager.CMakeRunConfiguration.");
addSupportedProjectType(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
-
- addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
}
} // Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
index 0f125ba6e4..991eb274c4 100644
--- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
@@ -67,12 +67,12 @@ public:
CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const;
CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const;
- QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected);
+ QModelIndex addCMakeTool(const QString &name, const FilePath &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected);
void addCMakeTool(const CMakeTool *item, bool changed);
TreeItem *autoGroupItem() const;
TreeItem *manualGroupItem() const;
void reevaluateChangedFlag(CMakeToolTreeItem *item) const;
- void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable,
+ void updateCMakeTool(const Core::Id &id, const QString &displayName, const FilePath &executable,
bool autoRun, bool autoCreate);
void removeCMakeTool(const Core::Id &id);
void apply();
@@ -101,7 +101,7 @@ public:
m_changed(changed)
{}
- CMakeToolTreeItem(const QString &name, const Utils::FileName &executable,
+ CMakeToolTreeItem(const QString &name, const Utils::FilePath &executable,
bool autoRun, bool autoCreate, bool autodetected) :
m_id(Core::Id::fromString(QUuid::createUuid().toString())),
m_name(name),
@@ -143,7 +143,7 @@ public:
Core::Id m_id;
QString m_name;
- FileName m_executable;
+ FilePath m_executable;
bool m_isAutoRun = true;
bool m_autoCreateBuildDirectory = false;
bool m_autodetected = false;
@@ -168,7 +168,7 @@ CMakeToolItemModel::CMakeToolItemModel()
}
-QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable,
+QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FilePath &executable,
const bool autoRun, const bool autoCreate,
const bool isAutoDetected)
{
@@ -223,7 +223,7 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const
}
void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName,
- const FileName &executable, bool autoRun,
+ const FilePath &executable, bool autoRun,
bool autoCreate)
{
CMakeToolTreeItem *treeItem = cmakeToolItem(id);
@@ -519,7 +519,7 @@ void CMakeToolConfigWidget::cloneCMakeTool()
void CMakeToolConfigWidget::addCMakeTool()
{
QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")),
- FileName(), true, false, false);
+ FilePath(), true, false, false);
m_cmakeToolsView->setCurrentIndex(newItem);
}
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp
index 795f2dc7cb..ac0ac0999e 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp
@@ -102,7 +102,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) :
if (!fromSdk)
m_isAutoDetected = map.value(CMAKE_INFORMATION_AUTODETECTED, false).toBool();
- setCMakeExecutable(Utils::FileName::fromString(map.value(CMAKE_INFORMATION_COMMAND).toString()));
+ setCMakeExecutable(Utils::FilePath::fromString(map.value(CMAKE_INFORMATION_COMMAND).toString()));
}
CMakeTool::~CMakeTool() = default;
@@ -112,7 +112,7 @@ Core::Id CMakeTool::createId()
return Core::Id::fromString(QUuid::createUuid().toString());
}
-void CMakeTool::setCMakeExecutable(const Utils::FileName &executable)
+void CMakeTool::setCMakeExecutable(const Utils::FilePath &executable)
{
if (m_executable == executable)
return;
@@ -187,11 +187,10 @@ QVariantMap CMakeTool::toMap() const
return data;
}
-Utils::FileName CMakeTool::cmakeExecutable() const
+Utils::FilePath CMakeTool::cmakeExecutable() const
{
if (Utils::HostOsInfo::isMacHost() && m_executable.endsWith(".app")) {
- Utils::FileName toTest = m_executable;
- toTest = toTest.appendPath("Contents/bin/cmake");
+ const Utils::FilePath toTest = m_executable.pathAppended("Contents/bin/cmake");
if (toTest.exists())
return toTest;
}
@@ -280,7 +279,7 @@ CMakeTool::PathMapper CMakeTool::pathMapper() const
{
if (m_pathMapper)
return m_pathMapper;
- return [](const Utils::FileName &fn) { return fn; };
+ return [](const Utils::FilePath &fn) { return fn; };
}
void CMakeTool::readInformation(CMakeTool::QueryType type) const
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h
index 052722d89f..85feaf41e5 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.h
+++ b/src/plugins/cmakeprojectmanager/cmaketool.h
@@ -76,7 +76,7 @@ public:
bool matches(const QString &n, const QString &ex) const;
};
- using PathMapper = std::function<Utils::FileName (const Utils::FileName &)>;
+ using PathMapper = std::function<Utils::FilePath (const Utils::FilePath &)>;
explicit CMakeTool(Detection d, const Core::Id &id);
explicit CMakeTool(const QVariantMap &map, bool fromSdk);
@@ -89,11 +89,11 @@ public:
Core::Id id() const { return m_id; }
QVariantMap toMap () const;
- void setCMakeExecutable(const Utils::FileName &executable);
+ void setCMakeExecutable(const Utils::FilePath &executable);
void setAutorun(bool autoRun);
void setAutoCreateBuildDirectory(bool autoBuildDir);
- Utils::FileName cmakeExecutable() const;
+ Utils::FilePath cmakeExecutable() const;
bool isAutoRun() const;
bool autoCreateBuildDirectory() const;
QList<Generator> supportedGenerators() const;
@@ -129,7 +129,7 @@ private:
Core::Id m_id;
QString m_displayName;
- Utils::FileName m_executable;
+ Utils::FilePath m_executable;
bool m_isAutoRun = true;
bool m_isAutoDetected = false;
diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
index a90fe59c81..b9b70c5352 100644
--- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.cpp
@@ -57,7 +57,7 @@ static CMakeToolManagerPrivate *d = nullptr;
CMakeToolManager *CMakeToolManager::m_instance = nullptr;
-CMakeToolManager::CMakeToolManager(QObject *parent) : QObject(parent)
+CMakeToolManager::CMakeToolManager()
{
QTC_ASSERT(!m_instance, return);
m_instance = this;
@@ -86,7 +86,7 @@ QList<CMakeTool *> CMakeToolManager::cmakeTools()
return Utils::toRawPointer<QList>(d->m_cmakeTools);
}
-Id CMakeToolManager::registerOrFindCMakeTool(const FileName &command)
+Id CMakeToolManager::registerOrFindCMakeTool(const FilePath &command)
{
if (CMakeTool *cmake = findByCommand(command))
return cmake->id();
@@ -149,7 +149,7 @@ void CMakeToolManager::setDefaultCMakeTool(const Id &id)
ensureDefaultCMakeToolIsValid();
}
-CMakeTool *CMakeToolManager::findByCommand(const FileName &command)
+CMakeTool *CMakeToolManager::findByCommand(const FilePath &command)
{
return Utils::findOrDefault(d->m_cmakeTools, Utils::equal(&CMakeTool::cmakeExecutable, command));
}
diff --git a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h
index bd7f232553..49308e616b 100644
--- a/src/plugins/cmakeprojectmanager/cmaketoolmanager.h
+++ b/src/plugins/cmakeprojectmanager/cmaketoolmanager.h
@@ -40,20 +40,20 @@ class CMAKE_EXPORT CMakeToolManager : public QObject
{
Q_OBJECT
public:
- CMakeToolManager(QObject *parent);
+ CMakeToolManager();
~CMakeToolManager() override;
static CMakeToolManager *instance();
static QList<CMakeTool *> cmakeTools();
- static Core::Id registerOrFindCMakeTool(const Utils::FileName &command);
+ static Core::Id registerOrFindCMakeTool(const Utils::FilePath &command);
static bool registerCMakeTool(std::unique_ptr<CMakeTool> &&tool);
static void deregisterCMakeTool(const Core::Id &id);
static CMakeTool *defaultCMakeTool();
static void setDefaultCMakeTool(const Core::Id &id);
- static CMakeTool *findByCommand(const Utils::FileName &command);
+ static CMakeTool *findByCommand(const Utils::FilePath &command);
static CMakeTool *findById(const Core::Id &id);
static void notifyAboutUpdate(CMakeTool *);
diff --git a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp
index 2f2d40b91d..a34f463318 100644
--- a/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketoolsettingsaccessor.cpp
@@ -72,30 +72,30 @@ static std::vector<std::unique_ptr<CMakeTool>> autoDetectCMakeTools()
{
Utils::Environment env = Environment::systemEnvironment();
- Utils::FileNameList path = env.path();
+ Utils::FilePathList path = env.path();
path = Utils::filteredUnique(path);
if (HostOsInfo::isWindowsHost()) {
const QString progFiles = QLatin1String(qgetenv("ProgramFiles"));
- path.append(Utils::FileName::fromString(progFiles + "/CMake"));
- path.append(Utils::FileName::fromString(progFiles + "/CMake/bin"));
+ path.append(Utils::FilePath::fromString(progFiles + "/CMake"));
+ path.append(Utils::FilePath::fromString(progFiles + "/CMake/bin"));
const QString progFilesX86 = QLatin1String(qgetenv("ProgramFiles(x86)"));
if (!progFilesX86.isEmpty()) {
- path.append(Utils::FileName::fromString(progFilesX86 + "/CMake"));
- path.append(Utils::FileName::fromString(progFilesX86 + "/CMake/bin"));
+ path.append(Utils::FilePath::fromString(progFilesX86 + "/CMake"));
+ path.append(Utils::FilePath::fromString(progFilesX86 + "/CMake/bin"));
}
}
if (HostOsInfo::isMacHost()) {
- path.append(Utils::FileName::fromString("/Applications/CMake.app/Contents/bin"));
- path.append(Utils::FileName::fromString("/usr/local/bin"));
- path.append(Utils::FileName::fromString("/opt/local/bin"));
+ path.append(Utils::FilePath::fromString("/Applications/CMake.app/Contents/bin"));
+ path.append(Utils::FilePath::fromString("/usr/local/bin"));
+ path.append(Utils::FilePath::fromString("/opt/local/bin"));
}
const QStringList execs = env.appendExeExtensions(QLatin1String("cmake"));
- FileNameList suspects;
- foreach (const Utils::FileName &base, path) {
+ FilePathList suspects;
+ foreach (const Utils::FilePath &base, path) {
if (base.isEmpty())
continue;
@@ -103,12 +103,12 @@ static std::vector<std::unique_ptr<CMakeTool>> autoDetectCMakeTools()
for (const QString &exec : execs) {
fi.setFile(QDir(base.toString()), exec);
if (fi.exists() && fi.isFile() && fi.isExecutable())
- suspects << FileName::fromString(fi.absoluteFilePath());
+ suspects << FilePath::fromString(fi.absoluteFilePath());
}
}
std::vector<std::unique_ptr<CMakeTool>> found;
- foreach (const FileName &command, suspects) {
+ foreach (const FilePath &command, suspects) {
auto item = std::make_unique<CMakeTool>(CMakeTool::AutoDetection, CMakeTool::createId());
item->setCMakeExecutable(command);
item->setDisplayName(CMakeToolManager::tr("System CMake at %1").arg(command.toUserOutput()));
@@ -166,7 +166,7 @@ CMakeToolSettingsAccessor::CMakeToolSettingsAccessor() :
QCoreApplication::translate("CMakeProjectManager::CMakeToolManager", "CMake"),
Core::Constants::IDE_DISPLAY_NAME)
{
- setBaseFilePath(FileName::fromString(Core::ICore::userResourcePath() + CMAKE_TOOL_FILENAME));
+ setBaseFilePath(FilePath::fromString(Core::ICore::userResourcePath() + CMAKE_TOOL_FILENAME));
addVersionUpgrader(std::make_unique<CMakeToolSettingsUpgraderV0>());
}
@@ -175,7 +175,7 @@ CMakeToolSettingsAccessor::CMakeTools CMakeToolSettingsAccessor::restoreCMakeToo
{
CMakeTools result;
- const FileName sdkSettingsFile = FileName::fromString(Core::ICore::installerResourcePath()
+ const FilePath sdkSettingsFile = FilePath::fromString(Core::ICore::installerResourcePath()
+ CMAKE_TOOL_FILENAME);
CMakeTools sdkTools = cmakeTools(restoreSettings(sdkSettingsFile, parent), true);
diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
index 90a3c40f24..588855d345 100644
--- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
+++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
@@ -28,7 +28,7 @@
namespace CMakeProjectManager {
-ConfigModelItemDelegate::ConfigModelItemDelegate(const Utils::FileName &base, QObject* parent)
+ConfigModelItemDelegate::ConfigModelItemDelegate(const Utils::FilePath &base, QObject* parent)
: QStyledItemDelegate(parent)
, m_base(base)
{ }
@@ -78,7 +78,7 @@ void ConfigModelItemDelegate::setEditorData(QWidget *editor, const QModelIndex &
ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
auto edit = static_cast<Utils::PathChooser *>(editor);
- edit->setFileName(Utils::FileName::fromUserInput(data.value));
+ edit->setFileName(Utils::FilePath::fromUserInput(data.value));
return;
} else if (!data.values.isEmpty()) {
auto edit = static_cast<QComboBox *>(editor);
diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h
index ce5571b6be..d33fb48c7a 100644
--- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h
+++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h
@@ -30,7 +30,7 @@ class ConfigModelItemDelegate : public QStyledItemDelegate
Q_OBJECT
public:
- ConfigModelItemDelegate(const Utils::FileName &base, QObject *parent = nullptr);
+ ConfigModelItemDelegate(const Utils::FilePath &base, QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const final;
@@ -40,7 +40,7 @@ public:
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const final;
private:
- Utils::FileName m_base;
+ Utils::FilePath m_base;
QComboBox m_measurement;
};
diff --git a/src/plugins/cmakeprojectmanager/servermode.cpp b/src/plugins/cmakeprojectmanager/servermode.cpp
index 8e21749927..bd37c4f6fe 100644
--- a/src/plugins/cmakeprojectmanager/servermode.cpp
+++ b/src/plugins/cmakeprojectmanager/servermode.cpp
@@ -78,8 +78,8 @@ bool isValid(const QVariant &v)
ServerMode::ServerMode(const Environment &env,
- const FileName &sourceDirectory, const FileName &buildDirectory,
- const FileName &cmakeExecutable,
+ const FilePath &sourceDirectory, const FilePath &buildDirectory,
+ const FilePath &cmakeExecutable,
const QString &generator, const QString &extraGenerator,
const QString &platform, const QString &toolset,
bool experimental, int major, int minor,
@@ -92,7 +92,7 @@ ServerMode::ServerMode(const Environment &env,
m_socketDir("/tmp/cmake-"),
#endif
m_sourceDirectory(sourceDirectory), m_buildDirectory(buildDirectory),
- m_cmakeExecutable(cmakeExecutable),
+ m_cmakeCommand(cmakeExecutable, {}),
m_generator(generator), m_extraGenerator(extraGenerator),
m_platform(platform), m_toolset(toolset),
m_useExperimental(experimental), m_majorProtocol(major), m_minorProtocol(minor)
@@ -114,28 +114,24 @@ ServerMode::ServerMode(const Environment &env,
m_socketName = QString::fromLatin1("\\\\.\\pipe\\") + QUuid::createUuid().toString();
#endif
- const QStringList args = QStringList({"-E", "server", "--pipe=" + m_socketName});
-
connect(m_cmakeProcess.get(), &QtcProcess::started, this, [this]() { m_connectionTimer.start(); });
connect(m_cmakeProcess.get(),
- static_cast<void(QtcProcess::*)(int, QProcess::ExitStatus)>(&QtcProcess::finished),
+ QOverload<int, QProcess::ExitStatus>::of(&QtcProcess::finished),
this, &ServerMode::handleCMakeFinished);
- QString argumentString;
- QtcProcess::addArgs(&argumentString, args);
+ m_cmakeCommand.addArgs({"-E", "server", "--pipe=" + m_socketName});
if (m_useExperimental)
- QtcProcess::addArg(&argumentString, "--experimental");
+ m_cmakeCommand.addArg("--experimental");
qCInfo(cmakeServerMode)
- << "Preparing cmake:" << cmakeExecutable.toString() << argumentString
+ << "Preparing cmake:" << m_cmakeCommand.toUserOutput()
<< "in" << m_buildDirectory.toString();
- m_cmakeProcess->setCommand(cmakeExecutable.toString(), argumentString);
+ m_cmakeProcess->setCommand(m_cmakeCommand);
// Delay start:
- QTimer::singleShot(0, this, [argumentString, this] {
- emit message(tr("Running \"%1 %2\" in %3.")
- .arg(m_cmakeExecutable.toUserOutput())
- .arg(argumentString)
+ QTimer::singleShot(0, this, [this] {
+ emit message(tr("Running \"%1\" in %2.")
+ .arg(m_cmakeCommand.toUserOutput())
.arg(m_buildDirectory.toUserOutput()));
m_cmakeProcess->start();
@@ -199,7 +195,7 @@ void ServerMode::connectToServer()
m_cmakeProcess->disconnect();
qCInfo(cmakeServerMode) << "Timeout waiting for pipe" << m_socketName;
reportError(tr("Running \"%1\" failed: Timeout waiting for pipe \"%2\".")
- .arg(m_cmakeExecutable.toUserOutput())
+ .arg(m_cmakeCommand.toUserOutput())
.arg(m_socketName));
Core::Reaper::reap(m_cmakeProcess.release());
@@ -211,7 +207,7 @@ void ServerMode::connectToServer()
auto socket = new QLocalSocket(m_cmakeProcess.get());
connect(socket, &QLocalSocket::readyRead, this, &ServerMode::handleRawCMakeServerData);
- connect(socket, static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error),
+ connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
this, [this, socket]() {
reportError(socket->errorString());
m_cmakeSocket = nullptr;
@@ -236,14 +232,14 @@ void ServerMode::handleCMakeFinished(int code, QProcess::ExitStatus status)
qCInfo(cmakeServerMode) << "CMake has finished" << code << status;
QString msg;
if (status != QProcess::NormalExit)
- msg = tr("CMake process \"%1\" crashed.").arg(m_cmakeExecutable.toUserOutput());
+ msg = tr("CMake process \"%1\" crashed.").arg(m_cmakeCommand.toUserOutput());
else if (code != 0)
- msg = tr("CMake process \"%1\" quit with exit code %2.").arg(m_cmakeExecutable.toUserOutput()).arg(code);
+ msg = tr("CMake process \"%1\" quit with exit code %2.").arg(m_cmakeCommand.toUserOutput()).arg(code);
if (!msg.isEmpty()) {
reportError(msg);
} else {
- emit message(tr("CMake process \"%1\" quit normally.").arg(m_cmakeExecutable.toUserOutput()));
+ emit message(tr("CMake process \"%1\" quit normally.").arg(m_cmakeCommand.toUserOutput()));
}
if (m_cmakeSocket) {
diff --git a/src/plugins/cmakeprojectmanager/servermode.h b/src/plugins/cmakeprojectmanager/servermode.h
index e7b645623a..2a4ccbf232 100644
--- a/src/plugins/cmakeprojectmanager/servermode.h
+++ b/src/plugins/cmakeprojectmanager/servermode.h
@@ -47,8 +47,8 @@ class ServerMode : public QObject
public:
ServerMode(const Utils::Environment &env,
- const Utils::FileName &sourceDirectory, const Utils::FileName &buildDirectory,
- const Utils::FileName &cmakeExecutable,
+ const Utils::FilePath &sourceDirectory, const Utils::FilePath &buildDirectory,
+ const Utils::FilePath &cmakeExecutable,
const QString &generator, const QString &extraGenerator,
const QString &platform, const QString &toolset,
bool experimental, int major, int minor = -1,
@@ -92,9 +92,9 @@ private:
QLocalSocket *m_cmakeSocket = nullptr;
QTimer m_connectionTimer;
- Utils::FileName m_sourceDirectory;
- Utils::FileName m_buildDirectory;
- Utils::FileName m_cmakeExecutable;
+ Utils::FilePath m_sourceDirectory;
+ Utils::FilePath m_buildDirectory;
+ Utils::CommandLine m_cmakeCommand;
QByteArray m_buffer;
diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp
index 9b293d0ff8..a0a70a8d85 100644
--- a/src/plugins/cmakeprojectmanager/servermodereader.cpp
+++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp
@@ -85,7 +85,7 @@ ServerModeReader::ServerModeReader()
Task editable(t);
if (!editable.file.isEmpty()) {
QDir srcDir(m_parameters.sourceDirectory.toString());
- editable.file = FileName::fromString(srcDir.absoluteFilePath(editable.file.toString()));
+ editable.file = FilePath::fromString(srcDir.absoluteFilePath(editable.file.toString()));
}
TaskHub::addTask(editable);
});
@@ -228,7 +228,7 @@ QList<CMakeBuildTarget> ServerModeReader::takeBuildTargets()
const QList<CMakeBuildTarget> result = transform(m_targets, [](const Target *t) -> CMakeBuildTarget {
CMakeBuildTarget ct;
ct.title = t->name;
- ct.executable = t->artifacts.isEmpty() ? FileName() : t->artifacts.at(0);
+ ct.executable = t->artifacts.isEmpty() ? FilePath() : t->artifacts.at(0);
TargetType type = UtilityType;
if (t->type == "EXECUTABLE")
type = ExecutableType;
@@ -245,7 +245,7 @@ QList<CMakeBuildTarget> ServerModeReader::takeBuildTargets()
if (t->artifacts.isEmpty()) {
ct.workingDirectory = t->buildDirectory;
} else {
- ct.workingDirectory = Utils::FileName::fromString(t->artifacts.at(0).toFileInfo().absolutePath());
+ ct.workingDirectory = Utils::FilePath::fromString(t->artifacts.at(0).toFileInfo().absolutePath());
}
ct.sourceDirectory = t->sourceDirectory;
return ct;
@@ -261,7 +261,7 @@ CMakeConfig ServerModeReader::takeParsedConfiguration()
return config;
}
-static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, int priority,
+static void addCMakeVFolder(FolderNode *base, const Utils::FilePath &basePath, int priority,
const QString &displayName,
std::vector<std::unique_ptr<FileNode>> &&files)
{
@@ -269,7 +269,8 @@ static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, i
return;
FolderNode *folder = base;
if (!displayName.isEmpty()) {
- auto newFolder = std::make_unique<VirtualFolderNode>(basePath, priority);
+ auto newFolder = std::make_unique<VirtualFolderNode>(basePath);
+ newFolder->setPriority(priority);
newFolder->setDisplayName(displayName);
folder = newFolder.get();
base->addNode(std::move(newFolder));
@@ -280,7 +281,7 @@ static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, i
}
static std::vector<std::unique_ptr<FileNode>> &&
-removeKnownNodes(const QSet<Utils::FileName> &knownFiles,
+removeKnownNodes(const QSet<Utils::FilePath> &knownFiles,
std::vector<std::unique_ptr<FileNode>> &&files)
{
Utils::erase(files, [&knownFiles](const std::unique_ptr<FileNode> &n) {
@@ -290,15 +291,15 @@ removeKnownNodes(const QSet<Utils::FileName> &knownFiles,
}
static void addCMakeInputs(FolderNode *root,
- const Utils::FileName &sourceDir,
- const Utils::FileName &buildDir,
+ const Utils::FilePath &sourceDir,
+ const Utils::FilePath &buildDir,
std::vector<std::unique_ptr<FileNode>> &&sourceInputs,
std::vector<std::unique_ptr<FileNode>> &&buildInputs,
std::vector<std::unique_ptr<FileNode>> &&rootInputs)
{
std::unique_ptr<ProjectNode> cmakeVFolder = std::make_unique<CMakeInputsNode>(root->filePath());
- QSet<Utils::FileName> knownFiles;
+ QSet<Utils::FilePath> knownFiles;
root->forEachGenericNode([&knownFiles](const Node *n) {
if (n->listInProject())
knownFiles.insert(n->filePath());
@@ -308,7 +309,7 @@ static void addCMakeInputs(FolderNode *root,
addCMakeVFolder(cmakeVFolder.get(), buildDir, 100,
QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Build Directory>"),
removeKnownNodes(knownFiles, std::move(buildInputs)));
- addCMakeVFolder(cmakeVFolder.get(), Utils::FileName(), 10,
+ addCMakeVFolder(cmakeVFolder.get(), Utils::FilePath(), 10,
QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Other Locations>"),
removeKnownNodes(knownFiles, std::move(rootInputs)));
@@ -325,7 +326,7 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root,
std::vector<std::unique_ptr<FileNode>> cmakeLists;
for (std::unique_ptr<FileNode> &fn : m_cmakeInputsFileNodes) {
- const FileName path = fn->filePath();
+ const FilePath path = fn->filePath();
if (path.fileName().compare("CMakeLists.txt", HostOsInfo::fileNameCaseSensitivity()) == 0)
cmakeLists.emplace_back(std::move(fn));
else if (path.isChildOf(m_parameters.workDirectory))
@@ -343,7 +344,7 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root,
if (topLevel)
root->setDisplayName(topLevel->name);
- QHash<Utils::FileName, ProjectNode *> cmakeListsNodes
+ QHash<Utils::FilePath, ProjectNode *> cmakeListsNodes
= addCMakeLists(root, std::move(cmakeLists));
QList<FileNode *> knownHeaders;
addProjects(cmakeListsNodes, m_projects, knownHeaders);
@@ -368,7 +369,7 @@ CppTools::RawProjectParts ServerModeReader::createRawProjectParts() const
if (fg->macros.isEmpty()
&& fg->includePaths.isEmpty()
&& !fg->isGenerated
- && Utils::allOf(fg->sources, [](const Utils::FileName &source) {
+ && Utils::allOf(fg->sources, [](const Utils::FilePath &source) {
return Node::fileTypeForFileName(source) == FileType::Header;
})) {
qWarning() << "Not reporting all-header file group of target" << fg->target << "to code model.";
@@ -381,7 +382,7 @@ CppTools::RawProjectParts ServerModeReader::createRawProjectParts() const
CppTools::RawProjectPart rpp;
rpp.setProjectFileLocation(fg->target->sourceDirectory.toString() + "/CMakeLists.txt");
- rpp.setBuildSystemTarget(fg->target->name + QChar('\n') + fg->target->sourceDirectory.toString() + QChar('/'));
+ rpp.setBuildSystemTarget(CMakeTargetNode::generateId(fg->target->sourceDirectory, fg->target->name));
rpp.setDisplayName(fg->target->name + QString::number(counter));
rpp.setMacros(fg->macros);
rpp.setIncludePaths(includes);
@@ -394,7 +395,7 @@ CppTools::RawProjectParts ServerModeReader::createRawProjectParts() const
cxxProjectFlags.commandLineFlags = flags;
rpp.setFlagsForCxx(cxxProjectFlags);
- rpp.setFiles(transform(fg->sources, &FileName::toString));
+ rpp.setFiles(transform(fg->sources, &FilePath::toString));
const bool isExecutable = fg->target->type == "EXECUTABLE";
rpp.setBuildTargetType(isExecutable ? CppTools::ProjectPart::Executable
@@ -456,7 +457,7 @@ void ServerModeReader::handleReply(const QVariantMap &data, const QString &inRep
void ServerModeReader::handleError(const QString &message)
{
TaskHub::addTask(Task::Error, message, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
- Utils::FileName(), -1);
+ Utils::FilePath(), -1);
if (!m_delayedErrorMessage.isEmpty()) {
reportError();
return;
@@ -534,7 +535,7 @@ ServerModeReader::Project *ServerModeReader::extractProjectData(const QVariantMa
{
auto project = new Project;
project->name = data.value(NAME_KEY).toString();
- project->sourceDirectory = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
+ project->sourceDirectory = FilePath::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
const QVariantList targets = data.value("targets").toList();
for (const QVariant &t : targets) {
@@ -561,8 +562,8 @@ ServerModeReader::Target *ServerModeReader::extractTargetData(const QVariantMap
auto target = new Target;
target->project = p;
target->name = targetName;
- target->sourceDirectory = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
- target->buildDirectory = FileName::fromString(data.value("buildDirectory").toString());
+ target->sourceDirectory = FilePath::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
+ target->buildDirectory = FilePath::fromString(data.value("buildDirectory").toString());
target->crossReferences = extractCrossReferences(data.value("crossReferences").toMap());
@@ -570,7 +571,7 @@ ServerModeReader::Target *ServerModeReader::extractTargetData(const QVariantMap
target->type = data.value("type").toString();
const QStringList artifacts = data.value("artifacts").toStringList();
- target->artifacts = transform(artifacts, [&srcDir](const QString &a) { return FileName::fromString(srcDir.absoluteFilePath(a)); });
+ target->artifacts = transform(artifacts, [&srcDir](const QString &a) { return FilePath::fromString(srcDir.absoluteFilePath(a)); });
const QVariantList fileGroups = data.value("fileGroups").toList();
for (const QVariant &fg : fileGroups) {
@@ -598,14 +599,14 @@ ServerModeReader::FileGroup *ServerModeReader::extractFileGroupData(const QVaria
[](const QVariant &i) -> IncludePath* {
const QVariantMap iData = i.toMap();
auto result = new IncludePath;
- result->path = FileName::fromString(iData.value("path").toString());
+ result->path = FilePath::fromString(iData.value("path").toString());
result->isSystem = iData.value("isSystem", false).toBool();
return result;
});
fileGroup->isGenerated = data.value("isGenerated", false).toBool();
fileGroup->sources = transform(data.value(SOURCES_KEY).toStringList(),
[&srcDir](const QString &s) {
- return FileName::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s)));
+ return FilePath::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s)));
});
m_fileGroups.append(fileGroup);
@@ -680,7 +681,7 @@ QList<ServerModeReader::BacktraceItem *> ServerModeReader::extractBacktrace(cons
void ServerModeReader::extractCMakeInputsData(const QVariantMap &data)
{
- const FileName src = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
+ const FilePath src = FilePath::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
QTC_ASSERT(src == m_parameters.sourceDirectory, return);
QDir srcDir(src.toString());
@@ -691,18 +692,28 @@ void ServerModeReader::extractCMakeInputsData(const QVariantMap &data)
const QVariantMap &section = bf.toMap();
const QStringList sources = section.value(SOURCES_KEY).toStringList();
- const bool isTemporary = section.value("isTemporary").toBool();
- const bool isCMake = section.value("isCMake").toBool();
+ const bool isTemporary = section.value("isTemporary").toBool(); // generated file
+ const bool isCMake = section.value("isCMake").toBool(); // part of the cmake installation
for (const QString &s : sources) {
- const FileName sfn = FileName::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s)));
+ const FilePath sfn = FilePath::fromString(QDir::cleanPath(srcDir.absoluteFilePath(s)));
const int oldCount = m_cmakeFiles.count();
m_cmakeFiles.insert(sfn);
- if (oldCount < m_cmakeFiles.count() && (!isCMake || sfn.toString().endsWith("/CMakeLists.txt"))) {
- // Always include CMakeLists.txt files, even when cmake things these are part of its
- // stuff. This unbreaks cmake binaries running from their own build directory.
- m_cmakeInputsFileNodes.emplace_back(
- std::make_unique<FileNode>(sfn, FileType::Project, isTemporary));
+ if (oldCount < m_cmakeFiles.count()) {
+ const bool isCMakeListsFile = sfn.toString().endsWith("/CMakeLists.txt");
+
+ if (isCMake && !isCMakeListsFile)
+ // Skip files that cmake considers to be part of the installation -- but include
+ // CMakeLists.txt files. This unbreaks cmake binaries running from their own
+ // build directory.
+ continue;
+
+ auto node = std::make_unique<FileNode>(sfn, FileType::Project);
+ node->setIsGenerated(isTemporary && !isCMakeListsFile); // CMakeLists.txt are never
+ // generated, independent
+ // what cmake thinks:-)
+
+ m_cmakeInputsFileNodes.emplace_back(std::move(node));
}
}
}
@@ -770,24 +781,24 @@ void ServerModeReader::fixTarget(ServerModeReader::Target *target) const
}
}
-QHash<Utils::FileName, ProjectNode *>
+QHash<Utils::FilePath, ProjectNode *>
ServerModeReader::addCMakeLists(CMakeProjectNode *root,
std::vector<std::unique_ptr<FileNode>> &&cmakeLists)
{
- QHash<Utils::FileName, ProjectNode *> cmakeListsNodes;
+ QHash<Utils::FilePath, ProjectNode *> cmakeListsNodes;
cmakeListsNodes.insert(root->filePath(), root);
- const QSet<Utils::FileName> cmakeDirs
+ const QSet<Utils::FilePath> cmakeDirs
= Utils::transform<QSet>(cmakeLists, [](const std::unique_ptr<FileNode> &n) {
return n->filePath().parentDir();
});
- root->addNestedNodes(std::move(cmakeLists), Utils::FileName(),
- [&cmakeDirs, &cmakeListsNodes](const Utils::FileName &fp)
+ root->addNestedNodes(std::move(cmakeLists), Utils::FilePath(),
+ [&cmakeDirs, &cmakeListsNodes](const Utils::FilePath &fp)
-> std::unique_ptr<ProjectExplorer::FolderNode> {
if (cmakeDirs.contains(fp)) {
auto fn = std::make_unique<CMakeListsNode>(fp);
cmakeListsNodes.insert(fp, fn.get());
- return std::move(fn);
+ return fn;
}
return std::make_unique<FolderNode>(fp);
@@ -796,14 +807,13 @@ ServerModeReader::addCMakeLists(CMakeProjectNode *root,
return cmakeListsNodes;
}
-static void createProjectNode(const QHash<Utils::FileName, ProjectNode *> &cmakeListsNodes,
- const Utils::FileName &dir, const QString &displayName)
+static void createProjectNode(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNodes,
+ const Utils::FilePath &dir, const QString &displayName)
{
ProjectNode *cmln = cmakeListsNodes.value(dir);
QTC_ASSERT(cmln, qDebug() << dir.toUserOutput(); return);
- Utils::FileName projectName = dir;
- projectName.appendPath(".project::" + displayName);
+ const Utils::FilePath projectName = dir.pathAppended(".project::" + displayName);
ProjectNode *pn = cmln->projectNode(projectName);
if (!pn) {
@@ -814,7 +824,7 @@ static void createProjectNode(const QHash<Utils::FileName, ProjectNode *> &cmake
pn->setDisplayName(displayName);
}
-void ServerModeReader::addProjects(const QHash<Utils::FileName, ProjectNode *> &cmakeListsNodes,
+void ServerModeReader::addProjects(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNodes,
const QList<Project *> &projects,
QList<FileNode *> &knownHeaderNodes)
{
@@ -824,16 +834,16 @@ void ServerModeReader::addProjects(const QHash<Utils::FileName, ProjectNode *> &
}
}
-static CMakeTargetNode *createTargetNode(const QHash<Utils::FileName, ProjectNode *> &cmakeListsNodes,
- const Utils::FileName &dir, const QString &displayName)
+static CMakeTargetNode *createTargetNode(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNodes,
+ const Utils::FilePath &dir, const QString &displayName)
{
ProjectNode *cmln = cmakeListsNodes.value(dir);
QTC_ASSERT(cmln, return nullptr);
- QByteArray targetId = CMakeTargetNode::generateId(dir, displayName);
+ QString targetId = CMakeTargetNode::generateId(dir, displayName);
CMakeTargetNode *tn = static_cast<CMakeTargetNode *>(cmln->findNode([&targetId](const Node *n) {
- return n->id() == targetId;
+ return n->buildKey() == targetId;
}));
if (!tn) {
auto newNode = std::make_unique<CMakeTargetNode>(dir, displayName);
@@ -844,7 +854,7 @@ static CMakeTargetNode *createTargetNode(const QHash<Utils::FileName, ProjectNod
return tn;
}
-void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
+void ServerModeReader::addTargets(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
const QList<Target *> &targets,
QList<ProjectExplorer::FileNode *> &knownHeaderNodes)
{
@@ -852,15 +862,15 @@ void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer::
CMakeTargetNode *tNode = createTargetNode(cmakeListsNodes, t->sourceDirectory, t->name);
QTC_ASSERT(tNode, qDebug() << "No target node for" << t->sourceDirectory << t->name; continue);
tNode->setTargetInformation(t->artifacts, t->type);
+ tNode->setBuildDirectory(t->buildDirectory);
QList<FolderNode::LocationInfo> info;
// Set up a default target path:
- FileName targetPath = t->sourceDirectory;
- targetPath.appendPath("CMakeLists.txt");
+ FilePath targetPath = t->sourceDirectory.pathAppended("CMakeLists.txt");
for (CrossReference *cr : qAsConst(t->crossReferences)) {
BacktraceItem *bt = cr->backtrace.isEmpty() ? nullptr : cr->backtrace.at(0);
if (bt) {
const QString btName = bt->name.toLower();
- const FileName path = Utils::FileName::fromUserInput(bt->path);
+ const FilePath path = Utils::FilePath::fromUserInput(bt->path);
QString dn;
if (cr->type != CrossReference::TARGET) {
if (path == targetPath) {
@@ -887,29 +897,29 @@ void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer::
}
void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
- const Utils::FileName &sourceDirectory,
- const Utils::FileName &buildDirectory,
+ const Utils::FilePath &sourceDirectory,
+ const Utils::FilePath &buildDirectory,
const QList<ServerModeReader::FileGroup *> &fileGroups,
QList<FileNode *> &knownHeaderNodes)
{
std::vector<std::unique_ptr<FileNode>> toList;
- QSet<Utils::FileName> alreadyListed;
+ QSet<Utils::FilePath> alreadyListed;
// Files already added by other configurations:
targetRoot->forEachGenericNode([&alreadyListed](const Node *n) {
alreadyListed.insert(n->filePath());
});
for (const FileGroup *f : fileGroups) {
- const QList<FileName> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FileName &fn) {
+ const QList<FilePath> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FilePath &fn) {
const int count = alreadyListed.count();
alreadyListed.insert(fn);
return count != alreadyListed.count();
});
std::vector<std::unique_ptr<FileNode>> newFileNodes
= Utils::transform<std::vector>(newSources,
- [f, &knownHeaderNodes](const Utils::FileName &fn) {
- auto node
- = std::make_unique<FileNode>(fn, Node::fileTypeForFileName(fn), f->isGenerated);
+ [f, &knownHeaderNodes](const Utils::FilePath &fn) {
+ auto node = std::make_unique<FileNode>(fn, Node::fileTypeForFileName(fn));
+ node->setIsGenerated(f->isGenerated);
if (node->fileType() == FileType::Header)
knownHeaderNodes.append(node.get());
return node;
@@ -933,7 +943,7 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
addCMakeVFolder(targetRoot, sourceDirectory, 1000, QString(), std::move(sourceFileNodes));
addCMakeVFolder(targetRoot, buildDirectory, 100, tr("<Build Directory>"), std::move(buildFileNodes));
- addCMakeVFolder(targetRoot, Utils::FileName(), 10, tr("<Other Locations>"), std::move(otherFileNodes));
+ addCMakeVFolder(targetRoot, Utils::FilePath(), 10, tr("<Other Locations>"), std::move(otherFileNodes));
}
void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *> knownHeaders,
@@ -944,13 +954,13 @@ void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *>
static QIcon headerNodeIcon
= Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_H);
- auto headerNode
- = std::make_unique<VirtualFolderNode>(root->filePath(), Node::DefaultPriority - 5);
+ auto headerNode = std::make_unique<VirtualFolderNode>(root->filePath());
+ headerNode->setPriority(Node::DefaultPriority - 5);
headerNode->setDisplayName(tr("<Headers>"));
headerNode->setIcon(headerNodeIcon);
// knownHeaders are already listed in their targets:
- QSet<Utils::FileName> seenHeaders = Utils::transform<QSet>(knownHeaders, &FileNode::filePath);
+ QSet<Utils::FilePath> seenHeaders = Utils::transform<QSet>(knownHeaders, &FileNode::filePath);
// Add scanned headers:
for (const FileNode *fn : allFiles) {
diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h
index a8e998c68c..b362b15b3f 100644
--- a/src/plugins/cmakeprojectmanager/servermodereader.h
+++ b/src/plugins/cmakeprojectmanager/servermodereader.h
@@ -78,7 +78,7 @@ private:
struct Project;
struct IncludePath {
- Utils::FileName path;
+ Utils::FilePath path;
bool isSystem;
};
@@ -90,7 +90,7 @@ private:
ProjectExplorer::Macros macros;
QList<IncludePath *> includePaths;
QString language;
- QList<Utils::FileName> sources;
+ QList<Utils::FilePath> sources;
bool isGenerated;
};
@@ -118,9 +118,9 @@ private:
Project *project = nullptr;
QString name;
QString type;
- QList<Utils::FileName> artifacts;
- Utils::FileName sourceDirectory;
- Utils::FileName buildDirectory;
+ QList<Utils::FilePath> artifacts;
+ Utils::FilePath sourceDirectory;
+ Utils::FilePath buildDirectory;
QList<FileGroup *> fileGroups;
QList<CrossReference *> crossReferences;
};
@@ -128,7 +128,7 @@ private:
struct Project {
~Project() { qDeleteAll(targets); targets.clear(); }
QString name;
- Utils::FileName sourceDirectory;
+ Utils::FilePath sourceDirectory;
QList<Target *> targets;
};
@@ -145,17 +145,17 @@ private:
void fixTarget(Target *target) const;
- QHash<Utils::FileName, ProjectExplorer::ProjectNode *>
+ QHash<Utils::FilePath, ProjectExplorer::ProjectNode *>
addCMakeLists(CMakeProjectNode *root, std::vector<std::unique_ptr<ProjectExplorer::FileNode> > &&cmakeLists);
- void addProjects(const QHash<Utils::FileName, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
+ void addProjects(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
const QList<Project *> &projects,
QList<ProjectExplorer::FileNode *> &knownHeaderNodes);
- void addTargets(const QHash<Utils::FileName, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
+ void addTargets(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
const QList<Target *> &targets,
QList<ProjectExplorer::FileNode *> &knownHeaderNodes);
void addFileGroups(ProjectExplorer::ProjectNode *targetRoot,
- const Utils::FileName &sourceDirectory,
- const Utils::FileName &buildDirectory, const QList<FileGroup *> &fileGroups,
+ const Utils::FilePath &sourceDirectory,
+ const Utils::FilePath &buildDirectory, const QList<FileGroup *> &fileGroups,
QList<ProjectExplorer::FileNode *> &knowHeaderNodes);
void addHeaderNodes(ProjectExplorer::ProjectNode *root,
@@ -172,7 +172,7 @@ private:
CMakeConfig m_cmakeConfiguration;
- QSet<Utils::FileName> m_cmakeFiles;
+ QSet<Utils::FilePath> m_cmakeFiles;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_cmakeInputsFileNodes;
QList<Project *> m_projects;
diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp
index 320b470e45..d336d9e8cf 100644
--- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp
+++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp
@@ -70,7 +70,7 @@ namespace Internal {
class CMakeFile : public IDocument
{
public:
- CMakeFile(TeaLeafReader *r, const FileName &fileName);
+ CMakeFile(TeaLeafReader *r, const FilePath &fileName);
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override;
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
@@ -79,7 +79,7 @@ private:
TeaLeafReader *m_reader;
};
-CMakeFile::CMakeFile(TeaLeafReader *r, const FileName &fileName) : m_reader(r)
+CMakeFile::CMakeFile(TeaLeafReader *r, const FilePath &fileName) : m_reader(r)
{
setId("Cmake.ProjectFile");
setMimeType(Constants::CMAKEPROJECTMIMETYPE);
@@ -200,7 +200,7 @@ void TeaLeafReader::parse(bool forceConfiguration)
}
const bool mustUpdate = m_cmakeFiles.isEmpty()
- || anyOf(m_cmakeFiles, [&cbpFileFi](const FileName &f) {
+ || anyOf(m_cmakeFiles, [&cbpFileFi](const FilePath &f) {
return f.toFileInfo().lastModified() > cbpFileFi.lastModified();
});
if (mustUpdate) {
@@ -235,8 +235,7 @@ QList<CMakeBuildTarget> TeaLeafReader::takeBuildTargets()
CMakeConfig TeaLeafReader::takeParsedConfiguration()
{
- FileName cacheFile = m_parameters.workDirectory;
- cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
+ const FilePath cacheFile = m_parameters.workDirectory.pathAppended("CMakeCache.txt");
if (!cacheFile.exists())
return { };
@@ -249,10 +248,10 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
return { };
}
- const FileName sourceOfBuildDir
- = FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", result));
- const FileName canonicalSourceOfBuildDir = FileUtils::canonicalPath(sourceOfBuildDir);
- const FileName canonicalSourceDirectory = FileUtils::canonicalPath(m_parameters.sourceDirectory);
+ const FilePath sourceOfBuildDir
+ = FilePath::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", result));
+ const FilePath canonicalSourceOfBuildDir = sourceOfBuildDir.canonicalPath();
+ const FilePath canonicalSourceDirectory = m_parameters.sourceDirectory.canonicalPath();
if (canonicalSourceOfBuildDir != canonicalSourceDirectory) { // Uses case-insensitive compare where appropriate
emit errorOccured(tr("The build directory is not for %1 but for %2")
.arg(canonicalSourceOfBuildDir.toUserOutput(),
@@ -270,10 +269,10 @@ void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<cons
root->setDisplayName(m_projectName);
// Delete no longer necessary file watcher based on m_cmakeFiles:
- const QSet<FileName> currentWatched
+ const QSet<FilePath> currentWatched
= transform(m_watchedFiles, &CMakeFile::filePath);
- const QSet<FileName> toWatch = m_cmakeFiles;
- QSet<FileName> toDelete = currentWatched;
+ const QSet<FilePath> toWatch = m_cmakeFiles;
+ QSet<FilePath> toDelete = currentWatched;
toDelete.subtract(toWatch);
m_watchedFiles = filtered(m_watchedFiles, [&toDelete](Internal::CMakeFile *cmf) {
if (toDelete.contains(cmf->filePath())) {
@@ -284,30 +283,30 @@ void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<cons
});
// Add new file watchers:
- QSet<FileName> toAdd = toWatch;
+ QSet<FilePath> toAdd = toWatch;
toAdd.subtract(currentWatched);
- foreach (const FileName &fn, toAdd) {
+ foreach (const FilePath &fn, toAdd) {
auto cm = new CMakeFile(this, fn);
DocumentManager::addDocument(cm);
m_watchedFiles.insert(cm);
}
- QSet<FileName> allIncludePathSet;
+ QSet<FilePath> allIncludePathSet;
for (const CMakeBuildTarget &bt : m_buildTargets) {
- const QList<Utils::FileName> targetIncludePaths
- = Utils::filtered(bt.includeFiles, [this](const Utils::FileName &fn) {
+ const QList<Utils::FilePath> targetIncludePaths
+ = Utils::filtered(bt.includeFiles, [this](const Utils::FilePath &fn) {
return fn.isChildOf(m_parameters.sourceDirectory);
});
- allIncludePathSet.unite(QSet<FileName>::fromList(targetIncludePaths));
+ allIncludePathSet.unite(QSet<FilePath>::fromList(targetIncludePaths));
}
- const QList<FileName> allIncludePaths = allIncludePathSet.toList();
+ const QList<FilePath> allIncludePaths = allIncludePathSet.toList();
const QList<const FileNode *> missingHeaders
= Utils::filtered(allFiles, [&allIncludePaths](const FileNode *fn) -> bool {
if (fn->fileType() != FileType::Header)
return false;
- return Utils::contains(allIncludePaths, [fn](const FileName &inc) { return fn->filePath().isChildOf(inc); });
+ return Utils::contains(allIncludePaths, [fn](const FilePath &inc) { return fn->filePath().isChildOf(inc); });
});
// filter duplicates:
@@ -328,15 +327,15 @@ void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<cons
}
static void processCMakeIncludes(const CMakeBuildTarget &cbt, const ToolChain *tc,
- const QStringList& flags, const FileName &sysroot,
- QSet<FileName> &tcIncludes, QStringList &includePaths)
+ const QStringList& flags, const FilePath &sysroot,
+ QSet<FilePath> &tcIncludes, QStringList &includePaths)
{
if (!tc)
return;
foreach (const HeaderPath &hp, tc->builtInHeaderPaths(flags, sysroot))
- tcIncludes.insert(FileName::fromString(hp.path));
- foreach (const FileName &i, cbt.includeFiles) {
+ tcIncludes.insert(FilePath::fromString(hp.path));
+ foreach (const FilePath &i, cbt.includeFiles) {
if (!tcIncludes.contains(i))
includePaths.append(i.toString());
}
@@ -346,7 +345,7 @@ CppTools::RawProjectParts TeaLeafReader::createRawProjectParts() const
{
const ToolChain *tcCxx = ToolChainManager::findToolChain(m_parameters.cxxToolChainId);
const ToolChain *tcC = ToolChainManager::findToolChain(m_parameters.cToolChainId);
- const FileName sysroot = m_parameters.sysRoot;
+ const FilePath sysroot = m_parameters.sysRoot;
CppTools::RawProjectParts rpps;
QHash<QString, QStringList> targetDataCacheCxx;
@@ -360,18 +359,18 @@ CppTools::RawProjectParts TeaLeafReader::createRawProjectParts() const
// place.
auto cxxflags = getFlagsFor(cbt, targetDataCacheCxx, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
auto cflags = getFlagsFor(cbt, targetDataCacheC, ProjectExplorer::Constants::C_LANGUAGE_ID);
- QSet<FileName> tcIncludes;
+ QSet<FilePath> tcIncludes;
QStringList includePaths;
if (tcCxx || tcC) {
processCMakeIncludes(cbt, tcCxx, cxxflags, sysroot, tcIncludes, includePaths);
processCMakeIncludes(cbt, tcC, cflags, sysroot, tcIncludes, includePaths);
} else {
- includePaths = transform(cbt.includeFiles, &FileName::toString);
+ includePaths = transform(cbt.includeFiles, &FilePath::toString);
}
includePaths += m_parameters.workDirectory.toString();
CppTools::RawProjectPart rpp;
rpp.setProjectFileLocation(cbt.sourceDirectory.toString() + "/CMakeLists.txt");
- rpp.setBuildSystemTarget(cbt.title + QChar('\n') + cbt.sourceDirectory.toString() + QChar('/'));
+ rpp.setBuildSystemTarget(CMakeTargetNode::generateId(cbt.sourceDirectory, cbt.title));
rpp.setIncludePaths(includePaths);
CppTools::RawProjectPartFlags cProjectFlags;
@@ -384,7 +383,7 @@ CppTools::RawProjectParts TeaLeafReader::createRawProjectParts() const
rpp.setMacros(cbt.macros);
rpp.setDisplayName(cbt.title);
- rpp.setFiles(transform(cbt.files, &FileName::toString));
+ rpp.setFiles(transform(cbt.files, &FilePath::toString));
const bool isExecutable = cbt.targetType == ExecutableType;
rpp.setBuildTargetType(isExecutable ? CppTools::ProjectPart::Executable
@@ -415,26 +414,25 @@ void TeaLeafReader::extractData()
CMakeTool *cmake = m_parameters.cmakeTool();
QTC_ASSERT(m_parameters.isValid() && cmake, return);
- const FileName srcDir = m_parameters.sourceDirectory;
- const FileName bldDir = m_parameters.workDirectory;
- const FileName topCMake = Utils::FileName(srcDir).appendPath("CMakeLists.txt");
+ const FilePath srcDir = m_parameters.sourceDirectory;
+ const FilePath bldDir = m_parameters.workDirectory;
+ const FilePath topCMake = srcDir.pathAppended("CMakeLists.txt");
resetData();
m_projectName = m_parameters.projectName;
- m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project, false));
+ m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project));
// Do not insert topCMake into m_cmakeFiles: The project already watches that!
// Find cbp file
- FileName cbpFile = FileName::fromString(findCbpFile(bldDir.toString()));
+ FilePath cbpFile = FilePath::fromString(findCbpFile(bldDir.toString()));
if (cbpFile.isEmpty())
return;
m_cmakeFiles.insert(cbpFile);
// Add CMakeCache.txt file:
- FileName cacheFile = m_parameters.workDirectory;
- cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
- if (cacheFile.toFileInfo().exists())
+ const FilePath cacheFile = m_parameters.workDirectory.pathAppended("CMakeCache.txt");
+ if (cacheFile.exists())
m_cmakeFiles.insert(cacheFile);
// setFolderName
@@ -458,7 +456,7 @@ void TeaLeafReader::extractData()
if (!contains(m_files, [topCMake](const std::unique_ptr<FileNode> &fn) {
return fn->filePath() == topCMake;
}))
- m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project, false));
+ m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project));
m_buildTargets = cbpparser.buildTargets();
}
@@ -468,7 +466,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
CMakeTool *cmake = m_parameters.cmakeTool();
QTC_ASSERT(m_parameters.isValid() && cmake, return);
- const FileName workDirectory = m_parameters.workDirectory;
+ const FilePath workDirectory = m_parameters.workDirectory;
QTC_ASSERT(!m_cmakeProcess, return);
QTC_ASSERT(!m_parser, return);
QTC_ASSERT(!m_future, return);
@@ -484,7 +482,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
TaskHub::addTask(task);
} else {
Task t = task;
- t.file = FileName::fromString(source.absoluteFilePath(task.file.toString()));
+ t.file = FilePath::fromString(source.absoluteFilePath(task.file.toString()));
TaskHub::addTask(t);
}
});
@@ -500,7 +498,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
this, &TeaLeafReader::processCMakeOutput);
connect(m_cmakeProcess, &QProcess::readyReadStandardError,
this, &TeaLeafReader::processCMakeError);
- connect(m_cmakeProcess, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_cmakeProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &TeaLeafReader::cmakeFinished);
QString args;
@@ -521,7 +519,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
tr("Configuring \"%1\"").arg(m_parameters.projectName),
"CMake.Configure");
- m_cmakeProcess->setCommand(cmake->cmakeExecutable().toString(), args);
+ m_cmakeProcess->setCommand(CommandLine(cmake->cmakeExecutable(), args));
emit configurationStarted();
m_cmakeProcess->start();
}
diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.h b/src/plugins/cmakeprojectmanager/tealeafreader.h
index 142ea4b5af..356adc8110 100644
--- a/src/plugins/cmakeprojectmanager/tealeafreader.h
+++ b/src/plugins/cmakeprojectmanager/tealeafreader.h
@@ -79,7 +79,7 @@ private:
ProjectExplorer::IOutputParser *m_parser = nullptr;
QFutureInterface<void> *m_future = nullptr;
- QSet<Utils::FileName> m_cmakeFiles;
+ QSet<Utils::FilePath> m_cmakeFiles;
QString m_projectName;
QList<CMakeBuildTarget> m_buildTargets;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_files;
diff --git a/src/plugins/cmakeprojectmanager/treescanner.cpp b/src/plugins/cmakeprojectmanager/treescanner.cpp
deleted file mode 100644
index 7a25e9e266..0000000000
--- a/src/plugins/cmakeprojectmanager/treescanner.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Alexander Drozdov.
-** Contact: Alexander Drozdov (adrozdoff@gmail.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 "treescanner.h"
-
-#include <coreplugin/iversioncontrol.h>
-#include <coreplugin/vcsmanager.h>
-#include <projectexplorer/projectexplorerconstants.h>
-
-#include <cpptools/cpptoolsconstants.h>
-
-#include <utils/qtcassert.h>
-#include <utils/algorithm.h>
-#include <utils/runextensions.h>
-
-#include <memory>
-
-using namespace ProjectExplorer;
-
-namespace CMakeProjectManager {
-namespace Internal {
-
-TreeScanner::TreeScanner(QObject *parent) : QObject(parent)
-{
- m_factory = TreeScanner::genericFileType;
- m_filter = [](const Utils::MimeType &mimeType, const Utils::FileName &fn) {
- return isWellKnownBinary(mimeType, fn) && isMimeBinary(mimeType, fn);
- };
-
- connect(&m_futureWatcher, &FutureWatcher::finished, this, &TreeScanner::finished);
-}
-
-TreeScanner::~TreeScanner()
-{
- if (!m_futureWatcher.isFinished()) {
- m_futureWatcher.cancel();
- m_futureWatcher.waitForFinished();
- }
-}
-
-bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory)
-{
- if (!m_futureWatcher.isFinished())
- return false;
-
- auto fi = new FutureInterface();
- m_scanFuture = fi->future();
- m_futureWatcher.setFuture(m_scanFuture);
-
- Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); });
-
- return true;
-}
-
-void TreeScanner::setFilter(TreeScanner::FileFilter filter)
-{
- if (isFinished())
- m_filter = filter;
-}
-
-void TreeScanner::setTypeFactory(TreeScanner::FileTypeFactory factory)
-{
- if (isFinished())
- m_factory = factory;
-}
-
-TreeScanner::Future TreeScanner::future() const
-{
- return m_scanFuture;
-}
-
-bool TreeScanner::isFinished() const
-{
- return m_futureWatcher.isFinished();
-}
-
-TreeScanner::Result TreeScanner::result() const
-{
- if (isFinished())
- return m_scanFuture.result();
- return Result();
-}
-
-TreeScanner::Result TreeScanner::release()
-{
- if (isFinished()) {
- auto result = m_scanFuture.result();
- m_scanFuture = Future();
- return result;
- }
- return Result();
-}
-
-void TreeScanner::reset()
-{
- if (isFinished())
- m_scanFuture = Future();
-}
-
-bool TreeScanner::isWellKnownBinary(const Utils::MimeType & /*mdb*/, const Utils::FileName &fn)
-{
- return fn.endsWith(QLatin1String(".a")) ||
- fn.endsWith(QLatin1String(".o")) ||
- fn.endsWith(QLatin1String(".d")) ||
- fn.endsWith(QLatin1String(".exe")) ||
- fn.endsWith(QLatin1String(".dll")) ||
- fn.endsWith(QLatin1String(".obj")) ||
- fn.endsWith(QLatin1String(".elf"));
-}
-
-bool TreeScanner::isMimeBinary(const Utils::MimeType &mimeType, const Utils::FileName &/*fn*/)
-{
- bool isBinary = false;
- if (mimeType.isValid()) {
- QStringList mimes;
- mimes << mimeType.name() << mimeType.allAncestors();
- isBinary = !mimes.contains(QLatin1String("text/plain"));
- }
- return isBinary;
-}
-
-FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Utils::FileName &/*fn*/)
-{
- return Node::fileTypeForMimeType(mimeType);
-}
-
-void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory,
- const FileFilter &filter, const FileTypeFactory &factory)
-{
- std::unique_ptr<FutureInterface> fip(fi);
- fip->reportStarted();
-
- Result nodes = FileNode::scanForFiles(
- directory,
- [&filter, &factory](const Utils::FileName &fn) -> FileNode * {
- const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString());
-
- // Skip some files during scan.
- if (filter && filter(mimeType, fn))
- return nullptr;
-
- // Type detection
- FileType type = FileType::Unknown;
- if (factory)
- type = factory(mimeType, fn);
-
- return new FileNode(fn, type, false);
- }, fip.get());
-
- Utils::sort(nodes, ProjectExplorer::Node::sortByPath);
-
- fip->setProgressValue(fip->progressMaximum());
- fip->reportResult(nodes);
- fip->reportFinished();
-}
-
-} // namespace Internal
-} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/treescanner.h b/src/plugins/cmakeprojectmanager/treescanner.h
deleted file mode 100644
index bf9872f6df..0000000000
--- a/src/plugins/cmakeprojectmanager/treescanner.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Alexander Drozdov.
-** Contact: Alexander Drozdov (adrozdoff@gmail.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 "projectexplorer/projectnodes.h"
-
-#include <utils/mimetypes/mimedatabase.h>
-#include <utils/fileutils.h>
-
-#include <QObject>
-#include <QFuture>
-#include <QFutureWatcher>
-
-#include <functional>
-
-namespace Core { class IVersionControl; }
-
-namespace CMakeProjectManager {
-namespace Internal {
-
-class TreeScanner : public QObject
-{
- Q_OBJECT
-
-public:
- using Result = QList<ProjectExplorer::FileNode *>;
- using Future = QFuture<Result>;
- using FutureWatcher = QFutureWatcher<Result>;
- using FutureInterface = QFutureInterface<Result>;
-
- using FileFilter = std::function<bool(const Utils::MimeType &, const Utils::FileName &)>;
- using FileTypeFactory = std::function<ProjectExplorer::FileType(const Utils::MimeType &, const Utils::FileName &)>;
-
- explicit TreeScanner(QObject *parent = nullptr);
- ~TreeScanner() override;
-
- // Start scanning in given directory
- bool asyncScanForFiles(const Utils::FileName& directory);
-
- // Setup filter for ignored files
- void setFilter(FileFilter filter);
-
- // Setup factory for file types
- void setTypeFactory(FileTypeFactory factory);
-
- Future future() const;
- bool isFinished() const;
-
- // Takes not-owning result
- Result result() const;
- // Takes owning of result
- Result release();
- // Clear scan results
- void reset();
-
- // Standard filters helpers
- static bool isWellKnownBinary(const Utils::MimeType &mimeType, const Utils::FileName &fn);
- static bool isMimeBinary(const Utils::MimeType &mimeType, const Utils::FileName &fn);
-
- // Standard file factory
- static ProjectExplorer::FileType genericFileType(const Utils::MimeType &mdb, const Utils::FileName& fn);
-
-signals:
- void finished();
-
-private:
- static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory,
- const FileFilter &filter, const FileTypeFactory &factory);
-
-private:
- FileFilter m_filter;
- FileTypeFactory m_factory;
-
- FutureWatcher m_futureWatcher;
- Future m_scanFuture;
-};
-
-} // namespace Internal
-} // namespace CMakeProjectManager
-
-
diff --git a/src/plugins/compilationdatabaseprojectmanager/CMakeLists.txt b/src/plugins/compilationdatabaseprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..163342854f
--- /dev/null
+++ b/src/plugins/compilationdatabaseprojectmanager/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_qtc_plugin(CompilationDatabaseProjectManager
+ DEPENDS Utils
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer TextEditor
+ SOURCES
+ compilationdatabaseconstants.h
+ compilationdatabaseproject.cpp compilationdatabaseproject.h
+ compilationdatabaseprojectmanagerplugin.cpp compilationdatabaseprojectmanagerplugin.h
+ compilationdatabasetests.qrc
+ compilationdatabaseutils.cpp compilationdatabaseutils.h
+ compilationdbparser.cpp compilationdbparser.h
+)
+
+extend_qtc_plugin(CompilationDatabaseProjectManager
+ CONDITION WITH_TESTS
+ SOURCES compilationdatabasetests.cpp compilationdatabasetests.h
+)
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseconstants.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseconstants.h
index 1cb47d5dfd..4fab0e4980 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseconstants.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseconstants.h
@@ -30,6 +30,7 @@ namespace Constants {
const char COMPILATIONDATABASEMIMETYPE[] = "text/x-compilation-database-project";
const char COMPILATIONDATABASEPROJECT_ID[] = "CompilationDatabase.CompilationDatabaseEditor";
+const char COMPILATIONDATABASEPROJECT_FILES_SUFFIX[] = ".files";
} // Constants
} // CompilationDatabaseProjectManager
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
index 9909b22d94..94bc8b40a7 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp
@@ -26,16 +26,21 @@
#include "compilationdatabaseproject.h"
#include "compilationdatabaseconstants.h"
-#include "compilationdatabaseutils.h"
+#include "compilationdbparser.h"
#include <coreplugin/icontext.h>
-#include <cpptools/projectinfo.h>
#include <cpptools/cppkitinfo.h>
#include <cpptools/cppprojectupdater.h>
+#include <cpptools/projectinfo.h>
+#include <projectexplorer/buildinfo.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/gcctoolchain.h>
#include <projectexplorer/headerpath.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/namedwidget.h>
+#include <projectexplorer/processstep.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/target.h>
@@ -47,9 +52,8 @@
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
-#include <QJsonArray>
-#include <QJsonDocument>
-#include <QJsonObject>
+#include <QFileDialog>
+#include <QTimer>
#ifdef Q_OS_WIN
#include <Windows.h>
@@ -61,32 +65,17 @@ namespace CompilationDatabaseProjectManager {
namespace Internal {
namespace {
-class DBProjectNode : public ProjectNode
-{
-public:
- explicit DBProjectNode(const Utils::FileName &projectFilePath)
- : ProjectNode(projectFilePath)
- {}
-};
-QStringList jsonObjectFlags(const QJsonObject &object)
-{
- QStringList flags;
- const QJsonArray arguments = object["arguments"].toArray();
- if (arguments.isEmpty()) {
- flags = splitCommandLine(object["command"].toString());
- } else {
- flags.reserve(arguments.size());
- for (const QJsonValue &arg : arguments)
- flags.append(arg.toString());
- }
- return flags;
+bool isGccCompiler(const QString &compilerName)
+{
+ return compilerName.contains("gcc")
+ || (compilerName.contains("g++") && !compilerName.contains("clang"));
}
-bool isGccCompiler(const QString &compilerName)
+bool isClCompatibleCompiler(const QString &compilerName)
{
- return compilerName.contains("gcc") || compilerName.contains("g++");
+ return compilerName.endsWith("cl");
}
Core::Id getCompilerId(QString compilerName)
@@ -96,9 +85,9 @@ Core::Id getCompilerId(QString compilerName)
compilerName.chop(4);
if (isGccCompiler(compilerName))
return ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID;
-
- // Default is clang-cl
- return ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID;
+ if (isClCompatibleCompiler(compilerName))
+ return ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID;
+ return ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID;
}
if (isGccCompiler(compilerName))
return ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
@@ -122,11 +111,17 @@ QString compilerPath(QString pathFlag)
return pathFlag;
#ifdef Q_OS_WIN
// Handle short DOS style file names (cmake can generate them).
- const DWORD pathLength = GetLongPathNameW((LPCWSTR)pathFlag.utf16(), 0, 0);
- wchar_t* buffer = new wchar_t[pathLength];
- GetLongPathNameW((LPCWSTR)pathFlag.utf16(), buffer, pathLength);
- pathFlag = QString::fromUtf16((ushort *)buffer, pathLength - 1);
- delete[] buffer;
+ const DWORD pathLength = GetLongPathNameW(reinterpret_cast<LPCWSTR>(pathFlag.utf16()),
+ nullptr,
+ 0);
+ if (pathLength > 0) {
+ // Works only with existing paths.
+ wchar_t *buffer = new wchar_t[pathLength];
+ GetLongPathNameW(reinterpret_cast<LPCWSTR>(pathFlag.utf16()), buffer, pathLength);
+ pathFlag = QString::fromUtf16(reinterpret_cast<ushort *>(buffer),
+ static_cast<int>(pathLength - 1));
+ delete[] buffer;
+ }
#endif
return QDir::fromNativeSeparators(pathFlag);
}
@@ -134,10 +129,10 @@ QString compilerPath(QString pathFlag)
ToolChain *toolchainFromFlags(const Kit *kit, const QStringList &flags, const Core::Id &language)
{
if (flags.empty())
- return ToolChainKitInformation::toolChain(kit, language);
+ return ToolChainKitAspect::toolChain(kit, language);
// Try exact compiler match.
- const Utils::FileName compiler = Utils::FileName::fromString(compilerPath(flags.front()));
+ const Utils::FilePath compiler = Utils::FilePath::fromString(compilerPath(flags.front()));
ToolChain *toolchain = ToolChainManager::toolChain([&compiler, &language](const ToolChain *tc) {
return tc->isValid() && tc->language() == language && tc->compilerCommand() == compiler;
});
@@ -157,38 +152,27 @@ ToolChain *toolchainFromFlags(const Kit *kit, const QStringList &flags, const Co
return toolchain;
}
- toolchain = ToolChainKitInformation::toolChain(kit, language);
+ toolchain = ToolChainKitAspect::toolChain(kit, language);
qWarning() << "No matching toolchain found, use the default.";
return toolchain;
}
-Utils::FileName jsonObjectFilename(const QJsonObject &object)
-{
- const QString workingDir = QDir::fromNativeSeparators(object["directory"].toString());
- Utils::FileName fileName = Utils::FileName::fromString(
- QDir::fromNativeSeparators(object["file"].toString()));
- if (fileName.toFileInfo().isRelative()) {
- fileName = Utils::FileUtils::canonicalPath(
- Utils::FileName::fromString(workingDir + "/" + fileName.toString()));
- }
- return fileName;
-}
-
-void addDriverModeFlagIfNeeded(const ToolChain *toolchain, QStringList &flags)
+void addDriverModeFlagIfNeeded(const ToolChain *toolchain,
+ QStringList &flags,
+ const QStringList &originalFlags)
{
if (toolchain->typeId() == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID
- && !flags.empty() && !flags.front().endsWith("cl")
- && !flags.front().endsWith("cl.exe")) {
+ && !originalFlags.empty() && !originalFlags.front().endsWith("cl")
+ && !originalFlags.front().endsWith("cl.exe")) {
flags.prepend("--driver-mode=g++");
}
}
-CppTools::RawProjectPart makeRawProjectPart(const Utils::FileName &projectFile,
+CppTools::RawProjectPart makeRawProjectPart(const Utils::FilePath &projectFile,
Kit *kit,
- ToolChain *&cToolchain,
- ToolChain *&cxxToolchain,
+ CppTools::KitInfo &kitInfo,
const QString &workingDir,
- const Utils::FileName &fileName,
+ const Utils::FilePath &fileName,
QStringList flags)
{
HeaderPaths headerPaths;
@@ -201,7 +185,8 @@ CppTools::RawProjectPart makeRawProjectPart(const Utils::FileName &projectFile,
flags,
headerPaths,
macros,
- fileKind);
+ fileKind,
+ kitInfo.sysRootPath);
CppTools::RawProjectPart rpp;
rpp.setProjectFileLocation(projectFile.toString());
@@ -213,27 +198,29 @@ CppTools::RawProjectPart makeRawProjectPart(const Utils::FileName &projectFile,
if (fileKind == CppTools::ProjectFile::Kind::CHeader
|| fileKind == CppTools::ProjectFile::Kind::CSource) {
- if (!cToolchain) {
- cToolchain = toolchainFromFlags(kit, originalFlags,
- ProjectExplorer::Constants::C_LANGUAGE_ID);
- ToolChainKitInformation::setToolChain(kit, cToolchain);
+ if (!kitInfo.cToolChain) {
+ kitInfo.cToolChain = toolchainFromFlags(kit,
+ originalFlags,
+ ProjectExplorer::Constants::C_LANGUAGE_ID);
+ ToolChainKitAspect::setToolChain(kit, kitInfo.cToolChain);
}
- addDriverModeFlagIfNeeded(cToolchain, flags);
- rpp.setFlagsForC({cToolchain, flags});
+ addDriverModeFlagIfNeeded(kitInfo.cToolChain, flags, originalFlags);
+ rpp.setFlagsForC({kitInfo.cToolChain, flags});
} else {
- if (!cxxToolchain) {
- cxxToolchain = toolchainFromFlags(kit, originalFlags,
- ProjectExplorer::Constants::CXX_LANGUAGE_ID);
- ToolChainKitInformation::setToolChain(kit, cxxToolchain);
+ if (!kitInfo.cxxToolChain) {
+ kitInfo.cxxToolChain = toolchainFromFlags(kit,
+ originalFlags,
+ ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChainKitAspect::setToolChain(kit, kitInfo.cxxToolChain);
}
- addDriverModeFlagIfNeeded(cxxToolchain, flags);
- rpp.setFlagsForCxx({cxxToolchain, flags});
+ addDriverModeFlagIfNeeded(kitInfo.cxxToolChain, flags, originalFlags);
+ rpp.setFlagsForCxx({kitInfo.cxxToolChain, flags});
}
return rpp;
}
-QStringList relativeDirsList(Utils::FileName currentPath, const Utils::FileName &rootPath)
+QStringList relativeDirsList(Utils::FilePath currentPath, const Utils::FilePath &rootPath)
{
QStringList dirsList;
while (!currentPath.isEmpty() && currentPath != rootPath) {
@@ -248,10 +235,10 @@ QStringList relativeDirsList(Utils::FileName currentPath, const Utils::FileName
FolderNode *addChildFolderNode(FolderNode *parent, const QString &childName)
{
- Utils::FileName parentPath = parent->filePath();
- auto node = std::make_unique<FolderNode>(
- parentPath.appendPath(childName), NodeType::Folder, childName);
+ const Utils::FilePath path = parent->filePath().pathAppended(childName);
+ auto node = std::make_unique<FolderNode>(path);
FolderNode *childNode = node.get();
+ childNode->setDisplayName(childName);
parent->addNode(std::move(node));
return childNode;
@@ -269,7 +256,7 @@ FolderNode *addOrGetChildFolderNode(FolderNode *parent, const QString &childName
}
// Return the node for folderPath.
-FolderNode *createFoldersIfNeeded(FolderNode *root, const Utils::FileName &folderPath)
+FolderNode *createFoldersIfNeeded(FolderNode *root, const Utils::FilePath &folderPath)
{
const QStringList dirsList = relativeDirsList(folderPath, root->filePath());
@@ -288,89 +275,80 @@ FileType fileTypeForName(const QString &fileName)
return FileType::Source;
}
-void createTree(FolderNode *root,
- const Utils::FileName &rootPath,
- const CppTools::RawProjectParts &rpps)
+void addChild(FolderNode *root, const Utils::FilePath &fileName)
+{
+ FolderNode *parentNode = createFoldersIfNeeded(root, fileName.parentDir());
+ if (!parentNode->fileNode(fileName)) {
+ parentNode->addNode(
+ std::make_unique<FileNode>(fileName, fileTypeForName(fileName.fileName())));
+ }
+}
+
+void createTree(std::unique_ptr<ProjectNode> &root,
+ const Utils::FilePath &rootPath,
+ const CppTools::RawProjectParts &rpps,
+ const QList<FileNode *> &scannedFiles = QList<FileNode *>())
{
root->setAbsoluteFilePathAndLine(rootPath, -1);
+ std::unique_ptr<FolderNode> secondRoot;
for (const CppTools::RawProjectPart &rpp : rpps) {
for (const QString &filePath : rpp.files) {
- Utils::FileName fileName = Utils::FileName::fromString(filePath);
- FolderNode *parentNode = createFoldersIfNeeded(root, fileName.parentDir());
- if (!parentNode->fileNode(fileName)) {
- parentNode->addNode(std::make_unique<FileNode>(fileName,
- fileTypeForName(fileName.fileName()),
- false));
+ Utils::FilePath fileName = Utils::FilePath::fromString(filePath);
+ if (!fileName.isChildOf(rootPath)) {
+ if (fileName.isChildOf(Utils::FilePath::fromString(rpp.buildSystemTarget))) {
+ if (!secondRoot)
+ secondRoot = std::make_unique<ProjectNode>(
+ Utils::FilePath::fromString(rpp.buildSystemTarget));
+ addChild(secondRoot.get(), fileName);
+ }
+ } else {
+ addChild(root.get(), fileName);
}
}
}
-}
-struct Entry
-{
- QStringList flags;
- Utils::FileName fileName;
- QString workingDir;
-};
+ for (FileNode *node : scannedFiles) {
+ if (node->fileType() != FileType::Header)
+ continue;
-std::vector<Entry> readJsonObjects(const QString &filePath)
-{
- std::vector<Entry> result;
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly))
- return result;
-
- const QByteArray contents = file.readAll();
- int objectStart = contents.indexOf('{');
- int objectEnd = contents.indexOf('}', objectStart + 1);
-
- while (objectStart >= 0 && objectEnd >= 0) {
- const QJsonDocument document = QJsonDocument::fromJson(
- contents.mid(objectStart, objectEnd - objectStart + 1));
- if (document.isNull()) {
- // The end was found incorrectly, search for the next one.
- objectEnd = contents.indexOf('}', objectEnd + 1);
+ const Utils::FilePath fileName = node->filePath();
+ if (!fileName.isChildOf(rootPath))
continue;
+ FolderNode *parentNode = createFoldersIfNeeded(root.get(), fileName.parentDir());
+ if (!parentNode->fileNode(fileName)) {
+ std::unique_ptr<FileNode> headerNode(node->clone());
+ headerNode->setEnabled(false);
+ parentNode->addNode(std::move(headerNode));
}
-
- const QJsonObject object = document.object();
- const Utils::FileName fileName = jsonObjectFilename(object);
- const QStringList flags
- = filterFromFileName(jsonObjectFlags(object), fileName.toFileInfo().baseName());
- result.push_back({flags, fileName, object["directory"].toString()});
-
- objectStart = contents.indexOf('{', objectEnd + 1);
- objectEnd = contents.indexOf('}', objectStart + 1);
}
-
- return result;
+ qDeleteAll(scannedFiles);
+
+ if (secondRoot) {
+ std::unique_ptr<ProjectNode> firstRoot = std::move(root);
+ root = std::make_unique<ProjectNode>(firstRoot->filePath());
+ firstRoot->setDisplayName(rootPath.fileName());
+ root->addNode(std::move(firstRoot));
+ root->addNode(std::move(secondRoot));
+ }
}
+
} // anonymous namespace
-void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName &projectFile)
+void CompilationDatabaseProject::buildTreeAndProjectParts()
{
- std::vector<Entry> array = readJsonObjects(projectFilePath().toString());
- if (array.empty()) {
- emitParsingFinished(false);
- return;
- }
-
- auto root = std::make_unique<DBProjectNode>(projectDirectory());
-
CppTools::KitInfo kitInfo(this);
QTC_ASSERT(kitInfo.isValid(), return);
+ // Reset toolchains to pick them based on the database entries.
+ kitInfo.cToolChain = nullptr;
+ kitInfo.cxxToolChain = nullptr;
CppTools::RawProjectParts rpps;
- Utils::FileName commonPath;
- std::sort(array.begin(), array.end(), [](const Entry &lhs, const Entry &rhs) {
- return std::lexicographical_compare(lhs.flags.begin(), lhs.flags.end(),
- rhs.flags.begin(), rhs.flags.end());
- });
-
- const Entry *prevEntry = nullptr;
- for (const Entry &entry : array) {
+ QTC_ASSERT(m_parser, return);
+ const DbContents dbContents = m_parser->dbContents();
+ const DbEntry *prevEntry = nullptr;
+ for (const DbEntry &entry : dbContents.entries) {
if (prevEntry && prevEntry->flags == entry.flags) {
rpps.back().files.append(entry.fileName.toString());
continue;
@@ -378,14 +356,9 @@ void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName
prevEntry = &entry;
- commonPath = rpps.empty()
- ? entry.fileName.parentDir()
- : Utils::FileUtils::commonPath(commonPath, entry.fileName);
-
- CppTools::RawProjectPart rpp = makeRawProjectPart(projectFile,
+ CppTools::RawProjectPart rpp = makeRawProjectPart(projectFilePath(),
m_kit.get(),
- kitInfo.cToolChain,
- kitInfo.cxxToolChain,
+ kitInfo,
entry.workingDir,
entry.fileName,
entry.flags);
@@ -393,23 +366,37 @@ void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName
rpps.append(rpp);
}
- createTree(root.get(), commonPath, rpps);
+ if (!dbContents.extras.empty()) {
+ const Utils::FilePath baseDir = projectFilePath().parentDir();
+
+ QStringList extraFiles;
+ for (const QString &extra : dbContents.extras)
+ extraFiles.append(baseDir.pathAppended(extra).toString());
+
+ CppTools::RawProjectPart rppExtra;
+ rppExtra.setFiles(extraFiles);
+ rpps.append(rppExtra);
+ }
+
+
+ auto root = std::make_unique<ProjectNode>(projectDirectory());
+ createTree(root, rootProjectDirectory(), rpps, m_parser->scannedFiles());
- root->addNode(std::make_unique<FileNode>(
- projectFile,
- FileType::Project,
- false));
+ root->addNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project));
+
+ if (QFile::exists(dbContents.extraFileName))
+ root->addNode(std::make_unique<FileNode>(Utils::FilePath::fromString(dbContents.extraFileName),
+ FileType::Project));
setRootProjectNode(std::move(root));
m_cppCodeModelUpdater->update({this, kitInfo, rpps});
-
- emitParsingFinished(true);
}
-CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FileName &projectFile)
+CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FilePath &projectFile)
: Project(Constants::COMPILATIONDATABASEMIMETYPE, projectFile)
, m_cppCodeModelUpdater(std::make_unique<CppTools::CppProjectUpdater>())
+ , m_parseDelay(new QTimer(this))
{
setId(Constants::COMPILATIONDATABASEPROJECT_ID);
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
@@ -418,7 +405,6 @@ CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FileName &pr
setPreferredKitPredicate([](const Kit *) { return false; });
m_kit.reset(KitManager::defaultKit()->clone());
-
connect(this, &CompilationDatabaseProject::parsingFinished, this, [this]() {
if (!m_hasTarget) {
addTarget(createTarget(m_kit.get()));
@@ -426,23 +412,61 @@ CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FileName &pr
}
});
- reparseProject(projectFile);
+ connect(this, &CompilationDatabaseProject::rootProjectDirectoryChanged,
+ m_parseDelay, QOverload<>::of(&QTimer::start));
m_fileSystemWatcher.addFile(projectFile.toString(), Utils::FileSystemWatcher::WatchModifiedDate);
- connect(&m_fileSystemWatcher,
- &Utils::FileSystemWatcher::fileChanged,
- this,
- [this](const QString &projectFile) {
- reparseProject(Utils::FileName::fromString(projectFile));
- });
+ m_fileSystemWatcher.addFile(projectFile.toString() + Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX,
+ Utils::FileSystemWatcher::WatchModifiedDate);
+ connect(&m_fileSystemWatcher, &Utils::FileSystemWatcher::fileChanged,
+ m_parseDelay, QOverload<>::of(&QTimer::start));
+ connect(m_parseDelay, &QTimer::timeout, this, &CompilationDatabaseProject::reparseProject);
+ m_parseDelay->setSingleShot(true);
+ m_parseDelay->setInterval(1000);
}
-void CompilationDatabaseProject::reparseProject(const Utils::FileName &projectFile)
+Utils::FilePath CompilationDatabaseProject::rootPathFromSettings() const
{
+#ifdef WITH_TESTS
+ return Utils::FilePath::fromString(projectDirectory().fileName());
+#else
+ return Utils::FileName::fromString(
+ namedSettings(ProjectExplorer::Constants::PROJECT_ROOT_PATH_KEY).toString());
+#endif
+}
+
+Project::RestoreResult CompilationDatabaseProject::fromMap(const QVariantMap &map,
+ QString *errorMessage)
+{
+ Project::RestoreResult result = Project::fromMap(map, errorMessage);
+ if (result == Project::RestoreResult::Ok) {
+ const Utils::FilePath rootPath = rootPathFromSettings();
+ if (rootPath.isEmpty())
+ changeRootProjectDirectory(); // This triggers reparse itself.
+ else
+ reparseProject();
+ }
+
+ return result;
+}
+
+void CompilationDatabaseProject::reparseProject()
+{
+ if (m_parser) {
+ QTC_CHECK(isParsing());
+ m_parser->stop();
+ emitParsingFinished(false);
+ }
+ m_parser = new CompilationDbParser(displayName(), projectFilePath(), rootPathFromSettings(),
+ m_mimeBinaryCache, this);
+ connect(m_parser, &CompilationDbParser::finished, this, [this](bool success) {
+ if (success)
+ buildTreeAndProjectParts();
+ m_parser = nullptr;
+ emitParsingFinished(success);
+ });
emitParsingStarted();
- const QFuture<void> future = ::Utils::runAsync(
- [this, projectFile]() { buildTreeAndProjectParts(projectFile); });
- m_parserWatcher.setFuture(future);
+ m_parser->start();
}
CompilationDatabaseProject::~CompilationDatabaseProject()
@@ -473,5 +497,62 @@ CompilationDatabaseEditorFactory::CompilationDatabaseEditorFactory()
setCodeFoldingSupported(true);
}
+CompilationDatabaseBuildConfiguration::CompilationDatabaseBuildConfiguration(
+ ProjectExplorer::Target *target, Core::Id id)
+ : ProjectExplorer::BuildConfiguration(target, id)
+{
+ target->setApplicationTargets({BuildTargetInfo()});
+}
+
+void CompilationDatabaseBuildConfiguration::initialize(const ProjectExplorer::BuildInfo &info)
+{
+ ProjectExplorer::BuildConfiguration::initialize(info);
+ BuildStepList *buildSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
+ buildSteps->appendStep(new ProjectExplorer::ProcessStep(buildSteps));
+}
+
+ProjectExplorer::NamedWidget *CompilationDatabaseBuildConfiguration::createConfigWidget()
+{
+ return new ProjectExplorer::NamedWidget();
+}
+
+ProjectExplorer::BuildConfiguration::BuildType CompilationDatabaseBuildConfiguration::buildType() const
+{
+ return ProjectExplorer::BuildConfiguration::Release;
+}
+
+CompilationDatabaseBuildConfigurationFactory::CompilationDatabaseBuildConfigurationFactory()
+{
+ registerBuildConfiguration<CompilationDatabaseBuildConfiguration>(
+ "CompilationDatabase.CompilationDatabaseBuildConfiguration");
+
+ setSupportedProjectType(Constants::COMPILATIONDATABASEPROJECT_ID);
+ setSupportedProjectMimeTypeName(Constants::COMPILATIONDATABASEMIMETYPE);
+}
+
+static QList<ProjectExplorer::BuildInfo> defaultBuildInfos(
+ const ProjectExplorer::BuildConfigurationFactory *factory, const QString &name)
+{
+ ProjectExplorer::BuildInfo info(factory);
+ info.typeName = name;
+ info.displayName = name;
+ info.buildType = BuildConfiguration::Release;
+ QList<ProjectExplorer::BuildInfo> buildInfos;
+ buildInfos << info;
+ return buildInfos;
+}
+
+QList<ProjectExplorer::BuildInfo> CompilationDatabaseBuildConfigurationFactory::availableBuilds(
+ const ProjectExplorer::Target * /*parent*/) const
+{
+ return defaultBuildInfos(this, tr("Release"));
+}
+
+QList<ProjectExplorer::BuildInfo> CompilationDatabaseBuildConfigurationFactory::availableSetups(
+ const ProjectExplorer::Kit * /*k*/, const QString & /*projectPath*/) const
+{
+ return defaultBuildInfos(this, tr("Release"));
+}
+
} // namespace Internal
} // namespace CompilationDatabaseProjectManager
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
index 5b6fc0a116..376ebcc63b 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
@@ -25,39 +25,55 @@
#pragma once
+#include "compilationdatabaseutils.h"
+
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
#include <texteditor/texteditor.h>
#include <utils/filesystemwatcher.h>
#include <QFutureWatcher>
+QT_BEGIN_NAMESPACE
+class QTimer;
+QT_END_NAMESPACE
+
namespace CppTools {
class CppProjectUpdater;
}
-namespace ProjectExplorer { class Kit; }
+namespace ProjectExplorer {
+class Kit;
+}
namespace CompilationDatabaseProjectManager {
namespace Internal {
+class CompilationDbParser;
class CompilationDatabaseProject : public ProjectExplorer::Project
{
Q_OBJECT
public:
- explicit CompilationDatabaseProject(const Utils::FileName &filename);
+ explicit CompilationDatabaseProject(const Utils::FilePath &filename);
~CompilationDatabaseProject() override;
bool needsConfiguration() const override { return false; }
- bool needsBuildConfigurations() const override { return false; }
+ bool needsBuildConfigurations() const override { return true; }
private:
- void reparseProject(const Utils::FileName &projectFile);
- void buildTreeAndProjectParts(const Utils::FileName &projectFile);
+ RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
+
+ void reparseProject();
+ void buildTreeAndProjectParts();
+ Utils::FilePath rootPathFromSettings() const;
QFutureWatcher<void> m_parserWatcher;
std::unique_ptr<CppTools::CppProjectUpdater> m_cppCodeModelUpdater;
std::unique_ptr<ProjectExplorer::Kit> m_kit;
Utils::FileSystemWatcher m_fileSystemWatcher;
+ MimeBinaryCache m_mimeBinaryCache;
+ QTimer * const m_parseDelay;
+ CompilationDbParser *m_parser = nullptr;
bool m_hasTarget = false;
};
@@ -69,5 +85,30 @@ public:
CompilationDatabaseEditorFactory();
};
+class CompilationDatabaseBuildConfiguration : public ProjectExplorer::BuildConfiguration
+{
+ Q_OBJECT
+public:
+ CompilationDatabaseBuildConfiguration(ProjectExplorer::Target *target, Core::Id id);
+ ProjectExplorer::NamedWidget *createConfigWidget() override;
+ BuildType buildType() const override;
+
+protected:
+ void initialize(const ProjectExplorer::BuildInfo &info) override;
+};
+
+class CompilationDatabaseBuildConfigurationFactory
+ : public ProjectExplorer::BuildConfigurationFactory
+{
+ Q_OBJECT
+public:
+ CompilationDatabaseBuildConfigurationFactory();
+
+ QList<ProjectExplorer::BuildInfo> availableBuilds(
+ const ProjectExplorer::Target *parent) const override;
+ QList<ProjectExplorer::BuildInfo> availableSetups(const ProjectExplorer::Kit *k,
+ const QString &projectPath) const override;
+};
+
} // namespace Internal
} // namespace CompilationDatabaseProjectManager
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.pro b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.pro
index e7efefb47e..e11a8cc06b 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.pro
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.pro
@@ -3,13 +3,15 @@ include(../../qtcreatorplugin.pri)
SOURCES = \
compilationdatabaseproject.cpp \
compilationdatabaseprojectmanagerplugin.cpp \
- compilationdatabaseutils.cpp
+ compilationdatabaseutils.cpp \
+ compilationdbparser.cpp
HEADERS = \
compilationdatabaseproject.h \
compilationdatabaseprojectmanagerplugin.h \
compilationdatabaseconstants.h \
- compilationdatabaseutils.h
+ compilationdatabaseutils.h \
+ compilationdbparser.h
equals(TEST, 1) {
HEADERS += \
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.qbs b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.qbs
index 4cbe2af284..8f592cbc51 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.qbs
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanager.qbs
@@ -17,6 +17,8 @@ QtcPlugin {
"compilationdatabaseutils.h",
"compilationdatabaseprojectmanagerplugin.cpp",
"compilationdatabaseprojectmanagerplugin.h",
+ "compilationdbparser.cpp",
+ "compilationdbparser.h",
]
Group {
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.cpp
index 77359adc70..5da42c8bfd 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.cpp
@@ -29,33 +29,75 @@
#include "compilationdatabaseproject.h"
#include "compilationdatabasetests.h"
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
#include <coreplugin/fileiconprovider.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
+#include <projectexplorer/projecttree.h>
+#include <projectexplorer/session.h>
#include <utils/utilsicons.h>
namespace CompilationDatabaseProjectManager {
namespace Internal {
+const char CHANGEROOTDIR[] = "CompilationDatabaseProjectManager.ChangeRootDirectory";
+const char COMPILE_COMMANDS_JSON[] = "compile_commands.json";
+
bool CompilationDatabaseProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
Q_UNUSED(arguments);
Q_UNUSED(errorMessage);
- Core::FileIconProvider::registerIconOverlayForFilename(Utils::Icons::PROJECT.imageFileName(),
- "compile_commands.json");
+ Core::FileIconProvider::registerIconOverlayForFilename(
+ Utils::Icons::PROJECT.imageFileName(),
+ COMPILE_COMMANDS_JSON);
+ Core::FileIconProvider::registerIconOverlayForFilename(
+ Utils::Icons::PROJECT.imageFileName(),
+ QString(COMPILE_COMMANDS_JSON) + Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX);
ProjectExplorer::ProjectManager::registerProjectType<CompilationDatabaseProject>(
Constants::COMPILATIONDATABASEMIMETYPE);
+ m_changeProjectRootDirectoryAction = new QAction(tr("Change Root Directory"), this);
+ Core::Command *cmd = Core::ActionManager::registerAction(m_changeProjectRootDirectoryAction,
+ CHANGEROOTDIR);
+ Core::ActionContainer *mprojectContextMenu = Core::ActionManager::actionContainer(
+ ProjectExplorer::Constants::M_PROJECTCONTEXT);
+ mprojectContextMenu->addSeparator(ProjectExplorer::Constants::G_PROJECT_TREE);
+ mprojectContextMenu->addAction(cmd, ProjectExplorer::Constants::G_PROJECT_TREE);
+
+ connect(m_changeProjectRootDirectoryAction,
+ &QAction::triggered,
+ ProjectExplorer::ProjectTree::instance(),
+ &ProjectExplorer::ProjectTree::changeProjectRootDirectory);
+
+ connect(ProjectExplorer::SessionManager::instance(),
+ &ProjectExplorer::SessionManager::startupProjectChanged,
+ this,
+ &CompilationDatabaseProjectManagerPlugin::projectChanged);
+ connect(ProjectExplorer::ProjectTree::instance(),
+ &ProjectExplorer::ProjectTree::currentProjectChanged,
+ this,
+ &CompilationDatabaseProjectManagerPlugin::projectChanged);
return true;
}
+void CompilationDatabaseProjectManagerPlugin::projectChanged()
+{
+ const auto *currentProject = qobject_cast<CompilationDatabaseProject *>(
+ ProjectExplorer::ProjectTree::currentProject());
+
+ m_changeProjectRootDirectoryAction->setEnabled(currentProject);
+}
+
void CompilationDatabaseProjectManagerPlugin::extensionsInitialized()
{
}
-QList<QObject *> CompilationDatabaseProjectManagerPlugin::createTestObjects() const
+QVector<QObject *> CompilationDatabaseProjectManagerPlugin::createTestObjects() const
{
- QList<QObject *> tests;
+ QVector<QObject *> tests;
#ifdef WITH_TESTS
tests << new CompilationDatabaseTests;
#endif
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.h
index 37c9c1db1d..42a15ad3cf 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseprojectmanagerplugin.h
@@ -43,9 +43,13 @@ public:
bool initialize(const QStringList &arguments, QString *errorMessage) final;
void extensionsInitialized() final;
private:
- QList<QObject *> createTestObjects() const final;
+ void projectChanged();
+
+ QVector<QObject *> createTestObjects() const final;
CompilationDatabaseEditorFactory factory;
+ CompilationDatabaseBuildConfigurationFactory buildConfigFactory;
+ QAction *m_changeProjectRootDirectoryAction;
};
} // namespace Internal
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp
index 72a1b6ac74..42ba0e0887 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp
@@ -33,6 +33,7 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/toolchainmanager.h>
+#include <utils/algorithm.h>
#include <QtTest>
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
index 1884aa1c6d..1affca78fa 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp
@@ -33,18 +33,18 @@
#include <QDir>
#include <QRegularExpression>
+#include <QSet>
using namespace ProjectExplorer;
namespace CompilationDatabaseProjectManager {
+namespace Internal {
static QString updatedPathFlag(const QString &pathStr, const QString &workingDir)
{
QString result = pathStr;
- if (!QDir(pathStr).exists()
- && QDir(workingDir + "/" + pathStr).exists()) {
+ if (QDir(pathStr).isRelative())
result = workingDir + "/" + pathStr;
- }
return result;
}
@@ -99,7 +99,8 @@ void filteredFlags(const QString &fileName,
QStringList &flags,
HeaderPaths &headerPaths,
Macros &macros,
- CppTools::ProjectFile::Kind &fileKind)
+ CppTools::ProjectFile::Kind &fileKind,
+ QString &sysRoot)
{
if (flags.empty())
return;
@@ -183,6 +184,12 @@ void filteredFlags(const QString &fileName,
continue;
}
+ if (flag.startsWith("--sysroot=")) {
+ if (sysRoot.isEmpty())
+ sysRoot = updatedPathFlag(flag.mid(10), workingDir);
+ continue;
+ }
+
if ((flag.startsWith("-std=") || flag.startsWith("/std:"))
&& fileKind == CppTools::ProjectFile::Unclassified) {
const bool cpp = (flag.contains("c++") || flag.contains("gnu++"));
@@ -205,7 +212,7 @@ void filteredFlags(const QString &fileName,
flags = filtered;
}
-QStringList splitCommandLine(QString commandLine)
+QStringList splitCommandLine(QString commandLine, QSet<QString> &flagsCache)
{
QStringList result;
bool insideQuotes = false;
@@ -215,16 +222,24 @@ QStringList splitCommandLine(QString commandLine)
for (const QString &part : commandLine.split(QRegularExpression("\""))) {
if (insideQuotes) {
const QString quotedPart = "\"" + part + "\"";
- if (result.last().endsWith("="))
- result.last().append(quotedPart);
- else
- result.append(quotedPart);
+ if (result.last().endsWith("=")) {
+ auto flagIt = flagsCache.insert(result.last() + quotedPart);
+ result.last() = *flagIt;
+ } else {
+ auto flagIt = flagsCache.insert(quotedPart);
+ result.append(*flagIt);
+ }
} else { // If 's' is outside quotes ...
- result.append(part.split(QRegularExpression("\\s+"), QString::SkipEmptyParts));
+ for (const QString &flag :
+ part.split(QRegularExpression("\\s+"), QString::SkipEmptyParts)) {
+ auto flagIt = flagsCache.insert(flag);
+ result.append(*flagIt);
+ }
}
insideQuotes = !insideQuotes;
}
return result;
}
+} // namespace Internal
} // namespace CompilationDatabaseProjectManager
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
index e465b6ba23..d2c062e7c3 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h
@@ -28,7 +28,9 @@
#include "compilationdatabaseconstants.h"
#include <cpptools/cppprojectfile.h>
+#include <utils/fileutils.h>
+#include <QHash>
#include <QStringList>
namespace ProjectExplorer {
@@ -37,6 +39,23 @@ class Macro;
}
namespace CompilationDatabaseProjectManager {
+namespace Internal {
+
+class DbEntry {
+public:
+ QStringList flags;
+ Utils::FilePath fileName;
+ QString workingDir;
+};
+
+class DbContents {
+public:
+ std::vector<DbEntry> entries;
+ QString extraFileName;
+ QStringList extras;
+};
+
+using MimeBinaryCache = QHash<QString, bool>;
QStringList filterFromFileName(const QStringList &flags, QString baseName);
@@ -45,8 +64,10 @@ void filteredFlags(const QString &fileName,
QStringList &flags,
QVector<ProjectExplorer::HeaderPath> &headerPaths,
QVector<ProjectExplorer::Macro> &macros,
- CppTools::ProjectFile::Kind &fileKind);
+ CppTools::ProjectFile::Kind &fileKind,
+ QString &sysRoot);
-QStringList splitCommandLine(QString commandLine);
+QStringList splitCommandLine(QString commandLine, QSet<QString> &flagsCache);
+} // namespace Internal
} // namespace CompilationDatabaseProjectManager
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
new file mode 100644
index 0000000000..d75bf7be40
--- /dev/null
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** 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 "compilationdbparser.h"
+
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <projectexplorer/task.h>
+#include <projectexplorer/treescanner.h>
+#include <utils/mimetypes/mimetype.h>
+#include <utils/runextensions.h>
+
+#include <QDir>
+#include <QFileInfo>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace CompilationDatabaseProjectManager {
+namespace Internal {
+
+CompilationDbParser::CompilationDbParser(const QString &projectName, const FilePath &projectPath,
+ const FilePath &rootPath, MimeBinaryCache &mimeBinaryCache,
+ QObject *parent)
+ : QObject(parent),
+ m_projectName(projectName),
+ m_projectFilePath(projectPath),
+ m_rootPath(rootPath),
+ m_mimeBinaryCache(mimeBinaryCache)
+{
+ connect(&m_parserWatcher, &QFutureWatcher<void>::finished, this, [this] {
+ m_dbContents = m_parserWatcher.result();
+ if (!m_treeScanner || m_treeScanner->isFinished())
+ finish();
+ });
+}
+
+void CompilationDbParser::start()
+{
+ // Thread 1: Scan disk.
+ if (!m_rootPath.isEmpty()) {
+ m_treeScanner = new TreeScanner(this);
+ m_treeScanner->setFilter([this](const MimeType &mimeType, const FilePath &fn) {
+ // Mime checks requires more resources, so keep it last in check list
+ bool isIgnored = fn.toString().startsWith(m_projectFilePath.toString() + ".user")
+ || TreeScanner::isWellKnownBinary(mimeType, fn);
+
+ // Cache mime check result for speed up
+ if (!isIgnored) {
+ auto it = m_mimeBinaryCache.find(mimeType.name());
+ if (it != m_mimeBinaryCache.end()) {
+ isIgnored = *it;
+ } else {
+ isIgnored = TreeScanner::isMimeBinary(mimeType, fn);
+ m_mimeBinaryCache[mimeType.name()] = isIgnored;
+ }
+ }
+
+ return isIgnored;
+ });
+ m_treeScanner->setTypeFactory([](const Utils::MimeType &mimeType, const Utils::FilePath &fn) {
+ return TreeScanner::genericFileType(mimeType, fn);
+ });
+ m_treeScanner->asyncScanForFiles(m_rootPath);
+ Core::ProgressManager::addTask(m_treeScanner->future(),
+ tr("Scan \"%1\" project tree").arg(m_projectName),
+ "CompilationDatabase.Scan.Tree");
+ connect(m_treeScanner, &TreeScanner::finished, this, [this] {
+ if (m_parserWatcher.isFinished())
+ finish();
+ });
+ }
+
+ // Thread 2: Parse the project file.
+ const QFuture<DbContents> future = runAsync(&CompilationDbParser::parseProject, this);
+ Core::ProgressManager::addTask(future,
+ tr("Parse \"%1\" project").arg(m_projectName),
+ "CompilationDatabase.Parse");
+ m_parserWatcher.setFuture(future);
+}
+
+void CompilationDbParser::stop()
+{
+ disconnect();
+ m_parserWatcher.disconnect();
+ m_parserWatcher.cancel();
+ if (m_treeScanner) {
+ m_treeScanner->disconnect();
+ m_treeScanner->future().cancel();
+ }
+ deleteLater();
+}
+
+QList<FileNode *> CompilationDbParser::scannedFiles() const
+{
+ return m_treeScanner && !m_treeScanner->future().isCanceled()
+ ? m_treeScanner->release() : QList<FileNode *>();
+}
+
+void CompilationDbParser::finish()
+{
+ emit finished(true);
+ deleteLater();
+}
+
+static QStringList jsonObjectFlags(const QJsonObject &object, QSet<QString> &flagsCache)
+{
+ QStringList flags;
+ const QJsonArray arguments = object["arguments"].toArray();
+ if (arguments.isEmpty()) {
+ flags = splitCommandLine(object["command"].toString(), flagsCache);
+ } else {
+ flags.reserve(arguments.size());
+ for (const QJsonValue &arg : arguments) {
+ auto flagIt = flagsCache.insert(arg.toString());
+ flags.append(*flagIt);
+ }
+ }
+
+ return flags;
+}
+
+static FilePath jsonObjectFilename(const QJsonObject &object)
+{
+ const QString workingDir = QDir::fromNativeSeparators(object["directory"].toString());
+ FilePath fileName = FilePath::fromString(QDir::fromNativeSeparators(object["file"].toString()));
+ if (fileName.toFileInfo().isRelative())
+ fileName = FilePath::fromString(workingDir + "/" + fileName.toString()).canonicalPath();
+ return fileName;
+}
+
+static std::vector<DbEntry> readJsonObjects(const QString &filePath)
+{
+ std::vector<DbEntry> result;
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly))
+ return result;
+
+ const QByteArray contents = file.readAll();
+ int objectStart = contents.indexOf('{');
+ int objectEnd = contents.indexOf('}', objectStart + 1);
+
+ QSet<QString> flagsCache;
+ while (objectStart >= 0 && objectEnd >= 0) {
+ const QJsonDocument document = QJsonDocument::fromJson(
+ contents.mid(objectStart, objectEnd - objectStart + 1));
+ if (document.isNull()) {
+ // The end was found incorrectly, search for the next one.
+ objectEnd = contents.indexOf('}', objectEnd + 1);
+ continue;
+ }
+
+ const QJsonObject object = document.object();
+ const Utils::FilePath fileName = jsonObjectFilename(object);
+ const QStringList flags = filterFromFileName(jsonObjectFlags(object, flagsCache),
+ fileName.toFileInfo().baseName());
+ result.push_back({flags, fileName, object["directory"].toString()});
+
+ objectStart = contents.indexOf('{', objectEnd + 1);
+ objectEnd = contents.indexOf('}', objectStart + 1);
+ }
+
+ return result;
+}
+
+QStringList readExtraFiles(const QString &filePath)
+{
+ QStringList result;
+
+ QFile file(filePath);
+ if (file.open(QFile::ReadOnly)) {
+ QTextStream stream(&file);
+
+ while (!stream.atEnd()) {
+ QString line = stream.readLine();
+ line = line.trimmed();
+
+ if (line.isEmpty() || line.startsWith('#'))
+ continue;
+
+ result.push_back(line);
+ }
+ }
+
+ return result;
+}
+
+DbContents CompilationDbParser::parseProject()
+{
+ DbContents dbContents;
+ dbContents.entries = readJsonObjects(m_projectFilePath.toString());
+ dbContents.extraFileName = m_projectFilePath.toString() +
+ Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX;
+ dbContents.extras = readExtraFiles(dbContents.extraFileName);
+ std::sort(dbContents.entries.begin(), dbContents.entries.end(),
+ [](const DbEntry &lhs, const DbEntry &rhs) {
+ return std::lexicographical_compare(lhs.flags.begin(), lhs.flags.end(),
+ rhs.flags.begin(), rhs.flags.end());
+ });
+ return dbContents;
+}
+
+} // namespace Internal
+} // namespace CompilationDatabaseProjectManager
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h
new file mode 100644
index 0000000000..ded713d590
--- /dev/null
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 "compilationdatabaseutils.h"
+
+#include <utils/fileutils.h>
+
+#include <QFutureWatcher>
+#include <QList>
+#include <QObject>
+#include <QStringList>
+
+#include <vector>
+
+namespace ProjectExplorer {
+class FileNode;
+class TreeScanner;
+}
+
+namespace CompilationDatabaseProjectManager {
+namespace Internal {
+
+class CompilationDbParser : public QObject
+{
+ Q_OBJECT
+public:
+ explicit CompilationDbParser(const QString &projectName, const Utils::FilePath &projectPath,
+ const Utils::FilePath &rootPath, MimeBinaryCache &mimeBinaryCache,
+ QObject *parent = nullptr);
+
+ void start();
+ void stop();
+
+ QList<ProjectExplorer::FileNode *> scannedFiles() const;
+ DbContents dbContents() const { return m_dbContents; }
+
+signals:
+ void finished(bool success);
+
+private:
+ void finish();
+ DbContents parseProject();
+
+ const QString m_projectName;
+ const Utils::FilePath m_projectFilePath;
+ const Utils::FilePath m_rootPath;
+ MimeBinaryCache &m_mimeBinaryCache;
+ ProjectExplorer::TreeScanner *m_treeScanner = nullptr;
+ QFutureWatcher<DbContents> m_parserWatcher;
+ DbContents m_dbContents;
+};
+
+} // namespace Internal
+} // namespace CompilationDatabaseProjectManager
diff --git a/src/plugins/coreplugin/CMakeLists.txt b/src/plugins/coreplugin/CMakeLists.txt
new file mode 100644
index 0000000000..7783685969
--- /dev/null
+++ b/src/plugins/coreplugin/CMakeLists.txt
@@ -0,0 +1,185 @@
+add_qtc_plugin(Core
+ DEPENDS Qt5::PrintSupport Qt5::Qml Qt5::Sql Qt5::Gui Qt5::GuiPrivate
+ PUBLIC_DEPENDS Aggregation ExtensionSystem Utils app_version
+ SOURCES
+ actionmanager/actioncontainer.cpp actionmanager/actioncontainer.h actionmanager/actioncontainer_p.h
+ actionmanager/actionmanager.cpp actionmanager/actionmanager.h actionmanager/actionmanager_p.h
+ actionmanager/command.cpp actionmanager/command.h actionmanager/command_p.h
+ actionmanager/commandbutton.cpp actionmanager/commandbutton.h
+ actionmanager/commandmappings.cpp actionmanager/commandmappings.h
+ actionmanager/commandsfile.cpp actionmanager/commandsfile.h
+ basefilewizard.cpp basefilewizard.h
+ basefilewizardfactory.cpp basefilewizardfactory.h
+ core.qrc
+ core_global.h
+ coreconstants.h
+ coreicons.cpp coreicons.h
+ corejsextensions.cpp corejsextensions.h
+ coreplugin.cpp coreplugin.h
+ designmode.cpp designmode.h
+ dialogs/addtovcsdialog.cpp dialogs/addtovcsdialog.h dialogs/addtovcsdialog.ui
+ dialogs/externaltoolconfig.cpp dialogs/externaltoolconfig.h dialogs/externaltoolconfig.ui
+ dialogs/filepropertiesdialog.cpp dialogs/filepropertiesdialog.h dialogs/filepropertiesdialog.ui
+ dialogs/ioptionspage.cpp dialogs/ioptionspage.h
+ dialogs/newdialog.cpp dialogs/newdialog.h dialogs/newdialog.ui
+ dialogs/openwithdialog.cpp dialogs/openwithdialog.h dialogs/openwithdialog.ui
+ dialogs/promptoverwritedialog.cpp dialogs/promptoverwritedialog.h
+ dialogs/readonlyfilesdialog.cpp dialogs/readonlyfilesdialog.h dialogs/readonlyfilesdialog.ui
+ dialogs/saveitemsdialog.cpp dialogs/saveitemsdialog.h dialogs/saveitemsdialog.ui
+ dialogs/settingsdialog.cpp dialogs/settingsdialog.h
+ dialogs/shortcutsettings.cpp dialogs/shortcutsettings.h
+ diffservice.cpp diffservice.h
+ documentmanager.cpp documentmanager.h
+ editmode.cpp editmode.h
+ editormanager/documentmodel.cpp editormanager/documentmodel.h editormanager/documentmodel_p.h
+ editormanager/editorarea.cpp editormanager/editorarea.h
+ editormanager/editormanager.cpp editormanager/editormanager.h editormanager/editormanager_p.h
+ editormanager/editorview.cpp editormanager/editorview.h
+ editormanager/editorwindow.cpp editormanager/editorwindow.h
+ editormanager/ieditor.cpp editormanager/ieditor.h
+ editormanager/ieditorfactory.cpp editormanager/ieditorfactory.h editormanager/ieditorfactory_p.h
+ editormanager/iexternaleditor.cpp editormanager/iexternaleditor.h
+ editormanager/openeditorsview.cpp editormanager/openeditorsview.h
+ editormanager/openeditorswindow.cpp editormanager/openeditorswindow.h
+ editormanager/systemeditor.cpp editormanager/systemeditor.h
+ editortoolbar.cpp editortoolbar.h
+ externaltool.cpp externaltool.h
+ externaltoolmanager.cpp externaltoolmanager.h
+ fancyactionbar.cpp fancyactionbar.h
+ fancyactionbar.qrc
+ fancytabwidget.cpp fancytabwidget.h
+ featureprovider.cpp featureprovider.h
+ fileiconprovider.cpp fileiconprovider.h
+ fileutils.cpp fileutils.h
+ find/basetextfind.cpp find/basetextfind.h
+ find/currentdocumentfind.cpp find/currentdocumentfind.h
+ find/find.qrc
+ find/finddialog.ui
+ find/findplugin.cpp find/findplugin.h
+ find/findtoolbar.cpp find/findtoolbar.h
+ find/findtoolwindow.cpp find/findtoolwindow.h
+ find/findwidget.ui
+ find/highlightscrollbarcontroller.cpp find/highlightscrollbarcontroller.h
+ find/ifindfilter.cpp find/ifindfilter.h
+ find/ifindsupport.cpp find/ifindsupport.h
+ find/itemviewfind.cpp find/itemviewfind.h
+ find/optionspopup.cpp find/optionspopup.h
+ find/searchresultcolor.h
+ find/searchresultitem.h
+ find/searchresulttreeitemdelegate.cpp find/searchresulttreeitemdelegate.h
+ find/searchresulttreeitemroles.h
+ find/searchresulttreeitems.cpp find/searchresulttreeitems.h
+ find/searchresulttreemodel.cpp find/searchresulttreemodel.h
+ find/searchresulttreeview.cpp find/searchresulttreeview.h
+ find/searchresultwidget.cpp find/searchresultwidget.h
+ find/searchresultwindow.cpp find/searchresultwindow.h
+ find/textfindconstants.h
+ findplaceholder.cpp findplaceholder.h
+ generalsettings.cpp generalsettings.h generalsettings.ui
+ generatedfile.cpp generatedfile.h
+ helpitem.cpp helpitem.h
+ helpmanager.cpp helpmanager.h helpmanager_implementation.h
+ icontext.cpp icontext.h
+ icore.cpp icore.h
+ id.cpp id.h
+ idocument.cpp idocument.h
+ idocumentfactory.cpp idocumentfactory.h
+ ifilewizardextension.h
+ imode.cpp imode.h
+ inavigationwidgetfactory.cpp inavigationwidgetfactory.h
+ infobar.cpp infobar.h
+ ioutputpane.cpp ioutputpane.h
+ iversioncontrol.cpp iversioncontrol.h
+ iwelcomepage.cpp iwelcomepage.h
+ iwizardfactory.cpp iwizardfactory.h
+ jsexpander.cpp jsexpander.h
+ locator/basefilefilter.cpp locator/basefilefilter.h
+ locator/commandlocator.cpp locator/commandlocator.h
+ locator/directoryfilter.cpp locator/directoryfilter.h locator/directoryfilter.ui
+ locator/executefilter.cpp locator/executefilter.h
+ locator/externaltoolsfilter.cpp locator/externaltoolsfilter.h
+ locator/filesystemfilter.cpp locator/filesystemfilter.h locator/filesystemfilter.ui
+ locator/ilocatorfilter.cpp locator/ilocatorfilter.h
+ locator/locator.cpp locator/locator.h
+ locator/locatorconstants.h
+ locator/locatorfiltersfilter.cpp locator/locatorfiltersfilter.h
+ locator/locatormanager.cpp locator/locatormanager.h
+ locator/locatorsearchutils.cpp locator/locatorsearchutils.h
+ locator/locatorsettingspage.cpp locator/locatorsettingspage.h locator/locatorsettingspage.ui
+ locator/locatorwidget.cpp locator/locatorwidget.h
+ locator/opendocumentsfilter.cpp locator/opendocumentsfilter.h
+ mainwindow.cpp mainwindow.h
+ manhattanstyle.cpp manhattanstyle.h
+ menubarfilter.cpp menubarfilter.h
+ messagebox.cpp messagebox.h
+ messagemanager.cpp messagemanager.h
+ messageoutputwindow.cpp messageoutputwindow.h
+ mimetypemagicdialog.cpp mimetypemagicdialog.h mimetypemagicdialog.ui
+ mimetypesettings.cpp mimetypesettings.h
+ mimetypesettingspage.ui
+ minisplitter.cpp minisplitter.h
+ modemanager.cpp modemanager.h
+ navigationsubwidget.cpp navigationsubwidget.h
+ navigationwidget.cpp navigationwidget.h
+ opendocumentstreeview.cpp opendocumentstreeview.h
+ outputpane.cpp outputpane.h
+ outputpanemanager.cpp outputpanemanager.h
+ outputwindow.cpp outputwindow.h
+ patchtool.cpp patchtool.h
+ plugindialog.cpp plugindialog.h
+ progressmanager/futureprogress.cpp progressmanager/futureprogress.h
+ progressmanager/progressbar.cpp progressmanager/progressbar.h
+ progressmanager/progressmanager.cpp progressmanager/progressmanager.h progressmanager/progressmanager_p.h
+ progressmanager/progressview.cpp progressmanager/progressview.h
+ reaper.cpp reaper.h reaper_p.h
+ rightpane.cpp rightpane.h
+ settingsdatabase.cpp settingsdatabase.h
+ shellcommand.cpp shellcommand.h
+ sidebar.cpp sidebar.h
+ sidebarwidget.cpp sidebarwidget.h
+ statusbarmanager.cpp statusbarmanager.h
+ styleanimator.cpp styleanimator.h
+ systemsettings.cpp systemsettings.h systemsettings.ui
+ textdocument.cpp textdocument.h
+ themechooser.cpp themechooser.h
+ toolsettings.cpp toolsettings.h
+ variablechooser.cpp variablechooser.h
+ vcsmanager.cpp vcsmanager.h
+ versiondialog.cpp versiondialog.h
+ windowsupport.cpp windowsupport.h
+ EXPLICIT_MOC dialogs/filepropertiesdialog.h
+)
+
+extend_qtc_plugin(Core
+ CONDITION WITH_TESTS
+ SOURCES
+ locator/locator_test.cpp
+ locator/locatorfiltertest.cpp locator/locatorfiltertest.h
+ testdatadir.cpp testdatadir.h
+)
+
+extend_qtc_plugin(Core
+ CONDITION WIN32
+ SOURCES progressmanager/progressmanager_win.cpp
+)
+
+extend_qtc_plugin(Core
+ CONDITION APPLE
+ DEPENDS ${FWAppKit}
+ SOURCES
+ progressmanager/progressmanager_mac.mm
+ locator/spotlightlocatorfilter.h locator/spotlightlocatorfilter.mm
+)
+
+extend_qtc_plugin(Core
+ CONDITION (NOT WIN32) AND (NOT APPLE)
+ SOURCES progressmanager/progressmanager_x11.cpp
+)
+
+extend_qtc_plugin(Core
+ CONDITION TARGET Qt5::Script
+ DEPENDS Qt5::Script
+ DEFINES WITH_JAVASCRIPTFILTER
+ SOURCES
+ locator/javascriptfilter.cpp locator/javascriptfilter.h
+)
diff --git a/src/plugins/coreplugin/corejsextensions.cpp b/src/plugins/coreplugin/corejsextensions.cpp
index 7398d60a94..b5cbd08973 100644
--- a/src/plugins/coreplugin/corejsextensions.cpp
+++ b/src/plugins/coreplugin/corejsextensions.cpp
@@ -118,7 +118,7 @@ QString UtilsJsExtension::preferredSuffix(const QString &mimetype) const
QString UtilsJsExtension::fileName(const QString &path, const QString &extension) const
{
- return Utils::FileName::fromString(path, extension).toString();
+ return Utils::FilePath::fromStringWithExtension(path, extension).toString();
}
QString UtilsJsExtension::mktemp(const QString &pattern) const
diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp
index 7f36733131..95398acc29 100644
--- a/src/plugins/coreplugin/coreplugin.cpp
+++ b/src/plugins/coreplugin/coreplugin.cpp
@@ -276,7 +276,7 @@ void CorePlugin::addToPathChooserContextMenu(Utils::PathChooser *pathChooser, QM
});
menu->insertAction(firstAction, showInGraphicalShell);
- auto *showInTerminal = new QAction(Core::FileUtils::msgTerminalAction(), menu);
+ auto *showInTerminal = new QAction(Core::FileUtils::msgTerminalHereAction(), menu);
connect(showInTerminal, &QAction::triggered, pathChooser, [pathChooser]() {
Core::FileUtils::openTerminal(pathChooser->path());
});
diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs
index cc4da8d2fd..4a603b655c 100644
--- a/src/plugins/coreplugin/coreplugin.qbs
+++ b/src/plugins/coreplugin/coreplugin.qbs
@@ -314,6 +314,8 @@ Project {
"ifindsupport.h",
"itemviewfind.cpp",
"itemviewfind.h",
+ "optionspopup.cpp",
+ "optionspopup.h",
"searchresultcolor.h",
"searchresulttreeitemdelegate.cpp",
"searchresulttreeitemdelegate.h",
diff --git a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp
index 33d2123238..fef059d7fa 100644
--- a/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/filepropertiesdialog.cpp
@@ -37,7 +37,7 @@
#include <QFileInfo>
#include <QLocale>
-FilePropertiesDialog::FilePropertiesDialog(const Utils::FileName &fileName, QWidget *parent) :
+FilePropertiesDialog::FilePropertiesDialog(const Utils::FilePath &fileName, QWidget *parent) :
QDialog(parent),
m_ui(new Ui::FilePropertiesDialog),
m_fileName(fileName.toString())
@@ -78,11 +78,7 @@ void FilePropertiesDialog::refresh()
m_ui->owner->setText(fileInfo.owner());
m_ui->group->setText(fileInfo.group());
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
m_ui->size->setText(locale.formattedDataSize(fileInfo.size()));
-#else
- m_ui->size->setText(tr("%1 Bytes").arg(locale.toString(fileInfo.size())));
-#endif
m_ui->readable->setChecked(fileInfo.isReadable());
m_ui->writable->setChecked(fileInfo.isWritable());
m_ui->executable->setChecked(fileInfo.isExecutable());
diff --git a/src/plugins/coreplugin/dialogs/filepropertiesdialog.h b/src/plugins/coreplugin/dialogs/filepropertiesdialog.h
index db55abeb0e..95d8bfbceb 100644
--- a/src/plugins/coreplugin/dialogs/filepropertiesdialog.h
+++ b/src/plugins/coreplugin/dialogs/filepropertiesdialog.h
@@ -41,7 +41,7 @@ class FilePropertiesDialog : public QDialog
Q_OBJECT
public:
- explicit FilePropertiesDialog(const Utils::FileName &fileName, QWidget *parent = nullptr);
+ explicit FilePropertiesDialog(const Utils::FilePath &fileName, QWidget *parent = nullptr);
~FilePropertiesDialog() override;
private:
diff --git a/src/plugins/coreplugin/dialogs/newdialog.cpp b/src/plugins/coreplugin/dialogs/newdialog.cpp
index e89ea9846c..e691d826ed 100644
--- a/src/plugins/coreplugin/dialogs/newdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/newdialog.cpp
@@ -231,7 +231,7 @@ NewDialog::NewDialog(QWidget *parent) :
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &NewDialog::reject);
connect(m_ui->comboBox,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
+ QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
this, &NewDialog::setSelectedPlatform);
}
diff --git a/src/plugins/coreplugin/dialogs/openwithdialog.cpp b/src/plugins/coreplugin/dialogs/openwithdialog.cpp
index 7452fdb319..526a32f7e5 100644
--- a/src/plugins/coreplugin/dialogs/openwithdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/openwithdialog.cpp
@@ -37,7 +37,7 @@ OpenWithDialog::OpenWithDialog(const QString &fileName, QWidget *parent)
{
setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
- label->setText(tr("Open file \"%1\" with:").arg(Utils::FileName::fromString(fileName).fileName()));
+ label->setText(tr("Open file \"%1\" with:").arg(Utils::FilePath::fromString(fileName).fileName()));
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked,
diff --git a/src/plugins/coreplugin/dialogs/openwithdialog.h b/src/plugins/coreplugin/dialogs/openwithdialog.h
index a3f0db0366..1833af8383 100644
--- a/src/plugins/coreplugin/dialogs/openwithdialog.h
+++ b/src/plugins/coreplugin/dialogs/openwithdialog.h
@@ -29,8 +29,6 @@
#include "ui_openwithdialog.h"
namespace Core {
-
-
namespace Internal {
// Present the user with a file name and a list of available
diff --git a/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp b/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
index af41349cff..9e9a8cc428 100644
--- a/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/readonlyfilesdialog.cpp
@@ -33,6 +33,7 @@
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
+#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/stringutils.h>
@@ -45,6 +46,8 @@
#include <QPushButton>
#include <QRadioButton>
+using namespace Utils;
+
namespace Core {
namespace Internal {
@@ -65,8 +68,8 @@ public:
NumberOfColumns
};
- void initDialog(const QStringList &fileNames);
- void promptFailWarning(const QStringList &files, ReadOnlyFilesDialog::ReadOnlyResult type) const;
+ void initDialog(const FilePathList &filePaths);
+ void promptFailWarning(const FilePathList &files, ReadOnlyFilesDialog::ReadOnlyResult type) const;
QRadioButton *createRadioButtonForItem(QTreeWidgetItem *item, QButtonGroup *group, ReadOnlyFilesTreeColumn type);
void setAll(int index);
@@ -77,14 +80,14 @@ public:
// Buttongroups containing the operation for one file.
struct ButtonGroupForFile
{
- QString fileName;
+ FilePath filePath;
QButtonGroup *group;
};
QList <ButtonGroupForFile> buttonGroups;
QMap <int, int> setAllIndexForOperation;
// The version control systems for every file, if the file isn't in VCS the value is 0.
- QHash <QString, IVersionControl*> versionControls;
+ QHash<FilePath, IVersionControl*> versionControls;
// Define if some specific operations should be allowed to make the files writable.
const bool useSaveAs;
@@ -140,19 +143,19 @@ using namespace Internal;
* and Save As which is used to save the changes to a document in another file.
*/
-ReadOnlyFilesDialog::ReadOnlyFilesDialog(const QList<QString> &fileNames, QWidget *parent)
+ReadOnlyFilesDialog::ReadOnlyFilesDialog(const Utils::FilePathList &filePaths, QWidget *parent)
: QDialog(parent)
, d(new ReadOnlyFilesDialogPrivate(this))
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
- d->initDialog(fileNames);
+ d->initDialog(filePaths);
}
-ReadOnlyFilesDialog::ReadOnlyFilesDialog(const QString &fileName, QWidget *parent)
+ReadOnlyFilesDialog::ReadOnlyFilesDialog(const Utils::FilePath &filePath, QWidget *parent)
: QDialog(parent)
, d(new ReadOnlyFilesDialogPrivate(this))
{
- d->initDialog(QStringList(fileName));
+ d->initDialog({filePath});
}
ReadOnlyFilesDialog::ReadOnlyFilesDialog(IDocument *document, QWidget *parent,
@@ -160,16 +163,16 @@ ReadOnlyFilesDialog::ReadOnlyFilesDialog(IDocument *document, QWidget *parent,
: QDialog(parent)
, d(new ReadOnlyFilesDialogPrivate(this, document, displaySaveAs))
{
- d->initDialog(QStringList(document->filePath().toString()));
+ d->initDialog({document->filePath()});
}
ReadOnlyFilesDialog::ReadOnlyFilesDialog(const QList<IDocument *> &documents, QWidget *parent)
: QDialog(parent)
, d(new ReadOnlyFilesDialogPrivate(this))
{
- QStringList files;
- foreach (IDocument *document, documents)
- files << document->filePath().toString();
+ FilePathList files;
+ for (IDocument *document : documents)
+ files << document->filePath();
d->initDialog(files);
}
@@ -202,7 +205,7 @@ void ReadOnlyFilesDialog::setShowFailWarning(bool show, const QString &warning)
* Opens a message box with an error description according to the type.
* \internal
*/
-void ReadOnlyFilesDialogPrivate::promptFailWarning(const QStringList &files, ReadOnlyFilesDialog::ReadOnlyResult type) const
+void ReadOnlyFilesDialogPrivate::promptFailWarning(const FilePathList &files, ReadOnlyFilesDialog::ReadOnlyResult type) const
{
if (files.isEmpty())
return;
@@ -210,7 +213,7 @@ void ReadOnlyFilesDialogPrivate::promptFailWarning(const QStringList &files, Rea
QString message;
QString details;
if (files.count() == 1) {
- const QString file = files.first();
+ const FilePath file = files.first();
switch (type) {
case ReadOnlyFilesDialog::RO_OpenVCS: {
if (IVersionControl *vc = versionControls[file]) {
@@ -218,31 +221,31 @@ void ReadOnlyFilesDialogPrivate::promptFailWarning(const QStringList &files, Rea
title = tr("Failed to %1 File").arg(openText);
message = tr("%1 file %2 from version control system %3 failed.")
.arg(openText)
- .arg(QDir::toNativeSeparators(file))
+ .arg(file.toUserOutput())
.arg(vc->displayName())
- + QLatin1Char('\n')
+ + '\n'
+ failWarning;
} else {
title = tr("No Version Control System Found");
message = tr("Cannot open file %1 from version control system.\n"
"No version control system found.")
- .arg(QDir::toNativeSeparators(file))
- + QLatin1Char('\n')
- + failWarning;;
+ .arg(file.toUserOutput())
+ + '\n'
+ + failWarning;
}
break;
}
case ReadOnlyFilesDialog::RO_MakeWritable:
title = tr("Cannot Set Permissions");
message = tr("Cannot set permissions for %1 to writable.")
- .arg(QDir::toNativeSeparators(file))
- + QLatin1Char('\n')
+ .arg(file.toUserOutput())
+ + '\n'
+ failWarning;
break;
case ReadOnlyFilesDialog::RO_SaveAs:
title = tr("Cannot Save File");
- message = tr("Cannot save file %1").arg(QDir::toNativeSeparators(file))
- + QLatin1Char('\n')
+ message = tr("Cannot save file %1").arg(file.toUserOutput())
+ + '\n'
+ failWarning;
break;
default:
@@ -254,7 +257,7 @@ void ReadOnlyFilesDialogPrivate::promptFailWarning(const QStringList &files, Rea
title = tr("Could Not Change Permissions on Some Files");
message = failWarning + QLatin1Char('\n')
+ tr("See details for a complete list of files.");
- details = files.join(QLatin1Char('\n'));
+ details = Utils::transform(files, &FilePath::toString).join('\n');
}
QMessageBox msgBox(QMessageBox::Warning, title, message,
QMessageBox::Ok, ICore::dialogParent());
@@ -278,34 +281,34 @@ int ReadOnlyFilesDialog::exec()
return RO_Cancel;
ReadOnlyResult result = RO_Cancel;
- QStringList failedToMakeWritable;
- foreach (ReadOnlyFilesDialogPrivate::ButtonGroupForFile buttongroup, d->buttonGroups) {
+ FilePathList failedToMakeWritable;
+ for (ReadOnlyFilesDialogPrivate::ButtonGroupForFile buttongroup : qAsConst(d->buttonGroups)) {
result = static_cast<ReadOnlyResult>(buttongroup.group->checkedId());
switch (result) {
case RO_MakeWritable:
- if (!Utils::FileUtils::makeWritable(Utils::FileName(QFileInfo(buttongroup.fileName)))) {
- failedToMakeWritable << buttongroup.fileName;
+ if (!Utils::FileUtils::makeWritable(buttongroup.filePath)) {
+ failedToMakeWritable << buttongroup.filePath;
continue;
}
break;
case RO_OpenVCS:
- if (!d->versionControls[buttongroup.fileName]->vcsOpen(buttongroup.fileName)) {
- failedToMakeWritable << buttongroup.fileName;
+ if (!d->versionControls[buttongroup.filePath]->vcsOpen(buttongroup.filePath.toString())) {
+ failedToMakeWritable << buttongroup.filePath;
continue;
}
break;
case RO_SaveAs:
if (!EditorManagerPrivate::saveDocumentAs(d->document)) {
- failedToMakeWritable << buttongroup.fileName;
+ failedToMakeWritable << buttongroup.filePath;
continue;
}
break;
default:
- failedToMakeWritable << buttongroup.fileName;
+ failedToMakeWritable << buttongroup.filePath;
continue;
}
- if (!QFileInfo(buttongroup.fileName).isWritable())
- failedToMakeWritable << buttongroup.fileName;
+ if (!buttongroup.filePath.toFileInfo().isWritable())
+ failedToMakeWritable << buttongroup.filePath;
}
if (!failedToMakeWritable.isEmpty()) {
if (d->showWarnings)
@@ -381,11 +384,11 @@ void ReadOnlyFilesDialogPrivate::updateSelectAll()
/*!
* Adds files to the dialog and checks for a possible operation to make the file
* writable.
- * \a fileNames contains the list of the files that should be added to the
+ * \a filePaths contains the list of the files that should be added to the
* dialog.
* \internal
*/
-void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
+void ReadOnlyFilesDialogPrivate::initDialog(const FilePathList &filePaths)
{
ui.setupUi(q);
ui.buttonBox->addButton(tr("Change &Permission"), QDialogButtonBox::AcceptRole);
@@ -394,16 +397,16 @@ void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
QString vcsOpenTextForAll;
QString vcsMakeWritableTextForAll;
bool useMakeWritable = false;
- foreach (const QString &fileName, fileNames) {
- const QFileInfo info = QFileInfo(fileName);
+ for (const FilePath &filePath : filePaths) {
+ const QFileInfo info = filePath.toFileInfo();
const QString visibleName = info.fileName();
const QString directory = info.absolutePath();
// Setup a default entry with filename folder and make writable radio button.
auto item = new QTreeWidgetItem(ui.treeWidget);
item->setText(FileName, visibleName);
- item->setIcon(FileName, FileIconProvider::icon(fileName));
- item->setText(Folder, Utils::FileUtils::shortNativePath(Utils::FileName(QFileInfo(directory))));
+ item->setIcon(FileName, FileIconProvider::icon(info));
+ item->setText(Folder, Utils::FilePath::fromFileInfo(directory).shortNativePath());
auto radioButtonGroup = new QButtonGroup;
// Add a button for opening the file with a version control system
@@ -411,7 +414,7 @@ void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
IVersionControl *versionControlForFile =
VcsManager::findVersionControlForDirectory(directory);
const bool fileManagedByVCS = versionControlForFile
- && versionControlForFile->openSupportMode(fileName) != IVersionControl::NoOpen;
+ && versionControlForFile->openSupportMode(filePath.toString()) != IVersionControl::NoOpen;
if (fileManagedByVCS) {
const QString vcsOpenTextForFile =
Utils::stripAccelerator(versionControlForFile->vcsOpenText());
@@ -429,7 +432,7 @@ void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
vcsMakeWritableTextForAll.clear();
}
// Add make writable if it is supported by the reposetory.
- if (versionControlForFile->openSupportMode(fileName) == IVersionControl::OpenOptional) {
+ if (versionControlForFile->openSupportMode(filePath.toString()) == IVersionControl::OpenOptional) {
useMakeWritable = true;
createRadioButtonForItem(item, radioButtonGroup, MakeWritable);
}
@@ -442,15 +445,12 @@ void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
if (useSaveAs)
createRadioButtonForItem(item, radioButtonGroup, SaveAs);
// If the file is managed by a version control system save the vcs for this file.
- versionControls[fileName] = fileManagedByVCS ? versionControlForFile : nullptr;
+ versionControls[filePath] = fileManagedByVCS ? versionControlForFile : nullptr;
// Also save the buttongroup for every file to get the result for each entry.
- ReadOnlyFilesDialogPrivate::ButtonGroupForFile groupForFile;
- groupForFile.fileName = fileName;
- groupForFile.group = radioButtonGroup;
- buttonGroups.append(groupForFile);
- QObject::connect(radioButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked),
- [this](int) { updateSelectAll(); });
+ buttonGroups.append({filePath, radioButtonGroup});
+ QObject::connect(radioButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked),
+ [this] { updateSelectAll(); });
}
// Apply the Mac file dialog style.
@@ -474,7 +474,7 @@ void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
}
// If there is just one file entry, there is no need to show the select all combo box
- if (fileNames.count() < 2) {
+ if (filePaths.count() < 2) {
ui.setAll->setVisible(false);
ui.setAllLabel->setVisible(false);
ui.verticalLayout->removeItem(ui.setAllLayout);
@@ -508,7 +508,7 @@ void ReadOnlyFilesDialogPrivate::initDialog(const QStringList &fileNames)
ui.setAll->addItem(saveAsText);
setAllIndexForOperation[SaveAs] = ui.setAll->count() - 1;
}
- QObject::connect(ui.setAll, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ QObject::connect(ui.setAll, QOverload<int>::of(&QComboBox::activated),
[this](int index) { setAll(index); });
// Filter which columns should be visible and resize them to content.
diff --git a/src/plugins/coreplugin/dialogs/readonlyfilesdialog.h b/src/plugins/coreplugin/dialogs/readonlyfilesdialog.h
index 6bb9afa7f5..2baf2fa883 100644
--- a/src/plugins/coreplugin/dialogs/readonlyfilesdialog.h
+++ b/src/plugins/coreplugin/dialogs/readonlyfilesdialog.h
@@ -27,6 +27,8 @@
#include <coreplugin/core_global.h>
+#include <utils/fileutils.h>
+
#include <QDialog>
namespace Core {
@@ -57,9 +59,9 @@ public:
RO_SaveAs = SaveAs
};
- explicit ReadOnlyFilesDialog(const QList<QString> &fileNames,
+ explicit ReadOnlyFilesDialog(const Utils::FilePathList &filePaths,
QWidget *parent = nullptr);
- explicit ReadOnlyFilesDialog(const QString &fileName,
+ explicit ReadOnlyFilesDialog(const Utils::FilePath &filePath,
QWidget * parent = nullptr);
explicit ReadOnlyFilesDialog(IDocument *document,
QWidget * parent = nullptr,
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
index f3e476fed3..94c0bbddc1 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
@@ -81,7 +81,7 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent,
<< visibleName << QDir::toNativeSeparators(directory));
if (!fileName.isEmpty())
item->setIcon(0, FileIconProvider::icon(fileName));
- item->setData(0, Qt::UserRole, qVariantFromValue(document));
+ item->setData(0, Qt::UserRole, QVariant::fromValue(document));
}
m_ui.treeWidget->resizeColumnToContents(0);
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.h b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
index 37d321fade..f62af24768 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.h
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
@@ -36,7 +36,6 @@ class IDocument;
namespace Internal {
-
class SaveItemsDialog : public QDialog
{
Q_OBJECT
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
index 596d498875..8057a9e48a 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
@@ -726,7 +726,7 @@ void SettingsDialog::done(int val)
QSettings *settings = ICore::settings();
settings->setValue(QLatin1String(pageKeyC), m_currentPage.toSetting());
- ICore::saveSettings(); // save all settings
+ ICore::saveSettings(ICore::SettingsDialogDone); // save all settings
// exit event loops in reverse order of addition
for (QEventLoop *eventLoop : m_eventLoops)
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
index 675996881d..d740b6ca20 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp
@@ -514,7 +514,7 @@ void ShortcutSettingsWidget::initialize()
if (s->m_cmd->defaultKeySequence() != s->m_key)
setModified(item, true);
- item->setData(0, Qt::UserRole, qVariantFromValue(s));
+ item->setData(0, Qt::UserRole, QVariant::fromValue(s));
markCollisions(s);
}
diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp
index 13b5b42546..933b20bd3f 100644
--- a/src/plugins/coreplugin/documentmanager.cpp
+++ b/src/plugins/coreplugin/documentmanager.cpp
@@ -164,7 +164,7 @@ public:
QFileSystemWatcher *m_linkWatcher = nullptr; // Delayed creation (only UNIX/if a link is seen).
QString m_lastVisitedDirectory = QDir::currentPath();
QString m_defaultLocationForNewFiles;
- FileName m_projectsDirectory;
+ FilePath m_projectsDirectory;
// When we are calling into an IDocument
// we don't want to receive a changed()
// signal
@@ -438,14 +438,14 @@ void DocumentManager::renamedFile(const QString &from, const QString &to)
foreach (IDocument *document, documentsToRename) {
d->m_blockedIDocument = document;
removeFileInfo(document);
- document->setFilePath(FileName::fromString(to));
+ document->setFilePath(FilePath::fromString(to));
addFileInfo(document);
d->m_blockedIDocument = nullptr;
}
emit m_instance->allDocumentsRenamed(from, to);
}
-void DocumentManager::filePathChanged(const FileName &oldName, const FileName &newName)
+void DocumentManager::filePathChanged(const FilePath &oldName, const FilePath &newName)
{
auto doc = qobject_cast<IDocument *>(sender());
QTC_ASSERT(doc, return);
@@ -961,7 +961,7 @@ bool DocumentManager::saveModifiedDocument(IDocument *document, const QString &m
alwaysSaveMessage, alwaysSave, failedToClose);
}
-void DocumentManager::showFilePropertiesDialog(const FileName &filePath)
+void DocumentManager::showFilePropertiesDialog(const FilePath &filePath)
{
FilePropertiesDialog properties(filePath);
properties.exec();
@@ -1340,12 +1340,12 @@ void readSettings()
}
s->beginGroup(QLatin1String(directoryGroupC));
- const FileName settingsProjectDir = FileName::fromString(s->value(QLatin1String(projectDirectoryKeyC),
+ const FilePath settingsProjectDir = FilePath::fromString(s->value(QLatin1String(projectDirectoryKeyC),
QString()).toString());
if (!settingsProjectDir.isEmpty() && settingsProjectDir.toFileInfo().isDir())
d->m_projectsDirectory = settingsProjectDir;
else
- d->m_projectsDirectory = FileName::fromString(PathChooser::homePath());
+ d->m_projectsDirectory = FilePath::fromString(PathChooser::homePath());
d->m_useProjectsDirectory = s->value(QLatin1String(useProjectDirectoryKeyC),
d->m_useProjectsDirectory).toBool();
@@ -1398,7 +1398,7 @@ void DocumentManager::setDefaultLocationForNewFiles(const QString &location)
\sa setProjectsDirectory, setUseProjectsDirectory
*/
-FileName DocumentManager::projectsDirectory()
+FilePath DocumentManager::projectsDirectory()
{
return d->m_projectsDirectory;
}
@@ -1410,7 +1410,7 @@ FileName DocumentManager::projectsDirectory()
\sa projectsDirectory, useProjectsDirectory
*/
-void DocumentManager::setProjectsDirectory(const FileName &directory)
+void DocumentManager::setProjectsDirectory(const FilePath &directory)
{
if (d->m_projectsDirectory != directory) {
d->m_projectsDirectory = directory;
diff --git a/src/plugins/coreplugin/documentmanager.h b/src/plugins/coreplugin/documentmanager.h
index 911e46615a..92323efdc3 100644
--- a/src/plugins/coreplugin/documentmanager.h
+++ b/src/plugins/coreplugin/documentmanager.h
@@ -34,7 +34,7 @@ QT_BEGIN_NAMESPACE
class QStringList;
QT_END_NAMESPACE
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace Core {
@@ -123,7 +123,7 @@ public:
const QString &alwaysSaveMessage = QString(),
bool *alwaysSave = nullptr,
QList<IDocument *> *failedToClose = nullptr);
- static void showFilePropertiesDialog(const Utils::FileName &filePath);
+ static void showFilePropertiesDialog(const Utils::FilePath &filePath);
static QString fileDialogLastVisitedDirectory();
static void setFileDialogLastVisitedDirectory(const QString &);
@@ -136,8 +136,8 @@ public:
static bool useProjectsDirectory();
static void setUseProjectsDirectory(bool);
- static Utils::FileName projectsDirectory();
- static void setProjectsDirectory(const Utils::FileName &directory);
+ static Utils::FilePath projectsDirectory();
+ static void setProjectsDirectory(const Utils::FilePath &directory);
/* Used to notify e.g. the code model to update the given files. Does *not*
lead to any editors to reload or any other editor manager actions. */
@@ -151,7 +151,7 @@ signals:
void allDocumentsRenamed(const QString &from, const QString &to);
/// emitted if one document changed its name e.g. due to save as
void documentRenamed(Core::IDocument *document, const QString &from, const QString &to);
- void projectsDirectoryChanged(const Utils::FileName &directory);
+ void projectsDirectoryChanged(const Utils::FilePath &directory);
private:
explicit DocumentManager(QObject *parent);
@@ -161,7 +161,7 @@ private:
void checkForNewFileName();
void checkForReload();
void changedFile(const QString &file);
- void filePathChanged(const Utils::FileName &oldName, const Utils::FileName &newName);
+ void filePathChanged(const Utils::FilePath &oldName, const Utils::FilePath &newName);
friend class Core::Internal::MainWindow;
friend class Core::Internal::DocumentManagerPrivate;
diff --git a/src/plugins/coreplugin/editormanager/documentmodel.cpp b/src/plugins/coreplugin/editormanager/documentmodel.cpp
index 4cdb055bfc..b3cec42210 100644
--- a/src/plugins/coreplugin/editormanager/documentmodel.cpp
+++ b/src/plugins/coreplugin/editormanager/documentmodel.cpp
@@ -43,7 +43,6 @@
#include <QSet>
#include <QUrl>
-
static Core::Internal::DocumentModelPrivate *d;
namespace Core {
@@ -52,6 +51,10 @@ namespace Internal {
namespace {
bool compare(const DocumentModel::Entry *e1, const DocumentModel::Entry *e2)
{
+ // Pinned files should go at the top.
+ if (e1->pinned != e2->pinned)
+ return e1->pinned;
+
const int cmp = e1->plainDisplayName().localeAwareCompare(e2->plainDisplayName());
return (cmp < 0) || (cmp == 0 && e1->fileName() < e2->fileName());
}
@@ -98,7 +101,7 @@ int DocumentModelPrivate::rowCount(const QModelIndex &parent) const
void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
{
- const Utils::FileName fileName = entry->fileName();
+ const Utils::FilePath fileName = entry->fileName();
QString fixedPath;
if (!fileName.isEmpty())
fixedPath = DocumentManager::filePathKey(fileName.toString(), DocumentManager::ResolveLinks);
@@ -111,7 +114,8 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
previousEntry->isSuspended = false;
delete previousEntry->document;
previousEntry->document = entry->document;
- connect(previousEntry->document, &IDocument::changed, this, &DocumentModelPrivate::itemChanged);
+ connect(previousEntry->document, &IDocument::changed,
+ this, [this, document = previousEntry->document] { itemChanged(document); });
}
delete entry;
entry = nullptr;
@@ -129,7 +133,9 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
disambiguateDisplayNames(entry);
if (!fixedPath.isEmpty())
m_entryByFixedPath[fixedPath] = entry;
- connect(entry->document, &IDocument::changed, this, &DocumentModelPrivate::itemChanged);
+ connect(entry->document, &IDocument::changed, this, [this, document = entry->document] {
+ itemChanged(document);
+ });
endInsertRows();
}
@@ -163,7 +169,7 @@ bool DocumentModelPrivate::disambiguateDisplayNames(DocumentModel::Entry *entry)
bool seenDups = false;
for (int i = 0; i < dupsCount - 1; ++i) {
DynamicEntry &e = dups[i];
- const Utils::FileName myFileName = e->document->filePath();
+ const Utils::FilePath myFileName = e->document->filePath();
if (e->document->isTemporary() || myFileName.isEmpty() || count > 10) {
// path-less entry, append number
e.setNumberedName(++serial);
@@ -172,7 +178,7 @@ bool DocumentModelPrivate::disambiguateDisplayNames(DocumentModel::Entry *entry)
for (int j = i + 1; j < dupsCount; ++j) {
DynamicEntry &e2 = dups[j];
if (e->displayName().compare(e2->displayName(), Utils::HostOsInfo::fileNameCaseSensitivity()) == 0) {
- const Utils::FileName otherFileName = e2->document->filePath();
+ const Utils::FilePath otherFileName = e2->document->filePath();
if (otherFileName.isEmpty())
continue;
seenDups = true;
@@ -196,13 +202,30 @@ bool DocumentModelPrivate::disambiguateDisplayNames(DocumentModel::Entry *entry)
return true;
}
+void DocumentModelPrivate::setPinned(DocumentModel::Entry *entry, bool pinned)
+{
+ if (entry->pinned == pinned)
+ return;
+
+ entry->pinned = pinned;
+ // Ensure that this entry is re-sorted in the list of open documents
+ // now that its pinned state has changed.
+ d->itemChanged(entry->document);
+}
+
QIcon DocumentModelPrivate::lockedIcon()
{
const static QIcon icon = Utils::Icons::LOCKED.icon();
return icon;
}
-Utils::optional<int> DocumentModelPrivate::indexOfFilePath(const Utils::FileName &filePath) const
+QIcon DocumentModelPrivate::pinnedIcon()
+{
+ const static QIcon icon = Utils::Icons::PINNED.icon();
+ return icon;
+}
+
+Utils::optional<int> DocumentModelPrivate::indexOfFilePath(const Utils::FilePath &filePath) const
{
if (filePath.isEmpty())
return Utils::nullopt;
@@ -230,7 +253,7 @@ void DocumentModelPrivate::removeDocument(int idx)
DocumentManager::ResolveLinks);
m_entryByFixedPath.remove(fixedPath);
}
- disconnect(entry->document, &IDocument::changed, this, &DocumentModelPrivate::itemChanged);
+ disconnect(entry->document, &IDocument::changed, this, nullptr);
disambiguateDisplayNames(entry);
delete entry;
}
@@ -307,7 +330,11 @@ QVariant DocumentModelPrivate::data(const QModelIndex &index, int role) const
return name;
}
case Qt::DecorationRole:
- return entry->document->isFileReadOnly() ? lockedIcon() : QIcon();
+ if (entry->document->isFileReadOnly())
+ return lockedIcon();
+ if (entry->pinned)
+ return pinnedIcon();
+ return QIcon();
case Qt::ToolTipRole:
return entry->fileName().isEmpty() ? entry->displayName() : entry->fileName().toUserOutput();
default:
@@ -316,10 +343,8 @@ QVariant DocumentModelPrivate::data(const QModelIndex &index, int role) const
return QVariant();
}
-void DocumentModelPrivate::itemChanged()
+void DocumentModelPrivate::itemChanged(IDocument *document)
{
- auto document = qobject_cast<IDocument *>(sender());
-
const Utils::optional<int> idx = indexOfDocument(document);
if (!idx)
return;
@@ -353,14 +378,19 @@ void DocumentModelPrivate::itemChanged()
// Make sure the entries stay sorted:
auto positions = positionEntry(m_entries, entry);
if (positions.first >= 0 && positions.second >= 0) {
- // Entry did move: remove and add it again.
- beginRemoveRows(QModelIndex(), positions.first + 1, positions.first + 1);
- m_entries.removeAt(positions.first);
- endRemoveRows();
-
- beginInsertRows(QModelIndex(), positions.second + 1, positions.second + 1);
- m_entries.insert(positions.second, entry);
- endInsertRows();
+ // Entry did move: update its position.
+
+ // Account for the <no document> entry.
+ static const int noDocumentEntryOffset = 1;
+ const int fromIndex = positions.first + noDocumentEntryOffset;
+ const int toIndex = positions.second + noDocumentEntryOffset;
+ // Account for the weird requirements of beginMoveRows().
+ const int effectiveToIndex = toIndex > fromIndex ? toIndex + 1 : toIndex;
+ beginMoveRows(QModelIndex(), fromIndex, fromIndex, QModelIndex(), effectiveToIndex);
+
+ m_entries.move(fromIndex - 1, toIndex - 1);
+
+ endMoveRows();
} else {
// Nothing to remove or add: The entry did not move.
QTC_CHECK(positions.first == -1 && positions.second == -1);
@@ -384,15 +414,18 @@ void DocumentModelPrivate::addEditor(IEditor *editor, bool *isNewDocument)
}
}
-void DocumentModelPrivate::addSuspendedDocument(const QString &fileName, const QString &displayName, Id id)
+DocumentModel::Entry *DocumentModelPrivate::addSuspendedDocument(const QString &fileName,
+ const QString &displayName,
+ Id id)
{
auto entry = new DocumentModel::Entry;
entry->document = new IDocument;
- entry->document->setFilePath(Utils::FileName::fromString(fileName));
+ entry->document->setFilePath(Utils::FilePath::fromString(fileName));
entry->document->setPreferredDisplayName(displayName);
entry->document->setId(id);
entry->isSuspended = true;
d->addEntry(entry);
+ return entry;
}
DocumentModel::Entry *DocumentModelPrivate::firstSuspendedEntry()
@@ -433,15 +466,20 @@ void DocumentModelPrivate::removeEntry(DocumentModel::Entry *entry)
d->removeDocument(index);
}
-void DocumentModelPrivate::removeAllSuspendedEntries()
+void DocumentModelPrivate::removeAllSuspendedEntries(PinnedFileRemovalPolicy pinnedFileRemovalPolicy)
{
for (int i = d->m_entries.count()-1; i >= 0; --i) {
- if (d->m_entries.at(i)->isSuspended) {
- int row = i + 1/*<no document>*/;
- d->beginRemoveRows(QModelIndex(), row, row);
- delete d->m_entries.takeAt(i);
- d->endRemoveRows();
- }
+ const DocumentModel::Entry *entry = d->m_entries.at(i);
+ if (!entry->isSuspended)
+ continue;
+
+ if (pinnedFileRemovalPolicy == DoNotRemovePinnedFiles && entry->pinned)
+ continue;
+
+ int row = i + 1/*<no document>*/;
+ d->beginRemoveRows(QModelIndex(), row, row);
+ delete d->m_entries.takeAt(i);
+ d->endRemoveRows();
}
QSet<QString> displayNames;
foreach (DocumentModel::Entry *entry, d->m_entries) {
@@ -480,7 +518,8 @@ void DocumentModelPrivate::DynamicEntry::setNumberedName(int number)
DocumentModel::Entry::Entry() :
document(nullptr),
- isSuspended(false)
+ isSuspended(false),
+ pinned(false)
{
}
@@ -512,7 +551,7 @@ QAbstractItemModel *DocumentModel::model()
return d;
}
-Utils::FileName DocumentModel::Entry::fileName() const
+Utils::FilePath DocumentModel::Entry::fileName() const
{
return document->filePath();
}
@@ -555,7 +594,7 @@ Utils::optional<int> DocumentModel::indexOfDocument(IDocument *document)
return d->indexOfDocument(document);
}
-Utils::optional<int> DocumentModel::indexOfFilePath(const Utils::FileName &filePath)
+Utils::optional<int> DocumentModel::indexOfFilePath(const Utils::FilePath &filePath)
{
return d->indexOfFilePath(filePath);
}
@@ -566,7 +605,7 @@ DocumentModel::Entry *DocumentModel::entryForDocument(IDocument *document)
[&document](Entry *entry) { return entry->document == document; });
}
-DocumentModel::Entry *DocumentModel::entryForFilePath(const Utils::FileName &filePath)
+DocumentModel::Entry *DocumentModel::entryForFilePath(const Utils::FilePath &filePath)
{
const Utils::optional<int> index = d->indexOfFilePath(filePath);
if (!index)
@@ -581,7 +620,7 @@ QList<IDocument *> DocumentModel::openedDocuments()
IDocument *DocumentModel::documentForFilePath(const QString &filePath)
{
- const Utils::optional<int> index = d->indexOfFilePath(Utils::FileName::fromString(filePath));
+ const Utils::optional<int> index = d->indexOfFilePath(Utils::FilePath::fromString(filePath));
if (!index)
return nullptr;
return d->m_entries.at(*index)->document;
diff --git a/src/plugins/coreplugin/editormanager/documentmodel.h b/src/plugins/coreplugin/editormanager/documentmodel.h
index 09bb465272..72b4caeedb 100644
--- a/src/plugins/coreplugin/editormanager/documentmodel.h
+++ b/src/plugins/coreplugin/editormanager/documentmodel.h
@@ -53,14 +53,24 @@ public:
struct CORE_EXPORT Entry {
Entry();
~Entry();
- Utils::FileName fileName() const;
+ Utils::FilePath fileName() const;
QString displayName() const;
QString plainDisplayName() const;
QString uniqueDisplayName() const;
Id id() const;
IDocument *document;
+ // When an entry is suspended, it means that it is not in memory,
+ // and there is no IEditor for it and only a dummy IDocument.
+ // 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
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
+ // files in bulk should not close this one.
+ bool pinned;
};
static Entry *entryAtRow(int row);
@@ -69,9 +79,9 @@ public:
static int entryCount();
static QList<Entry *> entries();
static Utils::optional<int> indexOfDocument(IDocument *document);
- static Utils::optional<int> indexOfFilePath(const Utils::FileName &filePath);
+ static Utils::optional<int> indexOfFilePath(const Utils::FilePath &filePath);
static Entry *entryForDocument(IDocument *document);
- static Entry *entryForFilePath(const Utils::FileName &filePath);
+ static Entry *entryForFilePath(const Utils::FilePath &filePath);
static QList<IDocument *> openedDocuments();
static IDocument *documentForFilePath(const QString &filePath);
diff --git a/src/plugins/coreplugin/editormanager/documentmodel_p.h b/src/plugins/coreplugin/editormanager/documentmodel_p.h
index 10f8ebfb4d..e5d7fa2a2c 100644
--- a/src/plugins/coreplugin/editormanager/documentmodel_p.h
+++ b/src/plugins/coreplugin/editormanager/documentmodel_p.h
@@ -58,20 +58,30 @@ public:
void addEntry(DocumentModel::Entry *entry);
void removeDocument(int idx);
- Utils::optional<int> indexOfFilePath(const Utils::FileName &filePath) const;
+ Utils::optional<int> indexOfFilePath(const Utils::FilePath &filePath) const;
Utils::optional<int> indexOfDocument(IDocument *document) const;
bool disambiguateDisplayNames(DocumentModel::Entry *entry);
+ static void setPinned(DocumentModel::Entry *entry, bool pinned);
+
static QIcon lockedIcon();
+ static QIcon pinnedIcon();
static void addEditor(IEditor *editor, bool *isNewDocument);
- static void addSuspendedDocument(const QString &fileName, const QString &displayName, Id id);
+ static DocumentModel::Entry *addSuspendedDocument(const QString &fileName,
+ const QString &displayName,
+ Id id);
static DocumentModel::Entry *firstSuspendedEntry();
static DocumentModel::Entry *removeEditor(IEditor *editor);
static void removeEntry(DocumentModel::Entry *entry);
- static void removeAllSuspendedEntries();
+ enum PinnedFileRemovalPolicy {
+ DoNotRemovePinnedFiles,
+ RemovePinnedFiles
+ };
+ static void removeAllSuspendedEntries(PinnedFileRemovalPolicy pinnedFileRemovalPolicy
+ = RemovePinnedFiles);
- void itemChanged();
+ void itemChanged(IDocument *document);
class DynamicEntry
{
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 1dc2236873..f1073e6bb2 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -214,9 +214,10 @@ EditorManagerPrivate::EditorManagerPrivate(QObject *parent) :
m_closeOtherDocumentsContextAction(new QAction(EditorManager::tr("Close Others"), this)),
m_closeAllEditorsExceptVisibleContextAction(new QAction(EditorManager::tr("Close All Except Visible"), this)),
m_openGraphicalShellAction(new QAction(FileUtils::msgGraphicalShellAction(), this)),
- m_openTerminalAction(new QAction(FileUtils::msgTerminalAction(), this)),
+ m_openTerminalAction(new QAction(FileUtils::msgTerminalHereAction(), this)),
m_findInDirectoryAction(new QAction(FileUtils::msgFindInDirectory(), this)),
- m_filePropertiesAction(new QAction(tr("Properties..."), this))
+ m_filePropertiesAction(new QAction(tr("Properties..."), this)),
+ m_pinAction(new QAction(tr("Pin"), this))
{
d = this;
}
@@ -302,8 +303,7 @@ void EditorManagerPrivate::init()
cmd = ActionManager::registerAction(m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext, true);
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+W")));
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
- connect(m_closeAllEditorsAction, &QAction::triggered,
- m_instance, []() { EditorManager::closeAllEditors(); });
+ connect(m_closeAllEditorsAction, &QAction::triggered, m_instance, &EditorManager::closeAllDocuments);
// Close All Others Action
cmd = ActionManager::registerAction(m_closeOtherDocumentsAction, Constants::CLOSEOTHERS, editManagerContext, true);
@@ -334,7 +334,7 @@ void EditorManagerPrivate::init()
// Close XXX Context Actions
connect(m_closeAllEditorsContextAction, &QAction::triggered,
- m_instance, []() { EditorManager::closeAllEditors(); });
+ m_instance, &EditorManager::closeAllDocuments);
connect(m_closeCurrentEditorContextAction, &QAction::triggered,
this, &EditorManagerPrivate::closeEditorFromContextMenu);
connect(m_closeOtherDocumentsContextAction, &QAction::triggered,
@@ -352,6 +352,7 @@ void EditorManagerPrivate::init()
return;
DocumentManager::showFilePropertiesDialog(d->m_contextMenuEntry->fileName());
});
+ connect(m_pinAction, &QAction::triggered, this, &EditorManagerPrivate::togglePinned);
// Goto Previous In History Action
cmd = ActionManager::registerAction(m_gotoPreviousDocHistoryAction, Constants::GOTOPREVINHISTORY, editDesignContext);
@@ -537,7 +538,7 @@ bool EditorManagerPrivate::skipOpeningBigTextFile(const QString &filePath)
messageBox.setText(text);
messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::No);
messageBox.setDefaultButton(QDialogButtonBox::No);
- messageBox.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question));
+ messageBox.setIcon(QMessageBox::Question);
messageBox.setCheckBoxVisible(true);
messageBox.setCheckBoxText(CheckableMessageBox::msgDoNotAskAgain());
messageBox.exec();
@@ -607,7 +608,7 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN
Utils::MimeType mimeType = Utils::mimeTypeForFile(fn);
QMessageBox msgbox(QMessageBox::Critical, EditorManager::tr("File Error"),
tr("Could not open \"%1\": Cannot open files of type \"%2\".")
- .arg(FileName::fromString(realFn).toUserOutput(), mimeType.name()),
+ .arg(FilePath::fromString(realFn).toUserOutput(), mimeType.name()),
QMessageBox::Ok, ICore::dialogParent());
msgbox.exec();
return nullptr;
@@ -649,7 +650,7 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN
tr("Could not open \"%1\" for reading. "
"Either the file does not exist or you do not have "
"the permissions to open it.")
- .arg(FileName::fromString(realFn).toUserOutput()),
+ .arg(FilePath::fromString(realFn).toUserOutput()),
QMessageBox::Ok, ICore::dialogParent());
msgbox.exec();
return nullptr;
@@ -658,7 +659,7 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN
if (errorString.isEmpty()) {
errorString = tr("Could not open \"%1\": Unknown error.")
- .arg(FileName::fromString(realFn).toUserOutput());
+ .arg(FilePath::fromString(realFn).toUserOutput());
}
QMessageBox msgbox(QMessageBox::Critical, EditorManager::tr("File Error"), errorString, QMessageBox::Open | QMessageBox::Cancel, ICore::mainWindow());
@@ -1206,12 +1207,14 @@ void EditorManagerPrivate::addEditor(IEditor *editor)
bool isNewDocument = false;
DocumentModelPrivate::addEditor(editor, &isNewDocument);
if (isNewDocument) {
- const bool isTemporary = editor->document()->isTemporary();
+ IDocument *document = editor->document();
+ const bool isTemporary = document->isTemporary();
const bool addWatcher = !isTemporary;
- DocumentManager::addDocument(editor->document(), addWatcher);
+ DocumentManager::addDocument(document, addWatcher);
if (!isTemporary)
- DocumentManager::addToRecentFiles(editor->document()->filePath().toString(),
- editor->document()->id());
+ DocumentManager::addToRecentFiles(document->filePath().toString(),
+ document->id());
+ emit m_instance->documentOpened(document);
}
emit m_instance->editorOpened(editor);
QTimer::singleShot(0, d, &EditorManagerPrivate::autoSuspendDocuments);
@@ -1222,9 +1225,11 @@ void EditorManagerPrivate::removeEditor(IEditor *editor, bool removeSuspendedEnt
DocumentModel::Entry *entry = DocumentModelPrivate::removeEditor(editor);
QTC_ASSERT(entry, return);
if (entry->isSuspended) {
- DocumentManager::removeDocument(editor->document());
+ IDocument *document = editor->document();
+ DocumentManager::removeDocument(document);
if (removeSuspendedEntry)
DocumentModelPrivate::removeEntry(entry);
+ emit m_instance->documentClosed(document);
}
ICore::removeContextObject(editor);
}
@@ -2213,8 +2218,13 @@ bool EditorManagerPrivate::saveDocumentAs(IDocument *document)
void EditorManagerPrivate::closeAllEditorsExceptVisible()
{
- DocumentModelPrivate::removeAllSuspendedEntries();
+ DocumentModelPrivate::removeAllSuspendedEntries(DocumentModelPrivate::DoNotRemovePinnedFiles);
QList<IDocument *> documentsToClose = DocumentModel::openedDocuments();
+ // Remove all pinned files from the list of files to close.
+ documentsToClose = Utils::filtered(documentsToClose, [](IDocument *document) {
+ DocumentModel::Entry *entry = DocumentModel::entryForDocument(document);
+ return !entry->pinned;
+ });
foreach (IEditor *editor, EditorManager::visibleEditors())
documentsToClose.removeAll(editor->document());
EditorManager::closeDocuments(documentsToClose, true);
@@ -2296,11 +2306,20 @@ void EditorManagerPrivate::findInDirectory()
{
if (!d->m_contextMenuEntry || d->m_contextMenuEntry->fileName().isEmpty())
return;
- const FileName path = d->m_contextMenuEntry->fileName();
+ const FilePath path = d->m_contextMenuEntry->fileName();
emit m_instance->findOnFileSystemRequest(
(path.toFileInfo().isDir() ? path : path.parentDir()).toString());
}
+void EditorManagerPrivate::togglePinned()
+{
+ if (!d->m_contextMenuEntry || d->m_contextMenuEntry->fileName().isEmpty())
+ return;
+
+ const bool currentlyPinned = d->m_contextMenuEntry->pinned;
+ DocumentModelPrivate::setPinned(d->m_contextMenuEntry, !currentlyPinned);
+}
+
void EditorManagerPrivate::split(Qt::Orientation orientation)
{
EditorView *view = currentEditorView();
@@ -2399,12 +2418,25 @@ bool EditorManager::closeAllEditors(bool askAboutModifiedEditors)
void EditorManager::closeOtherDocuments(IDocument *document)
{
- DocumentModelPrivate::removeAllSuspendedEntries();
+ DocumentModelPrivate::removeAllSuspendedEntries(DocumentModelPrivate::DoNotRemovePinnedFiles);
QList<IDocument *> documentsToClose = DocumentModel::openedDocuments();
+ // Remove all pinned files from the list of files to close.
+ documentsToClose = Utils::filtered(documentsToClose, [](IDocument *document) {
+ DocumentModel::Entry *entry = DocumentModel::entryForDocument(document);
+ return !entry->pinned;
+ });
documentsToClose.removeAll(document);
closeDocuments(documentsToClose, true);
}
+bool EditorManager::closeAllDocuments()
+{
+ // Only close the files that aren't pinned.
+ const QList<DocumentModel::Entry *> entriesToClose
+ = Utils::filtered(DocumentModel::entries(), Utils::equal(&DocumentModel::Entry::pinned, false));
+ return EditorManager::closeDocuments(entriesToClose);
+}
+
// SLOT connected to action
void EditorManager::slotCloseCurrentEditorOrDocument()
{
@@ -2435,7 +2467,7 @@ void EditorManager::addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentMod
d->m_contextMenuEntry = entry;
d->m_contextMenuEditor = editor;
- const FileName filePath = entry ? entry->fileName() : FileName();
+ const FilePath filePath = entry ? entry->fileName() : FilePath();
const bool copyActionsEnabled = !filePath.isEmpty();
d->m_copyFilePathContextAction->setEnabled(copyActionsEnabled);
d->m_copyLocationContextAction->setEnabled(copyActionsEnabled);
@@ -2486,6 +2518,20 @@ void EditorManager::addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentMod
contextMenu->addAction(d->m_closeAllEditorsExceptVisibleContextAction);
}
+void EditorManager::addPinEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry)
+{
+ const QString quotedDisplayName = entry ? Utils::quoteAmpersands(entry->displayName()) : QString();
+ if (entry) {
+ d->m_pinAction->setText(entry->pinned
+ ? tr("Unpin \"%1\"").arg(quotedDisplayName)
+ : tr("Pin \"%1\"").arg(quotedDisplayName));
+ } else {
+ d->m_pinAction->setText(tr("Pin Editor"));
+ }
+ d->m_pinAction->setEnabled(entry != nullptr);
+ contextMenu->addAction(d->m_pinAction);
+}
+
void EditorManager::addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry)
{
QTC_ASSERT(contextMenu, return);
@@ -2585,6 +2631,20 @@ void EditorManager::closeDocument(DocumentModel::Entry *entry)
closeDocuments({entry->document});
}
+bool EditorManager::closeDocuments(const QList<DocumentModel::Entry *> &entries)
+{
+ QList<IDocument *> documentsToClose;
+ for (DocumentModel::Entry *entry : entries) {
+ if (!entry)
+ continue;
+ if (entry->isSuspended)
+ DocumentModelPrivate::removeEntry(entry);
+ else
+ documentsToClose << entry->document;
+ }
+ return closeDocuments(documentsToClose);
+}
+
bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool askAboutModifiedEditors)
{
return EditorManagerPrivate::closeEditors(editorsToClose,
@@ -2904,13 +2964,13 @@ QVector<EditorWindow *> editorWindows(const QList<EditorArea *> &areas)
return result;
}
-// Save state of all non-teporary editors.
+// Save state of all non-temporary editors.
QByteArray EditorManager::saveState()
{
QByteArray bytes;
QDataStream stream(&bytes, QIODevice::WriteOnly);
- stream << QByteArray("EditorManagerV4");
+ stream << QByteArray("EditorManagerV5");
// TODO: In case of split views it's not possible to restore these for all correctly with this
QList<IDocument *> documents = DocumentModel::openedDocuments();
@@ -2936,8 +2996,10 @@ QByteArray EditorManager::saveState()
stream << entriesCount;
foreach (DocumentModel::Entry *entry, entries) {
- if (!entry->document->isTemporary())
- stream << entry->fileName().toString() << entry->plainDisplayName() << entry->id();
+ if (!entry->document->isTemporary()) {
+ stream << entry->fileName().toString() << entry->plainDisplayName() << entry->id()
+ << entry->pinned;
+ }
}
stream << d->m_editorAreas.first()->saveState(); // TODO
@@ -2962,7 +3024,8 @@ bool EditorManager::restoreState(const QByteArray &state)
QByteArray version;
stream >> version;
- if (version != "EditorManagerV4")
+ const bool isVersion5 = version == "EditorManagerV5";
+ if (version != "EditorManagerV4" && !isVersion5)
return false;
QApplication::setOverrideCursor(Qt::WaitCursor);
@@ -2978,16 +3041,22 @@ bool EditorManager::restoreState(const QByteArray &state)
stream >> displayName;
Id id;
stream >> id;
+ bool pinned = false;
+ if (isVersion5)
+ stream >> pinned;
if (!fileName.isEmpty() && !displayName.isEmpty()) {
QFileInfo fi(fileName);
if (!fi.exists())
continue;
QFileInfo rfi(autoSaveName(fileName));
- if (rfi.exists() && fi.lastModified() < rfi.lastModified())
- openEditor(fileName, id, DoNotMakeVisible);
- else
- DocumentModelPrivate::addSuspendedDocument(fileName, displayName, id);
+ if (rfi.exists() && fi.lastModified() < rfi.lastModified()) {
+ if (IEditor *editor = openEditor(fileName, id, DoNotMakeVisible))
+ DocumentModelPrivate::setPinned(DocumentModel::entryForDocument(editor->document()), pinned);
+ } else {
+ if (DocumentModel::Entry *entry = DocumentModelPrivate::addSuspendedDocument(fileName, displayName, id))
+ DocumentModelPrivate::setPinned(entry, pinned);
+ }
}
}
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 6cd9dd88a1..5be379ceb2 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -128,7 +128,9 @@ public:
static bool closeDocument(IDocument *document, bool askAboutModifiedEditors = true);
static bool closeDocuments(const QList<IDocument *> &documents, bool askAboutModifiedEditors = true);
static void closeDocument(DocumentModel::Entry *entry);
+ static bool closeDocuments(const QList<DocumentModel::Entry *> &entries);
static void closeOtherDocuments(IDocument *document);
+ static bool closeAllDocuments();
static void addCurrentPositionToNavigationHistory(const QByteArray &saveState = QByteArray());
static void cutForwardNavigationHistory();
@@ -161,6 +163,7 @@ public:
static void addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry,
IEditor *editor = nullptr);
+ static void addPinEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry);
static void addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry);
static void populateOpenWithMenu(QMenu *menu, const QString &fileName);
@@ -174,10 +177,12 @@ signals:
void documentStateChanged(Core::IDocument *document);
void editorCreated(Core::IEditor *editor, const QString &fileName);
void editorOpened(Core::IEditor *editor);
+ void documentOpened(Core::IDocument *document);
void editorAboutToClose(Core::IEditor *editor);
void editorsClosed(QList<Core::IEditor *> editors);
+ void documentClosed(Core::IDocument *document);
void findOnFileSystemRequest(const QString &path);
- void openFileProperties(const Utils::FileName &path);
+ void openFileProperties(const Utils::FilePath &path);
void aboutToSave(IDocument *document);
void saved(IDocument *document);
void autoSaved();
diff --git a/src/plugins/coreplugin/editormanager/editormanager_p.h b/src/plugins/coreplugin/editormanager/editormanager_p.h
index b9e021bcb8..4dd7f62e31 100644
--- a/src/plugins/coreplugin/editormanager/editormanager_p.h
+++ b/src/plugins/coreplugin/editormanager/editormanager_p.h
@@ -180,6 +180,8 @@ private:
static void openTerminal();
static void findInDirectory();
+ static void togglePinned();
+
static void removeCurrentSplit();
static void setCurrentEditorFromContextChange();
@@ -251,6 +253,7 @@ private:
QAction *m_openTerminalAction;
QAction *m_findInDirectoryAction;
QAction *m_filePropertiesAction = nullptr;
+ QAction *m_pinAction = nullptr;
DocumentModel::Entry *m_contextMenuEntry = nullptr;
IEditor *m_contextMenuEditor = nullptr;
diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp
index aea929a3aa..d38923be38 100644
--- a/src/plugins/coreplugin/editormanager/editorview.cpp
+++ b/src/plugins/coreplugin/editormanager/editorview.cpp
@@ -268,7 +268,7 @@ void EditorView::updateEditorHistory(IEditor *editor, QList<EditLocation> &histo
const EditLocation &item = history.at(i);
if (item.document == document
|| (!item.document
- && !DocumentModel::indexOfFilePath(FileName::fromString(item.fileName)))) {
+ && !DocumentModel::indexOfFilePath(FilePath::fromString(item.fileName)))) {
history.removeAt(i--);
}
}
diff --git a/src/plugins/coreplugin/editormanager/openeditorsview.cpp b/src/plugins/coreplugin/editormanager/openeditorsview.cpp
index 234fe28e5a..a467e089be 100644
--- a/src/plugins/coreplugin/editormanager/openeditorsview.cpp
+++ b/src/plugins/coreplugin/editormanager/openeditorsview.cpp
@@ -115,10 +115,12 @@ void OpenEditorsWidget::contextMenuRequested(QPoint pos)
{
QMenu contextMenu;
QModelIndex editorIndex = indexAt(pos);
- DocumentModel::Entry *entry = DocumentModel::entryAtRow(
- m_model->mapToSource(editorIndex).row());
+ const int row = m_model->mapToSource(editorIndex).row();
+ DocumentModel::Entry *entry = DocumentModel::entryAtRow(row);
EditorManager::addSaveAndCloseEditorActions(&contextMenu, entry);
contextMenu.addSeparator();
+ EditorManager::addPinEditorActions(&contextMenu, entry);
+ contextMenu.addSeparator();
EditorManager::addNativeDirAndOpenWithActions(&contextMenu, entry);
contextMenu.exec(mapToGlobal(pos));
}
diff --git a/src/plugins/coreplugin/editormanager/openeditorswindow.cpp b/src/plugins/coreplugin/editormanager/openeditorswindow.cpp
index d766531f51..ad1775f9d2 100644
--- a/src/plugins/coreplugin/editormanager/openeditorswindow.cpp
+++ b/src/plugins/coreplugin/editormanager/openeditorswindow.cpp
@@ -217,7 +217,7 @@ static DocumentModel::Entry *entryForEditLocation(const EditLocation &item)
{
if (!item.document.isNull())
return DocumentModel::entryForDocument(item.document);
- return DocumentModel::entryForFilePath(Utils::FileName::fromString(item.fileName));
+ return DocumentModel::entryForFilePath(Utils::FilePath::fromString(item.fileName));
}
void OpenEditorsWindow::addHistoryItems(const QList<EditLocation> &history, EditorView *view,
diff --git a/src/plugins/coreplugin/editortoolbar.cpp b/src/plugins/coreplugin/editortoolbar.cpp
index c23aaa49d2..9d19415e45 100644
--- a/src/plugins/coreplugin/editortoolbar.cpp
+++ b/src/plugins/coreplugin/editortoolbar.cpp
@@ -128,7 +128,6 @@ EditorToolBar::EditorToolBar(QWidget *parent) :
d->m_defaultToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
d->m_activeToolBar = d->m_defaultToolBar;
- d->m_lockButton->setAutoRaise(true);
d->m_lockButton->setEnabled(false);
d->m_dragHandle->setProperty("noArrow", true);
@@ -149,7 +148,6 @@ EditorToolBar::EditorToolBar(QWidget *parent) :
d->m_editorList->setMaxVisibleItems(40);
d->m_editorList->setContextMenuPolicy(Qt::CustomContextMenu);
- d->m_closeEditorButton->setAutoRaise(true);
d->m_closeEditorButton->setIcon(Utils::Icons::CLOSE_TOOLBAR.icon());
d->m_closeEditorButton->setEnabled(false);
d->m_closeEditorButton->setProperty("showborder", true);
@@ -170,7 +168,6 @@ EditorToolBar::EditorToolBar(QWidget *parent) :
splitMenu->addAction(d->m_splitNewWindowAction);
d->m_splitButton->setMenu(splitMenu);
- d->m_closeSplitButton->setAutoRaise(true);
d->m_closeSplitButton->setIcon(Utils::Icons::CLOSE_SPLIT_BOTTOM.icon());
auto toplayout = new QHBoxLayout(this);
@@ -190,7 +187,7 @@ EditorToolBar::EditorToolBar(QWidget *parent) :
// this signal is disconnected for standalone toolbars and replaced with
// a private slot connection
- connect(d->m_editorList, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(d->m_editorList, QOverload<int>::of(&QComboBox::activated),
this, &EditorToolBar::listSelectionActivated);
connect(d->m_editorList, &QComboBox::customContextMenuRequested, [this](QPoint p) {
@@ -303,9 +300,9 @@ void EditorToolBar::setToolbarCreationFlags(ToolbarCreationFlags flags)
this,
&EditorToolBar::setCurrentEditor);
- disconnect(d->m_editorList, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ disconnect(d->m_editorList, QOverload<int>::of(&QComboBox::activated),
this, &EditorToolBar::listSelectionActivated);
- connect(d->m_editorList, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(d->m_editorList, QOverload<int>::of(&QComboBox::activated),
this, &EditorToolBar::changeActiveEditor);
d->m_splitButton->setVisible(false);
d->m_closeSplitButton->setVisible(false);
@@ -347,6 +344,8 @@ void EditorToolBar::fillListContextMenu(QMenu *menu)
: nullptr;
EditorManager::addSaveAndCloseEditorActions(menu, entry, editor);
menu->addSeparator();
+ EditorManager::addPinEditorActions(menu, entry);
+ menu->addSeparator();
EditorManager::addNativeDirAndOpenWithActions(menu, entry);
}
}
diff --git a/src/plugins/coreplugin/externaltool.cpp b/src/plugins/coreplugin/externaltool.cpp
index 15f7a97660..b339dddd3d 100644
--- a/src/plugins/coreplugin/externaltool.cpp
+++ b/src/plugins/coreplugin/externaltool.cpp
@@ -654,7 +654,7 @@ void ExternalToolRunner::run()
}
m_process = new QtcProcess(this);
connect(m_process, &QProcess::started, this, &ExternalToolRunner::started);
- connect(m_process, static_cast<void (QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &ExternalToolRunner::finished);
connect(m_process, &QProcess::errorOccurred, this, &ExternalToolRunner::error);
connect(m_process, &QProcess::readyReadStandardOutput,
@@ -663,7 +663,7 @@ void ExternalToolRunner::run()
this, &ExternalToolRunner::readStandardError);
if (!m_resolvedWorkingDirectory.isEmpty())
m_process->setWorkingDirectory(m_resolvedWorkingDirectory);
- m_process->setCommand(m_resolvedExecutable.toString(), m_resolvedArguments);
+ m_process->setCommand(CommandLine(m_resolvedExecutable, m_resolvedArguments));
m_process->setEnvironment(m_resolvedEnvironment);
MessageManager::write(tr("Starting external tool \"%1\" %2")
.arg(m_resolvedExecutable.toUserOutput(), m_resolvedArguments),
diff --git a/src/plugins/coreplugin/externaltool.h b/src/plugins/coreplugin/externaltool.h
index b41ae450f2..394ee091a5 100644
--- a/src/plugins/coreplugin/externaltool.h
+++ b/src/plugins/coreplugin/externaltool.h
@@ -145,7 +145,7 @@ private:
bool resolve();
const ExternalTool *m_tool; // is a copy of the tool that was passed in
- Utils::FileName m_resolvedExecutable;
+ Utils::FilePath m_resolvedExecutable;
QString m_resolvedArguments;
QString m_resolvedInput;
QString m_resolvedWorkingDirectory;
diff --git a/src/plugins/coreplugin/fancyactionbar.cpp b/src/plugins/coreplugin/fancyactionbar.cpp
index 8d496ea3d2..d332817f62 100644
--- a/src/plugins/coreplugin/fancyactionbar.cpp
+++ b/src/plugins/coreplugin/fancyactionbar.cpp
@@ -102,19 +102,19 @@ static QVector<QString> splitInTwoLines(const QString &text,
nextSplitPos = rx.lastIndexIn(text, nextSplitPos - text.length() - 1);
if (nextSplitPos != -1) {
int splitCandidate = nextSplitPos + rx.matchedLength();
- if (fontMetrics.width(text.mid(splitCandidate)) <= availableWidth)
+ if (fontMetrics.horizontalAdvance(text.mid(splitCandidate)) <= availableWidth)
splitPos = splitCandidate;
else
break;
}
- } while (nextSplitPos > 0 && fontMetrics.width(text.left(nextSplitPos)) > availableWidth);
+ } while (nextSplitPos > 0 && fontMetrics.horizontalAdvance(text.left(nextSplitPos)) > availableWidth);
// check if we could split at white space at all
if (splitPos < 0) {
splitLines[0] = fontMetrics.elidedText(text, Qt::ElideRight, int(availableWidth));
QString common = Utils::commonPrefix(QStringList({splitLines[0], text}));
splitLines[1] = text.mid(common.length());
// elide the second line even if it fits, since it is cut off in mid-word
- while (fontMetrics.width(QChar(0x2026) /*'...'*/ + splitLines[1]) > availableWidth
+ while (fontMetrics.horizontalAdvance(QChar(0x2026) /*'...'*/ + splitLines[1]) > availableWidth
&& splitLines[1].length() > 3
/*keep at least three original characters (should not happen)*/) {
splitLines[1].remove(0, 1);
@@ -222,7 +222,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
painter.setFont(boldFont);
QVector<QString> splitBuildConfiguration(2);
const QString buildConfiguration = defaultAction()->property("subtitle").toString();
- if (boldFm.width(buildConfiguration) <= availableWidth)
+ if (boldFm.horizontalAdvance(buildConfiguration) <= availableWidth)
// text fits in one line
splitBuildConfiguration[0] = buildConfiguration;
else
diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp
index 0653d8639c..684b47bd15 100644
--- a/src/plugins/coreplugin/fancytabwidget.cpp
+++ b/src/plugins/coreplugin/fancytabwidget.cpp
@@ -98,7 +98,7 @@ QSize FancyTabBar::tabSizeHint(bool minimum) const
const int width = 60 + spacing + 2;
int maxLabelwidth = 0;
for (auto tab : qAsConst(m_tabs)) {
- const int width = fm.width(tab->text);
+ const int width = fm.horizontalAdvance(tab->text);
if (width > maxLabelwidth)
maxLabelwidth = width;
}
diff --git a/src/plugins/coreplugin/fileutils.cpp b/src/plugins/coreplugin/fileutils.cpp
index 157dde7477..223cc70cf6 100644
--- a/src/plugins/coreplugin/fileutils.cpp
+++ b/src/plugins/coreplugin/fileutils.cpp
@@ -69,7 +69,7 @@ void FileUtils::showInGraphicalShell(QWidget *parent, const QString &pathIn)
const QFileInfo fileInfo(pathIn);
// Mac, Windows support folder or file.
if (HostOsInfo::isWindowsHost()) {
- const FileName explorer = Environment::systemEnvironment().searchInPath(QLatin1String("explorer.exe"));
+ const FilePath explorer = Environment::systemEnvironment().searchInPath(QLatin1String("explorer.exe"));
if (explorer.isEmpty()) {
QMessageBox::warning(parent,
QApplication::translate("Core::Internal",
@@ -135,13 +135,20 @@ QString FileUtils::msgGraphicalShellAction()
return QApplication::translate("Core::Internal", "Show Containing Folder");
}
-QString FileUtils::msgTerminalAction()
+QString FileUtils::msgTerminalHereAction()
{
if (HostOsInfo::isWindowsHost())
return QApplication::translate("Core::Internal", "Open Command Prompt Here");
return QApplication::translate("Core::Internal", "Open Terminal Here");
}
+QString FileUtils::msgTerminalWithAction()
+{
+ if (HostOsInfo::isWindowsHost())
+ return QApplication::translate("Core::Internal", "Open Command Prompt With");
+ return QApplication::translate("Core::Internal", "Open Terminal With");
+}
+
void FileUtils::removeFile(const QString &filePath, bool deleteFromFS)
{
// remove from version control
diff --git a/src/plugins/coreplugin/fileutils.h b/src/plugins/coreplugin/fileutils.h
index c7746251c1..0067d1d728 100644
--- a/src/plugins/coreplugin/fileutils.h
+++ b/src/plugins/coreplugin/fileutils.h
@@ -44,7 +44,8 @@ struct CORE_EXPORT FileUtils
static QString msgFindInDirectory();
// Platform-dependent action descriptions
static QString msgGraphicalShellAction();
- static QString msgTerminalAction();
+ static QString msgTerminalHereAction();
+ static QString msgTerminalWithAction();
// File operations aware of version control and file system case-insensitiveness
static void removeFile(const QString &filePath, bool deleteFromFS);
static bool renameFile(const QString &from, const QString &to);
diff --git a/src/plugins/coreplugin/find/find.pri b/src/plugins/coreplugin/find/find.pri
index 41005912fb..811f20a5c0 100644
--- a/src/plugins/coreplugin/find/find.pri
+++ b/src/plugins/coreplugin/find/find.pri
@@ -8,6 +8,7 @@ HEADERS += \
$$PWD/ifindfilter.h \
$$PWD/ifindsupport.h \
$$PWD/itemviewfind.h \
+ $$PWD/optionspopup.h \
$$PWD/searchresultcolor.h \
$$PWD/searchresulttreeitemdelegate.h \
$$PWD/searchresulttreeitemroles.h \
@@ -29,6 +30,7 @@ SOURCES += \
$$PWD/ifindfilter.cpp \
$$PWD/ifindsupport.cpp \
$$PWD/itemviewfind.cpp \
+ $$PWD/optionspopup.cpp \
$$PWD/searchresulttreeitemdelegate.cpp \
$$PWD/searchresulttreeitems.cpp \
$$PWD/searchresulttreemodel.cpp \
diff --git a/src/plugins/coreplugin/find/findtoolbar.cpp b/src/plugins/coreplugin/find/findtoolbar.cpp
index 4307ba388d..72a2d23e3c 100644
--- a/src/plugins/coreplugin/find/findtoolbar.cpp
+++ b/src/plugins/coreplugin/find/findtoolbar.cpp
@@ -26,6 +26,7 @@
#include "findtoolbar.h"
#include "ifindfilter.h"
#include "findplugin.h"
+#include "optionspopup.h"
#include <coreplugin/coreicons.h>
#include <coreplugin/coreplugin.h>
@@ -118,8 +119,7 @@ FindToolBar::FindToolBar(CurrentDocumentFind *currentDocumentFind)
this, &FindToolBar::invokeFindEnter, Qt::QueuedConnection);
connect(m_ui.replaceEdit, &Utils::FancyLineEdit::returnPressed,
this, &FindToolBar::invokeReplaceEnter, Qt::QueuedConnection);
- connect(m_findCompleter,
- static_cast<void (QCompleter::*)(const QModelIndex &)>(&QCompleter::activated),
+ connect(m_findCompleter, QOverload<const QModelIndex &>::of(&QCompleter::activated),
this, &FindToolBar::findCompleterActivated);
auto shiftEnterAction = new QAction(m_ui.findEdit);
@@ -660,7 +660,8 @@ void FindToolBar::findFlagsChanged()
void FindToolBar::findEditButtonClicked()
{
- auto popup = new OptionsPopup(m_ui.findEdit);
+ auto popup = new OptionsPopup(m_ui.findEdit, {Constants::CASE_SENSITIVE, Constants::WHOLE_WORDS,
+ Constants::REGULAR_EXPRESSIONS, Constants::PRESERVE_CASE});
popup->show();
}
@@ -1015,71 +1016,5 @@ void FindToolBar::updateReplaceEnabled()
m_replacePreviousAction->setEnabled(globalsEnabled);
}
-OptionsPopup::OptionsPopup(QWidget *parent)
- : QWidget(parent, Qt::Popup)
-{
- setAttribute(Qt::WA_DeleteOnClose);
- auto layout = new QVBoxLayout(this);
- layout->setContentsMargins(2, 2, 2, 2);
- layout->setSpacing(2);
- setLayout(layout);
- QCheckBox *firstCheckBox = createCheckboxForCommand(Constants::CASE_SENSITIVE);
- layout->addWidget(firstCheckBox);
- layout->addWidget(createCheckboxForCommand(Constants::WHOLE_WORDS));
- layout->addWidget(createCheckboxForCommand(Constants::REGULAR_EXPRESSIONS));
- layout->addWidget(createCheckboxForCommand(Constants::PRESERVE_CASE));
- firstCheckBox->setFocus();
- move(parent->mapToGlobal(QPoint(0, -sizeHint().height())));
-}
-
-bool OptionsPopup::event(QEvent *ev)
-{
- if (ev->type() == QEvent::ShortcutOverride) {
- auto ke = static_cast<QKeyEvent *>(ev);
- if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
- ev->accept();
- return true;
- }
- }
- return QWidget::event(ev);
-}
-
-bool OptionsPopup::eventFilter(QObject *obj, QEvent *ev)
-{
- auto checkbox = qobject_cast<QCheckBox *>(obj);
- if (ev->type() == QEvent::KeyPress && checkbox) {
- auto ke = static_cast<QKeyEvent *>(ev);
- if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)) {
- checkbox->click();
- ev->accept();
- return true;
- }
- }
- return QWidget::eventFilter(obj, ev);
-}
-
-void OptionsPopup::actionChanged()
-{
- auto action = qobject_cast<QAction *>(sender());
- QTC_ASSERT(action, return);
- QCheckBox *checkbox = m_checkboxMap.value(action);
- QTC_ASSERT(checkbox, return);
- checkbox->setEnabled(action->isEnabled());
-}
-
-QCheckBox *OptionsPopup::createCheckboxForCommand(Id id)
-{
- QAction *action = ActionManager::command(id)->action();
- QCheckBox *checkbox = new QCheckBox(action->text());
- checkbox->setToolTip(action->toolTip());
- checkbox->setChecked(action->isChecked());
- checkbox->setEnabled(action->isEnabled());
- checkbox->installEventFilter(this); // enter key handling
- QObject::connect(checkbox, &QCheckBox::clicked, action, &QAction::setChecked);
- QObject::connect(action, &QAction::changed, this, &OptionsPopup::actionChanged);
- m_checkboxMap.insert(action, checkbox);
- return checkbox;
-}
-
} // namespace Internal
} // namespace Core
diff --git a/src/plugins/coreplugin/find/findtoolbar.h b/src/plugins/coreplugin/find/findtoolbar.h
index 8d6a9b77a4..f2fb494905 100644
--- a/src/plugins/coreplugin/find/findtoolbar.h
+++ b/src/plugins/coreplugin/find/findtoolbar.h
@@ -43,25 +43,6 @@ class FindToolBarPlaceHolder;
namespace Internal {
-class OptionsPopup : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit OptionsPopup(QWidget *parent);
-
-protected:
- bool event(QEvent *ev) override;
- bool eventFilter(QObject *obj, QEvent *ev) override;
-
-private:
- void actionChanged();
-
- QCheckBox *createCheckboxForCommand(Id id);
-
- QMap<QAction *, QCheckBox *> m_checkboxMap;
-};
-
class FindToolBar : public Utils::StyledBar
{
Q_OBJECT
diff --git a/src/plugins/coreplugin/find/findtoolwindow.cpp b/src/plugins/coreplugin/find/findtoolwindow.cpp
index 04f138a151..0490e8481f 100644
--- a/src/plugins/coreplugin/find/findtoolwindow.cpp
+++ b/src/plugins/coreplugin/find/findtoolwindow.cpp
@@ -77,14 +77,13 @@ FindToolWindow::FindToolWindow(QWidget *parent)
connect(m_ui.matchCase, &QAbstractButton::toggled, Find::instance(), &Find::setCaseSensitive);
connect(m_ui.wholeWords, &QAbstractButton::toggled, Find::instance(), &Find::setWholeWord);
connect(m_ui.regExp, &QAbstractButton::toggled, Find::instance(), &Find::setRegularExpression);
- connect(m_ui.filterList, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
- this, static_cast<void (FindToolWindow::*)(int)>(&FindToolWindow::setCurrentFilter));
+ connect(m_ui.filterList, QOverload<int>::of(&QComboBox::activated),
+ this, QOverload<int>::of(&FindToolWindow::setCurrentFilter));
m_findCompleter->setModel(Find::findCompletionModel());
m_ui.searchTerm->setSpecialCompleter(m_findCompleter);
m_ui.searchTerm->installEventFilter(this);
- connect(m_findCompleter,
- static_cast<void (QCompleter::*)(const QModelIndex &)>(&QCompleter::activated),
+ connect(m_findCompleter, QOverload<const QModelIndex &>::of(&QCompleter::activated),
this, &FindToolWindow::findCompleterActivated);
m_ui.searchTerm->setValidationFunction(validateRegExp);
diff --git a/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp
index 2ea32798de..b9d07b70da 100644
--- a/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp
+++ b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp
@@ -92,7 +92,7 @@ void HighlightScrollBarOverlay::scheduleUpdate()
return;
m_isCacheUpdateScheduled = true;
- QTimer::singleShot(0, this, static_cast<void (QWidget::*)()>(&QWidget::update));
+ QTimer::singleShot(0, this, QOverload<>::of(&QWidget::update));
}
void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent)
diff --git a/src/plugins/coreplugin/find/optionspopup.cpp b/src/plugins/coreplugin/find/optionspopup.cpp
new file mode 100644
index 0000000000..d7274f87e0
--- /dev/null
+++ b/src/plugins/coreplugin/find/optionspopup.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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 "optionspopup.h"
+
+#include <coreplugin/actionmanager/actionmanager.h>
+
+#include <utils/qtcassert.h>
+
+#include <QAction>
+#include <QCheckBox>
+#include <QEvent>
+#include <QKeyEvent>
+#include <QVBoxLayout>
+
+namespace Core {
+
+OptionsPopup::OptionsPopup(QWidget *parent, const QVector<Id> &commands)
+ : QWidget(parent, Qt::Popup)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ auto layout = new QVBoxLayout(this);
+ layout->setContentsMargins(2, 2, 2, 2);
+ layout->setSpacing(2);
+ setLayout(layout);
+
+ bool first = true;
+ for (const Id &command : commands) {
+ QCheckBox *checkBox = createCheckboxForCommand(command);
+ if (first) {
+ checkBox->setFocus();
+ first = false;
+ }
+ layout->addWidget(checkBox);
+ }
+ move(parent->mapToGlobal(QPoint(0, -sizeHint().height())));
+}
+
+bool OptionsPopup::event(QEvent *ev)
+{
+ if (ev->type() == QEvent::ShortcutOverride) {
+ auto ke = static_cast<QKeyEvent *>(ev);
+ if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
+ ev->accept();
+ return true;
+ }
+ }
+ return QWidget::event(ev);
+}
+
+bool OptionsPopup::eventFilter(QObject *obj, QEvent *ev)
+{
+ auto checkbox = qobject_cast<QCheckBox *>(obj);
+ if (ev->type() == QEvent::KeyPress && checkbox) {
+ auto ke = static_cast<QKeyEvent *>(ev);
+ if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)) {
+ checkbox->click();
+ ev->accept();
+ return true;
+ }
+ }
+ return QWidget::eventFilter(obj, ev);
+}
+
+void OptionsPopup::actionChanged()
+{
+ auto action = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(action, return);
+ QCheckBox *checkbox = m_checkboxMap.value(action);
+ QTC_ASSERT(checkbox, return);
+ checkbox->setEnabled(action->isEnabled());
+}
+
+QCheckBox *OptionsPopup::createCheckboxForCommand(Id id)
+{
+ QAction *action = ActionManager::command(id)->action();
+ QCheckBox *checkbox = new QCheckBox(action->text());
+ checkbox->setToolTip(action->toolTip());
+ checkbox->setChecked(action->isChecked());
+ checkbox->setEnabled(action->isEnabled());
+ checkbox->installEventFilter(this); // enter key handling
+ QObject::connect(checkbox, &QCheckBox::clicked, action, &QAction::setChecked);
+ QObject::connect(action, &QAction::changed, this, &OptionsPopup::actionChanged);
+ m_checkboxMap.insert(action, checkbox);
+ return checkbox;
+}
+
+} // namespace Core
diff --git a/src/plugins/coreplugin/find/optionspopup.h b/src/plugins/coreplugin/find/optionspopup.h
new file mode 100644
index 0000000000..003280eb36
--- /dev/null
+++ b/src/plugins/coreplugin/find/optionspopup.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 <coreplugin/id.h>
+
+#include <QMap>
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+class QCheckBox;
+QT_END_NAMESPACE
+
+namespace Core {
+
+class CORE_EXPORT OptionsPopup : public QWidget
+{
+ Q_OBJECT
+
+public:
+ OptionsPopup(QWidget *parent, const QVector<Id> &commands);
+
+protected:
+ bool event(QEvent *ev) override;
+ bool eventFilter(QObject *obj, QEvent *ev) override;
+
+private:
+ void actionChanged();
+
+ QCheckBox *createCheckboxForCommand(Id id);
+
+ QMap<QAction *, QCheckBox *> m_checkboxMap;
+};
+
+} // namespace Core
diff --git a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp
index 81ec2541c6..9351387c5b 100644
--- a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp
+++ b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.cpp
@@ -40,59 +40,101 @@ SearchResultTreeItemDelegate::SearchResultTreeItemDelegate(int tabWidth, QObject
setTabWidth(tabWidth);
}
-void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- static const int iconSize = 16;
+const int lineNumberAreaHorizontalPadding = 4;
+const int minimumLineNumberDigits = 6;
- painter->save();
+static std::pair<int, QString> lineNumberInfo(const QStyleOptionViewItem &option,
+ const QModelIndex &index)
+{
+ const int lineNumber = index.data(ItemDataRoles::ResultBeginLineNumberRole).toInt();
+ if (lineNumber < 1)
+ return {0, {}};
+ const QString lineNumberText = QString::number(lineNumber);
+ const int lineNumberDigits = qMax(minimumLineNumberDigits, lineNumberText.count());
+ const int fontWidth = option.fontMetrics.horizontalAdvance(QString(lineNumberDigits, QLatin1Char('0')));
+ const QStyle *style = option.widget ? option.widget->style() : QApplication::style();
+ return {lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding
+ + style->pixelMetric(QStyle::PM_FocusFrameHMargin),
+ lineNumberText};
+}
- QStyleOptionViewItem opt = setOptions(index, option);
- painter->setFont(opt.font);
+static QString itemText(const QModelIndex &index)
+{
+ const QString text = index.data(Qt::DisplayRole).toString();
+ // show number of subresults in displayString
+ if (index.model()->hasChildren(index)) {
+ return text + QLatin1String(" (") + QString::number(index.model()->rowCount(index))
+ + QLatin1Char(')');
+ }
+ return text;
+}
- QItemDelegate::drawBackground(painter, opt, index);
+LayoutInfo SearchResultTreeItemDelegate::getLayoutInfo(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ static const int iconSize = 16;
- // ---- do the layout
- QRect checkRect;
- QRect pixmapRect;
- QRect textRect;
+ LayoutInfo info;
+ info.option = setOptions(index, option);
// check mark
- bool checkable = (index.model()->flags(index) & Qt::ItemIsUserCheckable);
- Qt::CheckState checkState = Qt::Unchecked;
+ const bool checkable = (index.model()->flags(index) & Qt::ItemIsUserCheckable);
+ info.checkState = Qt::Unchecked;
if (checkable) {
QVariant checkStateData = index.data(Qt::CheckStateRole);
- checkState = static_cast<Qt::CheckState>(checkStateData.toInt());
- checkRect = doCheck(opt, opt.rect, checkStateData);
+ info.checkState = static_cast<Qt::CheckState>(checkStateData.toInt());
+ info.checkRect = doCheck(info.option, info.option.rect, checkStateData);
}
// icon
- QIcon icon = index.model()->data(index, ItemDataRoles::ResultIconRole).value<QIcon>();
- if (!icon.isNull()) {
- const QSize size = icon.actualSize(QSize(iconSize, iconSize));
- pixmapRect = QRect(0, 0, size.width(), size.height());
+ info.icon = index.data(ItemDataRoles::ResultIconRole).value<QIcon>();
+ if (!info.icon.isNull()) {
+ const QSize size = info.icon.actualSize(QSize(iconSize, iconSize));
+ info.pixmapRect = QRect(0, 0, size.width(), size.height());
}
// text
- textRect = opt.rect.adjusted(0, 0, checkRect.width() + pixmapRect.width(), 0);
+ info.textRect = info.option.rect.adjusted(0,
+ 0,
+ info.checkRect.width() + info.pixmapRect.width(),
+ 0);
+
+ // do basic layout
+ doLayout(info.option, &info.checkRect, &info.pixmapRect, &info.textRect, false);
+
+ // adapt for line numbers
+ const int lineNumberWidth = lineNumberInfo(info.option, index).first;
+ info.lineNumberRect = info.textRect;
+ info.lineNumberRect.setWidth(lineNumberWidth);
+ info.textRect.adjust(lineNumberWidth, 0, 0, 0);
+ return info;
+}
+
+void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ painter->save();
+
+ const LayoutInfo info = getLayoutInfo(option, index);
+
+ painter->setFont(info.option.font);
+
+ QItemDelegate::drawBackground(painter, info.option, index);
- // do layout
- doLayout(opt, &checkRect, &pixmapRect, &textRect, false);
// ---- draw the items
// icon
- if (!icon.isNull())
- icon.paint(painter, pixmapRect, option.decorationAlignment);
+ if (!info.icon.isNull())
+ info.icon.paint(painter, info.pixmapRect, info.option.decorationAlignment);
// line numbers
- int lineNumberAreaWidth = drawLineNumber(painter, opt, textRect, index);
- textRect.adjust(lineNumberAreaWidth, 0, 0, 0);
+ drawLineNumber(painter, info.option, info.lineNumberRect, index);
// text and focus/selection
- drawText(painter, opt, textRect, index);
- QItemDelegate::drawFocus(painter, opt, opt.rect);
+ drawText(painter, info.option, info.textRect, index);
+ QItemDelegate::drawFocus(painter, info.option, info.option.rect);
// check mark
- if (checkable)
- QItemDelegate::drawCheck(painter, opt, checkRect, checkState);
+ if (info.checkRect.isValid())
+ QItemDelegate::drawCheck(painter, info.option, info.checkRect, info.checkState);
painter->restore();
}
@@ -102,22 +144,31 @@ void SearchResultTreeItemDelegate::setTabWidth(int width)
m_tabString = QString(width, QLatin1Char(' '));
}
+QSize SearchResultTreeItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ 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);
+ 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);
+ const QRect layoutRect = info.checkRect | info.pixmapRect | info.lineNumberRect | textRect;
+ return QSize(layoutRect.x(), layoutRect.y()) + layoutRect.size();
+}
+
// returns the width of the line number area
int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option,
const QRect &rect,
const QModelIndex &index) const
{
- static const int lineNumberAreaHorizontalPadding = 4;
- int lineNumber = index.model()->data(index, ItemDataRoles::ResultBeginLineNumberRole).toInt();
- if (lineNumber < 1)
- return 0;
const bool isSelected = option.state & QStyle::State_Selected;
- QString lineText = QString::number(lineNumber);
- int minimumLineNumberDigits = qMax((int)m_minimumLineNumberDigits, lineText.count());
- int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, QLatin1Char('0')));
- int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding;
+ const std::pair<int, QString> numberInfo = lineNumberInfo(option, index);
+ if (numberInfo.first == 0)
+ return 0;
QRect lineNumberAreaRect(rect);
- lineNumberAreaRect.setWidth(lineNumberAreaWidth);
+ lineNumberAreaRect.setWidth(numberInfo.first);
QPalette::ColorGroup cg = QPalette::Normal;
if (!(option.state & QStyle::State_Active))
@@ -137,9 +188,9 @@ int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyle
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, nullptr) + 1;
const QRect rowRect = lineNumberAreaRect.adjusted(-textMargin, 0, textMargin-lineNumberAreaHorizontalPadding, 0);
- QItemDelegate::drawDisplay(painter, opt, rowRect, lineText);
+ QItemDelegate::drawDisplay(painter, opt, rowRect, numberInfo.second);
- return lineNumberAreaWidth;
+ return numberInfo.first;
}
void SearchResultTreeItemDelegate::drawText(QPainter *painter,
@@ -147,18 +198,15 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
const QRect &rect,
const QModelIndex &index) const
{
- QString text = index.model()->data(index, Qt::DisplayRole).toString();
- // show number of subresults in displayString
- if (index.model()->hasChildren(index)) {
- text += QLatin1String(" (")
- + QString::number(index.model()->rowCount(index))
- + QLatin1Char(')');
- }
+ const QString text = itemText(index);
const int searchTermStart = index.model()->data(index, ItemDataRoles::ResultBeginColumnNumberRole).toInt();
int searchTermLength = index.model()->data(index, ItemDataRoles::SearchTermLengthRole).toInt();
if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) {
- QItemDelegate::drawDisplay(painter, option, rect, text.replace(QLatin1Char('\t'), m_tabString));
+ QItemDelegate::drawDisplay(painter,
+ option,
+ rect,
+ QString(text).replace(QLatin1Char('\t'), m_tabString));
return;
}
@@ -168,8 +216,8 @@ void SearchResultTreeItemDelegate::drawText(QPainter *painter,
const QString textBefore = text.left(searchTermStart).replace(QLatin1Char('\t'), m_tabString);
const QString textHighlight = text.mid(searchTermStart, searchTermLength).replace(QLatin1Char('\t'), m_tabString);
const QString textAfter = text.mid(searchTermStart + searchTermLength).replace(QLatin1Char('\t'), m_tabString);
- int searchTermStartPixels = painter->fontMetrics().width(textBefore);
- int searchTermLengthPixels = painter->fontMetrics().width(textHighlight);
+ int searchTermStartPixels = painter->fontMetrics().horizontalAdvance(textBefore);
+ int searchTermLengthPixels = painter->fontMetrics().horizontalAdvance(textHighlight);
// rects
QRect beforeHighlightRect(rect);
diff --git a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.h b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.h
index 0551e4c8d7..edb13e98ed 100644
--- a/src/plugins/coreplugin/find/searchresulttreeitemdelegate.h
+++ b/src/plugins/coreplugin/find/searchresulttreeitemdelegate.h
@@ -30,20 +30,31 @@
namespace Core {
namespace Internal {
+struct LayoutInfo
+{
+ QRect checkRect;
+ QRect pixmapRect;
+ QRect textRect;
+ QRect lineNumberRect;
+ QIcon icon;
+ Qt::CheckState checkState;
+ QStyleOptionViewItem option;
+};
+
class SearchResultTreeItemDelegate: public QItemDelegate
{
public:
SearchResultTreeItemDelegate(int tabWidth, QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setTabWidth(int width);
-
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
+ LayoutInfo getLayoutInfo(const QStyleOptionViewItem &option, const QModelIndex &index) const;
int drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const;
void drawText(QPainter *painter, const QStyleOptionViewItem &option,
const QRect &rect, const QModelIndex &index) const;
QString m_tabString;
- static const int m_minimumLineNumberDigits = 6;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/find/searchresulttreemodel.cpp b/src/plugins/coreplugin/find/searchresulttreemodel.cpp
index 150e9dcc09..3fba0f899d 100644
--- a/src/plugins/coreplugin/find/searchresulttreemodel.cpp
+++ b/src/plugins/coreplugin/find/searchresulttreemodel.cpp
@@ -258,7 +258,7 @@ QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role)
result = row->item.text;
break;
case ItemDataRoles::ResultItemRole:
- result = qVariantFromValue(row->item);
+ result = QVariant::fromValue(row->item);
break;
case ItemDataRoles::ResultBeginLineNumberRole:
result = row->item.mainRange.begin.line;
diff --git a/src/plugins/coreplugin/find/searchresulttreeview.cpp b/src/plugins/coreplugin/find/searchresulttreeview.cpp
index 0ca09fcefd..48d1845053 100644
--- a/src/plugins/coreplugin/find/searchresulttreeview.cpp
+++ b/src/plugins/coreplugin/find/searchresulttreeview.cpp
@@ -44,6 +44,8 @@ SearchResultTreeView::SearchResultTreeView(QWidget *parent)
setIndentation(14);
setUniformRowHeights(true);
setExpandsOnDoubleClick(true);
+ header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+ header()->setStretchLastSection(false);
header()->hide();
connect(this, &SearchResultTreeView::activated,
@@ -93,6 +95,13 @@ void SearchResultTreeView::keyPressEvent(QKeyEvent *event)
TreeView::keyPressEvent(event);
}
+bool SearchResultTreeView::event(QEvent *e)
+{
+ if (e->type() == QEvent::Resize)
+ header()->setMinimumSectionSize(width());
+ return TreeView::event(e);
+}
+
void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index)
{
if (model()->data(index, ItemDataRoles::IsGeneratedRole).toBool())
diff --git a/src/plugins/coreplugin/find/searchresulttreeview.h b/src/plugins/coreplugin/find/searchresulttreeview.h
index eb11d29a7d..4809a6887b 100644
--- a/src/plugins/coreplugin/find/searchresulttreeview.h
+++ b/src/plugins/coreplugin/find/searchresulttreeview.h
@@ -50,6 +50,7 @@ public:
void addResults(const QList<SearchResultItem> &items, SearchResult::AddMode mode);
void keyPressEvent(QKeyEvent *event) override;
+ bool event(QEvent *e) override;
signals:
void jumpToSearchResult(const SearchResultItem &item);
diff --git a/src/plugins/coreplugin/find/searchresultwidget.cpp b/src/plugins/coreplugin/find/searchresultwidget.cpp
index 9428a31a1d..5827885802 100644
--- a/src/plugins/coreplugin/find/searchresultwidget.cpp
+++ b/src/plugins/coreplugin/find/searchresultwidget.cpp
@@ -72,8 +72,8 @@ public:
QSize sizeHint() const override
{
QSize sh = QLineEdit::minimumSizeHint();
- sh.rwidth() += qMax(25 * fontMetrics().width(QLatin1Char('x')),
- fontMetrics().width(text()));
+ sh.rwidth() += qMax(25 * fontMetrics().horizontalAdvance(QLatin1Char('x')),
+ fontMetrics().horizontalAdvance(text()));
return sh;
}
};
diff --git a/src/plugins/coreplugin/find/searchresultwindow.cpp b/src/plugins/coreplugin/find/searchresultwindow.cpp
index 7cea0166d1..ec723c8928 100644
--- a/src/plugins/coreplugin/find/searchresultwindow.cpp
+++ b/src/plugins/coreplugin/find/searchresultwindow.cpp
@@ -124,7 +124,7 @@ namespace Internal {
m_recentSearchesBox->setProperty("drawleftborder", true);
m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_recentSearchesBox->addItem(tr("New Search"));
- connect(m_recentSearchesBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_recentSearchesBox, QOverload<int>::of(&QComboBox::activated),
this, &SearchResultWindowPrivate::setCurrentIndexWithFocus);
m_widget->setWindowTitle(q->displayName());
@@ -135,7 +135,6 @@ namespace Internal {
m_widget->addWidget(newSearchArea);
m_expandCollapseButton = new QToolButton(m_widget);
- m_expandCollapseButton->setAutoRaise(true);
m_expandCollapseAction->setCheckable(true);
m_expandCollapseAction->setIcon(Utils::Icons::EXPAND_ALL_TOOLBAR.icon());
@@ -167,11 +166,13 @@ namespace Internal {
if (focus)
m_widget->currentWidget()->setFocus();
m_expandCollapseAction->setEnabled(false);
+ m_newSearchButton->setEnabled(false);
} else {
if (focus)
m_searchResultWidgets.at(visibleSearchIndex())->setFocusInternally();
m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(true);
m_expandCollapseAction->setEnabled(true);
+ m_newSearchButton->setEnabled(true);
}
q->navigateStateChanged();
}
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index 9cb23af656..63eba664cc 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -33,9 +33,10 @@
#include <utils/qtcassert.h>
-#include <QSysInfo>
#include <QApplication>
+#include <QDebug>
#include <QStandardPaths>
+#include <QSysInfo>
/*!
\namespace Core
@@ -329,9 +330,11 @@ ICore::ICore(MainWindow *mainwindow)
m_mainwindow = mainwindow;
// Save settings once after all plugins are initialized:
connect(PluginManager::instance(), &PluginManager::initializationDone,
- this, &ICore::saveSettings);
+ this, [] { ICore::saveSettings(ICore::InitializationDone); });
connect(PluginManager::instance(), &PluginManager::testsFinished, [this] (int failedTests) {
emit coreAboutToClose();
+ if (failedTests != 0)
+ qWarning("Test run was not successful: %d test(s) failed.", failedTests);
QCoreApplication::exit(failedTests);
});
}
@@ -687,9 +690,9 @@ void ICore::setupScreenShooter(const QString &name, QWidget *w, const QRect &rc)
new ScreenShooter(w, name, rc);
}
-void ICore::saveSettings()
+void ICore::saveSettings(SaveSettingsReason reason)
{
- emit m_instance->saveSettingsRequested();
+ emit m_instance->saveSettingsRequested(reason);
m_mainwindow->saveSettings();
ICore::settings(QSettings::SystemScope)->sync();
diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h
index 5125345cff..04d501e134 100644
--- a/src/plugins/coreplugin/icore.h
+++ b/src/plugins/coreplugin/icore.h
@@ -141,14 +141,21 @@ public:
static QString systemInformation();
static void setupScreenShooter(const QString &name, QWidget *w, const QRect &rc = QRect());
+ enum SaveSettingsReason {
+ InitializationDone,
+ SettingsDialogDone,
+ ModeChanged,
+ MainWindowClosing,
+ };
+
public slots:
- static void saveSettings();
+ static void saveSettings(SaveSettingsReason reason);
signals:
void coreAboutToOpen();
void coreOpened();
void newItemDialogStateChanged();
- void saveSettingsRequested();
+ void saveSettingsRequested(SaveSettingsReason reason);
void coreAboutToClose();
void contextAboutToChange(const QList<Core::IContext *> &context);
void contextChanged(const Core::Context &context);
diff --git a/src/plugins/coreplugin/idocument.cpp b/src/plugins/coreplugin/idocument.cpp
index e5a78b32d5..aab9845f1a 100644
--- a/src/plugins/coreplugin/idocument.cpp
+++ b/src/plugins/coreplugin/idocument.cpp
@@ -69,7 +69,7 @@ public:
}
QString mimeType;
- Utils::FileName filePath;
+ Utils::FilePath filePath;
QString preferredDisplayName;
QString uniqueDisplayName;
QString autoSaveName;
@@ -167,7 +167,7 @@ bool IDocument::setContents(const QByteArray &contents)
return false;
}
-const Utils::FileName &IDocument::filePath() const
+const Utils::FilePath &IDocument::filePath() const
{
return d->filePath;
}
@@ -322,11 +322,11 @@ InfoBar *IDocument::infoBar()
signals. Can be reimplemented by subclasses to do more.
\sa filePath()
*/
-void IDocument::setFilePath(const Utils::FileName &filePath)
+void IDocument::setFilePath(const Utils::FilePath &filePath)
{
if (d->filePath == filePath)
return;
- Utils::FileName oldName = d->filePath;
+ Utils::FilePath oldName = d->filePath;
d->filePath = filePath;
emit filePathChanged(oldName, d->filePath);
emit changed();
diff --git a/src/plugins/coreplugin/idocument.h b/src/plugins/coreplugin/idocument.h
index 4af747dc97..feae466705 100644
--- a/src/plugins/coreplugin/idocument.h
+++ b/src/plugins/coreplugin/idocument.h
@@ -29,7 +29,7 @@
#include <QObject>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace Core {
class Id;
@@ -93,8 +93,8 @@ public:
virtual QByteArray contents() const;
virtual bool setContents(const QByteArray &contents);
- const Utils::FileName &filePath() const;
- virtual void setFilePath(const Utils::FileName &filePath);
+ const Utils::FilePath &filePath() const;
+ virtual void setFilePath(const Utils::FilePath &filePath);
QString displayName() const;
void setPreferredDisplayName(const QString &name);
QString preferredDisplayName() const;
@@ -144,7 +144,7 @@ signals:
void aboutToReload();
void reloadFinished(bool success);
- void filePathChanged(const Utils::FileName &oldName, const Utils::FileName &newName);
+ void filePathChanged(const Utils::FilePath &oldName, const Utils::FilePath &newName);
private:
Internal::IDocumentPrivate *d;
diff --git a/src/plugins/coreplugin/infobar.h b/src/plugins/coreplugin/infobar.h
index b65a821bcf..74a0f8136f 100644
--- a/src/plugins/coreplugin/infobar.h
+++ b/src/plugins/coreplugin/infobar.h
@@ -55,7 +55,6 @@ public:
};
InfoBarEntry(Id _id, const QString &_infoText, GlobalSuppressionMode _globalSuppression = GlobalSuppressionDisabled);
- InfoBarEntry(const InfoBarEntry &other) { *this = other; }
using CallBack = std::function<void()>;
void setCustomButtonInfo(const QString &_buttonText, CallBack callBack);
diff --git a/src/plugins/coreplugin/ioutputpane.h b/src/plugins/coreplugin/ioutputpane.h
index 9ca6b1ef80..b7800a65c8 100644
--- a/src/plugins/coreplugin/ioutputpane.h
+++ b/src/plugins/coreplugin/ioutputpane.h
@@ -26,16 +26,23 @@
#pragma once
#include "core_global.h"
+#include "id.h"
+
+#include <utils/fancylineedit.h>
#include <QObject>
#include <QList>
#include <QString>
QT_BEGIN_NAMESPACE
+class QAction;
+class QToolButton;
class QWidget;
QT_END_NAMESPACE
namespace Core {
+class CommandButton;
+class IContext;
class CORE_EXPORT IOutputPane : public QObject
{
@@ -46,7 +53,7 @@ public:
~IOutputPane() override;
virtual QWidget *outputWidget(QWidget *parent) = 0;
- virtual QList<QWidget *> toolBarWidgets() const = 0;
+ virtual QList<QWidget *> toolBarWidgets() const;
virtual QString displayName() const = 0;
virtual int priorityInStatusBar() const = 0;
@@ -64,6 +71,9 @@ public:
virtual void goToNext() = 0;
virtual void goToPrev() = 0;
+ void setFont(const QFont &font);
+ void setWheelZoomEnabled(bool enabled);
+
enum Flag { NoModeSwitch = 0, ModeSwitch = 1, WithFocus = 2, EnsureSizeHint = 4};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -83,6 +93,39 @@ signals:
void navigateStateUpdate();
void flashButton();
void setBadgeNumber(int number);
+ void zoomIn(int range);
+ void zoomOut(int range);
+ void resetZoom();
+ void wheelZoomEnabledChanged(bool enabled);
+ void fontChanged(const QFont &font);
+
+protected:
+ void setupFilterUi(const QString &historyKey);
+ QString filterText() const;
+ bool filterUsesRegexp() const { return m_filterRegexp; }
+ Qt::CaseSensitivity filterCaseSensitivity() const { return m_filterCaseSensitivity; }
+ void setFilteringEnabled(bool enable);
+ QWidget *filterWidget() const { return m_filterOutputLineEdit; }
+ void setupContext(const char *context, QWidget *widget);
+ void setZoomButtonsEnabled(bool enabled);
+
+private:
+ virtual void updateFilter();
+
+ void filterOutputButtonClicked();
+ void setCaseSensitive(bool caseSensitive);
+ void setRegularExpressions(bool regularExpressions);
+ Id filterRegexpActionId() const;
+ Id filterCaseSensitivityActionId() const;
+
+ Core::CommandButton * const m_zoomInButton;
+ Core::CommandButton * const m_zoomOutButton;
+ QAction *m_filterActionRegexp = nullptr;
+ QAction *m_filterActionCaseSensitive = nullptr;
+ Utils::FancyLineEdit *m_filterOutputLineEdit = nullptr;
+ IContext *m_context = nullptr;
+ bool m_filterRegexp = false;
+ Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive;
};
} // namespace Core
diff --git a/src/plugins/coreplugin/iversioncontrol.cpp b/src/plugins/coreplugin/iversioncontrol.cpp
index befa60fbab..3bc7ddd6f8 100644
--- a/src/plugins/coreplugin/iversioncontrol.cpp
+++ b/src/plugins/coreplugin/iversioncontrol.cpp
@@ -79,7 +79,7 @@ QStringList IVersionControl::additionalToolsPath() const
}
ShellCommand *IVersionControl::createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs)
{
diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index cdb780f7fc..0846793b5a 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -103,7 +103,7 @@ public:
*
* This method needs to be thread safe!
*/
- virtual bool isVcsFileOrDirectory(const Utils::FileName &fileName) const = 0;
+ virtual bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const = 0;
/*!
* Returns whether files in this directory should be managed with this
@@ -213,7 +213,7 @@ public:
* \a extraArgs are passed on to the command being run.
*/
virtual ShellCommand *createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs);
@@ -226,10 +226,10 @@ private:
TopicCache *m_topicCache;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(Core::IVersionControl::SettingsFlags)
-
} // namespace Core
+Q_DECLARE_OPERATORS_FOR_FLAGS(Core::IVersionControl::SettingsFlags)
+
#if defined(WITH_TESTS)
#include <QSet>
@@ -245,7 +245,7 @@ public:
{ }
~TestVersionControl() override;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final
{ Q_UNUSED(fileName); return false; }
void setManagedDirectories(const QHash<QString, QString> &dirs);
diff --git a/src/plugins/coreplugin/jsexpander.cpp b/src/plugins/coreplugin/jsexpander.cpp
index effa3464cc..4ee72752e5 100644
--- a/src/plugins/coreplugin/jsexpander.cpp
+++ b/src/plugins/coreplugin/jsexpander.cpp
@@ -34,8 +34,26 @@
#include <QDebug>
#include <QJSEngine>
-namespace Core {
+#include <unordered_map>
+
+namespace std {
+template<> struct hash<QString>
+{
+ using argument_type = QString;
+ using result_type = size_t;
+ result_type operator()(const argument_type &v) const
+ {
+ return hash<string>()(v.toStdString());
+ }
+};
+} // namespace std
+
+using ExtensionMap = std::unordered_map<QString, Core::JsExpander::ObjectFactory>;
+Q_GLOBAL_STATIC(ExtensionMap, globalJsExtensions);
+static Core::JsExpander *globalExpander = nullptr;
+
+namespace Core {
namespace Internal {
class JsExpanderPrivate {
@@ -45,9 +63,14 @@ public:
} // namespace Internal
-static Internal::JsExpanderPrivate *d;
+void JsExpander::registerGlobalObject(const QString &name, const ObjectFactory &factory)
+{
+ globalJsExtensions->insert({name, factory});
+ if (globalExpander)
+ globalExpander->registerObject(name, factory());
+}
-void JsExpander::registerQObjectForJs(const QString &name, QObject *obj)
+void JsExpander::registerObject(const QString &name, QObject *obj)
{
QJSValue jsObj = d->m_engine.newQObject(obj);
d->m_engine.globalObject().setProperty(name, jsObj);
@@ -77,16 +100,23 @@ QString JsExpander::evaluate(const QString &expression, QString *errorMessage)
return QString();
}
-JsExpander::JsExpander()
+QJSEngine &JsExpander::engine()
{
- d = new Internal::JsExpanderPrivate;
- Utils::globalMacroExpander()->registerPrefix("JS",
+ return d->m_engine;
+}
+
+void JsExpander::registerForExpander(Utils::MacroExpander *macroExpander)
+{
+ macroExpander->registerPrefix(
+ "JS",
QCoreApplication::translate("Core::JsExpander",
"Evaluate simple JavaScript statements.<br>"
- "The statements may not contain '{' nor '}' characters."),
- [](QString in) -> QString {
+ "Literal '}' characters must be escaped as \"\\}\", "
+ "'\\' characters must be escaped as \"\\\\\", "
+ "and \"%{\" must be escaped as \"%\\{\"."),
+ [this](QString in) -> QString {
QString errorMessage;
- QString result = JsExpander::evaluate(in, &errorMessage);
+ QString result = evaluate(in, &errorMessage);
if (!errorMessage.isEmpty()) {
qWarning() << errorMessage;
return errorMessage;
@@ -94,8 +124,21 @@ JsExpander::JsExpander()
return result;
}
});
+}
- registerQObjectForJs(QLatin1String("Util"), new Internal::UtilsJsExtension);
+JsExpander *JsExpander::createGlobalJsExpander()
+{
+ globalExpander = new JsExpander();
+ registerGlobalObject<Internal::UtilsJsExtension>("Util");
+ globalExpander->registerForExpander(Utils::globalMacroExpander());
+ return globalExpander;
+}
+
+JsExpander::JsExpander()
+{
+ d = new Internal::JsExpanderPrivate;
+ for (const std::pair<const QString, ObjectFactory> &obj : *globalJsExtensions)
+ registerObject(obj.first, obj.second());
}
JsExpander::~JsExpander()
diff --git a/src/plugins/coreplugin/jsexpander.h b/src/plugins/coreplugin/jsexpander.h
index 087f494ac0..df8c6bceea 100644
--- a/src/plugins/coreplugin/jsexpander.h
+++ b/src/plugins/coreplugin/jsexpander.h
@@ -27,26 +27,51 @@
#include "core_global.h"
+#include <functional>
+
QT_BEGIN_NAMESPACE
+class QJSEngine;
class QObject;
class QString;
QT_END_NAMESPACE
+namespace Utils {
+class MacroExpander;
+}
+
namespace Core {
-namespace Internal { class MainWindow; }
+namespace Internal {
+class MainWindow;
+class JsExpanderPrivate;
+} // namespace Internal
class CORE_EXPORT JsExpander
{
public:
- static void registerQObjectForJs(const QString &name, QObject *obj);
-
- static QString evaluate(const QString &expression, QString *errorMessage = nullptr);
+ using ObjectFactory = std::function<QObject *()>;
-private:
JsExpander();
~JsExpander();
+ template <class T>
+ static void registerGlobalObject(const QString &name)
+ {
+ registerGlobalObject(name, []{ return new T; });
+ }
+
+ static void registerGlobalObject(const QString &name, const ObjectFactory &factory);
+
+ void registerObject(const QString &name, QObject *obj);
+ QString evaluate(const QString &expression, QString *errorMessage = nullptr);
+
+ QJSEngine &engine();
+ void registerForExpander(Utils::MacroExpander *macroExpander);
+
+private:
+ static JsExpander *createGlobalJsExpander();
+
+ Internal::JsExpanderPrivate *d;
friend class Core::Internal::MainWindow;
};
diff --git a/src/plugins/coreplugin/locator/basefilefilter.cpp b/src/plugins/coreplugin/locator/basefilefilter.cpp
index 220f6ff782..e2b26b57ae 100644
--- a/src/plugins/coreplugin/locator/basefilefilter.cpp
+++ b/src/plugins/coreplugin/locator/basefilefilter.cpp
@@ -153,7 +153,7 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QFileInfo fi(path);
LocatorFilterEntry filterEntry(this, fi.fileName(), QString(path + fp.postfix));
filterEntry.fileName = path;
- filterEntry.extraInfo = FileUtils::shortNativePath(FileName(fi));
+ filterEntry.extraInfo = FilePath::fromFileInfo(fi).shortNativePath();
const int matchLevel = matchLevelFor(match, matchText);
if (hasPathSeparator) {
diff --git a/src/plugins/coreplugin/locator/directoryfilter.cpp b/src/plugins/coreplugin/locator/directoryfilter.cpp
index 645bae42d3..02e7e59fe9 100644
--- a/src/plugins/coreplugin/locator/directoryfilter.cpp
+++ b/src/plugins/coreplugin/locator/directoryfilter.cpp
@@ -24,6 +24,9 @@
****************************************************************************/
#include "directoryfilter.h"
+#include "ui_directoryfilter.h"
+
+#include "locator.h"
#include <coreplugin/coreconstants.h>
#include <utils/algorithm.h>
@@ -32,8 +35,7 @@
#include <QFileDialog>
#include <QTimer>
-using namespace Core;
-using namespace Core::Internal;
+namespace Core {
DirectoryFilter::DirectoryFilter(Id id)
: m_filters({"*.h", "*.cpp", "*.ui", "*.qrc"}),
@@ -64,12 +66,13 @@ void DirectoryFilter::restoreState(const QByteArray &state)
QMutexLocker locker(&m_lock);
QString name;
+ QStringList directories;
QString shortcut;
bool defaultFilter;
QDataStream in(state);
in >> name;
- in >> m_directories;
+ in >> directories;
in >> m_filters;
in >> shortcut;
in >> defaultFilter;
@@ -79,6 +82,8 @@ void DirectoryFilter::restoreState(const QByteArray &state)
else
m_exclusionFilters.clear();
+ if (m_isCustomFilter)
+ m_directories = directories;
setDisplayName(name);
setShortcutString(shortcut);
setIncludedByDefault(defaultFilter);
@@ -88,60 +93,83 @@ void DirectoryFilter::restoreState(const QByteArray &state)
bool DirectoryFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
{
+ if (!m_ui) {
+ m_ui = new Internal::Ui::DirectoryFilterOptions;
+ }
bool success = false;
QDialog dialog(parent);
m_dialog = &dialog;
- m_ui.setupUi(&dialog);
+ m_ui->setupUi(&dialog);
dialog.setWindowTitle(ILocatorFilter::msgConfigureDialogTitle());
- m_ui.prefixLabel->setText(ILocatorFilter::msgPrefixLabel());
- m_ui.prefixLabel->setToolTip(ILocatorFilter::msgPrefixToolTip());
- m_ui.defaultFlag->setText(ILocatorFilter::msgIncludeByDefault());
- m_ui.defaultFlag->setToolTip(ILocatorFilter::msgIncludeByDefaultToolTip());
- connect(m_ui.addButton, &QPushButton::clicked,
- this, &DirectoryFilter::addDirectory, Qt::DirectConnection);
- connect(m_ui.editButton, &QPushButton::clicked,
- this, &DirectoryFilter::editDirectory, Qt::DirectConnection);
- connect(m_ui.removeButton, &QPushButton::clicked,
- this, &DirectoryFilter::removeDirectory, Qt::DirectConnection);
- connect(m_ui.directoryList, &QListWidget::itemSelectionChanged,
- this, &DirectoryFilter::updateOptionButtons, Qt::DirectConnection);
- m_ui.nameEdit->setText(displayName());
- m_ui.nameEdit->selectAll();
- m_ui.directoryList->clear();
- m_ui.directoryList->addItems(m_directories);
- m_ui.filePatternLabel->setText(Utils::msgFilePatternLabel());
- m_ui.filePatternLabel->setBuddy(m_ui.filePattern);
- m_ui.filePattern->setToolTip(Utils::msgFilePatternToolTip());
- m_ui.filePattern->setText(Utils::transform(m_filters, &QDir::toNativeSeparators).join(','));
- m_ui.exclusionPatternLabel->setText(Utils::msgExclusionPatternLabel());
- m_ui.exclusionPatternLabel->setBuddy(m_ui.exclusionPattern);
- m_ui.exclusionPattern->setToolTip(Utils::msgFilePatternToolTip());
- m_ui.exclusionPattern->setText(Utils::transform(m_exclusionFilters, &QDir::toNativeSeparators)
- .join(','));
- m_ui.shortcutEdit->setText(shortcutString());
- m_ui.defaultFlag->setChecked(isIncludedByDefault());
+ m_ui->prefixLabel->setText(ILocatorFilter::msgPrefixLabel());
+ m_ui->prefixLabel->setToolTip(ILocatorFilter::msgPrefixToolTip());
+ m_ui->defaultFlag->setText(ILocatorFilter::msgIncludeByDefault());
+ m_ui->defaultFlag->setToolTip(ILocatorFilter::msgIncludeByDefaultToolTip());
+ m_ui->nameEdit->setText(displayName());
+ m_ui->nameEdit->selectAll();
+ connect(m_ui->addButton,
+ &QPushButton::clicked,
+ this,
+ &DirectoryFilter::handleAddDirectory,
+ Qt::DirectConnection);
+ connect(m_ui->editButton,
+ &QPushButton::clicked,
+ this,
+ &DirectoryFilter::handleEditDirectory,
+ Qt::DirectConnection);
+ connect(m_ui->removeButton,
+ &QPushButton::clicked,
+ this,
+ &DirectoryFilter::handleRemoveDirectory,
+ Qt::DirectConnection);
+ connect(m_ui->directoryList,
+ &QListWidget::itemSelectionChanged,
+ this,
+ &DirectoryFilter::updateOptionButtons,
+ Qt::DirectConnection);
+ m_ui->directoryList->clear();
+ m_ui->directoryList->addItems(m_directories);
+ m_ui->nameLabel->setVisible(m_isCustomFilter);
+ m_ui->nameEdit->setVisible(m_isCustomFilter);
+ m_ui->directoryLabel->setVisible(m_isCustomFilter);
+ m_ui->directoryList->setVisible(m_isCustomFilter);
+ m_ui->addButton->setVisible(m_isCustomFilter);
+ m_ui->editButton->setVisible(m_isCustomFilter);
+ m_ui->removeButton->setVisible(m_isCustomFilter);
+ m_ui->filePatternLabel->setText(Utils::msgFilePatternLabel());
+ m_ui->filePatternLabel->setBuddy(m_ui->filePattern);
+ m_ui->filePattern->setToolTip(Utils::msgFilePatternToolTip());
+ m_ui->filePattern->setText(Utils::transform(m_filters, &QDir::toNativeSeparators).join(','));
+ m_ui->exclusionPatternLabel->setText(Utils::msgExclusionPatternLabel());
+ m_ui->exclusionPatternLabel->setBuddy(m_ui->exclusionPattern);
+ m_ui->exclusionPattern->setToolTip(Utils::msgFilePatternToolTip());
+ m_ui->exclusionPattern->setText(
+ Utils::transform(m_exclusionFilters, &QDir::toNativeSeparators).join(','));
+ m_ui->shortcutEdit->setText(shortcutString());
+ m_ui->defaultFlag->setChecked(isIncludedByDefault());
updateOptionButtons();
+ dialog.adjustSize();
if (dialog.exec() == QDialog::Accepted) {
QMutexLocker locker(&m_lock);
bool directoriesChanged = false;
const QStringList oldDirectories = m_directories;
const QStringList oldFilters = m_filters;
const QStringList oldExclusionFilters = m_exclusionFilters;
- setDisplayName(m_ui.nameEdit->text().trimmed());
+ setDisplayName(m_ui->nameEdit->text().trimmed());
m_directories.clear();
const int oldCount = oldDirectories.count();
- const int newCount = m_ui.directoryList->count();
+ const int newCount = m_ui->directoryList->count();
if (oldCount != newCount)
directoriesChanged = true;
for (int i = 0; i < newCount; ++i) {
- m_directories.append(m_ui.directoryList->item(i)->text());
+ m_directories.append(m_ui->directoryList->item(i)->text());
if (!directoriesChanged && m_directories.at(i) != oldDirectories.at(i))
directoriesChanged = true;
}
- m_filters = Utils::splitFilterUiText(m_ui.filePattern->text());
- m_exclusionFilters = Utils::splitFilterUiText(m_ui.exclusionPattern->text());
- setShortcutString(m_ui.shortcutEdit->text().trimmed());
- setIncludedByDefault(m_ui.defaultFlag->isChecked());
+ m_filters = Utils::splitFilterUiText(m_ui->filePattern->text());
+ m_exclusionFilters = Utils::splitFilterUiText(m_ui->exclusionPattern->text());
+ setShortcutString(m_ui->shortcutEdit->text().trimmed());
+ setIncludedByDefault(m_ui->defaultFlag->isChecked());
needsRefresh = directoriesChanged || oldFilters != m_filters
|| oldExclusionFilters != m_exclusionFilters;
success = true;
@@ -149,37 +177,37 @@ bool DirectoryFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
return success;
}
-void DirectoryFilter::addDirectory()
+void DirectoryFilter::handleAddDirectory()
{
QString dir = QFileDialog::getExistingDirectory(m_dialog, tr("Select Directory"));
if (!dir.isEmpty())
- m_ui.directoryList->addItem(dir);
+ m_ui->directoryList->addItem(dir);
}
-void DirectoryFilter::editDirectory()
+void DirectoryFilter::handleEditDirectory()
{
- if (m_ui.directoryList->selectedItems().count() < 1)
+ if (m_ui->directoryList->selectedItems().count() < 1)
return;
- QListWidgetItem *currentItem = m_ui.directoryList->selectedItems().at(0);
+ QListWidgetItem *currentItem = m_ui->directoryList->selectedItems().at(0);
QString dir = QFileDialog::getExistingDirectory(m_dialog, tr("Select Directory"),
currentItem->text());
if (!dir.isEmpty())
currentItem->setText(dir);
}
-void DirectoryFilter::removeDirectory()
+void DirectoryFilter::handleRemoveDirectory()
{
- if (m_ui.directoryList->selectedItems().count() < 1)
+ if (m_ui->directoryList->selectedItems().count() < 1)
return;
- QListWidgetItem *currentItem = m_ui.directoryList->selectedItems().at(0);
- delete m_ui.directoryList->takeItem(m_ui.directoryList->row(currentItem));
+ QListWidgetItem *currentItem = m_ui->directoryList->selectedItems().at(0);
+ delete m_ui->directoryList->takeItem(m_ui->directoryList->row(currentItem));
}
void DirectoryFilter::updateOptionButtons()
{
- bool haveSelectedItem = (m_ui.directoryList->selectedItems().count() > 0);
- m_ui.editButton->setEnabled(haveSelectedItem);
- m_ui.removeButton->setEnabled(haveSelectedItem);
+ bool haveSelectedItem = (m_ui->directoryList->selectedItems().count() > 0);
+ m_ui->editButton->setEnabled(haveSelectedItem);
+ m_ui->removeButton->setEnabled(haveSelectedItem);
}
void DirectoryFilter::updateFileIterator()
@@ -225,3 +253,45 @@ void DirectoryFilter::refresh(QFutureInterface<void> &future)
future.setProgressValueAndText(subDirIterator.currentProgress(), tr("%1 filter update: canceled").arg(displayName()));
}
}
+
+void DirectoryFilter::setIsCustomFilter(bool value)
+{
+ m_isCustomFilter = value;
+}
+
+void DirectoryFilter::setDirectories(const QStringList &directories)
+{
+ if (directories == m_directories)
+ return;
+ m_directories = directories;
+ Internal::Locator::instance()->refresh({this});
+}
+
+void DirectoryFilter::addDirectory(const QString &directory)
+{
+ setDirectories(m_directories + QStringList(directory));
+}
+
+void DirectoryFilter::removeDirectory(const QString &directory)
+{
+ QStringList directories = m_directories;
+ directories.removeOne(directory);
+ setDirectories(directories);
+}
+
+QStringList DirectoryFilter::directories() const
+{
+ return m_directories;
+}
+
+void DirectoryFilter::setFilters(const QStringList &filters)
+{
+ m_filters = filters;
+}
+
+void DirectoryFilter::setExclusionFilters(const QStringList &exclusionFilters)
+{
+ m_exclusionFilters = exclusionFilters;
+}
+
+} // namespace Core
diff --git a/src/plugins/coreplugin/locator/directoryfilter.h b/src/plugins/coreplugin/locator/directoryfilter.h
index 06ef1f37e3..803141afdb 100644
--- a/src/plugins/coreplugin/locator/directoryfilter.h
+++ b/src/plugins/coreplugin/locator/directoryfilter.h
@@ -25,9 +25,10 @@
#pragma once
-#include "ui_directoryfilter.h"
#include "basefilefilter.h"
+#include <coreplugin/core_global.h>
+
#include <QString>
#include <QByteArray>
#include <QFutureInterface>
@@ -35,8 +36,12 @@
namespace Core {
namespace Internal {
+namespace Ui {
+class DirectoryFilterOptions;
+} // namespace Ui
+} // namespace Internal
-class DirectoryFilter : public BaseFileFilter
+class CORE_EXPORT DirectoryFilter : public BaseFileFilter
{
Q_OBJECT
@@ -47,10 +52,20 @@ public:
bool openConfigDialog(QWidget *parent, bool &needsRefresh) override;
void refresh(QFutureInterface<void> &future) override;
+ void setIsCustomFilter(bool value);
+ void setDirectories(const QStringList &directories);
+ void addDirectory(const QString &directory);
+ void removeDirectory(const QString &directory);
+ QStringList directories() const;
+ void setFilters(const QStringList &filters);
+ void setExclusionFilters(const QStringList &exclusionFilters);
+
+ using ILocatorFilter::setDisplayName;
+
private:
- void addDirectory();
- void editDirectory();
- void removeDirectory();
+ void handleAddDirectory();
+ void handleEditDirectory();
+ void handleRemoveDirectory();
void updateOptionButtons();
void updateFileIterator();
@@ -60,10 +75,10 @@ private:
// Our config dialog, uses in addDirectory and editDirectory
// to give their dialogs the right parent
QDialog *m_dialog = nullptr;
- Ui::DirectoryFilterOptions m_ui;
+ Internal::Ui::DirectoryFilterOptions *m_ui = nullptr;
mutable QMutex m_lock;
QStringList m_files;
+ bool m_isCustomFilter = true;
};
-} // namespace Internal
} // namespace Core
diff --git a/src/plugins/coreplugin/locator/directoryfilter.ui b/src/plugins/coreplugin/locator/directoryfilter.ui
index 37d26e4ed7..5889a82750 100644
--- a/src/plugins/coreplugin/locator/directoryfilter.ui
+++ b/src/plugins/coreplugin/locator/directoryfilter.ui
@@ -10,11 +10,11 @@
<height>300</height>
</rect>
</property>
- <layout class="QGridLayout">
- <item row="0" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
<layout class="QGridLayout">
<item row="0" column="0">
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="nameLabel">
<property name="text">
<string>Name:</string>
</property>
@@ -81,7 +81,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t
</widget>
</item>
<item row="1" column="3">
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="directoryButtonLayout">
<item>
<widget class="QPushButton" name="addButton">
<property name="text">
@@ -110,8 +110,8 @@ To do this, you type this shortcut and a space in the Locator entry field, and t
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
- <height>40</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
</spacer>
@@ -119,23 +119,23 @@ To do this, you type this shortcut and a space in the Locator entry field, and t
</layout>
</item>
<item row="1" column="0">
- <layout class="QVBoxLayout" name="verticalLayout_2">
+ <layout class="QVBoxLayout" name="directoryLabelLayout">
<item>
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="directoryLabel">
<property name="text">
<string>Directories:</string>
</property>
</widget>
</item>
<item>
- <spacer name="verticalSpacer">
+ <spacer name="directoryLabelSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
- <height>40</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
</spacer>
@@ -154,7 +154,20 @@ To do this, you type this shortcut and a space in the Locator entry field, and t
</item>
</layout>
</item>
- <item row="1" column="0">
+ <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>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
diff --git a/src/plugins/coreplugin/locator/executefilter.cpp b/src/plugins/coreplugin/locator/executefilter.cpp
index b85bf4ff28..bc4a4b65a7 100644
--- a/src/plugins/coreplugin/locator/executefilter.cpp
+++ b/src/plugins/coreplugin/locator/executefilter.cpp
@@ -44,7 +44,7 @@ ExecuteFilter::ExecuteFilter()
m_process = new Utils::QtcProcess(this);
m_process->setEnvironment(Utils::Environment::systemEnvironment());
- connect(m_process, static_cast<void (QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_process, QOverload<int ,QProcess::ExitStatus>::of(&QProcess::finished),
this, &ExecuteFilter::finished);
connect(m_process, &QProcess::readyReadStandardOutput, this, &ExecuteFilter::readStandardOutput);
connect(m_process, &QProcess::readyReadStandardError, this, &ExecuteFilter::readStandardError);
@@ -160,7 +160,7 @@ void ExecuteFilter::runHeadCommand()
{
if (!m_taskQueue.isEmpty()) {
const ExecuteData &d = m_taskQueue.head();
- const Utils::FileName fullPath = Utils::Environment::systemEnvironment().searchInPath(d.executable);
+ const Utils::FilePath fullPath = Utils::Environment::systemEnvironment().searchInPath(d.executable);
if (fullPath.isEmpty()) {
MessageManager::write(tr("Could not find executable for \"%1\".").arg(d.executable));
m_taskQueue.dequeue();
@@ -169,7 +169,7 @@ void ExecuteFilter::runHeadCommand()
}
MessageManager::write(tr("Starting command \"%1\".").arg(headCommand()));
m_process->setWorkingDirectory(d.workingDirectory);
- m_process->setCommand(fullPath.toString(), d.arguments);
+ m_process->setCommand(Utils::CommandLine(fullPath, d.arguments));
m_process->start();
m_process->closeWriteChannel();
if (!m_process->waitForStarted(1000)) {
diff --git a/src/plugins/coreplugin/locator/filesystemfilter.cpp b/src/plugins/coreplugin/locator/filesystemfilter.cpp
index 3c55e00240..0719e9b781 100644
--- a/src/plugins/coreplugin/locator/filesystemfilter.cpp
+++ b/src/plugins/coreplugin/locator/filesystemfilter.cpp
@@ -142,8 +142,7 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
const QString fullFilePath = dirInfo.filePath(fileName);
if (!QFileInfo::exists(fullFilePath) && dirInfo.exists()) {
LocatorFilterEntry createAndOpen(this, tr("Create and Open \"%1\"").arg(entry), fullFilePath);
- createAndOpen.extraInfo = Utils::FileUtils::shortNativePath(
- Utils::FileName::fromString(dirInfo.absolutePath()));
+ createAndOpen.extraInfo = Utils::FilePath::fromString(dirInfo.absolutePath()).shortNativePath();
betterEntries.append(createAndOpen);
}
diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp
index 17f8fbbd86..48749cce3e 100644
--- a/src/plugins/coreplugin/locator/locator.cpp
+++ b/src/plugins/coreplugin/locator/locator.cpp
@@ -56,7 +56,6 @@
#include <utils/utilsicons.h>
#include <QAction>
-#include <QFuture>
#include <QSettings>
#include <QtPlugin>
@@ -92,7 +91,7 @@ Locator::Locator()
{
m_instance = this;
m_refreshTimer.setSingleShot(false);
- connect(&m_refreshTimer, &QTimer::timeout, this, [this]() { refresh(); });
+ connect(&m_refreshTimer, &QTimer::timeout, this, [this]() { refresh(filters()); });
}
Locator::~Locator()
@@ -339,12 +338,22 @@ void Locator::setRefreshInterval(int interval)
void Locator::refresh(QList<ILocatorFilter *> filters)
{
- if (filters.isEmpty())
- filters = m_filters;
- QFuture<void> task = Utils::map(filters, &ILocatorFilter::refresh, Utils::MapReduceOption::Unordered);
- FutureProgress *progress =
- ProgressManager::addTask(task, tr("Updating Locator Caches"), Constants::TASK_INDEX);
- connect(progress, &FutureProgress::finished, this, &Locator::saveSettings);
+ if (m_refreshTask.isRunning()) {
+ m_refreshTask.cancel();
+ // this is not ideal because some of the previous filters might have finished, but we
+ // currently cannot find out which part of a map-reduce has finished
+ filters = Utils::filteredUnique(m_refreshingFilters + filters);
+ }
+ m_refreshingFilters = filters;
+ m_refreshTask = Utils::map(filters, &ILocatorFilter::refresh, Utils::MapReduceOption::Unordered);
+ ProgressManager::addTask(m_refreshTask, tr("Updating Locator Caches"), Constants::TASK_INDEX);
+ Utils::onFinished(m_refreshTask, this, [this](const QFuture<void> &future) {
+ if (!future.isCanceled()) {
+ saveSettings();
+ m_refreshingFilters.clear();
+ m_refreshTask = QFuture<void>();
+ }
+ });
}
} // namespace Internal
diff --git a/src/plugins/coreplugin/locator/locator.h b/src/plugins/coreplugin/locator/locator.h
index 10b2dc256a..d7c62c44ba 100644
--- a/src/plugins/coreplugin/locator/locator.h
+++ b/src/plugins/coreplugin/locator/locator.h
@@ -30,6 +30,7 @@
#include <coreplugin/actionmanager/command.h>
+#include <QFuture>
#include <QObject>
#include <QTimer>
@@ -64,7 +65,7 @@ signals:
void filtersChanged();
public slots:
- void refresh(QList<ILocatorFilter *> filters = QList<ILocatorFilter *>());
+ void refresh(QList<ILocatorFilter *> filters);
void saveSettings() const;
private:
@@ -80,6 +81,8 @@ private:
QList<ILocatorFilter *> m_customFilters;
QMap<Id, QAction *> m_filterActionMap;
QTimer m_refreshTimer;
+ QFuture<void> m_refreshTask;
+ QList<ILocatorFilter *> m_refreshingFilters;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/locator/locator_test.cpp b/src/plugins/coreplugin/locator/locator_test.cpp
index cf99717e5b..c76a5633ea 100644
--- a/src/plugins/coreplugin/locator/locator_test.cpp
+++ b/src/plugins/coreplugin/locator/locator_test.cpp
@@ -89,7 +89,7 @@ void Core::Internal::CorePlugin::test_basefilefilter()
void Core::Internal::CorePlugin::test_basefilefilter_data()
{
auto shortNativePath = [](const QString &file) {
- return Utils::FileUtils::shortNativePath(Utils::FileName::fromString(file));
+ return Utils::FilePath::fromString(file).shortNativePath();
};
QTest::addColumn<QStringList>("testFiles");
diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp
index 994c9e5d0e..b21afd2adc 100644
--- a/src/plugins/coreplugin/locator/locatorwidget.cpp
+++ b/src/plugins/coreplugin/locator/locatorwidget.cpp
@@ -210,7 +210,7 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
return QColor(Qt::darkGray);
break;
case LocatorEntryRole:
- return qVariantFromValue(mEntries.at(index.row()));
+ return QVariant::fromValue(mEntries.at(index.row()));
case int(HighlightingItemRole::StartColumn):
case int(HighlightingItemRole::Length): {
LocatorFilterEntry &entry = mEntries[index.row()];
@@ -579,8 +579,9 @@ LocatorWidget::LocatorWidget(Locator *locator) :
m_fileLineEdit->setButtonMenu(Utils::FancyLineEdit::Left, m_filterMenu);
- connect(m_refreshAction, &QAction::triggered,
- locator, [locator]() { locator->refresh(); });
+ connect(m_refreshAction, &QAction::triggered, locator, [locator]() {
+ locator->refresh(locator->filters());
+ });
connect(m_configureAction, &QAction::triggered, this, &LocatorWidget::showConfigureDialog);
connect(m_fileLineEdit, &QLineEdit::textChanged,
this, &LocatorWidget::showPopupDelayed);
diff --git a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp
index 575e992557..fe67e5d884 100644
--- a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp
+++ b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp
@@ -76,7 +76,7 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
const QRegularExpressionMatch match = regexp.match(displayName);
if (match.hasMatch()) {
LocatorFilterEntry filterEntry(this, displayName, QString(fileName + fp.postfix));
- filterEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName));
+ filterEntry.extraInfo = FilePath::fromString(fileName).shortNativePath();
filterEntry.fileName = fileName;
filterEntry.highlightInfo = highlightInfo(match);
if (match.capturedStart() == 0)
diff --git a/src/plugins/coreplugin/locator/opendocumentsfilter.h b/src/plugins/coreplugin/locator/opendocumentsfilter.h
index 8d140c86d7..956dea22d2 100644
--- a/src/plugins/coreplugin/locator/opendocumentsfilter.h
+++ b/src/plugins/coreplugin/locator/opendocumentsfilter.h
@@ -56,7 +56,7 @@ private:
class Entry
{
public:
- Utils::FileName fileName;
+ Utils::FilePath fileName;
QString displayName;
};
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 2e8b5f2ad1..dd724d9f9c 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -100,25 +100,26 @@ namespace Internal {
enum { debugMainWindow = 0 };
-MainWindow::MainWindow() :
- AppMainWindow(),
- m_coreImpl(new ICore(this)),
- m_lowPrioAdditionalContexts(Constants::C_GLOBAL),
- m_settingsDatabase(new SettingsDatabase(QFileInfo(PluginManager::settings()->fileName()).path(),
- QLatin1String(Constants::IDE_CASED_ID),
- this)),
- m_progressManager(new ProgressManagerPrivate),
- m_jsExpander(new JsExpander),
- m_vcsManager(new VcsManager),
- m_modeStack(new FancyTabWidget(this)),
- m_generalSettings(new GeneralSettings),
- m_systemSettings(new SystemSettings),
- m_shortcutSettings(new ShortcutSettings),
- m_toolSettings(new ToolSettings),
- m_mimeTypeSettings(new MimeTypeSettings),
- m_systemEditor(new SystemEditor),
- m_toggleLeftSideBarButton(new QToolButton),
- m_toggleRightSideBarButton(new QToolButton)
+MainWindow::MainWindow()
+ : AppMainWindow()
+ , m_coreImpl(new ICore(this))
+ , m_lowPrioAdditionalContexts(Constants::C_GLOBAL)
+ , m_settingsDatabase(
+ new SettingsDatabase(QFileInfo(PluginManager::settings()->fileName()).path(),
+ QLatin1String(Constants::IDE_CASED_ID),
+ this))
+ , m_progressManager(new ProgressManagerPrivate)
+ , m_jsExpander(JsExpander::createGlobalJsExpander())
+ , m_vcsManager(new VcsManager)
+ , m_modeStack(new FancyTabWidget(this))
+ , m_generalSettings(new GeneralSettings)
+ , m_systemSettings(new SystemSettings)
+ , m_shortcutSettings(new ShortcutSettings)
+ , m_toolSettings(new ToolSettings)
+ , m_mimeTypeSettings(new MimeTypeSettings)
+ , m_systemEditor(new SystemEditor)
+ , m_toggleLeftSideBarButton(new QToolButton)
+ , m_toggleRightSideBarButton(new QToolButton)
{
(void) new DocumentManager(this);
@@ -321,7 +322,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
return;
}
- ICore::saveSettings();
+ ICore::saveSettings(ICore::MainWindowClosing);
// Save opened files
if (!DocumentManager::saveAllModifiedDocuments()) {
diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp
index 709dcf62aa..76593c18d0 100644
--- a/src/plugins/coreplugin/manhattanstyle.cpp
+++ b/src/plugins/coreplugin/manhattanstyle.cpp
@@ -722,11 +722,11 @@ void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *opt
bool notElideAsterisk = widget && widget->property("notelideasterisk").toBool()
&& cb->currentText.endsWith(asterisk)
- && option->fontMetrics.width(cb->currentText) > elideWidth;
+ && option->fontMetrics.horizontalAdvance(cb->currentText) > elideWidth;
QString text;
if (notElideAsterisk) {
- elideWidth -= option->fontMetrics.width(asterisk);
+ elideWidth -= option->fontMetrics.horizontalAdvance(asterisk);
text = asterisk;
}
text.prepend(option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, elideWidth));
@@ -980,7 +980,7 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti
QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9);
if (!alignarrow) {
- int labelwidth = option->fontMetrics.width(cb->currentText);
+ int labelwidth = option->fontMetrics.horizontalAdvance(cb->currentText);
if (reverse)
arrowRect.moveLeft(qMax(rect.width() - labelwidth - menuButtonWidth - 2, 4));
else
diff --git a/src/plugins/coreplugin/messagemanager.cpp b/src/plugins/coreplugin/messagemanager.cpp
index c4bf4269a4..5644db547f 100644
--- a/src/plugins/coreplugin/messagemanager.cpp
+++ b/src/plugins/coreplugin/messagemanager.cpp
@@ -24,14 +24,18 @@
****************************************************************************/
#include "messagemanager.h"
+
#include "messageoutputwindow.h"
#include <extensionsystem/pluginmanager.h>
+#include <utils/qtcassert.h>
+
+#include <QFont>
using namespace Core;
static MessageManager *m_instance = nullptr;
-Internal::MessageOutputWindow *m_messageOutputWindow = nullptr;
+static Internal::MessageOutputWindow *m_messageOutputWindow = nullptr;
MessageManager *MessageManager::instance()
{
@@ -40,8 +44,8 @@ MessageManager *MessageManager::instance()
void MessageManager::showOutputPane(Core::MessageManager::PrintToOutputPaneFlags flags)
{
- if (!m_messageOutputWindow)
- return;
+ QTC_ASSERT(m_messageOutputWindow, return);
+
if (flags & Flash) {
m_messageOutputWindow->flash();
} else if (flags & Silent) {
@@ -73,11 +77,24 @@ void MessageManager::init()
ExtensionSystem::PluginManager::addObject(m_messageOutputWindow);
}
+void MessageManager::setFont(const QFont &font)
+{
+ QTC_ASSERT(m_messageOutputWindow, return);
+
+ m_messageOutputWindow->setFont(font);
+}
+
+void MessageManager::setWheelZoomEnabled(bool enabled)
+{
+ QTC_ASSERT(m_messageOutputWindow, return);
+
+ m_messageOutputWindow->setWheelZoomEnabled(enabled);
+}
+
void MessageManager::write(const QString &text, PrintToOutputPaneFlags flags)
{
- if (!m_messageOutputWindow)
- return;
+ QTC_ASSERT(m_messageOutputWindow, return);
+
showOutputPane(flags);
- m_messageOutputWindow->append(text + QLatin1Char('\n'));
+ m_messageOutputWindow->append(text + '\n');
}
-
diff --git a/src/plugins/coreplugin/messagemanager.h b/src/plugins/coreplugin/messagemanager.h
index d530db8603..6ead1ddeb8 100644
--- a/src/plugins/coreplugin/messagemanager.h
+++ b/src/plugins/coreplugin/messagemanager.h
@@ -27,10 +27,14 @@
#include "core_global.h"
#include "ioutputpane.h"
-#include <QMetaType>
+#include <QMetaType>
#include <QObject>
+QT_BEGIN_NAMESPACE
+class QFont;
+QT_END_NAMESPACE
+
namespace Core {
namespace Internal { class MainWindow; }
@@ -55,6 +59,9 @@ public:
static void showOutputPane(Core::MessageManager::PrintToOutputPaneFlags flags = NoModeSwitch);
+ static void setFont(const QFont &font);
+ static void setWheelZoomEnabled(bool enabled);
+
public slots:
static void write(const QString &text,
Core::MessageManager::PrintToOutputPaneFlags flags = NoModeSwitch);
diff --git a/src/plugins/coreplugin/messageoutputwindow.cpp b/src/plugins/coreplugin/messageoutputwindow.cpp
index 35a1bd50be..c7c752e155 100644
--- a/src/plugins/coreplugin/messageoutputwindow.cpp
+++ b/src/plugins/coreplugin/messageoutputwindow.cpp
@@ -30,13 +30,20 @@
#include "find/basetextfind.h"
#include <aggregation/aggregate.h>
+#include <coreplugin/icore.h>
+#include <utils/utilsicons.h>
+
+#include <QFont>
+#include <QToolButton>
namespace Core {
namespace Internal {
+const char zoomSettingsKey[] = "Core/MessageOutput/Zoom";
+
MessageOutputWindow::MessageOutputWindow()
{
- m_widget = new OutputWindow(Context(Constants::C_GENERAL_OUTPUT_PANE));
+ m_widget = new OutputWindow(Context(Constants::C_GENERAL_OUTPUT_PANE), zoomSettingsKey);
m_widget->setReadOnly(true);
// Let selected text be colored as if the text edit was editable,
// otherwise the highlight for searching is too light
@@ -46,9 +53,20 @@ MessageOutputWindow::MessageOutputWindow()
QColor activeHighlightedText = p.color(QPalette::Active, QPalette::HighlightedText);
p.setColor(QPalette::HighlightedText, activeHighlightedText);
m_widget->setPalette(p);
+
+ connect(this, &IOutputPane::zoomIn, m_widget, &Core::OutputWindow::zoomIn);
+ connect(this, &IOutputPane::zoomOut, m_widget, &Core::OutputWindow::zoomOut);
+ connect(this, &IOutputPane::resetZoom, m_widget, &Core::OutputWindow::resetZoom);
+ connect(this, &IOutputPane::fontChanged, m_widget, &OutputWindow::setBaseFont);
+ connect(this, &IOutputPane::wheelZoomEnabledChanged, m_widget, &OutputWindow::setWheelZoomEnabled);
+
auto agg = new Aggregation::Aggregate;
agg->add(m_widget);
agg->add(new BaseTextFind(m_widget));
+
+ setupFilterUi("MessageOutputPane.Filter");
+ setFilteringEnabled(true);
+ setupContext(Constants::C_GENERAL_OUTPUT_PANE, m_widget);
}
MessageOutputWindow::~MessageOutputWindow()
@@ -126,5 +144,10 @@ bool MessageOutputWindow::canNavigate() const
return false;
}
+void MessageOutputWindow::updateFilter()
+{
+ m_widget->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp());
+}
+
} // namespace Internal
} // namespace Core
diff --git a/src/plugins/coreplugin/messageoutputwindow.h b/src/plugins/coreplugin/messageoutputwindow.h
index bd8c5ca3d4..69f940dc8e 100644
--- a/src/plugins/coreplugin/messageoutputwindow.h
+++ b/src/plugins/coreplugin/messageoutputwindow.h
@@ -27,6 +27,11 @@
#include "ioutputpane.h"
+QT_BEGIN_NAMESPACE
+class QFont;
+class QToolButton;
+QT_END_NAMESPACE
+
namespace Core {
class OutputWindow;
@@ -41,7 +46,6 @@ public:
~MessageOutputWindow() override;
QWidget *outputWidget(QWidget *parent) override;
- QList<QWidget*> toolBarWidgets() const override { return {}; }
QString displayName() const override;
int priorityInStatusBar() const override;
@@ -60,6 +64,8 @@ public:
bool canNavigate() const override;
private:
+ void updateFilter() override;
+
OutputWindow *m_widget;
};
diff --git a/src/plugins/coreplugin/mimetypemagicdialog.cpp b/src/plugins/coreplugin/mimetypemagicdialog.cpp
index 5c1566d022..36a5f099c6 100644
--- a/src/plugins/coreplugin/mimetypemagicdialog.cpp
+++ b/src/plugins/coreplugin/mimetypemagicdialog.cpp
@@ -55,7 +55,7 @@ MimeTypeMagicDialog::MimeTypeMagicDialog(QWidget *parent) :
connect(ui.informationLabel, &QLabel::linkActivated, this, [](const QString &link) {
QDesktopServices::openUrl(QUrl(link));
});
- connect(ui.typeSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(ui.typeSelector, QOverload<int>::of(&QComboBox::activated),
this, [this]() {
if (ui.useRecommendedGroupBox->isChecked())
setToRecommendedValues();
diff --git a/src/plugins/coreplugin/mimetypesettings.cpp b/src/plugins/coreplugin/mimetypesettings.cpp
index a5750d13c7..7b4d891339 100644
--- a/src/plugins/coreplugin/mimetypesettings.cpp
+++ b/src/plugins/coreplugin/mimetypesettings.cpp
@@ -157,9 +157,9 @@ QVariant MimeTypeSettingsModel::data(const QModelIndex &modelIndex, int role) co
return defaultHandler ? defaultHandler->displayName() : QString();
}
} else if (role == Qt::EditRole) {
- return qVariantFromValue(handlersForMimeType(m_mimeTypes.at(modelIndex.row())));
+ return QVariant::fromValue(handlersForMimeType(m_mimeTypes.at(modelIndex.row())));
} else if (role == int(Role::DefaultHandler)) {
- return qVariantFromValue(defaultHandlerForMimeType(m_mimeTypes.at(modelIndex.row())));
+ return QVariant::fromValue(defaultHandlerForMimeType(m_mimeTypes.at(modelIndex.row())));
} else if (role == Qt::FontRole) {
if (column == 1) {
const Utils::MimeType &type = m_mimeTypes.at(modelIndex.row());
@@ -397,7 +397,7 @@ void MimeTypeSettingsPrivate::editMagicHeaderRowData(const int row, const MagicD
item->setText(1, QString::fromLatin1(Utils::Internal::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, qVariantFromValue(data));
+ item->setData(0, Qt::UserRole, QVariant::fromValue(data));
m_ui.magicHeadersTreeWidget->takeTopLevelItem(row);
m_ui.magicHeadersTreeWidget->insertTopLevelItem(row, item);
m_ui.magicHeadersTreeWidget->setCurrentItem(item);
@@ -501,7 +501,7 @@ void MimeTypeSettingsPrivate::ensurePendingMimeType(const Utils::MimeType &mimeT
void MimeTypeSettingsPrivate::writeUserModifiedMimeTypes()
{
- static Utils::FileName modifiedMimeTypesFile = Utils::FileName::fromString(
+ static Utils::FilePath modifiedMimeTypesFile = Utils::FilePath::fromString(
ICore::userResourcePath() + QLatin1String(kModifiedMimeTypesFile));
if (QFile::exists(modifiedMimeTypesFile.toString())
@@ -690,7 +690,7 @@ void MimeEditorDelegate::setEditorData(QWidget *editor, const QModelIndex &index
auto box = static_cast<QComboBox *>(editor);
const auto factories = index.model()->data(index, Qt::EditRole).value<QList<IEditorFactory *>>();
for (IEditorFactory *factory : factories)
- box->addItem(factory->displayName(), qVariantFromValue(factory));
+ box->addItem(factory->displayName(), QVariant::fromValue(factory));
int currentIndex = factories.indexOf(
index.model()
->data(index, int(MimeTypeSettingsModel::Role::DefaultHandler))
diff --git a/src/plugins/coreplugin/navigationsubwidget.cpp b/src/plugins/coreplugin/navigationsubwidget.cpp
index c8aed179c5..ab4858e388 100644
--- a/src/plugins/coreplugin/navigationsubwidget.cpp
+++ b/src/plugins/coreplugin/navigationsubwidget.cpp
@@ -97,7 +97,7 @@ NavigationSubWidget::NavigationSubWidget(NavigationWidget *parentWidget, int pos
setFactoryIndex(factoryIndex);
connect(m_navigationComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &NavigationSubWidget::comboBoxIndexChanged);
comboBoxIndexChanged(factoryIndex);
diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp
index f223cfa777..aae3a618f9 100644
--- a/src/plugins/coreplugin/navigationwidget.cpp
+++ b/src/plugins/coreplugin/navigationwidget.cpp
@@ -260,7 +260,7 @@ void NavigationWidget::setFactories(const QList<INavigationWidgetFactory *> &fac
}
QStandardItem *newRow = new QStandardItem(factory->displayName());
- newRow->setData(qVariantFromValue(factory), FactoryObjectRole);
+ newRow->setData(QVariant::fromValue(factory), FactoryObjectRole);
newRow->setData(QVariant::fromValue(factory->id()), FactoryIdRole);
newRow->setData(factory->priority(), FactoryPriorityRole);
d->m_factoryModel->appendRow(newRow);
diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp
index 7825126565..7cf2ec2c90 100644
--- a/src/plugins/coreplugin/outputpanemanager.cpp
+++ b/src/plugins/coreplugin/outputpanemanager.cpp
@@ -35,8 +35,10 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/actionmanager/commandbutton.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/find/optionspopup.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
@@ -88,18 +90,152 @@ static bool g_managerConstructed = false; // For debugging reasons.
// OutputPane
IOutputPane::IOutputPane(QObject *parent)
- : QObject(parent)
+ : QObject(parent),
+ m_zoomInButton(new Core::CommandButton),
+ m_zoomOutButton(new Core::CommandButton)
{
// We need all pages first. Ignore latecomers and shout.
QTC_ASSERT(!g_managerConstructed, return);
g_outputPanes.append(OutputPaneData(this));
+
+ m_zoomInButton->setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
+ m_zoomInButton->setCommandId(Constants::ZOOM_IN);
+ connect(m_zoomInButton, &QToolButton::clicked, this, [this] { emit zoomIn(1); });
+
+ m_zoomOutButton->setIcon(Utils::Icons::MINUS.icon());
+ m_zoomOutButton->setCommandId(Constants::ZOOM_OUT);
+ connect(m_zoomOutButton, &QToolButton::clicked, this, [this] { emit zoomOut(1); });
}
IOutputPane::~IOutputPane()
{
+ if (m_context)
+ ICore::removeContextObject(m_context);
+
const int i = Utils::indexOf(g_outputPanes, Utils::equal(&OutputPaneData::pane, this));
QTC_ASSERT(i >= 0, return);
delete g_outputPanes.at(i).button;
+
+ delete m_zoomInButton;
+ delete m_zoomOutButton;
+}
+
+QList<QWidget *> IOutputPane::toolBarWidgets() const
+{
+ QList<QWidget *> widgets;
+ if (m_filterOutputLineEdit)
+ widgets << m_filterOutputLineEdit;
+ return widgets << m_zoomInButton << m_zoomOutButton;
+}
+
+void IOutputPane::setFont(const QFont &font)
+{
+ emit fontChanged(font);
+}
+
+void IOutputPane::setWheelZoomEnabled(bool enabled)
+{
+ emit wheelZoomEnabledChanged(enabled);
+}
+
+void IOutputPane::setupFilterUi(const QString &historyKey)
+{
+ m_filterOutputLineEdit = new FancyLineEdit;
+ m_filterActionRegexp = new QAction(this);
+ m_filterActionRegexp->setCheckable(true);
+ m_filterActionRegexp->setText(tr("Use Regular Expressions"));
+ connect(m_filterActionRegexp, &QAction::toggled, this, &IOutputPane::setRegularExpressions);
+ Core::ActionManager::registerAction(m_filterActionRegexp, filterRegexpActionId());
+
+ m_filterActionCaseSensitive = new QAction(this);
+ m_filterActionCaseSensitive->setCheckable(true);
+ m_filterActionCaseSensitive->setText(tr("Case Sensitive"));
+ connect(m_filterActionCaseSensitive, &QAction::toggled, this, &IOutputPane::setCaseSensitive);
+ Core::ActionManager::registerAction(m_filterActionCaseSensitive,
+ filterCaseSensitivityActionId());
+
+ m_filterOutputLineEdit->setPlaceholderText(tr("Filter output..."));
+ m_filterOutputLineEdit->setButtonVisible(FancyLineEdit::Left, true);
+ m_filterOutputLineEdit->setButtonIcon(FancyLineEdit::Left, Icons::MAGNIFIER.icon());
+ m_filterOutputLineEdit->setFiltering(true);
+ m_filterOutputLineEdit->setEnabled(false);
+ m_filterOutputLineEdit->setHistoryCompleter(historyKey);
+ connect(m_filterOutputLineEdit, &FancyLineEdit::textChanged,
+ this, &IOutputPane::updateFilter);
+ connect(m_filterOutputLineEdit, &FancyLineEdit::returnPressed,
+ this, &IOutputPane::updateFilter);
+ connect(m_filterOutputLineEdit, &FancyLineEdit::leftButtonClicked,
+ this, &IOutputPane::filterOutputButtonClicked);
+}
+
+QString IOutputPane::filterText() const
+{
+ return m_filterOutputLineEdit->text();
+}
+
+void IOutputPane::setFilteringEnabled(bool enable)
+{
+ m_filterOutputLineEdit->setEnabled(enable);
+}
+
+void IOutputPane::setupContext(const char *context, QWidget *widget)
+{
+ QTC_ASSERT(!m_context, return);
+ m_context = new IContext(this);
+ m_context->setContext(Context(context));
+ m_context->setWidget(widget);
+ ICore::addContextObject(m_context);
+
+ const auto zoomInAction = new QAction(this);
+ Core::ActionManager::registerAction(zoomInAction, Constants::ZOOM_IN, m_context->context());
+ connect(zoomInAction, &QAction::triggered, this, [this] { emit zoomIn(1); });
+ const auto zoomOutAction = new QAction(this);
+ Core::ActionManager::registerAction(zoomOutAction, Constants::ZOOM_OUT, m_context->context());
+ connect(zoomOutAction, &QAction::triggered, this, [this] { emit zoomOut(1); });
+ const auto resetZoomAction = new QAction(this);
+ Core::ActionManager::registerAction(resetZoomAction, Constants::ZOOM_RESET,
+ m_context->context());
+ connect(resetZoomAction, &QAction::triggered, this, &IOutputPane::resetZoom);
+}
+
+void IOutputPane::setZoomButtonsEnabled(bool enabled)
+{
+ m_zoomInButton->setEnabled(enabled);
+ m_zoomOutButton->setEnabled(enabled);
+}
+
+void IOutputPane::updateFilter()
+{
+ QTC_ASSERT(false, qDebug() << "updateFilter() needs to get re-implemented");
+}
+
+void IOutputPane::filterOutputButtonClicked()
+{
+ auto popup = new Core::OptionsPopup(m_filterOutputLineEdit,
+ {filterRegexpActionId(), filterCaseSensitivityActionId()});
+ popup->show();
+}
+
+void IOutputPane::setRegularExpressions(bool regularExpressions)
+{
+ m_filterRegexp = regularExpressions;
+ updateFilter();
+}
+
+Id IOutputPane::filterRegexpActionId() const
+{
+ return Id("OutputFilter.RegularExpressions").withSuffix(metaObject()->className());
+}
+
+Id IOutputPane::filterCaseSensitivityActionId() const
+{
+ return Id("OutputFilter.CaseSensitive").withSuffix(metaObject()->className());
+}
+
+void IOutputPane::setCaseSensitive(bool caseSensitive)
+{
+ m_filterCaseSensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ updateFilter();
}
namespace Internal {
@@ -324,7 +460,7 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) :
m_opToolBarWidgets->addWidget(toolButtonsContainer);
- minTitleWidth = qMax(minTitleWidth, titleFm.width(outPane->displayName()));
+ minTitleWidth = qMax(minTitleWidth, titleFm.horizontalAdvance(outPane->displayName()));
QString suffix = outPane->displayName().simplified();
suffix.remove(QLatin1Char(' '));
@@ -636,7 +772,7 @@ OutputPaneToggleButton::OutputPaneToggleButton(int number, const QString &text,
m_flashTimer->setDirection(QTimeLine::Forward);
m_flashTimer->setCurveShape(QTimeLine::SineCurve);
m_flashTimer->setFrameRange(0, 92);
- auto updateSlot = static_cast<void (QWidget::*)()>(&QWidget::update);
+ auto updateSlot = QOverload<>::of(&QWidget::update);
connect(m_flashTimer, &QTimeLine::valueChanged, this, updateSlot);
connect(m_flashTimer, &QTimeLine::finished, this, updateSlot);
updateToolTip();
@@ -667,7 +803,7 @@ void OutputPaneToggleButton::paintEvent(QPaintEvent*)
{
const QFontMetrics fm = fontMetrics();
const int baseLine = (height() - fm.height() + 1) / 2 + fm.ascent();
- const int numberWidth = fm.width(m_number);
+ const int numberWidth = fm.horizontalAdvance(m_number);
QPainter p(this);
diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp
index d53abdd32d..e89f999a47 100644
--- a/src/plugins/coreplugin/outputwindow.cpp
+++ b/src/plugins/coreplugin/outputwindow.cpp
@@ -33,6 +33,7 @@
#include <utils/synchronousprocess.h>
#include <QAction>
+#include <QRegularExpression>
#include <QScrollBar>
#include <QTextBlock>
@@ -58,22 +59,28 @@ public:
IContext *outputWindowContext = nullptr;
Utils::OutputFormatter *formatter = nullptr;
+ QString settingsKey;
bool enforceNewline = false;
bool scrollToBottom = true;
bool linksActive = true;
- Qt::MouseButton mouseButtonPressed = Qt::NoButton;
- bool m_zoomEnabled = false;
- float m_originalFontSize = 0.;
+ bool zoomEnabled = false;
+ float originalFontSize = 0.;
+ bool originalReadOnly = false;
int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
+ Qt::MouseButton mouseButtonPressed = Qt::NoButton;
QTextCursor cursor;
+ QString filterText;
+ int lastFilteredBlockNumber = -1;
+ QPalette originalPalette;
+ OutputWindow::FilterModeFlags filterMode = OutputWindow::FilterModeFlag::Default;
};
} // namespace Internal
/*******************/
-OutputWindow::OutputWindow(Context context, QWidget *parent)
+OutputWindow::OutputWindow(Context context, const QString &settingsKey, QWidget *parent)
: QPlainTextEdit(parent)
, d(new Internal::OutputWindowPrivate(document()))
{
@@ -83,6 +90,8 @@ OutputWindow::OutputWindow(Context context, QWidget *parent)
setMouseTracking(true);
setUndoRedoEnabled(false);
+ d->settingsKey = settingsKey;
+
d->outputWindowContext = new IContext;
d->outputWindowContext->setContext(context);
d->outputWindowContext->setWidget(this);
@@ -108,11 +117,16 @@ OutputWindow::OutputWindow(Context context, QWidget *parent)
connect(copyAction, &QAction::triggered, this, &QPlainTextEdit::copy);
connect(pasteAction, &QAction::triggered, this, &QPlainTextEdit::paste);
connect(selectAllAction, &QAction::triggered, this, &QPlainTextEdit::selectAll);
+ connect(this, &QPlainTextEdit::blockCountChanged, this, &OutputWindow::filterNewContent);
connect(this, &QPlainTextEdit::undoAvailable, undoAction, &QAction::setEnabled);
connect(this, &QPlainTextEdit::redoAvailable, redoAction, &QAction::setEnabled);
connect(this, &QPlainTextEdit::copyAvailable, cutAction, &QAction::setEnabled); // OutputWindow never read-only
connect(this, &QPlainTextEdit::copyAvailable, copyAction, &QAction::setEnabled);
+ connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested, this, [this] {
+ if (!d->settingsKey.isEmpty())
+ Core::ICore::settings()->setValue(d->settingsKey, fontZoom());
+ });
undoAction->setEnabled(false);
redoAction->setEnabled(false);
@@ -125,7 +139,12 @@ OutputWindow::OutputWindow(Context context, QWidget *parent)
this, &OutputWindow::scrollToBottom);
m_lastMessage.start();
- d->m_originalFontSize = font().pointSizeF();
+ d->originalFontSize = font().pointSizeF();
+
+ if (!d->settingsKey.isEmpty()) {
+ float zoom = Core::ICore::settings()->value(d->settingsKey).toFloat();
+ setFontZoom(zoom);
+ }
}
OutputWindow::~OutputWindow()
@@ -210,7 +229,7 @@ void OutputWindow::showEvent(QShowEvent *e)
void OutputWindow::wheelEvent(QWheelEvent *e)
{
- if (d->m_zoomEnabled) {
+ if (d->zoomEnabled) {
if (e->modifiers() & Qt::ControlModifier) {
float delta = e->angleDelta().y() / 120.f;
zoomInF(delta);
@@ -225,31 +244,104 @@ void OutputWindow::wheelEvent(QWheelEvent *e)
void OutputWindow::setBaseFont(const QFont &newFont)
{
float zoom = fontZoom();
- d->m_originalFontSize = newFont.pointSizeF();
+ d->originalFontSize = newFont.pointSizeF();
QFont tmp = newFont;
- float newZoom = qMax(d->m_originalFontSize + zoom, 4.0f);
+ float newZoom = qMax(d->originalFontSize + zoom, 4.0f);
tmp.setPointSizeF(newZoom);
setFont(tmp);
}
float OutputWindow::fontZoom() const
{
- return font().pointSizeF() - d->m_originalFontSize;
+ return font().pointSizeF() - d->originalFontSize;
}
void OutputWindow::setFontZoom(float zoom)
{
QFont f = font();
- if (f.pointSizeF() == d->m_originalFontSize + zoom)
+ if (f.pointSizeF() == d->originalFontSize + zoom)
return;
- float newZoom = qMax(d->m_originalFontSize + zoom, 4.0f);
+ float newZoom = qMax(d->originalFontSize + zoom, 4.0f);
f.setPointSizeF(newZoom);
setFont(f);
}
void OutputWindow::setWheelZoomEnabled(bool enabled)
{
- d->m_zoomEnabled = enabled;
+ d->zoomEnabled = enabled;
+}
+
+void OutputWindow::updateFilterProperties(const QString &filterText,
+ Qt::CaseSensitivity caseSensitivity, bool isRegexp)
+{
+ FilterModeFlags flags;
+ flags.setFlag(FilterModeFlag::CaseSensitive, caseSensitivity == Qt::CaseSensitive)
+ .setFlag(FilterModeFlag::RegExp, isRegexp);
+ if (d->filterMode == flags && d->filterText == filterText)
+ return;
+ d->lastFilteredBlockNumber = -1;
+ if (d->filterText != filterText) {
+ const bool filterTextWasEmpty = d->filterText.isEmpty();
+ d->filterText = filterText;
+
+ // Update textedit's background color
+ if (filterText.isEmpty() && !filterTextWasEmpty) {
+ setPalette(d->originalPalette);
+ setReadOnly(d->originalReadOnly);
+ }
+ if (!filterText.isEmpty() && filterTextWasEmpty) {
+ d->originalReadOnly = isReadOnly();
+ setReadOnly(true);
+ const auto newBgColor = [this] {
+ const QColor currentColor = palette().color(QPalette::Base);
+ const int factor = 120;
+ return currentColor.value() < 128 ? currentColor.lighter(factor)
+ : currentColor.darker(factor);
+ };
+ QPalette p = palette();
+ p.setColor(QPalette::Base, newBgColor());
+ setPalette(p);
+ }
+ }
+ d->filterMode = flags;
+ filterNewContent();
+}
+
+void OutputWindow::filterNewContent()
+{
+ bool atBottom = isScrollbarAtBottom();
+
+ QTextBlock lastBlock = document()->findBlockByNumber(d->lastFilteredBlockNumber);
+ if (!lastBlock.isValid())
+ lastBlock = document()->begin();
+
+ if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::RegExp)) {
+ QRegularExpression regExp(d->filterText);
+ if (!d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive))
+ regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+
+ for (; lastBlock != document()->end(); lastBlock = lastBlock.next())
+ lastBlock.setVisible(d->filterText.isEmpty()
+ || regExp.match(lastBlock.text()).hasMatch());
+ } else {
+ if (d->filterMode.testFlag(OutputWindow::FilterModeFlag::CaseSensitive)) {
+ for (; lastBlock != document()->end(); lastBlock = lastBlock.next())
+ lastBlock.setVisible(d->filterText.isEmpty()
+ || lastBlock.text().contains(d->filterText));
+ } else {
+ for (; lastBlock != document()->end(); lastBlock = lastBlock.next())
+ lastBlock.setVisible(d->filterText.isEmpty()
+ || lastBlock.text().toLower().contains(d->filterText.toLower()));
+ }
+ }
+
+ d->lastFilteredBlockNumber = document()->lastBlock().blockNumber();
+
+ // FIXME: Why on earth is this necessary? We should probably do something else instead...
+ setDocument(document());
+
+ if (atBottom)
+ scrollToBottom();
}
QString OutputWindow::doNewlineEnforcement(const QString &out)
diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h
index 5e966c64ec..204a1106a9 100644
--- a/src/plugins/coreplugin/outputwindow.h
+++ b/src/plugins/coreplugin/outputwindow.h
@@ -30,9 +30,9 @@
#include <utils/outputformat.h>
+#include <QElapsedTimer>
#include <QPlainTextEdit>
#include <QTimer>
-#include <QTime>
namespace Utils { class OutputFormatter; }
@@ -45,7 +45,14 @@ class CORE_EXPORT OutputWindow : public QPlainTextEdit
Q_OBJECT
public:
- OutputWindow(Context context, QWidget *parent = nullptr);
+ enum class FilterModeFlag {
+ Default = 0x00, // Plain text, non case sensitive, for initialization
+ RegExp = 0x01,
+ CaseSensitive = 0x02,
+ };
+ Q_DECLARE_FLAGS(FilterModeFlags, FilterModeFlag)
+
+ OutputWindow(Context context, const QString &settingsKey, QWidget *parent = nullptr);
~OutputWindow() override;
Utils::OutputFormatter *formatter() const;
@@ -68,8 +75,11 @@ public:
void setBaseFont(const QFont &newFont);
float fontZoom() const;
void setFontZoom(float zoom);
+ void resetZoom() { setFontZoom(0); }
void setWheelZoomEnabled(bool enabled);
+ void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity, bool regexp);
+
signals:
void wheelZoom();
@@ -89,9 +99,10 @@ protected:
private:
using QPlainTextEdit::setFont; // call setBaseFont instead, which respects the zoom factor
QTimer m_scrollTimer;
- QTime m_lastMessage;
+ QElapsedTimer m_lastMessage;
void enableUndoRedo();
QString doNewlineEnforcement(const QString &out);
+ void filterNewContent();
Internal::OutputWindowPrivate *d;
};
diff --git a/src/plugins/coreplugin/patchtool.cpp b/src/plugins/coreplugin/patchtool.cpp
index 724fabd133..1442046325 100644
--- a/src/plugins/coreplugin/patchtool.cpp
+++ b/src/plugins/coreplugin/patchtool.cpp
@@ -88,7 +88,7 @@ static bool runPatchHelper(const QByteArray &input, const QString &workingDirect
return false;
}
- if (!Utils::FileName::fromString(patch).exists()
+ if (!Utils::FilePath::fromString(patch).exists()
&& !Utils::Environment::systemEnvironment().searchInPath(patch).exists()) {
MessageManager::write(QApplication::translate("Core::PatchTool", "The patch-command configured in the general \"Environment\" settings does not exist."));
return false;
diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.cpp b/src/plugins/coreplugin/progressmanager/futureprogress.cpp
index d7eeec9ff4..32193fd08b 100644
--- a/src/plugins/coreplugin/progressmanager/futureprogress.cpp
+++ b/src/plugins/coreplugin/progressmanager/futureprogress.cpp
@@ -71,6 +71,7 @@ public:
FutureProgress *m_q;
bool m_fadeStarting;
bool m_isFading;
+ bool m_isSubtitleVisibleInStatusBar = false;
};
FutureProgressPrivate::FutureProgressPrivate(FutureProgress *q) :
@@ -188,6 +189,33 @@ QString FutureProgress::title() const
return d->m_progress->title();
}
+void FutureProgress::setSubtitle(const QString &subtitle)
+{
+ if (subtitle != d->m_progress->subtitle()) {
+ d->m_progress->setSubtitle(subtitle);
+ if (d->m_isSubtitleVisibleInStatusBar)
+ emit subtitleInStatusBarChanged();
+ }
+}
+
+QString FutureProgress::subtitle() const
+{
+ return d->m_progress->subtitle();
+}
+
+void FutureProgress::setSubtitleVisibleInStatusBar(bool visible)
+{
+ if (visible != d->m_isSubtitleVisibleInStatusBar) {
+ d->m_isSubtitleVisibleInStatusBar = visible;
+ emit subtitleInStatusBarChanged();
+ }
+}
+
+bool FutureProgress::isSubtitleVisibleInStatusBar() const
+{
+ return d->m_isSubtitleVisibleInStatusBar;
+}
+
void FutureProgress::cancel()
{
d->m_watcher.future().cancel();
diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.h b/src/plugins/coreplugin/progressmanager/futureprogress.h
index 3f591b2b94..09b178dff2 100644
--- a/src/plugins/coreplugin/progressmanager/futureprogress.h
+++ b/src/plugins/coreplugin/progressmanager/futureprogress.h
@@ -56,6 +56,12 @@ public:
void setTitle(const QString &title);
QString title() const;
+ void setSubtitle(const QString &subtitle);
+ QString subtitle() const;
+
+ void setSubtitleVisibleInStatusBar(bool visible);
+ bool isSubtitleVisibleInStatusBar() const;
+
void setType(Id type);
Id type() const;
@@ -83,6 +89,7 @@ signals:
void fadeStarted();
void statusBarWidgetChanged();
+ void subtitleInStatusBarChanged();
protected:
void mousePressEvent(QMouseEvent *event) override;
diff --git a/src/plugins/coreplugin/progressmanager/progressbar.cpp b/src/plugins/coreplugin/progressmanager/progressbar.cpp
index 2dd28712e9..bf6f7d8e19 100644
--- a/src/plugins/coreplugin/progressmanager/progressbar.cpp
+++ b/src/plugins/coreplugin/progressmanager/progressbar.cpp
@@ -139,6 +139,18 @@ bool ProgressBar::isTitleVisible() const
return m_titleVisible;
}
+void ProgressBar::setSubtitle(const QString &subtitle)
+{
+ m_subtitle = subtitle;
+ updateGeometry();
+ update();
+}
+
+QString ProgressBar::subtitle() const
+{
+ return m_subtitle;
+}
+
void ProgressBar::setSeparatorVisible(bool visible)
{
if (m_separatorVisible == visible)
@@ -176,9 +188,13 @@ QSize ProgressBar::sizeHint() const
int width = 50;
int height = PROGRESSBAR_HEIGHT + 5;
if (m_titleVisible) {
- QFontMetrics fm(titleFont());
- width = qMax(width, fm.width(m_title) + 16);
+ const QFontMetrics fm(titleFont());
+ width = qMax(width, fm.horizontalAdvance(m_title) + 16);
height += fm.height() + 5;
+ if (!m_subtitle.isEmpty()) {
+ width = qMax(width, fm.horizontalAdvance(m_subtitle) + 16);
+ height += fm.height() + 5;
+ }
}
if (m_separatorVisible)
height += SEPARATOR_HEIGHT;
@@ -227,14 +243,13 @@ void ProgressBar::paintEvent(QPaintEvent *)
percent = 1;
QPainter p(this);
- QFont fnt(titleFont());
- p.setFont(fnt);
- QFontMetrics fm(fnt);
+ const QFont fnt(titleFont());
+ const QFontMetrics fm(fnt);
- int titleHeight = m_titleVisible ? fm.height() : 0;
+ const int titleHeight = m_titleVisible ? fm.height() + 5 : 4;
// Draw separator
- int separatorHeight = m_separatorVisible ? SEPARATOR_HEIGHT : 0;
+ const int separatorHeight = m_separatorVisible ? SEPARATOR_HEIGHT : 0;
if (m_separatorVisible) {
QRectF innerRect = QRectF(this->rect()).adjusted(0.5, 0.5, -0.5, -0.5);
p.setPen(StyleHelper::sidebarShadow());
@@ -246,28 +261,37 @@ void ProgressBar::paintEvent(QPaintEvent *)
}
}
- if (m_titleVisible) {
- QRect textBounds = fm.boundingRect(m_title);
- textBounds.moveCenter(rect().center());
- int alignment = Qt::AlignHCenter;
+ const int progressHeight = PROGRESSBAR_HEIGHT + ((PROGRESSBAR_HEIGHT % 2) + 1) % 2; // make odd
+ const int progressY = titleHeight + separatorHeight;
- int textSpace = rect().width() - 8;
+ if (m_titleVisible) {
+ const int alignment = Qt::AlignHCenter;
+ const int textSpace = rect().width() - 8;
// If there is not enough room when centered, we left align and
// elide the text
- QString elidedtitle = fm.elidedText(m_title, Qt::ElideRight, textSpace);
+ const QString elidedtitle = fm.elidedText(m_title, Qt::ElideRight, textSpace);
QRect textRect = rect().adjusted(3, separatorHeight - 1, -3, 0);
- textRect.setHeight(titleHeight + 4);
+ textRect.setHeight(fm.height() + 4);
+ p.setFont(fnt);
p.setPen(creatorTheme()->color(Theme::ProgressBarTitleColor));
p.drawText(textRect, alignment | Qt::AlignBottom, elidedtitle);
+
+ if (!m_subtitle.isEmpty()) {
+ const QString elidedsubtitle = fm.elidedText(m_subtitle, Qt::ElideRight, textSpace);
+
+ QRect subtextRect = textRect;
+ subtextRect.moveTop(progressY + progressHeight);
+
+ p.setFont(fnt);
+ p.setPen(creatorTheme()->color(Theme::ProgressBarTitleColor));
+ p.drawText(subtextRect, alignment | Qt::AlignBottom, elidedsubtitle);
+ }
}
- m_progressHeight = PROGRESSBAR_HEIGHT;
- m_progressHeight += ((m_progressHeight % 2) + 1) % 2; // make odd
// draw outer rect
- const QRect rect(INDENT - 1, titleHeight + separatorHeight + (m_titleVisible ? 5 : 4),
- size().width() - 2 * INDENT + 1, m_progressHeight);
+ const QRect rect(INDENT - 1, progressY, size().width() - 2 * INDENT + 1, progressHeight);
QRectF inner = rect.adjusted(2, 2, -2, -2);
inner.adjust(0, 0, qRound((percent - 1) * inner.width()), 0);
diff --git a/src/plugins/coreplugin/progressmanager/progressbar.h b/src/plugins/coreplugin/progressmanager/progressbar.h
index 9ff599adbb..108181f54b 100644
--- a/src/plugins/coreplugin/progressmanager/progressbar.h
+++ b/src/plugins/coreplugin/progressmanager/progressbar.h
@@ -44,6 +44,8 @@ public:
void setTitle(const QString &title);
void setTitleVisible(bool visible);
bool isTitleVisible() const;
+ void setSubtitle(const QString &subtitle);
+ QString subtitle() const;
void setSeparatorVisible(bool visible);
bool isSeparatorVisible() const;
void setCancelEnabled(bool enabled);
@@ -73,16 +75,17 @@ protected:
private:
QFont titleFont() const;
+ QFont subtitleFont() const;
QString m_text;
QString m_title;
+ QString m_subtitle;
bool m_titleVisible = true;
bool m_separatorVisible = true;
bool m_cancelEnabled = true;
bool m_finished = false;
bool m_error = false;
float m_cancelButtonFader = 0.0;
- int m_progressHeight = 0;
int m_minimum = 1;
int m_maximum = 100;
int m_value = 1;
diff --git a/src/plugins/coreplugin/progressmanager/progressmanager.cpp b/src/plugins/coreplugin/progressmanager/progressmanager.cpp
index 725721852f..d822397b90 100644
--- a/src/plugins/coreplugin/progressmanager/progressmanager.cpp
+++ b/src/plugins/coreplugin/progressmanager/progressmanager.cpp
@@ -39,6 +39,7 @@
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
#include <utils/theme/theme.h>
+#include <utils/utilsicons.h>
#include <QAction>
#include <QEvent>
@@ -291,7 +292,7 @@ void ProgressManagerPrivate::readSettings()
{
QSettings *settings = ICore::settings();
settings->beginGroup(QLatin1String(kSettingsGroup));
- m_progressViewPinned = settings->value(QLatin1String(kDetailsPinned), false).toBool();
+ m_progressViewPinned = settings->value(QLatin1String(kDetailsPinned), true).toBool();
settings->endGroup();
}
@@ -319,7 +320,7 @@ void ProgressManagerPrivate::init()
m_summaryProgressBar->setCancelEnabled(false);
m_summaryProgressLayout->addWidget(m_summaryProgressBar);
layout->addWidget(m_summaryProgressWidget);
- auto toggleButton = new ToggleButton(m_statusBarWidget);
+ auto toggleButton = new QToolButton(m_statusBarWidget);
layout->addWidget(toggleButton);
m_statusBarWidget->installEventFilter(this);
StatusBarManager::addStatusBarWidget(m_statusBarWidget, StatusBarManager::RightCorner);
@@ -327,10 +328,7 @@ void ProgressManagerPrivate::init()
QAction *toggleProgressView = new QAction(tr("Toggle Progress Details"), this);
toggleProgressView->setCheckable(true);
toggleProgressView->setChecked(m_progressViewPinned);
- // we have to set an transparent icon to prevent the tool button to show text
- QPixmap p(1, 1);
- p.fill(Qt::transparent);
- toggleProgressView->setIcon(QIcon(p));
+ toggleProgressView->setIcon(Utils::Icons::TOGGLE_PROGRESSDETAILS_TOOLBAR.icon());
Command *cmd = ActionManager::registerAction(toggleProgressView,
"QtCreator.ToggleProgressDetails");
@@ -457,6 +455,8 @@ FutureProgress *ProgressManagerPrivate::doAddTask(const QFuture<void> &future, c
this, &ProgressManagerPrivate::updateSummaryProgressBar);
connect(progress, &FutureProgress::statusBarWidgetChanged,
this, &ProgressManagerPrivate::updateStatusDetailsWidget);
+ connect(progress, &FutureProgress::subtitleInStatusBarChanged,
+ this, &ProgressManagerPrivate::updateStatusDetailsWidget);
updateStatusDetailsWidget();
emit taskStarted(type);
@@ -657,9 +657,22 @@ void ProgressManagerPrivate::updateStatusDetailsWidget()
QList<FutureProgress *>::iterator i = m_taskList.end();
while (i != m_taskList.begin()) {
--i;
- candidateWidget = (*i)->statusBarWidget();
+ FutureProgress *progress = *i;
+ candidateWidget = progress->statusBarWidget();
if (candidateWidget) {
- m_currentStatusDetailsProgress = *i;
+ m_currentStatusDetailsProgress = progress;
+ break;
+ } else if (progress->isSubtitleVisibleInStatusBar() && !progress->subtitle().isEmpty()) {
+ if (!m_statusDetailsLabel) {
+ m_statusDetailsLabel = new QLabel(m_summaryProgressWidget);
+ QFont font(m_statusDetailsLabel->font());
+ font.setPointSizeF(StyleHelper::sidebarFontSize());
+ font.setBold(true);
+ m_statusDetailsLabel->setFont(font);
+ }
+ m_statusDetailsLabel->setText(progress->subtitle());
+ candidateWidget = m_statusDetailsLabel;
+ m_currentStatusDetailsProgress = progress;
break;
}
}
@@ -697,33 +710,6 @@ void ProgressManagerPrivate::progressDetailsToggled(bool checked)
settings->endGroup();
}
-ToggleButton::ToggleButton(QWidget *parent)
- : QToolButton(parent)
-{
- setToolButtonStyle(Qt::ToolButtonIconOnly);
- if (creatorTheme()->flag(Theme::FlatToolBars)) {
- QPalette p = palette();
- p.setBrush(QPalette::Base, creatorTheme()->color(Theme::ToggleButtonBackgroundColor));
- setPalette(p);
- }
-}
-
-QSize ToggleButton::sizeHint() const
-{
- return QSize(13, 12); // Uneven width, because the arrow's width is also uneven.
-}
-
-void ToggleButton::paintEvent(QPaintEvent *event)
-{
- QToolButton::paintEvent(event);
- QPainter p(this);
- QStyleOption arrowOpt;
- arrowOpt.initFrom(this);
- arrowOpt.rect.adjust(2, 0, -1, -2);
- StyleHelper::drawArrow(QStyle::PE_IndicatorArrowUp, &p, &arrowOpt);
-}
-
-
ProgressManager::ProgressManager() = default;
ProgressManager::~ProgressManager() = default;
diff --git a/src/plugins/coreplugin/progressmanager/progressmanager_p.h b/src/plugins/coreplugin/progressmanager/progressmanager_p.h
index 85bf378159..4eabe50204 100644
--- a/src/plugins/coreplugin/progressmanager/progressmanager_p.h
+++ b/src/plugins/coreplugin/progressmanager/progressmanager_p.h
@@ -31,6 +31,7 @@
#include <QList>
#include <QGraphicsOpacityEffect>
#include <QHBoxLayout>
+#include <QLabel>
#include <QPointer>
#include <QPropertyAnimation>
#include <QToolButton>
@@ -103,6 +104,7 @@ private:
QHBoxLayout *m_summaryProgressLayout;
QWidget *m_currentStatusDetailsWidget = nullptr;
QPointer<FutureProgress> m_currentStatusDetailsProgress;
+ QLabel *m_statusDetailsLabel = nullptr;
ProgressBar *m_summaryProgressBar;
QGraphicsOpacityEffect *m_opacityEffect;
QPointer<QPropertyAnimation> m_opacityAnimation;
@@ -110,14 +112,5 @@ private:
bool m_hovered = false;
};
-class ToggleButton : public QToolButton
-{
- Q_OBJECT
-public:
- ToggleButton(QWidget *parent);
- QSize sizeHint() const override;
- void paintEvent(QPaintEvent *event) override;
-};
-
} // namespace Internal
} // namespace Core
diff --git a/src/plugins/coreplugin/rightpane.cpp b/src/plugins/coreplugin/rightpane.cpp
index e786051d04..403fe4b0c6 100644
--- a/src/plugins/coreplugin/rightpane.cpp
+++ b/src/plugins/coreplugin/rightpane.cpp
@@ -153,6 +153,11 @@ void RightPaneWidget::setWidget(QWidget *widget)
}
}
+QWidget *RightPaneWidget::widget() const
+{
+ return m_widget;
+}
+
int RightPaneWidget::storedWidth()
{
return m_width;
diff --git a/src/plugins/coreplugin/rightpane.h b/src/plugins/coreplugin/rightpane.h
index 14026a03e0..ad9117509a 100644
--- a/src/plugins/coreplugin/rightpane.h
+++ b/src/plugins/coreplugin/rightpane.h
@@ -72,6 +72,7 @@ public:
static RightPaneWidget *instance();
void setWidget(QWidget *widget);
+ QWidget *widget() const;
int storedWidth();
diff --git a/src/plugins/coreplugin/shellcommand.cpp b/src/plugins/coreplugin/shellcommand.cpp
index a236c906e4..a1ddd083eb 100644
--- a/src/plugins/coreplugin/shellcommand.cpp
+++ b/src/plugins/coreplugin/shellcommand.cpp
@@ -40,12 +40,17 @@ ShellCommand::ShellCommand(const QString &workingDirectory, const QProcessEnviro
this, &ShellCommand::coreAboutToClose);
}
+FutureProgress *ShellCommand::futureProgress() const
+{
+ return m_progress.data();
+}
+
void ShellCommand::addTask(QFuture<void> &future)
{
const QString name = displayName();
const auto id = Core::Id::fromString(name + QLatin1String(".action"));
if (hasProgressParser()) {
- ProgressManager::addTask(future, name, id);
+ m_progress = ProgressManager::addTask(future, name, id);
} else {
// add a timed tasked based on timeout
// we cannot access the future interface directly, so we need to create a new one
@@ -58,7 +63,7 @@ void ShellCommand::addTask(QFuture<void> &future)
watcher->deleteLater();
});
watcher->setFuture(future);
- ProgressManager::addTimedTask(*fi, name, id, qMax(2, timeoutS() / 5)/*itsmagic*/);
+ m_progress = ProgressManager::addTimedTask(*fi, name, id, qMax(2, timeoutS() / 5)/*itsmagic*/);
}
}
diff --git a/src/plugins/coreplugin/shellcommand.h b/src/plugins/coreplugin/shellcommand.h
index a5cd59bfa6..b960bae94d 100644
--- a/src/plugins/coreplugin/shellcommand.h
+++ b/src/plugins/coreplugin/shellcommand.h
@@ -27,8 +27,12 @@
#include "core_global.h"
+#include "progressmanager/futureprogress.h"
+
#include <utils/shellcommand.h>
+#include <QPointer>
+
namespace Core {
class CORE_EXPORT ShellCommand : public Utils::ShellCommand
@@ -38,10 +42,15 @@ class CORE_EXPORT ShellCommand : public Utils::ShellCommand
public:
ShellCommand(const QString &workingDirectory, const QProcessEnvironment &environment);
+ FutureProgress *futureProgress() const;
+
protected:
void addTask(QFuture<void> &future) override;
virtual void coreAboutToClose();
+
+private:
+ QPointer<FutureProgress> m_progress;
};
} // namespace Core
diff --git a/src/plugins/coreplugin/sidebarwidget.cpp b/src/plugins/coreplugin/sidebarwidget.cpp
index daad4cf813..fd561611c2 100644
--- a/src/plugins/coreplugin/sidebarwidget.cpp
+++ b/src/plugins/coreplugin/sidebarwidget.cpp
@@ -99,7 +99,7 @@ SideBarWidget::SideBarWidget(SideBar *sideBar, const QString &id)
}
setCurrentItem(t);
- connect(m_comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SideBarWidget::setCurrentIndex);
}
diff --git a/src/plugins/coreplugin/systemsettings.cpp b/src/plugins/coreplugin/systemsettings.cpp
index 584cfb0ca9..b6a435d36a 100644
--- a/src/plugins/coreplugin/systemsettings.cpp
+++ b/src/plugins/coreplugin/systemsettings.cpp
@@ -68,13 +68,13 @@ QWidget *SystemSettings::widget()
m_widget = new QWidget;
m_page->setupUi(m_widget);
m_page->terminalOpenArgs->setToolTip(
- tr("Command line arguments used for \"%1\".").arg(FileUtils::msgTerminalAction()));
+ tr("Command line arguments used for \"%1\".").arg(FileUtils::msgTerminalHereAction()));
m_page->reloadBehavior->setCurrentIndex(EditorManager::reloadSetting());
if (HostOsInfo::isAnyUnixHost()) {
const QVector<TerminalCommand> availableTerminals = ConsoleProcess::availableTerminalEmulators();
for (const TerminalCommand &term : availableTerminals)
- m_page->terminalComboBox->addItem(term.command, qVariantFromValue(term));
+ m_page->terminalComboBox->addItem(term.command, QVariant::fromValue(term));
updateTerminalUi(ConsoleProcess::terminalEmulator(ICore::settings()));
connect(m_page->terminalComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
diff --git a/src/plugins/coreplugin/toolsettings.cpp b/src/plugins/coreplugin/toolsettings.cpp
index 857d154125..200e425140 100644
--- a/src/plugins/coreplugin/toolsettings.cpp
+++ b/src/plugins/coreplugin/toolsettings.cpp
@@ -143,7 +143,7 @@ void ToolSettings::apply()
if (tool->preset() && (*tool) != (*(tool->preset()))) {
// check if we need to choose a new file name
if (tool->preset()->fileName() == tool->fileName()) {
- const QString &fileName = Utils::FileName::fromString(tool->preset()->fileName()).fileName();
+ const QString &fileName = Utils::FilePath::fromString(tool->preset()->fileName()).fileName();
const QString &newFilePath = getUserFilePath(fileName);
// TODO error handling if newFilePath.isEmpty() (i.e. failed to find a unused name)
tool->setFileName(newFilePath);
diff --git a/src/plugins/cpaster/CMakeLists.txt b/src/plugins/cpaster/CMakeLists.txt
new file mode 100644
index 0000000000..6e17d5c43b
--- /dev/null
+++ b/src/plugins/cpaster/CMakeLists.txt
@@ -0,0 +1,31 @@
+add_qtc_plugin(CodePaster
+ PLUGIN_DEPENDS Core TextEditor
+ DEFINES CPASTER_PLUGIN_GUI
+ DEPENDS Qt5::Network
+ INCLUDES ../../shared/cpaster
+ SOURCES
+ codepasterservice.h
+ columnindicatortextedit.cpp columnindicatortextedit.h
+ cpasterconstants.h
+ cpaster.qrc
+ cpasterplugin.cpp cpasterplugin.h
+ fileshareprotocol.cpp fileshareprotocol.h
+ fileshareprotocolsettingspage.cpp fileshareprotocolsettingspage.h
+ fileshareprotocolsettingswidget.ui
+ frontend/argumentscollector.cpp frontend/argumentscollector.h
+ frontend/main.cpp
+ pastebindotcomprotocol.cpp pastebindotcomprotocol.h
+ pastebindotcomsettings.ui
+ pastecodedotxyzprotocol.cpp pastecodedotxyzprotocol.h
+ pasteselect.ui
+ pasteselectdialog.cpp pasteselectdialog.h
+ pasteview.cpp pasteview.h pasteview.ui
+ protocol.cpp protocol.h
+ settings.cpp settings.h
+ settingspage.cpp settingspage.h settingspage.ui
+ stickynotespasteprotocol.cpp stickynotespasteprotocol.h
+ urlopenprotocol.cpp urlopenprotocol.h
+
+ ../../shared/cpaster/cgi.cpp ../../shared/cpaster/cgi.h
+ ../../shared/cpaster/splitter.cpp ../../shared/cpaster/splitter.h
+)
diff --git a/src/plugins/cpaster/authenticationdialog.cpp b/src/plugins/cpaster/authenticationdialog.cpp
deleted file mode 100644
index 326cdb2d80..0000000000
--- a/src/plugins/cpaster/authenticationdialog.cpp
+++ /dev/null
@@ -1,64 +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 "authenticationdialog.h"
-
-#include <QDialogButtonBox>
-#include <QFormLayout>
-#include <QLabel>
-#include <QLineEdit>
-#include <QVBoxLayout>
-
-namespace CodePaster {
-
-AuthenticationDialog::AuthenticationDialog(const QString &details, QWidget *parent)
- : QDialog(parent)
-{
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(new QLabel(details));
- auto *formLayout = new QFormLayout;
- formLayout->addRow(tr("Username:"), m_user = new QLineEdit);
- formLayout->addRow(tr("Password:"), m_pass = new QLineEdit);
- m_pass->setEchoMode(QLineEdit::Password);
- mainLayout->addLayout(formLayout);
- auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
- connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
- mainLayout->addWidget(buttonBox);
- setLayout(mainLayout);
-}
-
-QString AuthenticationDialog::userName() const
-{
- return m_user->text();
-}
-
-QString AuthenticationDialog::password() const
-{
- return m_pass->text();
-}
-
-} // namespace CodePaster
diff --git a/src/plugins/cpaster/authenticationdialog.h b/src/plugins/cpaster/authenticationdialog.h
deleted file mode 100644
index abab5b515e..0000000000
--- a/src/plugins/cpaster/authenticationdialog.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
-
-#include <QDialog>
-
-QT_BEGIN_NAMESPACE
-class QLineEdit;
-QT_END_NAMESPACE
-
-namespace CodePaster {
-
-class AuthenticationDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- AuthenticationDialog(const QString &details, QWidget *parent = nullptr);
-
- bool authenticated() const { return m_authenticated; }
- QString userName() const;
- QString password() const;
-
-private:
- bool m_authenticated = false;
- QLineEdit *m_user = nullptr;
- QLineEdit *m_pass = nullptr;
-};
-
-} // namespace CodePaster
diff --git a/src/plugins/cpaster/columnindicatortextedit.cpp b/src/plugins/cpaster/columnindicatortextedit.cpp
index a219170bef..cfbe8b2489 100644
--- a/src/plugins/cpaster/columnindicatortextedit.cpp
+++ b/src/plugins/cpaster/columnindicatortextedit.cpp
@@ -43,7 +43,7 @@ ColumnIndicatorTextEdit::ColumnIndicatorTextEdit(QWidget *parent) :
setSizePolicy(sizePolicy);
int cmx = 0, cmy = 0, cmw = 0, cmh = 0;
getContentsMargins(&cmx, &cmy, &cmw, &cmh);
- m_columnIndicator = QFontMetrics(font).width(QLatin1Char('W')) * 100 + cmx + 1;
+ m_columnIndicator = QFontMetrics(font).horizontalAdvance(QLatin1Char('W')) * 100 + cmx + 1;
m_columnIndicatorFont.setFamily(QLatin1String("Times"));
m_columnIndicatorFont.setPointSizeF(7.0);
}
diff --git a/src/plugins/cpaster/cpaster.pro b/src/plugins/cpaster/cpaster.pro
index fa3a983d3c..3565f4d03f 100644
--- a/src/plugins/cpaster/cpaster.pro
+++ b/src/plugins/cpaster/cpaster.pro
@@ -12,10 +12,9 @@ HEADERS += cpasterplugin.h \
columnindicatortextedit.h \
fileshareprotocol.h \
fileshareprotocolsettingspage.h \
- kdepasteprotocol.h \
+ stickynotespasteprotocol.h \
urlopenprotocol.h \
- codepasterservice.h \
- authenticationdialog.h
+ codepasterservice.h
SOURCES += cpasterplugin.cpp \
settingspage.cpp \
@@ -28,9 +27,8 @@ SOURCES += cpasterplugin.cpp \
columnindicatortextedit.cpp \
fileshareprotocol.cpp \
fileshareprotocolsettingspage.cpp \
- kdepasteprotocol.cpp \
- urlopenprotocol.cpp \
- authenticationdialog.cpp
+ stickynotespasteprotocol.cpp \
+ urlopenprotocol.cpp
FORMS += settingspage.ui \
pasteselect.ui \
diff --git a/src/plugins/cpaster/cpaster.qbs b/src/plugins/cpaster/cpaster.qbs
index d8d7726e7a..9547f8ad5e 100644
--- a/src/plugins/cpaster/cpaster.qbs
+++ b/src/plugins/cpaster/cpaster.qbs
@@ -24,8 +24,6 @@ QtcPlugin {
"fileshareprotocolsettingspage.cpp",
"fileshareprotocolsettingspage.h",
"fileshareprotocolsettingswidget.ui",
- "kdepasteprotocol.cpp",
- "kdepasteprotocol.h",
"pastebindotcomprotocol.cpp",
"pastebindotcomprotocol.h",
"pastebindotcomsettings.ui",
@@ -44,10 +42,10 @@ QtcPlugin {
"settingspage.cpp",
"settingspage.h",
"settingspage.ui",
+ "stickynotespasteprotocol.cpp",
+ "stickynotespasteprotocol.h",
"urlopenprotocol.cpp",
"urlopenprotocol.h",
- "authenticationdialog.cpp",
- "authenticationdialog.h"
]
Group {
diff --git a/src/plugins/cpaster/cpasterplugin.cpp b/src/plugins/cpaster/cpasterplugin.cpp
index a101598e8b..13c4faabe3 100644
--- a/src/plugins/cpaster/cpasterplugin.cpp
+++ b/src/plugins/cpaster/cpasterplugin.cpp
@@ -26,7 +26,6 @@
#include "cpasterplugin.h"
#include "pasteview.h"
-#include "kdepasteprotocol.h"
#include "pastebindotcomprotocol.h"
#include "pastecodedotxyzprotocol.h"
#include "fileshareprotocol.h"
@@ -120,7 +119,6 @@ bool CodepasterPlugin::initialize(const QStringList &arguments, QString *errorMe
// Create the protocols and append them to the Settings
Protocol *protos[] = {new PasteBinDotComProtocol,
- new KdePasteProtocol,
new FileShareProtocol,
new PasteCodeDotXyzProtocol,
};
diff --git a/src/plugins/cpaster/frontend/argumentscollector.cpp b/src/plugins/cpaster/frontend/argumentscollector.cpp
index 7cfdc6c5fd..99f9f0c037 100644
--- a/src/plugins/cpaster/frontend/argumentscollector.cpp
+++ b/src/plugins/cpaster/frontend/argumentscollector.cpp
@@ -68,7 +68,7 @@ bool ArgumentsCollector::collect(const QStringList &args)
QString ArgumentsCollector::usageString() const
{
QString usage = QString::fromLatin1("Usage:\n\t%1 <request> [ <request options>]\n\t")
- .arg(Utils::FileName::fromString(QCoreApplication::applicationFilePath()).fileName());
+ .arg(Utils::FilePath::fromString(QCoreApplication::applicationFilePath()).fileName());
usage += QString::fromLatin1("Possible requests: \"%1\", \"%2\", \"%3\"\n\t")
.arg(pasteRequestString(), listProtocolsRequestString(), helpRequestString());
usage += QString::fromLatin1("Possible options for request \"%1\": \"%2 <file>\" (default: stdin), "
diff --git a/src/plugins/cpaster/frontend/frontend.pro b/src/plugins/cpaster/frontend/frontend.pro
index fc5913b5e8..69b6428a3f 100644
--- a/src/plugins/cpaster/frontend/frontend.pro
+++ b/src/plugins/cpaster/frontend/frontend.pro
@@ -14,14 +14,12 @@ HEADERS = ../protocol.h \
../cpasterconstants.h \
../pastebindotcomprotocol.h \
../pastecodedotxyzprotocol.h \
- ../kdepasteprotocol.h \
../urlopenprotocol.h \
argumentscollector.h
SOURCES += ../protocol.cpp \
../pastebindotcomprotocol.cpp \
../pastecodedotxyzprotocol.cpp \
- ../kdepasteprotocol.cpp \
../urlopenprotocol.cpp \
argumentscollector.cpp \
main.cpp
diff --git a/src/plugins/cpaster/frontend/frontend.qbs b/src/plugins/cpaster/frontend/frontend.qbs
index b1b1c998e9..2993953105 100644
--- a/src/plugins/cpaster/frontend/frontend.qbs
+++ b/src/plugins/cpaster/frontend/frontend.qbs
@@ -23,7 +23,6 @@ QtcTool {
prefix: "../"
files: [
"cpasterconstants.h",
- "kdepasteprotocol.h", "kdepasteprotocol.cpp",
"pastebindotcomprotocol.h", "pastebindotcomprotocol.cpp",
"pastecodedotxyzprotocol.h", "pastecodedotxyzprotocol.cpp",
"protocol.h", "protocol.cpp",
diff --git a/src/plugins/cpaster/frontend/main.cpp b/src/plugins/cpaster/frontend/main.cpp
index 5845334293..50ae182334 100644
--- a/src/plugins/cpaster/frontend/main.cpp
+++ b/src/plugins/cpaster/frontend/main.cpp
@@ -24,7 +24,6 @@
****************************************************************************/
#include "argumentscollector.h"
-#include "../kdepasteprotocol.h"
#include "../pastebindotcomprotocol.h"
#include "../pastecodedotxyzprotocol.h"
@@ -46,9 +45,7 @@ class PasteReceiver : public QObject
public:
PasteReceiver(const QString &protocol, const QString &filePath) : m_filePath(filePath)
{
- if (protocol == KdePasteProtocol::protocolName().toLower())
- m_protocol.reset(new KdePasteProtocol);
- else if (protocol == PasteBinDotComProtocol::protocolName().toLower())
+ if (protocol == PasteBinDotComProtocol::protocolName().toLower())
m_protocol.reset(new PasteBinDotComProtocol);
else if (protocol == PasteCodeDotXyzProtocol::protocolName().toLower())
m_protocol.reset(new PasteCodeDotXyzProtocol);
@@ -91,8 +88,7 @@ int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
- const QStringList protocols = {KdePasteProtocol::protocolName().toLower(),
- PasteBinDotComProtocol::protocolName().toLower(),
+ const QStringList protocols = {PasteBinDotComProtocol::protocolName().toLower(),
PasteCodeDotXyzProtocol::protocolName().toLower()};
ArgumentsCollector argsCollector(protocols);
QStringList arguments = QCoreApplication::arguments();
diff --git a/src/plugins/cpaster/kdepasteprotocol.cpp b/src/plugins/cpaster/kdepasteprotocol.cpp
deleted file mode 100644
index 030b30e0e5..0000000000
--- a/src/plugins/cpaster/kdepasteprotocol.cpp
+++ /dev/null
@@ -1,394 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "kdepasteprotocol.h"
-#ifdef CPASTER_PLUGIN_GUI
-#include "authenticationdialog.h"
-#endif
-
-#include <coreplugin/icore.h>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QByteArray>
-#include <QStringList>
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonArray>
-#include <QRegularExpression>
-#include <QNetworkReply>
-
-#include <algorithm>
-
-enum { debug = 0 };
-
-static inline QByteArray expiryParameter(int daysRequested)
-{
- // Obtained by 'pastebin.kde.org/api/json/parameter/expire' on 26.03.2014
- static const int expiryTimesSec[] = {1800, 21600, 86400, 604800, 2592000, 31536000};
- const int *end = expiryTimesSec + sizeof(expiryTimesSec) / sizeof(expiryTimesSec[0]);
- // Find the first element >= requested span, search up to n - 1 such that 'end' defaults to last value.
- const int *match = std::lower_bound(expiryTimesSec, end - 1, 24 * 60 * 60 * daysRequested);
- return QByteArray("expire=") + QByteArray::number(*match);
-}
-
-namespace CodePaster {
-
-void StickyNotesPasteProtocol::setHostUrl(const QString &hostUrl)
-{
- m_hostUrl = hostUrl;
- if (!m_hostUrl.endsWith(QLatin1Char('/')))
- m_hostUrl.append(QLatin1Char('/'));
-}
-
-unsigned StickyNotesPasteProtocol::capabilities() const
-{
- return ListCapability | PostDescriptionCapability;
-}
-
-bool StickyNotesPasteProtocol::checkConfiguration(QString *errorMessage)
-{
- if (m_hostChecked) // Check the host once.
- return true;
- const bool ok = httpStatus(m_hostUrl, errorMessage, true);
- if (ok)
- m_hostChecked = true;
- return ok;
-}
-
-// Query 'http://pastebin.kde.org/api/json/parameter/language' to obtain the valid values.
-static inline QByteArray pasteLanguage(Protocol::ContentType ct)
-{
- switch (ct) {
- case Protocol::Text:
- break;
- case Protocol::C:
- return "language=c";
- case Protocol::Cpp:
- return "language=cpp-qt";
- case Protocol::JavaScript:
- return "language=javascript";
- case Protocol::Diff:
- return "language=diff";
- case Protocol::Xml:
- return "language=xml";
- }
- return QByteArray("language=text");
-}
-
-void StickyNotesPasteProtocol::paste(const QString &text,
- ContentType ct, int expiryDays,
- const QString &username,
- const QString &comment,
- const QString &description)
-{
- enum { maxDescriptionLength = 30 }; // Length of description is limited.
-
- Q_UNUSED(username)
- Q_UNUSED(comment);
- QTC_ASSERT(!m_pasteReply, return);
-
- // Format body
- QByteArray pasteData = "&data=";
- pasteData += QUrl::toPercentEncoding(fixNewLines(text));
- pasteData += '&';
- pasteData += pasteLanguage(ct);
- pasteData += '&';
- pasteData += expiryParameter(expiryDays);
- if (!description.isEmpty()) {
- pasteData += "&title=";
- pasteData += QUrl::toPercentEncoding(description.left(maxDescriptionLength));
- }
-
- m_pasteReply = httpPost(m_hostUrl + QLatin1String("api/json/create"), pasteData, true);
- connect(m_pasteReply, &QNetworkReply::finished, this, &StickyNotesPasteProtocol::pasteFinished);
- if (debug)
- qDebug() << "paste: sending " << m_pasteReply << pasteData;
-}
-
-// Parse for an element and return its contents
-static QString parseElement(QIODevice *device, const QString &elementName)
-{
- const QJsonDocument doc = QJsonDocument::fromJson(device->readAll());
- if (doc.isEmpty() || !doc.isObject())
- return QString();
-
- QJsonObject obj= doc.object();
- const QString resultKey = QLatin1String("result");
-
- if (obj.contains(resultKey)) {
- QJsonValue value = obj.value(resultKey);
- if (value.isObject()) {
- obj = value.toObject();
- if (obj.contains(elementName)) {
- value = obj.value(elementName);
- return value.toString();
- }
- } else if (value.isArray()) {
- qWarning() << "JsonArray not expected.";
- }
- }
-
- return QString();
-}
-
-void StickyNotesPasteProtocol::pasteFinished()
-{
- if (m_pasteReply->error()) {
- qWarning("%s protocol error: %s", qPrintable(name()),qPrintable(m_pasteReply->errorString()));
- } else {
- // Parse id from '<result><id>143204</id><hash></hash></result>'
- // No useful error reports have been observed.
- const QString id = parseElement(m_pasteReply, QLatin1String("id"));
- if (id.isEmpty())
- qWarning("%s protocol error: Could not send entry.", qPrintable(name()));
- else
- emit pasteDone(m_hostUrl + id);
- }
-
- m_pasteReply->deleteLater();
- m_pasteReply = nullptr;
-}
-
-void StickyNotesPasteProtocol::fetch(const QString &id)
-{
- QTC_ASSERT(!m_fetchReply, return);
-
- // Did we get a complete URL or just an id?
- m_fetchId = id;
- const int lastSlashPos = m_fetchId.lastIndexOf(QLatin1Char('/'));
- if (lastSlashPos != -1)
- m_fetchId.remove(0, lastSlashPos + 1);
- QString url = m_hostUrl + QLatin1String("api/json/show/") + m_fetchId;
- if (debug)
- qDebug() << "fetch: sending " << url;
-
- m_fetchReply = httpGet(url);
- connect(m_fetchReply, &QNetworkReply::finished,
- this, &StickyNotesPasteProtocol::fetchFinished);
-}
-
-// Parse: '<result><id>143228</id><author>foo</author><timestamp>1320661026</timestamp><language>text</language>
-// <data>bar</data></result>'
-
-void StickyNotesPasteProtocol::fetchFinished()
-{
- const QString title = name() + QLatin1String(": ") + m_fetchId;
- QString content;
- const bool error = m_fetchReply->error();
- if (error) {
- content = m_fetchReply->errorString();
- if (debug)
- qDebug() << "fetchFinished: error" << m_fetchId << content;
- } else {
- content = parseElement(m_fetchReply, QLatin1String("data"));
- content.remove(QLatin1Char('\r'));
- }
- m_fetchReply->deleteLater();
- m_fetchReply = nullptr;
- emit fetchDone(title, content, error);
-}
-
-void StickyNotesPasteProtocol::list()
-{
- QTC_ASSERT(!m_listReply, return);
-
- // Trailing slash is important to prevent redirection.
- QString url = m_hostUrl + QLatin1String("api/json/list");
- m_listReply = httpGet(url);
- connect(m_listReply, &QNetworkReply::finished,
- this, &StickyNotesPasteProtocol::listFinished);
- if (debug)
- qDebug() << "list: sending " << url << m_listReply;
-}
-
-// Parse 'result><pastes><paste>id1</paste><paste>id2</paste>...'
-static inline QStringList parseList(QIODevice *device)
-{
- QStringList result;
- const QJsonDocument doc = QJsonDocument::fromJson(device->readAll());
- if (doc.isEmpty() || !doc.isObject())
- return result;
-
- QJsonObject obj= doc.object();
- const QString resultKey = QLatin1String("result");
- const QString pastesKey = QLatin1String("pastes");
-
- if (obj.contains(resultKey)) {
- QJsonValue value = obj.value(resultKey);
- if (value.isObject()) {
- obj = value.toObject();
- if (obj.contains(pastesKey)) {
- value = obj.value(pastesKey);
- if (value.isArray()) {
- QJsonArray array = value.toArray();
- foreach (const QJsonValue &val, array)
- result.append(val.toString());
- }
- }
- }
- }
- return result;
-}
-
-void StickyNotesPasteProtocol::listFinished()
-{
- const bool error = m_listReply->error();
- if (error) {
- if (debug)
- qDebug() << "listFinished: error" << m_listReply->errorString();
- } else {
- emit listDone(name(), parseList(m_listReply));
- }
- m_listReply->deleteLater();
- m_listReply = nullptr;
-}
-
-KdePasteProtocol::KdePasteProtocol()
-{
- setHostUrl(QLatin1String("https://pastebin.kde.org/"));
- connect(this, &KdePasteProtocol::authenticationFailed, this, [this] () {
- m_loginFailed = true;
- paste(m_text, m_contentType, m_expiryDays, QString(), QString(), m_description);
- });
-}
-
-void KdePasteProtocol::paste(const QString &text, Protocol::ContentType ct, int expiryDays,
- const QString &username, const QString &comment,
- const QString &description)
-{
- Q_UNUSED(username);
- Q_UNUSED(comment);
- // KDE paster needs authentication nowadays
-#ifdef CPASTER_PLUGIN_GUI
- QString details = tr("Pasting to KDE paster needs authentication.<br/>"
- "Enter your KDE Identity credentials to continue.");
- if (m_loginFailed)
- details.prepend("<span style='background-color:LightYellow;color:red'>"
- + tr("Login failed") + "</span><br/><br/>");
-
- AuthenticationDialog authDialog(details, Core::ICore::dialogParent());
- authDialog.setWindowTitle("Authenticate for KDE paster");
- if (authDialog.exec() != QDialog::Accepted) {
- m_loginFailed = false;
- return;
- }
- const QString user = authDialog.userName();
- const QString passwd = authDialog.password();
-#else
- // FIXME get the credentials for the cmdline cpaster somehow
- const QString user;
- const QString passwd;
- qDebug() << "KDE needs credentials for pasting";
- emit pasteDone(QString());
- return;
-#endif
- // store input data as members to be able to use them after the authentication succeeded
- m_text = text;
- m_contentType = ct;
- m_expiryDays = expiryDays;
- m_description = description;
- authenticate(user, passwd);
-}
-
-QString KdePasteProtocol::protocolName()
-{
- return QLatin1String("Paste.KDE.Org");
-}
-
-void KdePasteProtocol::authenticate(const QString &user, const QString &passwd)
-{
- QTC_ASSERT(!m_authReply, return);
-
- // first we need to obtain the hidden form token for logging in
- m_authReply = httpGet(hostUrl() + "user/login");
- connect(m_authReply, &QNetworkReply::finished, this, [this, user, passwd] () {
- onPreAuthFinished(user, passwd);
- });
-}
-
-void KdePasteProtocol::onPreAuthFinished(const QString &user, const QString &passwd)
-{
- if (m_authReply->error() != QNetworkReply::NoError) {
- m_authReply->deleteLater();
- m_authReply = nullptr;
- return;
- }
- const QByteArray page = m_authReply->readAll();
- m_authReply->deleteLater();
- const QRegularExpression regex("name=\"_token\"\\s+type=\"hidden\"\\s+value=\"(.*?)\">");
- const QRegularExpressionMatch match = regex.match(QLatin1String(page));
- if (!match.hasMatch()) {
- m_authReply = nullptr;
- return;
- }
- const QString token = match.captured(1);
-
- QByteArray data("username=" + QUrl::toPercentEncoding(user)
- + "&password=" + QUrl::toPercentEncoding(passwd)
- + "&_token=" + QUrl::toPercentEncoding(token));
- m_authReply = httpPost(hostUrl() + "user/login", data, true);
- connect(m_authReply, &QNetworkReply::finished, this, &KdePasteProtocol::onAuthFinished);
-}
-
-void KdePasteProtocol::onAuthFinished()
-{
- if (m_authReply->error() != QNetworkReply::NoError) {
- m_authReply->deleteLater();
- m_authReply = nullptr;
- return;
- }
- const QVariant attribute = m_authReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
- m_redirectUrl = redirectUrl(attribute.toUrl().toString(), m_redirectUrl);
- if (!m_redirectUrl.isEmpty()) { // we need to perform a redirect
- QUrl url(m_redirectUrl);
- if (url.path().isEmpty())
- url.setPath("/"); // avoid issue inside cookiesForUrl()
- m_authReply->deleteLater();
- m_authReply = httpGet(url.url(), true);
- connect(m_authReply, &QNetworkReply::finished, this, &KdePasteProtocol::onAuthFinished);
- } else { // auth should be done now
- const QByteArray page = m_authReply->readAll();
- m_authReply->deleteLater();
- m_authReply = nullptr;
- if (page.contains("https://identity.kde.org")) // we're back on the login page
- emit authenticationFailed();
- else {
- m_loginFailed = false;
- StickyNotesPasteProtocol::paste(m_text, m_contentType, m_expiryDays, QString(),
- QString(), m_description);
- }
- }
-}
-
-QString KdePasteProtocol::redirectUrl(const QString &redirect, const QString &oldRedirect) const
-{
- QString redirectUrl;
- if (!redirect.isEmpty() && redirect != oldRedirect)
- redirectUrl = redirect;
- return redirectUrl;
-}
-
-} // namespace CodePaster
diff --git a/src/plugins/cpaster/kdepasteprotocol.h b/src/plugins/cpaster/kdepasteprotocol.h
deleted file mode 100644
index c1875b1477..0000000000
--- a/src/plugins/cpaster/kdepasteprotocol.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 "protocol.h"
-
-namespace CodePaster {
-
-class StickyNotesPasteProtocol : public NetworkProtocol
-{
- Q_OBJECT
-public:
- unsigned capabilities() const override;
-
- void fetch(const QString &id) override;
- void paste(const QString &text,
- ContentType ct = Text,
- int expiryDays = 1,
- const QString &username = QString(),
- const QString &comment = QString(),
- const QString &description = QString()) override;
- void list() override;
-
-
-
- QString hostUrl() const { return m_hostUrl; }
- void setHostUrl(const QString &hostUrl);
-
-protected:
- bool checkConfiguration(QString *errorMessage = nullptr) override;
-
-private:
- void fetchFinished();
- void pasteFinished();
- void listFinished();
-
- QString m_hostUrl;
-
- QNetworkReply *m_fetchReply = nullptr;
- QNetworkReply *m_pasteReply = nullptr;
- QNetworkReply *m_listReply = nullptr;
-
- QString m_fetchId;
- int m_postId = -1;
- bool m_hostChecked = false;
-};
-
-class KdePasteProtocol : public StickyNotesPasteProtocol
-{
- Q_OBJECT
-public:
- KdePasteProtocol();
-
- void paste(const QString &text, ContentType ct = Text, int expiryDays = 1,
- const QString &username = QString(),
- const QString &comment = QString() ,
- const QString &description = QString()) override;
-
- QString name() const override { return protocolName(); }
- static QString protocolName();
-signals:
- void authenticationFailed();
-private:
- void authenticate(const QString &user, const QString &passwd);
- void onPreAuthFinished(const QString &user, const QString &passwd);
- void onAuthFinished();
- QString redirectUrl(const QString &redirect, const QString &oldRedirect) const;
-
- QNetworkReply *m_authReply = nullptr;
- QString m_text;
- ContentType m_contentType = Text;
- int m_expiryDays = 1;
- bool m_loginFailed = false;
- QString m_description;
- QString m_redirectUrl;
-
-};
-
-} // namespace CodePaster
diff --git a/src/plugins/cpaster/pasteselectdialog.cpp b/src/plugins/cpaster/pasteselectdialog.cpp
index 32337e48f0..193c49525b 100644
--- a/src/plugins/cpaster/pasteselectdialog.cpp
+++ b/src/plugins/cpaster/pasteselectdialog.cpp
@@ -44,7 +44,7 @@ PasteSelectDialog::PasteSelectDialog(const QList<Protocol*> &protocols,
m_ui.protocolBox->addItem(protocol->name());
connect(protocol, &Protocol::listDone, this, &PasteSelectDialog::listDone);
}
- connect(m_ui.protocolBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui.protocolBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &PasteSelectDialog::protocolChanged);
m_refreshButton = m_ui.buttons->addButton(tr("Refresh"), QDialogButtonBox::ActionRole);
diff --git a/src/plugins/cpaster/pasteview.cpp b/src/plugins/cpaster/pasteview.cpp
index 0035fe10d3..17ad2abcfc 100644
--- a/src/plugins/cpaster/pasteview.cpp
+++ b/src/plugins/cpaster/pasteview.cpp
@@ -53,7 +53,7 @@ PasteView::PasteView(const QList<Protocol *> &protocols,
foreach (const Protocol *p, protocols)
m_ui.protocolBox->addItem(p->name());
- connect(m_ui.protocolBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui.protocolBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &PasteView::protocolChanged);
}
diff --git a/src/plugins/cpaster/protocol.cpp b/src/plugins/cpaster/protocol.cpp
index ba0b4b7ec3..b2b1e73792 100644
--- a/src/plugins/cpaster/protocol.cpp
+++ b/src/plugins/cpaster/protocol.cpp
@@ -24,9 +24,6 @@
****************************************************************************/
#include "protocol.h"
-#ifdef CPASTER_PLUGIN_GUI
-#include "authenticationdialog.h"
-#endif
#include <utils/networkaccessmanager.h>
@@ -50,7 +47,6 @@
#include <QMessageBox>
#include <QApplication>
#include <QPushButton>
-#include <QAuthenticator>
namespace CodePaster {
@@ -207,35 +203,8 @@ QNetworkReply *NetworkProtocol::httpPost(const QString &link, const QByteArray &
return Utils::NetworkAccessManager::instance()->post(r, data);
}
-NetworkProtocol::NetworkProtocol()
- : Protocol()
-{
- connect(Utils::NetworkAccessManager::instance(), &QNetworkAccessManager::authenticationRequired,
- this, &NetworkProtocol::authenticationRequired);
-}
-
NetworkProtocol::~NetworkProtocol() = default;
-void NetworkProtocol::requestAuthentication(const QUrl &url, QNetworkReply *reply, QAuthenticator *authenticator)
-{
-#ifdef CPASTER_PLUGIN_GUI
- if (reply->request().url().host() == url.host()) {
- const QString details = tr("Pasting needs authentication.<br/>"
- "Enter your identity credentials to continue.");
- AuthenticationDialog authDialog(details, Core::ICore::dialogParent());
- authDialog.setWindowTitle(tr("Authenticate for Paster"));
- if (authDialog.exec() == QDialog::Accepted) {
- authenticator->setUser(authDialog.userName());
- authenticator->setPassword(authDialog.password());
- }
- }
-#else
- Q_UNUSED(url);
- Q_UNUSED(reply);
- Q_UNUSED(authenticator);
-#endif
-}
-
bool NetworkProtocol::httpStatus(QString url, QString *errorMessage, bool useHttps)
{
// Connect to host and display a message box, using its event loop.
diff --git a/src/plugins/cpaster/protocol.h b/src/plugins/cpaster/protocol.h
index 0b1392656a..c315a673d1 100644
--- a/src/plugins/cpaster/protocol.h
+++ b/src/plugins/cpaster/protocol.h
@@ -30,7 +30,6 @@
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
-class QAuthenticator;
class QNetworkReply;
class QWidget;
QT_END_NAMESPACE
@@ -108,16 +107,11 @@ class NetworkProtocol : public Protocol
Q_OBJECT
public:
- NetworkProtocol();
+ NetworkProtocol() = default;
~NetworkProtocol() override;
-signals:
- void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
-
protected:
- void requestAuthentication(const QUrl &url, QNetworkReply *reply, QAuthenticator *authenticator);
-
QNetworkReply *httpGet(const QString &url, bool handleCookies = false);
QNetworkReply *httpPost(const QString &link, const QByteArray &data,
diff --git a/src/plugins/cpaster/stickynotespasteprotocol.cpp b/src/plugins/cpaster/stickynotespasteprotocol.cpp
new file mode 100644
index 0000000000..3ec958d99c
--- /dev/null
+++ b/src/plugins/cpaster/stickynotespasteprotocol.cpp
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "stickynotespasteprotocol.h"
+#ifdef CPASTER_PLUGIN_GUI
+#endif
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+
+#include <QDebug>
+#include <QByteArray>
+#include <QStringList>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QRegularExpression>
+#include <QNetworkReply>
+
+#include <algorithm>
+
+enum { debug = 0 };
+
+static inline QByteArray expiryParameter(int daysRequested)
+{
+ // Obtained by 'pastebin.kde.org/api/json/parameter/expire' on 26.03.2014
+ static const int expiryTimesSec[] = {1800, 21600, 86400, 604800, 2592000, 31536000};
+ const int *end = expiryTimesSec + sizeof(expiryTimesSec) / sizeof(expiryTimesSec[0]);
+ // Find the first element >= requested span, search up to n - 1 such that 'end' defaults to last value.
+ const int *match = std::lower_bound(expiryTimesSec, end - 1, 24 * 60 * 60 * daysRequested);
+ return QByteArray("expire=") + QByteArray::number(*match);
+}
+
+namespace CodePaster {
+
+void StickyNotesPasteProtocol::setHostUrl(const QString &hostUrl)
+{
+ m_hostUrl = hostUrl;
+ if (!m_hostUrl.endsWith(QLatin1Char('/')))
+ m_hostUrl.append(QLatin1Char('/'));
+}
+
+unsigned StickyNotesPasteProtocol::capabilities() const
+{
+ return ListCapability | PostDescriptionCapability;
+}
+
+bool StickyNotesPasteProtocol::checkConfiguration(QString *errorMessage)
+{
+ if (m_hostChecked) // Check the host once.
+ return true;
+ const bool ok = httpStatus(m_hostUrl, errorMessage, true);
+ if (ok)
+ m_hostChecked = true;
+ return ok;
+}
+
+// Query 'http://pastebin.kde.org/api/json/parameter/language' to obtain the valid values.
+static inline QByteArray pasteLanguage(Protocol::ContentType ct)
+{
+ switch (ct) {
+ case Protocol::Text:
+ break;
+ case Protocol::C:
+ return "language=c";
+ case Protocol::Cpp:
+ return "language=cpp-qt";
+ case Protocol::JavaScript:
+ return "language=javascript";
+ case Protocol::Diff:
+ return "language=diff";
+ case Protocol::Xml:
+ return "language=xml";
+ }
+ return QByteArray("language=text");
+}
+
+void StickyNotesPasteProtocol::paste(const QString &text,
+ ContentType ct, int expiryDays,
+ const QString &username,
+ const QString &comment,
+ const QString &description)
+{
+ enum { maxDescriptionLength = 30 }; // Length of description is limited.
+
+ Q_UNUSED(username)
+ Q_UNUSED(comment);
+ QTC_ASSERT(!m_pasteReply, return);
+
+ // Format body
+ QByteArray pasteData = "&data=";
+ pasteData += QUrl::toPercentEncoding(fixNewLines(text));
+ pasteData += '&';
+ pasteData += pasteLanguage(ct);
+ pasteData += '&';
+ pasteData += expiryParameter(expiryDays);
+ if (!description.isEmpty()) {
+ pasteData += "&title=";
+ pasteData += QUrl::toPercentEncoding(description.left(maxDescriptionLength));
+ }
+
+ m_pasteReply = httpPost(m_hostUrl + QLatin1String("api/json/create"), pasteData, true);
+ connect(m_pasteReply, &QNetworkReply::finished, this, &StickyNotesPasteProtocol::pasteFinished);
+ if (debug)
+ qDebug() << "paste: sending " << m_pasteReply << pasteData;
+}
+
+// Parse for an element and return its contents
+static QString parseElement(QIODevice *device, const QString &elementName)
+{
+ const QJsonDocument doc = QJsonDocument::fromJson(device->readAll());
+ if (doc.isEmpty() || !doc.isObject())
+ return QString();
+
+ QJsonObject obj= doc.object();
+ const QString resultKey = QLatin1String("result");
+
+ if (obj.contains(resultKey)) {
+ QJsonValue value = obj.value(resultKey);
+ if (value.isObject()) {
+ obj = value.toObject();
+ if (obj.contains(elementName)) {
+ value = obj.value(elementName);
+ return value.toString();
+ }
+ } else if (value.isArray()) {
+ qWarning() << "JsonArray not expected.";
+ }
+ }
+
+ return QString();
+}
+
+void StickyNotesPasteProtocol::pasteFinished()
+{
+ if (m_pasteReply->error()) {
+ qWarning("%s protocol error: %s", qPrintable(name()),qPrintable(m_pasteReply->errorString()));
+ } else {
+ // Parse id from '<result><id>143204</id><hash></hash></result>'
+ // No useful error reports have been observed.
+ const QString id = parseElement(m_pasteReply, QLatin1String("id"));
+ if (id.isEmpty())
+ qWarning("%s protocol error: Could not send entry.", qPrintable(name()));
+ else
+ emit pasteDone(m_hostUrl + id);
+ }
+
+ m_pasteReply->deleteLater();
+ m_pasteReply = nullptr;
+}
+
+void StickyNotesPasteProtocol::fetch(const QString &id)
+{
+ QTC_ASSERT(!m_fetchReply, return);
+
+ // Did we get a complete URL or just an id?
+ m_fetchId = id;
+ const int lastSlashPos = m_fetchId.lastIndexOf(QLatin1Char('/'));
+ if (lastSlashPos != -1)
+ m_fetchId.remove(0, lastSlashPos + 1);
+ QString url = m_hostUrl + QLatin1String("api/json/show/") + m_fetchId;
+ if (debug)
+ qDebug() << "fetch: sending " << url;
+
+ m_fetchReply = httpGet(url);
+ connect(m_fetchReply, &QNetworkReply::finished,
+ this, &StickyNotesPasteProtocol::fetchFinished);
+}
+
+// Parse: '<result><id>143228</id><author>foo</author><timestamp>1320661026</timestamp><language>text</language>
+// <data>bar</data></result>'
+
+void StickyNotesPasteProtocol::fetchFinished()
+{
+ const QString title = name() + QLatin1String(": ") + m_fetchId;
+ QString content;
+ const bool error = m_fetchReply->error();
+ if (error) {
+ content = m_fetchReply->errorString();
+ if (debug)
+ qDebug() << "fetchFinished: error" << m_fetchId << content;
+ } else {
+ content = parseElement(m_fetchReply, QLatin1String("data"));
+ content.remove(QLatin1Char('\r'));
+ }
+ m_fetchReply->deleteLater();
+ m_fetchReply = nullptr;
+ emit fetchDone(title, content, error);
+}
+
+void StickyNotesPasteProtocol::list()
+{
+ QTC_ASSERT(!m_listReply, return);
+
+ // Trailing slash is important to prevent redirection.
+ QString url = m_hostUrl + QLatin1String("api/json/list");
+ m_listReply = httpGet(url);
+ connect(m_listReply, &QNetworkReply::finished,
+ this, &StickyNotesPasteProtocol::listFinished);
+ if (debug)
+ qDebug() << "list: sending " << url << m_listReply;
+}
+
+// Parse 'result><pastes><paste>id1</paste><paste>id2</paste>...'
+static inline QStringList parseList(QIODevice *device)
+{
+ QStringList result;
+ const QJsonDocument doc = QJsonDocument::fromJson(device->readAll());
+ if (doc.isEmpty() || !doc.isObject())
+ return result;
+
+ QJsonObject obj= doc.object();
+ const QString resultKey = QLatin1String("result");
+ const QString pastesKey = QLatin1String("pastes");
+
+ if (obj.contains(resultKey)) {
+ QJsonValue value = obj.value(resultKey);
+ if (value.isObject()) {
+ obj = value.toObject();
+ if (obj.contains(pastesKey)) {
+ value = obj.value(pastesKey);
+ if (value.isArray()) {
+ QJsonArray array = value.toArray();
+ foreach (const QJsonValue &val, array)
+ result.append(val.toString());
+ }
+ }
+ }
+ }
+ return result;
+}
+
+void StickyNotesPasteProtocol::listFinished()
+{
+ const bool error = m_listReply->error();
+ if (error) {
+ if (debug)
+ qDebug() << "listFinished: error" << m_listReply->errorString();
+ } else {
+ emit listDone(name(), parseList(m_listReply));
+ }
+ m_listReply->deleteLater();
+ m_listReply = nullptr;
+}
+
+
+} // namespace CodePaster
diff --git a/src/plugins/cpaster/stickynotespasteprotocol.h b/src/plugins/cpaster/stickynotespasteprotocol.h
new file mode 100644
index 0000000000..584c90a921
--- /dev/null
+++ b/src/plugins/cpaster/stickynotespasteprotocol.h
@@ -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.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "protocol.h"
+
+namespace CodePaster {
+
+class StickyNotesPasteProtocol : public NetworkProtocol
+{
+ Q_OBJECT
+public:
+ unsigned capabilities() const override;
+
+ void fetch(const QString &id) override;
+ void paste(const QString &text,
+ ContentType ct = Text,
+ int expiryDays = 1,
+ const QString &username = QString(),
+ const QString &comment = QString(),
+ const QString &description = QString()) override;
+ void list() override;
+
+
+
+ QString hostUrl() const { return m_hostUrl; }
+ void setHostUrl(const QString &hostUrl);
+
+protected:
+ bool checkConfiguration(QString *errorMessage = nullptr) override;
+
+private:
+ void fetchFinished();
+ void pasteFinished();
+ void listFinished();
+
+ QString m_hostUrl;
+
+ QNetworkReply *m_fetchReply = nullptr;
+ QNetworkReply *m_pasteReply = nullptr;
+ QNetworkReply *m_listReply = nullptr;
+
+ QString m_fetchId;
+ int m_postId = -1;
+ bool m_hostChecked = false;
+};
+
+} // namespace CodePaster
diff --git a/src/plugins/cppcheck/CMakeLists.txt b/src/plugins/cppcheck/CMakeLists.txt
new file mode 100644
index 0000000000..76c2148c79
--- /dev/null
+++ b/src/plugins/cppcheck/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_qtc_plugin(Cppcheck
+ DEPENDS Qt5::Widgets
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer TextEditor
+ SOURCES
+ cppcheckconstants.h
+ cppcheckdiagnostic.h
+ cppcheckoptions.cpp cppcheckoptions.h
+ cppcheckplugin.cpp cppcheckplugin.h
+ cppcheckrunner.cpp cppcheckrunner.h
+ cppchecktextmark.cpp cppchecktextmark.h
+ cppchecktextmarkmanager.cpp cppchecktextmarkmanager.h
+ cppchecktool.cpp cppchecktool.h
+ cppchecktrigger.cpp cppchecktrigger.h
+)
diff --git a/src/plugins/cppcheck/cppcheckdiagnostic.h b/src/plugins/cppcheck/cppcheckdiagnostic.h
index 66e0b1dc82..566a60b974 100644
--- a/src/plugins/cppcheck/cppcheckdiagnostic.h
+++ b/src/plugins/cppcheck/cppcheckdiagnostic.h
@@ -44,7 +44,7 @@ public:
QString severityText;
QString checkId;
QString message;
- Utils::FileName fileName;
+ Utils::FilePath fileName;
int lineNumber = 0;
};
diff --git a/src/plugins/cppcheck/cppcheckrunner.cpp b/src/plugins/cppcheck/cppcheckrunner.cpp
index f67044cb67..9b9872097a 100644
--- a/src/plugins/cppcheck/cppcheckrunner.cpp
+++ b/src/plugins/cppcheck/cppcheckrunner.cpp
@@ -32,6 +32,8 @@
#include <coreplugin/messagemanager.h>
+using namespace Utils;
+
namespace Cppcheck {
namespace Internal {
@@ -75,15 +77,15 @@ void CppcheckRunner::reconfigure(const QString &binary, const QString &arguments
m_arguments = arguments;
}
-void CppcheckRunner::addToQueue(const Utils::FileNameList &files,
+void CppcheckRunner::addToQueue(const Utils::FilePathList &files,
const QString &additionalArguments)
{
- Utils::FileNameList &existing = m_queue[additionalArguments];
+ Utils::FilePathList &existing = m_queue[additionalArguments];
if (existing.isEmpty()) {
existing = files;
} else {
std::copy_if(files.cbegin(), files.cend(), std::back_inserter(existing),
- [&existing](const Utils::FileName &file) { return !existing.contains(file); });
+ [&existing](const Utils::FilePath &file) { return !existing.contains(file); });
}
if (m_isRunning) {
@@ -94,7 +96,7 @@ void CppcheckRunner::addToQueue(const Utils::FileNameList &files,
m_queueTimer.start();
}
-void CppcheckRunner::stop(const Utils::FileNameList &files)
+void CppcheckRunner::stop(const Utils::FilePathList &files)
{
if (!m_isRunning)
return;
@@ -103,7 +105,7 @@ void CppcheckRunner::stop(const Utils::FileNameList &files)
m_process->kill();
}
-void CppcheckRunner::removeFromQueue(const Utils::FileNameList &files)
+void CppcheckRunner::removeFromQueue(const Utils::FilePathList &files)
{
if (m_queue.isEmpty())
return;
@@ -112,14 +114,14 @@ void CppcheckRunner::removeFromQueue(const Utils::FileNameList &files)
m_queue.clear();
} else {
for (auto it = m_queue.begin(), end = m_queue.end(); it != end;) {
- for (const Utils::FileName &file : files)
+ for (const Utils::FilePath &file : files)
it.value().removeOne(file);
it = !it.value().isEmpty() ? ++it : m_queue.erase(it);
}
}
}
-const Utils::FileNameList &CppcheckRunner::currentFiles() const
+const Utils::FilePathList &CppcheckRunner::currentFiles() const
{
return m_currentFiles;
}
@@ -135,12 +137,12 @@ void CppcheckRunner::checkQueued()
if (m_queue.isEmpty() || m_binary.isEmpty())
return;
- Utils::FileNameList files = m_queue.begin().value();
+ Utils::FilePathList files = m_queue.begin().value();
QString arguments = m_arguments + ' ' + m_queue.begin().key();
m_currentFiles.clear();
int argumentsLength = arguments.length();
while (!files.isEmpty()) {
- argumentsLength += files.first().length() + 1; // +1 for separator
+ argumentsLength += files.first().toString().size() + 1; // +1 for separator
if (argumentsLength >= m_maxArgumentsLength)
break;
m_currentFiles.push_back(files.first());
@@ -153,7 +155,7 @@ void CppcheckRunner::checkQueued()
else
m_queue.begin().value() = files;
- m_process->setCommand(m_binary, arguments);
+ m_process->setCommand(CommandLine(FilePath::fromString(m_binary), arguments));
m_process->start();
}
diff --git a/src/plugins/cppcheck/cppcheckrunner.h b/src/plugins/cppcheck/cppcheckrunner.h
index 733ef07d6d..522c33af2c 100644
--- a/src/plugins/cppcheck/cppcheckrunner.h
+++ b/src/plugins/cppcheck/cppcheckrunner.h
@@ -30,8 +30,8 @@
namespace Utils {
class QtcProcess;
-class FileName;
-using FileNameList = QList<FileName>;
+class FilePath;
+using FilePathList = QList<FilePath>;
}
namespace Cppcheck {
@@ -48,12 +48,12 @@ public:
~CppcheckRunner() override;
void reconfigure(const QString &binary, const QString &arguments);
- void addToQueue(const Utils::FileNameList &files,
+ void addToQueue(const Utils::FilePathList &files,
const QString &additionalArguments = {});
- void removeFromQueue(const Utils::FileNameList &files);
- void stop(const Utils::FileNameList &files = {});
+ void removeFromQueue(const Utils::FilePathList &files);
+ void stop(const Utils::FilePathList &files = {});
- const Utils::FileNameList &currentFiles() const;
+ const Utils::FilePathList &currentFiles() const;
QString currentCommand() const;
private:
@@ -67,8 +67,8 @@ private:
Utils::QtcProcess *m_process = nullptr;
QString m_binary;
QString m_arguments;
- QHash<QString, Utils::FileNameList> m_queue;
- Utils::FileNameList m_currentFiles;
+ QHash<QString, Utils::FilePathList> m_queue;
+ Utils::FilePathList m_currentFiles;
QTimer m_queueTimer;
int m_maxArgumentsLength = 32767;
bool m_isRunning = false;
diff --git a/src/plugins/cppcheck/cppchecktextmarkmanager.cpp b/src/plugins/cppcheck/cppchecktextmarkmanager.cpp
index 2d19a22151..9c2d50c6aa 100644
--- a/src/plugins/cppcheck/cppchecktextmarkmanager.cpp
+++ b/src/plugins/cppcheck/cppchecktextmarkmanager.cpp
@@ -45,13 +45,13 @@ void CppcheckTextMarkManager::add(const Diagnostic &diagnostic)
fileMarks.push_back(std::make_unique<CppcheckTextMark>(diagnostic));
}
-void CppcheckTextMarkManager::clearFiles(const Utils::FileNameList &files)
+void CppcheckTextMarkManager::clearFiles(const Utils::FilePathList &files)
{
if (m_marks.empty())
return;
if (!files.empty()) {
- for (const Utils::FileName &file : files)
+ for (const Utils::FilePath &file : files)
m_marks.erase(file);
} else {
m_marks.clear();
diff --git a/src/plugins/cppcheck/cppchecktextmarkmanager.h b/src/plugins/cppcheck/cppchecktextmarkmanager.h
index e509fe9985..01be470816 100644
--- a/src/plugins/cppcheck/cppchecktextmarkmanager.h
+++ b/src/plugins/cppcheck/cppchecktextmarkmanager.h
@@ -42,11 +42,11 @@ public:
~CppcheckTextMarkManager();
void add(const Diagnostic &diagnostic);
- void clearFiles(const Utils::FileNameList &files);
+ void clearFiles(const Utils::FilePathList &files);
private:
using MarkPtr = std::unique_ptr<CppcheckTextMark>;
- std::unordered_map<Utils::FileName, std::vector<MarkPtr>> m_marks;
+ std::unordered_map<Utils::FilePath, std::vector<MarkPtr>> m_marks;
};
} // namespace Internal
diff --git a/src/plugins/cppcheck/cppchecktool.cpp b/src/plugins/cppcheck/cppchecktool.cpp
index 78d3c9fee0..0c95f30fbd 100644
--- a/src/plugins/cppcheck/cppchecktool.cpp
+++ b/src/plugins/cppcheck/cppchecktool.cpp
@@ -165,6 +165,8 @@ QStringList CppcheckTool::additionalArguments(const CppTools::ProjectPart &part)
case Version::CXX2a:
result.push_back("--language=c++");
break;
+ case Version::None:
+ break;
}
using QtVersion = CppTools::ProjectPart::QtVersion;
@@ -179,16 +181,16 @@ const CppcheckOptions &CppcheckTool::options() const
return m_options;
}
-void CppcheckTool::check(const Utils::FileNameList &files)
+void CppcheckTool::check(const Utils::FilePathList &files)
{
QTC_ASSERT(m_project, return);
- Utils::FileNameList filtered;
+ Utils::FilePathList filtered;
if (m_filters.isEmpty()) {
filtered = files;
} else {
std::copy_if(files.cbegin(), files.cend(), std::back_inserter(filtered),
- [this](const Utils::FileName &file) {
+ [this](const Utils::FilePath &file) {
const QString stringed = file.toString();
const auto filter = [stringed](const QRegExp &re) {return re.exactMatch(stringed);};
return !Utils::contains(m_filters, filter);
@@ -206,8 +208,8 @@ void CppcheckTool::check(const Utils::FileNameList &files)
return;
}
- std::map<CppTools::ProjectPart::Ptr, Utils::FileNameList> groups;
- for (const Utils::FileName &file : qAsConst(filtered)) {
+ std::map<CppTools::ProjectPart::Ptr, Utils::FilePathList> groups;
+ for (const Utils::FilePath &file : qAsConst(filtered)) {
const QString stringed = file.toString();
for (const CppTools::ProjectPart::Ptr &part : parts) {
using CppTools::ProjectFile;
@@ -222,7 +224,7 @@ void CppcheckTool::check(const Utils::FileNameList &files)
addToQueue(group.second, *group.first);
}
-void CppcheckTool::addToQueue(const Utils::FileNameList &files, CppTools::ProjectPart &part)
+void CppcheckTool::addToQueue(const Utils::FilePathList &files, CppTools::ProjectPart &part)
{
const QString key = part.id();
if (!m_cachedAdditionalArguments.contains(key))
@@ -230,7 +232,7 @@ void CppcheckTool::addToQueue(const Utils::FileNameList &files, CppTools::Projec
m_runner->addToQueue(files, m_cachedAdditionalArguments[key]);
}
-void CppcheckTool::stop(const Utils::FileNameList &files)
+void CppcheckTool::stop(const Utils::FilePathList &files)
{
m_runner->removeFromQueue(files);
m_runner->stop(files);
@@ -297,7 +299,7 @@ void CppcheckTool::parseErrorLine(const QString &line)
if (!match.hasMatch())
return;
- const Utils::FileName fileName = Utils::FileName::fromUserInput(match.captured(File));
+ const Utils::FilePath fileName = Utils::FilePath::fromUserInput(match.captured(File));
if (!m_runner->currentFiles().contains(fileName))
return;
diff --git a/src/plugins/cppcheck/cppchecktool.h b/src/plugins/cppcheck/cppchecktool.h
index b80e3436a7..ff668cf40e 100644
--- a/src/plugins/cppcheck/cppchecktool.h
+++ b/src/plugins/cppcheck/cppchecktool.h
@@ -34,8 +34,8 @@
#include <memory>
namespace Utils {
-class FileName;
-using FileNameList = QList<FileName>;
+class FilePath;
+using FilePathList = QList<FilePath>;
}
namespace CppTools {
@@ -64,8 +64,8 @@ public:
void updateOptions(const CppcheckOptions &options);
void setProject(ProjectExplorer::Project *project);
- void check(const Utils::FileNameList &files);
- void stop(const Utils::FileNameList &files);
+ void check(const Utils::FilePathList &files);
+ void stop(const Utils::FilePathList &files);
void startParsing();
void parseOutputLine(const QString &line);
@@ -76,7 +76,7 @@ public:
private:
void updateArguments();
- void addToQueue(const Utils::FileNameList &files, CppTools::ProjectPart &part);
+ void addToQueue(const Utils::FilePathList &files, CppTools::ProjectPart &part);
QStringList additionalArguments(const CppTools::ProjectPart &part) const;
CppcheckTextMarkManager &m_marks;
diff --git a/src/plugins/cppcheck/cppchecktrigger.cpp b/src/plugins/cppcheck/cppchecktrigger.cpp
index cac3772948..a69497f9fa 100644
--- a/src/plugins/cppcheck/cppchecktrigger.cpp
+++ b/src/plugins/cppcheck/cppchecktrigger.cpp
@@ -83,12 +83,12 @@ void CppcheckTrigger::checkEditors(const QList<Core::IEditor *> &editors)
const QList<Core::IEditor *> editorList = !editors.isEmpty()
? editors : Core::DocumentModel::editorsForOpenedDocuments();
- Utils::FileNameList toCheck;
+ Utils::FilePathList toCheck;
for (const Core::IEditor *editor : editorList) {
QTC_ASSERT(editor, continue);
Core::IDocument *document = editor->document();
QTC_ASSERT(document, continue);
- const Utils::FileName &path = document->filePath();
+ const Utils::FilePath &path = document->filePath();
if (path.isEmpty())
continue;
@@ -128,12 +128,12 @@ void CppcheckTrigger::removeEditors(const QList<Core::IEditor *> &editors)
const QList<Core::IEditor *> editorList = !editors.isEmpty()
? editors : Core::DocumentModel::editorsForOpenedDocuments();
- Utils::FileNameList toRemove;
+ Utils::FilePathList toRemove;
for (const Core::IEditor *editor : editorList) {
QTC_ASSERT(editor, return);
const Core::IDocument *document = editor->document();
QTC_ASSERT(document, return);
- const Utils::FileName &path = document->filePath();
+ const Utils::FilePath &path = document->filePath();
if (path.isEmpty())
return;
@@ -156,7 +156,7 @@ void CppcheckTrigger::checkChangedDocument(Core::IDocument *document)
if (!m_currentProject)
return;
- const Utils::FileName &path = document->filePath();
+ const Utils::FilePath &path = document->filePath();
QTC_ASSERT(!path.isEmpty(), return);
if (!m_checkedFiles.contains(path))
return;
@@ -185,12 +185,12 @@ void CppcheckTrigger::updateProjectFiles(ProjectExplorer::Project *project)
checkEditors(Core::DocumentModel::editorsForOpenedDocuments());
}
-void CppcheckTrigger::check(const Utils::FileNameList &files)
+void CppcheckTrigger::check(const Utils::FilePathList &files)
{
m_tool.check(files);
}
-void CppcheckTrigger::remove(const Utils::FileNameList &files)
+void CppcheckTrigger::remove(const Utils::FilePathList &files)
{
m_marks.clearFiles(files);
m_tool.stop(files);
diff --git a/src/plugins/cppcheck/cppchecktrigger.h b/src/plugins/cppcheck/cppchecktrigger.h
index aa44f46fb7..069bfc7b04 100644
--- a/src/plugins/cppcheck/cppchecktrigger.h
+++ b/src/plugins/cppcheck/cppchecktrigger.h
@@ -29,8 +29,8 @@
#include <QPointer>
namespace Utils {
-class FileName;
-using FileNameList = QList<FileName>;
+class FilePath;
+using FilePathList = QList<FilePath>;
}
namespace ProjectExplorer {
@@ -68,13 +68,13 @@ private:
void checkChangedDocument(Core::IDocument *document);
void changeCurrentProject(ProjectExplorer::Project *project);
void updateProjectFiles(ProjectExplorer::Project *project);
- void check(const Utils::FileNameList &files);
- void remove(const Utils::FileNameList &files);
+ void check(const Utils::FilePathList &files);
+ void remove(const Utils::FilePathList &files);
CppcheckTextMarkManager &m_marks;
CppcheckTool &m_tool;
QPointer<ProjectExplorer::Project> m_currentProject;
- QHash<Utils::FileName, QDateTime> m_checkedFiles;
+ QHash<Utils::FilePath, QDateTime> m_checkedFiles;
};
} // namespace Internal
diff --git a/src/plugins/cppeditor/CMakeLists.txt b/src/plugins/cppeditor/CMakeLists.txt
new file mode 100644
index 0000000000..d2072fa5ba
--- /dev/null
+++ b/src/plugins/cppeditor/CMakeLists.txt
@@ -0,0 +1,47 @@
+add_qtc_plugin(CppEditor
+ DEFINES CPPEDITOR_LIBRARY
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer TextEditor
+ SOURCES
+ cppautocompleter.cpp cppautocompleter.h
+ cppcodemodelinspectordialog.cpp cppcodemodelinspectordialog.h cppcodemodelinspectordialog.ui
+ cppdocumentationcommenthelper.cpp cppdocumentationcommenthelper.h
+ cppeditor.cpp cppeditor.h
+ cppeditor.qrc
+ cppeditor_global.h
+ cppeditorconstants.h
+ cppeditordocument.cpp cppeditordocument.h
+ cppeditorenums.h
+ cppeditorplugin.cpp cppeditorplugin.h
+ cppeditorwidget.cpp cppeditorwidget.h
+ cppfunctiondecldeflink.cpp cppfunctiondecldeflink.h
+ cpphighlighter.cpp cpphighlighter.h
+ cppincludehierarchy.cpp cppincludehierarchy.h
+ cppinsertvirtualmethods.cpp cppinsertvirtualmethods.h
+ cpplocalrenaming.cpp cpplocalrenaming.h
+ cppminimizableinfobars.cpp cppminimizableinfobars.h
+ cppoutline.cpp cppoutline.h
+ cppparsecontext.cpp cppparsecontext.h
+ cpppreprocessordialog.cpp cpppreprocessordialog.h cpppreprocessordialog.ui
+ cppquickfix.cpp cppquickfix.h
+ cppquickfixassistant.cpp cppquickfixassistant.h
+ cppquickfixes.cpp cppquickfixes.h
+ cpptypehierarchy.cpp cpptypehierarchy.h
+ cppuseselectionsupdater.cpp cppuseselectionsupdater.h
+ resourcepreviewhoverhandler.cpp resourcepreviewhoverhandler.h
+ EXPLICIT_MOC cppeditor.h
+)
+
+extend_qtc_plugin(CppEditor
+ CONDITION WITH_TESTS
+ SOURCES
+ cppdoxygen_test.cpp cppdoxygen_test.h
+ cppeditortestcase.cpp cppeditortestcase.h
+ cppincludehierarchy_test.cpp
+ cppquickfix_test.cpp cppquickfix_test.h
+ cppuseselections_test.cpp
+ fileandtokenactions_test.cpp
+ followsymbol_switchmethoddecldef_test.cpp
+ EXPLICIT_MOC
+ cppdoxygen_test.h
+ cppquickfix_test.h
+)
diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
index 1cedfbfd9d..6b26cd8185 100644
--- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
+++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
@@ -1254,7 +1254,7 @@ void WorkingCopyModel::configure(const WorkingCopy &workingCopy)
{
emit layoutAboutToBeChanged();
m_workingCopyList.clear();
- QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
+ QHashIterator<Utils::FilePath, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
while (it.hasNext()) {
it.next();
m_workingCopyList << WorkingCopyEntry(it.key().toString(), it.value().first,
@@ -1389,7 +1389,7 @@ CppCodeModelInspectorDialog::CppCodeModelInspectorDialog(QWidget *parent)
connect(m_snapshotView, &FilterableView::filterChanged,
this, &CppCodeModelInspectorDialog::onSnapshotFilterChanged);
connect(m_ui->snapshotSelector,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &CppCodeModelInspectorDialog::onSnapshotSelected);
connect(m_ui->docSymbolsView, &QTreeView::expanded,
this, &CppCodeModelInspectorDialog::onSymbolsViewExpandedOrCollapsed);
@@ -1806,11 +1806,14 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
{QString::fromLatin1("Project Part File"), part->projectFileLocation()},
{QString::fromLatin1("Project Name"), projectName},
{QString::fromLatin1("Project File"), projectFilePath},
- {QString::fromLatin1("Buildsystem Target"), buildSystemTarget},
{QString::fromLatin1("Callgroup Id"), callGroupId},
{QString::fromLatin1("Precompiled Headers"), precompiledHeaders},
{QString::fromLatin1("Selected For Building"), CMI::Utils::toString(part->selectedForBuilding)},
+ {QString::fromLatin1("Buildsystem Target"), buildSystemTarget},
{QString::fromLatin1("Build Target Type"), CMI::Utils::toString(part->buildTargetType)},
+ {QString::fromLatin1("ToolChain Type"), part->toolchainType.toString()},
+ {QString::fromLatin1("ToolChain Target Triple"), part->toolChainTargetTriple},
+ {QString::fromLatin1("ToolChain Word Width"), CMI::Utils::toString(part->toolChainWordWidth)},
{QString::fromLatin1("Language Version"), CMI::Utils::toString(part->languageVersion)},
{QString::fromLatin1("Language Extensions"), CMI::Utils::toString(part->languageExtensions)},
{QString::fromLatin1("Qt Version"), CMI::Utils::toString(part->qtVersion)}
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index 85c10e8f0c..f09e3807d3 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -238,8 +238,8 @@ void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseCon
scheduleProcessDocument();
}
-void CppEditorDocument::onFilePathChanged(const Utils::FileName &oldPath,
- const Utils::FileName &newPath)
+void CppEditorDocument::onFilePathChanged(const Utils::FilePath &oldPath,
+ const Utils::FilePath &newPath)
{
Q_UNUSED(oldPath);
diff --git a/src/plugins/cppeditor/cppeditordocument.h b/src/plugins/cppeditor/cppeditordocument.h
index 5055b2654a..d8fc7094aa 100644
--- a/src/plugins/cppeditor/cppeditordocument.h
+++ b/src/plugins/cppeditor/cppeditordocument.h
@@ -91,7 +91,7 @@ protected:
private:
void invalidateFormatterCache();
- void onFilePathChanged(const Utils::FileName &oldPath, const Utils::FileName &newPath);
+ void onFilePathChanged(const Utils::FilePath &oldPath, const Utils::FilePath &newPath);
void onMimeTypeChanged();
void onAboutToReload();
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index f46c3db17d..bb73272446 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -27,6 +27,7 @@
#include "cppautocompleter.h"
#include "cppcodemodelinspectordialog.h"
+#include "cppeditor.h"
#include "cppeditorconstants.h"
#include "cppeditorwidget.h"
#include "cppeditordocument.h"
@@ -370,11 +371,9 @@ void CppEditorPluginPrivate::inspectCppCodeModel()
}
#ifdef WITH_TESTS
-QList<QObject *> CppEditorPlugin::createTestObjects() const
+QVector<QObject *> CppEditorPlugin::createTestObjects() const
{
- return QList<QObject *>()
- << new Tests::DoxygenTest
- ;
+ return {new Tests::DoxygenTest};
}
#endif
diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h
index f4d024f33f..40b251fbef 100644
--- a/src/plugins/cppeditor/cppeditorplugin.h
+++ b/src/plugins/cppeditor/cppeditorplugin.h
@@ -64,7 +64,7 @@ public:
#ifdef WITH_TESTS
private:
- QList<QObject *> createTestObjects() const override;
+ QVector<QObject *> createTestObjects() const override;
private slots:
// The following tests expect that no projects are loaded on start-up.
diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp
index df37a22d29..e55ac8a665 100644
--- a/src/plugins/cppeditor/cppeditorwidget.cpp
+++ b/src/plugins/cppeditor/cppeditorwidget.cpp
@@ -516,7 +516,7 @@ bool CppEditorWidget::isWidgetHighlighted(QWidget *widget)
namespace {
QList<ProjectPart::Ptr> fetchProjectParts(CppTools::CppModelManager *modelManager,
- const Utils::FileName &filePath)
+ const Utils::FilePath &filePath)
{
QList<ProjectPart::Ptr> projectParts = modelManager->projectPart(filePath);
@@ -734,7 +734,7 @@ void CppEditorWidget::findLinkAt(const QTextCursor &cursor,
if (!d->m_modelManager)
return processLinkCallback(Utils::Link());
- const Utils::FileName &filePath = textDocument()->filePath();
+ const Utils::FilePath &filePath = textDocument()->filePath();
followSymbolInterface().findLink(CppTools::CursorInEditor{cursor, filePath, this},
std::move(processLinkCallback),
diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp
index 4f34433ba4..55a2e93f19 100644
--- a/src/plugins/cppeditor/cppoutline.cpp
+++ b/src/plugins/cppeditor/cppoutline.cpp
@@ -25,6 +25,7 @@
#include "cppoutline.h"
+#include "cppeditor.h"
#include <cpptools/cppeditoroutline.h>
#include <cpptools/cppoverviewmodel.h>
diff --git a/src/plugins/cppeditor/cppoutline.h b/src/plugins/cppeditor/cppoutline.h
index f8db92c46d..9cabc48aa5 100644
--- a/src/plugins/cppeditor/cppoutline.h
+++ b/src/plugins/cppeditor/cppoutline.h
@@ -25,7 +25,6 @@
#pragma once
-#include "cppeditor.h"
#include "cppeditorwidget.h"
#include <texteditor/ioutlinewidget.h>
diff --git a/src/plugins/cppeditor/cppparsecontext.cpp b/src/plugins/cppeditor/cppparsecontext.cpp
index ef941f44d2..521cc49328 100644
--- a/src/plugins/cppeditor/cppparsecontext.cpp
+++ b/src/plugins/cppeditor/cppparsecontext.cpp
@@ -111,14 +111,16 @@ QString ParseContextModel::currentId() const
return m_projectParts[m_currentIndex]->id();
}
-int ParseContextModel::rowCount(const QModelIndex &) const
+int ParseContextModel::rowCount(const QModelIndex &parent) const
{
+ if (parent.isValid())
+ return 0;
return m_projectParts.size();
}
QVariant ParseContextModel::data(const QModelIndex &index, int role) const
{
- if (m_projectParts.isEmpty())
+ if (!index.isValid() || index.row() < 0 || index.row() >= m_projectParts.size())
return QVariant();
const int row = index.row();
@@ -149,7 +151,7 @@ ParseContextWidget::ParseContextWidget(ParseContextModel &parseContextModel, QWi
// Set up sync of this widget and model in both directions
connect(this,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ QOverload<int>::of(&QComboBox::activated),
&m_parseContextModel,
&ParseContextModel::setPreferred);
connect(&m_parseContextModel, &ParseContextModel::updated,
diff --git a/src/plugins/cppeditor/cpppreprocessordialog.cpp b/src/plugins/cppeditor/cpppreprocessordialog.cpp
index f66ee92a89..b0edff0fc0 100644
--- a/src/plugins/cppeditor/cpppreprocessordialog.cpp
+++ b/src/plugins/cppeditor/cpppreprocessordialog.cpp
@@ -42,7 +42,7 @@ CppPreProcessorDialog::CppPreProcessorDialog(const QString &filePath, QWidget *p
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_ui->setupUi(this);
- m_ui->editorLabel->setText(m_ui->editorLabel->text().arg(Utils::FileName::fromString(m_filePath).fileName()));
+ m_ui->editorLabel->setText(m_ui->editorLabel->text().arg(Utils::FilePath::fromString(m_filePath).fileName()));
m_ui->editWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
CppEditor::decorateEditor(m_ui->editWidget);
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index c17850662f..538c9242b8 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -1510,8 +1510,7 @@ void ConvertNumericLiteral::match(const CppQuickFixInterface &interface, QuickFi
0x20
*/
- QString replacement;
- replacement.sprintf("0x%lX", value);
+ const QString replacement = QString::asprintf("0x%lX", value);
auto op = new ConvertNumericLiteralOp(interface, start, start + numberLength, replacement);
op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Hexadecimal"));
op->setPriority(priority);
@@ -1528,8 +1527,7 @@ void ConvertNumericLiteral::match(const CppQuickFixInterface &interface, QuickFi
With
040
*/
- QString replacement;
- replacement.sprintf("0%lo", value);
+ const QString replacement = QString::asprintf("0%lo", value);
auto op = new ConvertNumericLiteralOp(interface, start, start + numberLength, replacement);
op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Octal"));
op->setPriority(priority);
@@ -1546,8 +1544,7 @@ void ConvertNumericLiteral::match(const CppQuickFixInterface &interface, QuickFi
With
32
*/
- QString replacement;
- replacement.sprintf("%lu", value);
+ const QString replacement = QString::asprintf("%lu", value);
auto op = new ConvertNumericLiteralOp(interface, start, start + numberLength, replacement);
op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Decimal"));
op->setPriority(priority);
@@ -1973,16 +1970,16 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
Snapshot localForwardHeaders = forwardHeaders;
localForwardHeaders.insert(interface.snapshot().document(info->fileName()));
- Utils::FileNameList headerAndItsForwardingHeaders;
- headerAndItsForwardingHeaders << Utils::FileName::fromString(info->fileName());
+ Utils::FilePathList headerAndItsForwardingHeaders;
+ headerAndItsForwardingHeaders << Utils::FilePath::fromString(info->fileName());
headerAndItsForwardingHeaders += localForwardHeaders.filesDependingOn(info->fileName());
- foreach (const Utils::FileName &header, headerAndItsForwardingHeaders) {
+ foreach (const Utils::FilePath &header, headerAndItsForwardingHeaders) {
const QString include = findShortestInclude(currentDocumentFilePath,
header.toString(),
headerPaths);
if (include.size() > 2) {
- const QString headerFileName = Utils::FileName::fromString(info->fileName()).fileName();
+ const QString headerFileName = Utils::FilePath::fromString(info->fileName()).fileName();
QTC_ASSERT(!headerFileName.isEmpty(), break);
int priority = 0;
diff --git a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp
index 72fb74f087..082c04493d 100644
--- a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp
+++ b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp
@@ -143,8 +143,8 @@ static QString findResourceInProject(const QString &resName)
return QString();
if (auto *project = ProjectExplorer::ProjectTree::currentProject()) {
- const Utils::FileNameList files = project->files(ProjectExplorer::Project::AllFiles);
- for (const Utils::FileName &file : files) {
+ const Utils::FilePathList files = project->files(ProjectExplorer::Project::AllFiles);
+ for (const Utils::FilePath &file : files) {
if (!file.endsWith(".qrc"))
continue;
const QFileInfo fi = file.toFileInfo();
diff --git a/src/plugins/cpptools/CMakeLists.txt b/src/plugins/cpptools/CMakeLists.txt
new file mode 100644
index 0000000000..c99705cbc1
--- /dev/null
+++ b/src/plugins/cpptools/CMakeLists.txt
@@ -0,0 +1,131 @@
+add_qtc_plugin(CppTools
+ DEPENDS Qt5::Network Qt5::Xml
+ PUBLIC_DEPENDS CPlusPlus Qt5::Widgets
+ PLUGIN_DEPENDS Core ProjectExplorer TextEditor
+ SOURCES
+ abstracteditorsupport.cpp abstracteditorsupport.h
+ abstractoverviewmodel.h
+ baseeditordocumentparser.cpp baseeditordocumentparser.h
+ baseeditordocumentprocessor.cpp baseeditordocumentprocessor.h
+ builtincursorinfo.cpp builtincursorinfo.h
+ builtineditordocumentparser.cpp builtineditordocumentparser.h
+ builtineditordocumentprocessor.cpp builtineditordocumentprocessor.h
+ builtinindexingsupport.cpp builtinindexingsupport.h
+ clangbasechecks.ui
+ clangdiagnosticconfig.cpp clangdiagnosticconfig.h
+ clangdiagnosticconfigsmodel.cpp clangdiagnosticconfigsmodel.h
+ clangdiagnosticconfigsselectionwidget.cpp clangdiagnosticconfigsselectionwidget.h
+ clangdiagnosticconfigswidget.cpp clangdiagnosticconfigswidget.h clangdiagnosticconfigswidget.ui
+ clazychecks.ui
+ compileroptionsbuilder.cpp compileroptionsbuilder.h
+ cppbuiltinmodelmanagersupport.cpp cppbuiltinmodelmanagersupport.h
+ cppcanonicalsymbol.cpp cppcanonicalsymbol.h
+ cppchecksymbols.cpp cppchecksymbols.h
+ cppclassesfilter.cpp cppclassesfilter.h
+ cppcodeformatter.cpp cppcodeformatter.h
+ cppcodemodelinspectordumper.cpp cppcodemodelinspectordumper.h
+ cppcodemodelsettings.cpp cppcodemodelsettings.h
+ cppcodemodelsettingspage.cpp cppcodemodelsettingspage.h cppcodemodelsettingspage.ui
+ cppcodestylepreferences.cpp cppcodestylepreferences.h
+ cppcodestylepreferencesfactory.cpp cppcodestylepreferencesfactory.h
+ cppcodestylesettings.cpp cppcodestylesettings.h
+ cppcodestylesettingspage.cpp cppcodestylesettingspage.h cppcodestylesettingspage.ui
+ cppcodestylesnippets.h
+ cppcompletionassist.cpp cppcompletionassist.h
+ cppcompletionassistprocessor.cpp cppcompletionassistprocessor.h
+ cppcompletionassistprovider.cpp cppcompletionassistprovider.h
+ cppcurrentdocumentfilter.cpp cppcurrentdocumentfilter.h
+ cppcursorinfo.h
+ cppdoxygen.cpp cppdoxygen.h
+ cppeditoroutline.cpp cppeditoroutline.h
+ cppeditorwidgetinterface.h
+ cppelementevaluator.cpp cppelementevaluator.h
+ cppfileiterationorder.cpp cppfileiterationorder.h
+ cppfilesettingspage.cpp cppfilesettingspage.h cppfilesettingspage.ui
+ cppfindreferences.cpp cppfindreferences.h
+ cppfollowsymbolundercursor.cpp cppfollowsymbolundercursor.h
+ cppfunctionsfilter.cpp cppfunctionsfilter.h
+ cpphoverhandler.cpp cpphoverhandler.h
+ cppincludesfilter.cpp cppincludesfilter.h
+ cppindexingsupport.cpp cppindexingsupport.h
+ cppkitinfo.cpp cppkitinfo.h
+ cpplocalsymbols.cpp cpplocalsymbols.h
+ cpplocatordata.cpp cpplocatordata.h
+ cpplocatorfilter.cpp cpplocatorfilter.h
+ cppmodelmanager.cpp cppmodelmanager.h
+ cppmodelmanagerinterface.h
+ cppmodelmanagersupport.cpp cppmodelmanagersupport.h
+ cppoverviewmodel.cpp cppoverviewmodel.h
+ cpppointerdeclarationformatter.cpp cpppointerdeclarationformatter.h
+ cppprojectfile.cpp cppprojectfile.h
+ cppprojectfilecategorizer.cpp cppprojectfilecategorizer.h
+ cppprojectinfogenerator.cpp cppprojectinfogenerator.h
+ cppprojectpartchooser.cpp cppprojectpartchooser.h
+ cppprojectupdater.cpp cppprojectupdater.h
+ cppqtstyleindenter.cpp cppqtstyleindenter.h
+ cpprawprojectpart.cpp cpprawprojectpart.h
+ cpprefactoringchanges.cpp cpprefactoringchanges.h
+ cpprefactoringengine.cpp cpprefactoringengine.h
+ cppselectionchanger.cpp cppselectionchanger.h
+ cppsemanticinfo.h
+ cppsemanticinfoupdater.cpp cppsemanticinfoupdater.h
+ cppsourceprocessor.cpp cppsourceprocessor.h
+ cppsymbolinfo.h
+ cpptools.qrc
+ cpptools_clangtidychecks.h
+ cpptools_clazychecks.h
+ cpptools_global.h
+ cpptools_utils.h
+ cpptoolsbridge.cpp cpptoolsbridge.h
+ cpptoolsbridgeinterface.h
+ cpptoolsbridgeqtcreatorimplementation.cpp cpptoolsbridgeqtcreatorimplementation.h
+ cpptoolsconstants.h
+ cpptoolsjsextension.cpp cpptoolsjsextension.h
+ cpptoolsplugin.cpp cpptoolsplugin.h
+ cpptoolsreuse.cpp cpptoolsreuse.h
+ cpptoolssettings.cpp cpptoolssettings.h
+ cppvirtualfunctionassistprovider.cpp cppvirtualfunctionassistprovider.h
+ cppvirtualfunctionproposalitem.cpp cppvirtualfunctionproposalitem.h
+ cppworkingcopy.cpp cppworkingcopy.h
+ cursorineditor.h
+ doxygengenerator.cpp doxygengenerator.h
+ editordocumenthandle.cpp editordocumenthandle.h
+ followsymbolinterface.h
+ functionutils.cpp functionutils.h
+ generatedcodemodelsupport.cpp generatedcodemodelsupport.h
+ headerpathfilter.cpp headerpathfilter.h
+ includeutils.cpp includeutils.h
+ indexitem.cpp indexitem.h
+ insertionpointlocator.cpp insertionpointlocator.h
+ projectinfo.cpp projectinfo.h
+ projectpart.cpp projectpart.h
+ refactoringengineinterface.h
+ searchsymbols.cpp searchsymbols.h
+ semantichighlighter.cpp semantichighlighter.h
+ senddocumenttracker.cpp senddocumenttracker.h
+ stringtable.cpp stringtable.h
+ symbolfinder.cpp symbolfinder.h
+ symbolsfindfilter.cpp symbolsfindfilter.h
+ tidychecks.ui
+ typehierarchybuilder.cpp typehierarchybuilder.h
+ usages.h
+ wrappablelineedit.cpp wrappablelineedit.h
+)
+
+extend_qtc_plugin(CppTools
+ CONDITION WITH_TESTS
+ SOURCES
+ cppcodegen_test.cpp
+ cppcompletion_test.cpp
+ cppheadersource_test.cpp
+ cpplocalsymbols_test.cpp
+ cpplocatorfilter_test.cpp
+ cppmodelmanager_test.cpp
+ cpppointerdeclarationformatter_test.cpp
+ cppsourceprocessertesthelper.cpp cppsourceprocessertesthelper.h
+ cppsourceprocessor_test.cpp
+ cpptoolstestcase.cpp cpptoolstestcase.h
+ modelmanagertesthelper.cpp modelmanagertesthelper.h
+ symbolsearcher_test.cpp
+ typehierarchybuilder_test.cpp
+)
diff --git a/src/plugins/cpptools/abstracteditorsupport.cpp b/src/plugins/cpptools/abstracteditorsupport.cpp
index 8818c83efb..05c9112555 100644
--- a/src/plugins/cpptools/abstracteditorsupport.cpp
+++ b/src/plugins/cpptools/abstracteditorsupport.cpp
@@ -62,7 +62,7 @@ QString AbstractEditorSupport::licenseTemplate(const QString &file, const QStrin
const QString license = Internal::CppFileSettings::licenseTemplate();
Utils::MacroExpander expander;
expander.registerVariable("Cpp:License:FileName", tr("The file name."),
- [file]() { return Utils::FileName::fromString(file).fileName(); });
+ [file]() { return Utils::FilePath::fromString(file).fileName(); });
expander.registerVariable("Cpp:License:ClassName", tr("The class name."),
[className]() { return className; });
diff --git a/src/plugins/cpptools/baseeditordocumentparser.cpp b/src/plugins/cpptools/baseeditordocumentparser.cpp
index f0c7d9f680..91c6a3aa79 100644
--- a/src/plugins/cpptools/baseeditordocumentparser.cpp
+++ b/src/plugins/cpptools/baseeditordocumentparser.cpp
@@ -133,7 +133,7 @@ ProjectPartInfo BaseEditorDocumentParser::determineProjectPart(
return CppModelManager::instance()->projectPart(filePath);
});
chooser.setProjectPartsFromDependenciesForFile([&](const QString &filePath) {
- const auto fileName = Utils::FileName::fromString(filePath);
+ const auto fileName = Utils::FilePath::fromString(filePath);
return CppModelManager::instance()->projectPartFromDependencies(fileName);
});
diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp
index d802e67250..a8f44e1e0c 100644
--- a/src/plugins/cpptools/builtineditordocumentparser.cpp
+++ b/src/plugins/cpptools/builtineditordocumentparser.cpp
@@ -145,9 +145,9 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
state.snapshot = Snapshot();
} else {
// Remove changed files from the snapshot
- QSet<Utils::FileName> toRemove;
+ QSet<Utils::FilePath> toRemove;
foreach (const Document::Ptr &doc, state.snapshot) {
- const Utils::FileName fileName = Utils::FileName::fromString(doc->fileName());
+ const Utils::FilePath fileName = Utils::FilePath::fromString(doc->fileName());
if (workingCopy.contains(fileName)) {
if (workingCopy.get(fileName).second != doc->editorRevision())
addFileAndDependencies(&state.snapshot, &toRemove, fileName);
@@ -160,7 +160,7 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
if (!toRemove.isEmpty()) {
invalidateSnapshot = true;
- foreach (const Utils::FileName &fileName, toRemove)
+ foreach (const Utils::FilePath &fileName, toRemove)
state.snapshot.remove(fileName);
}
}
@@ -261,15 +261,15 @@ BuiltinEditorDocumentParser::Ptr BuiltinEditorDocumentParser::get(const QString
}
void BuiltinEditorDocumentParser::addFileAndDependencies(Snapshot *snapshot,
- QSet<Utils::FileName> *toRemove,
- const Utils::FileName &fileName) const
+ QSet<Utils::FilePath> *toRemove,
+ const Utils::FilePath &fileName) const
{
QTC_ASSERT(snapshot, return);
toRemove->insert(fileName);
- if (fileName != Utils::FileName::fromString(filePath())) {
- Utils::FileNameList deps = snapshot->filesDependingOn(fileName);
- toRemove->unite(QSet<Utils::FileName>::fromList(deps));
+ if (fileName != Utils::FilePath::fromString(filePath())) {
+ Utils::FilePathList deps = snapshot->filesDependingOn(fileName);
+ toRemove->unite(QSet<Utils::FilePath>::fromList(deps));
}
}
diff --git a/src/plugins/cpptools/builtineditordocumentparser.h b/src/plugins/cpptools/builtineditordocumentparser.h
index 3f53ae765e..7a1b9fd880 100644
--- a/src/plugins/cpptools/builtineditordocumentparser.h
+++ b/src/plugins/cpptools/builtineditordocumentparser.h
@@ -61,8 +61,8 @@ private:
void updateImpl(const QFutureInterface<void> &future,
const UpdateParams &updateParams) override;
void addFileAndDependencies(CPlusPlus::Snapshot *snapshot,
- QSet<Utils::FileName> *toRemove,
- const Utils::FileName &fileName) const;
+ QSet<Utils::FilePath> *toRemove,
+ const Utils::FilePath &fileName) const;
struct ExtraState {
QByteArray configFile;
diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp
index ff21e85500..3677cefc29 100644
--- a/src/plugins/cpptools/builtinindexingsupport.cpp
+++ b/src/plugins/cpptools/builtinindexingsupport.cpp
@@ -52,6 +52,7 @@ using namespace CppTools;
using namespace CppTools::Internal;
static const bool FindErrorsIndexing = qgetenv("QTC_FIND_ERRORS_INDEXING") == "1";
+static Q_LOGGING_CATEGORY(indexerLog, "qtc.cpptools.indexer", QtWarningMsg)
namespace {
@@ -205,6 +206,8 @@ void index(QFutureInterface<void> &indexingFuture,
const ProjectExplorer::HeaderPaths fallbackHeaderPaths = cmm->headerPaths();
const CPlusPlus::LanguageFeatures defaultFeatures =
CPlusPlus::LanguageFeatures::defaultFeatures();
+
+ qCDebug(indexerLog) << "About to index" << files.size() << "files.";
for (int i = 0; i < files.size(); ++i) {
if (indexingFuture.isCanceled() || superFuture.isCanceled())
break;
@@ -225,6 +228,7 @@ void index(QFutureInterface<void> &indexingFuture,
processingHeaders = true;
}
+ qCDebug(indexerLog) << " Indexing" << i + 1 << "of" << files.size() << ":" << fileName;
ProjectExplorer::HeaderPaths headerPaths = parts.isEmpty()
? fallbackHeaderPaths
: parts.first()->headerPaths;
@@ -236,6 +240,7 @@ void index(QFutureInterface<void> &indexingFuture,
if (isSourceFile)
sourceProcessor->resetEnvironment();
}
+ qCDebug(indexerLog) << "Indexing finished.";
}
void parse(QFutureInterface<void> &indexingFuture,
@@ -310,7 +315,7 @@ public:
item.path = scope.split(QLatin1String("::"), QString::SkipEmptyParts);
item.text = text;
item.icon = info->icon();
- item.userData = qVariantFromValue(info);
+ item.userData = QVariant::fromValue(info);
resultItems << item;
}
diff --git a/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp
index eb89d7d87e..7899fcae4c 100644
--- a/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp
+++ b/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp
@@ -68,10 +68,8 @@ Core::Id ClangDiagnosticConfigsSelectionWidget::currentConfigId() const
void ClangDiagnosticConfigsSelectionWidget::connectToCurrentIndexChanged()
{
m_currentIndexChangedConnection
- = connect(m_selectionComboBox,
- static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this,
- [this]() { emit currentConfigChanged(currentConfigId()); });
+ = connect(m_selectionComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, [this]() { emit currentConfigChanged(currentConfigId()); });
}
void ClangDiagnosticConfigsSelectionWidget::disconnectFromCurrentIndexChanged()
diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
index ea0386239f..01164bfb1a 100644
--- a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
+++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
@@ -70,7 +70,7 @@ static void buildTree(ProjectExplorer::Tree *parent,
current->fullPath = parent->fullPath + current->name;
parent->childDirectories.push_back(current);
} else {
- current->fullPath = Utils::FileName::fromString(current->name);
+ current->fullPath = Utils::FilePath::fromString(current->name);
}
current->parent = parent;
for (const Constants::TidyNode &nodeChild : node.children)
@@ -910,7 +910,7 @@ void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMes
void ClangDiagnosticConfigsWidget::connectClangTidyItemChanged()
{
connect(m_tidyChecks->tidyMode,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&ClangDiagnosticConfigsWidget::onClangTidyModeChanged);
connect(m_tidyTreeModel.get(), &TidyChecksTreeModel::dataChanged,
@@ -920,7 +920,7 @@ void ClangDiagnosticConfigsWidget::connectClangTidyItemChanged()
void ClangDiagnosticConfigsWidget::disconnectClangTidyItemChanged()
{
disconnect(m_tidyChecks->tidyMode,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&ClangDiagnosticConfigsWidget::onClangTidyModeChanged);
disconnect(m_tidyTreeModel.get(), &TidyChecksTreeModel::dataChanged,
diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp
index 8dfe0c7977..3d74ad8d32 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.cpp
+++ b/src/plugins/cpptools/compileroptionsbuilder.cpp
@@ -455,6 +455,8 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
case LanguageVersion::CXX2a:
option = (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a"));
break;
+ case LanguageVersion::None:
+ break;
}
add(option, /*gccOnlyOption=*/true);
@@ -522,6 +524,7 @@ static QStringList languageFeatureMacros()
"__cpp_guaranteed_copy_elision",
"__cpp_hex_float",
"__cpp_if_constexpr",
+ "__cpp_impl_destroying_delete",
"__cpp_inheriting_constructors",
"__cpp_init_captures",
"__cpp_initializer_lists",
@@ -706,6 +709,7 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
qgetenv("QTC_CLANG_CMD_OPTIONS_BLACKLIST"))
.split(';', QString::SkipEmptyParts);
+ const Core::Id &toolChain = m_projectPart.toolchainType;
bool containsDriverMode = false;
bool skipNext = false;
for (const QString &option : m_projectPart.compilerFlags) {
@@ -717,6 +721,13 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
if (userBlackList.contains(option))
continue;
+ // TODO: Make it possible that the clang binary/driver ignores unknown options,
+ // as it is done for libclang/clangd (not checking for OPT_UNKNOWN).
+ if (toolChain == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) {
+ if (option == "-fkeep-inline-dllexport" || option == "-fno-keep-inline-dllexport")
+ continue;
+ }
+
// Ignore warning flags as these interfere with our user-configured diagnostics.
// Note that once "-w" is provided, no warnings will be emitted, even if "-Wall" follows.
if (m_useBuildSystemWarnings == UseBuildSystemWarnings::No
@@ -752,7 +763,7 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
// Check whether a language version is already used.
QString theOption = option;
- if (theOption.startsWith("-std=")) {
+ if (theOption.startsWith("-std=") || theOption.startsWith("--std=")) {
m_compilerFlags.isLanguageVersionSpecified = true;
theOption.replace("=c18", "=c17");
theOption.replace("=gnu18", "=gnu17");
@@ -769,7 +780,6 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
m_compilerFlags.flags.append(theOption);
}
- const Core::Id &toolChain = m_projectPart.toolchainType;
if (!containsDriverMode
&& (toolChain == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
|| toolChain == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID)) {
diff --git a/src/plugins/cpptools/cppclassesfilter.cpp b/src/plugins/cpptools/cppclassesfilter.cpp
index 1306a155a4..ee691ba98b 100644
--- a/src/plugins/cpptools/cppclassesfilter.cpp
+++ b/src/plugins/cpptools/cppclassesfilter.cpp
@@ -43,7 +43,7 @@ CppClassesFilter::~CppClassesFilter() = default;
Core::LocatorFilterEntry CppClassesFilter::filterEntryFromIndexItem(IndexItem::Ptr info)
{
- const QVariant id = qVariantFromValue(info);
+ const QVariant id = QVariant::fromValue(info);
Core::LocatorFilterEntry filterEntry(this, info->symbolName(), id, info->icon());
filterEntry.extraInfo = info->symbolScope().isEmpty()
? info->shortNativeFilePath()
diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp
index e05c6c5eb3..efde14abc4 100644
--- a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp
+++ b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp
@@ -107,17 +107,18 @@ QString Utils::toString(::Utils::LanguageVersion languageVersion)
{
#define CASE_LANGUAGEVERSION(x) case ::Utils::LanguageVersion::x: return QLatin1String(#x)
switch (languageVersion) {
- CASE_LANGUAGEVERSION(C89);
- CASE_LANGUAGEVERSION(C99);
- CASE_LANGUAGEVERSION(C11);
- CASE_LANGUAGEVERSION(C18);
- CASE_LANGUAGEVERSION(CXX98);
- CASE_LANGUAGEVERSION(CXX03);
- CASE_LANGUAGEVERSION(CXX11);
- CASE_LANGUAGEVERSION(CXX14);
- CASE_LANGUAGEVERSION(CXX17);
- CASE_LANGUAGEVERSION(CXX2a);
- // no default to get a compiler warning if anything is added
+ CASE_LANGUAGEVERSION(None);
+ CASE_LANGUAGEVERSION(C89);
+ CASE_LANGUAGEVERSION(C99);
+ CASE_LANGUAGEVERSION(C11);
+ CASE_LANGUAGEVERSION(C18);
+ CASE_LANGUAGEVERSION(CXX98);
+ CASE_LANGUAGEVERSION(CXX03);
+ CASE_LANGUAGEVERSION(CXX11);
+ CASE_LANGUAGEVERSION(CXX14);
+ CASE_LANGUAGEVERSION(CXX17);
+ CASE_LANGUAGEVERSION(CXX2a);
+ // no default to get a compiler warning if anything is added
}
#undef CASE_LANGUAGEVERSION
return QString();
@@ -383,6 +384,17 @@ QString Utils::toString(CPlusPlus::Kind kind)
return QString();
}
+QString Utils::toString(ProjectPart::ToolChainWordWidth width)
+{
+ switch (width) {
+ case ProjectPart::ToolChainWordWidth::WordWidth32Bit:
+ return QString("32");
+ case ProjectPart::ToolChainWordWidth::WordWidth64Bit:
+ return QString("64");
+ }
+ return QString();
+}
+
QString Utils::partsForFile(const QString &fileName)
{
const QList<ProjectPart::Ptr> parts
@@ -502,16 +514,20 @@ void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos)
if (!part->projectConfigFile.isEmpty())
m_out << i3 << "Project Config File: " << part->projectConfigFile << "\n";
m_out << i2 << "Project Part \"" << part->id() << "\"{{{3\n";
- m_out << i3 << "Project Part Name : " << part->displayName << "\n";
- m_out << i3 << "Project Name : " << projectName << "\n";
- m_out << i3 << "Project File : " << projectFilePath << "\n";
- m_out << i3 << "Compiler Flags : " << part->compilerFlags.join(", ") << "\n";
- m_out << i3 << "Selected For Building: " << part->selectedForBuilding << "\n";
- m_out << i3 << "Build Target Type : " << Utils::toString(part->buildTargetType) << "\n";
- m_out << i3 << "Lanugage Version : " << Utils::toString(part->languageVersion)<<"\n";
- m_out << i3 << "Lanugage Extensions : " << Utils::toString(part->languageExtensions)
+ m_out << i3 << "Project Part Name : " << part->displayName << "\n";
+ m_out << i3 << "Project Name : " << projectName << "\n";
+ m_out << i3 << "Project File : " << projectFilePath << "\n";
+ m_out << i3 << "ToolChain Type : " << part->toolchainType.toString() << "\n";
+ m_out << i3 << "ToolChain Target Triple: " << part->toolChainTargetTriple << "\n";
+ m_out << i3 << "ToolChain Word Width : " << part->toolChainWordWidth << "\n";
+ m_out << i3 << "Compiler Flags : " << part->compilerFlags.join(", ") << "\n";
+ m_out << i3 << "Selected For Building : " << part->selectedForBuilding << "\n";
+ m_out << i3 << "Build System Target : " << part->buildSystemTarget << "\n";
+ m_out << i3 << "Build Target Type : " << Utils::toString(part->buildTargetType) << "\n";
+ m_out << i3 << "Language Version : " << Utils::toString(part->languageVersion)<<"\n";
+ m_out << i3 << "Language Extensions : " << Utils::toString(part->languageExtensions)
<< "\n";
- m_out << i3 << "Qt Version : " << Utils::toString(part->qtVersion) << "\n";
+ m_out << i3 << "Qt Version : " << Utils::toString(part->qtVersion) << "\n";
if (!part->files.isEmpty()) {
m_out << i3 << "Files:{{{4\n";
@@ -597,10 +613,10 @@ void Dumper::dumpWorkingCopy(const WorkingCopy &workingCopy)
m_out << "Working Copy contains " << workingCopy.size() << " entries{{{1\n";
const QByteArray i1 = indent(1);
- QHashIterator< ::Utils::FileName, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
+ QHashIterator< ::Utils::FilePath, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
while (it.hasNext()) {
it.next();
- const ::Utils::FileName &filePath = it.key();
+ const ::Utils::FilePath &filePath = it.key();
unsigned sourcRevision = it.value().second;
m_out << i1 << "rev=" << sourcRevision << ", " << filePath << "\n";
}
diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.h b/src/plugins/cpptools/cppcodemodelinspectordumper.h
index c3100d8b33..41d294e817 100644
--- a/src/plugins/cpptools/cppcodemodelinspectordumper.h
+++ b/src/plugins/cpptools/cppcodemodelinspectordumper.h
@@ -54,6 +54,7 @@ struct CPPTOOLS_EXPORT Utils
static QString toString(const QVector<CppTools::ProjectFile> &projectFiles);
static QString toString(CppTools::ProjectFile::Kind kind);
static QString toString(CPlusPlus::Kind kind);
+ static QString toString(ProjectPart::ToolChainWordWidth width);
static QString partsForFile(const QString &fileName);
static QString unresolvedFileNameWithDelimiters(const CPlusPlus::Document::Include &include);
static QString pathListToString(const QStringList &pathList);
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index 12b226f756..b51f833afe 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -92,7 +92,10 @@ public:
void keepCompletionOperator(unsigned compOp) { m_completionOperator = compOp; }
void keepTypeOfExpression(const QSharedPointer<TypeOfExpression> &typeOfExp)
{ m_typeOfExpression = typeOfExp; }
-
+ bool isKeyword() const final
+ { return m_isKeyword; }
+ void setIsKeyword(bool isKeyword)
+ { m_isKeyword = isKeyword; }
quint64 hash() const override;
@@ -101,6 +104,7 @@ private:
unsigned m_completionOperator = T_EOF_SYMBOL;
mutable QChar m_typedChar;
bool m_isOverloaded = false;
+ bool m_isKeyword = false;
};
} // Internal
@@ -1531,6 +1535,16 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
return !m_completions.isEmpty();
}
+void InternalCppCompletionAssistProcessor::addKeywordCompletionItem(const QString &text)
+{
+ auto item = new CppAssistProposalItem;
+ item->setText(text);
+ item->setIcon(Icons::keywordIcon());
+ item->setOrder(KeywordsOrder);
+ item->setIsKeyword(true);
+ m_completions.append(item);
+}
+
bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem> &baseResults)
{
const LookupContext &context = m_model->m_typeOfExpression->context();
@@ -1859,16 +1873,16 @@ void InternalCppCompletionAssistProcessor::addKeywords()
// keyword completion items.
for (int i = T_FIRST_KEYWORD; i < keywordLimit; ++i)
- addCompletionItem(QLatin1String(Token::name(i)), Icons::keywordIcon(), KeywordsOrder);
+ addKeywordCompletionItem(QLatin1String(Token::name(i)));
// primitive type completion items.
for (int i = T_FIRST_PRIMITIVE; i <= T_LAST_PRIMITIVE; ++i)
- addCompletionItem(QLatin1String(Token::name(i)), Icons::keywordIcon(), KeywordsOrder);
+ addKeywordCompletionItem(QLatin1String(Token::name(i)));
// "Identifiers with special meaning"
if (m_interface->languageFeatures().cxx11Enabled) {
- addCompletionItem(QLatin1String("override"), Icons::keywordIcon(), KeywordsOrder);
- addCompletionItem(QLatin1String("final"), Icons::keywordIcon(), KeywordsOrder);
+ addKeywordCompletionItem(QLatin1String("override"));
+ addKeywordCompletionItem(QLatin1String("final"));
}
}
diff --git a/src/plugins/cpptools/cppcompletionassist.h b/src/plugins/cpptools/cppcompletionassist.h
index e22ea38607..7213271263 100644
--- a/src/plugins/cpptools/cppcompletionassist.h
+++ b/src/plugins/cpptools/cppcompletionassist.h
@@ -138,6 +138,7 @@ private:
CPlusPlus::Scope *cursorScope);
bool globalCompletion(CPlusPlus::Scope *scope);
+ void addKeywordCompletionItem(const QString &text);
void addCompletionItem(const QString &text,
const QIcon &icon = QIcon(),
int order = 0,
diff --git a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp
index be1163d168..fdd4920504 100644
--- a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp
+++ b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp
@@ -83,7 +83,7 @@ QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
QRegularExpressionMatch match = regexp.match(matchString);
if (match.hasMatch()) {
const bool betterMatch = match.capturedStart() == 0;
- QVariant id = qVariantFromValue(info);
+ QVariant id = QVariant::fromValue(info);
QString name = matchString;
QString extraInfo = info->symbolScope();
if (info->type() == IndexItem::Function) {
diff --git a/src/plugins/cpptools/cppeditoroutline.cpp b/src/plugins/cpptools/cppeditoroutline.cpp
index d7840016d5..627385f107 100644
--- a/src/plugins/cpptools/cppeditoroutline.cpp
+++ b/src/plugins/cpptools/cppeditoroutline.cpp
@@ -124,9 +124,9 @@ CppEditorOutline::CppEditorOutline(TextEditor::TextEditorWidget *editorWidget)
&CppTools::CppToolsSettings::setSortedEditorDocumentOutline);
m_combo->addAction(m_sortAction);
- connect(m_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_combo, QOverload<int>::of(&QComboBox::activated),
this, &CppEditorOutline::gotoSymbolInEditor);
- connect(m_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &CppEditorOutline::updateToolTip);
// Set up timers
diff --git a/src/plugins/cpptools/cppelementevaluator.cpp b/src/plugins/cpptools/cppelementevaluator.cpp
index 949442c459..88ffc3c075 100644
--- a/src/plugins/cpptools/cppelementevaluator.cpp
+++ b/src/plugins/cpptools/cppelementevaluator.cpp
@@ -83,7 +83,7 @@ class CppInclude : public CppElement
public:
explicit CppInclude(const Document::Include &includeFile)
: path(QDir::toNativeSeparators(includeFile.resolvedFileName()))
- , fileName(Utils::FileName::fromString(includeFile.resolvedFileName()).fileName())
+ , fileName(Utils::FilePath::fromString(includeFile.resolvedFileName()).fileName())
{
helpCategory = Core::HelpItem::Brief;
helpIdCandidates = QStringList(fileName);
diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp
index 867b3d395a..e277edeb4f 100644
--- a/src/plugins/cpptools/cppfindreferences.cpp
+++ b/src/plugins/cpptools/cppfindreferences.cpp
@@ -56,7 +56,7 @@ using namespace CppTools::Internal;
using namespace CppTools;
using namespace ProjectExplorer;
-static QByteArray getSource(const Utils::FileName &fileName,
+static QByteArray getSource(const Utils::FilePath &fileName,
const WorkingCopy &workingCopy)
{
if (workingCopy.contains(fileName)) {
@@ -178,7 +178,7 @@ class ProcessFile
public:
// needed by QtConcurrent
- using argument_type = const Utils::FileName &;
+ using argument_type = const Utils::FilePath &;
using result_type = QList<CPlusPlus::Usage>;
ProcessFile(const WorkingCopy &workingCopy,
@@ -193,7 +193,7 @@ public:
future(future)
{ }
- QList<CPlusPlus::Usage> operator()(const Utils::FileName &fileName)
+ QList<CPlusPlus::Usage> operator()(const Utils::FilePath &fileName)
{
QList<CPlusPlus::Usage> usages;
if (future->isPaused())
@@ -210,7 +210,7 @@ public:
CPlusPlus::Document::Ptr doc;
const QByteArray unpreprocessedSource = getSource(fileName, workingCopy);
- if (symbolDocument && fileName == Utils::FileName::fromString(symbolDocument->fileName())) {
+ if (symbolDocument && fileName == Utils::FilePath::fromString(symbolDocument->fileName())) {
doc = symbolDocument;
} else {
doc = snapshot.preprocessedDocument(unpreprocessedSource, fileName);
@@ -282,9 +282,9 @@ static void find_helper(QFutureInterface<CPlusPlus::Usage> &future,
const CPlusPlus::Snapshot snapshot = context.snapshot();
- const Utils::FileName sourceFile = Utils::FileName::fromUtf8(symbol->fileName(),
+ const Utils::FilePath sourceFile = Utils::FilePath::fromUtf8(symbol->fileName(),
symbol->fileNameLength());
- Utils::FileNameList files{sourceFile};
+ Utils::FilePathList files{sourceFile};
if (symbol->isClass()
|| symbol->isForwardClassDeclaration()
@@ -351,7 +351,7 @@ void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
parameters.prettySymbolName = overview.prettyName(context.path(symbol).constLast());
}
- search->setUserData(qVariantFromValue(parameters));
+ search->setUserData(QVariant::fromValue(parameters));
findAll_helper(search, symbol, context);
}
@@ -527,7 +527,7 @@ CPlusPlus::Symbol *CppFindReferences::findSymbol(const CppFindReferencesParamete
CPlusPlus::Document::Ptr newSymbolDocument = snapshot.document(symbolFile);
// document is not parsed and has no bindings yet, do it
- QByteArray source = getSource(Utils::FileName::fromString(newSymbolDocument->fileName()),
+ QByteArray source = getSource(Utils::FilePath::fromString(newSymbolDocument->fileName()),
m_modelManager->workingCopy());
CPlusPlus::Document::Ptr doc =
snapshot.preprocessedDocument(source, newSymbolDocument->fileName());
@@ -571,7 +571,7 @@ static void displayResults(SearchResult *search, QFutureWatcher<CPlusPlus::Usage
parameters.filesToRename.append(node);
}
- search->setUserData(qVariantFromValue(parameters));
+ search->setUserData(QVariant::fromValue(parameters));
}
static void searchFinished(SearchResult *search, QFutureWatcher<CPlusPlus::Usage> *watcher)
@@ -607,7 +607,7 @@ class FindMacroUsesInFile
public:
// needed by QtConcurrent
- using argument_type = const Utils::FileName &;
+ using argument_type = const Utils::FilePath &;
using result_type = QList<CPlusPlus::Usage>;
FindMacroUsesInFile(const WorkingCopy &workingCopy,
@@ -617,7 +617,7 @@ public:
: workingCopy(workingCopy), snapshot(snapshot), macro(macro), future(future)
{ }
- QList<CPlusPlus::Usage> operator()(const Utils::FileName &fileName)
+ QList<CPlusPlus::Usage> operator()(const Utils::FilePath &fileName)
{
QList<CPlusPlus::Usage> usages;
CPlusPlus::Document::Ptr doc = snapshot.document(fileName);
@@ -688,8 +688,8 @@ static void findMacroUses_helper(QFutureInterface<CPlusPlus::Usage> &future,
const CPlusPlus::Snapshot snapshot,
const CPlusPlus::Macro macro)
{
- const Utils::FileName sourceFile = Utils::FileName::fromString(macro.fileName());
- Utils::FileNameList files{sourceFile};
+ const Utils::FilePath sourceFile = Utils::FilePath::fromString(macro.fileName());
+ Utils::FilePathList files{sourceFile};
files = Utils::filteredUnique(files + snapshot.filesDependingOn(sourceFile));
future.setProgressRange(0, files.size());
@@ -736,7 +736,7 @@ void CppFindReferences::findMacroUses(const CPlusPlus::Macro &macro, const QStri
// add the macro definition itself
{
- const QByteArray &source = getSource(Utils::FileName::fromString(macro.fileName()),
+ const QByteArray &source = getSource(Utils::FilePath::fromString(macro.fileName()),
workingCopy);
unsigned column;
const QString line = FindMacroUsesInFile::matchingLine(macro.bytesOffset(), source,
diff --git a/src/plugins/cpptools/cppfunctionsfilter.cpp b/src/plugins/cpptools/cppfunctionsfilter.cpp
index f2897215df..597e0f4d03 100644
--- a/src/plugins/cpptools/cppfunctionsfilter.cpp
+++ b/src/plugins/cpptools/cppfunctionsfilter.cpp
@@ -45,7 +45,7 @@ CppFunctionsFilter::~CppFunctionsFilter() = default;
Core::LocatorFilterEntry CppFunctionsFilter::filterEntryFromIndexItem(IndexItem::Ptr info)
{
- const QVariant id = qVariantFromValue(info);
+ const QVariant id = QVariant::fromValue(info);
QString name = info->symbolName();
QString extraInfo = info->symbolScope();
@@ -53,7 +53,7 @@ Core::LocatorFilterEntry CppFunctionsFilter::filterEntryFromIndexItem(IndexItem:
if (extraInfo.isEmpty()) {
extraInfo = info->shortNativeFilePath();
} else {
- extraInfo.append(" (" + Utils::FileName::fromString(info->fileName()).fileName() + ')');
+ extraInfo.append(" (" + Utils::FilePath::fromString(info->fileName()).fileName() + ')');
}
Core::LocatorFilterEntry filterEntry(this, name + info->symbolType(), id, info->icon());
diff --git a/src/plugins/cpptools/cppheadersource_test.cpp b/src/plugins/cpptools/cppheadersource_test.cpp
index ba830cc491..46994ed1f7 100644
--- a/src/plugins/cpptools/cppheadersource_test.cpp
+++ b/src/plugins/cpptools/cppheadersource_test.cpp
@@ -99,7 +99,7 @@ void CppToolsPlugin::initTestCase()
void CppToolsPlugin::cleanupTestCase()
{
- Utils::FileUtils::removeRecursively(Utils::FileName::fromString(baseTestDir()));
+ Utils::FileUtils::removeRecursively(Utils::FilePath::fromString(baseTestDir()));
m_fileSettings->headerSearchPaths.removeLast();
m_fileSettings->headerSearchPaths.removeLast();
m_fileSettings->sourceSearchPaths.removeLast();
diff --git a/src/plugins/cpptools/cppincludesfilter.cpp b/src/plugins/cpptools/cppincludesfilter.cpp
index 8675a9747a..8a852fb7a5 100644
--- a/src/plugins/cpptools/cppincludesfilter.cpp
+++ b/src/plugins/cpptools/cppincludesfilter.cpp
@@ -160,8 +160,8 @@ void CppIncludesFilter::prepareSearch(const QString &entry)
m_needsUpdate = false;
QSet<QString> seedPaths;
for (Project *project : SessionManager::projects()) {
- const Utils::FileNameList allFiles = project->files(Project::AllFiles);
- for (const Utils::FileName &filePath : allFiles )
+ const Utils::FilePathList allFiles = project->files(Project::AllFiles);
+ for (const Utils::FilePath &filePath : allFiles )
seedPaths.insert(filePath.toString());
}
const QList<DocumentModel::Entry *> entries = DocumentModel::entries();
diff --git a/src/plugins/cpptools/cppkitinfo.cpp b/src/plugins/cpptools/cppkitinfo.cpp
index 6cdf7d52df..e57a4dbd73 100644
--- a/src/plugins/cpptools/cppkitinfo.cpp
+++ b/src/plugins/cpptools/cppkitinfo.cpp
@@ -48,12 +48,12 @@ KitInfo::KitInfo(Project *project)
// Toolchains
if (kit) {
- cToolChain = ToolChainKitInformation::toolChain(kit, Constants::C_LANGUAGE_ID);
- cxxToolChain = ToolChainKitInformation::toolChain(kit, Constants::CXX_LANGUAGE_ID);
+ cToolChain = ToolChainKitAspect::toolChain(kit, Constants::C_LANGUAGE_ID);
+ cxxToolChain = ToolChainKitAspect::toolChain(kit, Constants::CXX_LANGUAGE_ID);
}
// Sysroot
- sysRootPath = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString();
+ sysRootPath = ProjectExplorer::SysRootKitAspect::sysRoot(kit).toString();
}
bool KitInfo::isValid() const
diff --git a/src/plugins/cpptools/cpplocatorfilter.cpp b/src/plugins/cpptools/cpplocatorfilter.cpp
index 6865cbe5a2..aa85f8d33f 100644
--- a/src/plugins/cpptools/cpplocatorfilter.cpp
+++ b/src/plugins/cpptools/cpplocatorfilter.cpp
@@ -50,7 +50,7 @@ CppLocatorFilter::~CppLocatorFilter() = default;
Core::LocatorFilterEntry CppLocatorFilter::filterEntryFromIndexItem(IndexItem::Ptr info)
{
- const QVariant id = qVariantFromValue(info);
+ const QVariant id = QVariant::fromValue(info);
Core::LocatorFilterEntry filterEntry(this, info->scopedSymbolName(), id, info->icon());
if (info->type() == IndexItem::Class || info->type() == IndexItem::Enum)
filterEntry.extraInfo = info->shortNativeFilePath();
diff --git a/src/plugins/cpptools/cpplocatorfilter_test.cpp b/src/plugins/cpptools/cpplocatorfilter_test.cpp
index 8c6f50390f..0dd3470826 100644
--- a/src/plugins/cpptools/cpplocatorfilter_test.cpp
+++ b/src/plugins/cpptools/cpplocatorfilter_test.cpp
@@ -166,8 +166,8 @@ void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter_data()
MyTestDataDir testDirectory("testdata_basic");
const QString testFile = testDirectory.file("file1.cpp");
const QString objTestFile = testDirectory.file("file1.mm");
- const QString testFileShort = FileUtils::shortNativePath(FileName::fromString(testFile));
- const QString objTestFileShort = FileUtils::shortNativePath(FileName::fromString(objTestFile));
+ const QString testFileShort = FilePath::fromString(testFile).shortNativePath();
+ const QString objTestFileShort = FilePath::fromString(objTestFile).shortNativePath();
QTest::newRow("CppFunctionsFilter")
<< testFile
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index 5a43feb322..c82355b31b 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -62,6 +62,7 @@
#include <projectexplorer/projectmacro.h>
#include <projectexplorer/session.h>
#include <utils/fileutils.h>
+#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
@@ -146,7 +147,7 @@ public:
mutable QMutex m_projectMutex;
QMap<ProjectExplorer::Project *, ProjectInfo> m_projectToProjectsInfo;
QHash<ProjectExplorer::Project *, bool> m_projectToIndexerCanceled;
- QMap<Utils::FileName, QList<ProjectPart::Ptr> > m_fileToProjectParts;
+ QMap<Utils::FilePath, QList<ProjectPart::Ptr> > m_fileToProjectParts;
QMap<QString, ProjectPart::Ptr> m_projectPartIdToProjectProjectPart;
// The members below are cached/(re)calculated from the projects and/or their project parts
bool m_dirty;
@@ -513,6 +514,10 @@ CppModelManager::CppModelManager()
d->m_indexingSupporter = nullptr;
d->m_enableGC = true;
+ // Visual C++ has 1MiB, macOSX has 512KiB
+ if (Utils::HostOsInfo::isWindowsHost() || Utils::HostOsInfo::isMacHost())
+ d->m_threadPool.setStackSize(2 * 1024 * 1024);
+
qRegisterMetaType<QSet<QString> >();
connect(this, &CppModelManager::sourceFilesRefreshed,
this, &CppModelManager::onSourceFilesRefreshed);
@@ -968,7 +973,7 @@ void CppModelManager::recalculateProjectPartMappings()
foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) {
d->m_projectPartIdToProjectProjectPart[projectPart->id()] = projectPart;
foreach (const ProjectFile &cxxFile, projectPart->files)
- d->m_fileToProjectParts[Utils::FileName::fromString(cxxFile.path)].append(
+ d->m_fileToProjectParts[Utils::FilePath::fromString(cxxFile.path)].append(
projectPart);
}
@@ -1132,20 +1137,20 @@ ProjectPart::Ptr CppModelManager::projectPartForId(const QString &projectPartId)
return d->m_projectPartIdToProjectProjectPart.value(projectPartId);
}
-QList<ProjectPart::Ptr> CppModelManager::projectPart(const Utils::FileName &fileName) const
+QList<ProjectPart::Ptr> CppModelManager::projectPart(const Utils::FilePath &fileName) const
{
QMutexLocker locker(&d->m_projectMutex);
return d->m_fileToProjectParts.value(fileName);
}
QList<ProjectPart::Ptr> CppModelManager::projectPartFromDependencies(
- const Utils::FileName &fileName) const
+ const Utils::FilePath &fileName) const
{
QSet<ProjectPart::Ptr> parts;
- const Utils::FileNameList deps = snapshot().filesDependingOn(fileName);
+ const Utils::FilePathList deps = snapshot().filesDependingOn(fileName);
QMutexLocker locker(&d->m_projectMutex);
- foreach (const Utils::FileName &dep, deps) {
+ foreach (const Utils::FilePath &dep, deps) {
parts.unite(QSet<ProjectPart::Ptr>::fromList(d->m_fileToProjectParts.value(dep)));
}
@@ -1338,7 +1343,7 @@ void CppModelManager::GC()
filesInEditorSupports << abstractEditorSupport->fileName();
Snapshot currentSnapshot = snapshot();
- QSet<Utils::FileName> reachableFiles;
+ QSet<Utils::FilePath> reachableFiles;
// The configuration file is part of the project files, which is just fine.
// If single files are open, without any project, then there is no need to
// keep the configuration file around.
@@ -1349,7 +1354,7 @@ void CppModelManager::GC()
const QString file = todo.last();
todo.removeLast();
- const Utils::FileName fileName = Utils::FileName::fromString(file);
+ const Utils::FilePath fileName = Utils::FilePath::fromString(file);
if (reachableFiles.contains(fileName))
continue;
reachableFiles.insert(fileName);
@@ -1362,7 +1367,7 @@ void CppModelManager::GC()
QStringList notReachableFiles;
Snapshot newSnapshot;
for (Snapshot::const_iterator it = currentSnapshot.begin(); it != currentSnapshot.end(); ++it) {
- const Utils::FileName &fileName = it.key();
+ const Utils::FilePath &fileName = it.key();
if (reachableFiles.contains(fileName))
newSnapshot.insert(it.value());
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 2c5fe960f2..9deaa2e392 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -121,12 +121,12 @@ public:
/// \return The project part with the given project file
ProjectPart::Ptr projectPartForId(const QString &projectPartId) const override;
/// \return All project parts that mention the given file name as one of the sources/headers.
- QList<ProjectPart::Ptr> projectPart(const Utils::FileName &fileName) const;
+ QList<ProjectPart::Ptr> projectPart(const Utils::FilePath &fileName) const;
QList<ProjectPart::Ptr> projectPart(const QString &fileName) const
- { return projectPart(Utils::FileName::fromString(fileName)); }
+ { return projectPart(Utils::FilePath::fromString(fileName)); }
/// This is a fall-back function: find all files that includes the file directly or indirectly,
/// and return its \c ProjectPart list for use with this file.
- QList<ProjectPart::Ptr> projectPartFromDependencies(const Utils::FileName &fileName) const;
+ QList<ProjectPart::Ptr> projectPartFromDependencies(const Utils::FilePath &fileName) const;
/// \return A synthetic \c ProjectPart which consists of all defines/includes/frameworks from
/// all loaded projects.
ProjectPart::Ptr fallbackProjectPart();
diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp
index aac046745b..ceab10028e 100644
--- a/src/plugins/cpptools/cppmodelmanager_test.cpp
+++ b/src/plugins/cpptools/cppmodelmanager_test.cpp
@@ -618,10 +618,10 @@ void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles()
QCOMPARE(workingCopy.size(), 2); // mm->configurationFileName() and "ui_*.h"
QStringList fileNamesInWorkinCopy;
- QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
+ QHashIterator<Utils::FilePath, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
while (it.hasNext()) {
it.next();
- fileNamesInWorkinCopy << Utils::FileName::fromString(it.key().toString()).fileName();
+ fileNamesInWorkinCopy << Utils::FilePath::fromString(it.key().toString()).fileName();
}
fileNamesInWorkinCopy.sort();
const QString expectedUiHeaderFileName = _("ui_mainwindow.h");
@@ -639,8 +639,8 @@ void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles()
QVERIFY(document);
const QStringList includedFiles = document->includedFiles();
QCOMPARE(includedFiles.size(), 2);
- QCOMPARE(Utils::FileName::fromString(includedFiles.at(0)).fileName(), _("mainwindow.h"));
- QCOMPARE(Utils::FileName::fromString(includedFiles.at(1)).fileName(), _("ui_mainwindow.h"));
+ QCOMPARE(Utils::FilePath::fromString(includedFiles.at(0)).fileName(), _("mainwindow.h"));
+ QCOMPARE(Utils::FilePath::fromString(includedFiles.at(1)).fileName(), _("ui_mainwindow.h"));
}
/// QTCREATORBUG-9828: Locator shows symbols of closed files
diff --git a/src/plugins/cpptools/cppprojectinfogenerator.cpp b/src/plugins/cpptools/cppprojectinfogenerator.cpp
index c177c7a7d9..18c7d4fb76 100644
--- a/src/plugins/cpptools/cppprojectinfogenerator.cpp
+++ b/src/plugins/cpptools/cppprojectinfogenerator.cpp
@@ -89,10 +89,13 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj
rawProjectPart.files,
rawProjectPart.fileClassifier);
- if (cat.hasParts()) {
- const ProjectPart::Ptr part = projectPartFromRawProjectPart(rawProjectPart,
- m_projectUpdateInfo.project);
+ if (!cat.hasParts())
+ return result;
+ const ProjectPart::Ptr part = projectPartFromRawProjectPart(rawProjectPart,
+ m_projectUpdateInfo.project);
+
+ if (m_projectUpdateInfo.cxxToolChain) {
if (cat.hasCxxSources()) {
result << createProjectPart(rawProjectPart,
part,
@@ -101,7 +104,6 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj
Language::Cxx,
LanguageExtension::None);
}
-
if (cat.hasObjcxxSources()) {
result << createProjectPart(rawProjectPart,
part,
@@ -110,7 +112,9 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj
Language::Cxx,
LanguageExtension::ObjectiveC);
}
+ }
+ if (m_projectUpdateInfo.cToolChain) {
if (cat.hasCSources()) {
result << createProjectPart(rawProjectPart,
part,
@@ -129,6 +133,7 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj
LanguageExtension::ObjectiveC);
}
}
+
return result;
}
@@ -182,7 +187,9 @@ ProjectPart::Ptr ProjectInfoGenerator::createProjectPart(
// Header paths
if (tcInfo.headerPathsRunner) {
const ProjectExplorer::HeaderPaths builtInHeaderPaths
- = tcInfo.headerPathsRunner(flags.commandLineFlags, tcInfo.sysRootPath);
+ = tcInfo.headerPathsRunner(flags.commandLineFlags,
+ tcInfo.sysRootPath,
+ tcInfo.targetTriple);
ProjectExplorer::HeaderPaths &headerPaths = part->headerPaths;
for (const ProjectExplorer::HeaderPath &header : builtInHeaderPaths) {
diff --git a/src/plugins/cpptools/cpptools_clangtidychecks.h b/src/plugins/cpptools/cpptools_clangtidychecks.h
index 20dcbdf120..813e9b9ed5 100644
--- a/src/plugins/cpptools/cpptools_clangtidychecks.h
+++ b/src/plugins/cpptools/cpptools_clangtidychecks.h
@@ -50,7 +50,33 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
{
"android-",
{
+ {
+ "uration-",
+ {
+ "comparison",
+ "division",
+ {
+ "factory-",
+ {
+ "float",
+ "scale"
+ }
+ },
+ "subtraction"
+ }
+ },
+ "aster-strsplit-delimiter",
+ {
+ "o-",
+ {
+ "internal-dependencies",
+ "namespace"
+ }
+ },
+ "edundant-strcat-calls",
+ "tr-cat-append",
"tring-find-startswith",
+ "pgrade-duration-conversions",
{
"cloexec-",
{
@@ -149,6 +175,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"swapped-arguments",
"terminating-continue",
"throw-keyword-missing",
+ "too-small-loop-variable",
"undefined-memory-manipulation",
"undelegated-constructor",
{
@@ -166,6 +193,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"cert-",
{
"dcl03-c",
+ "dcl16-c",
"dcl21-cpp",
"dcl50-cpp",
"dcl54-cpp",
@@ -193,6 +221,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
{
"apiModeling.",
{
+ "StdCLibraryFunctions",
"TrustNonnull",
"google.GTest"
}
@@ -232,13 +261,13 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"cplusplus.",
{
"InnerPointer",
+ "Move",
"NewDelete",
"NewDeleteLeaks",
"SelfAssignment"
}
},
"deadcode.DeadStores",
- "llvm.Conventions",
{
"nullability.",
{
@@ -286,6 +315,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
{
"API",
"NumberObjectConversion",
+ "OSObjectRetainCount",
"ObjCProperty",
"SecKeychainAPI",
{
@@ -357,7 +387,6 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"Malloc",
"MallocSizeof",
"MismatchedDeallocator",
- "StdCLibraryFunctions",
"Vfork",
{
"cstring.",
@@ -381,11 +410,20 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
{
"cppcoreguidelines-",
{
- "avoid-goto",
+ {
+ "avoid-",
+ {
+ "c-arrays",
+ "goto",
+ "magic-numbers"
+ }
+ },
"c-copy-assignment-signature",
"interfaces-global-init",
+ "macro-usage",
"narrowing-conversions",
"no-malloc",
+ "non-private-member-variables-in-classes",
"owning-memory",
{
"pro-",
@@ -447,6 +485,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"objc-",
{
"avoid-throwing-exception",
+ "function-naming",
"global-variable-declaration"
}
},
@@ -473,7 +512,13 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
{
"hicpp-",
{
- "avoid-goto",
+ {
+ "avoid-",
+ {
+ "c-arrays",
+ "goto"
+ }
+ },
"braces-around-statements",
"deprecated-headers",
"exception-baseclass",
@@ -498,6 +543,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"special-member-functions",
"static-assert",
"undelegated-constructor",
+ "uppercase-literal-suffix",
{
"use-",
{
@@ -533,7 +579,13 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"definitions-in-headers",
"misplaced-const",
"new-delete-overloads",
- "non-copyable-objects",
+ {
+ "non-",
+ {
+ "copyable-objects",
+ "private-member-variables-in-classes"
+ }
+ },
"redundant-expression",
"static-assert",
"throw-by-value-catch-by-reference",
@@ -552,8 +604,21 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
{
"modernize-",
{
- "avoid-bind",
- "deprecated-headers",
+ {
+ "avoid-",
+ {
+ "bind",
+ "c-arrays"
+ }
+ },
+ "concat-nested-namespaces",
+ {
+ "deprecated-",
+ {
+ "headers",
+ "ios-base-aliases"
+ }
+ },
"loop-convert",
{
"make-",
@@ -589,6 +654,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"delete"
}
},
+ "nodiscard",
"noexcept",
"nullptr",
"override",
@@ -658,6 +724,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
{
"avoid-const-params-in-decls",
"braces-around-statements",
+ "const-return-type",
"container-size-empty",
"delete-null-pointer",
"deleted-default",
@@ -666,6 +733,8 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"identifier-naming",
"implicit-bool-conversion",
"inconsistent-declaration-parameter-name",
+ "isolate-declaration",
+ "magic-numbers",
"misleading-indentation",
"misplaced-array-index",
"named-parameter",
@@ -677,6 +746,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
"declaration",
"function-ptr-dereference",
"member-init",
+ "preprocessor",
"smartptr-get",
{
"string-",
@@ -703,6 +773,7 @@ static const TidyNode CLANG_TIDY_CHECKS_ROOT
},
"string-compare",
"uniqueptr-delete-release",
+ "uppercase-literal-suffix",
"rary-objects"
}
}
diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h
index 2e1aebfd43..8490f2ccf5 100644
--- a/src/plugins/cpptools/cpptoolsconstants.h
+++ b/src/plugins/cpptools/cpptoolsconstants.h
@@ -100,7 +100,7 @@ const char SYMBOLS_FIND_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("CppTools", "C
// CLANG_VERSION here because it might denote a version that was not yet
// released (e.g. 6.0.1, but only 6.0.0 was released).
constexpr const char TIDY_DOCUMENTATION_URL_TEMPLATE[]
- = "https://releases.llvm.org/7.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/%1.html";
+ = "https://releases.llvm.org/8.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/%1.html";
constexpr const char CLAZY_DOCUMENTATION_URL_TEMPLATE[]
= "https://github.com/KDE/clazy/blob/master/docs/checks/README-%1.md";
diff --git a/src/plugins/cpptools/cpptoolsjsextension.cpp b/src/plugins/cpptools/cpptoolsjsextension.cpp
index d5efc1db6d..4c283fc644 100644
--- a/src/plugins/cpptools/cpptoolsjsextension.cpp
+++ b/src/plugins/cpptools/cpptoolsjsextension.cpp
@@ -38,33 +38,16 @@
namespace CppTools {
namespace Internal {
-QString CppToolsJsExtension::headerGuard(const QString &in) const
+static QString fileName(const QString &path, const QString &extension)
{
- return Utils::headerGuard(in);
+ return Utils::FilePath::fromStringWithExtension(path, extension).toString();
}
-QString CppToolsJsExtension::fileName(const QString &path, const QString &extension) const
+QString CppToolsJsExtension::headerGuard(const QString &in) const
{
- QString raw = Utils::FileName::fromString(path, extension).toString();
- CppFileSettings settings;
- settings.fromSettings(Core::ICore::settings());
- if (!settings.lowerCaseFiles)
- return raw;
-
- QFileInfo fi = QFileInfo(raw);
- QString finalPath = fi.path();
- if (finalPath == QStringLiteral("."))
- finalPath.clear();
- if (!finalPath.isEmpty() && !finalPath.endsWith(QLatin1Char('/')))
- finalPath += QLatin1Char('/');
- QString name = fi.baseName().toLower();
- QString ext = fi.completeSuffix();
- if (!ext.isEmpty())
- ext = QString(QLatin1Char('.')) + ext;
- return finalPath + name + ext;
+ return Utils::headerGuard(in);
}
-
static QStringList parts(const QString &klass)
{
return klass.split(QStringLiteral("::"));
@@ -77,6 +60,11 @@ QStringList CppToolsJsExtension::namespaces(const QString &klass) const
return result;
}
+bool CppToolsJsExtension::hasNamespaces(const QString &klass) const
+{
+ return !namespaces(klass).empty();
+}
+
QString CppToolsJsExtension::className(const QString &klass) const
{
QStringList result = parts(klass);
@@ -85,7 +73,23 @@ QString CppToolsJsExtension::className(const QString &klass) const
QString CppToolsJsExtension::classToFileName(const QString &klass, const QString &extension) const
{
- return fileName(className(klass), extension);
+ const QString raw = fileName(className(klass), extension);
+ CppFileSettings settings;
+ settings.fromSettings(Core::ICore::settings());
+ if (!settings.lowerCaseFiles)
+ return raw;
+
+ QFileInfo fi = QFileInfo(raw);
+ QString finalPath = fi.path();
+ if (finalPath == QStringLiteral("."))
+ finalPath.clear();
+ if (!finalPath.isEmpty() && !finalPath.endsWith(QLatin1Char('/')))
+ finalPath += QLatin1Char('/');
+ QString name = fi.baseName().toLower();
+ QString ext = fi.completeSuffix();
+ if (!ext.isEmpty())
+ ext = QString(QLatin1Char('.')) + ext;
+ return finalPath + name + ext;
}
QString CppToolsJsExtension::classToHeaderGuard(const QString &klass, const QString &extension) const
diff --git a/src/plugins/cpptools/cpptoolsjsextension.h b/src/plugins/cpptools/cpptoolsjsextension.h
index 16a4010f78..b528191033 100644
--- a/src/plugins/cpptools/cpptoolsjsextension.h
+++ b/src/plugins/cpptools/cpptoolsjsextension.h
@@ -45,12 +45,11 @@ public:
// Generate header guard:
Q_INVOKABLE QString headerGuard(const QString &in) const;
- // Fix the filename casing as configured in C++/File Naming:
- Q_INVOKABLE QString fileName(const QString &path, const QString &extension) const;
-
// Work with classes:
Q_INVOKABLE QStringList namespaces(const QString &klass) const;
+ Q_INVOKABLE bool hasNamespaces(const QString &klass) const;
Q_INVOKABLE QString className(const QString &klass) const;
+ // Fix the filename casing as configured in C++/File Naming:
Q_INVOKABLE QString classToFileName(const QString &klass,
const QString &extension) const;
Q_INVOKABLE QString classToHeaderGuard(const QString &klass, const QString &extension) const;
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index d2ca6d5d0b..be52ced3f1 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -130,9 +130,9 @@ void CppToolsPlugin::clearHeaderSourceCache()
m_headerSourceMapping.clear();
}
-Utils::FileName CppToolsPlugin::licenseTemplatePath()
+Utils::FilePath CppToolsPlugin::licenseTemplatePath()
{
- return Utils::FileName::fromString(m_instance->m_fileSettings->licenseTemplatePath);
+ return Utils::FilePath::fromString(m_instance->m_fileSettings->licenseTemplatePath);
}
QString CppToolsPlugin::licenseTemplate()
@@ -172,7 +172,7 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
d = new CppToolsPluginPrivate;
- JsExpander::registerQObjectForJs(QLatin1String("Cpp"), new CppToolsJsExtension);
+ JsExpander::registerGlobalObject<CppToolsJsExtension>("Cpp");
// Menus
ActionContainer *mtools = ActionManager::actionContainer(Core::Constants::M_TOOLS);
@@ -256,7 +256,7 @@ static QStringList findFilesInProject(const QString &name,
QString pattern = QString(1, QLatin1Char('/'));
pattern += name;
const QStringList projectFiles
- = Utils::transform(project->files(ProjectExplorer::Project::AllFiles), &Utils::FileName::toString);
+ = Utils::transform(project->files(ProjectExplorer::Project::AllFiles), &Utils::FilePath::toString);
const QStringList::const_iterator pcend = projectFiles.constEnd();
QStringList candidateList;
for (QStringList::const_iterator it = projectFiles.constBegin(); it != pcend; ++it) {
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index 84e43da383..d319c9eb1e 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -36,7 +36,7 @@ class QFileInfo;
class QDir;
QT_END_NAMESPACE
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace CppTools {
@@ -63,7 +63,7 @@ public:
static const QStringList &headerPrefixes();
static const QStringList &sourcePrefixes();
static void clearHeaderSourceCache();
- static Utils::FileName licenseTemplatePath();
+ static Utils::FilePath licenseTemplatePath();
static QString licenseTemplate();
static bool usePragmaOnce();
diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp
index 9bcf806b7d..0d186f8421 100644
--- a/src/plugins/cpptools/cpptoolsreuse.cpp
+++ b/src/plugins/cpptools/cpptoolsreuse.cpp
@@ -323,20 +323,10 @@ bool fileSizeExceedsLimit(const QFileInfo &fileInfo, int sizeLimitInMb)
"C++ Indexer: Skipping file \"%1\" because it is too big.")
.arg(absoluteFilePath);
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
QMetaObject::invokeMethod(Core::MessageManager::instance(), [msg]() {
Core::MessageManager::write(msg, Core::MessageManager::Silent);
});
-#else
- QMetaObject::invokeMethod(Core::MessageManager::instance(),
- "write",
- Qt::QueuedConnection,
- Q_ARG(QString, msg),
- Q_ARG(Core::MessageManager::PrintToOutputPaneFlags,
- Core::MessageManager::Silent));
-#endif
-
- qWarning().noquote() << msg;
+
return true;
}
diff --git a/src/plugins/cpptools/cpptoolstestcase.cpp b/src/plugins/cpptools/cpptoolstestcase.cpp
index 2b6d794955..5ed334b2e8 100644
--- a/src/plugins/cpptools/cpptoolstestcase.cpp
+++ b/src/plugins/cpptools/cpptoolstestcase.cpp
@@ -340,8 +340,8 @@ static bool copyRecursively(const QString &sourceDirPath,
return file.setPermissions(file.permissions() | QFile::WriteUser);
};
- return Utils::FileUtils::copyRecursively(Utils::FileName::fromString(sourceDirPath),
- Utils::FileName::fromString(targetDirPath),
+ return Utils::FileUtils::copyRecursively(Utils::FilePath::fromString(sourceDirPath),
+ Utils::FilePath::fromString(targetDirPath),
error,
copyHelper);
}
diff --git a/src/plugins/cpptools/cppworkingcopy.h b/src/plugins/cpptools/cppworkingcopy.h
index 6c9e74caa8..1477720553 100644
--- a/src/plugins/cpptools/cppworkingcopy.h
+++ b/src/plugins/cpptools/cppworkingcopy.h
@@ -41,43 +41,43 @@ public:
WorkingCopy();
void insert(const QString &fileName, const QByteArray &source, unsigned revision = 0)
- { insert(Utils::FileName::fromString(fileName), source, revision); }
+ { insert(Utils::FilePath::fromString(fileName), source, revision); }
- void insert(const Utils::FileName &fileName, const QByteArray &source, unsigned revision = 0)
+ void insert(const Utils::FilePath &fileName, const QByteArray &source, unsigned revision = 0)
{ _elements.insert(fileName, qMakePair(source, revision)); }
bool contains(const QString &fileName) const
- { return contains(Utils::FileName::fromString(fileName)); }
+ { return contains(Utils::FilePath::fromString(fileName)); }
- bool contains(const Utils::FileName &fileName) const
+ bool contains(const Utils::FilePath &fileName) const
{ return _elements.contains(fileName); }
QByteArray source(const QString &fileName) const
- { return source(Utils::FileName::fromString(fileName)); }
+ { return source(Utils::FilePath::fromString(fileName)); }
- QByteArray source(const Utils::FileName &fileName) const
+ QByteArray source(const Utils::FilePath &fileName) const
{ return _elements.value(fileName).first; }
unsigned revision(const QString &fileName) const
- { return revision(Utils::FileName::fromString(fileName)); }
+ { return revision(Utils::FilePath::fromString(fileName)); }
- unsigned revision(const Utils::FileName &fileName) const
+ unsigned revision(const Utils::FilePath &fileName) const
{ return _elements.value(fileName).second; }
QPair<QByteArray, unsigned> get(const QString &fileName) const
- { return get(Utils::FileName::fromString(fileName)); }
+ { return get(Utils::FilePath::fromString(fileName)); }
- QPair<QByteArray, unsigned> get(const Utils::FileName &fileName) const
+ QPair<QByteArray, unsigned> get(const Utils::FilePath &fileName) const
{ return _elements.value(fileName); }
- QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> > iterator() const
- { return QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> >(_elements); }
+ QHashIterator<Utils::FilePath, QPair<QByteArray, unsigned> > iterator() const
+ { return QHashIterator<Utils::FilePath, QPair<QByteArray, unsigned> >(_elements); }
int size() const
{ return _elements.size(); }
private:
- using Table = QHash<Utils::FileName, QPair<QByteArray, unsigned> >;
+ using Table = QHash<Utils::FilePath, QPair<QByteArray, unsigned> >;
Table _elements;
};
diff --git a/src/plugins/cpptools/cursorineditor.h b/src/plugins/cpptools/cursorineditor.h
index 18097e5dbd..b84633d9bc 100644
--- a/src/plugins/cpptools/cursorineditor.h
+++ b/src/plugins/cpptools/cursorineditor.h
@@ -36,7 +36,7 @@ namespace CppTools {
class CursorInEditor
{
public:
- CursorInEditor(const QTextCursor &cursor, const Utils::FileName &filePath,
+ CursorInEditor(const QTextCursor &cursor, const Utils::FilePath &filePath,
CppEditorWidgetInterface *editorWidget = nullptr)
: m_cursor(cursor)
, m_filePath(filePath)
@@ -44,10 +44,10 @@ public:
{}
CppEditorWidgetInterface *editorWidget() const { return m_editorWidget; }
const QTextCursor &cursor() const { return m_cursor; }
- const Utils::FileName &filePath() const { return m_filePath; }
+ const Utils::FilePath &filePath() const { return m_filePath; }
private:
QTextCursor m_cursor;
- Utils::FileName m_filePath;
+ Utils::FilePath m_filePath;
CppEditorWidgetInterface *m_editorWidget = nullptr;
};
diff --git a/src/plugins/cpptools/doxygengenerator.cpp b/src/plugins/cpptools/doxygengenerator.cpp
index 764930cbc9..c11cb4d7cb 100644
--- a/src/plugins/cpptools/doxygengenerator.cpp
+++ b/src/plugins/cpptools/doxygengenerator.cpp
@@ -76,7 +76,7 @@ static int lineBeforeCursor(const QTextCursor &cursor)
QString DoxygenGenerator::generate(QTextCursor cursor,
const CPlusPlus::Snapshot &snapshot,
- const Utils::FileName &documentFilePath)
+ const Utils::FilePath &documentFilePath)
{
const QTextCursor initialCursor = cursor;
diff --git a/src/plugins/cpptools/doxygengenerator.h b/src/plugins/cpptools/doxygengenerator.h
index 780525b65e..7448b12345 100644
--- a/src/plugins/cpptools/doxygengenerator.h
+++ b/src/plugins/cpptools/doxygengenerator.h
@@ -33,7 +33,7 @@ QT_FORWARD_DECLARE_CLASS(QTextCursor)
namespace CPlusPlus { class DeclarationAST; }
namespace CPlusPlus { class Snapshot; }
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace CppTools {
@@ -56,7 +56,7 @@ public:
QString generate(QTextCursor cursor,
const CPlusPlus::Snapshot &snapshot,
- const Utils::FileName &documentFilePath);
+ const Utils::FilePath &documentFilePath);
QString generate(QTextCursor cursor, CPlusPlus::DeclarationAST *decl);
private:
diff --git a/src/plugins/cpptools/generatedcodemodelsupport.cpp b/src/plugins/cpptools/generatedcodemodelsupport.cpp
index a779e38718..85825ae9ef 100644
--- a/src/plugins/cpptools/generatedcodemodelsupport.cpp
+++ b/src/plugins/cpptools/generatedcodemodelsupport.cpp
@@ -69,7 +69,7 @@ private:
GeneratedCodeModelSupport::GeneratedCodeModelSupport(CppModelManager *modelmanager,
ProjectExplorer::ExtraCompiler *generator,
- const Utils::FileName &generatedFile) :
+ const Utils::FilePath &generatedFile) :
CppTools::AbstractEditorSupport(modelmanager, generator), m_generatedFileName(generatedFile),
m_generator(generator)
{
@@ -90,7 +90,7 @@ GeneratedCodeModelSupport::~GeneratedCodeModelSupport()
qCDebug(log) << "dtor ~generatedcodemodelsupport for" << m_generatedFileName;
}
-void GeneratedCodeModelSupport::onContentsChanged(const Utils::FileName &file)
+void GeneratedCodeModelSupport::onContentsChanged(const Utils::FilePath &file)
{
if (file == m_generatedFileName) {
notifyAboutUpdatedContents();
@@ -124,7 +124,7 @@ void GeneratedCodeModelSupport::update(const QList<ProjectExplorer::ExtraCompile
continue;
extraCompilerCache.insert(generator);
- generator->forEachTarget([mm, generator](const Utils::FileName &generatedFile) {
+ generator->forEachTarget([mm, generator](const Utils::FilePath &generatedFile) {
new GeneratedCodeModelSupport(mm, generator, generatedFile);
});
}
diff --git a/src/plugins/cpptools/generatedcodemodelsupport.h b/src/plugins/cpptools/generatedcodemodelsupport.h
index 818d84e47c..0b471a1268 100644
--- a/src/plugins/cpptools/generatedcodemodelsupport.h
+++ b/src/plugins/cpptools/generatedcodemodelsupport.h
@@ -48,7 +48,7 @@ class CPPTOOLS_EXPORT GeneratedCodeModelSupport : public AbstractEditorSupport
public:
GeneratedCodeModelSupport(CppModelManager *modelmanager,
ProjectExplorer::ExtraCompiler *generator,
- const Utils::FileName &generatedFile);
+ const Utils::FilePath &generatedFile);
~GeneratedCodeModelSupport() override;
/// \returns the contents encoded in UTF-8.
@@ -59,8 +59,8 @@ public:
static void update(const QList<ProjectExplorer::ExtraCompiler *> &generators);
private:
- void onContentsChanged(const Utils::FileName &file);
- Utils::FileName m_generatedFileName;
+ void onContentsChanged(const Utils::FilePath &file);
+ Utils::FilePath m_generatedFileName;
ProjectExplorer::ExtraCompiler *m_generator;
};
diff --git a/src/plugins/cpptools/headerpathfilter.cpp b/src/plugins/cpptools/headerpathfilter.cpp
index b514c468d7..e2d1e6a4ca 100644
--- a/src/plugins/cpptools/headerpathfilter.cpp
+++ b/src/plugins/cpptools/headerpathfilter.cpp
@@ -29,6 +29,8 @@
#include <coreplugin/icore.h>
#endif
+#include <projectexplorer/project.h>
+
#include <QRegularExpression>
namespace CppTools {
@@ -41,6 +43,8 @@ void HeaderPathFilter::process()
{
const HeaderPaths &headerPaths = projectPart.headerPaths;
+ addPreIncludesPath();
+
for (const HeaderPath &headerPath : headerPaths)
filterHeaderPath(headerPath);
@@ -141,6 +145,17 @@ void HeaderPathFilter::tweakHeaderPaths()
}
}
+void HeaderPathFilter::addPreIncludesPath()
+{
+ if (projectDirectory.size()) {
+ const Utils::FilePath rootProjectDirectory = Utils::FilePath::fromString(projectDirectory)
+ .pathAppended(".pre_includes");
+
+ systemHeaderPaths.push_back(
+ {rootProjectDirectory.toString(), ProjectExplorer::HeaderPathType::System});
+ }
+}
+
QString HeaderPathFilter::ensurePathWithSlashEnding(const QString &path)
{
QString pathWithSlashEnding = path;
diff --git a/src/plugins/cpptools/headerpathfilter.h b/src/plugins/cpptools/headerpathfilter.h
index 8b4e771994..20fbc020e8 100644
--- a/src/plugins/cpptools/headerpathfilter.h
+++ b/src/plugins/cpptools/headerpathfilter.h
@@ -53,6 +53,8 @@ private:
void tweakHeaderPaths();
+ void addPreIncludesPath();
+
bool isProjectHeaderPath(const QString &path) const;
static QString ensurePathWithSlashEnding(const QString &path);
diff --git a/src/plugins/cpptools/indexitem.cpp b/src/plugins/cpptools/indexitem.cpp
index 1a07d9eada..161a7555cd 100644
--- a/src/plugins/cpptools/indexitem.cpp
+++ b/src/plugins/cpptools/indexitem.cpp
@@ -88,7 +88,7 @@ QString IndexItem::representDeclaration() const
QString IndexItem::shortNativeFilePath() const
{
- return Utils::FileUtils::shortNativePath(Utils::FileName::fromString(m_fileName));
+ return Utils::FilePath::fromString(m_fileName).shortNativePath();
}
void IndexItem::squeeze()
diff --git a/src/plugins/cpptools/modelmanagertesthelper.cpp b/src/plugins/cpptools/modelmanagertesthelper.cpp
index 83e27fb237..f1029be36b 100644
--- a/src/plugins/cpptools/modelmanagertesthelper.cpp
+++ b/src/plugins/cpptools/modelmanagertesthelper.cpp
@@ -37,7 +37,7 @@ using namespace CppTools::Internal;
using namespace CppTools::Tests;
TestProject::TestProject(const QString &name, QObject *parent) :
- ProjectExplorer::Project("x-binary/foo", Utils::FileName()),
+ ProjectExplorer::Project("x-binary/foo", Utils::FilePath()),
m_name(name)
{
setParent(parent);
diff --git a/src/plugins/cpptools/symbolsfindfilter.cpp b/src/plugins/cpptools/symbolsfindfilter.cpp
index f6bc1f52ba..93f4643587 100644
--- a/src/plugins/cpptools/symbolsfindfilter.cpp
+++ b/src/plugins/cpptools/symbolsfindfilter.cpp
@@ -119,7 +119,7 @@ void SymbolsFindFilter::findAll(const QString &txt, FindFlags findFlags)
parameters.flags = findFlags;
parameters.types = m_symbolsToSearch;
parameters.scope = m_scope;
- search->setUserData(qVariantFromValue(parameters));
+ search->setUserData(QVariant::fromValue(parameters));
startSearch(search);
}
@@ -129,7 +129,7 @@ void SymbolsFindFilter::startSearch(SearchResult *search)
QSet<QString> projectFileNames;
if (parameters.scope == SymbolSearcher::SearchProjectsOnly) {
for (ProjectExplorer::Project *project : ProjectExplorer::SessionManager::projects())
- projectFileNames += Utils::transform(project->files(ProjectExplorer::Project::AllFiles), &Utils::FileName::toString).toSet();
+ projectFileNames += Utils::transform(project->files(ProjectExplorer::Project::AllFiles), &Utils::FilePath::toString).toSet();
}
auto watcher = new QFutureWatcher<SearchResultItem>;
diff --git a/src/plugins/cpptools/typehierarchybuilder.cpp b/src/plugins/cpptools/typehierarchybuilder.cpp
index e54b546068..aee41076d7 100644
--- a/src/plugins/cpptools/typehierarchybuilder.cpp
+++ b/src/plugins/cpptools/typehierarchybuilder.cpp
@@ -193,9 +193,9 @@ QStringList TypeHierarchyBuilder::filesDependingOn(CPlusPlus::Symbol *symbol) co
if (!symbol)
return deps;
- Utils::FileName file = Utils::FileName::fromUtf8(symbol->fileName(), symbol->fileNameLength());
+ Utils::FilePath file = Utils::FilePath::fromUtf8(symbol->fileName(), symbol->fileNameLength());
deps << file.toString();
- foreach (const Utils::FileName &fileName, _snapshot.filesDependingOn(file))
+ foreach (const Utils::FilePath &fileName, _snapshot.filesDependingOn(file))
deps.append(fileName.toString());
return deps;
}
diff --git a/src/plugins/cvs/CMakeLists.txt b/src/plugins/cvs/CMakeLists.txt
new file mode 100644
index 0000000000..e1f5413715
--- /dev/null
+++ b/src/plugins/cvs/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_qtc_plugin(CVS
+ PLUGIN_DEPENDS Core TextEditor VcsBase
+ SOURCES
+ annotationhighlighter.cpp annotationhighlighter.h
+ cvsclient.cpp cvsclient.h
+ cvscontrol.cpp cvscontrol.h
+ cvseditor.cpp cvseditor.h
+ cvsplugin.cpp cvsplugin.h
+ cvssettings.cpp cvssettings.h
+ cvssubmiteditor.cpp cvssubmiteditor.h
+ cvsutils.cpp cvsutils.h
+ settingspage.cpp settingspage.h settingspage.ui
+)
diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp
index 602d6764a2..454e95df63 100644
--- a/src/plugins/cvs/cvscontrol.cpp
+++ b/src/plugins/cvs/cvscontrol.cpp
@@ -55,7 +55,7 @@ Core::Id CvsControl::id() const
return Core::Id(VcsBase::Constants::VCS_ID_CVS);
}
-bool CvsControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
+bool CvsControl::isVcsFileOrDirectory(const Utils::FilePath &fileName) const
{
return fileName.toFileInfo().isDir()
&& !fileName.fileName().compare("CVS", Utils::HostOsInfo::fileNameCaseSensitivity());
@@ -63,7 +63,7 @@ bool CvsControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
bool CvsControl::isConfigured() const
{
- const Utils::FileName binary = m_plugin->client()->vcsBinary();
+ const Utils::FilePath binary = m_plugin->client()->vcsBinary();
if (binary.isEmpty())
return false;
QFileInfo fi = binary.toFileInfo();
@@ -137,7 +137,7 @@ QString CvsControl::vcsOpenText() const
}
Core::ShellCommand *CvsControl::createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs)
{
diff --git a/src/plugins/cvs/cvscontrol.h b/src/plugins/cvs/cvscontrol.h
index 37370452c9..b988fb6adc 100644
--- a/src/plugins/cvs/cvscontrol.h
+++ b/src/plugins/cvs/cvscontrol.h
@@ -42,7 +42,7 @@ public:
QString displayName() const final;
Core::Id id() const final;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final;
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final;
bool managesDirectory(const QString &directory, QString *topLevel = nullptr) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
@@ -60,7 +60,7 @@ public:
QString vcsOpenText() const final;
Core::ShellCommand *createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs) final;
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 7335ba53ff..1d771ca31f 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -1100,7 +1100,7 @@ CvsResponse CvsPlugin::runCvs(const QString &workingDirectory,
unsigned flags,
QTextCodec *outputCodec) const
{
- const FileName executable = client()->vcsBinary();
+ const FilePath executable = client()->vcsBinary();
CvsResponse response;
if (executable.isEmpty()) {
response.result = CvsResponse::OtherError;
diff --git a/src/plugins/debugger/CMakeLists.txt b/src/plugins/debugger/CMakeLists.txt
new file mode 100644
index 0000000000..f88c5ffd60
--- /dev/null
+++ b/src/plugins/debugger/CMakeLists.txt
@@ -0,0 +1,109 @@
+add_qtc_plugin(Debugger
+ DEPENDS LanguageUtils QmlDebug qmljs QtcSsh registryaccess
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer QtSupport TextEditor
+ PLUGIN_RECOMMENDS QmakeProjectManager
+ SOURCES
+ analyzer/analyzerbase.qrc
+ analyzer/analyzerconstants.h
+ analyzer/analyzericons.h
+ analyzer/analyzermanager.h
+ analyzer/analyzerrunconfigwidget.cpp analyzer/analyzerrunconfigwidget.h
+ analyzer/analyzerutils.cpp analyzer/analyzerutils.h
+ analyzer/detailederrorview.cpp analyzer/detailederrorview.h
+ analyzer/diagnosticlocation.cpp analyzer/diagnosticlocation.h
+ analyzer/startremotedialog.cpp analyzer/startremotedialog.h
+ breakhandler.cpp breakhandler.h
+ breakpoint.cpp breakpoint.h
+ cdb/cdbengine.cpp cdb/cdbengine.h
+ cdb/cdboptionspage.cpp cdb/cdboptionspage.h
+ cdb/cdboptionspagewidget.ui
+ cdb/cdbparsehelpers.cpp cdb/cdbparsehelpers.h
+ cdb/stringinputstream.cpp cdb/stringinputstream.h
+ commonoptionspage.cpp commonoptionspage.h
+ console/console.cpp console/console.h
+ console/consoleedit.cpp console/consoleedit.h
+ console/consoleitem.cpp console/consoleitem.h
+ console/consoleitemdelegate.cpp console/consoleitemdelegate.h
+ console/consoleitemmodel.cpp console/consoleitemmodel.h
+ console/consoleproxymodel.cpp console/consoleproxymodel.h
+ console/consoleview.cpp console/consoleview.h
+ debugger.qrc
+ debugger_global.h
+ debuggeractions.cpp debuggeractions.h
+ debuggerconstants.h
+ debuggercore.h
+ debuggerdialogs.cpp debuggerdialogs.h
+ debuggerengine.cpp debuggerengine.h
+ debuggericons.cpp debuggericons.h
+ debuggerinternalconstants.h
+ debuggeritem.cpp debuggeritem.h
+ debuggeritemmanager.cpp debuggeritemmanager.h
+ debuggerkitinformation.cpp debuggerkitinformation.h
+ debuggermainwindow.cpp debuggermainwindow.h
+ debuggerplugin.cpp debuggerplugin.h
+ debuggerprotocol.cpp debuggerprotocol.h
+ debuggerrunconfigurationaspect.cpp debuggerrunconfigurationaspect.h
+ debuggerruncontrol.cpp debuggerruncontrol.h
+ debuggersourcepathmappingwidget.cpp debuggersourcepathmappingwidget.h
+ debuggertooltipmanager.cpp debuggertooltipmanager.h
+ disassembleragent.cpp disassembleragent.h
+ disassemblerlines.cpp disassemblerlines.h
+ gdb/gdbengine.cpp gdb/gdbengine.h
+ gdb/gdboptionspage.cpp
+ imageviewer.cpp imageviewer.h
+ enginemanager.cpp enginemanager.h
+ lldb/lldbengine.cpp lldb/lldbengine.h
+ loadcoredialog.cpp loadcoredialog.h
+ localsandexpressionswindow.cpp localsandexpressionswindow.h
+ logwindow.cpp logwindow.h
+ memoryagent.cpp memoryagent.h
+ moduleshandler.cpp moduleshandler.h
+ namedemangler/demanglerexceptions.h
+ namedemangler/globalparsestate.cpp namedemangler/globalparsestate.h
+ namedemangler/namedemangler.cpp namedemangler/namedemangler.h
+ namedemangler/parsetreenodes.cpp namedemangler/parsetreenodes.h
+ outputcollector.cpp outputcollector.h
+ pdb/pdbengine.cpp pdb/pdbengine.h
+ procinterrupt.cpp procinterrupt.h
+ qml/interactiveinterpreter.cpp qml/interactiveinterpreter.h
+ #qml/qmlcppengine.cpp qml/qmlcppengine.h
+ qml/qmlengine.cpp qml/qmlengine.h
+ qml/qmlengineutils.cpp qml/qmlengineutils.h
+ qml/qmlinspectoragent.cpp qml/qmlinspectoragent.h
+ qml/qmlv8debuggerclientconstants.h
+ registerhandler.cpp registerhandler.h
+ shared/backtrace.cpp shared/backtrace.h
+ shared/cdbsymbolpathlisteditor.cpp shared/cdbsymbolpathlisteditor.h
+ shared/hostutils.cpp shared/hostutils.h
+ shared/peutils.cpp shared/peutils.h
+ shared/symbolpathsdialog.cpp shared/symbolpathsdialog.h shared/symbolpathsdialog.ui
+ simplifytype.cpp simplifytype.h
+ sourceagent.cpp sourceagent.h
+ sourcefileshandler.cpp sourcefileshandler.h
+ sourceutils.cpp sourceutils.h
+ stackframe.cpp stackframe.h
+ stackhandler.cpp stackhandler.h
+ stackwindow.cpp stackwindow.h
+ terminal.cpp terminal.h
+ threaddata.h
+ threadshandler.cpp threadshandler.h
+ unstartedappwatcherdialog.cpp unstartedappwatcherdialog.h
+ watchdata.cpp watchdata.h
+ watchdelegatewidgets.cpp watchdelegatewidgets.h
+ watchhandler.cpp watchhandler.h
+ watchutils.cpp watchutils.h
+ watchwindow.cpp watchwindow.h
+)
+
+extend_qtc_plugin(Debugger
+ CONDITION WIN32
+ SOURCES registerpostmortemaction.cpp registerpostmortemaction.h
+ DEFINES UNICODE _UNICODE
+)
+
+extend_qtc_plugin(Debugger
+ CONDITION WITH_TESTS
+ SOURCES
+ debuggerunittests.qrc
+ unit-tests/simple/main.cpp
+)
diff --git a/src/plugins/debugger/analyzer/analyzerrunconfigwidget.cpp b/src/plugins/debugger/analyzer/analyzerrunconfigwidget.cpp
index 137e0612b4..39a3684ab3 100644
--- a/src/plugins/debugger/analyzer/analyzerrunconfigwidget.cpp
+++ b/src/plugins/debugger/analyzer/analyzerrunconfigwidget.cpp
@@ -52,7 +52,7 @@ AnalyzerRunConfigWidget::AnalyzerRunConfigWidget(ProjectExplorer::GlobalOrProjec
QApplication::translate("ProjectExplorer::Internal::EditorSettingsPropertiesPage", "Custom")
}));
globalSettingLayout->addWidget(m_settingsCombo);
- connect(m_settingsCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_settingsCombo, QOverload<int>::of(&QComboBox::activated),
this, &AnalyzerRunConfigWidget::chooseSettings);
m_restoreButton = new QPushButton(
QApplication::translate("ProjectExplorer::Internal::EditorSettingsPropertiesPage", "Restore Global"),
diff --git a/src/plugins/debugger/analyzer/startremotedialog.cpp b/src/plugins/debugger/analyzer/startremotedialog.cpp
index 0702536262..30ce83eca2 100644
--- a/src/plugins/debugger/analyzer/startremotedialog.cpp
+++ b/src/plugins/debugger/analyzer/startremotedialog.cpp
@@ -28,7 +28,7 @@
#include <coreplugin/icore.h>
#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <ssh/sshconnection.h>
#include <QDialogButtonBox>
@@ -63,7 +63,7 @@ StartRemoteDialog::StartRemoteDialog(QWidget *parent)
d->kitChooser = new KitChooser(this);
d->kitChooser->setKitPredicate([](const Kit *kit) {
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return kit->isValid() && device && !device->sshParameters().host().isEmpty();
});
d->executable = new QLineEdit(this);
@@ -132,7 +132,7 @@ Runnable StartRemoteDialog::runnable() const
{
Kit *kit = d->kitChooser->currentKit();
Runnable r;
- r.device = DeviceKitInformation::device(kit);
+ r.device = DeviceKitAspect::device(kit);
r.executable = d->executable->text();
r.commandLineArguments = d->arguments->text();
r.workingDirectory = d->workingDirectory->text();
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 481c123046..2fd197c618 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -87,7 +87,7 @@ static BreakpointManager *theBreakpointManager = nullptr;
class BreakpointMarker : public TextEditor::TextMark
{
public:
- BreakpointMarker(const Breakpoint &bp, const FileName &fileName, int lineNumber)
+ BreakpointMarker(const Breakpoint &bp, const FilePath &fileName, int lineNumber)
: TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY_BREAKPOINT), m_bp(bp)
{
setColor(Theme::Debugger_Breakpoint_TextMarkColor);
@@ -106,7 +106,7 @@ public:
gbp->m_params.lineNumber = lineNumber;
}
- void updateFileName(const FileName &fileName) final
+ void updateFileName(const FilePath &fileName) final
{
TextMark::updateFileName(fileName);
QTC_ASSERT(m_bp, return);
@@ -145,7 +145,7 @@ public:
class GlobalBreakpointMarker : public TextEditor::TextMark
{
public:
- GlobalBreakpointMarker(GlobalBreakpoint gbp, const FileName &fileName, int lineNumber)
+ GlobalBreakpointMarker(GlobalBreakpoint gbp, const FilePath &fileName, int lineNumber)
: TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY_BREAKPOINT), m_gbp(gbp)
{
setColor(Theme::Debugger_Breakpoint_TextMarkColor);
@@ -174,7 +174,7 @@ public:
m_gbp->update();
}
- void updateFileName(const FileName &fileName) final
+ void updateFileName(const FilePath &fileName) final
{
TextMark::updateFileName(fileName);
QTC_ASSERT(m_gbp, return);
@@ -541,7 +541,7 @@ BreakpointDialog::BreakpointDialog(unsigned int enabledParts, QWidget *parent)
verticalLayout->addWidget(m_buttonBox);
verticalLayout->setStretchFactor(groupBoxAdvanced, 10);
- connect(m_comboBoxType, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_comboBoxType, QOverload<int>::of(&QComboBox::activated),
this, &BreakpointDialog::typeChanged);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
@@ -1877,7 +1877,7 @@ void BreakpointItem::updateMarkerIcon()
void BreakpointItem::updateMarker()
{
- FileName file = FileName::fromString(markerFileName());
+ FilePath file = FilePath::fromString(markerFileName());
int line = markerLineNumber();
if (m_marker && (file != m_marker->fileName() || line != m_marker->lineNumber()))
destroyMarker();
@@ -2298,7 +2298,7 @@ void GlobalBreakpointItem::updateMarker()
return;
}
- const FileName file = FileName::fromString(m_params.fileName);
+ const FilePath file = FilePath::fromString(m_params.fileName);
const int line = m_params.lineNumber;
if (m_marker && (file != m_marker->fileName() || line != m_marker->lineNumber()))
destroyMarker();
diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h
index 544f4a509e..83d934034b 100644
--- a/src/plugins/debugger/breakhandler.h
+++ b/src/plugins/debugger/breakhandler.h
@@ -76,7 +76,7 @@ public:
void removeBreakpointFromModel();
void updateLineNumber(int lineNumber);
- void updateFileName(const Utils::FileName &fileName);
+ void updateFileName(const Utils::FilePath &fileName);
QString displayName() const;
QString markerFileName() const;
@@ -191,7 +191,7 @@ public:
void deleteGlobalOrThisBreakpoint();
void updateLineNumber(int lineNumber);
- void updateFileName(const Utils::FileName &fileName);
+ void updateFileName(const Utils::FilePath &fileName);
const GlobalBreakpoint globalBreakpoint() const;
void gotoState(BreakpointState target, BreakpointState assumedCurrent);
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index b5372bce5b..4a3839159e 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -203,7 +203,7 @@ CdbEngine::CdbEngine() :
connect(action(CreateFullBacktrace), &QAction::triggered,
this, &CdbEngine::createFullBacktrace);
- connect(&m_process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CdbEngine::processFinished);
connect(&m_process, &QProcess::errorOccurred, this, &CdbEngine::processError);
connect(&m_process, &QProcess::readyReadStandardOutput,
@@ -256,7 +256,7 @@ void CdbEngine::init()
if (!sourcePathMap.isEmpty()) {
for (auto it = sourcePathMap.constBegin(), cend = sourcePathMap.constEnd(); it != cend; ++it) {
m_sourcePathMappings.push_back({QDir::toNativeSeparators(it.key()),
- QDir::toNativeSeparators(it.value())});
+ QDir::toNativeSeparators(expand(it.value()))});
}
}
// update source path maps from debugger start params
@@ -324,12 +324,9 @@ static QStringList mergeEnvironment(QStringList runConfigEnvironment,
return runConfigEnvironment;
}
-int CdbEngine::elapsedLogTime() const
+int CdbEngine::elapsedLogTime()
{
- const int elapsed = m_logTime.elapsed();
- const int delta = elapsed - m_elapsedLogTime;
- m_elapsedLogTime = elapsed;
- return delta;
+ return m_logTimer.restart();
}
void CdbEngine::createFullBacktrace()
@@ -352,8 +349,8 @@ void CdbEngine::setupEngine()
qDebug(">setupEngine");
init();
- if (!m_logTime.elapsed())
- m_logTime.start();
+ if (!m_logTimer.elapsed())
+ m_logTimer.start();
// Console: Launch the stub with the suspended application and attach to it
// CDB in theory has a command line option '-2' that launches a
@@ -526,7 +523,7 @@ void CdbEngine::handleInitialSessionIdle()
if (rp.breakOnMain) {
BreakpointParameters bp(BreakpointAtMain);
if (rp.startMode == StartInternal || rp.startMode == StartExternal) {
- const QString &moduleFileName = Utils::FileName::fromString(rp.inferior.executable)
+ const QString &moduleFileName = Utils::FilePath::fromString(rp.inferior.executable)
.fileName();
bp.module = moduleFileName.left(moduleFileName.indexOf('.'));
}
@@ -1119,6 +1116,7 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
cmd.arg("dyntype", boolSetting(UseDynamicType));
cmd.arg("partialvar", updateParameters.partialVariable);
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
+ cmd.arg("timestamps", boolSetting(LogTimeStamps));
StackFrame frame = stackHandler()->currentFrame();
cmd.arg("context", frame.context);
@@ -2204,7 +2202,7 @@ void CdbEngine::handleExtensionMessage(char t, int token, const QString &what, c
if (!isDebuggerWinException(exception.exceptionCode)) {
const Task::TaskType type =
isFatalWinException(exception.exceptionCode) ? Task::Error : Task::Warning;
- const FileName fileName = FileName::fromUserInput(exception.file);
+ const FilePath fileName = FilePath::fromUserInput(exception.file);
const QString taskEntry = tr("Debugger encountered an exception: %1").arg(
exception.toString(false).trimmed());
TaskHub::addTask(type, taskEntry,
diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h
index 16b71b954b..fd0e35ba8a 100644
--- a/src/plugins/debugger/cdb/cdbengine.h
+++ b/src/plugins/debugger/cdb/cdbengine.h
@@ -32,14 +32,12 @@
#include <projectexplorer/devicesupport/idevice.h>
-#include <QTime>
+#include <QElapsedTimer>
namespace Debugger {
namespace Internal {
class CdbCommand;
-struct MemoryViewCookie;
-class StringInputStream;
class CdbEngine : public CppDebuggerEngine
{
@@ -195,7 +193,7 @@ private:
NormalizedSourceFileName sourceMapNormalizeFileNameFromDebugger(const QString &f);
void doUpdateLocals(const UpdateParameters &params) override;
void updateAll() override;
- int elapsedLogTime() const;
+ int elapsedLogTime();
unsigned parseStackTrace(const GdbMi &data, bool sourceStepInto);
void mergeStartParametersSourcePathMap();
@@ -223,8 +221,7 @@ private:
wow64Stack32Bit,
wow64Stack64Bit
} m_wow64State = wow64Uninitialized;
- QTime m_logTime;
- mutable int m_elapsedLogTime = 0;
+ QElapsedTimer m_logTimer;
QString m_extensionMessageBuffer;
bool m_sourceStepInto = false;
int m_watchPointX = 0;
diff --git a/src/plugins/debugger/cdb/cdbparsehelpers.cpp b/src/plugins/debugger/cdb/cdbparsehelpers.cpp
index 577776f8fb..2590a47a09 100644
--- a/src/plugins/debugger/cdb/cdbparsehelpers.cpp
+++ b/src/plugins/debugger/cdb/cdbparsehelpers.cpp
@@ -84,7 +84,7 @@ static inline QString cdbBreakPointFileName(const BreakpointParameters &params,
if (params.fileName.isEmpty())
return params.fileName;
if (params.pathUsage == BreakpointUseShortPath)
- return Utils::FileName::fromString(params.fileName).fileName();
+ return Utils::FilePath::fromString(params.fileName).fileName();
return cdbSourcePathMapping(QDir::toNativeSeparators(params.fileName), sourcePathMapping, SourceToDebugger);
}
diff --git a/src/plugins/debugger/console/console.cpp b/src/plugins/debugger/console/console.cpp
index 1ff13a2545..c7fe001c74 100644
--- a/src/plugins/debugger/console/console.cpp
+++ b/src/plugins/debugger/console/console.cpp
@@ -100,7 +100,6 @@ Console::Console()
vbox->addWidget(new Core::FindToolBarPlaceHolder(m_consoleWidget));
m_showDebugButton = new QToolButton(m_consoleWidget);
- m_showDebugButton->setAutoRaise(true);
m_showDebugButtonAction = new Utils::SavedAction(this);
m_showDebugButtonAction->setDefaultValue(true);
@@ -114,7 +113,6 @@ Console::Console()
m_showDebugButton->setDefaultAction(m_showDebugButtonAction);
m_showWarningButton = new QToolButton(m_consoleWidget);
- m_showWarningButton->setAutoRaise(true);
m_showWarningButtonAction = new Utils::SavedAction(this);
m_showWarningButtonAction->setDefaultValue(true);
@@ -128,7 +126,6 @@ Console::Console()
m_showWarningButton->setDefaultAction(m_showWarningButtonAction);
m_showErrorButton = new QToolButton(m_consoleWidget);
- m_showErrorButton->setAutoRaise(true);
m_showErrorButtonAction = new Utils::SavedAction(this);
m_showErrorButtonAction->setDefaultValue(true);
diff --git a/src/plugins/debugger/console/consoleitemdelegate.cpp b/src/plugins/debugger/console/consoleitemdelegate.cpp
index 265ee6ce17..2196d7a260 100644
--- a/src/plugins/debugger/console/consoleitemdelegate.cpp
+++ b/src/plugins/debugger/console/consoleitemdelegate.cpp
@@ -186,7 +186,7 @@ void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
const int pos = file.lastIndexOf('/');
if (pos != -1)
file = file.mid(pos +1);
- const int realFileWidth = fm.width(file);
+ const int realFileWidth = fm.horizontalAdvance(file);
painter->setClipRect(positions.fileArea());
painter->drawText(positions.fileAreaLeft(), positions.adjustedTop() + fm.ascent(),
file);
@@ -203,7 +203,7 @@ void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
// Paint LineArea
QString lineText = index.data(ConsoleItem::LineRole).toString();
painter->setClipRect(positions.lineArea());
- const int realLineWidth = fm.width(lineText);
+ const int realLineWidth = fm.horizontalAdvance(lineText);
painter->drawText(positions.lineAreaRight() - realLineWidth,
positions.adjustedTop() + fm.ascent(), lineText);
}
diff --git a/src/plugins/debugger/console/consoleitemmodel.cpp b/src/plugins/debugger/console/consoleitemmodel.cpp
index 525aca0dc0..aa31132956 100644
--- a/src/plugins/debugger/console/consoleitemmodel.cpp
+++ b/src/plugins/debugger/console/consoleitemmodel.cpp
@@ -92,7 +92,7 @@ int ConsoleItemModel::sizeOfFile(const QFont &font)
filename = filename.mid(pos + 1);
QFontMetrics fm(font);
- m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.width(filename));
+ m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.horizontalAdvance(filename));
return m_maxSizeOfFileName;
}
@@ -100,7 +100,7 @@ int ConsoleItemModel::sizeOfFile(const QFont &font)
int ConsoleItemModel::sizeOfLineNumber(const QFont &font)
{
QFontMetrics fm(font);
- return fm.width("88888");
+ return fm.horizontalAdvance("88888");
}
} // Internal
diff --git a/src/plugins/debugger/console/consoleview.cpp b/src/plugins/debugger/console/consoleview.cpp
index 9969bfb0f5..c6387cc9e0 100644
--- a/src/plugins/debugger/console/consoleview.cpp
+++ b/src/plugins/debugger/console/consoleview.cpp
@@ -218,7 +218,8 @@ void ConsoleView::onRowActivated(const QModelIndex &index)
if (!index.isValid())
return;
- const QFileInfo fi(m_finder.findFile(model()->data(index, ConsoleItem::FileRole).toString()));
+ const QFileInfo fi = m_finder.findFile(model()->data(index, ConsoleItem::FileRole).toString())
+ .first().toFileInfo();
if (fi.exists() && fi.isFile() && fi.isReadable()) {
Core::EditorManager::openEditorAt(fi.canonicalFilePath(),
model()->data(index, ConsoleItem::LineRole).toInt());
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index acbf5136b9..0f91ac1a92 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -29,7 +29,6 @@ HEADERS += \
debuggerprotocol.h \
debuggerrunconfigurationaspect.h \
debuggerruncontrol.h \
- debuggerkitconfigwidget.h \
debuggerkitinformation.h \
disassembleragent.h \
disassemblerlines.h \
@@ -76,7 +75,6 @@ SOURCES += \
debuggerprotocol.cpp \
debuggerrunconfigurationaspect.cpp \
debuggerruncontrol.cpp \
- debuggerkitconfigwidget.cpp \
debuggerkitinformation.cpp \
disassembleragent.cpp \
disassemblerlines.cpp \
diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index 50dd65fe76..6add8dd906 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -51,7 +51,6 @@ Project {
"debuggerinternalconstants.h",
"debuggeritem.cpp", "debuggeritem.h",
"debuggeritemmanager.cpp", "debuggeritemmanager.h",
- "debuggerkitconfigwidget.cpp", "debuggerkitconfigwidget.h",
"debuggerkitinformation.cpp", "debuggerkitinformation.h",
"debuggermainwindow.cpp", "debuggermainwindow.h",
"debuggerplugin.cpp", "debuggerplugin.h",
diff --git a/src/plugins/debugger/debugger.qrc b/src/plugins/debugger/debugger.qrc
index bf8095b338..86a05a73ff 100644
--- a/src/plugins/debugger/debugger.qrc
+++ b/src/plugins/debugger/debugger.qrc
@@ -14,6 +14,8 @@
<file>images/debugger_interrupt@2x.png</file>
<file>images/debugger_interrupt_mask.png</file>
<file>images/debugger_interrupt_mask@2x.png</file>
+ <file>images/debugger_stop.png</file>
+ <file>images/debugger_stop@2x.png</file>
<file>images/debugger_stop_mask.png</file>
<file>images/debugger_stop_mask@2x.png</file>
<file>images/debugger_reversemode.png</file>
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index e0ddfff85c..5c27458f47 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -33,82 +33,11 @@ namespace Constants {
// Debug mode
const char MODE_DEBUG[] = "Mode.Debug";
-// Contexts
+// Debug mode context
const char C_DEBUGMODE[] = "Debugger.DebugMode";
-const char C_CPPDEBUGGER[] = "Gdb Debugger";
-const char C_QMLDEBUGGER[] = "Qml/JavaScript Debugger";
-const char C_DEBUGGER_NOTRUNNING[] = "Debugger.NotRunning";
-
-const char PRESET_PERSPECTIVE_ID[] = "Debugger.Perspective.Preset";
-
-// Menu Groups
-const char G_GENERAL[] = "Debugger.Group.General";
-const char G_SPECIAL[] = "Debugger.Group.Special";
-const char G_START_QML[] = "Debugger.Group.Start.Qml";
-
-// Common actions
-const char INTERRUPT[] = "Debugger.Interrupt";
-const char CONTINUE[] = "Debugger.Continue";
-const char STOP[] = "Debugger.Stop";
-const char ABORT[] = "Debugger.Abort";
-const char STEP[] = "Debugger.StepLine";
-const char STEPOUT[] = "Debugger.StepOut";
-const char NEXT[] = "Debugger.NextLine";
-const char RUNTOLINE[] = "Debugger.RunToLine";
-const char RUNTOSELECTEDFUNCTION[] = "Debugger.RunToSelectedFunction";
-const char JUMPTOLINE[] = "Debugger.JumpToLine";
-const char RETURNFROMFUNCTION[] = "Debugger.ReturnFromFunction";
-const char RESET[] = "Debugger.Reset";
-const char WATCH[] = "Debugger.AddToWatch";
-const char DETACH[] = "Debugger.Detach";
-const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction";
-const char OPEN_MEMORY_EDITOR[] = "Debugger.Views.OpenMemoryEditor";
-const char FRAME_UP[] = "Debugger.FrameUp";
-const char FRAME_DOWN[] = "Debugger.FrameDown";
-const char QML_SHOW_APP_ON_TOP[] = "Debugger.QmlShowAppOnTop";
-const char QML_SELECTTOOL[] = "Debugger.QmlSelectTool";
-
-const char TASK_CATEGORY_DEBUGGER_DEBUGINFO[] = "Debuginfo";
-const char TASK_CATEGORY_DEBUGGER_RUNTIME[] = "DebugRuntime";
-
-const char TEXT_MARK_CATEGORY_BREAKPOINT[] = "Debugger.Mark.Breakpoint";
-const char TEXT_MARK_CATEGORY_LOCATION[] = "Debugger.Mark.Location";
-
-// Run Configuration Aspect defaults:
-const int QML_DEFAULT_DEBUG_SERVER_PORT = 3768;
} // namespace Constants
-enum DebuggerState
-{
- DebuggerNotReady, // Debugger not started
-
- EngineSetupRequested, // Engine starts
- EngineSetupFailed,
- EngineSetupOk,
-
- EngineRunRequested,
- EngineRunFailed,
-
- InferiorUnrunnable, // Used in the core dump adapter
-
- InferiorRunRequested, // Debuggee requested to run
- InferiorRunOk, // Debuggee running
- InferiorRunFailed, // Debuggee running
-
- InferiorStopRequested, // Debuggee running, stop requested
- InferiorStopOk, // Debuggee stopped
- InferiorStopFailed, // Debuggee not stopped, will kill debugger
-
- InferiorShutdownRequested,
- InferiorShutdownFinished,
-
- EngineShutdownRequested,
- EngineShutdownFinished,
-
- DebuggerFinished
-};
-
// Keep in sync with dumper.py
enum DebuggerStartMode
{
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp
index 0e274e439d..5fc852cf2c 100644
--- a/src/plugins/debugger/debuggerdialogs.cpp
+++ b/src/plugins/debugger/debuggerdialogs.cpp
@@ -110,21 +110,21 @@ DebuggerKitChooser::DebuggerKitChooser(Mode mode, QWidget *parent)
{
setKitPredicate([this](const Kit *k) {
// Match valid debuggers and restrict local debugging to compatible toolchains.
- auto errors = DebuggerKitInformation::configurationErrors(k);
+ auto errors = DebuggerKitAspect::configurationErrors(k);
// we do not care for mismatched ABI if we want *any* debugging
- if (m_mode == AnyDebugging && errors == DebuggerKitInformation::DebuggerDoesNotMatch)
- errors = DebuggerKitInformation::NoConfigurationError;
+ if (m_mode == AnyDebugging && errors == DebuggerKitAspect::DebuggerDoesNotMatch)
+ errors = DebuggerKitAspect::NoConfigurationError;
if (errors)
return false;
if (m_mode == LocalDebugging)
- return ToolChainKitInformation::targetAbi(k).os() == m_hostAbi.os();
+ return ToolChainKitAspect::targetAbi(k).os() == m_hostAbi.os();
return true;
});
}
QString DebuggerKitChooser::kitToolTip(Kit *k) const
{
- return DebuggerKitInformation::displayString(k);
+ return DebuggerKitAspect::displayString(k);
}
///////////////////////////////////////////////////////////////////////
@@ -150,7 +150,7 @@ public:
Runnable runnable;
bool breakAtMain = false;
bool runInTerminal = false;
- QString serverStartScript;
+ FilePath serverStartScript;
QString debugInfoLocation;
};
@@ -172,7 +172,7 @@ QString StartApplicationParameters::displayName() const
{
const int maxLength = 60;
- QString name = FileName::fromString(runnable.executable).fileName()
+ QString name = FilePath::fromString(runnable.executable).fileName()
+ ' ' + runnable.commandLineArguments;
if (name.size() > 60) {
int index = name.lastIndexOf(' ', maxLength);
@@ -198,7 +198,7 @@ void StartApplicationParameters::toSettings(QSettings *settings) const
settings->setValue("LastExternalWorkingDirectory", runnable.workingDirectory);
settings->setValue("LastExternalBreakAtMain", breakAtMain);
settings->setValue("LastExternalRunInTerminal", runInTerminal);
- settings->setValue("LastServerStartScript", serverStartScript);
+ settings->setValue("LastServerStartScript", serverStartScript.toVariant());
settings->setValue("LastDebugInfoLocation", debugInfoLocation);
}
@@ -212,7 +212,7 @@ void StartApplicationParameters::fromSettings(const QSettings *settings)
runnable.workingDirectory = settings->value("LastExternalWorkingDirectory").toString();
breakAtMain = settings->value("LastExternalBreakAtMain").toBool();
runInTerminal = settings->value("LastExternalRunInTerminal").toBool();
- serverStartScript = settings->value("LastServerStartScript").toString();
+ serverStartScript = FilePath::fromVariant(settings->value("LastServerStartScript"));
debugInfoLocation = settings->value("LastDebugInfoLocation").toString();
}
@@ -229,9 +229,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
setWindowTitle(tr("Start Debugger"));
d->kitChooser = new KitChooser(this);
- d->kitChooser->setKitPredicate([](const Kit *k) {
- return !DebuggerKitInformation::configurationErrors(k);
- });
+ d->kitChooser->setShowIcons(true);
d->kitChooser->populate();
d->serverPortLabel = new QLabel(tr("Server port:"), this);
@@ -326,7 +324,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
this, &StartApplicationDialog::updateState);
connect(d->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(d->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(d->historyComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(d->historyComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &StartApplicationDialog::historyIndexChanged);
connect(d->channelOverrideEdit, &QLineEdit::textChanged,
@@ -408,10 +406,10 @@ void StartApplicationDialog::run(bool attachRemote)
return;
Kit *k = dialog.d->kitChooser->currentKit();
- IDevice::ConstPtr dev = DeviceKitInformation::device(k);
- auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, k);
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setKit(k);
+ auto debugger = new DebuggerRunTool(runControl);
const StartApplicationParameters newParameters = dialog.parameters();
if (newParameters != history.back()) {
@@ -428,6 +426,7 @@ void StartApplicationDialog::run(bool attachRemote)
settings->endGroup();
}
+ IDevice::ConstPtr dev = DeviceKitAspect::device(k);
Runnable inferior = newParameters.runnable;
const QString inputAddress = dialog.d->channelOverrideEdit->text();
if (!inputAddress.isEmpty())
@@ -474,7 +473,7 @@ StartApplicationParameters StartApplicationDialog::parameters() const
result.serverPort = d->serverPortSpinBox->value();
result.serverAddress = d->channelOverrideEdit->text();
result.runnable.executable = d->localExecutablePathChooser->path();
- result.serverStartScript = d->serverStartScriptPathChooser->path();
+ result.serverStartScript = d->serverStartScriptPathChooser->fileName();
result.kitId = d->kitChooser->currentKitId();
result.debugInfoLocation = d->debuginfoPathChooser->path();
result.runnable.commandLineArguments = d->arguments->text();
@@ -490,7 +489,7 @@ void StartApplicationDialog::setParameters(const StartApplicationParameters &p)
d->serverPortSpinBox->setValue(p.serverPort);
d->channelOverrideEdit->setText(p.serverAddress);
d->localExecutablePathChooser->setPath(p.runnable.executable);
- d->serverStartScriptPathChooser->setPath(p.serverStartScript);
+ d->serverStartScriptPathChooser->setFileName(p.serverStartScript);
d->debuginfoPathChooser->setPath(p.debugInfoLocation);
d->arguments->setText(p.runnable.commandLineArguments);
d->workingDirectory->setPath(p.runnable.workingDirectory);
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index b86bb1088e..6b94e5025d 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -173,7 +173,7 @@ Location::Location(const StackFrame &frame, bool marker)
}
-LocationMark::LocationMark(DebuggerEngine *engine, const FileName &file, int line)
+LocationMark::LocationMark(DebuggerEngine *engine, const FilePath &file, int line)
: TextMark(file, line, Constants::TEXT_MARK_CATEGORY_LOCATION), m_engine(engine)
{
setPriority(TextMark::HighPriority);
@@ -454,7 +454,6 @@ public:
DebuggerEngine *m_engine = nullptr; // Not owned.
QString m_runId;
- QPointer<RunConfiguration> m_runConfiguration; // Not owned.
QString m_debuggerName;
QPointer<Perspective> m_perspective;
DebuggerRunParameters m_runParameters;
@@ -1010,7 +1009,6 @@ void DebuggerEngine::setRunId(const QString &id)
void DebuggerEngine::setRunTool(DebuggerRunTool *runTool)
{
RunControl *runControl = runTool->runControl();
- d->m_runConfiguration = runControl->runConfiguration();
d->m_device = runControl->device();
if (!d->m_device)
d->m_device = d->m_runParameters.inferior.device;
@@ -1067,7 +1065,7 @@ void DebuggerEngine::gotoLocation(const Location &loc)
editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
if (loc.needsMarker()) {
- d->m_locationMark.reset(new LocationMark(this, FileName::fromString(file), line));
+ d->m_locationMark.reset(new LocationMark(this, FilePath::fromString(file), line));
d->m_locationMark->setToolTip(tr("Current debugger location of %1").arg(displayName()));
}
}
@@ -1840,7 +1838,7 @@ QString DebuggerEngine::toFileInProject(const QUrl &fileUrl)
d->m_fileFinder.setAdditionalSearchDirectories(rp.additionalSearchDirectories);
d->m_fileFinder.setSysroot(rp.sysRoot);
- return d->m_fileFinder.findFile(fileUrl);
+ return d->m_fileFinder.findFile(fileUrl).first().toString();
}
QString DebuggerEngine::expand(const QString &string) const
@@ -1998,11 +1996,6 @@ void DebuggerEngine::progressPing()
d->m_progress.setProgressValue(progress);
}
-bool DebuggerEngine::isStartupRunConfiguration() const
-{
- return d->m_runConfiguration == RunConfiguration::startupRunConfiguration();
-}
-
void DebuggerEngine::setCompanionEngine(DebuggerEngine *engine)
{
d->m_companionEngine = engine;
@@ -2590,7 +2583,7 @@ QString DebuggerEngine::formatStartParameters() const
if (!sp.projectSourceDirectory.isEmpty()) {
str << "Project: " << sp.projectSourceDirectory.toUserOutput() << '\n';
str << "Additional Search Directories:";
- for (const FileName &dir : sp.additionalSearchDirectories)
+ for (const FilePath &dir : sp.additionalSearchDirectories)
str << ' ' << dir;
str << '\n';
}
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 736d2b3c03..78826dd518 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -34,7 +34,7 @@
#include <coreplugin/icontext.h>
#include <projectexplorer/devicesupport/idevice.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <texteditor/textmark.h>
#include <utils/fileutils.h>
@@ -56,6 +56,36 @@ namespace Debugger {
class DebuggerRunTool;
+enum DebuggerState
+{
+ DebuggerNotReady, // Debugger not started
+
+ EngineSetupRequested, // Engine starts
+ EngineSetupFailed,
+ EngineSetupOk,
+
+ EngineRunRequested,
+ EngineRunFailed,
+
+ InferiorUnrunnable, // Used in the core dump adapter
+
+ InferiorRunRequested, // Debuggee requested to run
+ InferiorRunOk, // Debuggee running
+ InferiorRunFailed, // Debuggee not running
+
+ InferiorStopRequested, // Debuggee running, stop requested
+ InferiorStopOk, // Debuggee stopped
+ InferiorStopFailed, // Debuggee not stopped, will kill debugger
+
+ InferiorShutdownRequested,
+ InferiorShutdownFinished,
+
+ EngineShutdownRequested,
+ EngineShutdownFinished,
+
+ DebuggerFinished
+};
+
DEBUGGER_EXPORT QDebug operator<<(QDebug str, DebuggerState state);
namespace Internal {
@@ -117,13 +147,13 @@ public:
// Used by Android to avoid false positives on warnOnRelease
bool skipExecutableValidation = false;
bool useTargetAsync = false;
- Utils::FileNameList additionalSearchDirectories;
+ Utils::FilePathList additionalSearchDirectories;
// Used by iOS.
QString platform;
QString deviceSymbolsRoot;
bool continueAfterAttach = false;
- Utils::FileName sysRoot;
+ Utils::FilePath sysRoot;
// Used by general core file debugging. Public access requested in QTCREATORBUG-17158.
QString coreFile;
@@ -147,8 +177,8 @@ public:
bool isSnapshot = false; // Set if created internally.
ProjectExplorer::Abi toolChainAbi;
- Utils::FileName projectSourceDirectory;
- Utils::FileNameList projectSourceFiles;
+ Utils::FilePath projectSourceDirectory;
+ Utils::FilePathList projectSourceFiles;
// Used by Script debugging
QString interpreter;
@@ -237,7 +267,6 @@ public:
QString runId() const;
const DebuggerRunParameters &runParameters() const;
- bool isStartupRunConfiguration() const;
void setCompanionEngine(DebuggerEngine *engine);
void setSecondaryEngine();
@@ -538,7 +567,7 @@ public:
class LocationMark : public TextEditor::TextMark
{
public:
- LocationMark(DebuggerEngine *engine, const Utils::FileName &file, int line);
+ LocationMark(DebuggerEngine *engine, const Utils::FilePath &file, int line);
void removedFromEditor() override { updateLineNumber(0); }
void updateIcon();
diff --git a/src/plugins/debugger/debuggericons.cpp b/src/plugins/debugger/debuggericons.cpp
index 1c047acc2d..c50f5fdc62 100644
--- a/src/plugins/debugger/debuggericons.cpp
+++ b/src/plugins/debugger/debuggericons.cpp
@@ -66,8 +66,10 @@ const Icon INTERRUPT(
const Icon INTERRUPT_FLAT({
{":/debugger/images/debugger_interrupt_mask.png", Theme::IconsInterruptToolBarColor},
{":/projectexplorer/images/debugger_beetle_mask.png", Theme::IconsDebugColor}});
+const Icon STOP(
+ ":/debugger/images/debugger_stop.png");
const Icon STOP_FLAT({
- {":/debugger/images/debugger_stop_mask.png", Theme::IconsStopColor},
+ {":/debugger/images/debugger_stop_mask.png", Theme::IconsStopToolBarColor},
{":/projectexplorer/images/debugger_beetle_mask.png", Theme::IconsDebugColor}});
const Icon DEBUG_INTERRUPT_SMALL({
{":/utils/images/interrupt_small.png", Theme::IconsInterruptColor},
diff --git a/src/plugins/debugger/debuggericons.h b/src/plugins/debugger/debuggericons.h
index 778fb4a33f..b7d83f27dd 100644
--- a/src/plugins/debugger/debuggericons.h
+++ b/src/plugins/debugger/debuggericons.h
@@ -50,6 +50,7 @@ extern const Utils::Icon DEBUG_CONTINUE_SMALL;
extern const Utils::Icon DEBUG_CONTINUE_SMALL_TOOLBAR;
extern const Utils::Icon INTERRUPT;
extern const Utils::Icon INTERRUPT_FLAT;
+extern const Utils::Icon STOP;
extern const Utils::Icon STOP_FLAT;
extern const Utils::Icon DEBUG_INTERRUPT_SMALL;
extern const Utils::Icon DEBUG_INTERRUPT_SMALL_TOOLBAR;
diff --git a/src/plugins/debugger/debuggerinternalconstants.h b/src/plugins/debugger/debuggerinternalconstants.h
index 8f6599b653..7137a9100c 100644
--- a/src/plugins/debugger/debuggerinternalconstants.h
+++ b/src/plugins/debugger/debuggerinternalconstants.h
@@ -28,22 +28,50 @@
#include <QtGlobal>
namespace Debugger {
+
namespace Constants {
-const char DEBUGGER_COMMON_SETTINGS_ID[] = "A.Debugger.General";
-const char DEBUGGER_SETTINGS_CATEGORY[] = "O.Debugger";
+// Common actions
+const char INTERRUPT[] = "Debugger.Interrupt";
+const char CONTINUE[] = "Debugger.Continue";
+const char STOP[] = "Debugger.Stop";
+const char ABORT[] = "Debugger.Abort";
+const char STEP[] = "Debugger.StepLine";
+const char STEPOUT[] = "Debugger.StepOut";
+const char NEXT[] = "Debugger.NextLine";
+const char RUNTOLINE[] = "Debugger.RunToLine";
+const char RUNTOSELECTEDFUNCTION[] = "Debugger.RunToSelectedFunction";
+const char JUMPTOLINE[] = "Debugger.JumpToLine";
+const char RETURNFROMFUNCTION[] = "Debugger.ReturnFromFunction";
+const char RESET[] = "Debugger.Reset";
+const char WATCH[] = "Debugger.AddToWatch";
+const char DETACH[] = "Debugger.Detach";
+const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction";
+const char OPEN_MEMORY_EDITOR[] = "Debugger.Views.OpenMemoryEditor";
+const char FRAME_UP[] = "Debugger.FrameUp";
+const char FRAME_DOWN[] = "Debugger.FrameDown";
+const char QML_SHOW_APP_ON_TOP[] = "Debugger.QmlShowAppOnTop";
+const char QML_SELECTTOOL[] = "Debugger.QmlSelectTool";
+
+const char DEBUGGER_COMMON_SETTINGS_ID[] = "A.Debugger.General";
+const char DEBUGGER_SETTINGS_CATEGORY[] = "O.Debugger";
+
+// Contexts
+const char C_CPPDEBUGGER[] = "Gdb Debugger";
+const char C_QMLDEBUGGER[] = "Qml/JavaScript Debugger";
+const char C_DEBUGGER_NOTRUNNING[] = "Debugger.NotRunning";
+
+const char PRESET_PERSPECTIVE_ID[] = "Debugger.Perspective.Preset";
-namespace Internal {
- enum { debug = 0 };
-} // namespace Internal
+const char TASK_CATEGORY_DEBUGGER_DEBUGINFO[] = "Debuginfo";
+const char TASK_CATEGORY_DEBUGGER_RUNTIME[] = "DebugRuntime";
-const char OPENED_BY_DEBUGGER[] = "OpenedByDebugger";
-const char OPENED_WITH_DISASSEMBLY[] = "DisassemblerView";
-const char DISASSEMBLER_SOURCE_FILE[] = "DisassemblerSourceFile";
+const char TEXT_MARK_CATEGORY_BREAKPOINT[] = "Debugger.Mark.Breakpoint";
+const char TEXT_MARK_CATEGORY_LOCATION[] = "Debugger.Mark.Location";
-// Debug action
-const char DEBUG[] = "Debugger.Debug";
-const int P_ACTION_DEBUG = 90; // Priority for the modemanager.
+const char OPENED_BY_DEBUGGER[] = "OpenedByDebugger";
+const char OPENED_WITH_DISASSEMBLY[] = "DisassemblerView";
+const char DISASSEMBLER_SOURCE_FILE[] = "DisassemblerSourceFile";
} // namespace Constants
diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp
index 2c889a016b..c17766361c 100644
--- a/src/plugins/debugger/debuggeritem.cpp
+++ b/src/plugins/debugger/debuggeritem.cpp
@@ -26,7 +26,6 @@
#include "debuggeritem.h"
#include "debuggeritemmanager.h"
#include "debuggerkitinformation.h"
-#include "debuggerkitconfigwidget.h"
#include "debuggerprotocol.h"
#include <projectexplorer/abi.h>
@@ -107,8 +106,8 @@ DebuggerItem::DebuggerItem(const QVariant &id)
DebuggerItem::DebuggerItem(const QVariantMap &data)
{
m_id = data.value(DEBUGGER_INFORMATION_ID).toString();
- m_command = FileName::fromUserInput(data.value(DEBUGGER_INFORMATION_COMMAND).toString());
- m_workingDirectory = FileName::fromUserInput(data.value(DEBUGGER_INFORMATION_WORKINGDIRECTORY).toString());
+ m_command = FilePath::fromUserInput(data.value(DEBUGGER_INFORMATION_COMMAND).toString());
+ m_workingDirectory = FilePath::fromUserInput(data.value(DEBUGGER_INFORMATION_WORKINGDIRECTORY).toString());
m_unexpandedDisplayName = data.value(DEBUGGER_INFORMATION_DISPLAYNAME).toString();
m_isAutoDetected = data.value(DEBUGGER_INFORMATION_AUTODETECTED, false).toBool();
m_version = data.value(DEBUGGER_INFORMATION_VERSION).toString();
@@ -303,14 +302,14 @@ QString DebuggerItem::displayName() const
return m_unexpandedDisplayName;
MacroExpander expander;
- expander.registerVariable("Debugger:Type", DebuggerKitInformation::tr("Type of Debugger Backend"),
+ expander.registerVariable("Debugger:Type", DebuggerKitAspect::tr("Type of Debugger Backend"),
[this] { return engineTypeName(); });
- expander.registerVariable("Debugger:Version", DebuggerKitInformation::tr("Debugger"),
+ expander.registerVariable("Debugger:Version", DebuggerKitAspect::tr("Debugger"),
[this] { return !m_version.isEmpty() ? m_version :
- DebuggerKitInformation::tr("Unknown debugger version"); });
- expander.registerVariable("Debugger:Abi", DebuggerKitInformation::tr("Debugger"),
+ DebuggerKitAspect::tr("Unknown debugger version"); });
+ expander.registerVariable("Debugger:Abi", DebuggerKitAspect::tr("Debugger"),
[this] { return !m_abis.isEmpty() ? abiNames().join(' ') :
- DebuggerKitInformation::tr("Unknown debugger ABI"); });
+ DebuggerKitAspect::tr("Unknown debugger ABI"); });
return expander.expand(m_unexpandedDisplayName);
}
@@ -324,7 +323,7 @@ void DebuggerItem::setEngineType(const DebuggerEngineType &engineType)
m_engineType = engineType;
}
-void DebuggerItem::setCommand(const FileName &command)
+void DebuggerItem::setCommand(const FilePath &command)
{
m_command = command;
}
@@ -344,7 +343,7 @@ void DebuggerItem::setVersion(const QString &version)
m_version = version;
}
-void DebuggerItem::setAbis(const QList<Abi> &abis)
+void DebuggerItem::setAbis(const Abis &abis)
{
m_abis = abis;
}
diff --git a/src/plugins/debugger/debuggeritem.h b/src/plugins/debugger/debuggeritem.h
index 20f141600b..77e18bff46 100644
--- a/src/plugins/debugger/debuggeritem.h
+++ b/src/plugins/debugger/debuggeritem.h
@@ -72,8 +72,8 @@ public:
DebuggerEngineType engineType() const { return m_engineType; }
void setEngineType(const DebuggerEngineType &engineType);
- Utils::FileName command() const { return m_command; }
- void setCommand(const Utils::FileName &command);
+ Utils::FilePath command() const { return m_command; }
+ void setCommand(const Utils::FilePath &command);
bool isAutoDetected() const { return m_isAutoDetected; }
void setAutoDetected(bool isAutoDetected);
@@ -81,8 +81,8 @@ public:
QString version() const;
void setVersion(const QString &version);
- const QList<ProjectExplorer::Abi> &abis() const { return m_abis; }
- void setAbis(const QList<ProjectExplorer::Abi> &abis);
+ const ProjectExplorer::Abis &abis() const { return m_abis; }
+ void setAbis(const ProjectExplorer::Abis &abis);
void setAbi(const ProjectExplorer::Abi &abi);
enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesWell, MatchesPerfectly, MatchesPerfectlyInPath };
@@ -99,8 +99,8 @@ public:
void reinitializeFromFile();
- Utils::FileName workingDirectory() const { return m_workingDirectory; }
- void setWorkingDirectory(const Utils::FileName &workingPath) { m_workingDirectory = workingPath; }
+ Utils::FilePath workingDirectory() const { return m_workingDirectory; }
+ void setWorkingDirectory(const Utils::FilePath &workingPath) { m_workingDirectory = workingPath; }
private:
DebuggerItem(const QVariant &id);
@@ -109,11 +109,11 @@ private:
QVariant m_id;
QString m_unexpandedDisplayName;
DebuggerEngineType m_engineType = NoEngineType;
- Utils::FileName m_command;
- Utils::FileName m_workingDirectory;
+ Utils::FilePath m_command;
+ Utils::FilePath m_workingDirectory;
bool m_isAutoDetected = false;
QString m_version;
- QList<ProjectExplorer::Abi> m_abis;
+ ProjectExplorer::Abis m_abis;
QDateTime m_lastModified;
friend class Internal::DebuggerConfigWidget;
diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp
index 0b730cb971..6d1e14cff8 100644
--- a/src/plugins/debugger/debuggeritemmanager.cpp
+++ b/src/plugins/debugger/debuggeritemmanager.cpp
@@ -71,7 +71,6 @@ namespace Internal {
const char DEBUGGER_COUNT_KEY[] = "DebuggerItem.Count";
const char DEBUGGER_DATA_KEY[] = "DebuggerItem.";
-const char DEBUGGER_LEGACY_FILENAME[] = "/profiles.xml";
const char DEBUGGER_FILE_VERSION_KEY[] = "Version";
const char DEBUGGER_FILENAME[] = "/debuggers.xml";
const char debuggingToolsWikiLinkC[] = "http://wiki.qt.io/Qt_Creator_Windows_Debugging";
@@ -90,10 +89,9 @@ public:
void addDebugger(const DebuggerItem &item);
QVariant registerDebugger(const DebuggerItem &item);
- void readDebuggers(const FileName &fileName, bool isSystem);
+ void readDebuggers(const FilePath &fileName, bool isSystem);
void autoDetectCdbDebuggers();
void autoDetectGdbOrLldbDebuggers();
- void readLegacyDebuggers(const FileName &file);
QString uniqueDisplayName(const QString &base);
PersistentSettingsWriter m_writer;
@@ -352,7 +350,7 @@ DebuggerItem DebuggerItemConfigWidget::item() const
item.setCommand(m_binaryChooser->fileName());
item.setWorkingDirectory(m_workingDirectoryChooser->fileName());
item.setAutoDetected(m_autodetected);
- QList<ProjectExplorer::Abi> abiList;
+ ProjectExplorer::Abis abiList;
foreach (const QString &a, m_abis->text().split(QRegExp("[^A-Za-z0-9-_]+"))) {
if (a.isNull())
continue;
@@ -626,7 +624,7 @@ void DebuggerOptionsPage::finish()
void DebuggerItemManagerPrivate::autoDetectCdbDebuggers()
{
- FileNameList cdbs;
+ FilePathList cdbs;
const QStringList programDirs = {
QString::fromLocal8Bit(qgetenv("ProgramFiles")),
@@ -655,8 +653,7 @@ void DebuggerItemManagerPrivate::autoDetectCdbDebuggers()
// Pre Windows SDK 8: Check 'Debugging Tools for Windows'
for (const QFileInfo &fi : dir.entryInfoList({"Debugging Tools for Windows*"},
QDir::Dirs | QDir::NoDotAndDotDot)) {
- FileName filePath(fi);
- filePath.appendPath("cdb.exe");
+ const FilePath filePath = FilePath::fromFileInfo(fi).pathAppended("cdb.exe");
if (!cdbs.contains(filePath))
cdbs.append(filePath);
}
@@ -679,13 +676,13 @@ void DebuggerItemManagerPrivate::autoDetectCdbDebuggers()
const QString path = kitFolderFi.absoluteFilePath();
const QFileInfo cdb32(path + "/Debuggers/x86/cdb.exe");
if (cdb32.isExecutable())
- cdbs.append(FileName::fromString(cdb32.absoluteFilePath()));
+ cdbs.append(FilePath::fromString(cdb32.absoluteFilePath()));
const QFileInfo cdb64(path + "/Debuggers/x64/cdb.exe");
if (cdb64.isExecutable())
- cdbs.append(FileName::fromString(cdb64.absoluteFilePath()));
+ cdbs.append(FilePath::fromString(cdb64.absoluteFilePath()));
}
- for (const FileName &cdb : qAsConst(cdbs)) {
+ for (const FilePath &cdb : qAsConst(cdbs)) {
if (DebuggerItemManager::findByCommand(cdb))
continue;
DebuggerItem item;
@@ -724,7 +721,7 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers()
}
*/
- FileNameList suspects;
+ FilePathList suspects;
if (HostOsInfo::isMacHost()) {
SynchronousProcess lldbInfo;
@@ -736,23 +733,23 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers()
if (!lPath.isEmpty()) {
const QFileInfo fi(lPath);
if (fi.exists() && fi.isExecutable() && !fi.isDir())
- suspects.append(FileName::fromString(fi.absoluteFilePath()));
+ suspects.append(FilePath::fromString(fi.absoluteFilePath()));
}
}
}
- Utils::FileNameList path = Environment::systemEnvironment().path();
+ Utils::FilePathList path = Environment::systemEnvironment().path();
path = Utils::filteredUnique(path);
QDir dir;
dir.setNameFilters(filters);
dir.setFilter(QDir::Files | QDir::Executable);
- foreach (const Utils::FileName &base, path) {
+ foreach (const Utils::FilePath &base, path) {
dir.setPath(base.toFileInfo().absoluteFilePath());
foreach (const QString &entry, dir.entryList())
- suspects.append(FileName::fromString(dir.absoluteFilePath(entry)));
+ suspects.append(FilePath::fromString(dir.absoluteFilePath(entry)));
}
- foreach (const FileName &command, suspects) {
+ foreach (const FilePath &command, suspects) {
const auto commandMatches = [command](const DebuggerTreeItem *titem) {
return titem->m_item.command() == command;
};
@@ -775,46 +772,9 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers()
}
}
-void DebuggerItemManagerPrivate::readLegacyDebuggers(const FileName &file)
+static FilePath userSettingsFileName()
{
- PersistentSettingsReader reader;
- if (!reader.load(file))
- return;
-
- foreach (const QVariant &v, reader.restoreValues()) {
- QVariantMap data1 = v.toMap();
- QString kitName = data1.value("PE.Profile.Name").toString();
- QVariantMap data2 = data1.value("PE.Profile.Data").toMap();
- QVariant v3 = data2.value(DebuggerKitInformation::id().toString());
- QString fn;
- if (v3.type() == QVariant::String)
- fn = v3.toString();
- else
- fn = v3.toMap().value("Binary").toString();
- if (fn.isEmpty())
- continue;
- if (fn.startsWith('{'))
- continue;
- if (fn == "auto")
- continue;
- FileName command = FileName::fromUserInput(fn);
- if (!command.exists())
- continue;
- if (DebuggerItemManager::findByCommand(command))
- continue;
- DebuggerItem item;
- item.createId();
- item.setCommand(command);
- item.setAutoDetected(true);
- item.reinitializeFromFile();
- item.setUnexpandedDisplayName(tr("Extracted from Kit %1").arg(kitName));
- m_model->addDebugger(item);
- }
-}
-
-static FileName userSettingsFileName()
-{
- return FileName::fromString(ICore::userResourcePath() + DEBUGGER_FILENAME);
+ return FilePath::fromString(ICore::userResourcePath() + DEBUGGER_FILENAME);
}
DebuggerItemManagerPrivate::DebuggerItemManagerPrivate()
@@ -865,7 +825,7 @@ QVariant DebuggerItemManagerPrivate::registerDebugger(const DebuggerItem &item)
return di.id();
}
-void DebuggerItemManagerPrivate::readDebuggers(const FileName &fileName, bool isSystem)
+void DebuggerItemManagerPrivate::readDebuggers(const FilePath &fileName, bool isSystem)
{
PersistentSettingsReader reader;
if (!reader.load(fileName))
@@ -910,7 +870,7 @@ void DebuggerItemManagerPrivate::readDebuggers(const FileName &fileName, bool is
void DebuggerItemManagerPrivate::restoreDebuggers()
{
// Read debuggers from SDK
- readDebuggers(FileName::fromString(ICore::installerResourcePath() + DEBUGGER_FILENAME), true);
+ readDebuggers(FilePath::fromString(ICore::installerResourcePath() + DEBUGGER_FILENAME), true);
// Read all debuggers from user file.
readDebuggers(userSettingsFileName(), false);
@@ -918,10 +878,6 @@ void DebuggerItemManagerPrivate::restoreDebuggers()
// Auto detect current.
autoDetectCdbDebuggers();
autoDetectGdbOrLldbDebuggers();
-
- // Add debuggers from pre-3.x profiles.xml
- readLegacyDebuggers(FileName::fromString(ICore::installerResourcePath() + DEBUGGER_LEGACY_FILENAME));
- readLegacyDebuggers(FileName::fromString(ICore::userResourcePath() + DEBUGGER_LEGACY_FILENAME));
}
void DebuggerItemManagerPrivate::saveDebuggers()
@@ -970,7 +926,7 @@ const QList<DebuggerItem> DebuggerItemManager::debuggers()
return result;
}
-const DebuggerItem *DebuggerItemManager::findByCommand(const FileName &command)
+const DebuggerItem *DebuggerItemManager::findByCommand(const FilePath &command)
{
return findDebugger([command](const DebuggerItem &item) {
return item.command() == command;
diff --git a/src/plugins/debugger/debuggeritemmanager.h b/src/plugins/debugger/debuggeritemmanager.h
index ec2d74c928..1b2c21e052 100644
--- a/src/plugins/debugger/debuggeritemmanager.h
+++ b/src/plugins/debugger/debuggeritemmanager.h
@@ -33,7 +33,7 @@
#include <QString>
#include <QCoreApplication>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace Debugger {
@@ -52,7 +52,7 @@ public:
static QVariant registerDebugger(const DebuggerItem &item);
static void deregisterDebugger(const QVariant &id);
- static const DebuggerItem *findByCommand(const Utils::FileName &command);
+ static const DebuggerItem *findByCommand(const Utils::FilePath &command);
static const DebuggerItem *findById(const QVariant &id);
static const DebuggerItem *findByEngineType(DebuggerEngineType engineType);
};
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp
deleted file mode 100644
index d95a2861ac..0000000000
--- a/src/plugins/debugger/debuggerkitconfigwidget.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 "debuggerkitconfigwidget.h"
-
-#include "debuggeritemmanager.h"
-#include "debuggeritem.h"
-#include "debuggerkitinformation.h"
-
-#include <coreplugin/icore.h>
-
-#include <projectexplorer/abi.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/toolchain.h>
-#include <projectexplorer/toolchainmanager.h>
-
-#include <utils/elidinglabel.h>
-#include <utils/environment.h>
-#include <utils/pathchooser.h>
-#include <utils/persistentsettings.h>
-#include <utils/qtcassert.h>
-
-#include <QApplication>
-#include <QComboBox>
-#include <QDirIterator>
-#include <QFileInfo>
-#include <QFormLayout>
-#include <QHeaderView>
-#include <QLineEdit>
-#include <QPushButton>
-#include <QStandardItem>
-#include <QStandardItemModel>
-#include <QUuid>
-
-using namespace ProjectExplorer;
-
-namespace Debugger {
-namespace Internal {
-
-// -----------------------------------------------------------------------
-// DebuggerKitConfigWidget
-// -----------------------------------------------------------------------
-
-DebuggerKitConfigWidget::DebuggerKitConfigWidget(Kit *workingCopy, const KitInformation *ki)
- : KitConfigWidget(workingCopy, ki)
-{
- m_comboBox = new QComboBox;
- m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
- m_comboBox->setEnabled(true);
-
- refresh();
- connect(m_comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &DebuggerKitConfigWidget::currentDebuggerChanged);
-
- m_manageButton = new QPushButton(KitConfigWidget::msgManage());
- m_manageButton->setContentsMargins(0, 0, 0, 0);
- connect(m_manageButton, &QAbstractButton::clicked,
- this, &DebuggerKitConfigWidget::manageDebuggers);
-}
-
-DebuggerKitConfigWidget::~DebuggerKitConfigWidget()
-{
- delete m_comboBox;
- delete m_manageButton;
-}
-
-QString DebuggerKitConfigWidget::toolTip() const
-{
- return tr("The debugger to use for this kit.");
-}
-
-QString DebuggerKitConfigWidget::displayName() const
-{
- return tr("Debugger");
-}
-
-void DebuggerKitConfigWidget::makeReadOnly()
-{
- m_manageButton->setEnabled(false);
- m_comboBox->setEnabled(false);
-}
-
-void DebuggerKitConfigWidget::refresh()
-{
- m_ignoreChanges = true;
- m_comboBox->clear();
- m_comboBox->setToolTip(toolTip());
- m_comboBox->addItem(tr("None"), QString());
- for (const DebuggerItem &item : DebuggerItemManager::debuggers())
- m_comboBox->addItem(item.displayName(), item.id());
-
- const DebuggerItem *item = DebuggerKitInformation::debugger(m_kit);
- updateComboBox(item ? item->id() : QVariant());
- m_ignoreChanges = false;
-}
-
-QWidget *DebuggerKitConfigWidget::buttonWidget() const
-{
- return m_manageButton;
-}
-
-QWidget *DebuggerKitConfigWidget::mainWidget() const
-{
- return m_comboBox;
-}
-
-void DebuggerKitConfigWidget::manageDebuggers()
-{
- Core::ICore::showOptionsDialog(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID,
- buttonWidget());
-}
-
-void DebuggerKitConfigWidget::currentDebuggerChanged(int)
-{
- if (m_ignoreChanges)
- return;
-
- int currentIndex = m_comboBox->currentIndex();
- QVariant id = m_comboBox->itemData(currentIndex);
- m_kit->setValue(DebuggerKitInformation::id(), id);
-}
-
-QVariant DebuggerKitConfigWidget::currentId() const
-{
- return m_comboBox->itemData(m_comboBox->currentIndex());
-}
-
-void DebuggerKitConfigWidget::updateComboBox(const QVariant &id)
-{
- for (int i = 0; i < m_comboBox->count(); ++i) {
- if (id == m_comboBox->itemData(i)) {
- m_comboBox->setCurrentIndex(i);
- return;
- }
- }
- m_comboBox->setCurrentIndex(0);
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.h b/src/plugins/debugger/debuggerkitconfigwidget.h
deleted file mode 100644
index e424481bef..0000000000
--- a/src/plugins/debugger/debuggerkitconfigwidget.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 <coreplugin/dialogs/ioptionspage.h>
-#include <projectexplorer/kitconfigwidget.h>
-#include <projectexplorer/abi.h>
-#include <utils/detailswidget.h>
-#include <utils/fileutils.h>
-#include <utils/pathchooser.h>
-
-#include <QDialog>
-#include <QStandardItemModel>
-
-QT_BEGIN_NAMESPACE
-class QComboBox;
-class QLabel;
-class QPushButton;
-QT_END_NAMESPACE
-
-namespace Debugger {
-namespace Internal {
-
-// -----------------------------------------------------------------------
-// DebuggerKitConfigWidget
-// -----------------------------------------------------------------------
-
-class DebuggerKitConfigWidget : public ProjectExplorer::KitConfigWidget
-{
- Q_OBJECT
-
-public:
- DebuggerKitConfigWidget(ProjectExplorer::Kit *workingCopy,
- const ProjectExplorer::KitInformation *ki);
- ~DebuggerKitConfigWidget() override;
-
- QString displayName() const override;
- QString toolTip() const override;
- void makeReadOnly() override;
- void refresh() override;
- QWidget *buttonWidget() const override;
- QWidget *mainWidget() const override;
-
-private:
- void manageDebuggers();
- void currentDebuggerChanged(int idx);
-
- QVariant currentId() const;
- void updateComboBox(const QVariant &id);
-
- bool m_isReadOnly;
- bool m_ignoreChanges = false;
- QComboBox *m_comboBox;
- QPushButton *m_manageButton;
-};
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp
index ccf6009d27..412d54b33c 100644
--- a/src/plugins/debugger/debuggerkitinformation.cpp
+++ b/src/plugins/debugger/debuggerkitinformation.cpp
@@ -27,17 +27,21 @@
#include "debuggeritemmanager.h"
#include "debuggeritem.h"
-#include "debuggerkitconfigwidget.h"
+
+#include <coreplugin/icore.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
+#include <QComboBox>
#include <QFileInfo>
+#include <QPushButton>
#include <utility>
using namespace ProjectExplorer;
@@ -46,19 +50,109 @@ using namespace Utils;
namespace Debugger {
// --------------------------------------------------------------------------
-// DebuggerKitInformation
+// DebuggerKitAspect
// --------------------------------------------------------------------------
-DebuggerKitInformation::DebuggerKitInformation()
+namespace Internal {
+
+class DebuggerKitAspectWidget : public KitAspectWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(Debugger::DebuggerKitAspect)
+
+public:
+ DebuggerKitAspectWidget(Kit *workingCopy, const KitAspect *ki)
+ : KitAspectWidget(workingCopy, ki)
+ {
+ m_comboBox = new QComboBox;
+ m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
+ m_comboBox->setEnabled(true);
+
+ refresh();
+ m_comboBox->setToolTip(ki->description());
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &DebuggerKitAspectWidget::currentDebuggerChanged);
+
+ m_manageButton = new QPushButton(KitAspectWidget::msgManage());
+ m_manageButton->setContentsMargins(0, 0, 0, 0);
+ connect(m_manageButton, &QAbstractButton::clicked,
+ this, &DebuggerKitAspectWidget::manageDebuggers);
+ }
+
+ ~DebuggerKitAspectWidget() override
+ {
+ delete m_comboBox;
+ delete m_manageButton;
+ }
+
+private:
+ QWidget *buttonWidget() const override { return m_manageButton; }
+ QWidget *mainWidget() const override { return m_comboBox; }
+
+ void makeReadOnly() override
+ {
+ m_manageButton->setEnabled(false);
+ m_comboBox->setEnabled(false);
+ }
+
+ void refresh() override
+ {
+ m_ignoreChanges = true;
+ m_comboBox->clear();
+ m_comboBox->addItem(tr("None"), QString());
+ for (const DebuggerItem &item : DebuggerItemManager::debuggers())
+ m_comboBox->addItem(item.displayName(), item.id());
+
+ const DebuggerItem *item = DebuggerKitAspect::debugger(m_kit);
+ updateComboBox(item ? item->id() : QVariant());
+ m_ignoreChanges = false;
+ }
+
+ void manageDebuggers()
+ {
+ Core::ICore::showOptionsDialog(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID,
+ buttonWidget());
+ }
+
+ void currentDebuggerChanged(int idx)
+ {
+ Q_UNUSED(idx);
+ if (m_ignoreChanges)
+ return;
+
+ int currentIndex = m_comboBox->currentIndex();
+ QVariant id = m_comboBox->itemData(currentIndex);
+ m_kit->setValue(DebuggerKitAspect::id(), id);
+ }
+
+ QVariant currentId() const { return m_comboBox->itemData(m_comboBox->currentIndex()); }
+
+ void updateComboBox(const QVariant &id)
+ {
+ for (int i = 0; i < m_comboBox->count(); ++i) {
+ if (id == m_comboBox->itemData(i)) {
+ m_comboBox->setCurrentIndex(i);
+ return;
+ }
+ }
+ m_comboBox->setCurrentIndex(0);
+ }
+
+ bool m_ignoreChanges = false;
+ QComboBox *m_comboBox;
+ QPushButton *m_manageButton;
+};
+} // namespace Internal
+
+DebuggerKitAspect::DebuggerKitAspect()
{
- setObjectName("DebuggerKitInformation");
- setId(DebuggerKitInformation::id());
+ setObjectName("DebuggerKitAspect");
+ setId(DebuggerKitAspect::id());
+ setDisplayName(tr("Debugger"));
+ setDescription(tr("The debugger to use for this kit."));
setPriority(28000);
}
-QVariant DebuggerKitInformation::defaultValue(const Kit *) const { return QVariant(); }
-
-void DebuggerKitInformation::setup(Kit *k)
+void DebuggerKitAspect::setup(Kit *k)
{
QTC_ASSERT(k, return);
@@ -75,9 +169,9 @@ void DebuggerKitInformation::setup(Kit *k)
// <value type="QString" key="Binary">auto</value>
// <value type="int" key="EngineType">4</value>
// </valuemap>
- const QVariant rawId = k->value(DebuggerKitInformation::id());
+ const QVariant rawId = k->value(DebuggerKitAspect::id());
- const Abi tcAbi = ToolChainKitInformation::targetAbi(k);
+ const Abi tcAbi = ToolChainKitAspect::targetAbi(k);
// Get the best of the available debugger matching the kit's toolchain.
// The general idea is to find an item that exactly matches what
@@ -124,7 +218,7 @@ void DebuggerKitInformation::setup(Kit *k)
}
} else {
// We have an executable path.
- FileName fileName = FileName::fromUserInput(binary);
+ FilePath fileName = FilePath::fromUserInput(binary);
if (item.command() == fileName) {
// And it's is the path of this item.
level = std::min(item.matchTarget(tcAbi), DebuggerItem::MatchesSomewhat);
@@ -143,17 +237,17 @@ void DebuggerKitInformation::setup(Kit *k)
}
// Use the best id we found, or an invalid one.
- k->setValue(DebuggerKitInformation::id(), bestLevel != DebuggerItem::DoesNotMatch ? bestItem.id() : QVariant());
+ k->setValue(DebuggerKitAspect::id(), bestLevel != DebuggerItem::DoesNotMatch ? bestItem.id() : QVariant());
}
// This handles the upgrade path from 2.8 to 3.0
-void DebuggerKitInformation::fix(Kit *k)
+void DebuggerKitAspect::fix(Kit *k)
{
QTC_ASSERT(k, return);
// This can be Id, binary path, but not "auto" anymore.
- const QVariant rawId = k->value(DebuggerKitInformation::id());
+ const QVariant rawId = k->value(DebuggerKitAspect::id());
if (rawId.isNull()) // No debugger set, that is fine.
return;
@@ -162,7 +256,7 @@ void DebuggerKitInformation::fix(Kit *k)
if (!DebuggerItemManager::findById(rawId)) {
qWarning("Unknown debugger id %s in kit %s",
qPrintable(rawId.toString()), qPrintable(k->displayName()));
- k->setValue(DebuggerKitInformation::id(), QVariant());
+ k->setValue(DebuggerKitAspect::id(), QVariant());
}
return; // All fine (now).
}
@@ -172,30 +266,30 @@ void DebuggerKitInformation::fix(Kit *k)
if (binary == "auto") {
// This should not happen as "auto" is handled by setup() already.
QTC_CHECK(false);
- k->setValue(DebuggerKitInformation::id(), QVariant());
+ k->setValue(DebuggerKitAspect::id(), QVariant());
return;
}
- FileName fileName = FileName::fromUserInput(binary);
+ FilePath fileName = FilePath::fromUserInput(binary);
const DebuggerItem *item = DebuggerItemManager::findByCommand(fileName);
if (!item) {
qWarning("Debugger command %s invalid in kit %s",
qPrintable(binary), qPrintable(k->displayName()));
- k->setValue(DebuggerKitInformation::id(), QVariant());
+ k->setValue(DebuggerKitAspect::id(), QVariant());
return;
}
- k->setValue(DebuggerKitInformation::id(), item->id());
+ k->setValue(DebuggerKitAspect::id(), item->id());
}
// Check the configuration errors and return a flag mask. Provide a quick check and
// a verbose one with a list of errors.
-DebuggerKitInformation::ConfigurationErrors DebuggerKitInformation::configurationErrors(const Kit *k)
+DebuggerKitAspect::ConfigurationErrors DebuggerKitAspect::configurationErrors(const Kit *k)
{
QTC_ASSERT(k, return NoDebugger);
- const DebuggerItem *item = DebuggerKitInformation::debugger(k);
+ const DebuggerItem *item = DebuggerKitAspect::debugger(k);
if (!item)
return NoDebugger;
@@ -209,10 +303,10 @@ DebuggerKitInformation::ConfigurationErrors DebuggerKitInformation::configuratio
else if (!fi.isExecutable())
result |= DebuggerNotExecutable;
- const Abi tcAbi = ToolChainKitInformation::targetAbi(k);
+ const Abi tcAbi = ToolChainKitAspect::targetAbi(k);
if (item->matchTarget(tcAbi) == DebuggerItem::DoesNotMatch) {
// currently restricting the check to desktop devices, may be extended to all device types
- const IDevice::ConstPtr device = DeviceKitInformation::device(k);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(k);
if (device && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
result |= DebuggerDoesNotMatch;
}
@@ -230,14 +324,14 @@ DebuggerKitInformation::ConfigurationErrors DebuggerKitInformation::configuratio
return result;
}
-const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit)
+const DebuggerItem *DebuggerKitAspect::debugger(const Kit *kit)
{
QTC_ASSERT(kit, return nullptr);
- const QVariant id = kit->value(DebuggerKitInformation::id());
+ const QVariant id = kit->value(DebuggerKitAspect::id());
return DebuggerItemManager::findById(id);
}
-Runnable DebuggerKitInformation::runnable(const Kit *kit)
+Runnable DebuggerKitAspect::runnable(const Kit *kit)
{
Runnable runnable;
if (const DebuggerItem *item = debugger(kit)) {
@@ -249,9 +343,9 @@ Runnable DebuggerKitInformation::runnable(const Kit *kit)
return runnable;
}
-QList<Task> DebuggerKitInformation::validateDebugger(const Kit *k)
+Tasks DebuggerKitAspect::validateDebugger(const Kit *k)
{
- QList<Task> result;
+ Tasks result;
const ConfigurationErrors errors = configurationErrors(k);
if (errors == NoConfigurationError)
@@ -263,35 +357,35 @@ QList<Task> DebuggerKitInformation::validateDebugger(const Kit *k)
const Core::Id id = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM;
if (errors & NoDebugger)
- result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id);
+ result << Task(Task::Warning, tr("No debugger set up."), FilePath(), -1, id);
if (errors & DebuggerNotFound)
result << Task(Task::Error, tr("Debugger \"%1\" not found.").arg(path),
- FileName(), -1, id);
+ FilePath(), -1, id);
if (errors & DebuggerNotExecutable)
- result << Task(Task::Error, tr("Debugger \"%1\" not executable.").arg(path), FileName(), -1, id);
+ result << Task(Task::Error, tr("Debugger \"%1\" not executable.").arg(path), FilePath(), -1, id);
if (errors & DebuggerNeedsAbsolutePath) {
const QString message =
tr("The debugger location must be given as an "
"absolute path (%1).").arg(path);
- result << Task(Task::Error, message, FileName(), -1, id);
+ result << Task(Task::Error, message, FilePath(), -1, id);
}
if (errors & DebuggerDoesNotMatch) {
const QString message = tr("The ABI of the selected debugger does not "
"match the toolchain ABI.");
- result << Task(Task::Warning, message, FileName(), -1, id);
+ result << Task(Task::Warning, message, FilePath(), -1, id);
}
return result;
}
-KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *DebuggerKitAspect::createConfigWidget(Kit *k) const
{
- return new Internal::DebuggerKitConfigWidget(k, this);
+ return new Internal::DebuggerKitAspectWidget(k, this);
}
-void DebuggerKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expander) const
+void DebuggerKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
QTC_ASSERT(kit, return);
expander->registerVariable("Debugger:Name", tr("Name of Debugger"),
@@ -322,19 +416,19 @@ void DebuggerKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expande
});
}
-KitInformation::ItemList DebuggerKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList DebuggerKitAspect::toUserOutput(const Kit *k) const
{
- return ItemList() << qMakePair(tr("Debugger"), displayString(k));
+ return {{tr("Debugger"), displayString(k)}};
}
-DebuggerEngineType DebuggerKitInformation::engineType(const Kit *k)
+DebuggerEngineType DebuggerKitAspect::engineType(const Kit *k)
{
const DebuggerItem *item = debugger(k);
QTC_ASSERT(item, return NoEngineType);
return item->engineType();
}
-QString DebuggerKitInformation::displayString(const Kit *k)
+QString DebuggerKitAspect::displayString(const Kit *k)
{
const DebuggerItem *item = debugger(k);
if (!item)
@@ -344,15 +438,15 @@ QString DebuggerKitInformation::displayString(const Kit *k)
return binary.isEmpty() ? tr("%1 <None>").arg(name) : tr("%1 using \"%2\"").arg(name, binary);
}
-void DebuggerKitInformation::setDebugger(Kit *k, const QVariant &id)
+void DebuggerKitAspect::setDebugger(Kit *k, const QVariant &id)
{
// Only register reasonably complete debuggers.
QTC_ASSERT(DebuggerItemManager::findById(id), return);
QTC_ASSERT(k, return);
- k->setValue(DebuggerKitInformation::id(), id);
+ k->setValue(DebuggerKitAspect::id(), id);
}
-Core::Id DebuggerKitInformation::id()
+Core::Id DebuggerKitAspect::id()
{
return "Debugger.Information";
}
diff --git a/src/plugins/debugger/debuggerkitinformation.h b/src/plugins/debugger/debuggerkitinformation.h
index 035f00dedf..3e5bfba1bb 100644
--- a/src/plugins/debugger/debuggerkitinformation.h
+++ b/src/plugins/debugger/debuggerkitinformation.h
@@ -34,17 +34,15 @@
namespace Debugger {
class DebuggerItem;
-class DEBUGGER_EXPORT DebuggerKitInformation : public ProjectExplorer::KitInformation
+class DEBUGGER_EXPORT DebuggerKitAspect : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- DebuggerKitInformation();
+ DebuggerKitAspect();
- QVariant defaultValue(const ProjectExplorer::Kit *k) const override;
-
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const override
- { return DebuggerKitInformation::validateDebugger(k); }
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const override
+ { return DebuggerKitAspect::validateDebugger(k); }
void setup(ProjectExplorer::Kit *k) override;
void fix(ProjectExplorer::Kit *k) override;
@@ -63,10 +61,10 @@ public:
};
Q_DECLARE_FLAGS(ConfigurationErrors, ConfigurationError)
- static QList<ProjectExplorer::Task> validateDebugger(const ProjectExplorer::Kit *k);
+ static ProjectExplorer::Tasks validateDebugger(const ProjectExplorer::Kit *k);
static ConfigurationErrors configurationErrors(const ProjectExplorer::Kit *k);
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const override;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const override;
void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override;
ItemList toUserOutput(const ProjectExplorer::Kit *k) const override;
diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp
index 598344bb25..82bb009cc2 100644
--- a/src/plugins/debugger/debuggermainwindow.cpp
+++ b/src/plugins/debugger/debuggermainwindow.cpp
@@ -161,6 +161,9 @@ public:
QList<QPointer<Perspective>> m_perspectives;
QSet<QString> m_persistentChangedDocks;
+
+ QHash<QString, QByteArray> m_lastPerspectiveStates;
+ QHash<QString, QByteArray> m_lastTypePerspectiveStates;
};
DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
@@ -169,14 +172,14 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent)
m_centralWidgetStack = new QStackedWidget;
m_statusLabel = new Utils::StatusLabel;
m_statusLabel->setProperty("panelwidget", true);
- m_statusLabel->setIndent(2 * QFontMetrics(q->font()).width(QChar('x')));
+ m_statusLabel->setIndent(2 * QFontMetrics(q->font()).horizontalAdvance(QChar('x')));
m_editorPlaceHolder = new EditorManagerPlaceHolder;
m_perspectiveChooser = new QComboBox;
m_perspectiveChooser->setObjectName("PerspectiveChooser");
m_perspectiveChooser->setProperty("panelwidget", true);
m_perspectiveChooser->setSizeAdjustPolicy(QComboBox::AdjustToContents);
- connect(m_perspectiveChooser, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_perspectiveChooser, QOverload<int>::of(&QComboBox::activated),
this, [this](int item) {
Perspective *perspective = Perspective::findPerspective(m_perspectiveChooser->itemData(item).toString());
QTC_ASSERT(perspective, return);
@@ -285,13 +288,12 @@ DebuggerMainWindow::DebuggerMainWindow()
cmd->setAttribute(Command::CA_Hide);
viewsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE);
- connect(ICore::instance(), &ICore::saveSettingsRequested, this, [this] {
+ connect(ICore::instance(), &ICore::saveSettingsRequested, this,
+ [this](ICore::SaveSettingsReason reason) {
// There's one saveSettings triggered after plugin loading intentionally.
// We do not want to save anything at that time.
- static bool firstOne = true;
- if (firstOne) {
+ if (reason == ICore::InitializationDone) {
qCDebug(perspectivesLog) << "FIRST SAVE SETTINGS REQUEST IGNORED";
- firstOne = false;
} else {
qCDebug(perspectivesLog) << "SAVING SETTINGS";
savePersistentSettings();
@@ -431,10 +433,11 @@ void DebuggerMainWindow::restorePersistentSettings()
qCDebug(perspectivesLog) << "RESTORE PERSISTENT";
QSettings *settings = ICore::settings();
settings->beginGroup(MAINWINDOW_KEY);
- const bool res = theMainWindow->restoreState(settings->value(STATE_KEY).toByteArray(),
- SettingsVersion);
- if (!res)
- qCDebug(perspectivesLog) << "NO READABLE PERSISTENT SETTINGS FOUND, ASSUMING NEW CLEAN SETTINGS";
+
+ const QHash<QString, QVariant> states = settings->value(STATE_KEY).toHash();
+ theMainWindow->d->m_lastTypePerspectiveStates.clear();
+ for (const QString &type : states.keys())
+ theMainWindow->d->m_lastTypePerspectiveStates.insert(type, states.value(type).toByteArray());
theMainWindow->setAutoHideTitleBars(settings->value(AUTOHIDE_TITLEBARS_KEY, true).toBool());
theMainWindow->showCentralWidget(settings->value(SHOW_CENTRALWIDGET_KEY, true).toBool());
@@ -497,10 +500,14 @@ void DebuggerMainWindow::savePersistentSettings()
theMainWindow->d->m_persistentChangedDocks = changedDocks;
qCDebug(perspectivesLog) << "CHANGED DOCKS:" << changedDocks;
+ QVariantHash states;
+ for (const QString &type : theMainWindow->d->m_lastTypePerspectiveStates.keys())
+ states.insert(type, QVariant::fromValue(theMainWindow->d->m_lastTypePerspectiveStates.value(type)));
+
QSettings *settings = ICore::settings();
settings->beginGroup(MAINWINDOW_KEY);
settings->setValue(CHANGED_DOCK_KEY, QStringList(changedDocks.toList()));
- settings->setValue(STATE_KEY, theMainWindow->saveState(SettingsVersion));
+ settings->setValue(STATE_KEY, states);
settings->setValue(AUTOHIDE_TITLEBARS_KEY, theMainWindow->autoHideTitleBars());
settings->setValue(SHOW_CENTRALWIDGET_KEY, theMainWindow->isCentralWidgetShown());
settings->endGroup();
@@ -634,7 +641,8 @@ void DebuggerMainWindowPrivate::updatePerspectiveChooserWidth()
if (index != -1) {
m_perspectiveChooser->setCurrentIndex(index);
- const int contentWidth = m_perspectiveChooser->fontMetrics().width(perspective->d->m_name);
+ const int contentWidth =
+ m_perspectiveChooser->fontMetrics().horizontalAdvance(perspective->d->m_name);
QStyleOptionComboBox option;
option.initFrom(m_perspectiveChooser);
const QSize sz(contentWidth, 1);
@@ -940,6 +948,13 @@ void PerspectivePrivate::restoreLayout()
<< (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER");
}
}
+
+ QByteArray state;
+ if (theMainWindow->d->m_lastTypePerspectiveStates.contains(settingsId()))
+ state = theMainWindow->d->m_lastTypePerspectiveStates.value(settingsId());
+ if (theMainWindow->d->m_lastPerspectiveStates.contains(m_id))
+ state = theMainWindow->d->m_lastPerspectiveStates.value(m_id);
+ theMainWindow->restoreState(state);
}
void PerspectivePrivate::saveLayout()
@@ -959,6 +974,8 @@ void PerspectivePrivate::saveLayout()
<< (active == op.visibleByDefault ? "DEFAULT USER" : "*** NON-DEFAULT USER");
}
}
+ theMainWindow->d->m_lastPerspectiveStates.insert(m_id, theMainWindow->saveState());
+ theMainWindow->d->m_lastTypePerspectiveStates.insert(settingsId(), theMainWindow->saveState());
}
QString PerspectivePrivate::settingsId() const
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 322a87277c..699ea751bd 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -28,7 +28,6 @@
#include "debuggeractions.h"
#include "debuggerinternalconstants.h"
#include "debuggercore.h"
-#include "debuggerkitconfigwidget.h"
#include "debuggerdialogs.h"
#include "debuggerengine.h"
#include "debuggericons.h"
@@ -396,6 +395,11 @@ namespace Internal {
const char DEBUGGER_START[] = "Debugger.Start";
+// Menu Groups
+const char MENU_GROUP_GENERAL[] = "Debugger.Group.General";
+const char MENU_GROUP_SPECIAL[] = "Debugger.Group.Special";
+const char MENU_GROUP_START_QML[] = "Debugger.Group.Start.Qml";
+
void addCdbOptionPages(QList<IOptionsPage*> *opts);
void addGdbOptionPages(QList<IOptionsPage*> *opts);
@@ -549,12 +553,12 @@ QWidget *addSearch(BaseTreeView *treeView)
static Kit::Predicate cdbPredicate(char wordWidth = 0)
{
return [wordWidth](const Kit *k) -> bool {
- if (DebuggerKitInformation::engineType(k) != CdbEngineType
- || DebuggerKitInformation::configurationErrors(k)) {
+ if (DebuggerKitAspect::engineType(k) != CdbEngineType
+ || DebuggerKitAspect::configurationErrors(k)) {
return false;
}
if (wordWidth)
- return ToolChainKitInformation::targetAbi(k).wordWidth() == wordWidth;
+ return ToolChainKitAspect::targetAbi(k).wordWidth() == wordWidth;
return true;
};
}
@@ -670,7 +674,7 @@ public:
message = tr("0x%1 hit").arg(data.address, 0, 16);
} else {
//: Message tracepoint: %1 file, %2 line %3 function hit.
- message = tr("%1:%2 %3() hit").arg(FileName::fromString(data.fileName).fileName()).
+ message = tr("%1:%2 %3() hit").arg(FilePath::fromString(data.fileName).fileName()).
arg(data.lineNumber).
arg(cppFunctionAt(data.fileName, data.lineNumber));
}
@@ -770,6 +774,8 @@ public:
DebugInfoTaskHandler m_debugInfoTaskHandler;
Perspective m_perspective{Constants::PRESET_PERSPECTIVE_ID, tr("Debugger")};
+
+ DebuggerKitAspect debuggerKitAspect;
};
DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin)
@@ -801,7 +807,7 @@ static QString msgParameterMissing(const QString &a)
return DebuggerPlugin::tr("Option \"%1\" is missing the parameter.").arg(a);
}
-static Kit *guessKitFromAbis(const QList<Abi> &abis)
+static Kit *guessKitFromAbis(const Abis &abis)
{
Kit *kit = nullptr;
@@ -809,14 +815,14 @@ static Kit *guessKitFromAbis(const QList<Abi> &abis)
if (!abis.isEmpty()) {
// Try exact abis.
kit = KitManager::kit([abis](const Kit *k) {
- const Abi tcAbi = ToolChainKitInformation::targetAbi(k);
- return abis.contains(tcAbi) && !DebuggerKitInformation::configurationErrors(k);
+ const Abi tcAbi = ToolChainKitAspect::targetAbi(k);
+ return abis.contains(tcAbi) && !DebuggerKitAspect::configurationErrors(k);
});
if (!kit) {
// Or something compatible.
kit = KitManager::kit([abis](const Kit *k) {
- const Abi tcAbi = ToolChainKitInformation::targetAbi(k);
- return !DebuggerKitInformation::configurationErrors(k)
+ const Abi tcAbi = ToolChainKitAspect::targetAbi(k);
+ return !DebuggerKitAspect::configurationErrors(k)
&& Utils::contains(abis, [tcAbi](const Abi &a) { return a.isCompatibleWith(tcAbi); });
});
}
@@ -879,11 +885,11 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
}
}
if (!kit)
- kit = guessKitFromAbis(Abi::abisOfBinary(FileName::fromString(executable)));
+ kit = guessKitFromAbis(Abi::abisOfBinary(FilePath::fromString(executable)));
- IDevice::ConstPtr device = DeviceKitInformation::device(kit);
- auto runControl = new RunControl(device, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, kit);
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setKit(kit);
+ auto debugger = new DebuggerRunTool(runControl);
debugger->setInferiorExecutable(executable);
if (pid) {
debugger->setStartMode(AttachExternal);
@@ -924,8 +930,9 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
return false;
}
qint64 pid = it->section(':', 1, 1).toULongLong();
- auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, findUniversalCdbKit());
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setKit(findUniversalCdbKit());
+ auto debugger = new DebuggerRunTool(runControl);
debugger->setStartMode(AttachCrashedExternal);
debugger->setCrashParameter(it->section(':', 0, 0));
debugger->setAttachPid(pid);
@@ -1006,8 +1013,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
QAction *act;
// Populate Windows->Views menu with standard actions.
- Context debugcontext(Constants::C_DEBUGMODE);
-
act = new QAction(tr("Memory..."), this);
act->setVisible(false);
act->setEnabled(false);
@@ -1023,9 +1028,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_debuggerSettings = new DebuggerSettings;
m_debuggerSettings->readSettings();
- const Context cppDebuggercontext(C_CPPDEBUGGER);
- const Context qmljsDebuggercontext(C_QMLDEBUGGER);
-
const auto addLabel = [](QWidget *widget, const QString &text) {
auto vbox = qobject_cast<QVBoxLayout *>(widget->layout());
QTC_ASSERT(vbox, return);
@@ -1101,15 +1103,16 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
// "Start Debugging" sub-menu
// groups:
// G_DEFAULT_ONE
- // G_START_LOCAL
- // G_START_REMOTE
- // G_START_QML
+ // MENU_GROUP_START_LOCAL
+ // MENU_GROUP_START_REMOTE
+ // MENU_GROUP_START_QML
ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING);
const QKeySequence startShortcut(useMacShortcuts ? tr("Ctrl+Y") : tr("F5"));
- cmd = ActionManager::registerAction(&m_visibleStartAction, Constants::DEBUG);
+ cmd = ActionManager::registerAction(&m_visibleStartAction, "Debugger.Debug");
+
cmd->setDescription(tr("Start Debugging or Continue"));
cmd->setAttribute(Command::CA_UpdateText);
cmd->setAttribute(Command::CA_UpdateIcon);
@@ -1127,7 +1130,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_visibleStartAction.setAction(&m_startAction);
m_visibleStartAction.setObjectName("Debug"); // used for UI introduction
- ModeManager::addAction(&m_visibleStartAction, Constants::P_ACTION_DEBUG);
+ ModeManager::addAction(&m_visibleStartAction, /*priority*/ 90);
m_undisturbableAction.setIcon(interruptIcon(false));
m_undisturbableAction.setEnabled(false);
@@ -1140,40 +1143,40 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
cmd = ActionManager::registerAction(&m_attachToRunningApplication,
"Debugger.AttachToRemoteProcess");
cmd->setDescription(tr("Attach to Running Application"));
- mstart->addAction(cmd, G_GENERAL);
+ mstart->addAction(cmd, MENU_GROUP_GENERAL);
cmd = ActionManager::registerAction(&m_attachToUnstartedApplication,
"Debugger.AttachToUnstartedProcess");
cmd->setDescription(tr("Attach to Unstarted Application"));
- mstart->addAction(cmd, G_GENERAL);
+ mstart->addAction(cmd, MENU_GROUP_GENERAL);
cmd = ActionManager::registerAction(&m_startAndDebugApplicationAction,
"Debugger.StartAndDebugApplication");
cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, G_GENERAL);
+ mstart->addAction(cmd, MENU_GROUP_GENERAL);
cmd = ActionManager::registerAction(&m_attachToCoreAction,
"Debugger.AttachCore");
cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, Constants::G_GENERAL);
+ mstart->addAction(cmd, MENU_GROUP_GENERAL);
cmd = ActionManager::registerAction(&m_attachToRemoteServerAction,
"Debugger.AttachToRemoteServer");
cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, Constants::G_SPECIAL);
+ mstart->addAction(cmd, MENU_GROUP_SPECIAL);
if (HostOsInfo::isWindowsHost()) {
cmd = ActionManager::registerAction(&m_startRemoteCdbAction,
"Debugger.AttachRemoteCdb");
cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, Constants::G_SPECIAL);
+ mstart->addAction(cmd, MENU_GROUP_SPECIAL);
}
- mstart->addSeparator(Context(CC::C_GLOBAL), Constants::G_START_QML);
+ mstart->addSeparator(Context(CC::C_GLOBAL), MENU_GROUP_START_QML);
cmd = ActionManager::registerAction(&m_attachToQmlPortAction, "Debugger.AttachToQmlPort");
cmd->setAttribute(Command::CA_Hide);
- mstart->addAction(cmd, Constants::G_START_QML);
+ mstart->addAction(cmd, MENU_GROUP_START_QML);
act = new QAction(tr("Detach Debugger"), this);
act->setEnabled(false);
@@ -1199,7 +1202,9 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
touchBar->addAction(cmd);
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
- act = new QAction(Icons::DEBUG_EXIT_SMALL.icon(), tr("Stop Debugger"), this);
+ const QIcon sidebarStopIcon = Icon::sideBarIcon(Icons::STOP, Icons::STOP_FLAT);
+ const QIcon stopIcon = Icon::combinedIcon({Icons::DEBUG_EXIT_SMALL.icon(), sidebarStopIcon});
+ act = new QAction(stopIcon, tr("Stop Debugger"), this);
act->setEnabled(false);
cmd = ActionManager::registerAction(act, Constants::STOP);
cmd->setTouchBarIcon(Icons::MACOS_TOUCHBAR_DEBUG_EXIT.icon());
@@ -1590,13 +1595,13 @@ void DebuggerPluginPrivate::attachCore()
setConfigValue("LastExternalStartScript", dlg.overrideStartScript());
setConfigValue("LastForceLocalCoreFile", dlg.forcesLocalCoreFile());
- IDevice::ConstPtr device = DeviceKitInformation::device(dlg.kit());
- auto runControl = new RunControl(device, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, dlg.kit());
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setKit(dlg.kit());
+ runControl->setDisplayName(tr("Core file \"%1\"")
+ .arg(dlg.useLocalCoreFile() ? dlg.localCoreFile() : dlg.remoteCoreFile()));
+ auto debugger = new DebuggerRunTool(runControl);
debugger->setInferiorExecutable(dlg.symbolFile());
debugger->setCoreFileName(dlg.localCoreFile());
- debugger->setRunControlName(tr("Core file \"%1\"")
- .arg(dlg.useLocalCoreFile() ? dlg.localCoreFile() : dlg.remoteCoreFile()));
debugger->setStartMode(AttachCore);
debugger->setCloseMode(DetachAtClose);
debugger->setOverrideStartScript(dlg.overrideStartScript());
@@ -1618,9 +1623,9 @@ void DebuggerPluginPrivate::startRemoteCdbSession()
return;
setConfigValue(connectionKey, dlg.connection());
- IDevice::ConstPtr device = DeviceKitInformation::device(kit);
- auto runControl = new RunControl(device, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, kit);
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setKit(kit);
+ auto debugger = new DebuggerRunTool(runControl);
debugger->setStartMode(AttachToRemoteServer);
debugger->setCloseMode(KillAtClose);
debugger->setRemoteChannel(dlg.connection());
@@ -1630,17 +1635,16 @@ void DebuggerPluginPrivate::startRemoteCdbSession()
class RemoteAttachRunner : public DebuggerRunTool
{
public:
- RemoteAttachRunner(RunControl *runControl, Kit *kit, int pid)
- : DebuggerRunTool(runControl, kit)
+ RemoteAttachRunner(RunControl *runControl, int pid)
+ : DebuggerRunTool(runControl)
{
- IDevice::ConstPtr device = DeviceKitInformation::device(kit);
setId("AttachToRunningProcess");
setUsePortsGatherer(true, false);
- portsGatherer()->setDevice(device);
+ portsGatherer()->setDevice(runControl->device());
auto gdbServer = new GdbServerRunner(runControl, portsGatherer());
gdbServer->setUseMulti(false);
- gdbServer->setDevice(device);
+ gdbServer->setDevice(runControl->device());
gdbServer->setAttachPid(ProcessHandle(pid));
addStartDependency(gdbServer);
@@ -1669,7 +1673,7 @@ void DebuggerPluginPrivate::attachToRunningApplication()
dlg->setAttribute(Qt::WA_DeleteOnClose);
Kit *kit = kitChooser->currentKit();
QTC_ASSERT(kit, return);
- IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return);
DeviceProcessItem process = dlg->currentProcess();
@@ -1677,8 +1681,11 @@ void DebuggerPluginPrivate::attachToRunningApplication()
if (device->type() == PE::DESKTOP_DEVICE_TYPE) {
attachToRunningProcess(kit, process, false);
} else {
- auto runControl = new RunControl(device, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new RemoteAttachRunner(runControl, kit, process.pid);
+ 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, process.pid);
debugger->startRunControl();
}
}
@@ -1706,14 +1713,14 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
DeviceProcessItem process, bool contAfterAttach)
{
QTC_ASSERT(kit, return nullptr);
- IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return nullptr);
if (process.pid == 0) {
AsynchronousMessageBox::warning(tr("Warning"), tr("Cannot attach to process with PID 0"));
return nullptr;
}
- const Abi tcAbi = ToolChainKitInformation::targetAbi(kit);
+ const Abi tcAbi = ToolChainKitAspect::targetAbi(kit);
const bool isWindows = (tcAbi.os() == Abi::WindowsOS);
if (isWindows && isWinProcessBeingDebugged(process.pid)) {
AsynchronousMessageBox::warning(
@@ -1730,10 +1737,12 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
return nullptr;
}
- auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, kit);
+ 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 DebuggerRunTool(runControl);
debugger->setAttachPid(ProcessHandle(process.pid));
- debugger->setRunControlName(tr("Process %1").arg(process.pid));
debugger->setInferiorExecutable(process.exe);
debugger->setInferiorDevice(device);
debugger->setStartMode(AttachExternal);
@@ -1748,14 +1757,11 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
void DebuggerPlugin::attachExternalApplication(RunControl *rc)
{
ProcessHandle pid = rc->applicationProcessHandle();
- RunConfiguration *runConfig = rc->runConfiguration();
- QTC_ASSERT(runConfig, return);
- Target *target = runConfig->target();
- QTC_ASSERT(target, return);
- auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, target->kit(), false);
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setTarget(rc->target());
+ runControl->setDisplayName(tr("Process %1").arg(pid.pid()));
+ auto debugger = new DebuggerRunTool(runControl);
debugger->setAttachPid(pid);
- debugger->setRunControlName(tr("Process %1").arg(pid.pid()));
debugger->setStartMode(AttachExternal);
debugger->setCloseMode(DetachAtClose);
debugger->startRunControl();
@@ -1808,11 +1814,12 @@ void DebuggerPluginPrivate::attachToQmlPort()
setConfigValue("LastQmlServerPort", dlg.port());
setConfigValue("LastProfile", kit->id().toSetting());
- IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return);
- auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(runControl, kit);
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setKit(kit);
+ auto debugger = new DebuggerRunTool(runControl);
QUrl qmlServer = device->toolControlChannel(IDevice::QmlControlChannel);
qmlServer.setPort(dlg.port());
@@ -2084,7 +2091,7 @@ void DebuggerPluginPrivate::extensionsInitialized()
if (runnable.device && runnable.device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return true;
- if (DeviceTypeKitInformation::deviceTypeId(runConfig->target()->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(runConfig->target()->kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return true;
@@ -2254,15 +2261,13 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
// Menu groups
ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING);
- mstart->appendGroup(Constants::G_GENERAL);
- mstart->appendGroup(Constants::G_SPECIAL);
- mstart->appendGroup(Constants::G_START_QML);
+ mstart->appendGroup(MENU_GROUP_GENERAL);
+ mstart->appendGroup(MENU_GROUP_SPECIAL);
+ mstart->appendGroup(MENU_GROUP_START_QML);
// Separators
- mstart->addSeparator(Constants::G_GENERAL);
- mstart->addSeparator(Constants::G_SPECIAL);
-
- KitManager::registerKitInformation<DebuggerKitInformation>();
+ mstart->addSeparator(MENU_GROUP_GENERAL);
+ mstart->addSeparator(MENU_GROUP_SPECIAL);
// Task integration.
//: Category under which Analyzer tasks are listed in Issues view
@@ -2458,7 +2463,7 @@ void DebuggerUnitTests::initTestCase()
// const QList<Kit *> allKits = KitManager::kits();
// if (allKits.count() != 1)
// QSKIP("This test requires exactly one kit to be present");
-// const ToolChain * const toolchain = ToolChainKitInformation::toolChain(allKits.first());
+// const ToolChain * const toolchain = ToolChainKitAspect::toolChain(allKits.first());
// if (!toolchain)
// QSKIP("This test requires that there is a kit with a toolchain.");
// bool hasClangExecutable;
@@ -2497,7 +2502,8 @@ void DebuggerUnitTests::testStateMachine()
RunConfiguration *rc = t->activeRunConfiguration();
QVERIFY(rc);
- auto runControl = new RunControl(rc, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setRunConfiguration(rc);
auto debugger = new DebuggerRunTool(runControl);
debugger->setInferior(rc->runnable());
@@ -2617,8 +2623,8 @@ void DebuggerUnitTests::testDebuggerMatching()
auto expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
- QList<Abi> debuggerAbis;
- foreach (const QString &abi, debugger)
+ Abis debuggerAbis;
+ for (const QString &abi : qAsConst(debugger))
debuggerAbis << Abi::fromString(abi);
DebuggerItem item;
@@ -2631,15 +2637,14 @@ void DebuggerUnitTests::testDebuggerMatching()
QCOMPARE(expectedLevel, level);
}
-
-QList<QObject *> DebuggerPlugin::createTestObjects() const
+QVector<QObject *> DebuggerPlugin::createTestObjects() const
{
return {new DebuggerUnitTests};
}
#else // ^-- if WITH_TESTS else --v
-QList<QObject *> DebuggerPlugin::createTestObjects() const
+QVector<QObject *> DebuggerPlugin::createTestObjects() const
{
return {};
}
diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h
index 2ecde571dd..45050f7c4d 100644
--- a/src/plugins/debugger/debuggerplugin.h
+++ b/src/plugins/debugger/debuggerplugin.h
@@ -59,7 +59,7 @@ private:
// Called from GammaRayIntegration
Q_SLOT void getEnginesState(QByteArray *json) const;
- QList<QObject *> createTestObjects() const override;
+ QVector<QObject *> createTestObjects() const override;
};
} // namespace Internal
diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
index bd4b09060f..161c755d10 100644
--- a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
+++ b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp
@@ -121,7 +121,7 @@ DebuggerRunConfigWidget::DebuggerRunConfigWidget(DebuggerRunConfigurationAspect
this, &DebuggerRunConfigWidget::useQmlDebuggerClicked);
connect(m_useCppDebugger, &QAbstractButton::clicked,
this, &DebuggerRunConfigWidget::useCppDebuggerClicked);
- connect(m_debugServerPort, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_debugServerPort, QOverload<int>::of(&QSpinBox::valueChanged),
this, &DebuggerRunConfigWidget::qmlDebugServerPortChanged);
connect(m_useMultiProcess, &QAbstractButton::toggled,
this, &DebuggerRunConfigWidget::useMultiProcessToggled);
@@ -260,11 +260,6 @@ uint DebuggerRunConfigurationAspect::qmlDebugServerPort() const
return d.qmlDebugServerPort;
}
-void DebuggerRunConfigurationAspect::setQmllDebugServerPort(uint port)
-{
- d.qmlDebugServerPort = port;
-}
-
bool DebuggerRunConfigurationAspect::useMultiProcess() const
{
return d.useMultiProcess;
@@ -278,7 +273,7 @@ void DebuggerRunConfigurationAspect::setUseMultiProcess(bool value)
bool DebuggerRunConfigurationAspect::isQmlDebuggingSpinboxSuppressed() const
{
Kit *k = m_target->kit();
- IDevice::ConstPtr dev = DeviceKitInformation::device(k);
+ IDevice::ConstPtr dev = DeviceKitAspect::device(k);
if (dev.isNull())
return false;
return dev->canAutoDetectPorts();
diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.h b/src/plugins/debugger/debuggerrunconfigurationaspect.h
index a361f234c4..299b7c1182 100644
--- a/src/plugins/debugger/debuggerrunconfigurationaspect.h
+++ b/src/plugins/debugger/debuggerrunconfigurationaspect.h
@@ -45,7 +45,10 @@ class DEBUGGER_EXPORT DebuggerRunConfigurationAspectData
public:
DebuggerLanguageStatus useCppDebugger = AutoEnabledLanguage;
DebuggerLanguageStatus useQmlDebugger = AutoEnabledLanguage;
- uint qmlDebugServerPort = Constants::QML_DEFAULT_DEBUG_SERVER_PORT;
+
+ const uint QML_DEFAULT_DEBUG_SERVER_PORT = 3768;
+ uint qmlDebugServerPort = QML_DEFAULT_DEBUG_SERVER_PORT;
+
bool useMultiProcess = false;
};
@@ -64,7 +67,6 @@ public:
bool useQmlDebugger() const;
void setUseQmlDebugger(bool value);
uint qmlDebugServerPort() const;
- void setQmllDebugServerPort(uint port);
bool useMultiProcess() const;
void setUseMultiProcess(bool on);
bool isQmlDebuggingSpinboxSuppressed() const;
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index ca76e8cfe1..f68d637e1f 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -31,6 +31,7 @@
#include "debuggeractions.h"
#include "debuggercore.h"
#include "debuggerengine.h"
+#include "debuggerinternalconstants.h"
#include "debuggerkitinformation.h"
#include "debuggerplugin.h"
#include "debuggerrunconfigurationaspect.h"
@@ -97,8 +98,8 @@ class LocalProcessRunner : public RunWorker
Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::LocalProcessRunner)
public:
- LocalProcessRunner(DebuggerRunTool *runTool, const Runnable &runnable)
- : RunWorker(runTool->runControl()), m_runTool(runTool), m_runnable(runnable)
+ LocalProcessRunner(DebuggerRunTool *runTool, const CommandLine &command)
+ : RunWorker(runTool->runControl()), m_runTool(runTool), m_command(command)
{
connect(&m_proc, &QProcess::errorOccurred,
this, &LocalProcessRunner::handleError);
@@ -112,7 +113,7 @@ public:
void start() override
{
- m_proc.setCommand(m_runnable.executable, m_runnable.commandLineArguments);
+ m_proc.setCommand(m_command);
m_proc.start();
}
@@ -180,7 +181,7 @@ public:
}
QPointer<DebuggerRunTool> m_runTool;
- Runnable m_runnable;
+ CommandLine m_command;
Utils::QtcProcess m_proc;
};
@@ -310,7 +311,7 @@ void DebuggerRunTool::setAttachPid(qint64 pid)
m_runParameters.attachPID = ProcessHandle(pid);
}
-void DebuggerRunTool::setSysRoot(const Utils::FileName &sysRoot)
+void DebuggerRunTool::setSysRoot(const Utils::FilePath &sysRoot)
{
m_runParameters.sysRoot = sysRoot;
}
@@ -399,14 +400,12 @@ void DebuggerRunTool::setCommandsForReset(const QString &commands)
m_runParameters.commandsForReset = commands;
}
-void DebuggerRunTool::setServerStartScript(const QString &serverStartScript)
+void DebuggerRunTool::setServerStartScript(const FilePath &serverStartScript)
{
if (!serverStartScript.isEmpty()) {
// Provide script information about the environment
- Runnable serverStarter;
- serverStarter.executable = serverStartScript;
- QtcProcess::addArg(&serverStarter.commandLineArguments, m_runParameters.inferior.executable);
- QtcProcess::addArg(&serverStarter.commandLineArguments, m_runParameters.remoteChannel);
+ CommandLine serverStarter(serverStartScript, {});
+ serverStarter.addArgs({m_runParameters.inferior.executable, m_runParameters.remoteChannel});
addStartDependency(new LocalProcessRunner(this, serverStarter));
}
}
@@ -516,15 +515,15 @@ void DebuggerRunTool::addExpectedSignal(const QString &signal)
m_runParameters.expectedSignals.append(signal);
}
-void DebuggerRunTool::addSearchDirectory(const Utils::FileName &dir)
+void DebuggerRunTool::addSearchDirectory(const Utils::FilePath &dir)
{
m_runParameters.additionalSearchDirectories.append(dir);
}
void DebuggerRunTool::start()
{
- TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO);
- TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_RUNTIME);
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO);
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_DEBUGGER_RUNTIME);
if (d->portsGatherer) {
setRemoteChannel(d->portsGatherer->gdbServer());
@@ -648,7 +647,8 @@ void DebuggerRunTool::start()
connect(m_engine, &DebuggerEngine::attachToCoreRequested, this, [this](const QString &coreFile) {
auto runConfig = runControl()->runConfiguration();
QTC_ASSERT(runConfig, return);
- auto rc = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto rc = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ rc->setRunConfiguration(runConfig);
auto name = QString(tr("%1 - Snapshot %2").arg(runControl()->displayName()).arg(++d->snapshotCounter));
auto debugger = new DebuggerRunTool(rc);
debugger->setStartMode(AttachCore);
@@ -884,7 +884,7 @@ Internal::TerminalRunner *DebuggerRunTool::terminalRunner() const
return d->terminalRunner;
}
-DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTerminal)
+DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerminal)
: RunWorker(runControl), d(new DebuggerRunToolPrivate)
{
setId("DebuggerRunTool");
@@ -897,8 +897,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer
d->runId = QString::number(++toolRunCount);
- RunConfiguration *runConfig = runControl->runConfiguration();
-
runControl->setIcon(ProjectExplorer::Icons::DEBUG_START_SMALL_TOOLBAR);
runControl->setPromptToStop([](bool *optionalPrompt) {
return RunControl::showPromptToStopDialog(
@@ -910,27 +908,25 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer
QString(), QString(), optionalPrompt);
});
- if (runConfig) {
- m_runParameters.displayName = runConfig->displayName();
- if (auto symbolsAspect = runConfig->aspect<SymbolFileAspect>())
- m_runParameters.symbolFile = symbolsAspect->value();
- if (auto terminalAspect = runConfig->aspect<TerminalAspect>())
- m_runParameters.useTerminal = terminalAspect->useTerminal();
- }
+ m_runParameters.displayName = runControl->displayName();
- if (runConfig && !kit)
- kit = runConfig->target()->kit();
+ if (auto symbolsAspect = runControl->aspect<SymbolFileAspect>())
+ m_runParameters.symbolFile = symbolsAspect->value();
+ if (auto terminalAspect = runControl->aspect<TerminalAspect>())
+ m_runParameters.useTerminal = terminalAspect->useTerminal();
+
+ Kit *kit = runControl->kit();
QTC_ASSERT(kit, return);
- m_runParameters.sysRoot = SysRootKitInformation::sysRoot(kit);
+ m_runParameters.sysRoot = SysRootKitAspect::sysRoot(kit);
m_runParameters.macroExpander = kit->macroExpander();
- m_runParameters.debugger = DebuggerKitInformation::runnable(kit);
- m_runParameters.cppEngineType = DebuggerKitInformation::engineType(kit);
+ m_runParameters.debugger = DebuggerKitAspect::runnable(kit);
+ m_runParameters.cppEngineType = DebuggerKitAspect::engineType(kit);
- if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit))
+ if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit))
m_runParameters.qtPackageSourceLocation = qtVersion->qtPackageSourcePath().toString();
- if (auto aspect = runConfig ? runConfig->aspect<DebuggerRunConfigurationAspect>() : nullptr) {
+ if (auto aspect = runControl->aspect<DebuggerRunConfigurationAspect>()) {
if (!aspect->useCppDebugger())
m_runParameters.cppEngineType = NoEngineType;
m_runParameters.isQmlDebugging = aspect->useQmlDebugger();
@@ -941,19 +937,18 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer
// Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
m_runParameters.inferior.workingDirectory =
FileUtils::normalizePathName(m_runParameters.inferior.workingDirectory);
- setUseTerminal(allowTerminal && m_runParameters.useTerminal);
+ setUseTerminal(allowTerminal == DoAllowTerminal && m_runParameters.useTerminal);
const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH");
if (!envBinary.isEmpty())
m_runParameters.debugger.executable = QString::fromLocal8Bit(envBinary);
- Project *project = runConfig ? runConfig->target()->project() : nullptr;
- if (project) {
+ if (Project *project = runControl->project()) {
m_runParameters.projectSourceDirectory = project->projectDirectory();
m_runParameters.projectSourceFiles = project->files(Project::SourceFiles);
}
- m_runParameters.toolChainAbi = ToolChainKitInformation::targetAbi(kit);
+ m_runParameters.toolChainAbi = ToolChainKitAspect::targetAbi(kit);
bool ok = false;
int nativeMixedOverride = qgetenv("QTC_DEBUGGER_NATIVE_MIXED").toInt(&ok);
@@ -962,12 +957,13 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer
// This will only be shown in some cases, but we don't want to access
// the kit at that time anymore.
- const QList<Task> tasks = DebuggerKitInformation::validateDebugger(kit);
+ const Tasks tasks = DebuggerKitAspect::validateDebugger(kit);
for (const Task &t : tasks) {
if (t.type != Task::Warning)
m_runParameters.validationErrors.append(t.description);
}
+ RunConfiguration *runConfig = runControl->runConfiguration();
if (runConfig && runConfig->property("supportsDebugger").toBool()) {
const QString mainScript = runConfig->property("mainScript").toString();
const QString interpreter = runConfig->property("interpreter").toString();
@@ -1015,6 +1011,8 @@ void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout)
if (channel == ConsoleOutput)
debuggerConsole()->printItem(ConsoleItem::DefaultType, msg);
+ QTC_ASSERT(m_engine, qDebug() << msg; return);
+
m_engine->showMessage(msg, channel, timeout);
if (m_engine2)
m_engine->showMessage(msg, channel, timeout);
diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h
index cc4a1f191b..f5512dd991 100644
--- a/src/plugins/debugger/debuggerruncontrol.h
+++ b/src/plugins/debugger/debuggerruncontrol.h
@@ -47,9 +47,9 @@ class DEBUGGER_EXPORT DebuggerRunTool : public ProjectExplorer::RunWorker
Q_OBJECT
public:
+ enum AllowTerminal { DoAllowTerminal, DoNotAllowTerminal };
explicit DebuggerRunTool(ProjectExplorer::RunControl *runControl,
- ProjectExplorer::Kit *kit = nullptr,
- bool allowTerminal = true);
+ AllowTerminal allowTerminal = DoAllowTerminal);
~DebuggerRunTool() override;
void startRunControl();
@@ -84,7 +84,7 @@ public:
void setCrashParameter(const QString &event);
void addExpectedSignal(const QString &signal);
- void addSearchDirectory(const Utils::FileName &dir);
+ void addSearchDirectory(const Utils::FilePath &dir);
void setStartMode(DebuggerStartMode startMode);
void setCloseMode(DebuggerCloseMode closeMode);
@@ -92,7 +92,7 @@ public:
void setAttachPid(Utils::ProcessHandle pid);
void setAttachPid(qint64 pid);
- void setSysRoot(const Utils::FileName &sysRoot);
+ void setSysRoot(const Utils::FilePath &sysRoot);
void setSymbolFile(const QString &symbolFile);
void setRemoteChannel(const QString &channel);
void setRemoteChannel(const QString &host, int port);
@@ -110,7 +110,7 @@ public:
void setCommandsAfterConnect(const QString &commands);
void setCommandsForReset(const QString &commands);
- void setServerStartScript(const QString &serverStartScript);
+ void setServerStartScript(const Utils::FilePath &serverStartScript);
void setDebugInfoLocation(const QString &debugInfoLocation);
void setQmlServer(const QUrl &qmlServer);
diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
index 5812763fc4..8652ff10f8 100644
--- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
+++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
@@ -294,7 +294,7 @@ QString DebuggerSourcePathMappingWidget::editSourceField() const
QString DebuggerSourcePathMappingWidget::editTargetField() const
{
- return m_targetChooser->path();
+ return m_targetChooser->rawPath();
}
void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m)
@@ -401,7 +401,7 @@ void DebuggerSourcePathMappingWidget::slotEditTargetFieldChanged()
}
// Find Qt installation by running qmake
-static QString findQtInstallPath(const FileName &qmakePath)
+static QString findQtInstallPath(const FilePath &qmakePath)
{
if (qmakePath.isEmpty())
return QString();
@@ -438,7 +438,7 @@ DebuggerSourcePathMappingWidget::SourcePathMap
DebuggerSourcePathMappingWidget::mergePlatformQtPath(const DebuggerRunParameters &sp,
const SourcePathMap &in)
{
- const FileName qmake = BuildableHelperLibrary::findSystemQt(sp.inferior.environment);
+ const FilePath qmake = BuildableHelperLibrary::findSystemQt(sp.inferior.environment);
// FIXME: Get this from the profile?
// We could query the QtVersion for this information directly, but then we
// will need to add a dependency on QtSupport to the debugger.
diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp
index 6f23a9df62..2ad12ff682 100644
--- a/src/plugins/debugger/debuggertooltipmanager.cpp
+++ b/src/plugins/debugger/debuggertooltipmanager.cpp
@@ -624,15 +624,10 @@ void DebuggerToolTipWidget::computeSize()
// Add a bit of space to account for tooltip border, and not
// touch the border of the screen.
QPoint pos(x(), y());
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
auto screen = QGuiApplication::screenAt(pos);
if (!screen)
screen = QGuiApplication::primaryScreen();
QRect desktopRect = screen->availableGeometry();
-#else
- QTC_ASSERT(QApplication::desktop(), return);
- QRect desktopRect = QApplication::desktop()->availableGeometry();
-#endif
const int maxWidth = desktopRect.right() - pos.x() - 5 - 5;
const int maxHeight = desktopRect.bottom() - pos.y() - 5 - 5;
@@ -726,8 +721,8 @@ DebuggerToolTipContext::DebuggerToolTipContext()
static bool filesMatch(const QString &file1, const QString &file2)
{
- return FileName::fromString(QFileInfo(file1).canonicalFilePath())
- == FileName::fromString(QFileInfo(file2).canonicalFilePath());
+ return FilePath::fromString(QFileInfo(file1).canonicalFilePath())
+ == FilePath::fromString(QFileInfo(file2).canonicalFilePath());
}
bool DebuggerToolTipContext::matchesFrame(const StackFrame &frame) const
diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp
index 8e65cec051..d8a083b8d5 100644
--- a/src/plugins/debugger/disassembleragent.cpp
+++ b/src/plugins/debugger/disassembleragent.cpp
@@ -66,7 +66,7 @@ class DisassemblerBreakpointMarker : public TextMark
{
public:
DisassemblerBreakpointMarker(const Breakpoint &bp, int lineNumber)
- : TextMark(Utils::FileName(), lineNumber, Constants::TEXT_MARK_CATEGORY_BREAKPOINT), m_bp(bp)
+ : TextMark(Utils::FilePath(), lineNumber, Constants::TEXT_MARK_CATEGORY_BREAKPOINT), m_bp(bp)
{
setIcon(bp->icon());
setPriority(TextMark::NormalPriority);
@@ -141,7 +141,7 @@ public:
DisassemblerAgentPrivate::DisassemblerAgentPrivate(DebuggerEngine *engine)
: document(nullptr),
engine(engine),
- locationMark(engine, Utils::FileName(), 0),
+ locationMark(engine, Utils::FilePath(), 0),
mimeType("text/x-qtcreator-generic-asm"),
resetLocationScheduled(false)
{}
diff --git a/src/plugins/debugger/enginemanager.cpp b/src/plugins/debugger/enginemanager.cpp
index 0ca42d64a7..6050dc50b9 100644
--- a/src/plugins/debugger/enginemanager.cpp
+++ b/src/plugins/debugger/enginemanager.cpp
@@ -145,7 +145,7 @@ public:
if (hideSwitcherUnlessNeeded)
m_engineChooser->hide();
- connect(m_engineChooser, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_engineChooser, QOverload<int>::of(&QComboBox::activated),
this, &EngineManagerPrivate::activateEngineByIndex);
}
@@ -377,7 +377,8 @@ void EngineManagerPrivate::selectUiForCurrentEngine()
row = m_engineModel.rootItem()->indexOf(m_currentItem);
m_engineChooser->setCurrentIndex(row);
- const int contentWidth = m_engineChooser->fontMetrics().width(m_engineChooser->currentText() + "xx");
+ const int contentWidth =
+ m_engineChooser->fontMetrics().horizontalAdvance(m_engineChooser->currentText() + "xx");
QStyleOptionComboBox option;
option.initFrom(m_engineChooser);
const QSize sz(contentWidth, 1);
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 796416374a..204a11698d 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -61,7 +61,6 @@
#include <app/app_version.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
-#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/savedaction.h>
@@ -133,7 +132,7 @@ GdbEngine::GdbEngine()
connect(&m_gdbProc, &QProcess::errorOccurred,
this, &GdbEngine::handleGdbError);
- connect(&m_gdbProc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_gdbProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &GdbEngine::handleGdbFinished);
connect(&m_gdbProc, &QtcProcess::readyReadStandardOutput,
this, &GdbEngine::readGdbStandardOutput);
@@ -356,7 +355,7 @@ void GdbEngine::handleResponse(const QString &buff)
Task task(Task::Warning,
tr("Missing debug information for %1\nTry: %2")
.arg(m_lastMissingDebugInfo).arg(cmd),
- FileName(), 0, Debugger::Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO);
+ FilePath(), 0, Debugger::Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO);
TaskHub::addTask(task);
Internal::addDebugInfoTask(task.taskId, cmd);
@@ -1630,7 +1629,7 @@ QString GdbEngine::cleanupFullName(const QString &fileName)
}
cleanFilePath.clear();
- const QString base = FileName::fromString(fileName).fileName();
+ const QString base = FilePath::fromString(fileName).fileName();
QMap<QString, QString>::const_iterator jt = m_baseNameToFullName.constFind(base);
while (jt != m_baseNameToFullName.constEnd() && jt.key() == base) {
@@ -1701,7 +1700,7 @@ void GdbEngine::setLinuxOsAbi()
const DebuggerRunParameters &rp = runParameters();
bool isElf = (rp.toolChainAbi.binaryFormat() == Abi::ElfFormat);
if (!isElf && !rp.inferior.executable.isEmpty()) {
- isElf = Utils::anyOf(Abi::abisOfBinary(FileName::fromString(rp.inferior.executable)),
+ isElf = Utils::anyOf(Abi::abisOfBinary(FilePath::fromString(rp.inferior.executable)),
[](const Abi &abi) {
return abi.binaryFormat() == Abi::ElfFormat;
});
@@ -2078,7 +2077,7 @@ QString GdbEngine::breakLocation(const QString &file) const
{
QString where = m_fullToShortName.value(file);
if (where.isEmpty())
- return FileName::fromString(file).fileName();
+ return FilePath::fromString(file).fileName();
return where;
}
@@ -3524,14 +3523,16 @@ void GdbEngine::setupEngine()
if (isRemoteEngine() && HostOsInfo::isWindowsHost())
m_gdbProc.setUseCtrlCStub(runParameters().useCtrlCStub); // This is only set for QNX
- QStringList gdbArgs;
+ const DebuggerRunParameters &rp = runParameters();
+ CommandLine gdbCommand{FilePath::fromString(rp.debugger.executable), {}};
+
if (isPlainEngine()) {
if (!m_outputCollector.listen()) {
handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
.arg(m_outputCollector.errorString()));
return;
}
- gdbArgs.append("--tty=" + m_outputCollector.serverName());
+ gdbCommand.addArg("--tty=" + m_outputCollector.serverName());
}
const QString tests = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_TESTS"));
@@ -3542,7 +3543,6 @@ void GdbEngine::setupEngine()
m_expectTerminalTrap = terminal();
- const DebuggerRunParameters &rp = runParameters();
if (rp.debugger.executable.isEmpty()) {
handleGdbStartFailed();
handleAdapterStartFailed(
@@ -3551,13 +3551,12 @@ void GdbEngine::setupEngine()
return;
}
- gdbArgs << "-i";
- gdbArgs << "mi";
+ gdbCommand.addArgs("-i mi");
if (!boolSetting(LoadGdbInit))
- gdbArgs << "-n";
+ gdbCommand.addArg("-n");
- showMessage("STARTING " + rp.debugger.executable + " " + gdbArgs.join(' '));
- m_gdbProc.setCommand(rp.debugger.executable, QtcProcess::joinArgs(gdbArgs));
+ showMessage("STARTING " + gdbCommand.toUserOutput());
+ m_gdbProc.setCommand(gdbCommand);
if (QFileInfo(rp.debugger.workingDirectory).isDir())
m_gdbProc.setWorkingDirectory(rp.debugger.workingDirectory);
m_gdbProc.setEnvironment(rp.debugger.environment);
@@ -3651,7 +3650,7 @@ void GdbEngine::setupEngine()
for (auto it = completeSourcePathMap.constBegin(), cend = completeSourcePathMap.constEnd();
it != cend;
++it) {
- runCommand({"set substitute-path " + it.key() + " " + it.value()});
+ runCommand({"set substitute-path " + it.key() + " " + expand(it.value())});
}
// Spaces just will not work.
@@ -4258,6 +4257,8 @@ void GdbEngine::handleAttach(const DebuggerResponse &response)
notifyEngineRunAndInferiorStopOk();
if (runParameters().continueAfterAttach)
continueInferiorInternal();
+ else
+ updateAll();
}
break;
case ResultError:
@@ -4742,6 +4743,7 @@ void GdbEngine::doUpdateLocals(const UpdateParameters &params)
cmd.arg("autoderef", boolSetting(AutoDerefPointers));
cmd.arg("dyntype", boolSetting(UseDynamicType));
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
+ cmd.arg("timestamps", boolSetting(LogTimeStamps));
StackFrame frame = stackHandler()->currentFrame();
cmd.arg("context", frame.context);
diff --git a/src/plugins/debugger/images/debugger_stop.png b/src/plugins/debugger/images/debugger_stop.png
new file mode 100644
index 0000000000..6d4c3c59e9
--- /dev/null
+++ b/src/plugins/debugger/images/debugger_stop.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_stop@2x.png b/src/plugins/debugger/images/debugger_stop@2x.png
new file mode 100644
index 0000000000..27f6b3828f
--- /dev/null
+++ b/src/plugins/debugger/images/debugger_stop@2x.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_stop_32.png b/src/plugins/debugger/images/debugger_stop_32.png
deleted file mode 100644
index 23ee07ac99..0000000000
--- a/src/plugins/debugger/images/debugger_stop_32.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index f91240bb93..3047fb8ad4 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -100,7 +100,7 @@ LldbEngine::LldbEngine()
connect(&m_lldbProc, &QProcess::errorOccurred,
this, &LldbEngine::handleLldbError);
- connect(&m_lldbProc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_lldbProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &LldbEngine::handleLldbFinished);
connect(&m_lldbProc, &QProcess::readyReadStandardOutput,
this, &LldbEngine::readLldbStandardOutput);
@@ -207,7 +207,7 @@ void LldbEngine::setupEngine()
if (QFileInfo(runParameters().debugger.workingDirectory).isDir())
m_lldbProc.setWorkingDirectory(runParameters().debugger.workingDirectory);
- m_lldbProc.setCommand(lldbCmd, QString());
+ m_lldbProc.setCommand(CommandLine(FilePath::fromString(lldbCmd), QString()));
m_lldbProc.start();
if (!m_lldbProc.waitForStarted()) {
@@ -263,7 +263,8 @@ void LldbEngine::setupEngine()
for (auto it = sourcePathMap.constBegin(), cend = sourcePathMap.constEnd();
it != cend;
++it) {
- executeDebuggerCommand("settings append target.source-map " + it.key() + ' ' + it.value());
+ executeDebuggerCommand(
+ "settings append target.source-map " + it.key() + ' ' + expand(it.value()));
}
DebuggerCommand cmd2("setupInferior");
@@ -763,6 +764,7 @@ void LldbEngine::doUpdateLocals(const UpdateParameters &params)
cmd.arg("dyntype", boolSetting(UseDynamicType));
cmd.arg("partialvar", params.partialVariable);
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
+ cmd.arg("timestamps", boolSetting(LogTimeStamps));
StackFrame frame = stackHandler()->currentFrame();
cmd.arg("context", frame.context);
diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp
index 8bd68aa791..075cefd595 100644
--- a/src/plugins/debugger/loadcoredialog.cpp
+++ b/src/plugins/debugger/loadcoredialog.cpp
@@ -137,7 +137,7 @@ void SelectRemoteFileDialog::attachToDevice(Kit *k)
{
m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
QTC_ASSERT(k, return);
- IDevice::ConstPtr device = DeviceKitInformation::device(k);
+ IDevice::ConstPtr device = DeviceKitAspect::device(k);
QTC_ASSERT(device, return);
SshConnectionParameters sshParams = device->sshParameters();
m_fileSystemModel.setSshConnection(sshParams);
@@ -352,7 +352,7 @@ bool AttachCoreDialog::isLocalKit() const
{
Kit *k = d->kitChooser->currentKit();
QTC_ASSERT(k, return false);
- IDevice::ConstPtr device = DeviceKitInformation::device(k);
+ IDevice::ConstPtr device = DeviceKitAspect::device(k);
QTC_ASSERT(device, return false);
return device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
}
@@ -367,12 +367,12 @@ void AttachCoreDialog::coreFileChanged(const QString &core)
if (!HostOsInfo::isWindowsHost() && QFile::exists(core)) {
Kit *k = d->kitChooser->currentKit();
QTC_ASSERT(k, return);
- Runnable debugger = DebuggerKitInformation::runnable(k);
+ Runnable debugger = DebuggerKitAspect::runnable(k);
CoreInfo cinfo = CoreInfo::readExecutableNameFromCore(debugger, core);
if (!cinfo.foundExecutableName.isEmpty())
- d->symbolFileName->setFileName(FileName::fromString(cinfo.foundExecutableName));
+ d->symbolFileName->setFileName(FilePath::fromString(cinfo.foundExecutableName));
else if (!d->symbolFileName->isValid() && !cinfo.rawStringFromCore.isEmpty())
- d->symbolFileName->setFileName(FileName::fromString(cinfo.rawStringFromCore));
+ d->symbolFileName->setFileName(FilePath::fromString(cinfo.rawStringFromCore));
}
changed();
}
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index f422225d45..39acf7df96 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -118,7 +118,7 @@ void PdbEngine::setupEngine()
QString bridge = ICore::resourcePath() + "/debugger/pdbbridge.py";
connect(&m_proc, &QProcess::errorOccurred, this, &PdbEngine::handlePdbError);
- connect(&m_proc, static_cast<void(QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &PdbEngine::handlePdbFinished);
connect(&m_proc, &QProcess::readyReadStandardOutput,
this, &PdbEngine::readPdbStandardOutput);
diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp
deleted file mode 100644
index 3353712dda..0000000000
--- a/src/plugins/debugger/qml/qmlcppengine.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "qmlcppengine.h"
-#include "qmlengine.h"
-
-#include <debugger/debuggercore.h>
-#include <debugger/debuggerruncontrol.h>
-#include <debugger/debuggertooltipmanager.h>
-#include <debugger/breakhandler.h>
-#include <debugger/stackhandler.h>
-#include <debugger/threaddata.h>
-#include <debugger/watchhandler.h>
-#include <debugger/console/console.h>
-
-#include <utils/qtcassert.h>
-#include <qmljseditor/qmljseditorconstants.h>
-#include <cppeditor/cppeditorconstants.h>
-
-namespace Debugger {
-namespace Internal {
-
-enum { debug = 0 };
-
-#define EDEBUG(s) do { if (debug) qDebug() << s; } while (0)
-
-#define CHECK_STATE(s) do { checkState(s, __FILE__, __LINE__); } while (0)
-
-DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine)
-{
- return new QmlCppEngine(cppEngine);
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// QmlCppEngine
-//
-////////////////////////////////////////////////////////////////////////
-
-QmlCppEngine::QmlCppEngine(DebuggerEngine *cppEngine)
-{
- setObjectName("QmlCppEngine");
- m_qmlEngine = new QmlEngine;
- m_qmlEngine->setMasterEngine(this);
- m_cppEngine = cppEngine;
- m_cppEngine->setMasterEngine(this);
- m_activeEngine = m_cppEngine;
-}
-
-QmlCppEngine::~QmlCppEngine()
-{
- delete m_qmlEngine;
- delete m_cppEngine;
-}
-
-bool QmlCppEngine::canDisplayTooltip() const
-{
- return m_cppEngine->canDisplayTooltip() || m_qmlEngine->canDisplayTooltip();
-}
-
-bool QmlCppEngine::canHandleToolTip(const DebuggerToolTipContext &ctx) const
-{
- bool success = false;
- if (ctx.isCppEditor)
- success = m_cppEngine->canHandleToolTip(ctx);
- else
- success = m_qmlEngine->canHandleToolTip(ctx);
- return success;
-}
-
-void QmlCppEngine::updateItem(const QString &iname)
-{
- if (iname.startsWith("inspect."))
- m_qmlEngine->updateItem(iname);
- else
- m_activeEngine->updateItem(iname);
-}
-
-void QmlCppEngine::expandItem(const QString &iname)
-{
- if (iname.startsWith("inspect."))
- m_qmlEngine->expandItem(iname);
- else
- m_activeEngine->expandItem(iname);
-}
-
-void QmlCppEngine::selectWatchData(const QString &iname)
-{
- if (iname.startsWith("inspect."))
- m_qmlEngine->selectWatchData(iname);
-}
-
-void QmlCppEngine::watchPoint(const QPoint &point)
-{
- m_cppEngine->watchPoint(point);
-}
-
-void QmlCppEngine::fetchMemory(MemoryAgent *agent, quint64 addr, quint64 length)
-{
- m_cppEngine->fetchMemory(agent, addr, length);
-}
-
-void QmlCppEngine::changeMemory(MemoryAgent *agent, quint64 addr, const QByteArray &data)
-{
- m_cppEngine->changeMemory(agent, addr, data);
-}
-
-void QmlCppEngine::fetchDisassembler(DisassemblerAgent *da)
-{
- m_cppEngine->fetchDisassembler(da);
-}
-
-void QmlCppEngine::activateFrame(int index)
-{
- if (state() != InferiorStopOk && state() != InferiorUnrunnable)
- return;
-
- m_activeEngine->activateFrame(index);
-
- stackHandler()->setCurrentIndex(index);
-}
-
-void QmlCppEngine::reloadModules()
-{
- m_cppEngine->reloadModules();
-}
-
-void QmlCppEngine::examineModules()
-{
- m_cppEngine->examineModules();
-}
-
-void QmlCppEngine::loadSymbols(const QString &moduleName)
-{
- m_cppEngine->loadSymbols(moduleName);
-}
-
-void QmlCppEngine::loadAllSymbols()
-{
- m_cppEngine->loadAllSymbols();
-}
-
-void QmlCppEngine::requestModuleSymbols(const QString &moduleName)
-{
- m_cppEngine->requestModuleSymbols(moduleName);
-}
-
-void QmlCppEngine::reloadRegisters()
-{
- m_cppEngine->reloadRegisters();
-}
-
-void QmlCppEngine::reloadSourceFiles()
-{
- m_cppEngine->reloadSourceFiles();
-}
-
-void QmlCppEngine::reloadFullStack()
-{
- m_cppEngine->reloadFullStack();
-}
-
-void QmlCppEngine::setRegisterValue(const QString &name, const QString &value)
-{
- m_cppEngine->setRegisterValue(name, value);
-}
-
-
-bool QmlCppEngine::hasCapability(unsigned cap) const
-{
- // ### this could also be an OR of both engines' capabilities
- bool hasCap = m_cppEngine->hasCapability(cap);
- if (m_activeEngine != m_cppEngine) {
- //Some capabilities cannot be handled by QML Engine
- //Expand this list as and when required
- if (cap == AddWatcherWhileRunningCapability)
- hasCap = hasCap || m_qmlEngine->hasCapability(cap);
- if (cap == WatchWidgetsCapability ||
- cap == DisassemblerCapability ||
- cap == OperateByInstructionCapability ||
- cap == ReverseSteppingCapability)
- hasCap = hasCap && m_qmlEngine->hasCapability(cap);
- }
- return hasCap;
-}
-
-QString QmlCppEngine::qtNamespace() const
-{
- return m_cppEngine->qtNamespace();
-}
-
-void QmlCppEngine::createSnapshot()
-{
- m_cppEngine->createSnapshot();
-}
-
-void QmlCppEngine::updateAll()
-{
- m_activeEngine->updateAll();
-}
-
-void QmlCppEngine::attemptBreakpointSynchronization()
-{
- m_cppEngine->attemptBreakpointSynchronization();
-
- switch (m_qmlEngine->state()) {
- case InferiorRunOk:
- case InferiorRunRequested:
- case InferiorStopOk: // fall through
- case InferiorStopRequested:
- m_qmlEngine->attemptBreakpointSynchronization();
- break;
- default:
- break;
- }
-}
-
-void QmlCppEngine::doUpdateLocals(const UpdateParameters &up)
-{
- m_activeEngine->doUpdateLocals(up);
-}
-
-bool QmlCppEngine::acceptsBreakpoint(Breakpoint bp) const
-{
- return m_cppEngine->acceptsBreakpoint(bp)
- || m_qmlEngine->acceptsBreakpoint(bp);
-}
-
-void QmlCppEngine::selectThread(ThreadId threadId)
-{
- m_activeEngine->selectThread(threadId);
-}
-
-void QmlCppEngine::assignValueInDebugger(WatchItem *item,
- const QString &expr, const QVariant &value)
-{
- if (item->isInspect())
- m_qmlEngine->assignValueInDebugger(item, expr, value);
- else
- m_activeEngine->assignValueInDebugger(item, expr, value);
-}
-
-void QmlCppEngine::notifyInferiorIll()
-{
- //Call notifyInferiorIll of cpp engine
- //as qml engine will follow state transitions
- //of cpp engine
- m_cppEngine->notifyInferiorIll();
-}
-
-void QmlCppEngine::detachDebugger()
-{
- m_qmlEngine->detachDebugger();
- m_cppEngine->detachDebugger();
-}
-
-void QmlCppEngine::executeStep()
-{
- notifyInferiorRunRequested();
- m_activeEngine->executeStep();
-}
-
-void QmlCppEngine::executeStepOut()
-{
- notifyInferiorRunRequested();
- m_activeEngine->executeStepOut();
-}
-
-void QmlCppEngine::executeNext()
-{
- notifyInferiorRunRequested();
- m_activeEngine->executeNext();
-}
-
-void QmlCppEngine::executeStepI()
-{
- notifyInferiorRunRequested();
- m_activeEngine->executeStepI();
-}
-
-void QmlCppEngine::executeNextI()
-{
- notifyInferiorRunRequested();
- m_activeEngine->executeNextI();
-}
-
-void QmlCppEngine::executeReturn()
-{
- notifyInferiorRunRequested();
- m_activeEngine->executeReturn();
-}
-
-void QmlCppEngine::continueInferior()
-{
- EDEBUG("\nMASTER CONTINUE INFERIOR"
- << state() << m_qmlEngine->state());
- notifyInferiorRunRequested();
- if (m_cppEngine->state() == InferiorStopOk) {
- m_cppEngine->continueInferior();
- } else if (m_qmlEngine->state() == InferiorStopOk) {
- m_qmlEngine->continueInferior();
- } else {
- QTC_ASSERT(false, qDebug() << "MASTER CANNOT CONTINUE INFERIOR"
- << m_cppEngine->state() << m_qmlEngine->state());
- notifyEngineIll();
- }
-}
-
-void QmlCppEngine::interruptInferior()
-{
- EDEBUG("\nMASTER INTERRUPT INFERIOR");
- m_activeEngine->setState(InferiorStopRequested);
- m_activeEngine->interruptInferior();
-}
-
-void QmlCppEngine::executeRunToLine(const ContextData &data)
-{
- m_activeEngine->executeRunToLine(data);
-}
-
-void QmlCppEngine::executeRunToFunction(const QString &functionName)
-{
- m_activeEngine->executeRunToFunction(functionName);
-}
-
-void QmlCppEngine::executeJumpToLine(const ContextData &data)
-{
- m_activeEngine->executeJumpToLine(data);
-}
-
-void QmlCppEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages languages)
-{
- m_qmlEngine->executeDebuggerCommand(command, languages);
- m_cppEngine->executeDebuggerCommand(command, languages);
-}
-
-/////////////////////////////////////////////////////////
-
-void QmlCppEngine::setupEngine()
-{
- EDEBUG("\nMASTER SETUP ENGINE");
- m_activeEngine = m_cppEngine;
- m_qmlEngine->setupSlaveEngine();
- m_cppEngine->setupSlaveEngine();
-}
-
-void QmlCppEngine::runEngine()
-{
- EDEBUG("\nMASTER RUN ENGINE");
- m_qmlEngine->runSlaveEngine();
- m_cppEngine->runSlaveEngine();
-}
-
-void QmlCppEngine::shutdownInferior()
-{
- EDEBUG("\nMASTER SHUTDOWN INFERIOR");
- m_cppEngine->shutdownInferior();
-}
-
-void QmlCppEngine::shutdownEngine()
-{
- EDEBUG("\nMASTER SHUTDOWN ENGINE");
- m_qmlEngine->shutdownSlaveEngine();
- m_cppEngine->shutdownSlaveEngine();
-}
-
-void QmlCppEngine::quitDebugger()
-{
- EDEBUG("\nMASTER QUIT DEBUGGER");
- m_cppEngine->quitDebugger();
-}
-
-void QmlCppEngine::abortDebuggerProcess()
-{
- EDEBUG("\nMASTER ABORT DEBUGGER");
- m_cppEngine->abortDebuggerProcess();
-}
-
-void QmlCppEngine::setState(DebuggerState newState, bool forced)
-{
- EDEBUG("SET MASTER STATE: " << newState);
- EDEBUG(" CPP STATE: " << m_cppEngine->state());
- EDEBUG(" QML STATE: " << m_qmlEngine->state());
- DebuggerEngine::setState(newState, forced);
-}
-
-void QmlCppEngine::slaveEngineStateChanged
- (DebuggerEngine *slaveEngine, const DebuggerState newState)
-{
- DebuggerEngine *otherEngine = (slaveEngine == m_cppEngine)
- ? m_qmlEngine.data() : m_cppEngine.data();
-
- QTC_ASSERT(otherEngine, return);
- QTC_CHECK(otherEngine != slaveEngine);
-
- if (debug) {
- EDEBUG("GOT SLAVE STATE: " << slaveEngine << newState);
- EDEBUG(" OTHER ENGINE: " << otherEngine << otherEngine->state());
- EDEBUG(" COMBINED ENGINE: " << this << state() << isDying());
- }
-
- if (state() == DebuggerFinished) {
- // We are done and don't care about slave state changes anymore.
- return;
- }
-
- // Idea is to follow the state of the cpp engine, except where we are stepping in QML.
- // That is, when the QmlEngine moves between InferiorStopOk, and InferiorRunOk, InferiorStopOk ...
- //
- // Accordingly, the 'active engine' is the cpp engine until the qml engine enters the
- // InferiorStopOk state. The cpp engine becomes the active one again as soon as it itself enters
- // the InferiorStopOk state.
-
- if (slaveEngine == m_cppEngine) {
- switch (newState) {
- case DebuggerNotReady: {
- // Can this ever happen?
- break;
- }
- case EngineSetupRequested: {
- // Set by queueSetupEngine()
- CHECK_STATE(EngineSetupRequested);
- break;
- }
- case EngineSetupFailed: {
- m_qmlEngine->quitDebugger();
- notifyEngineSetupFailed();
- break;
- }
- case EngineSetupOk: {
- notifyEngineSetupOk();
- break;
- }
- case EngineRunRequested: {
- // set by queueRunEngine()
- break;
- }
- case EngineRunFailed: {
- m_qmlEngine->quitDebugger();
- notifyEngineRunFailed();
- break;
- }
- case InferiorUnrunnable: {
- m_qmlEngine->quitDebugger();
- notifyEngineRunOkAndInferiorUnrunnable();
- break;
- }
- case InferiorRunRequested: {
- // Might be set already by notifyInferiorRunRequested()
- if (state() != InferiorRunRequested) {
- CHECK_STATE(InferiorStopOk);
- notifyInferiorRunRequested();
- }
- break;
- }
- case InferiorRunOk: {
- if (state() == EngineRunRequested) {
- notifyEngineRunAndInferiorRunOk();
- } else if (state() == InferiorRunRequested) {
- notifyInferiorRunOk();
- } else if (state() == InferiorStopOk) {
- notifyInferiorRunRequested();
- notifyInferiorRunOk();
- } else {
- QTC_ASSERT(false, qDebug() << state());
- }
-
- if (m_qmlEngine->state() == InferiorStopOk) {
- // track qml engine again
- setState(InferiorStopRequested);
- notifyInferiorStopOk();
- setActiveEngine(m_qmlEngine);
- }
- break;
- }
- case InferiorRunFailed: {
- m_qmlEngine->quitDebugger();
- notifyInferiorRunFailed();
- break;
- }
- case InferiorStopRequested: {
- if (m_activeEngine == cppEngine()) {
- if (state() == InferiorRunOk) {
- setState(InferiorStopRequested);
- } else {
- // Might be set by doInterruptInferior()
- CHECK_STATE(InferiorStopRequested);
- }
- } else {
- // We're debugging qml, but got an interrupt, or abort
- if (state() == InferiorRunOk) {
- setState(InferiorStopRequested);
- } else if (state() == InferiorStopOk) {
- if (!isDying()) {
- notifyInferiorRunRequested();
- notifyInferiorRunOk();
- setState(InferiorStopRequested);
- }
- } else if (state() == InferiorRunRequested) {
- notifyInferiorRunOk();
- setState(InferiorStopRequested);
- } else {
- QTC_ASSERT(false, qDebug() << state());
- }
- // now track cpp engine
- setActiveEngine(m_cppEngine);
- }
- break;
- }
- case InferiorStopOk: {
- if (isDying()) {
- EDEBUG("... CPP ENGINE STOPPED DURING SHUTDOWN ");
- QTC_ASSERT(state() == InferiorStopRequested
- || state() == InferiorRunOk
- || state() == InferiorStopOk, qDebug() << state());
-
- // Just to make sure, we're shutting down anyway ...
- m_activeEngine = m_cppEngine;
-
- if (state() == InferiorStopRequested)
- setState(InferiorStopOk);
- // otherwise we're probably inside notifyInferiorStopOk already
- } else {
- if (m_activeEngine != cppEngine()) {
- showStatusMessage(tr("C++ debugger activated"));
- setActiveEngine(m_cppEngine);
- }
- switch (state()) {
- case InferiorStopRequested:
- EDEBUG("... CPP ENGINE STOPPED EXPECTEDLY");
- notifyInferiorStopOk();
- break;
- case EngineRunRequested:
- EDEBUG("... CPP ENGINE STOPPED ON STARTUP");
- notifyEngineRunAndInferiorStopOk();
- break;
- case InferiorRunOk:
- EDEBUG("... CPP ENGINE STOPPED SPONTANEOUSLY");
- notifyInferiorSpontaneousStop();
- break;
- case InferiorRunRequested:
- // can happen if qml engine was active
- notifyInferiorRunFailed();
- break;
- default:
- CHECK_STATE(InferiorStopOk);
- break;
- }
- }
- break;
- }
- case InferiorStopFailed: {
- CHECK_STATE(InferiorStopRequested);
- notifyInferiorStopFailed();
- break;
- }
- case InferiorShutdownRequested: {
- if (state() == InferiorStopOk) {
- setState(InferiorShutdownRequested);
- } else {
- // might be set by queueShutdownInferior() already
- CHECK_STATE(InferiorShutdownRequested);
- }
- m_qmlEngine->quitDebugger();
- break;
- }
- case InferiorShutdownFinished: {
- if (state() == InferiorShutdownRequested) {
- notifyInferiorShutdownFinished();
- } else {
- // we got InferiorExitOk before, but ignored it ...
- notifyInferiorExited();
- }
- break;
- }
- case EngineShutdownRequested: {
- // set by queueShutdownEngine()
- CHECK_STATE(EngineShutdownRequested);
- break;
- }
- case EngineShutdownFinished: {
- CHECK_STATE(EngineShutdownRequested);
- notifyEngineShutdownFinished();
- break;
- }
- case DebuggerFinished: {
- // set by queueFinishDebugger()
- CHECK_STATE(DebuggerFinished);
- break;
- }
- }
- } else {
- // QML engine state change
- if (newState == InferiorStopOk) {
- if (isDying()) {
- EDEBUG("... QML ENGINE STOPPED DURING SHUTDOWN ");
-
- // Just to make sure, we're shutting down anyway ...
- setActiveEngine(m_cppEngine);
-
- if (state() == InferiorStopRequested)
- notifyInferiorStopOk();
- // otherwise we're probably inside notifyInferiorStopOk already
- } else {
- if (m_activeEngine != m_qmlEngine) {
- showStatusMessage(tr("QML debugger activated"));
- setActiveEngine(m_qmlEngine);
- }
-
- if (state() == InferiorRunOk)
- notifyInferiorSpontaneousStop();
- else if (state() == InferiorStopRequested)
- notifyInferiorStopOk();
- else
- CHECK_STATE(InferiorShutdownRequested);
- }
-
- } else if (newState == InferiorRunOk) {
- if (m_activeEngine == m_qmlEngine) {
- CHECK_STATE(InferiorRunRequested);
- notifyInferiorRunOk();
- }
- }
- }
-}
-
-void QmlCppEngine::resetLocation()
-{
- if (m_qmlEngine)
- m_qmlEngine->resetLocation();
- if (m_cppEngine)
- m_cppEngine->resetLocation();
-
- DebuggerEngine::resetLocation();
-}
-
-void QmlCppEngine::reloadDebuggingHelpers()
-{
- if (m_cppEngine)
- m_cppEngine->reloadDebuggingHelpers();
-}
-
-void QmlCppEngine::debugLastCommand()
-{
- if (m_cppEngine)
- m_cppEngine->debugLastCommand();
-}
-
-void QmlCppEngine::setRunTool(DebuggerRunTool *runTool)
-{
- DebuggerEngine::setRunTool(runTool);
- m_qmlEngine->setRunTool(runTool);
- m_cppEngine->setRunTool(runTool);
-}
-
-void QmlCppEngine::setActiveEngine(DebuggerEngine *engine)
-{
- m_activeEngine = engine;
- updateViews();
-}
-
-void QmlCppEngine::loadAdditionalQmlStack()
-{
- if (m_cppEngine)
- m_cppEngine->loadAdditionalQmlStack();
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h
deleted file mode 100644
index fffd08a89a..0000000000
--- a/src/plugins/debugger/qml/qmlcppengine.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/debuggerengine.h>
-
-namespace Debugger {
-namespace Internal {
-
-class QmlEngine;
-
-class QmlCppEngine : public DebuggerEngine
-{
- Q_OBJECT
-
-public:
- explicit QmlCppEngine(DebuggerEngine *cppEngine);
- ~QmlCppEngine() override;
-
- bool canDisplayTooltip() const override;
- bool canHandleToolTip(const DebuggerToolTipContext &) const override;
- void updateItem(const QString &iname) override;
- void expandItem(const QString &iname) override;
- void selectWatchData(const QString &iname) override;
-
- void watchPoint(const QPoint &) override;
- void fetchMemory(MemoryAgent *, quint64 addr, quint64 length) override;
- void changeMemory(MemoryAgent *, quint64 addr, const QByteArray &data) override;
- void fetchDisassembler(DisassemblerAgent *) override;
- void activateFrame(int index) override;
-
- void reloadModules() override;
- void examineModules() override;
- void loadSymbols(const QString &moduleName) override;
- void loadAllSymbols() override;
- void requestModuleSymbols(const QString &moduleName) override;
-
- void reloadRegisters() override;
- void reloadSourceFiles() override;
- void reloadFullStack() override;
-
- void setRegisterValue(const QString &name, const QString &value) override;
- bool hasCapability(unsigned cap) const override;
-
- QString qtNamespace() const override;
-
- void createSnapshot() override;
- void updateAll() override;
-
- void attemptBreakpointSynchronization() override;
- bool acceptsBreakpoint(Breakpoint bp) const override;
- void selectThread(ThreadId threadId) override;
-
- void assignValueInDebugger(WatchItem *item,
- const QString &expr, const QVariant &value) override;
-
- DebuggerEngine *cppEngine() override { return m_cppEngine; }
- DebuggerEngine *activeEngine() override { return m_activeEngine; }
- void setRunTool(DebuggerRunTool *runTool) override;
-
- void resetLocation() override;
- void notifyInferiorIll() override;
-
-protected:
- void detachDebugger() override;
- void reloadDebuggingHelpers() override;
- void debugLastCommand() override;
- void executeStep() override;
- void executeStepOut() override;
- void executeNext() override;
- void executeStepI() override;
- void executeNextI() override;
- void executeReturn() override;
- void continueInferior() override;
- void interruptInferior() override;
-
- void executeRunToLine(const ContextData &data) override;
- void executeRunToFunction(const QString &functionName) override;
- void executeJumpToLine(const ContextData &data) override;
- void executeDebuggerCommand(const QString &command, DebuggerLanguages languages) override;
- void doUpdateLocals(const UpdateParameters &up) override;
-
- void setupEngine() override;
- void runEngine() override;
- void shutdownInferior() override;
- void shutdownEngine() override;
- void quitDebugger() override;
- void abortDebuggerProcess() override;
-
- void loadAdditionalQmlStack() override;
-
-private:
- void engineStateChanged(DebuggerState newState);
- void setState(DebuggerState newState, bool forced = false) override;
- void slaveEngineStateChanged(DebuggerEngine *slaveEngine, DebuggerState state) override;
-
- void setActiveEngine(DebuggerEngine *engine);
-
-private:
- QPointer<QmlEngine> m_qmlEngine;
- QPointer<DebuggerEngine> m_cppEngine;
- QPointer<DebuggerEngine> m_activeEngine;
-};
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 7f5971e2be..255052936e 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -1419,7 +1419,7 @@ void QmlEnginePrivate::setBreakpoint(const QString type, const QString target,
cmd.arg(ENABLED, enabled);
if (type == SCRIPTREGEXP)
- cmd.arg(TARGET, Utils::FileName::fromString(target).fileName());
+ cmd.arg(TARGET, Utils::FilePath::fromString(target).fileName());
else
cmd.arg(TARGET, target);
diff --git a/src/plugins/debugger/qml/qmlinspectoragent.cpp b/src/plugins/debugger/qml/qmlinspectoragent.cpp
index 36272270c9..86d429749e 100644
--- a/src/plugins/debugger/qml/qmlinspectoragent.cpp
+++ b/src/plugins/debugger/qml/qmlinspectoragent.cpp
@@ -29,6 +29,7 @@
#include <debugger/debuggeractions.h>
#include <debugger/debuggercore.h>
#include <debugger/debuggerengine.h>
+#include <debugger/debuggerinternalconstants.h>
#include <debugger/debuggerruncontrol.h>
#include <debugger/watchhandler.h>
diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp
index 0e066afade..7614bc413c 100644
--- a/src/plugins/debugger/registerhandler.cpp
+++ b/src/plugins/debugger/registerhandler.cpp
@@ -119,7 +119,7 @@ public:
painter->setPen(lightColor);
// FIXME: performance? this changes only on real font changes.
QFontMetrics fm(option.font);
- int charWidth = qMax(fm.width('x'), fm.width('0'));
+ int charWidth = qMax(fm.horizontalAdvance('x'), fm.horizontalAdvance('0'));
QString str = index.data(Qt::DisplayRole).toString();
int x = option.rect.x();
bool light = !paintRed;
diff --git a/src/plugins/debugger/sourceagent.cpp b/src/plugins/debugger/sourceagent.cpp
index 074806c5bb..565144dac4 100644
--- a/src/plugins/debugger/sourceagent.cpp
+++ b/src/plugins/debugger/sourceagent.cpp
@@ -104,7 +104,7 @@ void SourceAgent::setContent(const QString &filePath, const QString &content)
if (!d->editor) {
QString titlePattern = d->producer + ": "
- + Utils::FileName::fromString(filePath).fileName();
+ + Utils::FilePath::fromString(filePath).fileName();
d->editor = qobject_cast<BaseTextEditor *>(
EditorManager::openEditorWithContents(
CppEditor::Constants::CPPEDITOR_ID,
@@ -137,7 +137,7 @@ void SourceAgent::updateLocationMarker()
if (d->engine->stackHandler()->currentFrame().file == d->path) {
int lineNumber = d->engine->stackHandler()->currentFrame().line;
- d->locationMark = new TextMark(Utils::FileName(), lineNumber,
+ d->locationMark = new TextMark(Utils::FilePath(), lineNumber,
Constants::TEXT_MARK_CATEGORY_LOCATION);
d->locationMark->setIcon(Icons::LOCATION.icon());
d->locationMark->setPriority(TextMark::HighPriority);
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index 4d134792bd..bd57ea0c6d 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -112,7 +112,7 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const
case StackFunctionNameColumn:
return simplifyType(frame.function);
case StackFileNameColumn:
- return frame.file.isEmpty() ? frame.module : FileName::fromString(frame.file).fileName();
+ return frame.file.isEmpty() ? frame.module : FilePath::fromString(frame.file).fileName();
case StackLineNumberColumn:
return frame.line > 0 ? QVariant(frame.line) : QVariant();
case StackAddressColumn:
diff --git a/src/plugins/debugger/terminal.h b/src/plugins/debugger/terminal.h
index d6caa55f98..8f23242c8a 100644
--- a/src/plugins/debugger/terminal.h
+++ b/src/plugins/debugger/terminal.h
@@ -28,7 +28,7 @@
#include <QCoreApplication>
#include <QSocketNotifier>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/consoleprocess.h>
diff --git a/src/plugins/debugger/unstartedappwatcherdialog.cpp b/src/plugins/debugger/unstartedappwatcherdialog.cpp
index 8a52c57e1d..25cfe10d7b 100644
--- a/src/plugins/debugger/unstartedappwatcherdialog.cpp
+++ b/src/plugins/debugger/unstartedappwatcherdialog.cpp
@@ -59,7 +59,7 @@ static bool isLocal(RunConfiguration *runConfiguration)
{
Target *target = runConfiguration ? runConfiguration->target() : nullptr;
Kit *kit = target ? target->kit() : nullptr;
- return DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+ return DeviceTypeKitAspect::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
}
/*!
@@ -275,7 +275,7 @@ void UnstartedAppWatcherDialog::stopAndCheckExecutable()
void UnstartedAppWatcherDialog::kitChanged()
{
- const DebuggerItem *debugger = DebuggerKitInformation::debugger(m_kitChooser->currentKit());
+ const DebuggerItem *debugger = DebuggerKitAspect::debugger(m_kitChooser->currentKit());
if (!debugger)
return;
if (debugger->engineType() == Debugger::CdbEngineType) {
diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp
index c37e9d46a2..7abde55e87 100644
--- a/src/plugins/debugger/watchdata.cpp
+++ b/src/plugins/debugger/watchdata.cpp
@@ -363,6 +363,10 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
if (mi.isValid())
exp = mi.data();
+ mi = input["time"];
+ if (mi.isValid())
+ time = mi.data().toFloat();
+
mi = input["sortgroup"];
if (mi.isValid())
sortGroup = mi.toInt();
@@ -462,6 +466,8 @@ void WatchItem::parse(const GdbMi &data, bool maySort)
if (wname.isValid())
exp = name;
+
+ time = data["time"].data().toFloat();
}
// Format a tooltip row with aligned colon.
@@ -508,6 +514,7 @@ QString WatchItem::toToolTip() const
if (size)
formatToolTipRow(str, tr("Static Object Size"), tr("%n bytes", nullptr, size));
formatToolTipRow(str, tr("Internal ID"), internalName());
+ formatToolTipRow(str, tr("Creation Time in ms"), QString::number(int(time * 1000)));
str << "</table></body></html>";
return res;
}
diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h
index e6131c39cd..15146d9616 100644
--- a/src/plugins/debugger/watchdata.h
+++ b/src/plugins/debugger/watchdata.h
@@ -99,6 +99,7 @@ public:
bool valueEnabled; // Value will be enabled or not
bool valueEditable; // Value will be editable
bool outdated; // \internal item is to be removed.
+ double time = 0; // Time used on the dumper side to produce this item
private:
void parseHelper(const GdbMi &input, bool maySort);
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 8087e77638..3e95668d52 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -484,7 +484,7 @@ WatchModel::WatchModel(WatchHandler *handler, DebuggerEngine *engine)
m_contentsValid = true;
- setHeader({tr("Name"), tr("Value"), tr("Type")});
+ setHeader({tr("Name"), tr("Time"), tr("Value"), tr("Type")});
m_localsRoot = new WatchItem;
m_localsRoot->iname = "local";
m_localsRoot->name = tr("Locals");
@@ -901,7 +901,7 @@ static QColor valueColor(const WatchItem *item, int column)
if (const WatchModel *model = watchModel(item)) {
if (!model->m_contentsValid && !item->isInspect()) {
color = Theme::Debugger_WatchItem_ValueInvalid;
- } else if (column == 1) {
+ } else if (column == WatchModel::ValueColumn) {
if (!item->valueEnabled)
color = Theme::Debugger_WatchItem_ValueInvalid;
else if (!model->m_contentsValid && !item->isInspect())
@@ -1011,11 +1011,13 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case Qt::EditRole: {
switch (column) {
- case 0:
+ case TimeColumn:
+ return item->time;
+ case NameColumn:
return item->expression();
- case 1:
+ case ValueColumn:
return item->editValue();
- case 2:
+ case TypeColumn:
return item->type;
}
break;
@@ -1023,11 +1025,13 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case Qt::DisplayRole: {
switch (column) {
- case 0:
+ case TimeColumn:
+ return int(1000 * item->time);
+ case NameColumn:
return displayName(item);
- case 1:
+ case ValueColumn:
return displayValue(item);
- case 2:
+ case TypeColumn:
return displayType(item);
}
break;
@@ -1129,14 +1133,14 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
switch (role) {
case Qt::EditRole:
switch (idx.column()) {
- case 0: {
+ case NameColumn: {
m_handler->updateWatchExpression(item, value.toString().trimmed());
break;
}
- case 1: // Change value
+ case ValueColumn: // Change value
m_engine->assignValueInDebugger(item, item->expression(), value);
break;
- case 2: // TODO: Implement change type.
+ case TypeColumn: // TODO: Implement change type.
m_engine->assignValueInDebugger(item, item->expression(), value);
break;
}
@@ -1206,20 +1210,20 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
if (item->isWatcher()) {
if (state == InferiorUnrunnable)
- return (column == 0 && item->iname.count('.') == 1) ? editable : notEditable;
+ return (column == NameColumn && item->iname.count('.') == 1) ? editable : notEditable;
if (isRunning && !m_engine->hasCapability(AddWatcherWhileRunningCapability))
return notEditable;
- if (column == 0 && item->iname.count('.') == 1)
+ if (column == NameColumn && item->iname.count('.') == 1)
return editable; // Watcher names are editable.
- if (column == 1 && item->arrayIndex >= 0)
+ if (column == ValueColumn && item->arrayIndex >= 0)
return editable;
if (!item->name.isEmpty()) {
// FIXME: Forcing types is not implemented yet.
//if (idx.column() == 2)
// return editable; // Watcher types can be set by force.
- if (column == 1 && item->valueEditable && !item->elided)
+ if (column == ValueColumn && item->valueEditable && !item->elided)
return editable; // Watcher values are sometimes editable.
}
} else if (item->isLocal()) {
@@ -1227,12 +1231,12 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
return notEditable;
if (isRunning && !m_engine->hasCapability(AddWatcherWhileRunningCapability))
return notEditable;
- if (column == 1 && item->valueEditable && !item->elided)
+ if (column == ValueColumn && item->valueEditable && !item->elided)
return editable; // Locals values are sometimes editable.
- if (column == 1 && item->arrayIndex >= 0)
+ if (column == ValueColumn && item->arrayIndex >= 0)
return editable;
} else if (item->isInspect()) {
- if (column == 1 && item->valueEditable)
+ if (column == ValueColumn && item->valueEditable)
return editable; // Inspector values are sometimes editable.
}
return notEditable;
diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h
index 5be7c7f58e..39c8630d75 100644
--- a/src/plugins/debugger/watchhandler.h
+++ b/src/plugins/debugger/watchhandler.h
@@ -46,6 +46,8 @@ class WatchModelBase : public Utils::TreeModel<WatchItem, WatchItem>
public:
WatchModelBase() = default;
+ enum { NameColumn, TimeColumn, ValueColumn, TypeColumn };
+
signals:
void currentIndexRequested(const QModelIndex &idx);
void itemIsExpanded(const QModelIndex &idx);
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index cf31ff7187..9da95b351e 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -53,6 +53,9 @@ WatchTreeView::WatchTreeView(WatchType type)
connect(this, &QTreeView::expanded, this, &WatchTreeView::expandNode);
connect(this, &QTreeView::collapsed, this, &WatchTreeView::collapseNode);
+
+ connect(action(LogTimeStamps), &QAction::triggered,
+ this, &WatchTreeView::updateTimeColumn);
}
void WatchTreeView::expandNode(const QModelIndex &idx)
@@ -96,6 +99,14 @@ void WatchTreeView::setModel(QAbstractItemModel *model)
connect(watchModel, &WatchModelBase::updateFinished,
this, &WatchTreeView::hideProgressIndicator);
}
+
+ updateTimeColumn();
+}
+
+void WatchTreeView::updateTimeColumn()
+{
+ if (header())
+ header()->setSectionHidden(WatchModelBase::TimeColumn, !boolSetting(LogTimeStamps));
}
void WatchTreeView::handleItemIsExpanded(const QModelIndex &idx)
diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h
index bd75e00549..a2ede3cbe4 100644
--- a/src/plugins/debugger/watchwindow.h
+++ b/src/plugins/debugger/watchwindow.h
@@ -56,6 +56,7 @@ private:
void resetHelper();
void expandNode(const QModelIndex &idx);
void collapseNode(const QModelIndex &idx);
+ void updateTimeColumn();
void adjustSlider();
void doItemsLayout() override;
diff --git a/src/plugins/designer/CMakeLists.txt b/src/plugins/designer/CMakeLists.txt
new file mode 100644
index 0000000000..d51c0ccf3e
--- /dev/null
+++ b/src/plugins/designer/CMakeLists.txt
@@ -0,0 +1,42 @@
+# Qt5::DesignerComponents doesn't have a target, so we need to define our own:-/
+find_package(DesignerComponents)
+
+if (WITH_TESTS)
+ set(TST_COMPONENT CppEditor)
+endif()
+
+add_qtc_plugin(Designer
+ CONDITION TARGET Qt5::DesignerComponents AND TARGET Qt5::Designer
+ DEPENDS designerintegrationv2
+ Qt5::Designer Qt5::PrintSupport Qt5::DesignerComponents
+ DEFINES CPP_ENABLED
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer QtSupport ResourceEditor TextEditor ${TST_COMPONENT}
+ SOURCES
+ 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/formclasswizardparameters.cpp cpp/formclasswizardparameters.h
+ designer_export.h
+ designerconstants.h
+ designercontext.cpp designercontext.h
+ editordata.h
+ editorwidget.cpp editorwidget.h
+ formeditorfactory.cpp formeditorfactory.h
+ formeditorplugin.cpp formeditorplugin.h
+ formeditorstack.cpp formeditorstack.h
+ formeditorw.cpp formeditorw.h
+ formtemplatewizardpage.cpp formtemplatewizardpage.h
+ formwindoweditor.cpp formwindoweditor.h
+ formwindowfile.cpp formwindowfile.h
+ qtcreatorintegration.cpp qtcreatorintegration.h
+ qtdesignerformclasscodegenerator.cpp qtdesignerformclasscodegenerator.h
+ resourcehandler.cpp resourcehandler.h
+ settingsmanager.cpp settingsmanager.h
+ settingspage.cpp settingspage.h
+)
+
+extend_qtc_plugin(Designer
+ CONDITION WITH_TESTS AND TARGET Qt5::DesignerComponents AND TARGET Qt5::Designer
+ SOURCES gotoslot_test.cpp
+)
diff --git a/src/plugins/designer/codemodelhelpers.cpp b/src/plugins/designer/codemodelhelpers.cpp
index 9f376a114a..52bb38f5d1 100644
--- a/src/plugins/designer/codemodelhelpers.cpp
+++ b/src/plugins/designer/codemodelhelpers.cpp
@@ -47,7 +47,7 @@ static const char setupUiC[] = "setupUi";
static QString generatedHeaderOf(const QString &uiFileName)
{
if (const ProjectExplorer::Project *uiProject =
- ProjectExplorer::SessionManager::projectForFile(Utils::FileName::fromString(uiFileName))) {
+ ProjectExplorer::SessionManager::projectForFile(Utils::FilePath::fromString(uiFileName))) {
QStringList files = uiProject->filesGeneratedFrom(uiFileName);
if (!files.isEmpty()) // There should be at most one header generated from a .ui
return files.front();
diff --git a/src/plugins/designer/formtemplatewizardpage.cpp b/src/plugins/designer/formtemplatewizardpage.cpp
index ce5f3ddb8c..fb01ddc5f4 100644
--- a/src/plugins/designer/formtemplatewizardpage.cpp
+++ b/src/plugins/designer/formtemplatewizardpage.cpp
@@ -117,7 +117,7 @@ bool FormTemplateWizardPage::validatePage()
QMessageBox::critical(this, tr("%1 - Error").arg(title()), errorMessage);
return false;
}
- wizard()->setProperty("FormContents", m_templateContents.split('\n'));
+ wizard()->setProperty("FormContents", m_templateContents);
return true;
}
diff --git a/src/plugins/designer/formwindowfile.cpp b/src/plugins/designer/formwindowfile.cpp
index a35e8e14f2..f84b9e197b 100644
--- a/src/plugins/designer/formwindowfile.cpp
+++ b/src/plugins/designer/formwindowfile.cpp
@@ -97,7 +97,7 @@ Core::IDocument::OpenResult FormWindowFile::open(QString *errorString, const QSt
form->setDirty(fileName != realFileName);
syncXmlFromFormWindow();
- setFilePath(Utils::FileName::fromString(absfileName));
+ setFilePath(Utils::FilePath::fromString(absfileName));
setShouldAutoSave(false);
resourceHandler()->updateProjectResources();
@@ -106,7 +106,7 @@ Core::IDocument::OpenResult FormWindowFile::open(QString *errorString, const QSt
bool FormWindowFile::save(QString *errorString, const QString &name, bool autoSave)
{
- const FileName actualName = name.isEmpty() ? filePath() : FileName::fromString(name);
+ const FilePath actualName = name.isEmpty() ? filePath() : FilePath::fromString(name);
if (Designer::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << name << "->" << actualName;
@@ -175,7 +175,7 @@ bool FormWindowFile::setContents(const QByteArray &contents)
return true;
}
-void FormWindowFile::setFilePath(const FileName &newName)
+void FormWindowFile::setFilePath(const FilePath &newName)
{
m_formWindow->setFileName(newName.toString());
IDocument::setFilePath(newName);
diff --git a/src/plugins/designer/formwindowfile.h b/src/plugins/designer/formwindowfile.h
index d9129c88b9..d5791e7461 100644
--- a/src/plugins/designer/formwindowfile.h
+++ b/src/plugins/designer/formwindowfile.h
@@ -69,7 +69,7 @@ public:
QString formWindowContents() const;
ResourceHandler *resourceHandler() const;
- void setFilePath(const Utils::FileName &) override;
+ void setFilePath(const Utils::FilePath &) override;
void setShouldAutoSave(bool sad = true) { m_shouldAutoSave = sad; }
void updateIsModified();
diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp
index 9d3f9919a0..d004f4a661 100644
--- a/src/plugins/designer/qtcreatorintegration.cpp
+++ b/src/plugins/designer/qtcreatorintegration.cpp
@@ -86,8 +86,7 @@ QtCreatorIntegration::QtCreatorIntegration(QDesignerFormEditorInterface *core, Q
f &= ~ResourceEditorFeature;
setFeatures(f);
- connect(this, static_cast<void (QDesignerIntegrationInterface::*)
- (const QString&, const QString&, const QStringList&)>
+ connect(this, QOverload<const QString &, const QString &, const QStringList &>::of
(&QDesignerIntegrationInterface::navigateToSlot),
this, &QtCreatorIntegration::slotNavigateToSlot);
connect(this, &QtCreatorIntegration::helpRequested,
@@ -492,7 +491,7 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
{
typedef QMap<int, Document::Ptr> DocumentMap;
- const Utils::FileName currentUiFile = FormEditorW::activeEditor()->document()->filePath();
+ const Utils::FilePath currentUiFile = FormEditorW::activeEditor()->document()->filePath();
#if 0
return Designer::Internal::navigateToSlot(currentUiFile.toString(), objectName,
signalSignature, parameterNames, errorMessage);
@@ -519,12 +518,12 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
} else {
const CppTools::WorkingCopy workingCopy =
CppTools::CppModelManager::instance()->workingCopy();
- const Utils::FileName configFileName =
- Utils::FileName::fromString(CppTools::CppModelManager::configurationFileName());
- QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
+ const Utils::FilePath configFileName =
+ Utils::FilePath::fromString(CppTools::CppModelManager::configurationFileName());
+ QHashIterator<Utils::FilePath, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
while (it.hasNext()) {
it.next();
- const Utils::FileName &fileName = it.key();
+ const Utils::FilePath &fileName = it.key();
if (fileName != configFileName)
newDocTable.insert(docTable.document(fileName));
}
diff --git a/src/plugins/designer/resourcehandler.cpp b/src/plugins/designer/resourcehandler.cpp
index 0bbc4cb2cd..0f7029a0e2 100644
--- a/src/plugins/designer/resourcehandler.cpp
+++ b/src/plugins/designer/resourcehandler.cpp
@@ -88,7 +88,7 @@ void ResourceHandler::updateResourcesHelper(bool updateProjectResources)
qDebug() << "ResourceHandler::updateResources()" << fileName;
// Filename could change in the meantime.
- Project *project = SessionManager::projectForFile(Utils::FileName::fromUserInput(fileName));
+ Project *project = SessionManager::projectForFile(Utils::FilePath::fromUserInput(fileName));
const bool dirty = m_form->property("_q_resourcepathchanged").toBool();
if (dirty)
m_form->setDirty(true);
@@ -96,9 +96,25 @@ void ResourceHandler::updateResourcesHelper(bool updateProjectResources)
// Does the file belong to a project?
if (project) {
// Collect project resource files.
- ProjectNode *root = project->rootProjectNode();
+
+ // Find the (sub-)project the file belongs to. We don't want to find resources
+ // from other parts of the project tree, e.g. via a qmake subdirs project.
+ ProjectNode *projectNode = project->rootProjectNode();
+ Node * const fileNode = projectNode->findNode([&fileName](const Node *n) {
+ return n->filePath().toString() == fileName;
+ });
+ if (fileNode) {
+ // We do not want qbs groups or qmake .pri files here, as they contain only a subset
+ // of the relevant files.
+ do
+ projectNode = fileNode->parentProjectNode();
+ while (projectNode && !projectNode->isProduct());
+ }
+ if (!projectNode)
+ projectNode = project->rootProjectNode();
+
QStringList projectQrcFiles;
- root->forEachNode([&](FileNode *node) {
+ projectNode->forEachNode([&](FileNode *node) {
if (node->fileType() == FileType::Resource)
projectQrcFiles.append(node->filePath().toString());
}, [&](FolderNode *node) {
@@ -114,7 +130,7 @@ void ResourceHandler::updateResourcesHelper(bool updateProjectResources)
}
if (!qrcPathsToBeAdded.isEmpty()) {
m_handlingResources = true;
- root->addFiles(qrcPathsToBeAdded);
+ projectNode->addFiles(qrcPathsToBeAdded);
m_handlingResources = false;
projectQrcFiles += qrcPathsToBeAdded;
}
diff --git a/src/plugins/diffeditor/CMakeLists.txt b/src/plugins/diffeditor/CMakeLists.txt
new file mode 100644
index 0000000000..f5fbb9630c
--- /dev/null
+++ b/src/plugins/diffeditor/CMakeLists.txt
@@ -0,0 +1,22 @@
+add_qtc_plugin(DiffEditor
+ PLUGIN_DEPENDS Core TextEditor
+ DEFINES DIFFEDITOR_LIBRARY
+ SOURCES
+ descriptionwidgetwatcher.cpp descriptionwidgetwatcher.h
+ diffeditor.cpp diffeditor.h
+ diffeditor.qrc
+ diffeditor_global.h
+ diffeditorconstants.h
+ diffeditorcontroller.cpp diffeditorcontroller.h
+ diffeditordocument.cpp diffeditordocument.h
+ diffeditorfactory.cpp diffeditorfactory.h
+ diffeditoricons.h
+ diffeditorplugin.cpp diffeditorplugin.h
+ diffeditorwidgetcontroller.cpp diffeditorwidgetcontroller.h
+ diffutils.cpp diffutils.h
+ diffview.cpp diffview.h
+ selectabletexteditorwidget.cpp selectabletexteditorwidget.h
+ sidebysidediffeditorwidget.cpp sidebysidediffeditorwidget.h
+ unifieddiffeditorwidget.cpp unifieddiffeditorwidget.h
+ EXPLICIT_MOC diffeditor.h
+)
diff --git a/src/plugins/diffeditor/diffeditor.cpp b/src/plugins/diffeditor/diffeditor.cpp
index 3e86febfab..0c1d6563dd 100644
--- a/src/plugins/diffeditor/diffeditor.cpp
+++ b/src/plugins/diffeditor/diffeditor.cpp
@@ -179,7 +179,7 @@ DiffEditor::DiffEditor()
QSizePolicy policy = m_entriesComboBox->sizePolicy();
policy.setHorizontalPolicy(QSizePolicy::Expanding);
m_entriesComboBox->setSizePolicy(policy);
- connect(m_entriesComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_entriesComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &DiffEditor::setCurrentDiffFileIndex);
m_toolBar->addWidget(m_entriesComboBox);
@@ -209,7 +209,7 @@ DiffEditor::DiffEditor()
m_viewSwitcherAction = m_toolBar->addAction(QIcon(), QString());
connect(m_whitespaceButtonAction, &QAction::toggled, this, &DiffEditor::ignoreWhitespaceHasChanged);
- connect(m_contextSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_contextSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &DiffEditor::contextLineCountHasChanged);
connect(m_toggleSyncAction, &QAction::toggled, this, &DiffEditor::toggleSync);
connect(m_toggleDescriptionAction, &QAction::toggled, this, &DiffEditor::toggleDescription);
@@ -317,8 +317,8 @@ void DiffEditor::documentHasChanged()
for (const FileData &diffFile : diffFileList) {
const DiffFileInfo &leftEntry = diffFile.leftFileInfo;
const DiffFileInfo &rightEntry = diffFile.rightFileInfo;
- const QString leftShortFileName = Utils::FileName::fromString(leftEntry.fileName).fileName();
- const QString rightShortFileName = Utils::FileName::fromString(rightEntry.fileName).fileName();
+ const QString leftShortFileName = Utils::FilePath::fromString(leftEntry.fileName).fileName();
+ const QString rightShortFileName = Utils::FilePath::fromString(rightEntry.fileName).fileName();
QString itemText;
QString itemToolTip;
if (leftEntry.fileName == rightEntry.fileName) {
diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp
index eb1a00a451..8c24d09424 100644
--- a/src/plugins/diffeditor/diffeditordocument.cpp
+++ b/src/plugins/diffeditor/diffeditordocument.cpp
@@ -216,7 +216,7 @@ bool DiffEditorDocument::save(QString *errorString, const QString &fileName, boo
const QFileInfo fi(fileName);
setTemporary(false);
- setFilePath(FileName::fromString(fi.absoluteFilePath()));
+ setFilePath(FilePath::fromString(fi.absoluteFilePath()));
setPreferredDisplayName(QString());
emit temporaryStateChanged();
@@ -263,7 +263,7 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const
const QFileInfo fi(fileName);
setTemporary(false);
emit temporaryStateChanged();
- setFilePath(FileName::fromString(fi.absoluteFilePath()));
+ setFilePath(FilePath::fromString(fi.absoluteFilePath()));
setDiffFiles(fileDataList, fi.absolutePath());
}
endReload(ok);
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
index 0975273ee2..c63d969519 100644
--- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
+++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
@@ -401,7 +401,7 @@ void SideDiffEditorWidget::paintSeparator(QPainter &painter,
painter.setPen(foreground);
const QString replacementText = " {" + foldReplacementText(block) + "}; ";
- const int replacementTextWidth = fontMetrics().width(replacementText) + 24;
+ const int replacementTextWidth = fontMetrics().horizontalAdvance(replacementText) + 24;
int x = replacementTextWidth + int(offset.x());
if (x < document()->documentMargin()
|| !TextDocumentLayout::isFolded(block)) {
diff --git a/src/plugins/emacskeys/CMakeLists.txt b/src/plugins/emacskeys/CMakeLists.txt
new file mode 100644
index 0000000000..20fd37aa29
--- /dev/null
+++ b/src/plugins/emacskeys/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_plugin(EmacsKeys
+ PLUGIN_DEPENDS Core TextEditor
+ SOURCES
+ emacskeysconstants.h
+ emacskeysplugin.cpp emacskeysplugin.h
+ emacskeysstate.cpp emacskeysstate.h
+)
diff --git a/src/plugins/fakevim/CMakeLists.txt b/src/plugins/fakevim/CMakeLists.txt
new file mode 100644
index 0000000000..0dd4f690f2
--- /dev/null
+++ b/src/plugins/fakevim/CMakeLists.txt
@@ -0,0 +1,19 @@
+if (WITH_TESTS)
+ set(TST_COMPONENT CppEditor CppTools)
+endif()
+
+add_qtc_plugin(FakeVim
+ PLUGIN_DEPENDS Core TextEditor ${TST_COMPONENT}
+ SOURCES ${TEST_SOURCES}
+ fakevim.qrc
+ fakevimactions.cpp fakevimactions.h
+ fakevimhandler.cpp fakevimhandler.h
+ fakevimoptions.ui
+ fakevimplugin.cpp fakevimplugin.h
+ fakevimtr.h
+)
+
+extend_qtc_plugin(FakeVim
+ CONDITION WITH_TESTS
+ SOURCES fakevim_test.cpp
+)
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 70db12a6b4..955f3f6062 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -2061,7 +2061,7 @@ public:
void pasteText(bool afterCursor);
- void cutSelectedText();
+ void cutSelectedText(int reg = 0);
void joinLines(int count, bool preserveSpace = false);
@@ -2155,6 +2155,7 @@ public:
bool handleExWriteCommand(const ExCommand &cmd);
bool handleExEchoCommand(const ExCommand &cmd);
+ void setTabSize(int tabSize);
void setupCharClass();
int charClass(QChar c, bool simple) const;
signed char m_charClass[256];
@@ -2686,17 +2687,22 @@ void FakeVimHandler::Private::ensureCursorVisible()
void FakeVimHandler::Private::updateEditor()
{
- const int charWidth = QFontMetrics(EDITOR(font())).width(' ');
- EDITOR(setTabStopWidth(charWidth * config(ConfigTabStop).toInt()));
+ setTabSize(config(ConfigTabStop).toInt());
setupCharClass();
}
+void FakeVimHandler::Private::setTabSize(int tabSize)
+{
+ const int charWidth = QFontMetrics(EDITOR(font())).horizontalAdvance(' ');
+ const int width = charWidth * tabSize;
+ EDITOR(setTabStopDistance(width));
+}
+
void FakeVimHandler::Private::restoreWidget(int tabSize)
{
//EDITOR(removeEventFilter(q));
//EDITOR(setReadOnly(m_wasReadOnly));
- const int charWidth = QFontMetrics(EDITOR(font())).width(' ');
- EDITOR(setTabStopWidth(charWidth * tabSize));
+ setTabSize(tabSize);
g.visualMode = NoVisualMode;
// Force "ordinary" cursor.
setThinCursor();
@@ -7231,7 +7237,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
bool pasteAfter = isVisualMode() ? false : afterCursor;
if (isVisualMode())
- cutSelectedText();
+ cutSelectedText('"');
switch (rangeMode) {
case RangeCharMode: {
@@ -7312,7 +7318,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
endEditBlock();
}
-void FakeVimHandler::Private::cutSelectedText()
+void FakeVimHandler::Private::cutSelectedText(int reg)
{
pushUndoState();
@@ -7323,8 +7329,11 @@ void FakeVimHandler::Private::cutSelectedText()
if (visualMode && g.rangemode == RangeCharMode)
++range.endPos;
+ if (!reg)
+ reg = m_register;
+
g.submode = DeleteSubMode;
- yankText(range, m_register);
+ yankText(range, reg);
removeText(range);
g.submode = NoSubMode;
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index 1807efb910..bb73e18141 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -245,7 +245,7 @@ public:
connect(&m_timerUpdate, &QTimer::timeout,
this, &RelativeNumbersColumn::followEditorLayout);
- auto start = static_cast<void(QTimer::*)()>(&QTimer::start);
+ auto start = QOverload<>::of(&QTimer::start);
connect(m_editor, &QPlainTextEdit::cursorPositionChanged,
&m_timerUpdate, start);
connect(m_editor->verticalScrollBar(), &QAbstractSlider::valueChanged,
diff --git a/src/plugins/genericprojectmanager/CMakeLists.txt b/src/plugins/genericprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..d41571b5ff
--- /dev/null
+++ b/src/plugins/genericprojectmanager/CMakeLists.txt
@@ -0,0 +1,22 @@
+if (WITH_TESTS)
+ set(TST_COMPONENT CppEditor)
+endif()
+
+add_qtc_plugin(GenericProjectManager
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer QtSupport TextEditor ${TST_COMPONENT}
+ SOURCES ${TEST_SOURCES}
+ filesselectionwizardpage.cpp filesselectionwizardpage.h
+ genericbuildconfiguration.cpp genericbuildconfiguration.h
+ genericmakestep.cpp genericmakestep.h
+ genericproject.cpp genericproject.h
+ genericprojectconstants.h
+ genericprojectfileseditor.cpp genericprojectfileseditor.h
+ genericprojectmanager.qrc
+ genericprojectplugin.cpp genericprojectplugin.h
+ genericprojectwizard.cpp genericprojectwizard.h
+)
+
+extend_qtc_plugin(GenericProjectManager
+ CONDITION WITH_TESTS
+ SOURCES genericprojectplugin_test.cpp
+)
diff --git a/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp b/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp
index 0f82ba8d6e..c7f839c06e 100644
--- a/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp
+++ b/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp
@@ -59,8 +59,8 @@ FilesSelectionWizardPage::FilesSelectionWizardPage(GenericProjectWizardDialog *g
void FilesSelectionWizardPage::initializePage()
{
- m_filesWidget->resetModel(Utils::FileName::fromString(m_genericProjectWizardDialog->path()),
- Utils::FileNameList());
+ m_filesWidget->resetModel(Utils::FilePath::fromString(m_genericProjectWizardDialog->path()),
+ Utils::FilePathList());
}
void FilesSelectionWizardPage::cleanupPage()
@@ -73,12 +73,12 @@ bool FilesSelectionWizardPage::isComplete() const
return m_filesWidget->hasFilesSelected();
}
-Utils::FileNameList FilesSelectionWizardPage::selectedPaths() const
+Utils::FilePathList FilesSelectionWizardPage::selectedPaths() const
{
return m_filesWidget->selectedPaths();
}
-Utils::FileNameList FilesSelectionWizardPage::selectedFiles() const
+Utils::FilePathList FilesSelectionWizardPage::selectedFiles() const
{
return m_filesWidget->selectedFiles();
}
diff --git a/src/plugins/genericprojectmanager/filesselectionwizardpage.h b/src/plugins/genericprojectmanager/filesselectionwizardpage.h
index 721f1d4cd5..eddf4a9c21 100644
--- a/src/plugins/genericprojectmanager/filesselectionwizardpage.h
+++ b/src/plugins/genericprojectmanager/filesselectionwizardpage.h
@@ -45,8 +45,8 @@ public:
bool isComplete() const override;
void initializePage() override;
void cleanupPage() override;
- Utils::FileNameList selectedFiles() const;
- Utils::FileNameList selectedPaths() const;
+ Utils::FilePathList selectedFiles() const;
+ Utils::FilePathList selectedPaths() const;
private:
GenericProjectWizardDialog *m_genericProjectWizardDialog;
diff --git a/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp b/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
index 28dfdc86bb..4c94efab5b 100644
--- a/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
+++ b/src/plugins/genericprojectmanager/genericbuildconfiguration.cpp
@@ -29,25 +29,22 @@
#include "genericproject.h"
#include "genericprojectconstants.h"
-#include <coreplugin/icore.h>
-
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectconfigurationaspects.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
-#include <projectexplorer/toolchain.h>
+
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
-#include <utils/mimetypes/mimedatabase.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
-#include <QFormLayout>
-#include <QInputDialog>
using namespace ProjectExplorer;
+using namespace Utils;
namespace GenericProjectManager {
namespace Internal {
@@ -55,6 +52,9 @@ namespace Internal {
GenericBuildConfiguration::GenericBuildConfiguration(Target *parent, Core::Id id)
: BuildConfiguration(parent, id)
{
+ setConfigWidgetDisplayName(tr("Generic Manager"));
+ setBuildDirectoryHistoryCompleter("Generic.BuildDir.History");
+
updateCacheAndEmitEnvironmentChanged();
}
@@ -71,10 +71,6 @@ void GenericBuildConfiguration::initialize(const BuildInfo &info)
updateCacheAndEmitEnvironmentChanged();
}
-NamedWidget *GenericBuildConfiguration::createConfigWidget()
-{
- return new GenericBuildSettingsWidget(this);
-}
/*!
\class GenericBuildConfigurationFactory
@@ -98,14 +94,14 @@ QList<BuildInfo> GenericBuildConfigurationFactory::availableBuilds(const Target
QList<BuildInfo> GenericBuildConfigurationFactory::availableSetups(const Kit *k, const QString &projectPath) const
{
- BuildInfo info = createBuildInfo(k, Project::projectDirectory(Utils::FileName::fromString(projectPath)));
+ BuildInfo info = createBuildInfo(k, Project::projectDirectory(Utils::FilePath::fromString(projectPath)));
//: The name of the build configuration created by default for a generic project.
info.displayName = tr("Default");
return {info};
}
BuildInfo GenericBuildConfigurationFactory::createBuildInfo(const Kit *k,
- const Utils::FileName &buildDir) const
+ const Utils::FilePath &buildDir) const
{
BuildInfo info(this);
info.typeName = tr("Build");
@@ -121,50 +117,11 @@ BuildConfiguration::BuildType GenericBuildConfiguration::buildType() const
void GenericBuildConfiguration::addToEnvironment(Utils::Environment &env) const
{
- prependCompilerPathToEnvironment(env);
- const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
+ prependCompilerPathToEnvironment(target()->kit(), env);
+ const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target()->kit());
if (qt)
env.prependOrSetPath(qt->binPath().toString());
}
-////////////////////////////////////////////////////////////////////////////////////
-// GenericBuildSettingsWidget
-////////////////////////////////////////////////////////////////////////////////////
-
-GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericBuildConfiguration *bc)
- : m_buildConfiguration(nullptr)
-{
- auto fl = new QFormLayout(this);
- fl->setContentsMargins(0, -1, 0, -1);
- fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
-
- // build directory
- m_pathChooser = new Utils::PathChooser(this);
- m_pathChooser->setHistoryCompleter("Generic.BuildDir.History");
- m_pathChooser->setEnabled(true);
- fl->addRow(tr("Build directory:"), m_pathChooser);
- connect(m_pathChooser, &Utils::PathChooser::rawPathChanged,
- this, &GenericBuildSettingsWidget::buildDirectoryChanged);
-
- m_buildConfiguration = bc;
- m_pathChooser->setBaseFileName(bc->target()->project()->projectDirectory());
- m_pathChooser->setEnvironment(bc->environment());
- m_pathChooser->setPath(m_buildConfiguration->rawBuildDirectory().toString());
- setDisplayName(tr("Generic Manager"));
-
- connect(bc, &GenericBuildConfiguration::environmentChanged,
- this, &GenericBuildSettingsWidget::environmentHasChanged);
-}
-
-void GenericBuildSettingsWidget::buildDirectoryChanged()
-{
- m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_pathChooser->rawPath()));
-}
-
-void GenericBuildSettingsWidget::environmentHasChanged()
-{
- m_pathChooser->setEnvironment(m_buildConfiguration->environment());
-}
-
} // namespace Internal
} // namespace GenericProjectManager
diff --git a/src/plugins/genericprojectmanager/genericbuildconfiguration.h b/src/plugins/genericprojectmanager/genericbuildconfiguration.h
index e4d2e3e65a..fdd97c36cf 100644
--- a/src/plugins/genericprojectmanager/genericbuildconfiguration.h
+++ b/src/plugins/genericprojectmanager/genericbuildconfiguration.h
@@ -26,12 +26,8 @@
#pragma once
#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/namedwidget.h>
-namespace Utils {
-class FileName;
-class PathChooser;
-} // namespace Utils
+namespace Utils { class FilePath; }
namespace GenericProjectManager {
namespace Internal {
@@ -44,7 +40,6 @@ class GenericBuildConfiguration : public ProjectExplorer::BuildConfiguration
GenericBuildConfiguration(ProjectExplorer::Target *parent, Core::Id id);
void initialize(const ProjectExplorer::BuildInfo &info) override;
- ProjectExplorer::NamedWidget *createConfigWidget() override;
BuildType buildType() const override;
void addToEnvironment(Utils::Environment &env) const final;
};
@@ -62,22 +57,7 @@ private:
QList<ProjectExplorer::BuildInfo> availableSetups(const ProjectExplorer::Kit *k,
const QString &projectPath) const override;
- ProjectExplorer::BuildInfo createBuildInfo(const ProjectExplorer::Kit *k, const Utils::FileName &buildDir) const;
-};
-
-class GenericBuildSettingsWidget : public ProjectExplorer::NamedWidget
-{
- Q_OBJECT
-
-public:
- GenericBuildSettingsWidget(GenericBuildConfiguration *bc);
-
-private:
- void buildDirectoryChanged();
- void environmentHasChanged();
-
- Utils::PathChooser *m_pathChooser;
- GenericBuildConfiguration *m_buildConfiguration;
+ ProjectExplorer::BuildInfo createBuildInfo(const ProjectExplorer::Kit *k, const Utils::FilePath &buildDir) const;
};
} // namespace Internal
diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp
index 3162fecd8e..faeb2cf702 100644
--- a/src/plugins/genericprojectmanager/genericproject.cpp
+++ b/src/plugins/genericprojectmanager/genericproject.cpp
@@ -82,7 +82,7 @@ namespace Internal {
class GenericProjectFile : public Core::IDocument
{
public:
- GenericProjectFile(GenericProject *parent, const FileName &fileName,
+ GenericProjectFile(GenericProject *parent, const FilePath &fileName,
GenericProject::RefreshOptions options) :
m_project(parent),
m_options(options)
@@ -129,8 +129,6 @@ public:
setDisplayName(project->projectFilePath().toFileInfo().completeBaseName());
}
- bool showInSimpleTree() const override { return true; }
-
bool supportsAction(ProjectAction action, const Node *) const override
{
return action == AddNewFile
@@ -172,7 +170,7 @@ static bool writeFile(const QString &filePath, const QString &contents)
return saver.write(contents.toUtf8()) && saver.finalize();
}
-GenericProject::GenericProject(const Utils::FileName &fileName) :
+GenericProject::GenericProject(const Utils::FilePath &fileName) :
Project(Constants::GENERICMIMETYPE, fileName, [this]() { refresh(Everything); }),
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater),
m_deployFileWatcher(new FileSystemWatcher(this))
@@ -203,19 +201,19 @@ GenericProject::GenericProject(const Utils::FileName &fileName) :
}
m_filesIDocument
- = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_filesFileName),
+ = new ProjectDocument(Constants::GENERICMIMETYPE, FilePath::fromString(m_filesFileName),
[this]() { refresh(Files); });
m_includesIDocument
- = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_includesFileName),
+ = new ProjectDocument(Constants::GENERICMIMETYPE, FilePath::fromString(m_includesFileName),
[this]() { refresh(Configuration); });
m_configIDocument
- = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_configFileName),
+ = new ProjectDocument(Constants::GENERICMIMETYPE, FilePath::fromString(m_configFileName),
[this]() { refresh(Configuration); });
m_cxxFlagsIDocument
- = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_cxxflagsFileName),
+ = new ProjectDocument(Constants::GENERICMIMETYPE, FilePath::fromString(m_cxxflagsFileName),
[this]() { refresh(Configuration); });
m_cFlagsIDocument
- = new ProjectDocument(Constants::GENERICMIMETYPE, FileName::fromString(m_cflagsFileName),
+ = new ProjectDocument(Constants::GENERICMIMETYPE, FilePath::fromString(m_cflagsFileName),
[this]() { refresh(Configuration); });
connect(m_deployFileWatcher, &FileSystemWatcher::fileChanged,
@@ -384,6 +382,23 @@ void GenericProject::parseProject(RefreshOptions options)
}
}
+QString GenericProject::findCommonSourceRoot(const QStringList &list)
+{
+ QString root = list.front();
+ for (const QString &item : list) {
+ if (root.length() > item.length())
+ root.truncate(item.length());
+
+ for (int i = 0; i < root.length(); ++i) {
+ if (root[i] != item[i]) {
+ root.truncate(i);
+ break;
+ }
+ }
+ }
+ return QFileInfo(root).absolutePath();
+}
+
void GenericProject::refresh(RefreshOptions options)
{
emitParsingStarted();
@@ -392,30 +407,28 @@ void GenericProject::refresh(RefreshOptions options)
if (options & Files) {
auto newRoot = std::make_unique<GenericProjectNode>(this);
+ // find the common base directory of all source files
+ Utils::FilePath baseDir = FilePath::fromFileInfo(QFileInfo(findCommonSourceRoot(m_files)));
+
for (const QString &f : m_files) {
FileType fileType = FileType::Source; // ### FIXME
if (f.endsWith(".qrc"))
fileType = FileType::Resource;
- newRoot->addNestedNode(std::make_unique<FileNode>(FileName::fromString(f), fileType,
- false));
+ newRoot->addNestedNode(std::make_unique<FileNode>(FilePath::fromString(f), fileType), baseDir);
}
- newRoot->addNestedNode(std::make_unique<FileNode>(FileName::fromString(m_filesFileName),
- FileType::Project,
- /* generated = */ false));
- newRoot->addNestedNode(std::make_unique<FileNode>(FileName::fromString(m_includesFileName),
- FileType::Project,
- /* generated = */ false));
- newRoot->addNestedNode(std::make_unique<FileNode>(FileName::fromString(m_configFileName),
- FileType::Project,
- /* generated = */ false));
- newRoot->addNestedNode(std::make_unique<FileNode>(FileName::fromString(m_cxxflagsFileName),
- FileType::Project,
- /* generated = */ false));
- newRoot->addNestedNode(std::make_unique<FileNode>(FileName::fromString(m_cflagsFileName),
- FileType::Project,
- /* generated = */ false));
-
+ newRoot->addNestedNode(std::make_unique<FileNode>(FilePath::fromString(m_filesFileName),
+ FileType::Project));
+ newRoot->addNestedNode(std::make_unique<FileNode>(FilePath::fromString(m_includesFileName),
+ FileType::Project));
+ newRoot->addNestedNode(std::make_unique<FileNode>(FilePath::fromString(m_configFileName),
+ FileType::Project));
+ newRoot->addNestedNode(std::make_unique<FileNode>(FilePath::fromString(m_cxxflagsFileName),
+ FileType::Project));
+ newRoot->addNestedNode(std::make_unique<FileNode>(FilePath::fromString(m_cflagsFileName),
+ FileType::Project));
+
+ newRoot->compress();
setRootProjectNode(std::move(newRoot));
}
@@ -458,7 +471,7 @@ QStringList GenericProject::processEntries(const QStringList &paths,
trimmedPath = buildEnv.expandVariables(trimmedPath);
trimmedPath = expander->expand(trimmedPath);
- trimmedPath = Utils::FileName::fromUserInput(trimmedPath).toString();
+ trimmedPath = Utils::FilePath::fromUserInput(trimmedPath).toString();
fileInfo.setFile(projectDir, trimmedPath);
if (fileInfo.exists()) {
@@ -493,14 +506,14 @@ void GenericProject::refreshCppCodeModel()
void GenericProject::updateDeploymentData()
{
static const QString fileName("QtCreatorDeployment.txt");
- Utils::FileName deploymentFilePath;
+ Utils::FilePath deploymentFilePath;
if (activeTarget() && activeTarget()->activeBuildConfiguration()) {
deploymentFilePath = activeTarget()->activeBuildConfiguration()->buildDirectory()
- .appendPath(fileName);
+ .pathAppended(fileName);
}
bool hasDeploymentData = QFileInfo::exists(deploymentFilePath.toString());
if (!hasDeploymentData) {
- deploymentFilePath = projectDirectory().appendPath(fileName);
+ deploymentFilePath = projectDirectory().pathAppended(fileName);
hasDeploymentData = QFileInfo::exists(deploymentFilePath.toString());
}
if (hasDeploymentData) {
@@ -574,5 +587,10 @@ Project::RestoreResult GenericProject::fromMap(const QVariantMap &map, QString *
return RestoreResult::Ok;
}
+ProjectExplorer::DeploymentKnowledge GenericProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Approximative;
+}
+
} // namespace Internal
} // namespace GenericProjectManager
diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h
index 0a1469588c..d914ddc149 100644
--- a/src/plugins/genericprojectmanager/genericproject.h
+++ b/src/plugins/genericprojectmanager/genericproject.h
@@ -38,7 +38,7 @@ class GenericProject : public ProjectExplorer::Project
Q_OBJECT
public:
- explicit GenericProject(const Utils::FileName &filename);
+ explicit GenericProject(const Utils::FilePath &filename);
~GenericProject() override;
bool addFiles(const QStringList &filePaths);
@@ -58,12 +58,15 @@ protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
private:
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+
bool saveRawFileList(const QStringList &rawFileList);
bool saveRawList(const QStringList &rawList, const QString &fileName);
void parseProject(RefreshOptions options);
QStringList processEntries(const QStringList &paths,
QHash<QString, QString> *map = nullptr) const;
+ static QString findCommonSourceRoot(const QStringList &list);
void refreshCppCodeModel();
void updateDeploymentData();
void activeTargetWasChanged();
diff --git a/src/plugins/genericprojectmanager/genericprojectplugin.cpp b/src/plugins/genericprojectmanager/genericprojectplugin.cpp
index c92b728f10..73183ffb13 100644
--- a/src/plugins/genericprojectmanager/genericprojectplugin.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectplugin.cpp
@@ -101,7 +101,7 @@ GenericProjectPluginPrivate::GenericProjectPluginPrivate()
genericProject->files(Project::AllFiles),
ICore::mainWindow());
if (sfd.exec() == QDialog::Accepted)
- genericProject->setFiles(Utils::transform(sfd.selectedFiles(), &Utils::FileName::toString));
+ genericProject->setFiles(Utils::transform(sfd.selectedFiles(), &Utils::FilePath::toString));
});
}
diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.cpp b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
index ce8e4034ee..204a6e4f43 100644
--- a/src/plugins/genericprojectmanager/genericprojectwizard.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
@@ -83,12 +83,12 @@ QString GenericProjectWizardDialog::path() const
return m_firstPage->path();
}
-Utils::FileNameList GenericProjectWizardDialog::selectedPaths() const
+Utils::FilePathList GenericProjectWizardDialog::selectedPaths() const
{
return m_secondPage->selectedPaths();
}
-Utils::FileNameList GenericProjectWizardDialog::selectedFiles() const
+Utils::FilePathList GenericProjectWizardDialog::selectedFiles() const
{
return m_secondPage->selectedFiles();
}
@@ -151,7 +151,7 @@ Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w,
const QString configFileName = QFileInfo(dir, projectName + QLatin1String(".config")).absoluteFilePath();
const QString cxxflagsFileName = QFileInfo(dir, projectName + QLatin1String(".cxxflags")).absoluteFilePath();
const QString cflagsFileName = QFileInfo(dir, projectName + QLatin1String(".cflags")).absoluteFilePath();
- const QStringList paths = Utils::transform(wizard->selectedPaths(), &Utils::FileName::toString);
+ const QStringList paths = Utils::transform(wizard->selectedPaths(), &Utils::FilePath::toString);
Utils::MimeType headerTy = Utils::mimeTypeForName(QLatin1String("text/x-chdr"));
@@ -175,7 +175,7 @@ Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w,
generatedCreatorFile.setContents(QLatin1String("[General]\n"));
generatedCreatorFile.setAttributes(Core::GeneratedFile::OpenProjectAttribute);
- QStringList sources = Utils::transform(wizard->selectedFiles(), &Utils::FileName::toString);
+ QStringList sources = Utils::transform(wizard->selectedFiles(), &Utils::FilePath::toString);
for (int i = 0; i < sources.length(); ++i)
sources[i] = dir.relativeFilePath(sources[i]);
Utils::sort(sources);
diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.h b/src/plugins/genericprojectmanager/genericprojectwizard.h
index fbe8590faa..5de68be69c 100644
--- a/src/plugins/genericprojectmanager/genericprojectwizard.h
+++ b/src/plugins/genericprojectmanager/genericprojectwizard.h
@@ -46,8 +46,8 @@ public:
QString path() const;
void setPath(const QString &path);
- Utils::FileNameList selectedFiles() const;
- Utils::FileNameList selectedPaths() const;
+ Utils::FilePathList selectedFiles() const;
+ Utils::FilePathList selectedPaths() const;
QString projectName() const;
diff --git a/src/plugins/git/CMakeLists.txt b/src/plugins/git/CMakeLists.txt
new file mode 100644
index 0000000000..7bf50b3276
--- /dev/null
+++ b/src/plugins/git/CMakeLists.txt
@@ -0,0 +1,41 @@
+add_qtc_plugin(Git
+ PLUGIN_DEPENDS Core DiffEditor TextEditor VcsBase
+ SOURCES
+ annotationhighlighter.cpp annotationhighlighter.h
+ branchadddialog.cpp branchadddialog.h branchadddialog.ui
+ branchcheckoutdialog.cpp branchcheckoutdialog.h branchcheckoutdialog.ui
+ branchmodel.cpp branchmodel.h
+ branchview.cpp branchview.h
+ changeselectiondialog.cpp changeselectiondialog.h changeselectiondialog.ui
+ commitdata.cpp commitdata.h
+ gerrit/authenticationdialog.cpp gerrit/authenticationdialog.h gerrit/authenticationdialog.ui
+ gerrit/branchcombobox.cpp gerrit/branchcombobox.h
+ gerrit/gerritdialog.cpp gerrit/gerritdialog.h gerrit/gerritdialog.ui
+ gerrit/gerritmodel.cpp gerrit/gerritmodel.h
+ gerrit/gerritoptionspage.cpp gerrit/gerritoptionspage.h
+ gerrit/gerritparameters.cpp gerrit/gerritparameters.h
+ gerrit/gerritplugin.cpp gerrit/gerritplugin.h
+ gerrit/gerritpushdialog.cpp gerrit/gerritpushdialog.h gerrit/gerritpushdialog.ui
+ gerrit/gerritremotechooser.cpp gerrit/gerritremotechooser.h
+ gerrit/gerritserver.cpp gerrit/gerritserver.h
+ git.qrc
+ gitclient.cpp gitclient.h
+ gitconstants.h
+ giteditor.cpp giteditor.h
+ gitgrep.cpp gitgrep.h
+ githighlighters.cpp githighlighters.h
+ gitplugin.cpp gitplugin.h
+ gitsettings.cpp gitsettings.h
+ gitsubmiteditor.cpp gitsubmiteditor.h
+ gitsubmiteditorwidget.cpp gitsubmiteditorwidget.h
+ gitsubmitpanel.ui
+ gitutils.cpp gitutils.h
+ gitversioncontrol.cpp gitversioncontrol.h
+ logchangedialog.cpp logchangedialog.h
+ mergetool.cpp mergetool.h
+ remoteadditiondialog.ui
+ remotedialog.cpp remotedialog.h remotedialog.ui
+ remotemodel.cpp remotemodel.h
+ settingspage.cpp settingspage.h settingspage.ui
+ stashdialog.cpp stashdialog.h stashdialog.ui
+)
diff --git a/src/plugins/git/branchadddialog.cpp b/src/plugins/git/branchadddialog.cpp
index edc50889ec..8a131a363c 100644
--- a/src/plugins/git/branchadddialog.cpp
+++ b/src/plugins/git/branchadddialog.cpp
@@ -105,13 +105,31 @@ QWidget *BranchValidationDelegate::createEditor(QWidget *parent,
return lineEdit;
}
-BranchAddDialog::BranchAddDialog(const QStringList &localBranches, bool addBranch, QWidget *parent) :
+BranchAddDialog::BranchAddDialog(const QStringList &localBranches, Type type, QWidget *parent) :
QDialog(parent),
m_ui(new Ui::BranchAddDialog)
{
m_ui->setupUi(this);
+ m_ui->trackingCheckBox->setVisible(false);
setCheckoutVisible(false);
- setWindowTitle(addBranch ? tr("Add Branch") : tr("Rename Branch"));
+
+ switch (type) {
+ case BranchAddDialog::AddBranch:
+ setWindowTitle(tr("Add Branch"));
+ break;
+ case BranchAddDialog::RenameBranch:
+ setWindowTitle(tr("Rename Branch"));
+ break;
+ case BranchAddDialog::AddTag:
+ setWindowTitle(tr("Add Tag"));
+ m_ui->branchNameLabel->setText(tr("Tag name:"));
+ break;
+ case BranchAddDialog::RenameTag:
+ setWindowTitle(tr("Rename Tag"));
+ m_ui->branchNameLabel->setText(tr("Tag name:"));
+ break;
+ }
+
m_ui->branchNameEdit->setValidator(new BranchNameValidator(localBranches, this));
connect(m_ui->branchNameEdit, &QLineEdit::textChanged, this, &BranchAddDialog::updateButtonStatus);
}
@@ -134,14 +152,14 @@ QString BranchAddDialog::branchName() const
void BranchAddDialog::setTrackedBranchName(const QString &name, bool remote)
{
- m_ui->trackingCheckBox->setVisible(true);
- if (!name.isEmpty()) {
- m_ui->trackingCheckBox->setText(remote ? tr("Track remote branch \'%1\'").arg(name) :
- tr("Track local branch \'%1\'").arg(name));
- m_ui->trackingCheckBox->setChecked(remote);
- } else {
+ if (name.isEmpty()) {
m_ui->trackingCheckBox->setVisible(false);
m_ui->trackingCheckBox->setChecked(false);
+ } else {
+ m_ui->trackingCheckBox->setText(remote ? tr("Track remote branch \"%1\"").arg(name) :
+ tr("Track local branch \"%1\"").arg(name));
+ m_ui->trackingCheckBox->setVisible(true);
+ m_ui->trackingCheckBox->setChecked(remote);
}
}
diff --git a/src/plugins/git/branchadddialog.h b/src/plugins/git/branchadddialog.h
index e90e71b581..fa2100bf2c 100644
--- a/src/plugins/git/branchadddialog.h
+++ b/src/plugins/git/branchadddialog.h
@@ -51,7 +51,14 @@ class BranchAddDialog : public QDialog
Q_OBJECT
public:
- BranchAddDialog(const QStringList &localBranches, bool addBranch, QWidget *parent);
+ enum Type {
+ AddBranch,
+ RenameBranch,
+ AddTag,
+ RenameTag
+ };
+
+ BranchAddDialog(const QStringList &localBranches, Type type, QWidget *parent);
~BranchAddDialog() override;
void setBranchName(const QString &);
diff --git a/src/plugins/git/branchadddialog.ui b/src/plugins/git/branchadddialog.ui
index 4ee0b5d787..41f9fc5caf 100644
--- a/src/plugins/git/branchadddialog.ui
+++ b/src/plugins/git/branchadddialog.ui
@@ -32,11 +32,7 @@
</widget>
</item>
<item row="2" column="0" colspan="2">
- <widget class="QCheckBox" name="trackingCheckBox">
- <property name="text">
- <string>CheckBox</string>
- </property>
- </widget>
+ <widget class="QCheckBox" name="trackingCheckBox"/>
</item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp
index cd2af5b02b..bf74f7b32c 100644
--- a/src/plugins/git/branchmodel.cpp
+++ b/src/plugins/git/branchmodel.cpp
@@ -36,6 +36,8 @@
#include <QDateTime>
#include <QFont>
+#include <set>
+
using namespace VcsBase;
namespace Git {
@@ -199,17 +201,24 @@ public:
class BranchModel::Private
{
public:
- Private(GitClient *client) :
+ explicit Private(GitClient *client) :
client(client),
rootNode(new BranchNode)
{
}
+ Private(const Private &) = delete;
+ Private &operator=(const Private &) = delete;
+
~Private()
{
delete rootNode;
}
+ bool hasTags() const { return rootNode->children.count() > Tags; }
+ void parseOutputLine(const QString &line, bool force = false);
+ void flushOldEntries();
+
GitClient *client;
QString workingDirectory;
BranchNode *rootNode;
@@ -220,6 +229,17 @@ public:
QStringList obsoleteLocalBranches;
Utils::FileSystemWatcher fsWatcher;
bool oldBranchesIncluded = false;
+
+ struct OldEntry
+ {
+ QString line;
+ QDateTime dateTime;
+ bool operator<(const OldEntry &other) const { return dateTime < other.dateTime; }
+ };
+
+ BranchNode *currentRoot = nullptr;
+ QString currentRemote;
+ std::set<OldEntry> oldEntries;
};
// --------------------------------------------------------------------------
@@ -366,7 +386,7 @@ void BranchModel::clear()
while (root->count())
delete root->children.takeLast();
}
- if (hasTags())
+ if (d->hasTags())
d->rootNode->children.takeLast();
d->currentSha.clear();
@@ -403,7 +423,8 @@ bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage
}
const QStringList lines = output.split('\n');
for (const QString &l : lines)
- parseOutputLine(l);
+ d->parseOutputLine(l);
+ d->flushOldEntries();
if (d->currentBranch) {
if (d->currentBranch->isLocal())
@@ -516,10 +537,7 @@ QDateTime BranchModel::dateTime(const QModelIndex &idx) const
return node->dateTime;
}
-bool BranchModel::hasTags() const
-{
- return d->rootNode->children.count() > Tags;
-}
+
bool BranchModel::isHead(const QModelIndex &idx) const
{
@@ -547,7 +565,7 @@ bool BranchModel::isLeaf(const QModelIndex &idx) const
bool BranchModel::isTag(const QModelIndex &idx) const
{
- if (!idx.isValid() || !hasTags())
+ if (!idx.isValid() || !d->hasTags())
return false;
return indexToNode(idx)->isTag();
}
@@ -648,8 +666,6 @@ QModelIndex BranchModel::addBranch(const QString &name, bool track, const QModel
startSha = sha(startPoint);
branchDateTime = dateTime(startPoint);
} else {
- QString output;
- QString errorMessage;
const QStringList arguments({"-n1", "--format=%H %ct"});
if (d->client->synchronousLog(d->workingDirectory, arguments, &output, &errorMessage,
VcsCommand::SuppressCommandLogging)) {
@@ -722,7 +738,7 @@ Utils::optional<QString> BranchModel::remoteName(const QModelIndex &idx) const
return Utils::nullopt;
}
-void BranchModel::parseOutputLine(const QString &line)
+void BranchModel::Private::parseOutputLine(const QString &line, bool force)
{
if (line.size() < 3)
return;
@@ -734,7 +750,7 @@ void BranchModel::parseOutputLine(const QString &line)
const QString fullName = lineParts.at(1);
const QString upstream = lineParts.at(2);
QDateTime dateTime;
- const bool current = (sha == d->currentSha);
+ const bool current = (sha == currentSha);
QString strDateTime = lineParts.at(5);
if (strDateTime.isEmpty())
strDateTime = lineParts.at(4);
@@ -743,34 +759,57 @@ void BranchModel::parseOutputLine(const QString &line)
dateTime = QDateTime::fromSecsSinceEpoch(timeT);
}
- if (!d->oldBranchesIncluded && !current && dateTime.isValid()) {
+ bool isOld = false;
+ if (!oldBranchesIncluded && !force && !current && dateTime.isValid()) {
const qint64 age = dateTime.daysTo(QDateTime::currentDateTime());
- if (age > Constants::OBSOLETE_COMMIT_AGE_IN_DAYS) {
- const QString heads = "refs/heads/";
- if (fullName.startsWith(heads))
- d->obsoleteLocalBranches.append(fullName.mid(heads.size()));
- return;
- }
+ isOld = age > Constants::OBSOLETE_COMMIT_AGE_IN_DAYS;
}
- bool showTags = d->client->settings().boolValue(GitSettings::showTagsKey);
+ bool showTags = client->settings().boolValue(GitSettings::showTagsKey);
// insert node into tree:
QStringList nameParts = fullName.split('/');
nameParts.removeFirst(); // remove refs...
BranchNode *root = nullptr;
+ BranchNode *oldEntriesRoot = nullptr;
+ RootNodes rootType;
if (nameParts.first() == "heads") {
- root = d->rootNode->children.at(LocalBranches);
+ rootType = LocalBranches;
+ if (isOld)
+ obsoleteLocalBranches.append(fullName.mid(sizeof("refs/heads/")-1));
} else if (nameParts.first() == "remotes") {
- root = d->rootNode->children.at(RemoteBranches);
+ rootType = RemoteBranches;
+ const QString remoteName = nameParts.at(1);
+ root = rootNode->children.at(rootType);
+ oldEntriesRoot = root->childOfName(remoteName);
+ if (!oldEntriesRoot)
+ oldEntriesRoot = root->append(new BranchNode(remoteName));
} else if (showTags && nameParts.first() == "tags") {
if (!hasTags()) // Tags is missing, add it
- d->rootNode->append(new BranchNode(tr("Tags"), "refs/tags"));
- root = d->rootNode->children.at(Tags);
+ rootNode->append(new BranchNode(tr("Tags"), "refs/tags"));
+ rootType = Tags;
} else {
return;
}
+ root = rootNode->children.at(rootType);
+ if (!oldEntriesRoot)
+ oldEntriesRoot = root;
+ if (isOld) {
+ if (oldEntriesRoot->children.size() > Constants::MAX_OBSOLETE_COMMITS_TO_DISPLAY)
+ return;
+ if (currentRoot != oldEntriesRoot) {
+ flushOldEntries();
+ currentRoot = oldEntriesRoot;
+ }
+ const bool eraseOldestEntry = oldEntries.size() >= Constants::MAX_OBSOLETE_COMMITS_TO_DISPLAY;
+ if (!eraseOldestEntry || dateTime > oldEntries.begin()->dateTime) {
+ if (eraseOldestEntry)
+ oldEntries.erase(oldEntries.begin());
+ oldEntries.insert(Private::OldEntry{line, dateTime});
+ }
+ return;
+ }
nameParts.removeFirst();
// limit depth of list. Git basically only ever wants one / and considers the rest as part of
@@ -786,7 +825,19 @@ void BranchModel::parseOutputLine(const QString &line)
auto newNode = new BranchNode(name, sha, upstream, dateTime);
root->insert(nameParts, newNode);
if (current)
- d->currentBranch = newNode;
+ currentBranch = newNode;
+}
+
+void BranchModel::Private::flushOldEntries()
+{
+ if (!currentRoot)
+ return;
+ for (int size = currentRoot->children.size(); size > 0 && !oldEntries.empty(); --size)
+ oldEntries.erase(oldEntries.begin());
+ for (const Private::OldEntry &entry : oldEntries)
+ parseOutputLine(entry.line, true);
+ oldEntries.clear();
+ currentRoot = nullptr;
}
BranchNode *BranchModel::indexToNode(const QModelIndex &index) const
diff --git a/src/plugins/git/branchmodel.h b/src/plugins/git/branchmodel.h
index 083f6d59f7..5c163801fd 100644
--- a/src/plugins/git/branchmodel.h
+++ b/src/plugins/git/branchmodel.h
@@ -71,7 +71,6 @@ public:
QStringList localBranchNames() const;
QString sha(const QModelIndex &idx) const;
QDateTime dateTime(const QModelIndex &idx) const;
- bool hasTags() const;
bool isHead(const QModelIndex &idx) const;
bool isLocal(const QModelIndex &idx) const;
bool isLeaf(const QModelIndex &idx) const;
@@ -87,7 +86,6 @@ public:
Utils::optional<QString> remoteName(const QModelIndex &idx) const;
private:
- void parseOutputLine(const QString &line);
void setCurrentBranch();
BranchNode *indexToNode(const QModelIndex &index) const;
QModelIndex nodeToIndex(BranchNode *node, int column) const;
diff --git a/src/plugins/git/branchview.cpp b/src/plugins/git/branchview.cpp
index 8a07af74f0..21f9c63e14 100644
--- a/src/plugins/git/branchview.cpp
+++ b/src/plugins/git/branchview.cpp
@@ -230,8 +230,11 @@ void BranchView::slotCustomContextMenu(const QPoint &point)
contextMenu.addAction(tr("&Log"), this, [this] { log(selectedIndex()); });
contextMenu.addSeparator();
if (!currentSelected) {
- if (currentLocal)
- contextMenu.addAction(tr("Re&set"), this, &BranchView::reset);
+ auto resetMenu = new QMenu(tr("Re&set"), &contextMenu);
+ resetMenu->addAction(tr("&Hard"), this, [this] { reset("hard"); });
+ resetMenu->addAction(tr("&Mixed"), this, [this] { reset("mixed"); });
+ resetMenu->addAction(tr("&Soft"), this, [this] { reset("soft"); });
+ contextMenu.addMenu(resetMenu);
QString mergeTitle;
if (isFastForwardMerge()) {
contextMenu.addAction(tr("&Merge (Fast-Forward)"), this, [this] { merge(true); });
@@ -313,7 +316,7 @@ bool BranchView::add()
}
}
- BranchAddDialog branchAddDialog(localNames, true, this);
+ BranchAddDialog branchAddDialog(localNames, BranchAddDialog::Type::AddBranch, this);
branchAddDialog.setBranchName(suggestedName);
branchAddDialog.setTrackedBranchName(isTracked ? trackedBranch : QString(), !isLocal);
branchAddDialog.setCheckoutVisible(true);
@@ -444,11 +447,10 @@ bool BranchView::rename()
if (!isTag)
localNames = m_model->localBranchNames();
- BranchAddDialog branchAddDialog(localNames, false, this);
- if (isTag)
- branchAddDialog.setWindowTitle(tr("Rename Tag"));
+ const BranchAddDialog::Type type = isTag ? BranchAddDialog::Type::RenameTag
+ : BranchAddDialog::Type::RenameBranch;
+ BranchAddDialog branchAddDialog(localNames, type, this);
branchAddDialog.setBranchName(oldName);
- branchAddDialog.setTrackedBranchName(QString(), false);
branchAddDialog.exec();
@@ -467,17 +469,17 @@ bool BranchView::rename()
return false;
}
-bool BranchView::reset()
+bool BranchView::reset(const QByteArray &resetType)
{
const QString currentName = m_model->fullName(m_model->currentBranch());
const QString branchName = m_model->fullName(selectedIndex());
if (currentName.isEmpty() || branchName.isEmpty())
return false;
- if (QMessageBox::question(this, tr("Git Reset"), tr("Hard reset branch \"%1\" to \"%2\"?")
+ if (QMessageBox::question(this, tr("Git Reset"), tr("Reset branch \"%1\" to \"%2\"?")
.arg(currentName).arg(branchName),
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
- GitPlugin::client()->reset(m_repository, "--hard", branchName);
+ GitPlugin::client()->reset(m_repository, QLatin1String("--" + resetType), branchName);
return true;
}
return false;
diff --git a/src/plugins/git/branchview.h b/src/plugins/git/branchview.h
index 7e400b704a..71b2aeef39 100644
--- a/src/plugins/git/branchview.h
+++ b/src/plugins/git/branchview.h
@@ -76,7 +76,7 @@ private:
bool checkout();
bool remove();
bool rename();
- bool reset();
+ bool reset(const QByteArray &resetType);
bool isFastForwardMerge();
bool merge(bool allowFastForward);
void rebase();
diff --git a/src/plugins/git/changeselectiondialog.h b/src/plugins/git/changeselectiondialog.h
index b87ce10eed..1de142ac7d 100644
--- a/src/plugins/git/changeselectiondialog.h
+++ b/src/plugins/git/changeselectiondialog.h
@@ -79,7 +79,7 @@ private:
Ui::ChangeSelectionDialog *m_ui;
QProcess *m_process = nullptr;
- Utils::FileName m_gitExecutable;
+ Utils::FilePath m_gitExecutable;
QProcessEnvironment m_gitEnvironment;
ChangeCommand m_command = NoCommand;
QStringListModel *m_changeModel = nullptr;
diff --git a/src/plugins/git/gerrit/gerritdialog.cpp b/src/plugins/git/gerrit/gerritdialog.cpp
index f26df525fa..0f7907f99f 100644
--- a/src/plugins/git/gerrit/gerritdialog.cpp
+++ b/src/plugins/git/gerrit/gerritdialog.cpp
@@ -213,7 +213,7 @@ void GerritDialog::refresh()
const QString &query = m_ui->queryLineEdit->text().trimmed();
updateCompletions(query);
m_model->refresh(m_server, query);
- m_ui->treeView->sortByColumn(-1);
+ m_ui->treeView->sortByColumn(-1, Qt::DescendingOrder);
}
void GerritDialog::scheduleUpdateRemotes()
diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp
index 6c53345ef9..ea3e311b52 100644
--- a/src/plugins/git/gerrit/gerritmodel.cpp
+++ b/src/plugins/git/gerrit/gerritmodel.cpp
@@ -284,7 +284,7 @@ QueryContext::QueryContext(const QString &query,
connect(&m_process, &QProcess::readyReadStandardOutput, this, [this] {
m_output.append(m_process.readAllStandardOutput());
});
- connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &QueryContext::processFinished);
connect(&m_process, &QProcess::errorOccurred, this, &QueryContext::processError);
connect(&m_watcher, &QFutureWatcherBase::canceled, this, &QueryContext::terminate);
@@ -315,7 +315,7 @@ void QueryContext::start()
m_progress.reportStarted();
// Order: synchronous call to error handling if something goes wrong.
VcsOutputWindow::appendCommand(
- m_process.workingDirectory(), Utils::FileName::fromString(m_binary), m_arguments);
+ m_process.workingDirectory(), Utils::FilePath::fromString(m_binary), m_arguments);
m_timer.start();
m_process.start(m_binary, m_arguments);
m_process.closeWriteChannel();
@@ -376,7 +376,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, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
&box, &QDialog::reject);
box.exec();
if (m_process.state() != QProcess::Running)
@@ -842,7 +842,7 @@ QList<QStandardItem *> GerritModel::changeToRow(const GerritChangePtr &c) const
{
QList<QStandardItem *> row;
const QVariant filterV = QVariant(c->filterString());
- const QVariant changeV = qVariantFromValue(c);
+ const QVariant changeV = QVariant::fromValue(c);
for (int i = 0; i < GerritModel::ColumnCount; ++i) {
auto item = new QStandardItem;
item->setData(changeV, GerritModel::GerritChangeRole);
diff --git a/src/plugins/git/gerrit/gerritparameters.cpp b/src/plugins/git/gerrit/gerritparameters.cpp
index a505bda6e4..7cbe62dbab 100644
--- a/src/plugins/git/gerrit/gerritparameters.cpp
+++ b/src/plugins/git/gerrit/gerritparameters.cpp
@@ -57,11 +57,10 @@ static inline QString detectApp(const char *defaultExe)
if (!app.isEmpty() || !HostOsInfo::isWindowsHost())
return app;
// Windows: Use app.exe from git if it cannot be found.
- const FileName gitBinDir = GerritPlugin::gitBinDirectory();
+ const FilePath gitBinDir = GerritPlugin::gitBinDirectory();
if (gitBinDir.isEmpty())
return QString();
- FileName path = gitBinDir;
- path.appendPath(defaultApp);
+ FilePath path = gitBinDir.pathAppended(defaultApp);
if (path.exists())
return path.toString();
@@ -74,7 +73,7 @@ static inline QString detectApp(const char *defaultExe)
const QStringList entries = dir.entryList({"mingw*"});
if (entries.isEmpty())
return QString();
- path.appendPath(entries.first()).appendPath("bin").appendPath(defaultApp);
+ path = path.pathAppended(entries.first()).pathAppended("bin").pathAppended(defaultApp);
if (path.exists())
return path.toString();
return QString();
diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp
index 3cc82f5c45..7dfdc5de61 100644
--- a/src/plugins/git/gerrit/gerritplugin.cpp
+++ b/src/plugins/git/gerrit/gerritplugin.cpp
@@ -91,7 +91,7 @@ class FetchContext : public QObject
Q_OBJECT
public:
FetchContext(const QSharedPointer<GerritChange> &change,
- const QString &repository, const Utils::FileName &git,
+ const QString &repository, const Utils::FilePath &git,
const GerritServer &server,
FetchMode fm, QObject *parent = nullptr);
~FetchContext() override;
@@ -119,7 +119,7 @@ private:
const QSharedPointer<GerritChange> m_change;
const QString m_repository;
const FetchMode m_fetchMode;
- const Utils::FileName m_git;
+ const Utils::FilePath m_git;
const GerritServer m_server;
State m_state;
QProcess m_process;
@@ -128,7 +128,7 @@ private:
};
FetchContext::FetchContext(const QSharedPointer<GerritChange> &change,
- const QString &repository, const Utils::FileName &git,
+ const QString &repository, const Utils::FilePath &git,
const GerritServer &server,
FetchMode fm, QObject *parent)
: QObject(parent)
@@ -140,7 +140,7 @@ FetchContext::FetchContext(const QSharedPointer<GerritChange> &change,
, m_state(FetchState)
{
connect(&m_process, &QProcess::errorOccurred, this, &FetchContext::processError);
- connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &FetchContext::processFinished);
connect(&m_process, &QProcess::readyReadStandardError,
this, &FetchContext::processReadyReadStandardError);
@@ -375,7 +375,7 @@ void GerritPlugin::push()
push(currentRepository());
}
-Utils::FileName GerritPlugin::gitBinDirectory()
+Utils::FilePath GerritPlugin::gitBinDirectory()
{
return GitPlugin::client()->gitBinDirectory();
}
@@ -389,7 +389,7 @@ QString GerritPlugin::branch(const QString &repository)
void GerritPlugin::fetch(const QSharedPointer<GerritChange> &change, int mode)
{
// Locate git.
- const Utils::FileName git = GitPlugin::client()->vcsBinary();
+ const Utils::FilePath git = GitPlugin::client()->vcsBinary();
if (git.isEmpty()) {
VcsBase::VcsOutputWindow::appendError(tr("Git is not available."));
return;
@@ -493,7 +493,7 @@ QString GerritPlugin::findLocalRepository(QString project, const QString &branch
branchRegexp.reset(); // Oops.
}
for (const QString &repository : gitRepositories) {
- const QString fileName = Utils::FileName::fromString(repository).fileName();
+ const QString fileName = Utils::FilePath::fromString(repository).fileName();
if ((!branchRegexp.isNull() && branchRegexp->exactMatch(fileName))
|| fileName == project) {
// Perform a check on the branch.
diff --git a/src/plugins/git/gerrit/gerritplugin.h b/src/plugins/git/gerrit/gerritplugin.h
index 5151235496..3c6ebb5335 100644
--- a/src/plugins/git/gerrit/gerritplugin.h
+++ b/src/plugins/git/gerrit/gerritplugin.h
@@ -57,7 +57,7 @@ public:
bool initialize(Core::ActionContainer *ac);
- static Utils::FileName gitBinDirectory();
+ static Utils::FilePath gitBinDirectory();
static QString branch(const QString &repository);
void addToLocator(Core::CommandLocator *locator);
void push(const QString &topLevel);
diff --git a/src/plugins/git/gerrit/gerritpushdialog.cpp b/src/plugins/git/gerrit/gerritpushdialog.cpp
index 70f0ffa3b6..a59f615b57 100644
--- a/src/plugins/git/gerrit/gerritpushdialog.cpp
+++ b/src/plugins/git/gerrit/gerritpushdialog.cpp
@@ -146,10 +146,10 @@ GerritPushDialog::GerritPushDialog(const QString &workingDir, const QString &rev
}
m_ui->localBranchComboBox->init(workingDir);
- connect(m_ui->localBranchComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->localBranchComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &GerritPushDialog::updateCommits);
- connect(m_ui->targetBranchComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->targetBranchComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &GerritPushDialog::setChangeRange);
connect(m_ui->targetBranchComboBox, &QComboBox::currentTextChanged,
diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp
index 9e85606c76..c07f22adcc 100644
--- a/src/plugins/git/gerrit/gerritserver.cpp
+++ b/src/plugins/git/gerrit/gerritserver.cpp
@@ -243,7 +243,7 @@ int GerritServer::testConnection()
static GitClient *const client = GitPlugin::client();
const QStringList arguments = curlArguments() << (url(RestUrl) + accountUrlC);
const SynchronousProcessResponse resp = client->vcsFullySynchronousExec(
- QString(), FileName::fromString(curlBinary), arguments,
+ QString(), FilePath::fromString(curlBinary), arguments,
Core::ShellCommand::NoOutput);
if (resp.result == SynchronousProcessResponse::Finished) {
QString output = resp.stdOut();
@@ -345,7 +345,7 @@ void GerritServer::resolveVersion(const GerritParameters &p, bool forceReload)
arguments << p.portFlag << QString::number(port);
arguments << hostArgument() << "gerrit" << "version";
const SynchronousProcessResponse resp = client->vcsFullySynchronousExec(
- QString(), FileName::fromString(p.ssh), arguments,
+ QString(), FilePath::fromString(p.ssh), arguments,
Core::ShellCommand::NoOutput);
QString stdOut = resp.stdOut().trimmed();
stdOut.remove("gerrit version ");
@@ -353,7 +353,7 @@ void GerritServer::resolveVersion(const GerritParameters &p, bool forceReload)
} else {
const QStringList arguments = curlArguments() << (url(RestUrl) + versionUrlC);
const SynchronousProcessResponse resp = client->vcsFullySynchronousExec(
- QString(), FileName::fromString(curlBinary), arguments,
+ QString(), FilePath::fromString(curlBinary), arguments,
Core::ShellCommand::NoOutput);
// REST endpoint for version is only available from 2.8 and up. Do not consider invalid
// if it fails.
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 550a8489e4..f95cda6e00 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -780,16 +780,15 @@ QString GitClient::findRepositoryForDirectory(const QString &directory) const
return QString();
// QFileInfo is outside loop, because it is faster this way
QFileInfo fileInfo;
- FileName parent;
- for (FileName dir = FileName::fromString(directory); !dir.isEmpty(); dir = dir.parentDir()) {
- FileName gitName = FileName(dir).appendPath(GIT_DIRECTORY);
+ FilePath parent;
+ for (FilePath dir = FilePath::fromString(directory); !dir.isEmpty(); dir = dir.parentDir()) {
+ const FilePath gitName = dir.pathAppended(GIT_DIRECTORY);
if (!gitName.exists())
continue; // parent might exist
fileInfo.setFile(gitName.toString());
if (fileInfo.isFile())
return dir.toString();
- gitName.appendPath("config");
- if (gitName.exists())
+ if (gitName.pathAppended("config").exists())
return dir.toString();
}
return QString();
@@ -1186,7 +1185,7 @@ QStringList GitClient::setupCheckoutArguments(const QString &workingDirectory,
}
}
- BranchAddDialog branchAddDialog(localBranches, true, ICore::dialogParent());
+ BranchAddDialog branchAddDialog(localBranches, BranchAddDialog::Type::AddBranch, ICore::dialogParent());
branchAddDialog.setTrackedBranchName(remoteBranch, true);
if (branchAddDialog.exec() != QDialog::Accepted)
@@ -2341,7 +2340,7 @@ void GitClient::launchGitK(const QString &workingDirectory, const QString &fileN
}
Environment sysEnv = Environment::systemEnvironment();
- const FileName exec = sysEnv.searchInPath("gitk");
+ const FilePath exec = sysEnv.searchInPath("gitk");
if (!exec.isEmpty() && tryLauchingGitK(env, workingDirectory, fileName,
exec.parentDir().toString())) {
@@ -2378,7 +2377,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
arguments.append(QtcProcess::splitArgs(gitkOpts, HostOsInfo::hostOs()));
if (!fileName.isEmpty())
arguments << "--" << fileName;
- VcsOutputWindow::appendCommand(workingDirectory, FileName::fromString(binary), arguments);
+ VcsOutputWindow::appendCommand(workingDirectory, FilePath::fromString(binary), arguments);
// This should always use QProcess::startDetached (as not to kill
// the child), but that does not have an environment parameter.
bool success = false;
@@ -2402,7 +2401,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env,
bool GitClient::launchGitGui(const QString &workingDirectory) {
bool success = true;
- FileName gitBinary = vcsBinary();
+ FilePath gitBinary = vcsBinary();
if (gitBinary.isEmpty()) {
success = false;
} else {
@@ -2416,11 +2415,11 @@ bool GitClient::launchGitGui(const QString &workingDirectory) {
return success;
}
-FileName GitClient::gitBinDirectory()
+FilePath GitClient::gitBinDirectory()
{
const QString git = vcsBinary().toString();
if (git.isEmpty())
- return FileName();
+ return FilePath();
// Is 'git\cmd' in the path (folder containing .bats)?
QString path = QFileInfo(git).absolutePath();
@@ -2440,15 +2439,15 @@ FileName GitClient::gitBinDirectory()
path = usrBinPath;
}
}
- return FileName::fromString(path);
+ return FilePath::fromString(path);
}
-FileName GitClient::vcsBinary() const
+FilePath GitClient::vcsBinary() const
{
bool ok;
- Utils::FileName binary = static_cast<GitSettings &>(settings()).gitExecutable(&ok);
+ Utils::FilePath binary = static_cast<GitSettings &>(settings()).gitExecutable(&ok);
if (!ok)
- return Utils::FileName();
+ return Utils::FilePath();
return binary;
}
@@ -2613,7 +2612,7 @@ bool GitClient::getCommitData(const QString &workingDirectory,
if (!QFile::exists(templateFilename))
templateFilename = gitDirectory.absoluteFilePath("SQUASH_MSG");
if (!QFile::exists(templateFilename)) {
- FileName templateName = FileName::fromUserInput(
+ FilePath templateName = FilePath::fromUserInput(
readConfigValue(workingDirectory, "commit.template"));
templateFilename = templateName.toString();
}
@@ -3024,8 +3023,29 @@ void GitClient::subversionDeltaCommit(const QString &workingDirectory)
void GitClient::push(const QString &workingDirectory, const QStringList &pushArgs)
{
- vcsExec(workingDirectory, QStringList({"push"}) + pushArgs, nullptr, true,
- VcsCommand::ShowSuccessMessage);
+ VcsCommand *command = vcsExec(
+ workingDirectory, QStringList({"push"}) + pushArgs, nullptr, true,
+ VcsCommand::ShowSuccessMessage);
+ connect(command, &VcsCommand::stdErrText, this, [command](const QString &text) {
+ if (text.contains("non-fast-forward"))
+ command->setCookie(true);
+ });
+ connect(command, &VcsCommand::finished,
+ this, [this, command, workingDirectory, pushArgs](bool success) {
+ if (!success && command->cookie().toBool()) {
+ const QColor warnColor = Utils::creatorTheme()->color(Theme::TextColorError);
+ if (QMessageBox::question(
+ Core::ICore::dialogParent(), tr("Force Push"),
+ tr("Push failed. Would you like to force-push <span style=\"color:#%1\">"
+ "(rewrites remote history)</span>?")
+ .arg(QString::number(warnColor.rgba(), 16)),
+ QMessageBox::Yes | QMessageBox::No,
+ QMessageBox::No) == QMessageBox::Yes) {
+ vcsExec(workingDirectory, QStringList({"push", "--force-with-lease"}) + pushArgs,
+ nullptr, true, VcsCommand::ShowSuccessMessage);
+ }
+ }
+ });
}
bool GitClient::synchronousMerge(const QString &workingDirectory, const QString &branch,
@@ -3239,7 +3259,7 @@ QString GitClient::readOneLine(const QString &workingDirectory, const QStringLis
// determine version as '(major << 16) + (minor << 8) + patch' or 0.
unsigned GitClient::gitVersion(QString *errorMessage) const
{
- const FileName newGitBinary = vcsBinary();
+ 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.
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 103e269824..abde02f40d 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -121,7 +121,7 @@ public:
explicit GitClient();
- Utils::FileName vcsBinary() const override;
+ Utils::FilePath vcsBinary() const override;
unsigned gitVersion(QString *errorMessage = nullptr) const;
VcsBase::VcsCommand *vcsExecAbortable(const QString &workingDirectory,
@@ -306,7 +306,7 @@ public:
void launchGitK(const QString &workingDirectory, const QString &fileName);
void launchGitK(const QString &workingDirectory) { launchGitK(workingDirectory, QString()); }
bool launchGitGui(const QString &workingDirectory);
- Utils::FileName gitBinDirectory();
+ Utils::FilePath gitBinDirectory();
void launchRepositoryBrowser(const QString &workingDirectory);
@@ -369,7 +369,7 @@ private:
QString msgBoxText, const QString &buttonName,
const QString &gitCommand, ContinueCommandMode continueMode);
- mutable Utils::FileName m_gitVersionForBinary;
+ mutable Utils::FilePath m_gitVersionForBinary;
mutable unsigned m_cachedGitVersion;
QString m_gitQtcEditor;
diff --git a/src/plugins/git/gitconstants.h b/src/plugins/git/gitconstants.h
index fb97b16b1d..9cb9ddada1 100644
--- a/src/plugins/git/gitconstants.h
+++ b/src/plugins/git/gitconstants.h
@@ -51,6 +51,7 @@ const char SUBMIT_MIMETYPE[] = "text/vnd.qtcreator.git.submit";
const char C_GITEDITORID[] = "Git Editor";
const int OBSOLETE_COMMIT_AGE_IN_DAYS = 90;
+const int MAX_OBSOLETE_COMMITS_TO_DISPLAY = 5;
const char EXPAND_BRANCHES[] = "Branches: <Expand>";
diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp
index 38074520ad..fbe90448d7 100644
--- a/src/plugins/git/giteditor.cpp
+++ b/src/plugins/git/giteditor.cpp
@@ -26,6 +26,7 @@
#include "giteditor.h"
#include "annotationhighlighter.h"
+#include "branchadddialog.h"
#include "gitplugin.h"
#include "gitclient.h"
#include "gitsettings.h"
@@ -290,34 +291,46 @@ bool GitEditorWidget::isValidRevision(const QString &revision) const
void GitEditorWidget::addChangeActions(QMenu *menu, const QString &change)
{
m_currentChange = change;
- if (contentType() != OtherContent) {
- connect(menu->addAction(tr("Cherr&y-Pick Change %1").arg(change)), &QAction::triggered,
- this, [this]() {
- GitPlugin::client()->synchronousCherryPick(sourceWorkingDirectory(), m_currentChange);
- });
- connect(menu->addAction(tr("Re&vert Change %1").arg(change)), &QAction::triggered,
- this, [this]() {
- GitPlugin::client()->synchronousRevert(sourceWorkingDirectory(), m_currentChange);
- });
- connect(menu->addAction(tr("C&heckout Change %1").arg(change)), &QAction::triggered,
- this, [this]() {
- GitPlugin::client()->checkout(sourceWorkingDirectory(), m_currentChange);
- });
- connect(menu->addAction(tr("&Log for Change %1").arg(change)), &QAction::triggered,
- this, [this]() {
- GitPlugin::client()->log(
- sourceWorkingDirectory(), QString(), false, {m_currentChange});
- });
-
- QMenu *resetMenu = new QMenu(tr("&Reset to Change %1").arg(change), menu);
- connect(resetMenu->addAction(tr("&Hard")), &QAction::triggered,
- this, [this]() { resetChange("hard"); });
- connect(resetMenu->addAction(tr("&Mixed")), &QAction::triggered,
- this, [this]() { resetChange("mixed"); });
- connect(resetMenu->addAction(tr("&Soft")), &QAction::triggered,
- this, [this]() { resetChange("soft"); });
- menu->addMenu(resetMenu);
- }
+ if (contentType() == OtherContent)
+ return;
+
+ menu->addAction(tr("Cherr&y-Pick Change %1").arg(change), this, [this] {
+ GitPlugin::client()->synchronousCherryPick(sourceWorkingDirectory(), m_currentChange);
+ });
+ menu->addAction(tr("Re&vert Change %1").arg(change), this, [this] {
+ GitPlugin::client()->synchronousRevert(sourceWorkingDirectory(), m_currentChange);
+ });
+ menu->addAction(tr("C&heckout Change %1").arg(change), this, [this] {
+ GitPlugin::client()->checkout(sourceWorkingDirectory(), m_currentChange);
+ });
+ menu->addAction(tr("&Log for Change %1").arg(change), this, [this] {
+ GitPlugin::client()->log(sourceWorkingDirectory(), QString(), false, {m_currentChange});
+ });
+ menu->addAction(tr("Add &Tag for Change %1...").arg(change), this, [this] {
+ QString output;
+ QString errorMessage;
+ GitPlugin::client()->synchronousTagCmd(sourceWorkingDirectory(), QStringList(),
+ &output, &errorMessage);
+
+ const QStringList tags = output.split('\n');
+ BranchAddDialog dialog(tags, BranchAddDialog::Type::AddTag, Core::ICore::dialogParent());
+
+ if (dialog.exec() == QDialog::Rejected)
+ return;
+
+ GitPlugin::client()->synchronousTagCmd(sourceWorkingDirectory(),
+ {dialog.branchName(), m_currentChange},
+ &output, &errorMessage);
+ VcsOutputWindow::append(output);
+ if (!errorMessage.isEmpty())
+ VcsOutputWindow::append(errorMessage, VcsOutputWindow::MessageStyle::Error);
+ });
+
+ auto resetMenu = new QMenu(tr("&Reset to Change %1").arg(change), menu);
+ resetMenu->addAction(tr("&Hard"), this, [this] { resetChange("hard"); });
+ resetMenu->addAction(tr("&Mixed"), this, [this] { resetChange("mixed"); });
+ resetMenu->addAction(tr("&Soft"), this, [this] { resetChange("soft"); });
+ menu->addMenu(resetMenu);
}
QString GitEditorWidget::revisionSubject(const QTextBlock &inBlock) const
@@ -355,7 +368,7 @@ QString GitEditorWidget::fileNameForLine(int line) const
QString GitEditorWidget::sourceWorkingDirectory() const
{
- Utils::FileName path = Utils::FileName::fromString(source());
+ Utils::FilePath path = Utils::FilePath::fromString(source());
if (!path.isEmpty() && !path.toFileInfo().isDir())
path = path.parentDir();
while (!path.isEmpty() && !path.exists())
diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp
index e02adf12cc..65d698ec0b 100644
--- a/src/plugins/git/gitgrep.cpp
+++ b/src/plugins/git/gitgrep.cpp
@@ -44,6 +44,7 @@
#include <utils/synchronousprocess.h>
#include <utils/textfileformat.h>
+#include <QCheckBox>
#include <QFuture>
#include <QFutureWatcher>
#include <QHBoxLayout>
@@ -59,6 +60,8 @@ class GitGrepParameters
{
public:
QString ref;
+ bool recurseSubmodules = false;
+ QString id() const { return recurseSubmodules ? ref + ".Rec" : ref; }
};
using namespace Core;
@@ -169,10 +172,10 @@ public:
arguments << "-P";
else
arguments << "-F";
- if (client->gitVersion() >= 0x021300)
- arguments << "--recurse-submodules";
arguments << "-e" << m_parameters.text;
GitGrepParameters params = m_parameters.searchEngineParameters.value<GitGrepParameters>();
+ if (params.recurseSubmodules)
+ arguments << "--recurse-submodules";
if (!params.ref.isEmpty()) {
arguments << params.ref;
m_ref = params.ref + ':';
@@ -245,6 +248,10 @@ GitGrep::GitGrep(QObject *parent)
const QRegularExpression refExpression("[\\S]*");
m_treeLineEdit->setValidator(new QRegularExpressionValidator(refExpression, this));
layout->addWidget(m_treeLineEdit);
+ if (GitPlugin::client()->gitVersion() >= 0x021300) {
+ m_recurseSubmodules = new QCheckBox(tr("Recurse submodules"));
+ layout->addWidget(m_recurseSubmodules);
+ }
TextEditor::FindInFiles *findInFiles = TextEditor::FindInFiles::instance();
QTC_ASSERT(findInFiles, return);
connect(findInFiles, &TextEditor::FindInFiles::pathChanged,
@@ -282,7 +289,9 @@ QVariant GitGrep::parameters() const
{
GitGrepParameters params;
params.ref = m_treeLineEdit->text();
- return qVariantFromValue(params);
+ if (m_recurseSubmodules)
+ params.recurseSubmodules = m_recurseSubmodules->isChecked();
+ return QVariant::fromValue(params);
}
void GitGrep::readSettings(QSettings *settings)
@@ -325,7 +334,7 @@ IEditor *GitGrep::openEditor(const SearchResultItem &item,
}
const QString documentId = QLatin1String(Git::Constants::GIT_PLUGIN)
- + QLatin1String(".GitShow.") + params.ref
+ + QLatin1String(".GitShow.") + params.id()
+ QLatin1String(".") + relativePath;
QString title = tr("Git Show %1:%2").arg(params.ref).arg(relativePath);
IEditor *editor = EditorManager::openEditorWithContents(Id(), &title, content, documentId,
diff --git a/src/plugins/git/gitgrep.h b/src/plugins/git/gitgrep.h
index af7a40ca30..1e4f81ceed 100644
--- a/src/plugins/git/gitgrep.h
+++ b/src/plugins/git/gitgrep.h
@@ -29,6 +29,8 @@
#include <QCoreApplication>
+QT_FORWARD_DECLARE_CLASS(QCheckBox);
+
namespace Utils { class FancyLineEdit; }
namespace Git {
@@ -56,6 +58,7 @@ public:
private:
QWidget *m_widget;
Utils::FancyLineEdit *m_treeLineEdit;
+ QCheckBox *m_recurseSubmodules = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp
index cc84fade0e..ee47d3075e 100644
--- a/src/plugins/git/gitsettings.cpp
+++ b/src/plugins/git/gitsettings.cpp
@@ -69,7 +69,7 @@ GitSettings::GitSettings()
declareKey(lastResetIndexKey, 0);
}
-Utils::FileName GitSettings::gitExecutable(bool *ok, QString *errorMessage) const
+Utils::FilePath GitSettings::gitExecutable(bool *ok, QString *errorMessage) const
{
// Locate binary in path if one is specified, otherwise default
// to pathless binary
@@ -78,7 +78,7 @@ Utils::FileName GitSettings::gitExecutable(bool *ok, QString *errorMessage) cons
if (errorMessage)
errorMessage->clear();
- Utils::FileName binPath = binaryPath();
+ Utils::FilePath binPath = binaryPath();
if (binPath.isEmpty()) {
if (ok)
*ok = false;
diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h
index 4a33bdc876..b6778dfca5 100644
--- a/src/plugins/git/gitsettings.h
+++ b/src/plugins/git/gitsettings.h
@@ -58,7 +58,7 @@ public:
static const QLatin1String firstParentKey;
static const QLatin1String lastResetIndexKey;
- Utils::FileName gitExecutable(bool *ok = nullptr, QString *errorMessage = nullptr) const;
+ Utils::FilePath gitExecutable(bool *ok = nullptr, QString *errorMessage = nullptr) const;
GitSettings &operator = (const GitSettings &s);
};
diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp
index e36a22239e..379eb67c64 100644
--- a/src/plugins/git/gitversioncontrol.cpp
+++ b/src/plugins/git/gitversioncontrol.cpp
@@ -76,7 +76,7 @@ Core::Id GitVersionControl::id() const
return Core::Id(VcsBase::Constants::VCS_ID_GIT);
}
-bool GitVersionControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
+bool GitVersionControl::isVcsFileOrDirectory(const Utils::FilePath &fileName) const
{
if (fileName.fileName().compare(".git", Utils::HostOsInfo::fileNameCaseSensitivity()))
return false;
@@ -150,7 +150,7 @@ QString GitVersionControl::vcsTopic(const QString &directory)
}
Core::ShellCommand *GitVersionControl::createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs)
{
diff --git a/src/plugins/git/gitversioncontrol.h b/src/plugins/git/gitversioncontrol.h
index 2df3c7c856..1e1025864d 100644
--- a/src/plugins/git/gitversioncontrol.h
+++ b/src/plugins/git/gitversioncontrol.h
@@ -42,7 +42,7 @@ public:
QString displayName() const final;
Core::Id id() const final;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final;
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final;
bool managesDirectory(const QString &directory, QString *topLevel) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
@@ -59,7 +59,7 @@ public:
QString vcsTopic(const QString &directory) final;
Core::ShellCommand *createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs) final;
diff --git a/src/plugins/git/mergetool.cpp b/src/plugins/git/mergetool.cpp
index c1fd1ec2df..8558163dfc 100644
--- a/src/plugins/git/mergetool.cpp
+++ b/src/plugins/git/mergetool.cpp
@@ -61,7 +61,7 @@ bool MergeTool::start(const QString &workingDirectory, const QStringList &files)
m_process->setWorkingDirectory(workingDirectory);
m_process->setProcessEnvironment(env);
m_process->setProcessChannelMode(QProcess::MergedChannels);
- const Utils::FileName binary = GitPlugin::client()->vcsBinary();
+ const Utils::FilePath binary = GitPlugin::client()->vcsBinary();
VcsOutputWindow::appendCommand(workingDirectory, binary, arguments);
m_process->start(binary.toString(), arguments);
if (m_process->waitForStarted()) {
diff --git a/src/plugins/glsleditor/CMakeLists.txt b/src/plugins/glsleditor/CMakeLists.txt
new file mode 100644
index 0000000000..9d5dc56629
--- /dev/null
+++ b/src/plugins/glsleditor/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_qtc_plugin(GLSLEditor
+ DEPENDS GLSL
+ PLUGIN_DEPENDS Core CppTools TextEditor
+ SOURCES
+ glslautocompleter.cpp glslautocompleter.h
+ glslcompletionassist.cpp glslcompletionassist.h
+ glsleditor.cpp glsleditor.h
+ glsleditor.qrc
+ glsleditorconstants.h
+ glsleditorplugin.cpp glsleditorplugin.h
+ glslhighlighter.cpp glslhighlighter.h
+ glslindenter.cpp glslindenter.h
+)
diff --git a/src/plugins/helloworld/CMakeLists.txt b/src/plugins/helloworld/CMakeLists.txt
new file mode 100644
index 0000000000..6b9c5df88d
--- /dev/null
+++ b/src/plugins/helloworld/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_qtc_plugin(HelloWorld
+ PLUGIN_DEPENDS Core
+ SOURCES
+ helloworldplugin.cpp helloworldplugin.h
+ helloworldwindow.cpp helloworldwindow.h
+)
diff --git a/src/plugins/help/CMakeLists.txt b/src/plugins/help/CMakeLists.txt
new file mode 100644
index 0000000000..7f3c05a75e
--- /dev/null
+++ b/src/plugins/help/CMakeLists.txt
@@ -0,0 +1,48 @@
+add_qtc_plugin(Help
+ CONDITION TARGET Qt5::Help
+ DEPENDS shared_help
+ PLUGIN_DEPENDS Core ProjectExplorer
+ PLUGIN_RECOMMENDS TextEditor
+ SOURCES
+ centralwidget.cpp centralwidget.h
+ docsettingspage.cpp docsettingspage.h docsettingspage.ui
+ filtersettingspage.cpp filtersettingspage.h filtersettingspage.ui
+ generalsettingspage.cpp generalsettingspage.h generalsettingspage.ui
+ help.qrc
+ helpconstants.h
+ helpfindsupport.cpp helpfindsupport.h
+ helpindexfilter.cpp helpindexfilter.h
+ helpmanager.cpp helpmanager.h
+ helpmode.cpp helpmode.h
+ helpplugin.cpp helpplugin.h
+ helpviewer.cpp helpviewer.h
+ helpwidget.cpp helpwidget.h
+ localhelpmanager.cpp localhelpmanager.h
+ openpagesmanager.cpp openpagesmanager.h
+ openpagesmodel.cpp openpagesmodel.h
+ openpagesswitcher.cpp openpagesswitcher.h
+ openpageswidget.cpp openpageswidget.h
+ remotehelpfilter.cpp remotehelpfilter.h remotehelpfilter.ui
+ searchtaskhandler.cpp searchtaskhandler.h
+ searchwidget.cpp searchwidget.h
+ textbrowserhelpviewer.cpp textbrowserhelpviewer.h
+ xbelsupport.cpp xbelsupport.h
+)
+
+extend_qtc_plugin(Help
+ CONDITION FWWebKit AND FWAppKit
+ DEPENDS ${FWWebKit} ${FWAppKit}
+ DEFINES QTC_MAC_NATIVE_HELPVIEWER
+ SOURCES
+ macwebkithelpviewer.h
+ macwebkithelpviewer.mm
+)
+
+find_package(Qt5WebEngineWidgets QUIET)
+extend_qtc_plugin(Help
+ CONDITION TARGET Qt5::WebEngineWidgets
+ DEPENDS Qt5::WebEngineWidgets
+ SOURCES
+ webenginehelpviewer.cpp
+ webenginehelpviewer.h
+)
diff --git a/src/plugins/help/centralwidget.h b/src/plugins/help/centralwidget.h
index b7ead61edc..b6fc9d4e89 100644
--- a/src/plugins/help/centralwidget.h
+++ b/src/plugins/help/centralwidget.h
@@ -32,7 +32,6 @@
namespace Help {
namespace Internal {
-
class CentralWidget : public HelpWidget
{
Q_OBJECT
diff --git a/src/plugins/help/generalsettingspage.cpp b/src/plugins/help/generalsettingspage.cpp
index fc8fa3d321..3b3e366858 100644
--- a/src/plugins/help/generalsettingspage.cpp
+++ b/src/plugins/help/generalsettingspage.cpp
@@ -81,14 +81,14 @@ QWidget *GeneralSettingsPage::widget()
updateFont(); // changes that might have happened when updating the selectors
});
- connect(m_ui->styleComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->styleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]() {
updateFont();
updateFontSizeSelector();
updateFont(); // changes that might have happened when updating the selectors
});
- connect(m_ui->sizeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->sizeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &GeneralSettingsPage::updateFont);
m_homePage = LocalHelpManager::homePage();
@@ -119,6 +119,9 @@ QWidget *GeneralSettingsPage::widget()
m_returnOnClose = LocalHelpManager::returnOnClose();
m_ui->m_returnOnClose->setChecked(m_returnOnClose);
+
+ m_scrollWheelZoomingEnabled = LocalHelpManager::isScrollWheelZoomingEnabled();
+ m_ui->scrollWheelZooming->setChecked(m_scrollWheelZoomingEnabled);
}
return m_widget;
}
@@ -159,6 +162,12 @@ void GeneralSettingsPage::apply()
m_returnOnClose = close;
LocalHelpManager::setReturnOnClose(m_returnOnClose);
}
+
+ const bool zoom = m_ui->scrollWheelZooming->isChecked();
+ if (m_scrollWheelZoomingEnabled != zoom) {
+ m_scrollWheelZoomingEnabled = zoom;
+ LocalHelpManager::setScrollWheelZoomingEnabled(m_scrollWheelZoomingEnabled);
+ }
}
void GeneralSettingsPage::setCurrentPage()
diff --git a/src/plugins/help/generalsettingspage.h b/src/plugins/help/generalsettingspage.h
index 3804039027..b72168ec1c 100644
--- a/src/plugins/help/generalsettingspage.h
+++ b/src/plugins/help/generalsettingspage.h
@@ -33,7 +33,6 @@
namespace Help {
namespace Internal {
-
class GeneralSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
@@ -69,6 +68,7 @@ private:
int m_startOption;
bool m_returnOnClose;
+ bool m_scrollWheelZoomingEnabled;
QPointer<QWidget> m_widget;
Ui::GeneralSettingsPage *m_ui = nullptr;
diff --git a/src/plugins/help/generalsettingspage.ui b/src/plugins/help/generalsettingspage.ui
index e303d50f6e..afca6739cb 100644
--- a/src/plugins/help/generalsettingspage.ui
+++ b/src/plugins/help/generalsettingspage.ui
@@ -289,6 +289,13 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
+ <widget class="QCheckBox" name="scrollWheelZooming">
+ <property name="text">
+ <string>Enable scroll wheel zooming</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QCheckBox" name="m_returnOnClose">
<property name="toolTip">
<string>Switches to editor context after last help page is closed.</string>
diff --git a/src/plugins/help/help.pro b/src/plugins/help/help.pro
index a967663078..76c6db63a2 100644
--- a/src/plugins/help/help.pro
+++ b/src/plugins/help/help.pro
@@ -69,7 +69,6 @@ FORMS += docsettingspage.ui \
osx {
DEFINES += QTC_MAC_NATIVE_HELPVIEWER
- QT += macextras
HEADERS += macwebkithelpviewer.h
OBJECTIVE_SOURCES += macwebkithelpviewer.mm
LIBS += -framework WebKit -framework AppKit
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index ee6261ee3b..7e8bf80c81 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -400,7 +400,7 @@ void HelpPluginPrivate::saveExternalWindowSettings()
return;
m_externalWindowState = m_externalWindow->geometry();
QSettings *settings = ICore::settings();
- settings->setValue(kExternalWindowStateKey, qVariantFromValue(m_externalWindowState));
+ settings->setValue(kExternalWindowStateKey, QVariant::fromValue(m_externalWindowState));
}
HelpWidget *HelpPluginPrivate::createHelpWidget(const Context &context, HelpWidget::WidgetStyle style)
@@ -495,6 +495,9 @@ HelpViewer *HelpPlugin::createHelpViewer(qreal zoom)
// initialize zoom
viewer->setScale(zoom);
+ viewer->setScrollWheelZoomingEnabled(LocalHelpManager::isScrollWheelZoomingEnabled());
+ connect(LocalHelpManager::instance(), &LocalHelpManager::scrollWheelZoomingEnabledChanged,
+ viewer, &HelpViewer::setScrollWheelZoomingEnabled);
// add find support
auto agg = new Aggregation::Aggregate;
diff --git a/src/plugins/help/helpviewer.cpp b/src/plugins/help/helpviewer.cpp
index 1c40bbd111..d667c3b26c 100644
--- a/src/plugins/help/helpviewer.cpp
+++ b/src/plugins/help/helpviewer.cpp
@@ -91,6 +91,16 @@ HelpViewer::~HelpViewer()
restoreOverrideCursor();
}
+void HelpViewer::setScrollWheelZoomingEnabled(bool enabled)
+{
+ m_scrollWheelZoomingEnabled = enabled;
+}
+
+bool HelpViewer::isScrollWheelZoomingEnabled() const
+{
+ return m_scrollWheelZoomingEnabled;
+}
+
void HelpViewer::setActionVisible(Action action, bool visible)
{
if (visible)
@@ -162,6 +172,16 @@ void HelpViewer::home()
setSource(LocalHelpManager::homePage());
}
+void HelpViewer::wheelEvent(QWheelEvent *event)
+{
+ if (m_scrollWheelZoomingEnabled && event->modifiers() == Qt::ControlModifier) {
+ event->accept();
+ event->delta() > 0 ? scaleUp() : scaleDown();
+ } else {
+ QWidget::wheelEvent(event);
+ }
+}
+
void HelpViewer::slotLoadStarted()
{
++m_loadOverrideStack;
diff --git a/src/plugins/help/helpviewer.h b/src/plugins/help/helpviewer.h
index 0a24fb7222..d502d7c664 100644
--- a/src/plugins/help/helpviewer.h
+++ b/src/plugins/help/helpviewer.h
@@ -57,6 +57,9 @@ public:
virtual qreal scale() const = 0;
virtual void setScale(qreal scale) = 0;
+ void setScrollWheelZoomingEnabled(bool enabled);
+ bool isScrollWheelZoomingEnabled() const;
+
virtual QString title() const = 0;
virtual QUrl source() const = 0;
@@ -105,12 +108,15 @@ signals:
void externalPageRequested(const QUrl &url);
protected:
+ void wheelEvent(QWheelEvent *event) override;
+
void slotLoadStarted();
void slotLoadFinished();
void restoreOverrideCursor();
Actions m_visibleActions;
+ bool m_scrollWheelZoomingEnabled = true;
int m_loadOverrideStack = 0;
};
diff --git a/src/plugins/help/helpwidget.cpp b/src/plugins/help/helpwidget.cpp
index d07cf9e145..64f76e4e6c 100644
--- a/src/plugins/help/helpwidget.cpp
+++ b/src/plugins/help/helpwidget.cpp
@@ -220,7 +220,7 @@ HelpWidget::HelpWidget(const Core::Context &context, WidgetStyle style, QWidget
m_filterComboBox->setModel(LocalHelpManager::filterModel());
m_filterComboBox->setCurrentIndex(LocalHelpManager::filterIndex());
layout->addWidget(m_filterComboBox);
- connect(m_filterComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_filterComboBox, QOverload<int>::of(&QComboBox::activated),
LocalHelpManager::instance(), &LocalHelpManager::setFilterIndex);
connect(LocalHelpManager::instance(), &LocalHelpManager::filterIndexChanged,
m_filterComboBox, &QComboBox::setCurrentIndex);
diff --git a/src/plugins/help/localhelpmanager.cpp b/src/plugins/help/localhelpmanager.cpp
index 3f698f2f28..140aa4a935 100644
--- a/src/plugins/help/localhelpmanager.cpp
+++ b/src/plugins/help/localhelpmanager.cpp
@@ -65,6 +65,7 @@ static const char kFontSizeKey[] = "Help/FallbackFontSize";
static const char kStartOptionKey[] = "Help/StartOption";
static const char kContextHelpOptionKey[] = "Help/ContextHelpOption";
static const char kReturnOnCloseKey[] = "Help/ReturnOnClose";
+static const char kUseScrollWheelZooming[] = "Help/UseScrollWheelZooming";
static const char kLastShownPagesKey[] = "Help/LastShownPages";
static const char kLastShownPagesZoomKey[] = "Help/LastShownPagesZoom";
static const char kLastSelectedTabKey[] = "Help/LastSelectedTab";
@@ -225,6 +226,17 @@ void LocalHelpManager::setReturnOnClose(bool returnOnClose)
emit m_instance->returnOnCloseChanged();
}
+bool LocalHelpManager::isScrollWheelZoomingEnabled()
+{
+ return Core::ICore::settings()->value(kUseScrollWheelZooming, true).toBool();
+}
+
+void LocalHelpManager::setScrollWheelZoomingEnabled(bool enabled)
+{
+ Core::ICore::settings()->setValue(kUseScrollWheelZooming, enabled);
+ emit m_instance->scrollWheelZoomingEnabledChanged(enabled);
+}
+
QStringList LocalHelpManager::lastShownPages()
{
const QVariant value = Core::ICore::settings()->value(kLastShownPagesKey, QVariant());
diff --git a/src/plugins/help/localhelpmanager.h b/src/plugins/help/localhelpmanager.h
index bc8cd3b94a..7b330ade30 100644
--- a/src/plugins/help/localhelpmanager.h
+++ b/src/plugins/help/localhelpmanager.h
@@ -78,6 +78,9 @@ public:
static bool returnOnClose();
static void setReturnOnClose(bool returnOnClose);
+ static bool isScrollWheelZoomingEnabled();
+ static void setScrollWheelZoomingEnabled(bool enabled);
+
static QStringList lastShownPages();
static void setLastShownPages(const QStringList &pages);
@@ -106,6 +109,7 @@ signals:
void filterIndexChanged(int index);
void fallbackFontChanged(const QFont &font);
void returnOnCloseChanged();
+ void scrollWheelZoomingEnabledChanged(bool enabled);
private:
static bool m_guiNeedsSetup;
diff --git a/src/plugins/help/macwebkithelpviewer.mm b/src/plugins/help/macwebkithelpviewer.mm
index 1a7d561aee..d0edb0e61c 100644
--- a/src/plugins/help/macwebkithelpviewer.mm
+++ b/src/plugins/help/macwebkithelpviewer.mm
@@ -37,7 +37,6 @@
#include <QHelpEngine>
#include <QStyle>
#include <QTimer>
-#include <QtMac>
#include <QToolTip>
#include <QUrl>
#include <QVBoxLayout>
diff --git a/src/plugins/help/openpagesmanager.cpp b/src/plugins/help/openpagesmanager.cpp
index 63d9a5cda0..a6b6168dcd 100644
--- a/src/plugins/help/openpagesmanager.cpp
+++ b/src/plugins/help/openpagesmanager.cpp
@@ -61,7 +61,7 @@ OpenPagesManager::OpenPagesManager(QObject *parent)
m_comboBox = new QComboBox;
m_comboBox->setModel(m_model);
m_comboBox->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(m_comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::activated),
this, &OpenPagesManager::setCurrentPageByRow);
connect(m_comboBox, &QWidget::customContextMenuRequested, this,
&OpenPagesManager::openPagesContextMenu);
diff --git a/src/plugins/help/textbrowserhelpviewer.cpp b/src/plugins/help/textbrowserhelpviewer.cpp
index d729535fa3..02afab8d4d 100644
--- a/src/plugins/help/textbrowserhelpviewer.cpp
+++ b/src/plugins/help/textbrowserhelpviewer.cpp
@@ -406,16 +406,6 @@ bool TextBrowserHelpWidget::eventFilter(QObject *obj, QEvent *event)
return QTextBrowser::eventFilter(obj, event);
}
-void TextBrowserHelpWidget::wheelEvent(QWheelEvent *e)
-{
- if (e->modifiers() == Qt::ControlModifier) {
- e->accept();
- e->delta() > 0 ? scaleUp() : scaleDown();
- } else {
- QTextBrowser::wheelEvent(e);
- }
-}
-
void TextBrowserHelpWidget::mousePressEvent(QMouseEvent *e)
{
if (Utils::HostOsInfo::isLinuxHost() && m_parent->handleForwardBackwardMouseButtons(e))
diff --git a/src/plugins/help/textbrowserhelpviewer.h b/src/plugins/help/textbrowserhelpviewer.h
index 3e046a8771..52d5b7ce2b 100644
--- a/src/plugins/help/textbrowserhelpviewer.h
+++ b/src/plugins/help/textbrowserhelpviewer.h
@@ -98,7 +98,6 @@ public:
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
bool eventFilter(QObject *obj, QEvent *event) override;
- void wheelEvent(QWheelEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
diff --git a/src/plugins/help/webenginehelpviewer.cpp b/src/plugins/help/webenginehelpviewer.cpp
index 60773b91fe..197f356d79 100644
--- a/src/plugins/help/webenginehelpviewer.cpp
+++ b/src/plugins/help/webenginehelpviewer.cpp
@@ -292,6 +292,31 @@ WebView::WebView(WebEngineHelpViewer *viewer)
{
}
+bool WebView::event(QEvent *ev)
+{
+ // work around QTBUG-43602
+ if (ev->type() == QEvent::ChildAdded) {
+ auto ce = static_cast<QChildEvent *>(ev);
+ ce->child()->installEventFilter(this);
+ } else if (ev->type() == QEvent::ChildRemoved) {
+ auto ce = static_cast<QChildEvent *>(ev);
+ ce->child()->removeEventFilter(this);
+ }
+ return QWebEngineView::event(ev);
+}
+
+bool WebView::eventFilter(QObject *src, QEvent *e)
+{
+ Q_UNUSED(src)
+ // work around QTBUG-43602
+ if (m_viewer->isScrollWheelZoomingEnabled() && e->type() == QEvent::Wheel) {
+ auto we = static_cast<QWheelEvent *>(e);
+ if (we->modifiers() == Qt::ControlModifier)
+ return true;
+ }
+ return false;
+}
+
void WebView::contextMenuEvent(QContextMenuEvent *event)
{
QMenu *menu = page()->createStandardContextMenu();
diff --git a/src/plugins/help/webenginehelpviewer.h b/src/plugins/help/webenginehelpviewer.h
index cffe26af21..f781889108 100644
--- a/src/plugins/help/webenginehelpviewer.h
+++ b/src/plugins/help/webenginehelpviewer.h
@@ -53,6 +53,9 @@ class WebView : public QWebEngineView
public:
explicit WebView(WebEngineHelpViewer *viewer);
+ bool event(QEvent *ev) override;
+ bool eventFilter(QObject *src, QEvent *e) override;
+
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
diff --git a/src/plugins/imageviewer/CMakeLists.txt b/src/plugins/imageviewer/CMakeLists.txt
new file mode 100644
index 0000000000..6bf9c9693c
--- /dev/null
+++ b/src/plugins/imageviewer/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_qtc_plugin(ImageViewer
+ DEPENDS OptionalSvg
+ PLUGIN_DEPENDS Core
+ SOURCES
+ exportdialog.cpp exportdialog.h
+ imageview.cpp imageview.h
+ imageviewer.cpp imageviewer.h
+ imageviewerconstants.h
+ imageviewerfactory.cpp imageviewerfactory.h
+ imageviewerfile.cpp imageviewerfile.h
+ imageviewerplugin.cpp imageviewerplugin.h
+ imageviewertoolbar.ui
+ multiexportdialog.cpp multiexportdialog.h
+ EXPLICIT_MOC imageviewer.h
+)
diff --git a/src/plugins/imageviewer/exportdialog.cpp b/src/plugins/imageviewer/exportdialog.cpp
index f0c52aeebe..682a7dfd30 100644
--- a/src/plugins/imageviewer/exportdialog.cpp
+++ b/src/plugins/imageviewer/exportdialog.cpp
@@ -88,8 +88,6 @@ ExportDialog::ExportDialog(QWidget *parent)
, m_heightSpinBox(new QSpinBox(this))
, m_aspectRatio(1)
{
- using QSpinBoxIntSignal = void (QSpinBox::*)(int);
-
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
auto formLayout = new QFormLayout(this);
@@ -102,14 +100,14 @@ ExportDialog::ExportDialog(QWidget *parent)
auto sizeLayout = new QHBoxLayout;
m_widthSpinBox->setMinimum(exportMinimumSize);
m_widthSpinBox->setMaximum(exportMaximumSize);
- connect(m_widthSpinBox, static_cast<QSpinBoxIntSignal>(&QSpinBox::valueChanged),
+ connect(m_widthSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &ExportDialog::exportWidthChanged);
sizeLayout->addWidget(m_widthSpinBox);
//: Multiplication, as in 32x32
sizeLayout->addWidget(new QLabel(tr("x")));
m_heightSpinBox->setMinimum(exportMinimumSize);
m_heightSpinBox->setMaximum(exportMaximumSize);
- connect(m_heightSpinBox, static_cast<QSpinBoxIntSignal>(&QSpinBox::valueChanged),
+ connect(m_heightSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &ExportDialog::exportHeightChanged);
sizeLayout->addWidget(m_heightSpinBox);
auto resetButton = new QToolButton(this);
@@ -196,7 +194,7 @@ QString ExportDialog::exportFileName() const
void ExportDialog::setExportFileName(const QString &f)
{
- m_pathChooser->setFileName(Utils::FileName::fromString(f));
+ m_pathChooser->setFileName(Utils::FilePath::fromString(f));
}
ExportData ExportDialog::exportData() const
diff --git a/src/plugins/imageviewer/imageview.cpp b/src/plugins/imageviewer/imageview.cpp
index dbdcd8fe02..821074db20 100644
--- a/src/plugins/imageviewer/imageview.cpp
+++ b/src/plugins/imageviewer/imageview.cpp
@@ -151,6 +151,7 @@ void ImageView::drawBackground(QPainter *p, const QRectF &)
{
p->save();
p->resetTransform();
+ p->setRenderHint(QPainter::SmoothPixmapTransform, false);
p->drawTiledPixmap(viewport()->rect(), backgroundBrush().texture());
p->restore();
}
diff --git a/src/plugins/imageviewer/imageviewerfile.cpp b/src/plugins/imageviewer/imageviewerfile.cpp
index 5909d92af0..2845b840ef 100644
--- a/src/plugins/imageviewer/imageviewerfile.cpp
+++ b/src/plugins/imageviewer/imageviewerfile.cpp
@@ -141,7 +141,7 @@ Core::IDocument::OpenResult ImageViewerFile::openImpl(QString *errorString, cons
emit imageSizeChanged(m_pixmap->size());
}
- setFilePath(Utils::FileName::fromString(fileName));
+ setFilePath(Utils::FilePath::fromString(fileName));
setMimeType(Utils::mimeTypeForFile(fileName).name());
return OpenResult::Success;
}
diff --git a/src/plugins/imageviewer/multiexportdialog.cpp b/src/plugins/imageviewer/multiexportdialog.cpp
index bdbcfc40bf..b47c52aaeb 100644
--- a/src/plugins/imageviewer/multiexportdialog.cpp
+++ b/src/plugins/imageviewer/multiexportdialog.cpp
@@ -339,7 +339,7 @@ void MultiExportDialog::setExportFileName(QString f)
const int lastDot = f.lastIndexOf('.');
if (lastDot != -1)
f.insert(lastDot, "-%1");
- m_pathChooser->setFileName(Utils::FileName::fromString(f));
+ m_pathChooser->setFileName(Utils::FilePath::fromString(f));
}
} // namespace Internal
diff --git a/src/plugins/ios/CMakeLists.txt b/src/plugins/ios/CMakeLists.txt
new file mode 100644
index 0000000000..87f6d1dbcb
--- /dev/null
+++ b/src/plugins/ios/CMakeLists.txt
@@ -0,0 +1,32 @@
+add_qtc_plugin(Ios
+ DEPENDS QmlDebug Qt5::Xml
+ PLUGIN_DEPENDS Core Debugger ProjectExplorer QmakeProjectManager
+ SOURCES
+ createsimulatordialog.cpp createsimulatordialog.h createsimulatordialog.ui
+ ios.qrc
+ iosbuildconfiguration.cpp iosbuildconfiguration.h
+ iosbuildstep.cpp iosbuildstep.h iosbuildstep.ui
+ iosconfigurations.cpp iosconfigurations.h
+ iosconstants.h
+ iosdeploystep.cpp iosdeploystep.h
+ iosdevice.cpp iosdevice.h
+ iosdsymbuildstep.cpp iosdsymbuildstep.h
+ iosplugin.cpp iosplugin.h
+ iospresetbuildstep.ui
+ iosprobe.cpp iosprobe.h
+ iosqtversion.cpp iosqtversion.h
+ iosrunconfiguration.cpp iosrunconfiguration.h
+ iosrunner.cpp iosrunner.h
+ iossettingspage.cpp iossettingspage.h
+ iossettingswidget.cpp iossettingswidget.h iossettingswidget.ui
+ iossimulator.cpp iossimulator.h
+ iostoolhandler.cpp iostoolhandler.h
+ simulatorcontrol.cpp simulatorcontrol.h
+ simulatorinfomodel.cpp simulatorinfomodel.h
+ simulatoroperationdialog.cpp simulatoroperationdialog.h simulatoroperationdialog.ui
+)
+
+extend_qtc_plugin(Ios
+ CONDITION APPLE
+ DEPENDS ${FWCoreFoundation} ${FWIOKit}
+)
diff --git a/src/plugins/ios/createsimulatordialog.cpp b/src/plugins/ios/createsimulatordialog.cpp
index 6c8d711b68..1bfcc25f71 100644
--- a/src/plugins/ios/createsimulatordialog.cpp
+++ b/src/plugins/ios/createsimulatordialog.cpp
@@ -53,7 +53,7 @@ CreateSimulatorDialog::CreateSimulatorDialog(QWidget *parent) :
m_ui->runtimeCombo->currentIndex() > 0);
};
- const auto indexChanged = static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged);
+ const auto indexChanged = QOverload<int>::of(&QComboBox::currentIndexChanged);
connect(m_ui->nameEdit, &QLineEdit::textChanged, enableOk);
connect(m_ui->runtimeCombo, indexChanged, enableOk);
connect(m_ui->deviceTypeCombo, indexChanged, [this, enableOk]() {
diff --git a/src/plugins/ios/ios.pro b/src/plugins/ios/ios.pro
index d4e4d9e05d..d8bfd14d15 100644
--- a/src/plugins/ios/ios.pro
+++ b/src/plugins/ios/ios.pro
@@ -15,21 +15,16 @@ HEADERS += \
iossettingswidget.h \
iosrunner.h \
iosdsymbuildstep.h \
- iosqtversionfactory.h \
iosqtversion.h \
iosplugin.h \
- iosdevicefactory.h \
iosdevice.h \
iossimulator.h \
- iossimulatorfactory.h \
iosprobe.h \
iosbuildstep.h \
iostoolhandler.h \
iosdeploystep.h \
- iosdeploystepwidget.h \
simulatorcontrol.h \
iosbuildconfiguration.h \
- iosbuildsettingswidget.h \
createsimulatordialog.h \
simulatoroperationdialog.h \
simulatorinfomodel.h
@@ -42,21 +37,16 @@ SOURCES += \
iossettingswidget.cpp \
iosrunner.cpp \
iosdsymbuildstep.cpp \
- iosqtversionfactory.cpp \
iosqtversion.cpp \
iosplugin.cpp \
- iosdevicefactory.cpp \
iosdevice.cpp \
iossimulator.cpp \
- iossimulatorfactory.cpp \
iosprobe.cpp \
iosbuildstep.cpp \
iostoolhandler.cpp \
iosdeploystep.cpp \
- iosdeploystepwidget.cpp \
simulatorcontrol.cpp \
iosbuildconfiguration.cpp \
- iosbuildsettingswidget.cpp \
createsimulatordialog.cpp \
simulatoroperationdialog.cpp \
simulatorinfomodel.cpp
@@ -64,9 +54,7 @@ SOURCES += \
FORMS += \
iossettingswidget.ui \
iosbuildstep.ui \
- iosdeploystepwidget.ui \
iospresetbuildstep.ui \
- iosbuildsettingswidget.ui \
createsimulatordialog.ui \
simulatoroperationdialog.ui
diff --git a/src/plugins/ios/ios.qbs b/src/plugins/ios/ios.qbs
index c5553f9e45..e338c9241f 100644
--- a/src/plugins/ios/ios.qbs
+++ b/src/plugins/ios/ios.qbs
@@ -20,9 +20,6 @@ QtcPlugin {
"ios.qrc",
"iosbuildconfiguration.cpp",
"iosbuildconfiguration.h",
- "iosbuildsettingswidget.cpp",
- "iosbuildsettingswidget.h",
- "iosbuildsettingswidget.ui",
"iosbuildstep.cpp",
"iosbuildstep.h",
"iosbuildstep.ui",
@@ -31,13 +28,8 @@ QtcPlugin {
"iosconstants.h",
"iosdeploystep.cpp",
"iosdeploystep.h",
- "iosdeploystepwidget.cpp",
- "iosdeploystepwidget.h",
- "iosdeploystepwidget.ui",
"iosdevice.cpp",
"iosdevice.h",
- "iosdevicefactory.cpp",
- "iosdevicefactory.h",
"iosdsymbuildstep.cpp",
"iosdsymbuildstep.h",
"iosplugin.cpp",
@@ -47,8 +39,6 @@ QtcPlugin {
"iosprobe.h",
"iosqtversion.cpp",
"iosqtversion.h",
- "iosqtversionfactory.cpp",
- "iosqtversionfactory.h",
"iosrunconfiguration.cpp",
"iosrunconfiguration.h",
"iosrunner.cpp",
@@ -60,8 +50,6 @@ QtcPlugin {
"iossettingswidget.ui",
"iossimulator.cpp",
"iossimulator.h",
- "iossimulatorfactory.cpp",
- "iossimulatorfactory.h",
"iostoolhandler.cpp",
"iostoolhandler.h",
"simulatorcontrol.cpp",
diff --git a/src/plugins/ios/iosbuildconfiguration.cpp b/src/plugins/ios/iosbuildconfiguration.cpp
index 3f6de58d38..0ef0002071 100644
--- a/src/plugins/ios/iosbuildconfiguration.cpp
+++ b/src/plugins/ios/iosbuildconfiguration.cpp
@@ -27,16 +27,23 @@
#include "iosconfigurations.h"
#include "iosconstants.h"
-#include "iosbuildsettingswidget.h"
-#include "projectexplorer/kitinformation.h"
-#include "projectexplorer/namedwidget.h"
-#include "projectexplorer/target.h"
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/namedwidget.h>
+#include <projectexplorer/target.h>
-#include "qmakeprojectmanager/qmakebuildinfo.h"
-#include "qmakeprojectmanager/qmakeprojectmanagerconstants.h"
+#include <qmakeprojectmanager/qmakebuildinfo.h>
+#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
#include <utils/algorithm.h>
+#include <utils/detailswidget.h>
+#include <utils/utilsicons.h>
+
+#include <QCheckBox>
+#include <QComboBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QPushButton>
using namespace QmakeProjectManager;
using namespace ProjectExplorer;
@@ -44,58 +51,392 @@ using namespace ProjectExplorer;
namespace Ios {
namespace Internal {
+Q_LOGGING_CATEGORY(iosSettingsLog, "qtc.ios.common", QtWarningMsg)
+
const char qmakeIosTeamSettings[] = "QMAKE_MAC_XCODE_SETTINGS+=qteam qteam.name=DEVELOPMENT_TEAM qteam.value=";
const char qmakeProvisioningProfileSettings[] = "QMAKE_MAC_XCODE_SETTINGS+=qprofile qprofile.name=PROVISIONING_PROFILE_SPECIFIER qprofile.value=";
const char signingIdentifierKey[] = "Ios.SigningIdentifier";
const char autoManagedSigningKey[] = "Ios.AutoManagedSigning";
+const int IdentifierRole = Qt::UserRole+1;
+
+
+class IosBuildSettingsWidget : public NamedWidget
+{
+public:
+ explicit IosBuildSettingsWidget(IosBuildConfiguration *iosBuildConfiguration);
+
+ bool isSigningAutomaticallyManaged() const;
+
+private:
+ void announceSigningChanged(bool isAutoManaged, QString identifier);
+ void onSigningEntityComboIndexChanged();
+ void onReset();
+
+ void setDefaultSigningIdentfier(const QString &identifier) const;
+ void configureSigningUi(bool autoManageSigning);
+ void populateDevelopmentTeams();
+ void populateProvisioningProfiles();
+ QString selectedIdentifier() const;
+ void updateInfoText();
+ void updateWarningText();
+
+private:
+ IosBuildConfiguration *m_bc = nullptr;
+ QString m_lastProfileSelection;
+ QString m_lastTeamSelection;
+ const bool m_isDevice;
+
+ QPushButton *m_qmakeDefaults;
+ QComboBox *m_signEntityCombo;
+ QCheckBox *m_autoSignCheckbox;
+ QLabel *m_signEntityLabel;
+ QLabel *m_infoIconLabel;
+ QLabel *m_infoLabel;
+ QLabel *m_warningIconLabel;
+ QLabel *m_warningLabel;
+};
+
+IosBuildSettingsWidget::IosBuildSettingsWidget(IosBuildConfiguration *bc)
+ : m_bc(bc),
+ m_isDevice(DeviceTypeKitAspect::deviceTypeId(bc->target()->kit())
+ == Constants::IOS_DEVICE_TYPE)
+{
+ auto detailsWidget = new Utils::DetailsWidget(this);
+ auto container = new QWidget(detailsWidget);
+
+ m_qmakeDefaults = new QPushButton(container);
+ QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ m_qmakeDefaults->setSizePolicy(sizePolicy);
+ m_qmakeDefaults->setText(IosBuildConfiguration::tr("Reset"));
+ m_qmakeDefaults->setEnabled(m_isDevice);
+
+ m_signEntityCombo = new QComboBox(container);
+ QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ sizePolicy1.setHorizontalStretch(0);
+ sizePolicy1.setVerticalStretch(0);
+ m_signEntityCombo->setSizePolicy(sizePolicy1);
+
+ m_autoSignCheckbox = new QCheckBox(container);
+ QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ sizePolicy2.setHorizontalStretch(0);
+ sizePolicy2.setVerticalStretch(0);
+ m_autoSignCheckbox->setSizePolicy(sizePolicy2);
+ m_autoSignCheckbox->setChecked(true);
+ m_autoSignCheckbox->setText(IosBuildConfiguration::tr("Automatically manage signing"));
+ m_autoSignCheckbox->setChecked(bc->m_autoManagedSigning->value());
+ m_autoSignCheckbox->setEnabled(m_isDevice);
+
+ m_signEntityLabel = new QLabel(container);
+
+ m_infoIconLabel = new QLabel(container);
+ QSizePolicy sizePolicy3(QSizePolicy::Maximum, QSizePolicy::Preferred);
+ sizePolicy3.setHorizontalStretch(0);
+ sizePolicy3.setVerticalStretch(0);
+ m_infoIconLabel->setSizePolicy(sizePolicy3);
+
+ m_infoLabel = new QLabel(container);
+ QSizePolicy sizePolicy4(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sizePolicy4.setHorizontalStretch(0);
+ sizePolicy4.setVerticalStretch(0);
+ m_infoLabel->setSizePolicy(sizePolicy4);
+ m_infoLabel->setWordWrap(false);
+
+ m_warningIconLabel = new QLabel(container);
+ m_warningIconLabel->setSizePolicy(sizePolicy3);
+
+ m_warningLabel = new QLabel(container);
+ m_warningLabel->setSizePolicy(sizePolicy4);
+ m_warningLabel->setWordWrap(true);
+
+ m_signEntityLabel->setText(IosBuildConfiguration::tr("Development team:"));
+
+ connect(m_qmakeDefaults, &QPushButton::clicked, this, &IosBuildSettingsWidget::onReset);
+
+ m_infoIconLabel->hide();
+ m_infoIconLabel->setPixmap(Utils::Icons::INFO.pixmap());
+ m_infoLabel->hide();
+
+ m_warningIconLabel->hide();
+ m_warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap());
+ m_warningLabel->hide();
+
+ detailsWidget->setState(Utils::DetailsWidget::NoSummary);
+ detailsWidget->setWidget(container);
+
+ setDisplayName(IosBuildConfiguration::tr("iOS Settings"));
+
+ if (m_isDevice) {
+ connect(IosConfigurations::instance(), &IosConfigurations::provisioningDataChanged,
+ this, &IosBuildSettingsWidget::populateDevelopmentTeams);
+ connect(m_signEntityCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &IosBuildSettingsWidget::onSigningEntityComboIndexChanged);
+ connect(m_autoSignCheckbox, &QCheckBox::toggled,
+ this, &IosBuildSettingsWidget::configureSigningUi);
+ configureSigningUi(m_autoSignCheckbox->isChecked());
+ setDefaultSigningIdentfier(bc->m_signingIdentifier->value());
+ }
+
+ m_signEntityCombo->setEnabled(m_isDevice);
+ m_signEntityLabel->setEnabled(m_isDevice);
+ adjustSize();
+
+ auto rootLayout = new QVBoxLayout(this);
+ rootLayout->setMargin(0);
+ rootLayout->addWidget(detailsWidget);
+
+ auto gridLayout = new QGridLayout();
+ gridLayout->addWidget(m_signEntityLabel, 0, 0, 1, 1);
+ gridLayout->addWidget(m_signEntityCombo, 0, 1, 1, 1);
+ gridLayout->addWidget(m_autoSignCheckbox, 0, 2, 1, 1);
+ gridLayout->addWidget(m_qmakeDefaults, 1, 1, 1, 1);
+
+ auto horizontalLayout = new QHBoxLayout();
+ horizontalLayout->addWidget(m_infoIconLabel);
+ horizontalLayout->addWidget(m_infoLabel);
+
+ auto horizontalLayout_2 = new QHBoxLayout();
+ horizontalLayout_2->addWidget(m_warningIconLabel);
+ horizontalLayout_2->addWidget(m_warningLabel);
+
+ auto verticalLayout = new QVBoxLayout(container);
+ verticalLayout->addLayout(gridLayout);
+ verticalLayout->addLayout(horizontalLayout);
+ verticalLayout->addLayout(horizontalLayout_2);
+}
+
+void IosBuildSettingsWidget::setDefaultSigningIdentfier(const QString &identifier) const
+{
+ if (identifier.isEmpty()) {
+ m_signEntityCombo->setCurrentIndex(0);
+ return;
+ }
+
+ int defaultIndex = -1;
+ for (int index = 0; index < m_signEntityCombo->count(); ++index) {
+ QString teamID = m_signEntityCombo->itemData(index, IdentifierRole).toString();
+ if (teamID == identifier) {
+ defaultIndex = index;
+ break;
+ }
+ }
+ if (defaultIndex > -1) {
+ m_signEntityCombo->setCurrentIndex(defaultIndex);
+ } else {
+ // Reset to default
+ m_signEntityCombo->setCurrentIndex(0);
+ qCDebug(iosSettingsLog) << "Cannot find default"
+ << (m_autoSignCheckbox->isChecked() ? "team": "provisioning profile")
+ << ". Identifier: " << identifier;
+ }
+}
+
+bool IosBuildSettingsWidget::isSigningAutomaticallyManaged() const
+{
+ return m_autoSignCheckbox->isChecked() && m_signEntityCombo->currentIndex() > 0;
+}
+
+void IosBuildSettingsWidget::onSigningEntityComboIndexChanged()
+{
+ QString identifier = selectedIdentifier();
+ (m_autoSignCheckbox->isChecked() ? m_lastTeamSelection : m_lastProfileSelection) = identifier;
+
+ updateInfoText();
+ updateWarningText();
+ announceSigningChanged(m_autoSignCheckbox->isChecked(), identifier);
+}
+
+void IosBuildSettingsWidget::onReset()
+{
+ m_lastTeamSelection.clear();
+ m_lastProfileSelection.clear();
+ m_autoSignCheckbox->setChecked(true);
+ setDefaultSigningIdentfier("");
+}
+
+void IosBuildSettingsWidget::configureSigningUi(bool autoManageSigning)
+{
+ m_signEntityLabel->setText(autoManageSigning ? IosBuildConfiguration::tr("Development team:")
+ : IosBuildConfiguration::tr("Provisioning profile:"));
+ if (autoManageSigning)
+ populateDevelopmentTeams();
+ else
+ populateProvisioningProfiles();
+
+ updateInfoText();
+ announceSigningChanged(autoManageSigning, selectedIdentifier());
+}
+
+void IosBuildSettingsWidget::announceSigningChanged(bool autoManagedSigning, QString identifier)
+{
+ if (m_bc->m_signingIdentifier->value().compare(identifier) != 0
+ || m_bc->m_autoManagedSigning->value() != autoManagedSigning) {
+ m_bc->m_autoManagedSigning->setValue(autoManagedSigning);
+ m_bc->m_signingIdentifier->setValue(identifier);
+ m_bc->updateQmakeCommand();
+ }
+}
+
+void IosBuildSettingsWidget::populateDevelopmentTeams()
+{
+ {
+ QSignalBlocker blocker(m_signEntityCombo);
+ // Populate Team id's
+ m_signEntityCombo->clear();
+ m_signEntityCombo->addItem(IosBuildConfiguration::tr("Default"));
+ foreach (auto team, IosConfigurations::developmentTeams()) {
+ m_signEntityCombo->addItem(team->displayName());
+ const int index = m_signEntityCombo->count() - 1;
+ m_signEntityCombo->setItemData(index, team->identifier(), IdentifierRole);
+ m_signEntityCombo->setItemData(index, team->details(), Qt::ToolTipRole);
+ }
+ }
+ // Maintain previous selection.
+ setDefaultSigningIdentfier(m_lastTeamSelection);
+ updateWarningText();
+}
+
+void IosBuildSettingsWidget::populateProvisioningProfiles()
+{
+ {
+ // Populate Team id's
+ QSignalBlocker blocker(m_signEntityCombo);
+ m_signEntityCombo->clear();
+ const ProvisioningProfiles profiles = IosConfigurations::provisioningProfiles();
+ if (profiles.count() > 0) {
+ for (auto profile : profiles) {
+ m_signEntityCombo->addItem(profile->displayName());
+ const int index = m_signEntityCombo->count() - 1;
+ m_signEntityCombo->setItemData(index, profile->identifier(), IdentifierRole);
+ m_signEntityCombo->setItemData(index, profile->details(), Qt::ToolTipRole);
+ }
+ } else {
+ m_signEntityCombo->addItem(IosBuildConfiguration::tr("None"));
+ }
+ }
+ // Maintain previous selection.
+ setDefaultSigningIdentfier(m_lastProfileSelection);
+ updateWarningText();
+}
+
+QString IosBuildSettingsWidget::selectedIdentifier() const
+{
+ return m_signEntityCombo->currentData(IdentifierRole).toString();
+}
+
+void IosBuildSettingsWidget::updateInfoText()
+{
+ if (!m_isDevice)
+ return;
+
+ QString infoMessage;
+ auto addMessage = [&infoMessage](const QString &msg) {
+ if (!infoMessage.isEmpty())
+ infoMessage += "\n";
+ infoMessage += msg;
+ };
+
+ QString identifier = selectedIdentifier();
+ bool configuringTeams = m_autoSignCheckbox->isChecked();
+
+ if (identifier.isEmpty()) {
+ // No signing entity selection.
+ if (configuringTeams)
+ addMessage(IosBuildConfiguration::tr("Development team is not selected."));
+ else
+ addMessage(IosBuildConfiguration::tr("Provisioning profile is not selected."));
+
+ addMessage(IosBuildConfiguration::tr("Using default development team and provisioning profile."));
+ } else {
+ if (!configuringTeams) {
+ ProvisioningProfilePtr profile = IosConfigurations::provisioningProfile(identifier);
+ QTC_ASSERT(profile, return);
+ auto team = profile->developmentTeam();
+ if (team) {
+ // Display corresponding team information.
+ addMessage(IosBuildConfiguration::tr("Development team: %1 (%2)").arg(team->displayName())
+ .arg(team->identifier()));
+ addMessage(IosBuildConfiguration::tr("Settings defined here override the QMake environment."));
+ } else {
+ qCDebug(iosSettingsLog) << "Development team not found for profile" << profile;
+ }
+ } else {
+ addMessage(IosBuildConfiguration::tr("Settings defined here override the QMake environment."));
+ }
+ }
+
+ m_infoIconLabel->setVisible(!infoMessage.isEmpty());
+ m_infoLabel->setVisible(!infoMessage.isEmpty());
+ m_infoLabel->setText(infoMessage);
+}
+
+void IosBuildSettingsWidget::updateWarningText()
+{
+ if (!m_isDevice)
+ return;
+
+ QString warningText;
+ bool configuringTeams = m_autoSignCheckbox->isChecked();
+ if (m_signEntityCombo->count() < 2) {
+ warningText = IosBuildConfiguration::tr("%1 not configured. Use Xcode and Apple "
+ "developer account to configure the "
+ "provisioning profiles and teams.")
+ .arg(configuringTeams ? IosBuildConfiguration::tr("Development teams")
+ : IosBuildConfiguration::tr("Provisioning profiles"));
+ } else {
+ QString identifier = selectedIdentifier();
+ if (configuringTeams) {
+ auto team = IosConfigurations::developmentTeam(identifier);
+ if (team && !team->hasProvisioningProfile())
+ warningText = IosBuildConfiguration::tr("No provisioning profile found for the selected team.");
+ } else {
+ auto profile = IosConfigurations::provisioningProfile(identifier);
+ if (profile && QDateTime::currentDateTimeUtc() > profile->expirationDate()) {
+ warningText = IosBuildConfiguration::tr("Provisioning profile expired. Expiration date: %1")
+ .arg(profile->expirationDate().toLocalTime().toString(Qt::SystemLocaleLongDate));
+ }
+ }
+ }
+
+ m_warningLabel->setVisible(!warningText.isEmpty());
+ m_warningIconLabel->setVisible(!warningText.isEmpty());
+ m_warningLabel->setText(warningText);
+}
+
+
+// IosBuildConfiguration
+
IosBuildConfiguration::IosBuildConfiguration(Target *target, Core::Id id)
: QmakeBuildConfiguration(target, id)
{
+ m_signingIdentifier = addAspect<BaseStringAspect>();
+ m_signingIdentifier->setSettingsKey(signingIdentifierKey);
+
+ m_autoManagedSigning = addAspect<BaseBoolAspect>();
+ m_autoManagedSigning->setDefaultValue(true);
+ m_autoManagedSigning->setSettingsKey(autoManagedSigningKey);
}
-QList<ProjectExplorer::NamedWidget *> IosBuildConfiguration::createSubConfigWidgets()
+QList<NamedWidget *> IosBuildConfiguration::createSubConfigWidgets()
{
auto subConfigWidgets = QmakeBuildConfiguration::createSubConfigWidgets();
- Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(target()->kit());
// Ownership of this widget is with BuildSettingsWidget
- auto buildSettingsWidget = new IosBuildSettingsWidget(devType, m_signingIdentifier,
- m_autoManagedSigning);
+ auto buildSettingsWidget = new IosBuildSettingsWidget(this);
subConfigWidgets.prepend(buildSettingsWidget);
- connect(buildSettingsWidget, &IosBuildSettingsWidget::signingSettingsChanged,
- this, &IosBuildConfiguration::onSigningSettingsChanged);
return subConfigWidgets;
}
-QVariantMap IosBuildConfiguration::toMap() const
-{
- QVariantMap map(QmakeBuildConfiguration::toMap());
- map.insert(signingIdentifierKey, m_signingIdentifier);
- map.insert(autoManagedSigningKey, m_autoManagedSigning);
- return map;
-}
-
bool IosBuildConfiguration::fromMap(const QVariantMap &map)
{
if (!QmakeBuildConfiguration::fromMap(map))
return false;
- m_autoManagedSigning = map.value(autoManagedSigningKey).toBool();
- m_signingIdentifier = map.value(signingIdentifierKey).toString();
updateQmakeCommand();
return true;
}
-void IosBuildConfiguration::onSigningSettingsChanged(bool autoManagedSigning, QString identifier)
-{
- if (m_signingIdentifier.compare(identifier) != 0
- || m_autoManagedSigning != autoManagedSigning) {
- m_autoManagedSigning = autoManagedSigning;
- m_signingIdentifier = identifier;
- updateQmakeCommand();
- }
-}
-
void IosBuildConfiguration::updateQmakeCommand()
{
QMakeStep *qmakeStepInstance = qmakeStep();
@@ -110,25 +451,26 @@ void IosBuildConfiguration::updateQmakeCommand()
});
// Set force ovveride qmake switch
- if (!m_signingIdentifier.isEmpty() )
+ const QString signingIdentifier = m_signingIdentifier->value();
+ if (signingIdentifier.isEmpty() )
extraArgs << forceOverrideArg;
- Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(target()->kit());
- if (devType == Constants::IOS_DEVICE_TYPE && !m_signingIdentifier.isEmpty()) {
- if (m_autoManagedSigning) {
- extraArgs << qmakeIosTeamSettings + m_signingIdentifier;
+ Core::Id devType = DeviceTypeKitAspect::deviceTypeId(target()->kit());
+ if (devType == Constants::IOS_DEVICE_TYPE && !signingIdentifier.isEmpty()) {
+ if (m_autoManagedSigning->value()) {
+ extraArgs << qmakeIosTeamSettings + signingIdentifier;
} else {
// Get the team id from provisioning profile
ProvisioningProfilePtr profile =
- IosConfigurations::provisioningProfile(m_signingIdentifier);
+ IosConfigurations::provisioningProfile(signingIdentifier);
QString teamId;
if (profile)
teamId = profile->developmentTeam()->identifier();
else
- qCDebug(iosLog) << "No provisioing profile found for id:"<< m_signingIdentifier;
+ qCDebug(iosLog) << "No provisioing profile found for id:" << signingIdentifier;
if (!teamId.isEmpty()) {
- extraArgs << qmakeProvisioningProfileSettings + m_signingIdentifier;
+ extraArgs << qmakeProvisioningProfileSettings + signingIdentifier;
extraArgs << qmakeIosTeamSettings + teamId;
} else {
qCDebug(iosLog) << "Development team unavailable for profile:" << profile;
diff --git a/src/plugins/ios/iosbuildconfiguration.h b/src/plugins/ios/iosbuildconfiguration.h
index aa3b529e94..d575b328b0 100644
--- a/src/plugins/ios/iosbuildconfiguration.h
+++ b/src/plugins/ios/iosbuildconfiguration.h
@@ -26,6 +26,8 @@
#include "qmakeprojectmanager/qmakebuildconfiguration.h"
+#include <projectexplorer/projectconfigurationaspects.h>
+
namespace Ios {
namespace Internal {
@@ -37,15 +39,15 @@ public:
IosBuildConfiguration(ProjectExplorer::Target *target, Core::Id id);
private:
+ friend class IosBuildSettingsWidget;
+
QList<ProjectExplorer::NamedWidget *> createSubConfigWidgets() override;
- QVariantMap toMap() const override;
bool fromMap(const QVariantMap &map) override;
- void onSigningSettingsChanged(bool autoManagedSigning, QString identifier);
void updateQmakeCommand();
- QString m_signingIdentifier;
- bool m_autoManagedSigning = true;
+ ProjectExplorer::BaseStringAspect *m_signingIdentifier = nullptr;
+ ProjectExplorer::BaseBoolAspect *m_autoManagedSigning = nullptr;
};
class IosBuildConfigurationFactory : public QmakeProjectManager::QmakeBuildConfigurationFactory
diff --git a/src/plugins/ios/iosbuildsettingswidget.cpp b/src/plugins/ios/iosbuildsettingswidget.cpp
deleted file mode 100644
index f7c90b3aa9..0000000000
--- a/src/plugins/ios/iosbuildsettingswidget.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "iosbuildsettingswidget.h"
-#include "ui_iosbuildsettingswidget.h"
-#include "iosconfigurations.h"
-#include "iosconstants.h"
-
-#include <qmakeprojectmanager/qmakeproject.h>
-#include <qmakeprojectmanager/qmakenodes.h>
-
-#include <projectexplorer/runconfiguration.h>
-
-#include <utils/algorithm.h>
-#include <utils/detailswidget.h>
-#include <utils/qtcassert.h>
-#include <utils/utilsicons.h>
-
-#include <QLoggingCategory>
-#include <QVBoxLayout>
-
-using namespace QmakeProjectManager;
-
-namespace Ios {
-namespace Internal {
-
-namespace {
-Q_LOGGING_CATEGORY(iosSettingsLog, "qtc.ios.common", QtWarningMsg)
-}
-
-static const int IdentifierRole = Qt::UserRole+1;
-
-IosBuildSettingsWidget::IosBuildSettingsWidget(const Core::Id &deviceType,
- const QString &signingIdentifier,
- bool isSigningAutoManaged, QWidget *parent) :
- ProjectExplorer::NamedWidget(parent),
- ui(new Ui::IosBuildSettingsWidget),
- m_detailsWidget(new Utils::DetailsWidget(this)),
- m_deviceType(deviceType)
-{
- auto rootLayout = new QVBoxLayout(this);
- rootLayout->setMargin(0);
- rootLayout->addWidget(m_detailsWidget);
-
- auto container = new QWidget(m_detailsWidget);
- ui->setupUi(container);
- ui->m_autoSignCheckbox->setChecked(isSigningAutoManaged);
- connect(ui->m_qmakeDefaults, &QPushButton::clicked, this, &IosBuildSettingsWidget::onReset);
-
- ui->m_infoIconLabel->hide();
- ui->m_infoIconLabel->setPixmap(Utils::Icons::INFO.pixmap());
- ui->m_infoLabel->hide();
-
- ui->m_warningIconLabel->hide();
- ui->m_warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap());
- ui->m_warningLabel->hide();
-
- m_detailsWidget->setState(Utils::DetailsWidget::NoSummary);
- m_detailsWidget->setWidget(container);
-
- setDisplayName(tr("iOS Settings"));
-
- const bool isDevice = m_deviceType == Constants::IOS_DEVICE_TYPE;
- if (isDevice) {
- connect(IosConfigurations::instance(), &IosConfigurations::provisioningDataChanged,
- this, &IosBuildSettingsWidget::populateDevelopmentTeams);
- connect(ui->m_signEntityCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &IosBuildSettingsWidget::onSigningEntityComboIndexChanged);
- connect(ui->m_autoSignCheckbox, &QCheckBox::toggled,
- this, &IosBuildSettingsWidget::configureSigningUi);
- configureSigningUi(ui->m_autoSignCheckbox->isChecked());
- setDefaultSigningIdentfier(signingIdentifier);
- }
-
- ui->m_autoSignCheckbox->setEnabled(isDevice);
- ui->m_signEntityCombo->setEnabled(isDevice);
- ui->m_qmakeDefaults->setEnabled(isDevice);
- ui->m_signEntityLabel->setEnabled(isDevice);
- adjustSize();
-}
-
-IosBuildSettingsWidget::~IosBuildSettingsWidget()
-{
- delete ui;
-}
-
-void IosBuildSettingsWidget::setDefaultSigningIdentfier(const QString &identifier) const
-{
- if (identifier.isEmpty()) {
- ui->m_signEntityCombo->setCurrentIndex(0);
- return;
- }
-
- int defaultIndex = -1;
- for (int index = 0; index < ui->m_signEntityCombo->count(); ++index) {
- QString teamID = ui->m_signEntityCombo->itemData(index, IdentifierRole).toString();
- if (teamID == identifier) {
- defaultIndex = index;
- break;
- }
- }
- if (defaultIndex > -1) {
- ui->m_signEntityCombo->setCurrentIndex(defaultIndex);
- } else {
- // Reset to default
- ui->m_signEntityCombo->setCurrentIndex(0);
- qCDebug(iosSettingsLog) << "Cannot find default"
- << (ui->m_autoSignCheckbox->isChecked() ? "team": "provisioning profile")
- << ". Identifier: " << identifier;
- }
-}
-
-bool IosBuildSettingsWidget::isSigningAutomaticallyManaged() const
-{
- return ui->m_autoSignCheckbox->isChecked() && ui->m_signEntityCombo->currentIndex() > 0;
-}
-
-void IosBuildSettingsWidget::onSigningEntityComboIndexChanged()
-{
- QString identifier = selectedIdentifier();
- (ui->m_autoSignCheckbox->isChecked() ? m_lastTeamSelection : m_lastProfileSelection) = identifier;
-
- updateInfoText();
- updateWarningText();
- emit signingSettingsChanged(ui->m_autoSignCheckbox->isChecked(), identifier);
-}
-
-void IosBuildSettingsWidget::onReset()
-{
- m_lastTeamSelection.clear();
- m_lastProfileSelection.clear();
- ui->m_autoSignCheckbox->setChecked(true);
- setDefaultSigningIdentfier("");
-}
-
-void IosBuildSettingsWidget::configureSigningUi(bool autoManageSigning)
-{
- ui->m_signEntityLabel->setText(autoManageSigning ? tr("Development team:")
- : tr("Provisioning profile:"));
- if (autoManageSigning)
- populateDevelopmentTeams();
- else
- populateProvisioningProfiles();
-
- updateInfoText();
- emit signingSettingsChanged(autoManageSigning, selectedIdentifier());
-}
-
-void IosBuildSettingsWidget::populateDevelopmentTeams()
-{
- {
- QSignalBlocker blocker(ui->m_signEntityCombo);
- // Populate Team id's
- ui->m_signEntityCombo->clear();
- ui->m_signEntityCombo->addItem(tr("Default"));
- foreach (auto team, IosConfigurations::developmentTeams()) {
- ui->m_signEntityCombo->addItem(team->displayName());
- const int index = ui->m_signEntityCombo->count() - 1;
- ui->m_signEntityCombo->setItemData(index, team->identifier(), IdentifierRole);
- ui->m_signEntityCombo->setItemData(index, team->details(), Qt::ToolTipRole);
- }
- }
- // Maintain previous selection.
- setDefaultSigningIdentfier(m_lastTeamSelection);
- updateWarningText();
-}
-
-void IosBuildSettingsWidget::populateProvisioningProfiles()
-{
- {
- // Populate Team id's
- QSignalBlocker blocker(ui->m_signEntityCombo);
- ui->m_signEntityCombo->clear();
- ProvisioningProfiles profiles = IosConfigurations::provisioningProfiles();
- if (profiles.count() > 0) {
- foreach (auto profile, profiles) {
- ui->m_signEntityCombo->addItem(profile->displayName());
- const int index = ui->m_signEntityCombo->count() - 1;
- ui->m_signEntityCombo->setItemData(index, profile->identifier(), IdentifierRole);
- ui->m_signEntityCombo->setItemData(index, profile->details(), Qt::ToolTipRole);
- }
- } else {
- ui->m_signEntityCombo->addItem(tr("None"));
- }
- }
- // Maintain previous selection.
- setDefaultSigningIdentfier(m_lastProfileSelection);
- updateWarningText();
-}
-
-QString IosBuildSettingsWidget::selectedIdentifier() const
-{
- return ui->m_signEntityCombo->currentData(IdentifierRole).toString();
-}
-
-void IosBuildSettingsWidget::updateInfoText()
-{
- if (m_deviceType != Constants::IOS_DEVICE_TYPE)
- return;
-
- QString infoMessage;
- auto addMessage = [&infoMessage](const QString &msg) {
- if (!infoMessage.isEmpty())
- infoMessage += "\n";
- infoMessage += msg;
- };
-
- QString identifier = selectedIdentifier();
- bool configuringTeams = ui->m_autoSignCheckbox->isChecked();
-
- if (identifier.isEmpty()) {
- // No signing entity selection.
- if (configuringTeams)
- addMessage(tr("Development team is not selected."));
- else
- addMessage(tr("Provisioning profile is not selected."));
-
- addMessage(tr("Using default development team and provisioning profile."));
- } else {
- if (!configuringTeams) {
- ProvisioningProfilePtr profile = IosConfigurations::provisioningProfile(identifier);
- QTC_ASSERT(profile, return);
- auto team = profile->developmentTeam();
- if (team) {
- // Display corresponding team information.
- addMessage(tr("Development team: %1 (%2)").arg(team->displayName())
- .arg(team->identifier()));
- addMessage(tr("Settings defined here override the QMake environment."));
- } else {
- qCDebug(iosSettingsLog) << "Development team not found for profile" << profile;
- }
- } else {
- addMessage(tr("Settings defined here override the QMake environment."));
- }
- }
-
- ui->m_infoIconLabel->setVisible(!infoMessage.isEmpty());
- ui->m_infoLabel->setVisible(!infoMessage.isEmpty());
- ui->m_infoLabel->setText(infoMessage);
-}
-
-void IosBuildSettingsWidget::updateWarningText()
-{
- if (m_deviceType != Constants::IOS_DEVICE_TYPE)
- return;
-
- QString warningText;
- bool configuringTeams = ui->m_autoSignCheckbox->isChecked();
- if (ui->m_signEntityCombo->count() < 2) {
- warningText = tr("%1 not configured. Use Xcode and Apple developer account to configure the "
- "provisioning profiles and teams.")
- .arg(configuringTeams ? tr("Development teams") : tr("Provisioning profiles"));
- } else {
- QString identifier = selectedIdentifier();
- if (configuringTeams) {
- auto team = IosConfigurations::developmentTeam(identifier);
- if (team && !team->hasProvisioningProfile())
- warningText = tr("No provisioning profile found for the selected team.");
- } else {
- auto profile = IosConfigurations::provisioningProfile(identifier);
- if (profile && QDateTime::currentDateTimeUtc() > profile->expirationDate()) {
- warningText = tr("Provisioning profile expired. Expiration date: %1")
- .arg(profile->expirationDate().toLocalTime().toString(Qt::SystemLocaleLongDate));
- }
- }
- }
-
- ui->m_warningLabel->setVisible(!warningText.isEmpty());
- ui->m_warningIconLabel->setVisible(!warningText.isEmpty());
- ui->m_warningLabel->setText(warningText);
-}
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iosbuildsettingswidget.h b/src/plugins/ios/iosbuildsettingswidget.h
deleted file mode 100644
index e8641fefcb..0000000000
--- a/src/plugins/ios/iosbuildsettingswidget.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 <coreplugin/id.h>
-#include "projectexplorer/namedwidget.h"
-
-#include <QWidget>
-
-namespace Utils {
-class DetailsWidget;
-}
-
-
-namespace Ios {
-namespace Internal {
-namespace Ui {
- class IosBuildSettingsWidget;
-}
-
-class IosBuildSettingsWidget : public ProjectExplorer::NamedWidget
-{
- Q_OBJECT
-
-public:
- explicit IosBuildSettingsWidget(const Core::Id &deviceType, const QString &signingIdentifier,
- bool isSigningAutoManaged, QWidget *parent = nullptr);
- ~IosBuildSettingsWidget() override;
-
- bool isSigningAutomaticallyManaged() const;
-
-signals:
- void signingSettingsChanged(bool isAutoManaged, QString identifier);
-
-private:
- void onSigningEntityComboIndexChanged();
- void onReset();
-
- void setDefaultSigningIdentfier(const QString &identifier) const;
- void configureSigningUi(bool autoManageSigning);
- void populateDevelopmentTeams();
- void populateProvisioningProfiles();
- QString selectedIdentifier() const;
- void updateInfoText();
- void updateWarningText();
-
-private:
- Ui::IosBuildSettingsWidget *ui;
- Utils::DetailsWidget *m_detailsWidget;
- QString m_lastProfileSelection;
- QString m_lastTeamSelection;
- const Core::Id m_deviceType;
-};
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iosbuildsettingswidget.ui b/src/plugins/ios/iosbuildsettingswidget.ui
deleted file mode 100644
index 3a947d42c8..0000000000
--- a/src/plugins/ios/iosbuildsettingswidget.ui
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Ios::Internal::IosBuildSettingsWidget</class>
- <widget class="QWidget" name="Ios::Internal::IosBuildSettingsWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>467</width>
- <height>141</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="1">
- <widget class="QPushButton" name="m_qmakeDefaults">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Reset</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="m_signEntityCombo">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QCheckBox" name="m_autoSignCheckbox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Automatically manage signing</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="m_signEntityLabel">
- <property name="text">
- <string>Development team:</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLabel" name="m_infoIconLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="m_infoLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLabel" name="m_warningIconLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="m_warningLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp
index 8d78446c51..0fbcb44305 100644
--- a/src/plugins/ios/iosbuildstep.cpp
+++ b/src/plugins/ios/iosbuildstep.cpp
@@ -76,7 +76,7 @@ bool IosBuildStep::init()
if (!bc)
emit addTask(Task::buildConfigurationMissingTask());
- ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!tc)
emit addTask(Task::compilerMissingTask());
@@ -87,11 +87,11 @@ bool IosBuildStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
- pp->setWorkingDirectory(bc->buildDirectory().toString());
+ pp->setWorkingDirectory(bc->buildDirectory());
Utils::Environment env = bc->environment();
Utils::Environment::setupEnglishOutput(&env);
pp->setEnvironment(env);
- pp->setCommand(buildCommand());
+ pp->setCommand(Utils::FilePath::fromString(buildCommand()));
pp->setArguments(Utils::QtcProcess::joinArgs(allArguments()));
pp->resolveAll();
@@ -138,7 +138,7 @@ QStringList IosBuildStep::defaultArguments() const
{
QStringList res;
Kit *kit = target()->kit();
- ToolChain *tc = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChain *tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
switch (buildConfiguration()->buildType()) {
case BuildConfiguration::Debug :
res << "-configuration" << "Debug";
@@ -158,8 +158,8 @@ QStringList IosBuildStep::defaultArguments() const
auto gtc = static_cast<GccToolChain *>(tc);
res << gtc->platformCodeGenFlags();
}
- if (!SysRootKitInformation::sysRoot(kit).isEmpty())
- res << "-sdk" << SysRootKitInformation::sysRoot(kit).toString();
+ if (!SysRootKitAspect::sysRoot(kit).isEmpty())
+ res << "-sdk" << SysRootKitAspect::sysRoot(kit).toString();
res << "SYMROOT=" + buildConfiguration()->buildDirectory().toString();
return res;
}
@@ -251,9 +251,9 @@ void IosBuildStepConfigWidget::updateDetails()
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
- param.setWorkingDirectory(bc->buildDirectory().toString());
+ param.setWorkingDirectory(bc->buildDirectory());
param.setEnvironment(bc->environment());
- param.setCommand(m_buildStep->buildCommand());
+ param.setCommand(Utils::FilePath::fromString(m_buildStep->buildCommand()));
param.setArguments(Utils::QtcProcess::joinArgs(m_buildStep->allArguments()));
setSummaryText(param.summary(displayName()));
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp
index 3ceec86714..6b4c244386 100644
--- a/src/plugins/ios/iosconfigurations.cpp
+++ b/src/plugins/ios/iosconfigurations.cpp
@@ -136,7 +136,7 @@ static ToolChainPair findToolChainForPlatform(const XcodePlatform &platform,
const QList<ClangToolChain *> &toolChains)
{
ToolChainPair platformToolChains;
- auto toolchainMatch = [](ClangToolChain *toolChain, const Utils::FileName &compilerPath, const QStringList &flags) {
+ auto toolchainMatch = [](ClangToolChain *toolChain, const Utils::FilePath &compilerPath, const QStringList &flags) {
return compilerPath == toolChain->compilerCommand()
&& flags == toolChain->platformCodeGenFlags()
&& flags == toolChain->platformLinkerFlags();
@@ -168,7 +168,7 @@ static QHash<XcodePlatform::ToolchainTarget, ToolChainPair> findToolChains(const
static QSet<Kit *> existingAutoDetectedIosKits()
{
return Utils::filtered(KitManager::kits(), [](Kit *kit) -> bool {
- Core::Id deviceKind = DeviceTypeKitInformation::deviceTypeId(kit);
+ Core::Id deviceKind = DeviceTypeKitAspect::deviceTypeId(kit);
return kit->isAutoDetected() && (deviceKind == Constants::IOS_DEVICE_TYPE
|| deviceKind == Constants::IOS_SIMULATOR_TYPE);
}).toSet();
@@ -181,40 +181,40 @@ static void printKits(const QSet<Kit *> &kits)
}
static void setupKit(Kit *kit, Core::Id pDeviceType, const ToolChainPair& toolChains,
- const QVariant &debuggerId, const Utils::FileName &sdkPath, BaseQtVersion *qtVersion)
+ const QVariant &debuggerId, const Utils::FilePath &sdkPath, BaseQtVersion *qtVersion)
{
- DeviceTypeKitInformation::setDeviceTypeId(kit, pDeviceType);
+ DeviceTypeKitAspect::setDeviceTypeId(kit, pDeviceType);
if (toolChains.first)
- ToolChainKitInformation::setToolChain(kit, toolChains.first);
+ ToolChainKitAspect::setToolChain(kit, toolChains.first);
else
- ToolChainKitInformation::clearToolChain(kit, ProjectExplorer::Constants::C_LANGUAGE_ID);
+ ToolChainKitAspect::clearToolChain(kit, ProjectExplorer::Constants::C_LANGUAGE_ID);
if (toolChains.second)
- ToolChainKitInformation::setToolChain(kit, toolChains.second);
+ ToolChainKitAspect::setToolChain(kit, toolChains.second);
else
- ToolChainKitInformation::clearToolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChainKitAspect::clearToolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
- QtKitInformation::setQtVersion(kit, qtVersion);
+ QtKitAspect::setQtVersion(kit, qtVersion);
// only replace debugger with the default one if we find an unusable one here
// (since the user could have changed it)
- if ((!DebuggerKitInformation::debugger(kit)
- || !DebuggerKitInformation::debugger(kit)->isValid()
- || DebuggerKitInformation::debugger(kit)->engineType() != LldbEngineType)
+ if ((!DebuggerKitAspect::debugger(kit)
+ || !DebuggerKitAspect::debugger(kit)->isValid()
+ || DebuggerKitAspect::debugger(kit)->engineType() != LldbEngineType)
&& debuggerId.isValid())
- DebuggerKitInformation::setDebugger(kit, debuggerId);
+ DebuggerKitAspect::setDebugger(kit, debuggerId);
- kit->setMutable(DeviceKitInformation::id(), true);
- kit->setSticky(QtKitInformation::id(), true);
- kit->setSticky(ToolChainKitInformation::id(), true);
- kit->setSticky(DeviceTypeKitInformation::id(), true);
- kit->setSticky(SysRootKitInformation::id(), true);
- kit->setSticky(DebuggerKitInformation::id(), false);
+ kit->setMutable(DeviceKitAspect::id(), true);
+ kit->setSticky(QtKitAspect::id(), true);
+ kit->setSticky(ToolChainKitAspect::id(), true);
+ kit->setSticky(DeviceTypeKitAspect::id(), true);
+ kit->setSticky(SysRootKitAspect::id(), true);
+ kit->setSticky(DebuggerKitAspect::id(), false);
- SysRootKitInformation::setSysRoot(kit, sdkPath);
+ SysRootKitAspect::setSysRoot(kit, sdkPath);
}
-static QVersionNumber findXcodeVersion(const Utils::FileName &developerPath)
+static QVersionNumber findXcodeVersion(const Utils::FilePath &developerPath)
{
- FileName xcodeInfo = developerPath.parentDir().appendPath("Info.plist");
+ const FilePath xcodeInfo = developerPath.parentDir().pathAppended("Info.plist");
if (xcodeInfo.exists()) {
QSettings settings(xcodeInfo.toString(), QSettings::NativeFormat);
return QVersionNumber::fromString(settings.value("CFBundleShortVersionString").toString());
@@ -287,10 +287,10 @@ void IosConfigurations::updateAutomaticKitList()
Kit *kit = Utils::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 DeviceTypeKitInformation::deviceTypeId(kit) == pDeviceType
- && ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID) == platformToolchains.second
- && ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::C_LANGUAGE_ID) == platformToolchains.first
- && QtKitInformation::qtVersion(kit) == qtVersion;
+ return DeviceTypeKitAspect::deviceTypeId(kit) == pDeviceType
+ && ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID) == platformToolchains.second
+ && ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::C_LANGUAGE_ID) == platformToolchains.first
+ && QtKitAspect::qtVersion(kit) == qtVersion;
});
QTC_ASSERT(!resultingKits.contains(kit), continue);
if (kit) {
@@ -300,17 +300,15 @@ void IosConfigurations::updateAutomaticKitList()
kit->unblockNotification();
} else {
qCDebug(kitSetupLog) << " - Setting up new kit";
- auto newKit = std::make_unique<Kit>();
- kit = newKit.get();
- kit->blockNotification();
- kit->setAutoDetected(true);
- const QString baseDisplayName = isSimulatorDeviceId(pDeviceType)
- ? tr("%1 Simulator").arg(qtVersion->unexpandedDisplayName())
- : qtVersion->unexpandedDisplayName();
- kit->setUnexpandedDisplayName(baseDisplayName);
- setupKit(kit, pDeviceType, platformToolchains, debuggerId, sdk.path, qtVersion);
- kit->unblockNotification();
- KitManager::registerKit(std::move(newKit));
+ const auto init = [&](Kit *k) {
+ k->setAutoDetected(true);
+ const QString baseDisplayName = isSimulatorDeviceId(pDeviceType)
+ ? tr("%1 Simulator").arg(qtVersion->unexpandedDisplayName())
+ : qtVersion->unexpandedDisplayName();
+ k->setUnexpandedDisplayName(baseDisplayName);
+ setupKit(k, pDeviceType, platformToolchains, debuggerId, sdk.path, qtVersion);
+ };
+ kit = KitManager::registerKit(init);
}
resultingKits.insert(kit);
}
@@ -359,7 +357,7 @@ void IosConfigurations::setIgnoreAllDevices(bool ignoreDevices)
}
}
-void IosConfigurations::setScreenshotDir(const FileName &path)
+void IosConfigurations::setScreenshotDir(const FilePath &path)
{
if (m_instance->m_screenshotDir != path) {
m_instance->m_screenshotDir = path;
@@ -367,12 +365,12 @@ void IosConfigurations::setScreenshotDir(const FileName &path)
}
}
-FileName IosConfigurations::screenshotDir()
+FilePath IosConfigurations::screenshotDir()
{
return m_instance->m_screenshotDir;
}
-FileName IosConfigurations::developerPath()
+FilePath IosConfigurations::developerPath()
{
return m_instance->m_developerPath;
}
@@ -404,11 +402,11 @@ void IosConfigurations::load()
QSettings *settings = Core::ICore::settings();
settings->beginGroup(SettingsGroup);
m_ignoreAllDevices = settings->value(ignoreAllDevicesKey, false).toBool();
- m_screenshotDir = FileName::fromString(settings->value(screenshotDirPathKey).toString());
+ m_screenshotDir = FilePath::fromString(settings->value(screenshotDirPathKey).toString());
if (!m_screenshotDir.exists()) {
QString defaultDir =
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).constFirst();
- m_screenshotDir = FileName::fromString(defaultDir);
+ m_screenshotDir = FilePath::fromString(defaultDir);
}
settings->endGroup();
@@ -427,7 +425,7 @@ void IosConfigurations::updateSimulators()
SimulatorControl::updateAvailableSimulators();
}
-void IosConfigurations::setDeveloperPath(const FileName &devPath)
+void IosConfigurations::setDeveloperPath(const FilePath &devPath)
{
static bool hasDevPath = false;
if (devPath != m_instance->m_developerPath) {
@@ -588,7 +586,8 @@ static ClangToolChain *createToolChain(const XcodePlatform &platform,
&& l != Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID))
return nullptr;
- auto toolChain = new ClangToolChain(ToolChain::AutoDetection);
+ auto toolChain = new ClangToolChain;
+ toolChain->setDetection(ToolChain::AutoDetection);
toolChain->setLanguage(l);
toolChain->setDisplayName(target.name);
toolChain->setPlatformCodeGenFlags(target.backendFlags);
@@ -599,12 +598,10 @@ static ClangToolChain *createToolChain(const XcodePlatform &platform,
return toolChain;
}
-QSet<Core::Id> IosToolChainFactory::supportedLanguages() const
+IosToolChainFactory::IosToolChainFactory()
{
- return {
- ProjectExplorer::Constants::C_LANGUAGE_ID,
- ProjectExplorer::Constants::CXX_LANGUAGE_ID
- };
+ setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID,
+ ProjectExplorer::Constants::CXX_LANGUAGE_ID});
}
QList<ToolChain *> IosToolChainFactory::autoDetect(const QList<ToolChain *> &existingToolChains)
diff --git a/src/plugins/ios/iosconfigurations.h b/src/plugins/ios/iosconfigurations.h
index 9b3faa348e..cddf0a5806 100644
--- a/src/plugins/ios/iosconfigurations.h
+++ b/src/plugins/ios/iosconfigurations.h
@@ -98,7 +98,8 @@ class IosToolChainFactory : public ProjectExplorer::ToolChainFactory
Q_OBJECT
public:
- QSet<Core::Id> supportedLanguages() const override;
+ IosToolChainFactory();
+
QList<ProjectExplorer::ToolChain *> autoDetect(const QList<ProjectExplorer::ToolChain *> &existingToolChains) override;
};
@@ -111,11 +112,11 @@ public:
static void initialize();
static bool ignoreAllDevices();
static void setIgnoreAllDevices(bool ignoreDevices);
- static void setScreenshotDir(const Utils::FileName &path);
- static Utils::FileName screenshotDir();
- static Utils::FileName developerPath();
+ static void setScreenshotDir(const Utils::FilePath &path);
+ static Utils::FilePath screenshotDir();
+ static Utils::FilePath developerPath();
static QVersionNumber xcodeVersion();
- static Utils::FileName lldbPath();
+ static Utils::FilePath lldbPath();
static void updateAutomaticKitList();
static const DevelopmentTeams &developmentTeams();
static DevelopmentTeamPtr developmentTeam(const QString &teamID);
@@ -131,12 +132,12 @@ private:
void save();
void kitsRestored();
void updateSimulators();
- static void setDeveloperPath(const Utils::FileName &devPath);
+ static void setDeveloperPath(const Utils::FilePath &devPath);
void initializeProvisioningData();
void loadProvisioningData(bool notify = true);
- Utils::FileName m_developerPath;
- Utils::FileName m_screenshotDir;
+ Utils::FilePath m_developerPath;
+ Utils::FilePath m_screenshotDir;
QVersionNumber m_xcodeVersion;
bool m_ignoreAllDevices;
QFileSystemWatcher *m_provisioningDataWatcher = nullptr;
diff --git a/src/plugins/ios/iosconstants.h b/src/plugins/ios/iosconstants.h
index 540896e0e6..9731960bde 100644
--- a/src/plugins/ios/iosconstants.h
+++ b/src/plugins/ios/iosconstants.h
@@ -44,6 +44,9 @@ const char IOS_SIMULATOR_DEVICE_ID[] = "iOS Simulator Device ";
const char IOS_PRESET_BUILD_STEP_ID[] = "Ios.IosPresetBuildStep";
const char IOS_DSYM_BUILD_STEP_ID[] = "Ios.IosDsymBuildStep";
+const char IosTarget[] = "IosTarget"; // QString
+const char IosBuildDir[] = "IosBuildDir"; // QString
+
const quint16 IOS_DEVICE_PORT_START = 30000;
const quint16 IOS_DEVICE_PORT_END = 31000;
const quint16 IOS_SIMULATOR_PORT_START = 30000;
diff --git a/src/plugins/ios/iosdeploystep.cpp b/src/plugins/ios/iosdeploystep.cpp
index 65a225e7e6..2a0da618af 100644
--- a/src/plugins/ios/iosdeploystep.cpp
+++ b/src/plugins/ios/iosdeploystep.cpp
@@ -23,7 +23,6 @@
**
****************************************************************************/
-#include "iosdeploystepwidget.h"
#include "iosdeploystep.h"
#include "iosbuildstep.h"
#include "iosconstants.h"
@@ -31,6 +30,7 @@
#include "iostoolhandler.h"
#include <coreplugin/messagemanager.h>
+
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
@@ -50,6 +50,7 @@
#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
using namespace ProjectExplorer;
+using namespace Utils;
namespace Ios {
namespace Internal {
@@ -73,7 +74,7 @@ Core::Id IosDeployStep::stepId()
void IosDeployStep::updateDisplayNames()
{
IDevice::ConstPtr dev =
- DeviceKitInformation::device(target()->kit());
+ DeviceKitAspect::device(target()->kit());
const QString devName = dev.isNull() ? IosDevice::name() : dev->displayName();
setDefaultDisplayName(tr("Deploy to %1").arg(devName));
setDisplayName(tr("Deploy to %1").arg(devName));
@@ -82,11 +83,11 @@ void IosDeployStep::updateDisplayNames()
bool IosDeployStep::init()
{
QTC_ASSERT(m_transferStatus == NoTransfer, return false);
- m_device = DeviceKitInformation::device(target()->kit());
+ m_device = DeviceKitAspect::device(target()->kit());
auto runConfig = qobject_cast<const IosRunConfiguration *>(
this->target()->activeRunConfiguration());
QTC_ASSERT(runConfig, return false);
- m_bundlePath = runConfig->bundleDirectory().toString();
+ m_bundlePath = runConfig->bundleDirectory();
if (iosdevice()) {
m_deviceType = IosDeviceType(IosDeviceType::IosDevice, deviceId());
@@ -122,7 +123,7 @@ void IosDeployStep::doRun()
connect(m_toolHandler, &IosToolHandler::errorMsg,
this, &IosDeployStep::handleErrorMsg);
checkProvisioningProfile();
- m_toolHandler->requestTransferApp(appBundle(), m_deviceType.identifier);
+ m_toolHandler->requestTransferApp(m_bundlePath.toString(), m_deviceType.identifier);
}
void IosDeployStep::doCancel()
@@ -197,7 +198,16 @@ void IosDeployStep::handleErrorMsg(IosToolHandler *handler, const QString &msg)
BuildStepConfigWidget *IosDeployStep::createConfigWidget()
{
- return new IosDeployStepWidget(this);
+ auto widget = new BuildStepConfigWidget(this);
+
+ widget->setObjectName("IosDeployStepWidget");
+ widget->setDisplayName(QString("<b>%1</b>").arg(displayName()));
+ widget->setSummaryText(widget->displayName());
+
+ connect(this, &ProjectConfiguration::displayNameChanged,
+ widget, &BuildStepConfigWidget::updateSummary);
+
+ return widget;
}
bool IosDeployStep::fromMap(const QVariantMap &map)
@@ -218,14 +228,9 @@ QString IosDeployStep::deviceId() const
return iosdevice()->uniqueDeviceID();
}
-QString IosDeployStep::appBundle() const
-{
- return m_bundlePath;
-}
-
void IosDeployStep::raiseError(const QString &errorString)
{
- emit addTask(Task(Task::Error, errorString, Utils::FileName::fromString(QString()), -1,
+ emit addTask(Task(Task::Error, errorString, Utils::FilePath::fromString(QString()), -1,
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT));
}
@@ -240,8 +245,7 @@ void IosDeployStep::checkProvisioningProfile()
if (device.isNull())
return;
- Utils::FileName provisioningFilePath = Utils::FileName::fromString(appBundle());
- provisioningFilePath.appendPath(QLatin1String("embedded.mobileprovision"));
+ const FilePath provisioningFilePath = m_bundlePath.pathAppended("embedded.mobileprovision");
// the file is a signed plist stored in DER format
// we simply search for start and end of the plist instead of decoding the DER payload
@@ -281,7 +285,7 @@ void IosDeployStep::checkProvisioningProfile()
"does not cover the device %3 (%4). Deployment to it will fail.")
.arg(provisioningProfile, provisioningUid, device->displayName(),
targetId),
- Utils::FileName(), /* filename */
+ Utils::FilePath(), /* filename */
-1, /* line */
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task);
diff --git a/src/plugins/ios/iosdeploystep.h b/src/plugins/ios/iosdeploystep.h
index 56ce87fec3..77b386583e 100644
--- a/src/plugins/ios/iosdeploystep.h
+++ b/src/plugins/ios/iosdeploystep.h
@@ -76,7 +76,6 @@ private:
IosSimulator::ConstPtr iossimulator() const;
QString deviceId() const;
- QString appBundle() const;
void raiseError(const QString &error);
void writeOutput(const QString &text, OutputFormat = OutputFormat::NormalMessage);
void checkProvisioningProfile();
@@ -84,7 +83,7 @@ private:
TransferStatus m_transferStatus = NoTransfer;
IosToolHandler *m_toolHandler = nullptr;
ProjectExplorer::IDevice::ConstPtr m_device;
- QString m_bundlePath;
+ Utils::FilePath m_bundlePath;
IosDeviceType m_deviceType;
static const Core::Id Id;
bool m_expectFail = false;
diff --git a/src/plugins/ios/iosdeploystepwidget.cpp b/src/plugins/ios/iosdeploystepwidget.cpp
deleted file mode 100644
index d24b2d38b7..0000000000
--- a/src/plugins/ios/iosdeploystepwidget.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 "iosdeploystepwidget.h"
-#include "ui_iosdeploystepwidget.h"
-
-#include "iosdeploystep.h"
-#include "iosrunconfiguration.h"
-
-#include <coreplugin/icore.h>
-
-namespace Ios {
-namespace Internal {
-
-IosDeployStepWidget::IosDeployStepWidget(IosDeployStep *step) :
- ProjectExplorer::BuildStepConfigWidget(step),
- ui(new Ui::IosDeployStepWidget),
- m_step(step)
-{
- setDisplayName(QString::fromLatin1("<b>%1</b>").arg(m_step->displayName()));
- setSummaryText(displayName());
- ui->setupUi(this);
- connect(m_step, &ProjectExplorer::ProjectConfiguration::displayNameChanged,
- this, &ProjectExplorer::BuildStepConfigWidget::updateSummary);
-}
-
-IosDeployStepWidget::~IosDeployStepWidget()
-{
- delete ui;
-}
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iosdeploystepwidget.h b/src/plugins/ios/iosdeploystepwidget.h
deleted file mode 100644
index fb07a8cee0..0000000000
--- a/src/plugins/ios/iosdeploystepwidget.h
+++ /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.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/buildstep.h>
-
-namespace Ios {
-namespace Internal {
-
-namespace Ui { class IosDeployStepWidget; }
-
-class IosDeployStep;
-
-class IosDeployStepWidget : public ProjectExplorer::BuildStepConfigWidget
-{
- Q_OBJECT
-
-public:
- IosDeployStepWidget(IosDeployStep *step);
- ~IosDeployStepWidget() override;
-
-private:
- Ui::IosDeployStepWidget *ui;
- IosDeployStep *m_step;
-};
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iosdeploystepwidget.ui b/src/plugins/ios/iosdeploystepwidget.ui
deleted file mode 100644
index e89429281e..0000000000
--- a/src/plugins/ios/iosdeploystepwidget.ui
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Ios::Internal::IosDeployStepWidget</class>
- <widget class="QWidget" name="IosDeployStepWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>479</width>
- <height>76</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <layout class="QGridLayout" name="gridLayout"/>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp
index 0f8cd500a0..6fe7bfe40c 100644
--- a/src/plugins/ios/iosdevice.cpp
+++ b/src/plugins/ios/iosdevice.cpp
@@ -92,8 +92,6 @@ IosDevice::IosDevice()
setFreePorts(ports);
}
-IosDevice::IosDevice(const IosDevice &other) = default;
-
IosDevice::IosDevice(const QString &uid)
: m_lastPort(Constants::IOS_DEVICE_PORT_START)
{
@@ -133,11 +131,6 @@ DeviceProcessSignalOperation::Ptr IosDevice::signalOperation() const
return DeviceProcessSignalOperation::Ptr();
}
-IDevice::Ptr IosDevice::clone() const
-{
- return IDevice::Ptr(new IosDevice(*this));
-}
-
void IosDevice::fromMap(const QVariantMap &map)
{
IDevice::fromMap(map);
@@ -234,14 +227,10 @@ void IosDeviceManager::deviceConnected(const QString &uid, const QString &name)
} else if (dev->deviceState() != IDevice::DeviceConnected &&
dev->deviceState() != IDevice::DeviceReadyToUse) {
qCDebug(detectLog) << "updating ios device " << uid;
- IosDevice *newDev = nullptr;
- if (dev->type() == devType) {
- auto iosDev = static_cast<const IosDevice *>(dev.data());
- newDev = new IosDevice(*iosDev);
- } else {
- newDev = new IosDevice(uid);
- }
- devManager->addDevice(IDevice::ConstPtr(newDev));
+ if (dev->type() == devType) // FIXME: Should that be a QTC_ASSERT?
+ devManager->addDevice(dev->clone());
+ else
+ devManager->addDevice(IDevice::ConstPtr(new IosDevice(uid)));
}
updateInfo(uid);
}
@@ -294,7 +283,8 @@ void IosDeviceManager::deviceInfo(IosToolHandler *, const QString &uid,
skipUpdate = true;
newDev = const_cast<IosDevice *>(iosDev);
} else {
- newDev = new IosDevice(*iosDev);
+ newDev = new IosDevice();
+ newDev->fromMap(iosDev->toMap());
}
} else {
newDev = new IosDevice(uid);
@@ -538,13 +528,25 @@ void IosDeviceManager::updateAvailableDevices(const QStringList &devices)
}
}
-IosDevice::ConstPtr IosKitInformation::device(Kit *kit)
+// Factory
+
+IosDeviceFactory::IosDeviceFactory()
+ : IDeviceFactory(Constants::IOS_DEVICE_TYPE)
{
- if (!kit)
- return IosDevice::ConstPtr();
- IDevice::ConstPtr dev = DeviceKitInformation::device(kit);
- IosDevice::ConstPtr res = dev.dynamicCast<const IosDevice>();
- return res;
+ setObjectName(QLatin1String("IosDeviceFactory"));
+ setDisplayName(IosDevice::name());
+ setCombinedIcon(":/ios/images/iosdevicesmall.png",
+ ":/ios/images/iosdevice.png");
+ setConstructionFunction([] { return IDevice::Ptr(new IosDevice); });
+}
+
+bool IosDeviceFactory::canRestore(const QVariantMap &map) const
+{
+ QVariantMap vMap = map.value(QLatin1String(Constants::EXTRA_INFO_KEY)).toMap();
+ if (vMap.isEmpty()
+ || vMap.value(QLatin1String("deviceName")).toString() == QLatin1String("*unknown*"))
+ return false; // transient device (probably generated during an activation)
+ return true;
}
} // namespace Internal
diff --git a/src/plugins/ios/iosdevice.h b/src/plugins/ios/iosdevice.h
index 54f5785e70..79037d8eb3 100644
--- a/src/plugins/ios/iosdevice.h
+++ b/src/plugins/ios/iosdevice.h
@@ -28,17 +28,14 @@
#include "iostoolhandler.h"
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefactory.h>
#include <QVariantMap>
#include <QMap>
#include <QString>
-#include <QSharedPointer>
#include <QStringList>
#include <QTimer>
-namespace ProjectExplorer{
-class Kit;
-}
namespace Ios {
class IosConfigurations;
@@ -57,11 +54,9 @@ public:
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override;
QString displayType() const override;
- ProjectExplorer::IDevice::Ptr clone() const override;
void fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
QString uniqueDeviceID() const;
- IosDevice(const QString &uid);
QString osVersion() const;
Utils::Port nextPort() const;
bool canAutoDetectPorts() const override;
@@ -73,13 +68,24 @@ protected:
friend class IosDeviceFactory;
friend class Ios::Internal::IosDeviceManager;
IosDevice();
- IosDevice(const IosDevice &other);
+ IosDevice(const QString &uid);
+
Dict m_extraInfo;
bool m_ignoreDevice = false;
mutable quint16 m_lastPort;
};
-class IosDeviceManager : public QObject {
+class IosDeviceFactory : public ProjectExplorer::IDeviceFactory
+{
+ Q_OBJECT
+public:
+ IosDeviceFactory();
+
+ bool canRestore(const QVariantMap &map) const override;
+};
+
+class IosDeviceManager : public QObject
+{
Q_OBJECT
public:
using TranslationMap = QHash<QString, QString>;
@@ -103,10 +109,5 @@ private:
QStringList m_userModeDeviceIds;
};
-namespace IosKitInformation {
-IosDevice::ConstPtr device(ProjectExplorer::Kit *);
-}
-
} // namespace Internal
-
} // namespace Ios
diff --git a/src/plugins/ios/iosdevicefactory.cpp b/src/plugins/ios/iosdevicefactory.cpp
deleted file mode 100644
index 6370cbce40..0000000000
--- a/src/plugins/ios/iosdevicefactory.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 "iosdevicefactory.h"
-#include "iosdevice.h"
-
-#include "iosconstants.h"
-
-namespace Ios {
-namespace Internal {
-
-IosDeviceFactory::IosDeviceFactory()
- : ProjectExplorer::IDeviceFactory(Constants::IOS_DEVICE_ID)
-{
- setObjectName(QLatin1String("IosDeviceFactory"));
- setDisplayName(IosDevice::name());
- setCombinedIcon(":/ios/images/iosdevicesmall.png",
- ":/ios/images/iosdevice.png");
- setConstructionFunction([] { return ProjectExplorer::IDevice::Ptr(new IosDevice); });
-}
-
-bool IosDeviceFactory::canRestore(const QVariantMap &map) const
-{
- QVariantMap vMap = map.value(QLatin1String(Constants::EXTRA_INFO_KEY)).toMap();
- if (vMap.isEmpty()
- || vMap.value(QLatin1String("deviceName")).toString() == QLatin1String("*unknown*"))
- return false; // transient device (probably generated during an activation)
- return true;
-}
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iosdevicefactory.h b/src/plugins/ios/iosdevicefactory.h
deleted file mode 100644
index cdf3d61ffd..0000000000
--- a/src/plugins/ios/iosdevicefactory.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 <projectexplorer/devicesupport/idevicefactory.h>
-
-namespace Ios {
-namespace Internal {
-
-class IosDeviceFactory : public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-public:
- IosDeviceFactory();
-
- bool canRestore(const QVariantMap &map) const override;
-};
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iosdsymbuildstep.cpp b/src/plugins/ios/iosdsymbuildstep.cpp
index c8b550352c..d238bcfb95 100644
--- a/src/plugins/ios/iosdsymbuildstep.cpp
+++ b/src/plugins/ios/iosdsymbuildstep.cpp
@@ -68,11 +68,11 @@ bool IosDsymBuildStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
- pp->setWorkingDirectory(bc->buildDirectory().toString());
+ pp->setWorkingDirectory(bc->buildDirectory());
Utils::Environment env = bc->environment();
Utils::Environment::setupEnglishOutput(&env);
pp->setEnvironment(env);
- pp->setCommand(command());
+ pp->setCommand(Utils::FilePath::fromString(command()));
pp->setArguments(Utils::QtcProcess::joinArgs(arguments()));
pp->resolveAll();
@@ -146,8 +146,8 @@ QStringList IosDsymBuildStep::defaultCleanCmdList() const
QStringList IosDsymBuildStep::defaultCmdList() const
{
QString dsymutilCmd = "dsymutil";
- Utils::FileName dsymUtilPath = IosConfigurations::developerPath()
- .appendPath("Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil");
+ const Utils::FilePath dsymUtilPath = IosConfigurations::developerPath()
+ .pathAppended("Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil");
if (dsymUtilPath.exists())
dsymutilCmd = dsymUtilPath.toUserOutput();
auto runConf = qobject_cast<const IosRunConfiguration *>(target()->activeRunConfiguration());
@@ -268,9 +268,9 @@ void IosDsymBuildStepConfigWidget::updateDetails()
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
- param.setWorkingDirectory(bc->buildDirectory().toString());
+ param.setWorkingDirectory(bc->buildDirectory());
param.setEnvironment(bc->environment());
- param.setCommand(m_buildStep->command());
+ param.setCommand(Utils::FilePath::fromString(m_buildStep->command()));
param.setArguments(Utils::QtcProcess::joinArgs(m_buildStep->arguments()));
setSummaryText(param.summary(displayName()));
diff --git a/src/plugins/ios/iosplugin.cpp b/src/plugins/ios/iosplugin.cpp
index 401b2a050c..080f9dcde7 100644
--- a/src/plugins/ios/iosplugin.cpp
+++ b/src/plugins/ios/iosplugin.cpp
@@ -30,13 +30,12 @@
#include "iosconfigurations.h"
#include "iosconstants.h"
#include "iosdeploystep.h"
-#include "iosdevicefactory.h"
+#include "iosdevice.h"
#include "iosdsymbuildstep.h"
-#include "iosqtversionfactory.h"
+#include "iosqtversion.h"
#include "iosrunner.h"
#include "iossettingspage.h"
#include "iossimulator.h"
-#include "iossimulatorfactory.h"
#include "iostoolhandler.h"
#include "iosrunconfiguration.h"
@@ -95,6 +94,13 @@ public:
IosDeployStepFactory deployStepFactory;
IosDsymBuildStepFactory dsymBuildStepFactory;
IosDeployConfigurationFactory deployConfigurationFactory;
+
+ SimpleRunWorkerFactory<Internal::IosRunSupport, IosRunConfiguration>
+ runWorkerFactory{ProjectExplorer::Constants::NORMAL_RUN_MODE};
+ SimpleRunWorkerFactory<Internal::IosDebugSupport, IosRunConfiguration>
+ debugWorkerFactory{ProjectExplorer::Constants::DEBUG_RUN_MODE};
+ SimpleRunWorkerFactory<Internal::IosQmlProfilerSupport, IosRunConfiguration>
+ qmlProfilerWorkerFactory{ProjectExplorer::Constants::QML_PROFILER_RUN_MODE};
};
IosPlugin::~IosPlugin()
@@ -113,17 +119,6 @@ bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage)
d = new IosPluginPrivate;
- auto constraint = [](RunConfiguration *runConfig) {
- return qobject_cast<IosRunConfiguration *>(runConfig) != nullptr;
- };
-
- RunControl::registerWorker<Internal::IosRunSupport>
- (ProjectExplorer::Constants::NORMAL_RUN_MODE, constraint);
- RunControl::registerWorker<Internal::IosDebugSupport>
- (ProjectExplorer::Constants::DEBUG_RUN_MODE, constraint);
- RunControl::registerWorker<Internal::IosQmlProfilerSupport>
- (ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, constraint);
-
return true;
}
diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp
index 35bcaff544..8e19eecc4f 100644
--- a/src/plugins/ios/iosprobe.cpp
+++ b/src/plugins/ios/iosprobe.cpp
@@ -87,15 +87,15 @@ void XcodeProbe::setupDefaultToolchains(const QString &devPath)
};
XcodePlatform clangProfile;
- clangProfile.developerPath = Utils::FileName::fromString(devPath);
+ clangProfile.developerPath = Utils::FilePath::fromString(devPath);
const QFileInfo clangCInfo = getClangInfo("clang");
if (clangCInfo.exists())
- clangProfile.cCompilerPath = Utils::FileName(clangCInfo);
+ clangProfile.cCompilerPath = Utils::FilePath::fromFileInfo(clangCInfo);
const QFileInfo clangCppInfo = getClangInfo("clang++");
if (clangCppInfo.exists())
- clangProfile.cxxCompilerPath = Utils::FileName(clangCppInfo);
+ clangProfile.cxxCompilerPath = Utils::FilePath::fromFileInfo(clangCppInfo);
QSet<QString> allArchitectures;
static const std::map<QString, QStringList> sdkConfigs {
@@ -111,7 +111,7 @@ void XcodeProbe::setupDefaultToolchains(const QString &devPath)
for (const auto &sdkConfig : sdkConfigs) {
XcodePlatform::SDK sdk;
sdk.directoryName = sdkConfig.first;
- sdk.path = Utils::FileName::fromString(devPath
+ sdk.path = Utils::FilePath::fromString(devPath
+ QString(QLatin1String("/Platforms/%1.platform/Developer/SDKs/%1.sdk")).arg(
sdk.directoryName));
sdk.architectures = sdkConfig.second;
diff --git a/src/plugins/ios/iosprobe.h b/src/plugins/ios/iosprobe.h
index ccaddcc5cc..52cf3015c5 100644
--- a/src/plugins/ios/iosprobe.h
+++ b/src/plugins/ios/iosprobe.h
@@ -39,7 +39,7 @@ public:
{
public:
QString directoryName;
- Utils::FileName path;
+ Utils::FilePath path;
QStringList architectures;
};
class ToolchainTarget
@@ -51,9 +51,9 @@ public:
bool operator==(const ToolchainTarget &other) const;
};
- Utils::FileName developerPath;
- Utils::FileName cxxCompilerPath;
- Utils::FileName cCompilerPath;
+ Utils::FilePath developerPath;
+ Utils::FilePath cxxCompilerPath;
+ Utils::FilePath cCompilerPath;
std::vector<ToolchainTarget> targets;
std::vector<SDK> sdks;
@@ -67,7 +67,7 @@ uint qHash(const XcodePlatform::ToolchainTarget &target);
class XcodeProbe
{
public:
- static Utils::FileName sdkPath(const QString &devPath, const QString &platformName);
+ static Utils::FilePath sdkPath(const QString &devPath, const QString &platformName);
static QMap<QString, XcodePlatform> detectPlatforms(const QString &devPath = QString());
private:
diff --git a/src/plugins/ios/iosqtversion.cpp b/src/plugins/ios/iosqtversion.cpp
index 7b83b6b5ea..e508c53cfe 100644
--- a/src/plugins/ios/iosqtversion.cpp
+++ b/src/plugins/ios/iosqtversion.cpp
@@ -42,23 +42,6 @@ using namespace ProjectExplorer;
IosQtVersion::IosQtVersion() = default;
-IosQtVersion::IosQtVersion(const Utils::FileName &path, bool isAutodetected,
- const QString &autodetectionSource)
- : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource)
-{
- setUnexpandedDisplayName(defaultUnexpandedDisplayName(path, false));
-}
-
-IosQtVersion *IosQtVersion::clone() const
-{
- return new IosQtVersion(*this);
-}
-
-QString IosQtVersion::type() const
-{
- return QLatin1String(Constants::IOSQT);
-}
-
bool IosQtVersion::isValid() const
{
if (!BaseQtVersion::isValid())
@@ -76,9 +59,9 @@ QString IosQtVersion::invalidReason() const
return tmp;
}
-QList<Abi> IosQtVersion::detectQtAbis() const
+Abis IosQtVersion::detectQtAbis() const
{
- QList<Abi> abis = qtAbisFromLibrary(qtCorePaths());
+ Abis abis = BaseQtVersion::detectQtAbis();
for (int i = 0; i < abis.count(); ++i) {
abis[i] = Abi(abis.at(i).architecture(),
abis.at(i).os(),
@@ -115,3 +98,16 @@ QSet<Core::Id> IosQtVersion::targetDeviceTypes() const
// iOS Qt version supports ios devices as well as simulator.
return {Constants::IOS_DEVICE_TYPE, Constants::IOS_SIMULATOR_TYPE};
}
+
+
+// Factory
+
+IosQtVersionFactory::IosQtVersionFactory()
+{
+ setQtVersionCreator([] { return new IosQtVersion; });
+ setSupportedType(Constants::IOSQT);
+ setPriority(90);
+ setRestrictionChecker([](const SetupData &setup) {
+ return setup.platforms.contains("ios");
+ });
+}
diff --git a/src/plugins/ios/iosqtversion.h b/src/plugins/ios/iosqtversion.h
index 6d4a093ba5..fa119d2f6f 100644
--- a/src/plugins/ios/iosqtversion.h
+++ b/src/plugins/ios/iosqtversion.h
@@ -26,6 +26,7 @@
#pragma once
#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtversionfactory.h>
#include <QCoreApplication>
@@ -38,15 +39,11 @@ class IosQtVersion : public QtSupport::BaseQtVersion
public:
IosQtVersion();
- IosQtVersion(const Utils::FileName &path, bool isAutodetected = false,
- const QString &autodetectionSource = QString());
- IosQtVersion *clone() const override;
- QString type() const override;
bool isValid() const override;
QString invalidReason() const override;
- QList<ProjectExplorer::Abi> detectQtAbis() const override;
+ ProjectExplorer::Abis detectQtAbis() const override;
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const override;
@@ -56,5 +53,11 @@ public:
QString description() const override;
};
+class IosQtVersionFactory : public QtSupport::QtVersionFactory
+{
+public:
+ IosQtVersionFactory();
+};
+
} // namespace Internal
} // namespace Ios
diff --git a/src/plugins/ios/iosqtversionfactory.cpp b/src/plugins/ios/iosqtversionfactory.cpp
deleted file mode 100644
index 4ef21af112..0000000000
--- a/src/plugins/ios/iosqtversionfactory.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 "iosqtversionfactory.h"
-#include "iosqtversion.h"
-#include "iosconstants.h"
-#include <qtsupport/qtsupportconstants.h>
-#include <utils/qtcassert.h>
-#include <proparser/profileevaluator.h>
-
-#include <QFileInfo>
-
-namespace Ios {
-namespace Internal {
-
-IosQtVersionFactory::IosQtVersionFactory(QObject *parent)
- : QtSupport::QtVersionFactory(parent)
-{
-}
-
-bool IosQtVersionFactory::canRestore(const QString &type)
-{
- return type == QLatin1String(Constants::IOSQT);
-}
-
-QtSupport::BaseQtVersion *IosQtVersionFactory::restore(const QString &type,
- const QVariantMap &data)
-{
- QTC_ASSERT(canRestore(type), return nullptr);
- auto v = new IosQtVersion;
- v->fromMap(data);
- return v;
-}
-
-int IosQtVersionFactory::priority() const
-{
- return 90;
-}
-
-QtSupport::BaseQtVersion *IosQtVersionFactory::create(const Utils::FileName &qmakePath,
- ProFileEvaluator *evaluator,
- bool isAutoDetected,
- const QString &autoDetectionSource)
-{
- if (!(evaluator->values(QLatin1String("QMAKE_PLATFORM")).contains(QLatin1String("ios"))))
- return nullptr;
- return new IosQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
-}
-
-} // Internal
-} // Ios
diff --git a/src/plugins/ios/iosqtversionfactory.h b/src/plugins/ios/iosqtversionfactory.h
deleted file mode 100644
index 4810e2ee8e..0000000000
--- a/src/plugins/ios/iosqtversionfactory.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/qtversionfactory.h>
-
-namespace Ios {
-namespace Internal {
-
-class IosQtVersionFactory : public QtSupport::QtVersionFactory
-{
-public:
- explicit IosQtVersionFactory(QObject *parent = nullptr);
-
- bool canRestore(const QString &type) override;
- QtSupport::BaseQtVersion *restore(const QString &type, const QVariantMap &data) override;
-
- int priority() const override;
- QtSupport::BaseQtVersion *create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator,
- bool isAutoDetected = false,
- const QString &autoDetectionSource = QString()) override;
-};
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp
index 0d26ba7e8f..db732fe953 100644
--- a/src/plugins/ios/iosrunconfiguration.cpp
+++ b/src/plugins/ios/iosrunconfiguration.cpp
@@ -34,13 +34,11 @@
#include <projectexplorer/deployconfiguration.h>
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectnodes.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h>
-#include <qmakeprojectmanager/qmakenodes.h>
-#include <qmakeprojectmanager/qmakeproject.h>
-#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
-
#include <qtsupport/qtoutputformatter.h>
#include <qtsupport/qtkitinformation.h>
@@ -62,7 +60,6 @@
#include <QWidget>
using namespace ProjectExplorer;
-using namespace QmakeProjectManager;
using namespace Utils;
namespace Ios {
@@ -125,7 +122,7 @@ void IosDeviceTypeAspect::deviceChanges()
void IosDeviceTypeAspect::updateDeviceType()
{
- if (DeviceTypeKitInformation::deviceTypeId(m_runConfiguration->target()->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(m_runConfiguration->target()->kit())
== Constants::IOS_DEVICE_TYPE)
m_deviceType = IosDeviceType(IosDeviceType::IosDevice);
else if (m_deviceType.type == IosDeviceType::IosDevice)
@@ -134,7 +131,7 @@ void IosDeviceTypeAspect::updateDeviceType()
void IosRunConfiguration::updateDisplayNames()
{
- IDevice::ConstPtr dev = DeviceKitInformation::device(target()->kit());
+ IDevice::ConstPtr dev = DeviceKitAspect::device(target()->kit());
const QString devName = dev.isNull() ? IosDevice::name() : dev->displayName();
setDefaultDisplayName(tr("Run on %1").arg(devName));
setDisplayName(tr("Run %1 on %2").arg(applicationName()).arg(devName));
@@ -144,12 +141,12 @@ void IosRunConfiguration::updateDisplayNames()
void IosRunConfiguration::updateEnabledState()
{
- Core::Id devType = DeviceTypeKitInformation::deviceTypeId(target()->kit());
+ Core::Id devType = DeviceTypeKitAspect::deviceTypeId(target()->kit());
if (devType != Constants::IOS_DEVICE_TYPE && devType != Constants::IOS_SIMULATOR_TYPE) {
setEnabled(false);
return;
}
- IDevice::ConstPtr dev = DeviceKitInformation::device(target()->kit());
+ IDevice::ConstPtr dev = DeviceKitAspect::device(target()->kit());
if (dev.isNull() || dev->deviceState() != IDevice::DeviceReadyToUse) {
setEnabled(false);
return;
@@ -157,68 +154,56 @@ void IosRunConfiguration::updateEnabledState()
return RunConfiguration::updateEnabledState();
}
-bool IosRunConfiguration::canRunForNode(const Node *node) const
-{
- return node->filePath().toString() == buildKey();
-}
-
QString IosRunConfiguration::applicationName() const
{
Project *project = target()->project();
- if (auto pro = dynamic_cast<const QmakeProFileNode *>(project->findNodeForBuildKey(buildKey()))) {
- TargetInformation ti = pro->targetInformation();
- if (ti.valid)
- return ti.target;
- }
+ if (ProjectNode *node = project->findNodeForBuildKey(buildKey()))
+ return node->data(Constants::IosTarget).toString();
+
return QString();
}
-FileName IosRunConfiguration::bundleDirectory() const
+FilePath IosRunConfiguration::bundleDirectory() const
{
- FileName res;
- Core::Id devType = DeviceTypeKitInformation::deviceTypeId(target()->kit());
+ Core::Id devType = DeviceTypeKitAspect::deviceTypeId(target()->kit());
bool isDevice = (devType == Constants::IOS_DEVICE_TYPE);
if (!isDevice && devType != Constants::IOS_SIMULATOR_TYPE) {
qCWarning(iosLog) << "unexpected device type in bundleDirForTarget: " << devType.toString();
- return res;
+ return {};
}
+ FilePath res;
if (BuildConfiguration *bc = target()->activeBuildConfiguration()) {
Project *project = target()->project();
- auto pro = dynamic_cast<const QmakeProFileNode *>(project->findNodeForBuildKey(buildKey()));
- if (pro) {
- TargetInformation ti = pro->targetInformation();
- if (ti.valid)
- res = ti.buildDir;
- }
+ if (ProjectNode *node = project->findNodeForBuildKey(buildKey()))
+ res = FilePath::fromString(node->data(Constants::IosBuildDir).toString());
if (res.isEmpty())
res = bc->buildDirectory();
switch (bc->buildType()) {
case BuildConfiguration::Debug :
case BuildConfiguration::Unknown :
if (isDevice)
- res.appendPath(QLatin1String("Debug-iphoneos"));
+ res = res.pathAppended("Debug-iphoneos");
else
- res.appendPath(QLatin1String("Debug-iphonesimulator"));
+ res = res.pathAppended("Debug-iphonesimulator");
break;
case BuildConfiguration::Profile :
case BuildConfiguration::Release :
if (isDevice)
- res.appendPath(QLatin1String("Release-iphoneos"));
+ res = res.pathAppended("Release-iphoneos");
else
- res.appendPath(QLatin1String("Release-iphonesimulator"));
+ res = res.pathAppended("Release-iphonesimulator");
break;
default:
qCWarning(iosLog) << "IosBuildStep had an unknown buildType "
<< target()->activeBuildConfiguration()->buildType();
}
}
- res.appendPath(applicationName() + QLatin1String(".app"));
- return res;
+ return res.pathAppended(applicationName() + ".app");
}
-FileName IosRunConfiguration::localExecutable() const
+FilePath IosRunConfiguration::localExecutable() const
{
- return bundleDirectory().appendPath(applicationName());
+ return bundleDirectory().pathAppended(applicationName());
}
void IosDeviceTypeAspect::fromMap(const QVariantMap &map)
@@ -238,10 +223,10 @@ void IosDeviceTypeAspect::toMap(QVariantMap &map) const
QString IosRunConfiguration::disabledReason() const
{
- Core::Id devType = DeviceTypeKitInformation::deviceTypeId(target()->kit());
+ Core::Id devType = DeviceTypeKitAspect::deviceTypeId(target()->kit());
if (devType != Constants::IOS_DEVICE_TYPE && devType != Constants::IOS_SIMULATOR_TYPE)
return tr("Kit has incorrect device type for running on iOS devices.");
- IDevice::ConstPtr dev = DeviceKitInformation::device(target()->kit());
+ IDevice::ConstPtr dev = DeviceKitAspect::device(target()->kit());
QString validDevName;
bool hasConncetedDev = false;
if (devType == Constants::IOS_DEVICE_TYPE) {
@@ -347,7 +332,7 @@ void IosDeviceTypeAspect::addToConfigurationLayout(QFormLayout *layout)
updateValues();
- connect(m_deviceTypeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_deviceTypeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &IosDeviceTypeAspect::setDeviceTypeIndex);
}
@@ -405,7 +390,6 @@ IosRunConfigurationFactory::IosRunConfigurationFactory()
registerRunConfiguration<IosRunConfiguration>("Qt4ProjectManager.IosRunConfiguration:");
addSupportedTargetDeviceType(Constants::IOS_DEVICE_TYPE);
addSupportedTargetDeviceType(Constants::IOS_SIMULATOR_TYPE);
- addSupportedProjectType(QmakeProjectManager::Constants::QMAKEPROJECT_ID);
}
} // namespace Internal
diff --git a/src/plugins/ios/iosrunconfiguration.h b/src/plugins/ios/iosrunconfiguration.h
index 72d30b0227..a5072abddf 100644
--- a/src/plugins/ios/iosrunconfiguration.h
+++ b/src/plugins/ios/iosrunconfiguration.h
@@ -44,10 +44,10 @@ class IosRunConfiguration : public ProjectExplorer::RunConfiguration
public:
IosRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
- Utils::FileName profilePath() const;
+ Utils::FilePath profilePath() const;
QString applicationName() const;
- Utils::FileName bundleDirectory() const;
- Utils::FileName localExecutable() const;
+ Utils::FilePath bundleDirectory() const;
+ Utils::FilePath localExecutable() const;
QString disabledReason() const override;
IosDeviceType deviceType() const;
@@ -57,7 +57,6 @@ private:
friend class IosDeviceTypeAspect;
void updateDisplayNames();
void updateEnabledState() final;
- bool canRunForNode(const ProjectExplorer::Node *node) const final;
IosDeviceTypeAspect *m_deviceTypeAspect = nullptr;
};
diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp
index dc6d222e0f..5c34309921 100644
--- a/src/plugins/ios/iosrunner.cpp
+++ b/src/plugins/ios/iosrunner.cpp
@@ -79,9 +79,8 @@ static void stopRunningRunControl(RunControl *runControl)
{
static QMap<Core::Id, QPointer<RunControl>> activeRunControls;
- RunConfiguration *runConfig = runControl->runConfiguration();
- Target *target = runConfig->target();
- Core::Id devId = DeviceKitInformation::deviceId(target->kit());
+ Target *target = runControl->target();
+ Core::Id devId = DeviceKitAspect::deviceId(target->kit());
// The device can only run an application at a time, if an app is running stop it.
if (activeRunControls.contains(devId)) {
@@ -100,8 +99,8 @@ IosRunner::IosRunner(RunControl *runControl)
stopRunningRunControl(runControl);
auto runConfig = qobject_cast<IosRunConfiguration *>(runControl->runConfiguration());
m_bundleDir = runConfig->bundleDirectory().toString();
- m_arguments = runConfig->aspect<ArgumentsAspect>()->arguments(runConfig->macroExpander());
- m_device = DeviceKitInformation::device(runConfig->target()->kit());
+ m_arguments = runControl->aspect<ArgumentsAspect>()->arguments(runConfig->macroExpander());
+ m_device = DeviceKitAspect::device(runControl->target()->kit());
m_deviceType = runConfig->deviceType();
}
@@ -387,7 +386,7 @@ IosQmlProfilerSupport::IosQmlProfilerSupport(RunControl *runControl)
Runnable runnable;
runnable.executable = iosRunConfig->localExecutable().toUserOutput();
runnable.commandLineArguments =
- iosRunConfig->aspect<ArgumentsAspect>()->arguments(iosRunConfig->macroExpander());
+ runControl->aspect<ArgumentsAspect>()->arguments(iosRunConfig->macroExpander());
runControl->setDisplayName(iosRunConfig->applicationName());
runControl->setRunnable(runnable);
@@ -438,23 +437,21 @@ void IosDebugSupport::start()
return;
}
- RunConfiguration *runConfig = runControl()->runConfiguration();
-
if (device()->type() == Ios::Constants::IOS_DEVICE_TYPE) {
IosDevice::ConstPtr dev = device().dynamicCast<const IosDevice>();
setStartMode(AttachToRemoteProcess);
setIosPlatform("remote-ios");
QString osVersion = dev->osVersion();
- FileName deviceSdk1 = FileName::fromString(QDir::homePath()
+ FilePath deviceSdk1 = FilePath::fromString(QDir::homePath()
+ "/Library/Developer/Xcode/iOS DeviceSupport/"
+ osVersion + "/Symbols");
QString deviceSdk;
if (deviceSdk1.toFileInfo().isDir()) {
deviceSdk = deviceSdk1.toString();
} else {
- FileName deviceSdk2 = IosConfigurations::developerPath()
- .appendPath("Platforms/iPhoneOS.platform/DeviceSupport/")
- .appendPath(osVersion).appendPath("Symbols");
+ const FilePath deviceSdk2 = IosConfigurations::developerPath()
+ .pathAppended("Platforms/iPhoneOS.platform/DeviceSupport/"
+ + osVersion + "/Symbols");
if (deviceSdk2.toFileInfo().isDir()) {
deviceSdk = deviceSdk2.toString();
} else {
@@ -472,7 +469,7 @@ void IosDebugSupport::start()
setIosPlatform("ios-simulator");
}
- auto iosRunConfig = qobject_cast<IosRunConfiguration *>(runConfig);
+ auto iosRunConfig = qobject_cast<IosRunConfiguration *>(runControl()->runConfiguration());
setRunControlName(iosRunConfig->applicationName());
setContinueAfterAttach(true);
@@ -488,7 +485,7 @@ void IosDebugSupport::start()
QString bundlePath = iosRunConfig->bundleDirectory().toString();
bundlePath.chop(4);
- FileName dsymPath = FileName::fromString(bundlePath.append(".dSYM"));
+ FilePath dsymPath = FilePath::fromString(bundlePath.append(".dSYM"));
if (dsymPath.exists() && dsymPath.toFileInfo().lastModified()
< QFileInfo(iosRunConfig->localExecutable().toUserOutput()).lastModified()) {
TaskHub::addTask(Task::Warning,
diff --git a/src/plugins/ios/iossettingswidget.cpp b/src/plugins/ios/iossettingswidget.cpp
index 4f7cd37f58..467ded471d 100644
--- a/src/plugins/ios/iossettingswidget.cpp
+++ b/src/plugins/ios/iossettingswidget.cpp
@@ -275,7 +275,7 @@ void IosSettingsWidget::onScreenshot()
const auto generatePath = [this](const SimulatorInfo &info) {
const QString fileName = QString("%1_%2_%3.png").arg(info.name).arg(info.runtimeName)
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss-z")).replace(' ', '_');
- return m_ui->pathWidget->fileName().appendPath(fileName).toString();
+ return m_ui->pathWidget->fileName().pathAppended(fileName).toString();
};
QPointer<SimulatorOperationDialog> statusDialog = new SimulatorOperationDialog(this);
diff --git a/src/plugins/ios/iossimulator.cpp b/src/plugins/ios/iossimulator.cpp
index 6a8ad80735..2312a5b10c 100644
--- a/src/plugins/ios/iossimulator.cpp
+++ b/src/plugins/ios/iossimulator.cpp
@@ -64,14 +64,6 @@ IosSimulator::IosSimulator()
setDeviceState(DeviceReadyToUse);
}
-IosSimulator::IosSimulator(const IosSimulator &other)
- : IDevice(other), m_lastPort(other.m_lastPort)
-{
- setDisplayName(QCoreApplication::translate("Ios::Internal::IosSimulator", "iOS Simulator"));
- setDeviceState(DeviceReadyToUse);
-}
-
-
IDevice::DeviceInfo IosSimulator::deviceInformation() const
{
return IDevice::DeviceInfo();
@@ -92,22 +84,6 @@ DeviceProcessSignalOperation::Ptr IosSimulator::signalOperation() const
return DeviceProcessSignalOperation::Ptr();
}
-IDevice::Ptr IosSimulator::clone() const
-{
- return IDevice::Ptr(new IosSimulator(*this));
-}
-
-void IosSimulator::fromMap(const QVariantMap &map)
-{
- IDevice::fromMap(map);
-}
-
-QVariantMap IosSimulator::toMap() const
-{
- QVariantMap res = IDevice::toMap();
- return res;
-}
-
Utils::Port IosSimulator::nextPort() const
{
for (int i = 0; i < 100; ++i) {
@@ -140,14 +116,7 @@ Utils::OsType IosSimulator::osType() const
return Utils::OsTypeMac;
}
-IosSimulator::ConstPtr IosKitInformation::simulator(Kit *kit)
-{
- if (!kit)
- return IosSimulator::ConstPtr();
- IDevice::ConstPtr dev = DeviceKitInformation::device(kit);
- IosSimulator::ConstPtr res = dev.dynamicCast<const IosSimulator>();
- return res;
-}
+// IosDeviceType
IosDeviceType::IosDeviceType(IosDeviceType::Type type, const QString &identifier, const QString &displayName) :
type(type), identifier(identifier), displayName(displayName)
@@ -281,5 +250,17 @@ QDebug operator <<(QDebug debug, const IosDeviceType &deviceType)
return debug;
}
+// Factory
+
+IosSimulatorFactory::IosSimulatorFactory()
+ : ProjectExplorer::IDeviceFactory(Constants::IOS_SIMULATOR_TYPE)
+{
+ setObjectName(QLatin1String("IosSimulatorFactory"));
+ setDisplayName(tr("iOS Simulator"));
+ setCombinedIcon(":/ios/images/iosdevicesmall.png",
+ ":/ios/images/iosdevice.png");
+ setConstructionFunction([] { return ProjectExplorer::IDevice::Ptr(new IosSimulator()); });
+}
+
} // namespace Internal
} // namespace Ios
diff --git a/src/plugins/ios/iossimulator.h b/src/plugins/ios/iossimulator.h
index d4652dfe4b..c2a390a5fe 100644
--- a/src/plugins/ios/iossimulator.h
+++ b/src/plugins/ios/iossimulator.h
@@ -26,19 +26,20 @@
#pragma once
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefactory.h>
+
#include <utils/fileutils.h>
-#include <QMutex>
#include <QDebug>
-#include <QSharedPointer>
-namespace ProjectExplorer { class Kit; }
namespace Ios {
namespace Internal {
+
class IosConfigurations;
class IosSimulatorFactory;
-class IosDeviceType {
+class IosDeviceType
+{
public:
enum Type {
IosDevice,
@@ -58,6 +59,7 @@ public:
QString identifier;
QString displayName;
};
+
QDebug operator <<(QDebug debug, const IosDeviceType &deviceType);
class IosSimulator : public ProjectExplorer::IDevice
@@ -70,26 +72,27 @@ public:
QString displayType() const override;
ProjectExplorer::IDeviceWidget *createWidget() override;
ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override;
- void fromMap(const QVariantMap &map) override;
- QVariantMap toMap() const override;
Utils::Port nextPort() const;
bool canAutoDetectPorts() const override;
Utils::OsType osType() const override;
- ProjectExplorer::IDevice::Ptr clone() const override;
protected:
friend class IosSimulatorFactory;
friend class IosConfigurations;
IosSimulator();
IosSimulator(Core::Id id);
- IosSimulator(const IosSimulator &other);
+
private:
mutable quint16 m_lastPort;
};
-namespace IosKitInformation {
-IosSimulator::ConstPtr simulator(ProjectExplorer::Kit *kit);
-} // namespace IosKitInformation
+class IosSimulatorFactory : public ProjectExplorer::IDeviceFactory
+{
+ Q_OBJECT
+public:
+ IosSimulatorFactory();
+};
+
} // namespace Internal
} // namespace Ios
diff --git a/src/plugins/ios/iossimulatorfactory.cpp b/src/plugins/ios/iossimulatorfactory.cpp
deleted file mode 100644
index 163bfac1b4..0000000000
--- a/src/plugins/ios/iossimulatorfactory.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 "iossimulatorfactory.h"
-
-#include "iosconstants.h"
-#include "iossimulator.h"
-
-#include <utils/qtcassert.h>
-
-namespace Ios {
-namespace Internal {
-
-IosSimulatorFactory::IosSimulatorFactory()
- : ProjectExplorer::IDeviceFactory(Constants::IOS_SIMULATOR_TYPE)
-{
- setObjectName(QLatin1String("IosSimulatorFactory"));
- setDisplayName(tr("iOS Simulator"));
- setCombinedIcon(":/ios/images/iosdevicesmall.png",
- ":/ios/images/iosdevice.png");
- setConstructionFunction([] { return ProjectExplorer::IDevice::Ptr(new IosSimulator()); });
-}
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iossimulatorfactory.h b/src/plugins/ios/iossimulatorfactory.h
deleted file mode 100644
index 5d05c7b370..0000000000
--- a/src/plugins/ios/iossimulatorfactory.h
+++ /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.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/devicesupport/idevicefactory.h>
-
-namespace Ios {
-namespace Internal {
-
-class IosSimulatorFactory : public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-public:
- IosSimulatorFactory();
-};
-
-} // namespace Internal
-} // namespace Ios
diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp
index 2526ecfdc3..646183db05 100644
--- a/src/plugins/ios/iostoolhandler.cpp
+++ b/src/plugins/ios/iostoolhandler.cpp
@@ -657,18 +657,14 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de
if (k.startsWith(QLatin1String("DYLD_")))
env.remove(k);
QStringList frameworkPaths;
- Utils::FileName xcPath = IosConfigurations::developerPath();
- QString privateFPath = xcPath.appendPath(QLatin1String("Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks")).toFileInfo().canonicalFilePath();
- if (!privateFPath.isEmpty())
- frameworkPaths << privateFPath;
- QString otherFPath = xcPath.appendPath(QLatin1String("../OtherFrameworks")).toFileInfo().canonicalFilePath();
- if (!otherFPath.isEmpty())
- frameworkPaths << otherFPath;
- QString sharedFPath = xcPath.appendPath(QLatin1String("../SharedFrameworks")).toFileInfo().canonicalFilePath();
- if (!sharedFPath.isEmpty())
- frameworkPaths << sharedFPath;
- frameworkPaths << QLatin1String("/System/Library/Frameworks")
- << QLatin1String("/System/Library/PrivateFrameworks");
+ const Utils::FilePath libPath = IosConfigurations::developerPath().pathAppended("Platforms/iPhoneSimulator.platform/Developer/Library");
+ for (const auto framework : {"PrivateFrameworks", "OtherFrameworks", "SharedFrameworks"}) {
+ const QString frameworkPath =
+ libPath.pathAppended(QLatin1String(framework)).toFileInfo().canonicalFilePath();
+ if (!frameworkPath.isEmpty())
+ frameworkPaths << frameworkPath;
+ }
+ frameworkPaths << "/System/Library/Frameworks" << "/System/Library/PrivateFrameworks";
env.insert(QLatin1String("DYLD_FALLBACK_FRAMEWORK_PATH"), frameworkPaths.join(QLatin1Char(':')));
qCDebug(toolHandlerLog) << "IosToolHandler runEnv:" << env.toStringList();
process->setProcessEnvironment(env);
@@ -676,7 +672,7 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de
QObject::connect(process.get(), &QProcess::readyReadStandardOutput,
std::bind(&IosDeviceToolHandlerPrivate::subprocessHasData,this));
- QObject::connect(process.get(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ QObject::connect(process.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
std::bind(&IosDeviceToolHandlerPrivate::subprocessFinished,this, _1,_2));
QObject::connect(process.get(), &QProcess::errorOccurred,
@@ -857,7 +853,7 @@ void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &appBundlePath,
m_deviceId = m_devType.identifier;
m_runKind = runType;
- Utils::FileName appBundle = Utils::FileName::fromString(m_bundlePath);
+ Utils::FilePath appBundle = Utils::FilePath::fromString(m_bundlePath);
if (!appBundle.exists()) {
errorMsg(IosToolHandler::tr("Application launch on simulator failed. Invalid bundle path %1")
.arg(m_bundlePath));
@@ -931,13 +927,13 @@ void IosSimulatorToolHandlerPrivate::installAppOnSimulator()
};
isTransferringApp(m_bundlePath, m_deviceId, 20, 100, "");
- auto installFuture = simCtl->installApp(m_deviceId, Utils::FileName::fromString(m_bundlePath));
+ auto installFuture = simCtl->installApp(m_deviceId, Utils::FilePath::fromString(m_bundlePath));
futureList << Utils::onResultReady(installFuture, onResponseAppInstall);
}
void IosSimulatorToolHandlerPrivate::launchAppOnSimulator(const QStringList &extraArgs)
{
- const Utils::FileName appBundle = Utils::FileName::fromString(m_bundlePath);
+ const Utils::FilePath appBundle = Utils::FilePath::fromString(m_bundlePath);
const QString bundleId = SimulatorControl::bundleIdentifier(appBundle);
const bool debugRun = m_runKind == IosToolHandler::DebugRun;
bool captureConsole = IosConfigurations::xcodeVersion() >= QVersionNumber(8);
diff --git a/src/plugins/ios/simulatorcontrol.cpp b/src/plugins/ios/simulatorcontrol.cpp
index cdf2a3da6a..baecf63a9c 100644
--- a/src/plugins/ios/simulatorcontrol.cpp
+++ b/src/plugins/ios/simulatorcontrol.cpp
@@ -96,7 +96,7 @@ static bool runSimCtlCommand(QStringList args, QString *output)
static bool launchSimulator(const QString &simUdid) {
QTC_ASSERT(!simUdid.isEmpty(), return false);
const QString simulatorAppPath = IosConfigurations::developerPath()
- .appendPath("Applications/Simulator.app/Contents/MacOS/Simulator").toString();
+ .pathAppended("Applications/Simulator.app/Contents/MacOS/Simulator").toString();
if (IosConfigurations::xcodeVersion() >= QVersionNumber(9)) {
// For XCode 9 boot the second device instead of launching simulator app twice.
@@ -172,12 +172,12 @@ private:
~SimulatorControlPrivate();
static SimulatorInfo deviceInfo(const QString &simUdid);
- static QString bundleIdentifier(const Utils::FileName &bundlePath);
- static QString bundleExecutable(const Utils::FileName &bundlePath);
+ static QString bundleIdentifier(const Utils::FilePath &bundlePath);
+ static QString bundleExecutable(const Utils::FilePath &bundlePath);
void startSimulator(QFutureInterface<SimulatorControl::ResponseData> &fi, const QString &simUdid);
void installApp(QFutureInterface<SimulatorControl::ResponseData> &fi, const QString &simUdid,
- const Utils::FileName &bundlePath);
+ const Utils::FilePath &bundlePath);
void launchApp(QFutureInterface<SimulatorControl::ResponseData> &fi, const QString &simUdid,
const QString &bundleIdentifier, bool waitForDebugger,
const QStringList &extraArgs, const QString &stdoutPath,
@@ -291,12 +291,12 @@ bool SimulatorControl::isSimulatorRunning(const QString &simUdid)
return SimulatorControlPrivate::deviceInfo(simUdid).isBooted();
}
-QString SimulatorControl::bundleIdentifier(const Utils::FileName &bundlePath)
+QString SimulatorControl::bundleIdentifier(const Utils::FilePath &bundlePath)
{
return SimulatorControlPrivate::bundleIdentifier(bundlePath);
}
-QString SimulatorControl::bundleExecutable(const Utils::FileName &bundlePath)
+QString SimulatorControl::bundleExecutable(const Utils::FilePath &bundlePath)
{
return SimulatorControlPrivate::bundleExecutable(bundlePath);
}
@@ -307,7 +307,7 @@ QFuture<SimulatorControl::ResponseData> SimulatorControl::startSimulator(const Q
}
QFuture<SimulatorControl::ResponseData>
-SimulatorControl::installApp(const QString &simUdid, const Utils::FileName &bundlePath) const
+SimulatorControl::installApp(const QString &simUdid, const Utils::FilePath &bundlePath) const
{
return Utils::runAsync(&SimulatorControlPrivate::installApp, d, simUdid, bundlePath);
}
@@ -372,7 +372,7 @@ SimulatorInfo SimulatorControlPrivate::deviceInfo(const QString &simUdid)
return device;
}
-QString SimulatorControlPrivate::bundleIdentifier(const Utils::FileName &bundlePath)
+QString SimulatorControlPrivate::bundleIdentifier(const Utils::FilePath &bundlePath)
{
QString bundleID;
#ifdef Q_OS_MAC
@@ -392,7 +392,7 @@ QString SimulatorControlPrivate::bundleIdentifier(const Utils::FileName &bundleP
return bundleID;
}
-QString SimulatorControlPrivate::bundleExecutable(const Utils::FileName &bundlePath)
+QString SimulatorControlPrivate::bundleExecutable(const Utils::FilePath &bundlePath)
{
QString executable;
#ifdef Q_OS_MAC
@@ -470,7 +470,7 @@ void SimulatorControlPrivate::startSimulator(QFutureInterface<SimulatorControl::
}
void SimulatorControlPrivate::installApp(QFutureInterface<SimulatorControl::ResponseData> &fi,
- const QString &simUdid, const Utils::FileName &bundlePath)
+ const QString &simUdid, const Utils::FilePath &bundlePath)
{
QTC_CHECK(bundlePath.exists());
diff --git a/src/plugins/ios/simulatorcontrol.h b/src/plugins/ios/simulatorcontrol.h
index c21469cd17..5d4351ae50 100644
--- a/src/plugins/ios/simulatorcontrol.h
+++ b/src/plugins/ios/simulatorcontrol.h
@@ -100,12 +100,12 @@ public:
static QList<SimulatorInfo> availableSimulators();
static QFuture<QList<SimulatorInfo> > updateAvailableSimulators();
static bool isSimulatorRunning(const QString &simUdid);
- static QString bundleIdentifier(const Utils::FileName &bundlePath);
- static QString bundleExecutable(const Utils::FileName &bundlePath);
+ static QString bundleIdentifier(const Utils::FilePath &bundlePath);
+ static QString bundleExecutable(const Utils::FilePath &bundlePath);
public:
QFuture<ResponseData> startSimulator(const QString &simUdid) const;
- QFuture<ResponseData> installApp(const QString &simUdid, const Utils::FileName &bundlePath) const;
+ QFuture<ResponseData> installApp(const QString &simUdid, const Utils::FilePath &bundlePath) const;
QFuture<ResponseData> launchApp(const QString &simUdid, const QString &bundleIdentifier,
bool waitForDebugger, const QStringList &extraArgs,
const QString& stdoutPath = QString(),
diff --git a/src/plugins/languageclient/CMakeLists.txt b/src/plugins/languageclient/CMakeLists.txt
new file mode 100644
index 0000000000..36040c1f5c
--- /dev/null
+++ b/src/plugins/languageclient/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_qtc_plugin(LanguageClient
+ DEPENDS LanguageServerProtocol Qt5::Core
+ PLUGIN_DEPENDS ProjectExplorer Core TextEditor
+ SOURCES
+ client.cpp client.h
+ documentsymbolcache.cpp documentsymbolcache.h
+ dynamiccapabilities.cpp dynamiccapabilities.h
+ languageclient.qrc
+ languageclientcompletionassist.cpp languageclientcompletionassist.h
+ languageclientfunctionhint.cpp languageclientfunctionhint.h
+ languageclienthoverhandler.cpp languageclienthoverhandler.h
+ languageclientinterface.cpp languageclientinterface.h
+ languageclientmanager.cpp languageclientmanager.h
+ languageclientoutline.cpp languageclientoutline.h
+ languageclientplugin.cpp languageclientplugin.h
+ languageclientquickfix.cpp languageclientquickfix.h
+ languageclientsettings.cpp languageclientsettings.h
+ languageclientutils.cpp languageclientutils.h
+ languageclient_global.h
+ locatorfilter.cpp locatorfilter.h
+)
diff --git a/src/plugins/languageclient/LanguageClient.json.in b/src/plugins/languageclient/LanguageClient.json.in
index c48a74c937..8eea5c88cc 100644
--- a/src/plugins/languageclient/LanguageClient.json.in
+++ b/src/plugins/languageclient/LanguageClient.json.in
@@ -2,7 +2,6 @@
\"Name\" : \"LanguageClient\",
\"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\",
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index fc9df47ff7..3acea15080 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -36,12 +36,13 @@
#include <languageserverprotocol/languagefeatures.h>
#include <languageserverprotocol/messages.h>
#include <languageserverprotocol/workspace.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
+#include <texteditor/codeassist/documentcontentcompletion.h>
#include <texteditor/semantichighlighter.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include <texteditor/textmark.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/session.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcprocess.h>
#include <utils/synchronousprocess.h>
@@ -67,7 +68,7 @@ static Q_LOGGING_CATEGORY(LOGLSPCLIENT, "qtc.languageclient.client", QtWarningMs
class TextMark : public TextEditor::TextMark
{
public:
- TextMark(const Utils::FileName &fileName, const Diagnostic &diag)
+ TextMark(const Utils::FilePath &fileName, const Diagnostic &diag)
: TextEditor::TextMark(fileName, diag.range().start().line() + 1, "lspmark")
, m_diagnostic(diag)
{
@@ -92,8 +93,11 @@ private:
Client::Client(BaseClientInterface *clientInterface)
: m_id(Core::Id::fromString(QUuid::createUuid().toString()))
, m_completionProvider(this)
+ , m_functionHintProvider(this)
, m_quickFixProvider(this)
, m_clientInterface(clientInterface)
+ , m_documentSymbolCache(this)
+ , m_hoverHandler(this)
{
m_contentHandler.insert(JsonRpcMessageHandler::jsonRpcMimeType(),
&JsonRpcMessageHandler::parseContent);
@@ -103,23 +107,121 @@ Client::Client(BaseClientInterface *clientInterface)
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
}
+static void updateEditorToolBar(QList<Utils::FilePath> files)
+{
+ QList<Core::IEditor *> editors = Core::DocumentModel::editorsForDocuments(
+ Utils::transform(files, [](Utils::FilePath &file) {
+ return Core::DocumentModel::documentForFilePath(file.toString());
+ }));
+ for (auto editor : editors)
+ updateEditorToolBar(editor);
+}
+
Client::~Client()
{
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
- for (TextDocument *document : m_resetAssistProvider) {
- document->setCompletionAssistProvider(nullptr);
+ for (TextDocument *document : m_resetAssistProvider.keys()) {
+ if (document->completionAssistProvider() == &m_completionProvider)
+ document->setCompletionAssistProvider(m_resetAssistProvider[document]);
+ document->setFunctionHintAssistProvider(nullptr);
document->setQuickFixAssistProvider(nullptr);
}
for (Core::IEditor * editor : Core::DocumentModel::editorsForOpenedDocuments()) {
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
TextEditorWidget *widget = textEditor->editorWidget();
widget->setRefactorMarkers(RefactorMarker::filterOutType(widget->refactorMarkers(), id()));
+ widget->removeHoverHandler(&m_hoverHandler);
}
}
for (const DocumentUri &uri : m_diagnostics.keys())
removeDiagnostics(uri);
+ updateEditorToolBar(m_openedDocument.keys());
+}
+
+static ClientCapabilities generateClientCapabilities()
+{
+ ClientCapabilities capabilities;
+ WorkspaceClientCapabilities workspaceCapabilities;
+ workspaceCapabilities.setWorkspaceFolders(true);
+ workspaceCapabilities.setApplyEdit(true);
+ DynamicRegistrationCapabilities allowDynamicRegistration;
+ allowDynamicRegistration.setDynamicRegistration(true);
+ workspaceCapabilities.setDidChangeConfiguration(allowDynamicRegistration);
+ workspaceCapabilities.setExecuteCommand(allowDynamicRegistration);
+ capabilities.setWorkspace(workspaceCapabilities);
+
+ TextDocumentClientCapabilities documentCapabilities;
+ TextDocumentClientCapabilities::SynchronizationCapabilities syncCapabilities;
+ syncCapabilities.setDynamicRegistration(true);
+ syncCapabilities.setWillSave(true);
+ syncCapabilities.setWillSaveWaitUntil(false);
+ syncCapabilities.setDidSave(true);
+ documentCapabilities.setSynchronization(syncCapabilities);
+
+ SymbolCapabilities symbolCapabilities;
+ SymbolCapabilities::SymbolKindCapabilities symbolKindCapabilities;
+ symbolKindCapabilities.setValueSet(
+ {SymbolKind::File, SymbolKind::Module, SymbolKind::Namespace,
+ SymbolKind::Package, SymbolKind::Class, SymbolKind::Method,
+ SymbolKind::Property, SymbolKind::Field, SymbolKind::Constructor,
+ SymbolKind::Enum, SymbolKind::Interface, SymbolKind::Function,
+ SymbolKind::Variable, SymbolKind::Constant, SymbolKind::String,
+ SymbolKind::Number, SymbolKind::Boolean, SymbolKind::Array,
+ SymbolKind::Object, SymbolKind::Key, SymbolKind::Null,
+ SymbolKind::EnumMember, SymbolKind::Struct, SymbolKind::Event,
+ SymbolKind::Operator, SymbolKind::TypeParameter});
+ symbolCapabilities.setSymbolKind(symbolKindCapabilities);
+ documentCapabilities.setDocumentSymbol(symbolCapabilities);
+
+ TextDocumentClientCapabilities::CompletionCapabilities completionCapabilities;
+ completionCapabilities.setDynamicRegistration(true);
+ TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities
+ completionItemKindCapabilities;
+ completionItemKindCapabilities.setValueSet(
+ {CompletionItemKind::Text, CompletionItemKind::Method,
+ CompletionItemKind::Function, CompletionItemKind::Constructor,
+ CompletionItemKind::Field, CompletionItemKind::Variable,
+ CompletionItemKind::Class, CompletionItemKind::Interface,
+ CompletionItemKind::Module, CompletionItemKind::Property,
+ CompletionItemKind::Unit, CompletionItemKind::Value,
+ CompletionItemKind::Enum, CompletionItemKind::Keyword,
+ CompletionItemKind::Snippet, CompletionItemKind::Color,
+ CompletionItemKind::File, CompletionItemKind::Reference,
+ CompletionItemKind::Folder, CompletionItemKind::EnumMember,
+ CompletionItemKind::Constant, CompletionItemKind::Struct,
+ CompletionItemKind::Event, CompletionItemKind::Operator,
+ CompletionItemKind::TypeParameter});
+ completionCapabilities.setCompletionItemKind(completionItemKindCapabilities);
+ TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities
+ completionItemCapbilities;
+ completionItemCapbilities.setSnippetSupport(false);
+ completionItemCapbilities.setCommitCharacterSupport(true);
+ completionCapabilities.setCompletionItem(completionItemCapbilities);
+ documentCapabilities.setCompletion(completionCapabilities);
+
+ TextDocumentClientCapabilities::CodeActionCapabilities codeActionCapabilities;
+ TextDocumentClientCapabilities::CodeActionCapabilities::CodeActionLiteralSupport literalSupport;
+ literalSupport.setCodeActionKind(
+ TextDocumentClientCapabilities::CodeActionCapabilities::CodeActionLiteralSupport::
+ CodeActionKind(QList<QString>{"*"}));
+ codeActionCapabilities.setCodeActionLiteralSupport(literalSupport);
+ documentCapabilities.setCodeAction(codeActionCapabilities);
+
+ TextDocumentClientCapabilities::HoverCapabilities hover;
+ hover.setContentFormat({MarkupKind::plaintext});
+ hover.setDynamicRegistration(true);
+ documentCapabilities.setHover(hover);
+
+ documentCapabilities.setReferences(allowDynamicRegistration);
+ documentCapabilities.setDocumentHighlight(allowDynamicRegistration);
+ documentCapabilities.setDefinition(allowDynamicRegistration);
+ documentCapabilities.setTypeDefinition(allowDynamicRegistration);
+ documentCapabilities.setImplementation(allowDynamicRegistration);
+ capabilities.setTextDocument(documentCapabilities);
+
+ return capabilities;
}
void Client::initialize()
@@ -129,15 +231,15 @@ void Client::initialize()
QTC_ASSERT(m_state == Uninitialized, return);
qCDebug(LOGLSPCLIENT) << "initializing language server " << m_displayName;
auto initRequest = new InitializeRequest();
- if (auto startupProject = SessionManager::startupProject()) {
- auto params = initRequest->params().value_or(InitializeParams());
- params.setRootUri(DocumentUri::fromFileName(startupProject->projectDirectory()));
- initRequest->setParams(params);
+ auto params = initRequest->params().value_or(InitializeParams());
+ params.setCapabilities(generateClientCapabilities());
+ if (m_project) {
+ params.setRootUri(DocumentUri::fromFileName(m_project->projectDirectory()));
params.setWorkSpaceFolders(Utils::transform(SessionManager::projects(), [](Project *pro){
return WorkSpaceFolder(pro->projectDirectory().toString(), pro->displayName());
}));
- initRequest->setParams(params);
}
+ initRequest->setParams(params);
initRequest->setResponseCallback([this](const InitializeRequest::Response &initResponse){
intializeCallback(initResponse);
});
@@ -164,27 +266,27 @@ Client::State Client::state() const
return m_state;
}
-void Client::openDocument(Core::IDocument *document)
+bool Client::openDocument(Core::IDocument *document)
{
using namespace TextEditor;
if (!isSupportedDocument(document))
- return;
- const FileName &filePath = document->filePath();
+ return false;
+ const FilePath &filePath = document->filePath();
const QString method(DidOpenTextDocumentNotification::methodName);
if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
if (!registered.value())
- return;
+ return false;
const TextDocumentRegistrationOptions option(
m_dynamicCapabilities.option(method).toObject());
if (option.isValid(nullptr)
&& !option.filterApplies(filePath, Utils::mimeTypeForName(document->mimeType()))) {
- return;
+ return false;
}
} else if (Utils::optional<ServerCapabilities::TextDocumentSync> _sync
= m_serverCapabilities.textDocumentSync()) {
if (auto options = Utils::get_if<TextDocumentSyncOptions>(&_sync.value())) {
if (!options->openClose().value_or(true))
- return;
+ return false;
}
}
auto uri = DocumentUri::fromFileName(filePath);
@@ -196,24 +298,46 @@ void Client::openDocument(Core::IDocument *document)
item.setText(QString::fromUtf8(document->contents()));
item.setVersion(textDocument ? textDocument->document()->revision() : 0);
- connect(document, &Core::IDocument::contentsChanged, this,
- [this, document](){
- documentContentsChanged(document);
- });
if (textDocument) {
- textDocument->completionAssistProvider();
- m_resetAssistProvider << textDocument;
+ connect(textDocument,
+ &TextEditor::TextDocument::contentsChangedWithPosition,
+ this,
+ [this, textDocument](int position, int charsRemoved, int charsAdded) {
+ documentContentsChanged(textDocument, position, charsRemoved, charsAdded);
+ });
+ auto *oldCompletionProvider = qobject_cast<TextEditor::DocumentContentCompletionProvider *>(
+ textDocument->completionAssistProvider());
+ if (oldCompletionProvider || !textDocument->completionAssistProvider()) {
+ // only replace the completion assist provider if it is the default one or null
+ m_completionProvider.setTriggerCharacters(
+ m_serverCapabilities.completionProvider()
+ .value_or(ServerCapabilities::CompletionOptions())
+ .triggerCharacters()
+ .value_or(QList<QString>()));
+ textDocument->setCompletionAssistProvider(&m_completionProvider);
+ }
+ m_resetAssistProvider[textDocument] = oldCompletionProvider;
+ m_functionHintProvider.setTriggerCharacters(
+ m_serverCapabilities.signatureHelpProvider()
+ .value_or(ServerCapabilities::SignatureHelpOptions())
+ .triggerCharacters()
+ .value_or(QList<QString>()));
textDocument->setCompletionAssistProvider(&m_completionProvider);
+ textDocument->setFunctionHintAssistProvider(&m_functionHintProvider);
textDocument->setQuickFixAssistProvider(&m_quickFixProvider);
connect(textDocument, &QObject::destroyed, this, [this, textDocument]{
m_resetAssistProvider.remove(textDocument);
});
+ m_openedDocument.insert(document->filePath(), textDocument->plainText());
+ } else {
+ m_openedDocument.insert(document->filePath(), QString());
}
- m_openedDocument.append(document->filePath());
sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)));
if (textDocument)
requestDocumentSymbols(textDocument);
+
+ return true;
}
void Client::sendContent(const IContent &content)
@@ -245,6 +369,11 @@ void Client::closeDocument(const DidCloseTextDocumentParams &params)
sendContent(params.textDocument().uri(), DidCloseTextDocumentNotification(params));
}
+bool Client::documentOpen(const Core::IDocument *document) const
+{
+ return m_openedDocument.contains(document->filePath());
+}
+
void Client::documentContentsSaved(Core::IDocument *document)
{
if (!m_openedDocument.contains(document->filePath()))
@@ -281,7 +410,7 @@ void Client::documentContentsSaved(Core::IDocument *document)
void Client::documentWillSave(Core::IDocument *document)
{
- const FileName &filePath = document->filePath();
+ const FilePath &filePath = document->filePath();
if (!m_openedDocument.contains(filePath))
return;
bool sendMessage = true;
@@ -307,7 +436,10 @@ void Client::documentWillSave(Core::IDocument *document)
sendContent(WillSaveTextDocumentNotification(params));
}
-void Client::documentContentsChanged(Core::IDocument *document)
+void Client::documentContentsChanged(TextEditor::TextDocument *document,
+ int position,
+ int charsRemoved,
+ int charsAdded)
{
if (!m_openedDocument.contains(document->filePath()))
return;
@@ -327,7 +459,21 @@ void Client::documentContentsChanged(Core::IDocument *document)
const auto uri = DocumentUri::fromFileName(document->filePath());
VersionedTextDocumentIdentifier docId(uri);
docId.setVersion(textDocument ? textDocument->document()->revision() : 0);
- const DidChangeTextDocumentParams params(docId, QString::fromUtf8(document->contents()));
+ DidChangeTextDocumentParams params;
+ params.setTextDocument(docId);
+ if (syncKind == TextDocumentSyncKind::Incremental) {
+ DidChangeTextDocumentParams::TextDocumentContentChangeEvent change;
+ QTextDocument oldDoc(m_openedDocument[document->filePath()]);
+ QTextCursor cursor(&oldDoc);
+ cursor.setPosition(position + charsRemoved);
+ cursor.setPosition(position, QTextCursor::KeepAnchor);
+ change.setRange(Range(cursor));
+ change.setText(document->textAt(position, charsAdded));
+ params.setContentChanges({change});
+ } else {
+ params.setContentChanges({document->plainText()});
+ }
+ m_openedDocument[document->filePath()] = document->plainText();
sendContent(DidChangeTextDocumentNotification(params));
}
@@ -364,7 +510,7 @@ static bool sendTextDocumentPositionParamsRequest(Client *client,
if (sendMessage) {
const TextDocumentRegistrationOptions option(dynamicCapabilities.option(Request::methodName));
if (option.isValid(nullptr))
- sendMessage = option.filterApplies(FileName::fromString(QUrl(uri).adjusted(QUrl::PreferLocalFile).toString()));
+ sendMessage = option.filterApplies(FilePath::fromString(QUrl(uri).adjusted(QUrl::PreferLocalFile).toString()));
else
sendMessage = supportedFile;
} else {
@@ -400,7 +546,7 @@ void Client::requestDocumentSymbols(TextEditor::TextDocument *document)
{
// TODO: Do not use this information for highlighting but the overview model
return;
- const FileName &filePath = document->filePath();
+ const FilePath &filePath = document->filePath();
bool sendMessage = m_dynamicCapabilities.isRegistered(DocumentSymbolsRequest::methodName).value_or(false);
if (sendMessage) {
const TextDocumentRegistrationOptions option(m_dynamicCapabilities.option(DocumentSymbolsRequest::methodName));
@@ -542,7 +688,7 @@ void Client::cursorPositionChanged(TextEditor::TextEditorWidget *widget)
void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic> &diagnostics)
{
- const Utils::FileName fileName = uri.toFileName();
+ const Utils::FilePath fileName = uri.toFileName();
TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFileName(fileName);
if (!doc)
return;
@@ -570,7 +716,7 @@ void Client::requestCodeActions(const CodeActionRequest &request)
if (!request.isValid(nullptr))
return;
- const Utils::FileName fileName
+ const Utils::FilePath fileName
= request.params().value_or(CodeActionParams()).textDocument().uri().toFileName();
const QString method(CodeActionRequest::methodName);
@@ -631,6 +777,16 @@ void Client::executeCommand(const Command &command)
sendContent(request);
}
+const ProjectExplorer::Project *Client::project() const
+{
+ return m_project;
+}
+
+void Client::setCurrentProject(ProjectExplorer::Project *project)
+{
+ m_project = project;
+}
+
void Client::projectOpened(ProjectExplorer::Project *project)
{
if (!sendWorkspceFolderChanges())
@@ -645,10 +801,19 @@ void Client::projectOpened(ProjectExplorer::Project *project)
void Client::projectClosed(ProjectExplorer::Project *project)
{
+ if (project == m_project) {
+ if (m_state == Initialized) {
+ shutdown();
+ } else {
+ m_state = Shutdown; // otherwise the manager would try to restart this server
+ emit finished();
+ }
+ }
if (!sendWorkspceFolderChanges())
return;
WorkspaceFoldersChangeEvent event;
- event.setRemoved({WorkSpaceFolder(project->projectDirectory().toString(), project->displayName())});
+ event.setRemoved(
+ {WorkSpaceFolder(project->projectDirectory().toString(), project->displayName())});
DidChangeWorkspaceFoldersParams params;
params.setEvent(event);
DidChangeWorkspaceFoldersNotification change(params);
@@ -663,27 +828,18 @@ void Client::setSupportedLanguage(const LanguageFilter &filter)
bool Client::isSupportedDocument(const Core::IDocument *document) const
{
QTC_ASSERT(document, return false);
- return isSupportedFile(document->filePath(), document->mimeType());
+ return m_languagFilter.isSupported(document);
}
-bool Client::isSupportedFile(const Utils::FileName &filePath, const QString &mimeType) const
+bool Client::isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) const
{
- if (m_languagFilter.mimeTypes.isEmpty() && m_languagFilter.filePattern.isEmpty())
- return true;
- if (m_languagFilter.mimeTypes.contains(mimeType))
- return true;
- auto regexps = Utils::transform(m_languagFilter.filePattern, [](const QString &pattern){
- return QRegExp(pattern, Utils::HostOsInfo::fileNameCaseSensitivity(), QRegExp::Wildcard);
- });
- return Utils::anyOf(regexps, [filePath](const QRegExp &reg){
- return reg.exactMatch(filePath.toString()) || reg.exactMatch(filePath.fileName());
- });
+ return m_languagFilter.isSupported(filePath, mimeType);
}
bool Client::isSupportedUri(const DocumentUri &uri) const
{
- return isSupportedFile(uri.toFileName(),
- Utils::mimeTypeForFile(uri.toFileName().fileName()).name());
+ return m_languagFilter.isSupported(uri.toFileName(),
+ Utils::mimeTypeForFile(uri.toFileName().fileName()).name());
}
bool Client::needsRestart(const BaseSettings *settings) const
@@ -717,9 +873,11 @@ bool Client::reset()
m_state = Uninitialized;
m_responseHandlers.clear();
m_clientInterface->resetBuffer();
+ updateEditorToolBar(m_openedDocument.keys());
m_openedDocument.clear();
m_serverCapabilities = ServerCapabilities();
m_dynamicCapabilities.reset();
+ m_project = nullptr;
for (const DocumentUri &uri : m_diagnostics.keys())
removeDiagnostics(uri);
return true;
@@ -769,6 +927,16 @@ const BaseClientInterface *Client::clientInterface() const
return m_clientInterface.data();
}
+DocumentSymbolCache *Client::documentSymbolCache()
+{
+ return &m_documentSymbolCache;
+}
+
+HoverHandler *Client::hoverHandler()
+{
+ return &m_hoverHandler;
+}
+
void Client::log(const ShowMessageParams &message,
Core::MessageManager::PrintToOutputPaneFlag flag)
{
@@ -793,8 +961,7 @@ void Client::showMessageBox(const ShowMessageRequestParams &message, const Messa
}
box->setModal(true);
connect(box, &QMessageBox::finished, this, [=]{
- ShowMessageRequest::Response response;
- response.setId(id);
+ ShowMessageRequest::Response response(id);
const MessageActionItem &item = itemForButton.value(box->clickedButton());
response.setResult(item.isValid(nullptr) ? LanguageClientValue<MessageActionItem>(item)
: LanguageClientValue<MessageActionItem>());
@@ -856,8 +1023,7 @@ void Client::handleMethod(const QString &method, MessageId id, const IContent *c
if (paramsValid) {
showMessageBox(params, request->id());
} else {
- ShowMessageRequest::Response response;
- response.setId(request->id());
+ ShowMessageRequest::Response response(request->id());
ResponseError<std::nullptr_t> error;
const QString errorMessage =
QString("Could not parse ShowMessageRequest parameter of '%1': \"%2\"")
@@ -882,9 +1048,23 @@ void Client::handleMethod(const QString &method, MessageId id, const IContent *c
paramsValid = params.isValid(&error);
if (paramsValid)
applyWorkspaceEdit(params.edit());
+ } else if (method == WorkSpaceFolderRequest::methodName) {
+ WorkSpaceFolderRequest::Response response(dynamic_cast<const WorkSpaceFolderRequest *>(content)->id());
+ const QList<ProjectExplorer::Project *> projects
+ = ProjectExplorer::SessionManager::projects();
+ WorkSpaceFolderResult result;
+ if (projects.isEmpty()) {
+ result = nullptr;
+ } else {
+ result = Utils::transform(projects, [](ProjectExplorer::Project *project) {
+ return WorkSpaceFolder(project->projectDirectory().toString(),
+ project->displayName());
+ });
+ }
+ response.setResult(result);
+ sendContent(response);
} else if (id.isValid(&error)) {
- Response<JsonObject, JsonObject> response;
- response.setId(id);
+ Response<JsonObject, JsonObject> response(id);
ResponseError<JsonObject> error;
error.setCode(ResponseError<JsonObject>::MethodNotFound);
response.setError(error);
@@ -949,9 +1129,17 @@ void Client::intializeCallback(const InitializeRequest::Response &initResponse)
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " initialized";
m_state = Initialized;
sendContent(InitializeNotification());
+ for (auto openedDocument : Core::DocumentModel::openedDocuments()) {
+ if (openDocument(openedDocument)) {
+ for (Core::IEditor *editor : Core::DocumentModel::editorsForDocument(openedDocument))
+ updateEditorToolBar(editor);
+ }
+ }
+ for (Core::IEditor *editor : Core::DocumentModel::editorsForOpenedDocuments()) {
+ if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor))
+ textEditor->editorWidget()->addHoverHandler(&m_hoverHandler);
+ }
emit initialized(m_serverCapabilities);
- for (auto openedDocument : Core::DocumentModel::openedDocuments())
- openDocument(openedDocument);
}
void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h
index 635512fa28..9746607e62 100644
--- a/src/plugins/languageclient/client.h
+++ b/src/plugins/languageclient/client.h
@@ -25,10 +25,13 @@
#pragma once
+#include "documentsymbolcache.h"
#include "dynamiccapabilities.h"
#include "languageclientcompletionassist.h"
+#include "languageclientfunctionhint.h"
#include "languageclientquickfix.h"
#include "languageclientsettings.h"
+#include "languageclienthoverhandler.h"
#include <coreplugin/id.h>
#include <coreplugin/messagemanager.h>
@@ -90,12 +93,15 @@ public:
bool reachable() const { return m_state == Initialized; }
// document synchronization
- void openDocument(Core::IDocument *document);
+ bool openDocument(Core::IDocument *document);
void closeDocument(const LanguageServerProtocol::DidCloseTextDocumentParams &params);
- bool documentOpen(const LanguageServerProtocol::DocumentUri &uri) const;
+ bool documentOpen(const Core::IDocument *document) const;
void documentContentsSaved(Core::IDocument *document);
void documentWillSave(Core::IDocument *document);
- void documentContentsChanged(Core::IDocument *document);
+ void documentContentsChanged(TextEditor::TextDocument *document,
+ int position,
+ int charsRemoved,
+ int charsAdded);
void registerCapabilities(const QList<LanguageServerProtocol::Registration> &registrations);
void unregisterCapabilities(const QList<LanguageServerProtocol::Unregistration> &unregistrations);
bool findLinkAt(LanguageServerProtocol::GotoDefinitionRequest &request);
@@ -111,6 +117,8 @@ public:
void executeCommand(const LanguageServerProtocol::Command &command);
// workspace control
+ void setCurrentProject(ProjectExplorer::Project *project);
+ const ProjectExplorer::Project *project() const;
void projectOpened(ProjectExplorer::Project *project);
void projectClosed(ProjectExplorer::Project *project);
@@ -121,7 +129,7 @@ public:
void setSupportedLanguage(const LanguageFilter &filter);
bool isSupportedDocument(const Core::IDocument *document) const;
- bool isSupportedFile(const Utils::FileName &filePath, const QString &mimeType) const;
+ bool isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) const;
bool isSupportedUri(const LanguageServerProtocol::DocumentUri &uri) const;
void setName(const QString &name) { m_displayName = name; }
@@ -148,6 +156,8 @@ public:
const LanguageServerProtocol::ServerCapabilities &capabilities() const;
const DynamicCapabilities &dynamicCapabilities() const;
const BaseClientInterface *clientInterface() const;
+ DocumentSymbolCache *documentSymbolCache();
+ HoverHandler *hoverHandler();
signals:
void initialized(LanguageServerProtocol::ServerCapabilities capabilities);
@@ -186,17 +196,21 @@ private:
QHash<QByteArray, ContentHandler> m_contentHandler;
QString m_displayName;
LanguageFilter m_languagFilter;
- QList<Utils::FileName> m_openedDocument;
+ QMap<Utils::FilePath, QString> m_openedDocument;
Core::Id m_id;
LanguageServerProtocol::ServerCapabilities m_serverCapabilities;
DynamicCapabilities m_dynamicCapabilities;
LanguageClientCompletionAssistProvider m_completionProvider;
+ FunctionHintAssistProvider m_functionHintProvider;
LanguageClientQuickFixProvider m_quickFixProvider;
- QSet<TextEditor::TextDocument *> m_resetAssistProvider;
+ QMap<TextEditor::TextDocument *, QPointer<TextEditor::CompletionAssistProvider>> m_resetAssistProvider;
QHash<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::MessageId> m_highlightRequests;
int m_restartsLeft = 5;
QScopedPointer<BaseClientInterface> m_clientInterface;
QMap<LanguageServerProtocol::DocumentUri, QList<TextMark *>> m_diagnostics;
+ DocumentSymbolCache m_documentSymbolCache;
+ HoverHandler m_hoverHandler;
+ const ProjectExplorer::Project *m_project = nullptr;
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/documentsymbolcache.cpp b/src/plugins/languageclient/documentsymbolcache.cpp
new file mode 100644
index 0000000000..b922486d56
--- /dev/null
+++ b/src/plugins/languageclient/documentsymbolcache.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 "documentsymbolcache.h"
+
+#include "client.h"
+
+#include <coreplugin/editormanager/editormanager.h>
+#include <texteditor/textdocument.h>
+
+using namespace LanguageServerProtocol;
+
+namespace LanguageClient {
+
+DocumentSymbolCache::DocumentSymbolCache(Client *client)
+ : QObject(client)
+ , m_client(client)
+{
+ connect(Core::EditorManager::instance(),
+ &Core::EditorManager::documentOpened,
+ this,
+ [this](Core::IDocument *document) {
+ connect(document, &Core::IDocument::contentsChanged, this, [this, document]() {
+ m_cache.remove(DocumentUri::fromFileName(document->filePath()));
+ });
+ });
+}
+
+void DocumentSymbolCache::requestSymbols(const DocumentUri &uri)
+{
+ auto entry = m_cache.find(uri);
+ if (entry != m_cache.end()) {
+ emit gotSymbols(uri, entry.value());
+ return;
+ }
+
+ const DocumentSymbolParams params((TextDocumentIdentifier(uri)));
+ DocumentSymbolsRequest request(params);
+ request.setResponseCallback([uri, self = QPointer<DocumentSymbolCache>(this)](
+ const DocumentSymbolsRequest::Response &response) {
+ if (self)
+ self->handleResponse(uri, response);
+ });
+ m_client->sendContent(request);
+}
+
+void DocumentSymbolCache::handleResponse(const DocumentUri &uri,
+ const DocumentSymbolsRequest::Response &response)
+{
+ if (Utils::optional<DocumentSymbolsRequest::Response::Error> error = response.error()) {
+ if (m_client)
+ m_client->log(error.value());
+ }
+ const DocumentSymbolsResult &symbols = response.result().value_or(DocumentSymbolsResult());
+ m_cache[uri] = symbols;
+ emit gotSymbols(uri, symbols);
+}
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/documentsymbolcache.h b/src/plugins/languageclient/documentsymbolcache.h
new file mode 100644
index 0000000000..2f0b2376bc
--- /dev/null
+++ b/src/plugins/languageclient/documentsymbolcache.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 "utils/optional.h"
+
+#include <languageserverprotocol/languagefeatures.h>
+
+#include <QObject>
+
+namespace LanguageClient {
+
+class Client;
+
+class DocumentSymbolCache : public QObject
+{
+ Q_OBJECT
+public:
+ DocumentSymbolCache(Client *client);
+
+ void requestSymbols(const LanguageServerProtocol::DocumentUri &uri);
+
+signals:
+ void gotSymbols(const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::DocumentSymbolsResult &symbols);
+
+private:
+ void handleResponse(const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::DocumentSymbolsRequest::Response &response);
+
+ QMap<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::DocumentSymbolsResult> m_cache;
+ Client *m_client = nullptr;
+};
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/images/languageclient.png b/src/plugins/languageclient/images/languageclient.png
new file mode 100644
index 0000000000..38e5f28498
--- /dev/null
+++ b/src/plugins/languageclient/images/languageclient.png
Binary files differ
diff --git a/src/plugins/languageclient/images/languageclient@2x.png b/src/plugins/languageclient/images/languageclient@2x.png
new file mode 100644
index 0000000000..bb01ed83bb
--- /dev/null
+++ b/src/plugins/languageclient/images/languageclient@2x.png
Binary files differ
diff --git a/src/plugins/languageclient/languageclient.pro b/src/plugins/languageclient/languageclient.pro
index dbae20e109..b2d39acf16 100644
--- a/src/plugins/languageclient/languageclient.pro
+++ b/src/plugins/languageclient/languageclient.pro
@@ -4,29 +4,37 @@ DEFINES += LANGUAGECLIENT_LIBRARY
HEADERS += \
client.h \
+ documentsymbolcache.h \
dynamiccapabilities.h \
languageclient_global.h \
languageclientcompletionassist.h \
+ languageclientfunctionhint.h \
+ languageclienthoverhandler.h \
languageclientinterface.h \
languageclientmanager.h \
languageclientoutline.h \
languageclientplugin.h \
languageclientquickfix.h \
languageclientsettings.h \
- languageclientutils.h
+ languageclientutils.h \
+ locatorfilter.h
SOURCES += \
client.cpp \
+ documentsymbolcache.cpp \
dynamiccapabilities.cpp \
languageclientcompletionassist.cpp \
+ languageclientfunctionhint.cpp \
+ languageclienthoverhandler.cpp \
languageclientinterface.cpp \
languageclientmanager.cpp \
languageclientoutline.cpp \
languageclientplugin.cpp \
languageclientquickfix.cpp \
languageclientsettings.cpp \
- languageclientutils.cpp
+ languageclientutils.cpp \
+ locatorfilter.cpp
RESOURCES += \
languageclient.qrc
diff --git a/src/plugins/languageclient/languageclient.qbs b/src/plugins/languageclient/languageclient.qbs
index 0c2752ef5e..13ca210570 100644
--- a/src/plugins/languageclient/languageclient.qbs
+++ b/src/plugins/languageclient/languageclient.qbs
@@ -16,10 +16,16 @@ QtcPlugin {
files: [
"client.cpp",
"client.h",
+ "documentsymbolcache.cpp",
+ "documentsymbolcache.h",
"dynamiccapabilities.cpp",
"dynamiccapabilities.h",
"languageclient.qrc",
"languageclient_global.h",
+ "languageclienthoverhandler.cpp",
+ "languageclienthoverhandler.h",
+ "languageclientfunctionhint.cpp",
+ "languageclientfunctionhint.h",
"languageclientinterface.cpp",
"languageclientinterface.h",
"languageclientcompletionassist.cpp",
@@ -36,5 +42,7 @@ QtcPlugin {
"languageclientsettings.h",
"languageclientutils.cpp",
"languageclientutils.h",
+ "locatorfilter.cpp",
+ "locatorfilter.h",
]
}
diff --git a/src/plugins/languageclient/languageclient.qrc b/src/plugins/languageclient/languageclient.qrc
index eb73a75300..f5bbf281e0 100644
--- a/src/plugins/languageclient/languageclient.qrc
+++ b/src/plugins/languageclient/languageclient.qrc
@@ -1,5 +1,7 @@
<RCC>
<qresource prefix="/languageclient">
+ <file>images/languageclient.png</file>
+ <file>images/languageclient@2x.png</file>
<file>images/settingscategory_languageclient.png</file>
<file>images/settingscategory_languageclient@2x.png</file>
</qresource>
diff --git a/src/plugins/languageclient/languageclient_global.h b/src/plugins/languageclient/languageclient_global.h
index a4cd255d90..685379804d 100644
--- a/src/plugins/languageclient/languageclient_global.h
+++ b/src/plugins/languageclient/languageclient_global.h
@@ -31,7 +31,16 @@ namespace LanguageClient {
namespace Constants {
const char LANGUAGECLIENT_SETTINGS_CATEGORY[] = "ZY.LanguageClient";
+const char LANGUAGECLIENT_SETTINGS_PAGE[] = "LanguageClient.General";
const char LANGUAGECLIENT_SETTINGS_TR[] = QT_TRANSLATE_NOOP("LanguageClient", "Language Client");
+const char LANGUAGECLIENT_DOCUMENT_FILTER_ID[] = "Current Document Symbols";
+const char LANGUAGECLIENT_DOCUMENT_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Symbols in Current Document");
+const char LANGUAGECLIENT_WORKSPACE_FILTER_ID[] = "Workspace Symbols";
+const char LANGUAGECLIENT_WORKSPACE_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Symbols in Workspace");
+const char LANGUAGECLIENT_WORKSPACE_CLASS_FILTER_ID[] = "Workspace Classes and Structs";
+const char LANGUAGECLIENT_WORKSPACE_CLASS_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Classes and Structs in Workspace");
+const char LANGUAGECLIENT_WORKSPACE_METHOD_FILTER_ID[] = "Workspace Functions and Methods";
+const char LANGUAGECLIENT_WORKSPACE_METHOD_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Functions and Methods in Workspace");
} // namespace Constants
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp
index 1d9a10f6e4..a036f7beb3 100644
--- a/src/plugins/languageclient/languageclientcompletionassist.cpp
+++ b/src/plugins/languageclient/languageclientcompletionassist.cpp
@@ -41,6 +41,7 @@
#include <QDebug>
#include <QLoggingCategory>
#include <QRegExp>
+#include <QRegularExpression>
#include <QTextBlock>
#include <QTextDocument>
#include <QTime>
@@ -76,6 +77,7 @@ public:
private:
CompletionItem m_item;
+ mutable QChar m_triggeredCommitCharacter;
mutable QString m_sortText;
};
@@ -89,8 +91,14 @@ QString LanguageClientCompletionItem::text() const
bool LanguageClientCompletionItem::implicitlyApplies() const
{ return false; }
-bool LanguageClientCompletionItem::prematurelyApplies(const QChar &/*typedCharacter*/) const
-{ return false; }
+bool LanguageClientCompletionItem::prematurelyApplies(const QChar &typedCharacter) const
+{
+ if (m_item.commitCharacters().has_value() && m_item.commitCharacters().value().contains(typedCharacter)) {
+ m_triggeredCommitCharacter = typedCharacter;
+ return true;
+ }
+ return false;
+}
void LanguageClientCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
int /*basePosition*/) const
@@ -101,13 +109,20 @@ void LanguageClientCompletionItem::apply(TextDocumentManipulatorInterface &manip
} else {
const QString textToInsert(m_item.insertText().value_or(text()));
int length = 0;
- for (auto it = textToInsert.crbegin(); it != textToInsert.crend(); ++it) {
- auto ch = *it;
- if (ch == manipulator.characterAt(pos - length - 1))
- ++length;
- else if (length != 0)
+ for (auto it = textToInsert.crbegin(), end = textToInsert.crend(); it != end; ++it) {
+ if (it->toLower() != manipulator.characterAt(pos - length - 1).toLower()) {
length = 0;
+ break;
+ }
+ ++length;
}
+ QTextCursor cursor = manipulator.textCursorAt(pos);
+ cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
+ const QString blockTextUntilPosition = cursor.selectedText();
+ static QRegularExpression identifier("[a-zA-Z_][a-zA-Z0-9_]*$");
+ QRegularExpressionMatch match = identifier.match(blockTextUntilPosition);
+ int matchLength = match.hasMatch() ? match.capturedLength(0) : 0;
+ length = qMax(length, matchLength);
manipulator.replace(pos - length, length, textToInsert);
}
@@ -115,6 +130,8 @@ void LanguageClientCompletionItem::apply(TextDocumentManipulatorInterface &manip
for (const auto &edit : *additionalEdits)
applyTextEdit(manipulator, edit);
}
+ if (!m_triggeredCommitCharacter.isNull())
+ manipulator.insertCodeSnippet(manipulator.currentPosition(), m_triggeredCommitCharacter);
}
QIcon LanguageClientCompletionItem::icon() const
@@ -136,8 +153,7 @@ QIcon LanguageClientCompletionItem::icon() const
case CompletionItemKind::Snippet: icon = QIcon(":/texteditor/images/snippet.png"); break;
case CompletionItemKind::EnumMember: icon = iconForType(Enumerator); break;
case CompletionItemKind::Struct: icon = iconForType(Struct); break;
- default:
- break;
+ default: icon = iconForType(Unknown); break;
}
return icon;
}
@@ -312,8 +328,9 @@ IAssistProposal *LanguageClientCompletionAssistProcessor::perform(const AssistIn
--line; // line is 0 based in the protocol
--column; // column is 0 based in the protocol
params.setPosition({line, column});
+ params.setContext(context);
params.setTextDocument(
- DocumentUri::fromFileName(Utils::FileName::fromString(interface->fileName())));
+ DocumentUri::fromFileName(Utils::FilePath::fromString(interface->fileName())));
completionRequest.setResponseCallback([this](auto response) {
this->handleCompletionResponse(response);
});
diff --git a/src/plugins/languageclient/languageclientfunctionhint.cpp b/src/plugins/languageclient/languageclientfunctionhint.cpp
new file mode 100644
index 0000000000..9a1fe6fc8e
--- /dev/null
+++ b/src/plugins/languageclient/languageclientfunctionhint.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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 "languageclientfunctionhint.h"
+#include "client.h"
+
+#include <languageserverprotocol/languagefeatures.h>
+#include <texteditor/codeassist/assistinterface.h>
+#include <texteditor/codeassist/functionhintproposal.h>
+#include <texteditor/codeassist/iassistprocessor.h>
+#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
+
+using namespace TextEditor;
+using namespace LanguageServerProtocol;
+
+namespace LanguageClient {
+
+class FunctionHintProposalModel : public IFunctionHintProposalModel
+{
+public:
+ explicit FunctionHintProposalModel(SignatureHelp signature)
+ : m_sigis(signature)
+ {}
+ void reset() override {}
+ int size() const override
+ { return m_sigis.signatures().size(); }
+ QString text(int index) const override;
+
+ int activeArgument(const QString &/*prefix*/) const override
+ { return m_sigis.activeParameter().value_or(0); }
+
+private:
+ LanguageServerProtocol::SignatureHelp m_sigis;
+};
+
+QString FunctionHintProposalModel::text(int index) const
+{
+ return m_sigis.signatures().size() > index ? m_sigis.signatures().at(index).label() : QString();
+}
+
+class FunctionHintProcessor : public IAssistProcessor
+{
+public:
+ explicit FunctionHintProcessor(Client *client) : m_client(client) {}
+ IAssistProposal *perform(const AssistInterface *interface) override;
+ bool running() override { return m_running; }
+ bool needsRestart() const override { return true; }
+
+private:
+ void handleSignatureResponse(const SignatureHelpRequest::Response &response);
+
+ QPointer<Client> m_client;
+ bool m_running = false;
+ int m_pos = -1;
+};
+
+IAssistProposal *FunctionHintProcessor::perform(const AssistInterface *interface)
+{
+ QTC_ASSERT(m_client, return nullptr);
+ m_pos = interface->position();
+ QTextCursor cursor(interface->textDocument());
+ cursor.setPosition(m_pos);
+ auto uri = DocumentUri::fromFileName(Utils::FilePath::fromString(interface->fileName()));
+ SignatureHelpRequest request;
+ request.setParams(TextDocumentPositionParams(TextDocumentIdentifier(uri), Position(cursor)));
+ request.setResponseCallback([this](auto response) { this->handleSignatureResponse(response); });
+ m_client->sendContent(request);
+ m_running = true;
+ return nullptr;
+}
+
+void FunctionHintProcessor::handleSignatureResponse(const SignatureHelpRequest::Response &response)
+{
+ m_running = false;
+ if (auto error = response.error())
+ m_client->log(error.value());
+ FunctionHintProposalModelPtr model(
+ new FunctionHintProposalModel(response.result().value().value()));
+ setAsyncProposalAvailable(new FunctionHintProposal(m_pos, model));
+}
+
+FunctionHintAssistProvider::FunctionHintAssistProvider(Client *client)
+ : m_client(client)
+{}
+
+TextEditor::IAssistProcessor *FunctionHintAssistProvider::createProcessor() const
+{
+ return new FunctionHintProcessor(m_client);
+}
+
+IAssistProvider::RunType FunctionHintAssistProvider::runType() const
+{
+ return Asynchronous;
+}
+
+int FunctionHintAssistProvider::activationCharSequenceLength() const
+{
+ return m_activationCharSequenceLength;
+}
+
+bool FunctionHintAssistProvider::isActivationCharSequence(
+ const QString &sequence) const
+{
+ return Utils::anyOf(m_triggerChars,
+ [sequence](const QString &trigger) { return trigger.endsWith(sequence); });
+}
+
+bool FunctionHintAssistProvider::isContinuationChar(const QChar &/*c*/) const
+{
+ return true;
+}
+
+void FunctionHintAssistProvider::setTriggerCharacters(QList<QString> triggerChars)
+{
+ m_triggerChars = triggerChars;
+ for (const QString &trigger : triggerChars) {
+ if (trigger.length() > m_activationCharSequenceLength)
+ m_activationCharSequenceLength = trigger.length();
+ }
+}
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientfunctionhint.h b/src/plugins/languageclient/languageclientfunctionhint.h
new file mode 100644
index 0000000000..cf5f96d812
--- /dev/null
+++ b/src/plugins/languageclient/languageclientfunctionhint.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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 <texteditor/codeassist/completionassistprovider.h>
+
+namespace LanguageClient {
+
+class Client;
+
+class FunctionHintAssistProvider : public TextEditor::CompletionAssistProvider
+{
+public:
+ explicit FunctionHintAssistProvider(Client *client);
+
+ TextEditor::IAssistProcessor *createProcessor() const override;
+ RunType runType() const override;
+
+ int activationCharSequenceLength() const override;
+ bool isActivationCharSequence(const QString &sequence) const override;
+ bool isContinuationChar(const QChar &c) const override;
+
+ void setTriggerCharacters(QList<QString> triggerChars);
+private:
+ QList<QString> m_triggerChars;
+ int m_activationCharSequenceLength = 0;
+ Client *m_client = nullptr; // not owned
+};
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclienthoverhandler.cpp b/src/plugins/languageclient/languageclienthoverhandler.cpp
new file mode 100644
index 0000000000..166fdc3049
--- /dev/null
+++ b/src/plugins/languageclient/languageclienthoverhandler.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** 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 "languageclienthoverhandler.h"
+
+#include "client.h"
+
+#include <texteditor/textdocument.h>
+#include <texteditor/texteditor.h>
+#include <utils/mimetypes/mimedatabase.h>
+#include <utils/qtcassert.h>
+#include <utils/tooltip/tooltip.h>
+
+using namespace LanguageServerProtocol;
+
+namespace LanguageClient {
+
+HoverHandler::HoverHandler(Client *client)
+ : m_client(client)
+{}
+
+HoverHandler::~HoverHandler()
+{
+ abort();
+}
+
+void HoverHandler::abort()
+{
+ if (m_client && m_client->reachable() && m_currentRequest.has_value())
+ m_client->cancelRequest(*m_currentRequest);
+ m_currentRequest.reset();
+}
+
+void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
+ int pos,
+ TextEditor::BaseHoverHandler::ReportPriority report)
+{
+ if (m_currentRequest.has_value())
+ abort();
+ if (m_client.isNull()
+ || !m_client->documentOpen(editorWidget->textDocument())
+ || !m_client->capabilities().hoverProvider().value_or(false)) {
+ report(Priority_None);
+ return;
+ }
+
+ bool sendMessage = m_client->capabilities().hoverProvider().value_or(false);
+ if (Utils::optional<bool> registered = m_client->dynamicCapabilities().isRegistered(
+ HoverRequest::methodName)) {
+ sendMessage = registered.value();
+ if (sendMessage) {
+ const TextDocumentRegistrationOptions option(
+ m_client->dynamicCapabilities().option(HoverRequest::methodName).toObject());
+ if (option.isValid(nullptr)) {
+ sendMessage = option.filterApplies(editorWidget->textDocument()->filePath(),
+ Utils::mimeTypeForName(
+ editorWidget->textDocument()->mimeType()));
+ }
+ }
+ }
+ if (!sendMessage) {
+ report(Priority_None);
+ return;
+ }
+
+ m_report = report;
+ auto uri = DocumentUri::fromFileName(editorWidget->textDocument()->filePath());
+ QTextCursor cursor = editorWidget->textCursor();
+ cursor.setPosition(pos);
+ TextDocumentPositionParams params(uri, Position(cursor));
+ HoverRequest request(params);
+ request.setResponseCallback(
+ [this](const HoverRequest::Response &response) { handleResponse(response); });
+ m_client->sendContent(request);
+}
+
+void HoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point)
+{
+ if (toolTip().isEmpty())
+ Utils::ToolTip::hide();
+ else
+ Utils::ToolTip::show(point, toolTip(), editorWidget);
+}
+
+void HoverHandler::handleResponse(const HoverRequest::Response &response)
+{
+ m_currentRequest.reset();
+ if (Utils::optional<HoverRequest::Response::Error> error = response.error()) {
+ if (m_client)
+ m_client->log(error.value());
+ }
+ if (Utils::optional<Hover> result = response.result())
+ setContent(result.value().content());
+ m_report(priority());
+}
+
+static QString toolTipForMarkedStrings(const QList<MarkedString> &markedStrings)
+{
+ QString tooltip;
+ for (const MarkedString &markedString : markedStrings) {
+ if (!tooltip.isEmpty())
+ tooltip += '\n';
+ if (auto string = Utils::get_if<QString>(&markedString))
+ tooltip += *string;
+ else if (auto string = Utils::get_if<MarkedLanguageString>(&markedString))
+ tooltip += string->value() + " [" + string->language() + ']';
+ }
+ return tooltip;
+}
+
+void HoverHandler::setContent(const HoverContent &hoverContent)
+{
+ if (auto markupContent = Utils::get_if<MarkupContent>(&hoverContent)) {
+ const QString &content = markupContent->content();
+ if (markupContent->kind() == MarkupKind::plaintext)
+ setToolTip(content);
+ else if (m_client)
+ m_client->log(tr("Got unsupported markup hover content: ") + content);
+ } else if (auto markedString = Utils::get_if<MarkedString>(&hoverContent)) {
+ setToolTip(toolTipForMarkedStrings({*markedString}));
+ } else if (auto markedStrings = Utils::get_if<QList<MarkedString>>(&hoverContent)) {
+ setToolTip(toolTipForMarkedStrings(*markedStrings));
+ }
+}
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclienthoverhandler.h b/src/plugins/languageclient/languageclienthoverhandler.h
new file mode 100644
index 0000000000..88a439e211
--- /dev/null
+++ b/src/plugins/languageclient/languageclienthoverhandler.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 <languageserverprotocol/languagefeatures.h>
+#include <texteditor/basehoverhandler.h>
+
+namespace LanguageClient {
+
+class Client;
+
+class HoverHandler : public TextEditor::BaseHoverHandler
+{
+ Q_DECLARE_TR_FUNCTIONS(HoverHandler)
+public:
+ explicit HoverHandler(Client *client);
+ ~HoverHandler() override;
+
+ void abort() override;
+
+protected:
+ void identifyMatch(TextEditor::TextEditorWidget *editorWidget,
+ int pos,
+ ReportPriority report) override;
+ void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
+
+private:
+ void handleResponse(const LanguageServerProtocol::HoverRequest::Response &response);
+ void setContent(const LanguageServerProtocol::HoverContent &content);
+
+ QPointer<Client> m_client;
+ Utils::optional<LanguageServerProtocol::MessageId> m_currentRequest;
+ TextEditor::BaseHoverHandler::ReportPriority m_report;
+};
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientinterface.cpp b/src/plugins/languageclient/languageclientinterface.cpp
index 6e138e02c0..91d2562e67 100644
--- a/src/plugins/languageclient/languageclientinterface.cpp
+++ b/src/plugins/languageclient/languageclientinterface.cpp
@@ -35,7 +35,6 @@
using namespace LanguageServerProtocol;
static Q_LOGGING_CATEGORY(LOGLSPCLIENTV, "qtc.languageclient.messages", QtWarningMsg);
-static Q_LOGGING_CATEGORY(LOGLSPCLIENTPARSE, "qtc.languageclient.parse", QtWarningMsg);
namespace LanguageClient {
@@ -64,8 +63,8 @@ void BaseClientInterface::resetBuffer()
void BaseClientInterface::parseData(const QByteArray &data)
{
const qint64 preWritePosition = m_buffer.pos();
- qCDebug(LOGLSPCLIENTPARSE) << "parse buffer pos: " << preWritePosition;
- qCDebug(LOGLSPCLIENTPARSE) << " data: " << data;
+ qCDebug(parseLog) << "parse buffer pos: " << preWritePosition;
+ qCDebug(parseLog) << " data: " << data;
if (!m_buffer.atEnd())
m_buffer.seek(preWritePosition + m_buffer.bytesAvailable());
m_buffer.write(data);
@@ -73,9 +72,9 @@ void BaseClientInterface::parseData(const QByteArray &data)
while (!m_buffer.atEnd()) {
QString parseError;
BaseMessage::parse(&m_buffer, parseError, m_currentMessage);
- qCDebug(LOGLSPCLIENTPARSE) << " complete: " << m_currentMessage.isComplete();
- qCDebug(LOGLSPCLIENTPARSE) << " length: " << m_currentMessage.contentLength;
- qCDebug(LOGLSPCLIENTPARSE) << " content: " << m_currentMessage.content;
+ qCDebug(parseLog) << " complete: " << m_currentMessage.isComplete();
+ qCDebug(parseLog) << " length: " << m_currentMessage.contentLength;
+ qCDebug(parseLog) << " content: " << m_currentMessage.content;
if (!parseError.isEmpty())
emit error(parseError);
if (!m_currentMessage.isComplete())
@@ -112,7 +111,7 @@ StdIOClientInterface::~StdIOClientInterface()
bool StdIOClientInterface::needsRestart(const StdIOSettings *settings) const
{
- return m_executable != settings->m_executable || m_arguments != settings->m_arguments;
+ return m_executable != settings->m_executable || m_arguments != settings->arguments();
}
bool StdIOClientInterface::start()
diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp
index 637a0efa28..4c5ec02a59 100644
--- a/src/plugins/languageclient/languageclientmanager.cpp
+++ b/src/plugins/languageclient/languageclientmanager.cpp
@@ -26,10 +26,12 @@
#include "languageclientmanager.h"
#include "languageclientutils.h"
+#include "languageclientplugin.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/find/searchresultwindow.h>
+#include <coreplugin/icore.h>
#include <languageserverprotocol/messages.h>
#include <projectexplorer/session.h>
#include <projectexplorer/project.h>
@@ -49,42 +51,51 @@ namespace LanguageClient {
static LanguageClientManager *managerInstance = nullptr;
-LanguageClientManager::LanguageClientManager()
+LanguageClientManager::LanguageClientManager(QObject *parent)
+ : QObject (parent)
{
+ using namespace Core;
+ using namespace ProjectExplorer;
JsonRpcMessageHandler::registerMessageProvider<PublishDiagnosticsNotification>();
JsonRpcMessageHandler::registerMessageProvider<ApplyWorkspaceEditRequest>();
JsonRpcMessageHandler::registerMessageProvider<LogMessageNotification>();
JsonRpcMessageHandler::registerMessageProvider<ShowMessageRequest>();
JsonRpcMessageHandler::registerMessageProvider<ShowMessageNotification>();
- managerInstance = this;
+ JsonRpcMessageHandler::registerMessageProvider<WorkSpaceFolderRequest>();
+ connect(EditorManager::instance(), &EditorManager::editorOpened,
+ this, &LanguageClientManager::editorOpened);
+ connect(EditorManager::instance(), &EditorManager::documentOpened,
+ this, &LanguageClientManager::documentOpened);
+ connect(EditorManager::instance(), &EditorManager::documentClosed,
+ this, &LanguageClientManager::documentClosed);
+ connect(EditorManager::instance(), &EditorManager::saved,
+ this, &LanguageClientManager::documentContentsSaved);
+ connect(EditorManager::instance(), &EditorManager::aboutToSave,
+ this, &LanguageClientManager::documentWillSave);
+ connect(SessionManager::instance(), &SessionManager::projectAdded,
+ this, &LanguageClientManager::projectAdded);
+ connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ this, &LanguageClientManager::projectRemoved);
}
LanguageClientManager::~LanguageClientManager()
{
QTC_ASSERT(m_clients.isEmpty(), qDeleteAll(m_clients));
+ qDeleteAll(m_currentSettings);
+ managerInstance = nullptr;
}
void LanguageClientManager::init()
{
- using namespace Core;
- using namespace ProjectExplorer;
- QTC_ASSERT(managerInstance, return);
- connect(EditorManager::instance(), &EditorManager::editorOpened,
- managerInstance, &LanguageClientManager::editorOpened);
- connect(EditorManager::instance(), &EditorManager::editorsClosed,
- managerInstance, &LanguageClientManager::editorsClosed);
- connect(EditorManager::instance(), &EditorManager::saved,
- managerInstance, &LanguageClientManager::documentContentsSaved);
- connect(EditorManager::instance(), &EditorManager::aboutToSave,
- managerInstance, &LanguageClientManager::documentWillSave);
- connect(SessionManager::instance(), &SessionManager::projectAdded,
- managerInstance, &LanguageClientManager::projectAdded);
- connect(SessionManager::instance(), &SessionManager::projectRemoved,
- managerInstance, &LanguageClientManager::projectRemoved);
+ if (managerInstance)
+ return;
+ QTC_ASSERT(LanguageClientPlugin::instance(), return);
+ managerInstance = new LanguageClientManager(LanguageClientPlugin::instance());
}
void LanguageClientManager::startClient(Client *client)
{
+ QTC_ASSERT(managerInstance, return);
QTC_ASSERT(client, return);
if (managerInstance->m_shuttingDown) {
managerInstance->clientFinished(client);
@@ -99,20 +110,40 @@ void LanguageClientManager::startClient(Client *client)
client->initialize();
else
managerInstance->clientFinished(client);
+
+ connect(client,
+ &Client::initialized,
+ &managerInstance->m_currentDocumentLocatorFilter,
+ &DocumentLocatorFilter::updateCurrentClient);
+}
+
+void LanguageClientManager::startClient(BaseSettings *setting, ProjectExplorer::Project *project)
+{
+ QTC_ASSERT(managerInstance, return);
+ QTC_ASSERT(setting, return);
+ QTC_ASSERT(setting->isValid(), return);
+ Client *client = setting->createClient();
+ QTC_ASSERT(client, return);
+ client->setCurrentProject(project);
+ startClient(client);
+ managerInstance->m_clientsForSetting[setting->m_id].append(client);
}
QVector<Client *> LanguageClientManager::clients()
{
+ QTC_ASSERT(managerInstance, return {});
return managerInstance->m_clients;
}
void LanguageClientManager::addExclusiveRequest(const MessageId &id, Client *client)
{
+ QTC_ASSERT(managerInstance, return);
managerInstance->m_exclusiveRequests[id] << client;
}
void LanguageClientManager::reportFinished(const MessageId &id, Client *byClient)
{
+ QTC_ASSERT(managerInstance, return);
for (Client *client : managerInstance->m_exclusiveRequests[id]) {
if (client != byClient)
client->cancelRequest(id);
@@ -120,11 +151,24 @@ void LanguageClientManager::reportFinished(const MessageId &id, Client *byClient
managerInstance->m_exclusiveRequests.remove(id);
}
+void LanguageClientManager::shutdownClient(Client *client)
+{
+ if (!client)
+ return;
+ if (client->reachable())
+ client->shutdown();
+ else if (client->state() != Client::Shutdown && client->state() != Client::ShutdownRequested)
+ deleteClient(client);
+}
+
void LanguageClientManager::deleteClient(Client *client)
{
+ QTC_ASSERT(managerInstance, return);
QTC_ASSERT(client, return);
client->disconnect();
managerInstance->m_clients.removeAll(client);
+ for (QVector<Client *> &clients : managerInstance->m_clientsForSetting)
+ clients.removeAll(client);
if (managerInstance->m_shuttingDown)
delete client;
else
@@ -133,15 +177,12 @@ void LanguageClientManager::deleteClient(Client *client)
void LanguageClientManager::shutdown()
{
+ QTC_ASSERT(managerInstance, return);
if (managerInstance->m_shuttingDown)
return;
managerInstance->m_shuttingDown = true;
- for (auto interface : managerInstance->m_clients) {
- if (interface->reachable())
- interface->shutdown();
- else
- deleteClient(interface);
- }
+ for (Client *client : managerInstance->m_clients)
+ shutdownClient(client);
QTimer::singleShot(3000, managerInstance, [](){
for (auto interface : managerInstance->m_clients)
deleteClient(interface);
@@ -157,12 +198,107 @@ LanguageClientManager *LanguageClientManager::instance()
QList<Client *> LanguageClientManager::clientsSupportingDocument(
const TextEditor::TextDocument *doc)
{
+ QTC_ASSERT(managerInstance, return {});
QTC_ASSERT(doc, return {};);
return Utils::filtered(managerInstance->reachableClients(), [doc](Client *client) {
return client->isSupportedDocument(doc);
}).toList();
}
+void LanguageClientManager::applySettings()
+{
+ QTC_ASSERT(managerInstance, return);
+ qDeleteAll(managerInstance->m_currentSettings);
+ managerInstance->m_currentSettings = Utils::transform(LanguageClientSettings::currentPageSettings(),
+ [](BaseSettings *settings) {
+ return settings->copy();
+ });
+ LanguageClientSettings::toSettings(Core::ICore::settings(), managerInstance->m_currentSettings);
+
+ const QList<BaseSettings *> restarts = Utils::filtered(managerInstance->m_currentSettings,
+ [](BaseSettings *settings) {
+ return settings->needsRestart();
+ });
+
+ for (BaseSettings *setting : restarts) {
+ for (Client *client : clientForSetting(setting))
+ shutdownClient(client);
+ if (!setting->isValid() || !setting->m_enabled)
+ continue;
+ switch (setting->m_startBehavior) {
+ case BaseSettings::AlwaysOn:
+ startClient(setting);
+ break;
+ case BaseSettings::RequiresFile:
+ if (Utils::anyOf(Core::DocumentModel::openedDocuments(),
+ [filter = setting->m_languageFilter](Core::IDocument *doc) {
+ return filter.isSupported(doc);
+ })) {
+ startClient(setting);
+ }
+ break;
+ case BaseSettings::RequiresProject: {
+ for (Core::IDocument *doc : Core::DocumentModel::openedDocuments()) {
+ if (setting->m_languageFilter.isSupported(doc)) {
+ const Utils::FilePath filePath = doc->filePath();
+ for (ProjectExplorer::Project *project :
+ ProjectExplorer::SessionManager::projects()) {
+ if (project->isKnownFile(filePath))
+ startClient(setting, project);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+QList<BaseSettings *> LanguageClientManager::currentSettings()
+{
+ QTC_ASSERT(managerInstance, return {});
+ return managerInstance->m_currentSettings;
+}
+
+QVector<Client *> LanguageClientManager::clientForSetting(const BaseSettings *setting)
+{
+ QTC_ASSERT(managerInstance, return {});
+ auto instance = managerInstance;
+ return instance->m_clientsForSetting.value(setting->m_id);
+}
+
+const BaseSettings *LanguageClientManager::settingForClient(Client *client)
+{
+ QTC_ASSERT(managerInstance, return nullptr);
+ for (const QString &id : managerInstance->m_clientsForSetting.keys()) {
+ for (const Client *settingClient : managerInstance->m_clientsForSetting[id]) {
+ if (settingClient == client) {
+ return Utils::findOrDefault(managerInstance->m_currentSettings,
+ [id](BaseSettings *setting) {
+ return setting->m_id == id;
+ });
+ }
+ }
+ }
+ return nullptr;
+}
+
+Client *LanguageClientManager::clientForEditor(Core::IEditor *iEditor)
+{
+ QTC_ASSERT(managerInstance, return nullptr);
+
+ auto editor = qobject_cast<TextEditor::BaseTextEditor *>(iEditor);
+ if (!editor)
+ return nullptr;
+
+ return Utils::findOrDefault(managerInstance->reachableClients(),
+ [doc = editor->textDocument()](Client *client) {
+ return client->documentOpen(doc);
+ });
+}
+
QVector<Client *> LanguageClientManager::reachableClients()
{
return Utils::filtered(m_clients, &Client::reachable);
@@ -188,7 +324,7 @@ void LanguageClientManager::clientFinished(Client *client)
client->disconnect(this);
client->log(tr("Unexpectedly finished. Restarting in %1 seconds.").arg(restartTimeoutS),
Core::MessageManager::Flash);
- QTimer::singleShot(restartTimeoutS * 1000, client, [client](){ startClient(client); });
+ QTimer::singleShot(restartTimeoutS * 1000, client, [client]() { startClient(client); });
} else {
if (unexpectedFinish && !m_shuttingDown)
client->log(tr("Unexpectedly finished."), Core::MessageManager::Flash);
@@ -198,23 +334,19 @@ void LanguageClientManager::clientFinished(Client *client)
}
}
-void LanguageClientManager::editorOpened(Core::IEditor *iEditor)
+void LanguageClientManager::editorOpened(Core::IEditor *editor)
{
using namespace TextEditor;
- Core::IDocument *document = iEditor->document();
- for (Client *interface : reachableClients())
- interface->openDocument(document);
-
- if (BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(iEditor)) {
- if (TextEditorWidget *widget = editor->editorWidget()) {
+ if (auto *textEditor = qobject_cast<BaseTextEditor *>(editor)) {
+ if (TextEditorWidget *widget = textEditor->editorWidget()) {
connect(widget, &TextEditorWidget::requestLinkAt, this,
- [this, filePath = document->filePath()]
+ [this, filePath = editor->document()->filePath()]
(const QTextCursor &cursor, Utils::ProcessLinkCallback &callback) {
findLinkAt(filePath, cursor, callback);
});
connect(widget, &TextEditorWidget::requestUsages, this,
- [this, filePath = document->filePath()]
- (const QTextCursor &cursor) {
+ [this, filePath = editor->document()->filePath()]
+ (const QTextCursor &cursor){
findUsages(filePath, cursor);
});
connect(widget, &TextEditorWidget::cursorPositionChanged, this, [this, widget](){
@@ -229,20 +361,52 @@ void LanguageClientManager::editorOpened(Core::IEditor *iEditor)
}
});
});
+ updateEditorToolBar(editor);
+ for (auto client : reachableClients())
+ widget->addHoverHandler(client->hoverHandler());
}
}
}
-void LanguageClientManager::editorsClosed(const QList<Core::IEditor *> &editors)
+void LanguageClientManager::documentOpened(Core::IDocument *document)
{
- for (auto iEditor : editors) {
- if (auto editor = qobject_cast<TextEditor::BaseTextEditor *>(iEditor)) {
- const DidCloseTextDocumentParams params(TextDocumentIdentifier(
- DocumentUri::fromFileName(editor->document()->filePath())));
- for (Client *interface : reachableClients())
- interface->closeDocument(params);
+ // check whether we have to start servers for this document
+ for (BaseSettings *setting : LanguageClientSettings::currentPageSettings()) {
+ const QVector<Client *> clients = clientForSetting(setting);
+ if (setting->isValid() && setting->m_enabled
+ && setting->m_languageFilter.isSupported(document)) {
+ if (setting->m_startBehavior == BaseSettings::RequiresProject) {
+ const Utils::FilePath filePath = document->filePath();
+ for (ProjectExplorer::Project *project :
+ ProjectExplorer::SessionManager::projects()) {
+ // check whether file is part of this project
+ if (!project->isKnownFile(filePath))
+ continue;
+
+ // check whether we already have a client running for this project
+ if (Utils::findOrDefault(clients,
+ [project](QPointer<Client> client) {
+ return client->project() == project;
+ })) {
+ continue;
+ }
+ startClient(setting, project);
+ }
+ } else if (setting->m_startBehavior == BaseSettings::RequiresFile && clients.isEmpty()) {
+ startClient(setting);
+ }
}
}
+ for (Client *interface : reachableClients())
+ interface->openDocument(document);
+}
+
+void LanguageClientManager::documentClosed(Core::IDocument *document)
+{
+ const DidCloseTextDocumentParams params(
+ TextDocumentIdentifier(DocumentUri::fromFileName(document->filePath())));
+ for (Client *interface : reachableClients())
+ interface->closeDocument(params);
}
void LanguageClientManager::documentContentsSaved(Core::IDocument *document)
@@ -257,7 +421,7 @@ void LanguageClientManager::documentWillSave(Core::IDocument *document)
interface->documentContentsSaved(document);
}
-void LanguageClientManager::findLinkAt(const Utils::FileName &filePath,
+void LanguageClientManager::findLinkAt(const Utils::FilePath &filePath,
const QTextCursor &cursor,
Utils::ProcessLinkCallback callback)
{
@@ -321,7 +485,7 @@ QList<Core::SearchResultItem> generateSearchResultItems(const LanguageClientArra
return result;
}
-void LanguageClientManager::findUsages(const Utils::FileName &filePath, const QTextCursor &cursor)
+void LanguageClientManager::findUsages(const Utils::FilePath &filePath, const QTextCursor &cursor)
{
const DocumentUri uri = DocumentUri::fromFileName(filePath);
const TextDocumentIdentifier document(uri);
@@ -357,13 +521,31 @@ void LanguageClientManager::findUsages(const Utils::FileName &filePath, const QT
void LanguageClientManager::projectAdded(ProjectExplorer::Project *project)
{
+ for (BaseSettings *setting : m_currentSettings) {
+ if (setting->isValid()
+ && setting->m_enabled
+ && setting->m_startBehavior == BaseSettings::RequiresProject) {
+ if (Utils::findOrDefault(clientForSetting(setting),
+ [project](QPointer<Client> client) {
+ return client->project() == project;
+ })
+ == nullptr) {
+ for (Core::IDocument *doc : Core::DocumentModel::openedDocuments()) {
+ if (setting->m_languageFilter.isSupported(doc)) {
+ if (project->isKnownFile(doc->filePath()))
+ startClient(setting, project);
+ }
+ }
+ }
+ }
+ }
for (Client *interface : reachableClients())
interface->projectOpened(project);
}
void LanguageClientManager::projectRemoved(ProjectExplorer::Project *project)
{
- for (Client *interface : reachableClients())
+ for (Client *interface : m_clients)
interface->projectClosed(project);
}
diff --git a/src/plugins/languageclient/languageclientmanager.h b/src/plugins/languageclient/languageclientmanager.h
index 6adf1bd773..6be720697f 100644
--- a/src/plugins/languageclient/languageclientmanager.h
+++ b/src/plugins/languageclient/languageclientmanager.h
@@ -27,6 +27,7 @@
#include "client.h"
#include "languageclientsettings.h"
+#include "locatorfilter.h"
#include <coreplugin/id.h>
@@ -56,11 +57,13 @@ public:
static void init();
static void startClient(Client *client);
+ static void startClient(BaseSettings *setting, ProjectExplorer::Project *project = nullptr);
static QVector<Client *> clients();
static void addExclusiveRequest(const LanguageServerProtocol::MessageId &id, Client *client);
static void reportFinished(const LanguageServerProtocol::MessageId &id, Client *byClient);
+ static void shutdownClient(Client *client);
static void deleteClient(Client *client);
static void shutdown();
@@ -69,19 +72,26 @@ public:
static QList<Client *> clientsSupportingDocument(const TextEditor::TextDocument *doc);
+ static void applySettings();
+ static QList<BaseSettings *> currentSettings();
+ static QVector<Client *> clientForSetting(const BaseSettings *setting);
+ static const BaseSettings *settingForClient(Client *setting);
+ static Client *clientForEditor(Core::IEditor *editor);
+
signals:
void shutdownFinished();
private:
- LanguageClientManager();
+ LanguageClientManager(QObject *parent);
void editorOpened(Core::IEditor *editor);
- void editorsClosed(const QList<Core::IEditor *> &editors);
+ void documentOpened(Core::IDocument *document);
+ void documentClosed(Core::IDocument *document);
void documentContentsSaved(Core::IDocument *document);
void documentWillSave(Core::IDocument *document);
- void findLinkAt(const Utils::FileName &filePath, const QTextCursor &cursor,
+ void findLinkAt(const Utils::FilePath &filePath, const QTextCursor &cursor,
Utils::ProcessLinkCallback callback);
- void findUsages(const Utils::FileName &filePath, const QTextCursor &cursor);
+ void findUsages(const Utils::FilePath &filePath, const QTextCursor &cursor);
void projectAdded(ProjectExplorer::Project *project);
void projectRemoved(ProjectExplorer::Project *project);
@@ -93,8 +103,12 @@ private:
bool m_shuttingDown = false;
QVector<Client *> m_clients;
+ QList<BaseSettings *> m_currentSettings; // owned
+ QMap<QString, QVector<Client *>> m_clientsForSetting;
QHash<LanguageServerProtocol::MessageId, QList<Client *>> m_exclusiveRequests;
-
- friend class LanguageClientPlugin;
+ DocumentLocatorFilter m_currentDocumentLocatorFilter;
+ WorkspaceLocatorFilter m_workspaceLocatorFilter;
+ WorkspaceClassLocatorFilter m_workspaceClassLocatorFilter;
+ WorkspaceMethodLocatorFilter m_workspaceMethodLocatorFilter;
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientoutline.cpp b/src/plugins/languageclient/languageclientoutline.cpp
index 3c3a1aa1b1..8a15a9e0b8 100644
--- a/src/plugins/languageclient/languageclientoutline.cpp
+++ b/src/plugins/languageclient/languageclientoutline.cpp
@@ -26,6 +26,7 @@
#include "languageclientoutline.h"
#include "languageclientmanager.h"
+#include "languageclientutils.h"
#include <coreplugin/find/itemviewfind.h>
#include <coreplugin/editormanager/ieditor.h>
@@ -43,46 +44,6 @@ using namespace LanguageServerProtocol;
namespace LanguageClient {
-static const QIcon symbolIcon(int type)
-{
- using namespace Utils::CodeModelIcon;
- static QMap<SymbolKind, QIcon> icons;
- if (type < int(SymbolKind::FirstSymbolKind) || type > int(SymbolKind::LastSymbolKind))
- return {};
- auto kind = static_cast<SymbolKind>(type);
- if (icons.contains(kind)) {
- switch (kind) {
- case SymbolKind::File: icons[kind] = Utils::Icons::NEWFILE.icon(); break;
- case SymbolKind::Module: icons[kind] = iconForType(Namespace); break;
- case SymbolKind::Namespace: icons[kind] = iconForType(Namespace); break;
- case SymbolKind::Package: icons[kind] = iconForType(Namespace); break;
- case SymbolKind::Class: icons[kind] = iconForType(Class); break;
- case SymbolKind::Method: icons[kind] = iconForType(FuncPublic); break;
- case SymbolKind::Property: icons[kind] = iconForType(Property); break;
- case SymbolKind::Field: icons[kind] = iconForType(VarPublic); break;
- case SymbolKind::Constructor: icons[kind] = iconForType(Class); break;
- case SymbolKind::Enum: icons[kind] = iconForType(Enum); break;
- case SymbolKind::Interface: icons[kind] = iconForType(Class); break;
- case SymbolKind::Function: icons[kind] = iconForType(FuncPublic); break;
- case SymbolKind::Variable: icons[kind] = iconForType(VarPublic); break;
- case SymbolKind::Constant: icons[kind] = iconForType(VarPublic); break;
- case SymbolKind::String: icons[kind] = iconForType(VarPublic); break;
- case SymbolKind::Number: icons[kind] = iconForType(VarPublic); break;
- case SymbolKind::Boolean: icons[kind] = iconForType(VarPublic); break;
- case SymbolKind::Array: icons[kind] = iconForType(VarPublic); break;
- case SymbolKind::Object: icons[kind] = iconForType(Class); break;
- case SymbolKind::Key: icons[kind] = iconForType(Keyword); break;
- case SymbolKind::Null: icons[kind] = iconForType(Keyword); break;
- case SymbolKind::EnumMember: icons[kind] = iconForType(Enumerator); break;
- case SymbolKind::Struct: icons[kind] = iconForType(Struct); break;
- case SymbolKind::Event: icons[kind] = iconForType(FuncPublic); break;
- case SymbolKind::Operator: icons[kind] = iconForType(FuncPublic); break;
- case SymbolKind::TypeParameter: icons[kind] = iconForType(VarPublic); break;
- }
- }
- return icons[kind];
-}
-
class LanguageClientOutlineItem : public Utils::TypedTreeItem<LanguageClientOutlineItem>
{
public:
@@ -155,7 +116,7 @@ public:
void setCursorSynchronization(bool syncWithCursor) override;
private:
- void handleResponse(const LanguageServerProtocol::DocumentSymbolsRequest::Response &response);
+ void handleResponse(const DocumentUri &uri, const DocumentSymbolsResult &response);
void updateTextCursor(const QModelIndex &proxyIndex);
void updateSelectionInTree(const QTextCursor &currentCursor);
void onItemActivated(const QModelIndex &index);
@@ -164,6 +125,7 @@ private:
QPointer<TextEditor::BaseTextEditor> m_editor;
LanguageClientOutlineModel m_model;
Utils::TreeView m_view;
+ DocumentUri m_uri;
bool m_sync = false;
};
@@ -172,23 +134,24 @@ LanguageClientOutlineWidget::LanguageClientOutlineWidget(Client *client,
: m_client(client)
, m_editor(editor)
, m_view(this)
+ , m_uri(DocumentUri::fromFileName(editor->textDocument()->filePath()))
{
- const DocumentSymbolParams params(
- TextDocumentIdentifier(
- DocumentUri::fromFileName(editor->textDocument()->filePath())));
- DocumentSymbolsRequest request(params);
- request.setResponseCallback([self = QPointer<LanguageClientOutlineWidget>(this)]
- (const DocumentSymbolsRequest::Response &response){
- if (self)
- self->handleResponse(response);
+ connect(client->documentSymbolCache(),
+ &DocumentSymbolCache::gotSymbols,
+ this,
+ &LanguageClientOutlineWidget::handleResponse);
+ connect(editor->textDocument(), &TextEditor::TextDocument::contentsChanged, this, [this]() {
+ if (m_client)
+ m_client->documentSymbolCache()->requestSymbols(m_uri);
});
+ client->documentSymbolCache()->requestSymbols(m_uri);
+
auto *layout = new QVBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(Core::ItemViewFind::createSearchableWrapper(&m_view));
setLayout(layout);
- client->sendContent(request);
m_view.setModel(&m_model);
m_view.setHeaderHidden(true);
connect(&m_view, &QAbstractItemView::activated,
@@ -212,20 +175,17 @@ void LanguageClientOutlineWidget::setCursorSynchronization(bool syncWithCursor)
updateSelectionInTree(m_editor->textCursor());
}
-void LanguageClientOutlineWidget::handleResponse(const DocumentSymbolsRequest::Response &response)
+void LanguageClientOutlineWidget::handleResponse(const DocumentUri &uri,
+ const DocumentSymbolsResult &result)
{
- if (Utils::optional<DocumentSymbolsRequest::Response::Error> error = response.error()) {
- if (m_client)
- m_client->log(error.value());
- }
- if (Utils::optional<DocumentSymbolsResult> result = response.result()) {
- if (Utils::holds_alternative<QList<SymbolInformation>>(result.value()))
- m_model.setInfo(Utils::get<QList<SymbolInformation>>(result.value()));
- else if (Utils::holds_alternative<QList<DocumentSymbol>>(result.value()))
- m_model.setInfo(Utils::get<QList<DocumentSymbol>>(result.value()));
- else
- m_model.clear();
- }
+ if (uri != m_uri)
+ return;
+ if (Utils::holds_alternative<QList<SymbolInformation>>(result))
+ m_model.setInfo(Utils::get<QList<SymbolInformation>>(result));
+ else if (Utils::holds_alternative<QList<DocumentSymbol>>(result))
+ m_model.setInfo(Utils::get<QList<DocumentSymbol>>(result));
+ else
+ m_model.clear();
}
void LanguageClientOutlineWidget::updateTextCursor(const QModelIndex &proxyIndex)
@@ -245,6 +205,8 @@ void LanguageClientOutlineWidget::updateSelectionInTree(const QTextCursor &curre
selection.select(m_model.indexForItem(item), m_model.indexForItem(item));
});
m_view.selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
+ if (!selection.isEmpty())
+ m_view.scrollTo(selection.indexes().first());
}
void LanguageClientOutlineWidget::onItemActivated(const QModelIndex &index)
diff --git a/src/plugins/languageclient/languageclientplugin.cpp b/src/plugins/languageclient/languageclientplugin.cpp
index 1d64097e62..31643474f6 100644
--- a/src/plugins/languageclient/languageclientplugin.cpp
+++ b/src/plugins/languageclient/languageclientplugin.cpp
@@ -25,18 +25,37 @@
#include "languageclientplugin.h"
+#include "languageclientmanager.h"
+
#include "client.h"
namespace LanguageClient {
+static LanguageClientPlugin *m_instance = nullptr;
+
+LanguageClientPlugin::LanguageClientPlugin()
+{
+ m_instance = this;
+}
+
+LanguageClientPlugin::~LanguageClientPlugin()
+{
+ m_instance = nullptr;
+}
+
+LanguageClientPlugin *LanguageClientPlugin::instance()
+{
+ return m_instance;
+}
+
bool LanguageClientPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorString*/)
{
+ LanguageClientManager::init();
return true;
}
void LanguageClientPlugin::extensionsInitialized()
{
- LanguageClientManager::init();
LanguageClientSettings::init();
}
@@ -45,6 +64,8 @@ ExtensionSystem::IPlugin::ShutdownFlag LanguageClientPlugin::aboutToShutdown()
LanguageClientManager::shutdown();
if (LanguageClientManager::clients().isEmpty())
return ExtensionSystem::IPlugin::SynchronousShutdown;
+ QTC_ASSERT(LanguageClientManager::instance(),
+ return ExtensionSystem::IPlugin::SynchronousShutdown);
connect(LanguageClientManager::instance(), &LanguageClientManager::shutdownFinished,
this, &ExtensionSystem::IPlugin::asynchronousShutdownFinished);
return ExtensionSystem::IPlugin::AsynchronousShutdown;
diff --git a/src/plugins/languageclient/languageclientplugin.h b/src/plugins/languageclient/languageclientplugin.h
index 2cff52cd7b..8fbf66de03 100644
--- a/src/plugins/languageclient/languageclientplugin.h
+++ b/src/plugins/languageclient/languageclientplugin.h
@@ -38,7 +38,10 @@ class LanguageClientPlugin : public ExtensionSystem::IPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "LanguageClient.json")
public:
- LanguageClientPlugin() = default;
+ LanguageClientPlugin();
+ ~LanguageClientPlugin() override;
+
+ static LanguageClientPlugin *instance();
// IPlugin interface
private:
@@ -47,7 +50,6 @@ private:
ShutdownFlag aboutToShutdown() override;
private:
- LanguageClientManager m_clientManager;
LanguageClientOutlineWidgetFactory m_outlineFactory;
};
diff --git a/src/plugins/languageclient/languageclientquickfix.cpp b/src/plugins/languageclient/languageclientquickfix.cpp
index def01b17d8..70db31b871 100644
--- a/src/plugins/languageclient/languageclientquickfix.cpp
+++ b/src/plugins/languageclient/languageclientquickfix.cpp
@@ -111,7 +111,7 @@ IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInte
cursor.select(QTextCursor::LineUnderCursor);
Range range(cursor);
params.setRange(range);
- auto uri = DocumentUri::fromFileName(Utils::FileName::fromString(interface->fileName()));
+ auto uri = DocumentUri::fromFileName(Utils::FilePath::fromString(interface->fileName()));
params.setTextDocument(uri);
CodeActionParams::CodeActionContext context;
context.setDiagnostics(m_client->diagnosticsAt(uri, range));
diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp
index 74ca22d5f2..a1b8db2169 100644
--- a/src/plugins/languageclient/languageclientsettings.cpp
+++ b/src/plugins/languageclient/languageclientsettings.cpp
@@ -30,7 +30,12 @@
#include "languageclient_global.h"
#include "languageclientinterface.h"
+#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/icore.h>
+#include <coreplugin/idocument.h>
+#include <coreplugin/variablechooser.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
#include <utils/algorithm.h>
#include <utils/delegates.h>
#include <utils/fancylineedit.h>
@@ -38,7 +43,6 @@
#include <utils/jsontreeitem.h>
#include <QBoxLayout>
-#include <QCheckBox>
#include <QComboBox>
#include <QCompleter>
#include <QCoreApplication>
@@ -56,7 +60,9 @@
#include <QTreeView>
constexpr char nameKey[] = "name";
+constexpr char idKey[] = "id";
constexpr char enabledKey[] = "enabled";
+constexpr char startupBehaviorKey[] = "startupBehavior";
constexpr char mimeTypeKey[] = "mimeType";
constexpr char filePatternKey[] = "filePattern";
constexpr char executableKey[] = "executable";
@@ -80,15 +86,15 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role) final;
Qt::ItemFlags flags(const QModelIndex &index) const final;
- void reset(const QList<StdIOSettings *> &settings);
- QList<StdIOSettings *> settings() const { return m_settings; }
- QList<StdIOSettings *> removed() const { return m_removed; }
- StdIOSettings *settingForIndex(const QModelIndex &index) const;
- QModelIndex indexForSetting(StdIOSettings *setting) const;
+ void reset(const QList<BaseSettings *> &settings);
+ QList<BaseSettings *> settings() const { return m_settings; }
+ QList<BaseSettings *> removed() const { return m_removed; }
+ BaseSettings *settingForIndex(const QModelIndex &index) const;
+ QModelIndex indexForSetting(BaseSettings *setting) const;
private:
- QList<StdIOSettings *> m_settings; // owned
- QList<StdIOSettings *> m_removed;
+ QList<BaseSettings *> m_settings; // owned
+ QList<BaseSettings *> m_removed;
};
class LanguageClientSettingsPageWidget : public QWidget
@@ -104,7 +110,7 @@ private:
LanguageClientSettingsModel &m_settings;
QTreeView *m_view = nullptr;
struct CurrentSettings {
- StdIOSettings *setting = nullptr;
+ BaseSettings *setting = nullptr;
QWidget *widget = nullptr;
} m_currentSettings;
@@ -126,9 +132,10 @@ public:
void apply() override;
void finish() override;
+ QList<BaseSettings *> settings() const;
+
private:
LanguageClientSettingsModel m_model;
- QList<StdIOSettings *> m_settings; // owned
QPointer<LanguageClientSettingsPageWidget> m_widget;
};
@@ -207,6 +214,7 @@ void LanguageClientSettingsPageWidget::addItem()
{
const int row = m_settings.rowCount();
m_settings.insertRows(row);
+ m_view->setCurrentIndex(m_settings.index(row));
}
void LanguageClientSettingsPageWidget::deleteItem()
@@ -218,7 +226,7 @@ void LanguageClientSettingsPageWidget::deleteItem()
LanguageClientSettingsPage::LanguageClientSettingsPage()
{
- setId("LanguageClient.General");
+ setId(Constants::LANGUAGECLIENT_SETTINGS_PAGE);
setDisplayName(tr("General"));
setCategory(Constants::LANGUAGECLIENT_SETTINGS_CATEGORY);
setDisplayCategory(QCoreApplication::translate("LanguageClient",
@@ -231,7 +239,6 @@ LanguageClientSettingsPage::~LanguageClientSettingsPage()
{
if (m_widget)
delete m_widget;
- qDeleteAll(m_settings);
}
void LanguageClientSettingsPage::init()
@@ -250,44 +257,32 @@ QWidget *LanguageClientSettingsPage::widget()
void LanguageClientSettingsPage::apply()
{
- qDeleteAll(m_settings);
if (m_widget)
m_widget->applyCurrentSettings();
- m_settings = Utils::transform(m_model.settings(), [](const StdIOSettings *other){
- return dynamic_cast<StdIOSettings *>(other->copy());
- });
- LanguageClientSettings::toSettings(Core::ICore::settings(), m_settings);
-
- QList<StdIOSettings *> restarts = Utils::filtered(m_settings, &StdIOSettings::needsRestart);
- for (auto setting : restarts + m_model.removed()) {
- if (auto client = setting->m_client) {
- if (client->reachable())
- client->shutdown();
- else
- LanguageClientManager::deleteClient(client);
- }
- }
- for (StdIOSettings *setting : restarts) {
- if (setting && setting->isValid() && setting->m_enabled) {
- if (auto client = setting->createClient()) {
- setting->m_client = client;
- LanguageClientManager::startClient(client);
- }
- }
+ LanguageClientManager::applySettings();
+
+ for (BaseSettings *setting : m_model.removed()) {
+ for (Client *client : LanguageClientManager::clientForSetting(setting))
+ LanguageClientManager::shutdownClient(client);
}
if (m_widget) {
int row = m_widget->currentRow();
- m_model.reset(m_settings);
+ m_model.reset(LanguageClientManager::currentSettings());
m_widget->resetCurrentSettings(row);
} else {
- m_model.reset(m_settings);
+ m_model.reset(LanguageClientManager::currentSettings());
}
}
void LanguageClientSettingsPage::finish()
{
- m_model.reset(m_settings);
+ m_model.reset(LanguageClientManager::currentSettings());
+}
+
+QList<BaseSettings *> LanguageClientSettingsPage::settings() const
+{
+ return m_model.settings();
}
LanguageClientSettingsModel::~LanguageClientSettingsModel()
@@ -297,11 +292,11 @@ LanguageClientSettingsModel::~LanguageClientSettingsModel()
QVariant LanguageClientSettingsModel::data(const QModelIndex &index, int role) const
{
- StdIOSettings *setting = settingForIndex(index);
+ BaseSettings *setting = settingForIndex(index);
if (!setting)
return QVariant();
if (role == Qt::DisplayRole)
- return setting->m_name;
+ return Utils::globalMacroExpander()->expand(setting->m_name);
else if (role == Qt::CheckStateRole)
return setting->m_enabled ? Qt::Checked : Qt::Unchecked;
return QVariant();
@@ -332,7 +327,7 @@ bool LanguageClientSettingsModel::insertRows(int row, int count, const QModelInd
bool LanguageClientSettingsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
- StdIOSettings *setting = settingForIndex(index);
+ BaseSettings *setting = settingForIndex(index);
if (!setting || role != Qt::CheckStateRole)
return false;
@@ -348,26 +343,24 @@ Qt::ItemFlags LanguageClientSettingsModel::flags(const QModelIndex &/*index*/) c
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
-void LanguageClientSettingsModel::reset(const QList<StdIOSettings *> &settings)
+void LanguageClientSettingsModel::reset(const QList<BaseSettings *> &settings)
{
beginResetModel();
qDeleteAll(m_settings);
qDeleteAll(m_removed);
m_removed.clear();
- m_settings = Utils::transform(settings, [](const StdIOSettings *other){
- return dynamic_cast<StdIOSettings *>(other->copy());
- });
+ m_settings = Utils::transform(settings, [](const BaseSettings *other) { return other->copy(); });
endResetModel();
}
-StdIOSettings *LanguageClientSettingsModel::settingForIndex(const QModelIndex &index) const
+BaseSettings *LanguageClientSettingsModel::settingForIndex(const QModelIndex &index) const
{
if (!index.isValid() || index.row() >= m_settings.size())
return nullptr;
return m_settings[index.row()];
}
-QModelIndex LanguageClientSettingsModel::indexForSetting(StdIOSettings *setting) const
+QModelIndex LanguageClientSettingsModel::indexForSetting(BaseSettings *setting) const
{
const int index = m_settings.indexOf(setting);
return index < 0 ? QModelIndex() : createIndex(index, 0, setting);
@@ -378,6 +371,7 @@ void BaseSettings::applyFromSettingsWidget(QWidget *widget)
if (auto settingsWidget = qobject_cast<BaseSettingsWidget *>(widget)) {
m_name = settingsWidget->name();
m_languageFilter = settingsWidget->filter();
+ m_startBehavior = settingsWidget->startupBehavior();
}
}
@@ -388,7 +382,14 @@ QWidget *BaseSettings::createSettingsWidget(QWidget *parent) const
bool BaseSettings::needsRestart() const
{
- return m_client ? !m_enabled || m_client->needsRestart(this) : m_enabled;
+ const QVector<Client *> clients = LanguageClientManager::clientForSetting(this);
+ if (clients.isEmpty())
+ return m_enabled;
+ if (!m_enabled)
+ return true;
+ return Utils::anyOf(clients, [this](const Client *client) {
+ return client->needsRestart(this);
+ });
}
bool BaseSettings::isValid() const
@@ -396,23 +397,25 @@ bool BaseSettings::isValid() const
return !m_name.isEmpty();
}
-Client *BaseSettings::createClient() const
+Client *BaseSettings::createClient()
{
+ if (!isValid() || !m_enabled)
+ return nullptr;
BaseClientInterface *interface = createInterface();
- if (QTC_GUARD(interface)) {
- auto *client = new Client(interface);
- client->setName(m_name);
- client->setSupportedLanguage(m_languageFilter);
- return client;
- }
- return nullptr;
+ QTC_ASSERT(interface, return nullptr);
+ auto *client = new Client(interface);
+ client->setName(Utils::globalMacroExpander()->expand(m_name));
+ client->setSupportedLanguage(m_languageFilter);
+ return client;
}
QVariantMap BaseSettings::toMap() const
{
QVariantMap map;
map.insert(nameKey, m_name);
+ map.insert(idKey, m_id);
map.insert(enabledKey, m_enabled);
+ map.insert(startupBehaviorKey, m_startBehavior);
map.insert(mimeTypeKey, m_languageFilter.mimeTypes);
map.insert(filePatternKey, m_languageFilter.filePattern);
return map;
@@ -421,23 +424,31 @@ QVariantMap BaseSettings::toMap() const
void BaseSettings::fromMap(const QVariantMap &map)
{
m_name = map[nameKey].toString();
+ m_id = map.value(idKey, QUuid::createUuid().toString()).toString();
m_enabled = map[enabledKey].toBool();
+ m_startBehavior = BaseSettings::StartBehavior(
+ map.value(startupBehaviorKey, BaseSettings::RequiresFile).toInt());
m_languageFilter.mimeTypes = map[mimeTypeKey].toStringList();
m_languageFilter.filePattern = map[filePatternKey].toStringList();
}
-void LanguageClientSettings::init()
+static LanguageClientSettingsPage &settingsPage()
{
static LanguageClientSettingsPage settingsPage;
- settingsPage.init();
+ return settingsPage;
+}
+
+void LanguageClientSettings::init()
+{
+ settingsPage().init();
}
-QList<StdIOSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn)
+QList<BaseSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn)
{
settingsIn->beginGroup(settingsGroupKey);
auto variants = settingsIn->value(clientsKey).toList();
auto settings = Utils::transform(variants, [](const QVariant& var){
- auto settings = new StdIOSettings();
+ BaseSettings *settings = new StdIOSettings();
settings->fromMap(var.toMap());
return settings;
});
@@ -445,11 +456,17 @@ QList<StdIOSettings *> LanguageClientSettings::fromSettings(QSettings *settingsI
return settings;
}
-void LanguageClientSettings::toSettings(QSettings *settings, const QList<StdIOSettings *> &languageClientSettings)
+QList<BaseSettings *> LanguageClientSettings::currentPageSettings()
+{
+ return settingsPage().settings();
+}
+
+void LanguageClientSettings::toSettings(QSettings *settings,
+ const QList<BaseSettings *> &languageClientSettings)
{
settings->beginGroup(settingsGroupKey);
settings->setValue(clientsKey, Utils::transform(languageClientSettings,
- [](const StdIOSettings *setting){
+ [](const BaseSettings *setting){
return QVariant(setting->toMap());
}));
settings->endGroup();
@@ -473,11 +490,13 @@ bool StdIOSettings::needsRestart() const
{
if (BaseSettings::needsRestart())
return true;
- if (m_client.isNull())
- return false;
- if (auto stdIOInterface = qobject_cast<const StdIOClientInterface *>(m_client->clientInterface()))
- return stdIOInterface->needsRestart(this);
- return false;
+ return Utils::anyOf(LanguageClientManager::clientForSetting(this),
+ [this](QPointer<Client> client) {
+ if (auto stdIOInterface = qobject_cast<const StdIOClientInterface *>(
+ client->clientInterface()))
+ return stdIOInterface->needsRestart(this);
+ return false;
+ });
}
bool StdIOSettings::isValid() const
@@ -500,15 +519,39 @@ void StdIOSettings::fromMap(const QVariantMap &map)
m_arguments = map[argumentsKey].toString();
}
+QString StdIOSettings::arguments() const
+{
+ return Utils::globalMacroExpander()->expand(m_arguments);
+}
+
BaseClientInterface *StdIOSettings::createInterface() const
{
- return new StdIOClientInterface(m_executable, m_arguments);
+ return new StdIOClientInterface(m_executable, arguments());
}
-static QWidget *createCapabilitiesView(
- const LanguageServerProtocol::ServerCapabilities &capabilities)
+class JsonTreeItemDelegate : public QStyledItemDelegate
{
- auto root = new Utils::JsonTreeItem("Capabilities", QJsonValue(capabilities));
+public:
+ QString displayText(const QVariant &value, const QLocale &) const override
+ {
+ QString result = value.toString();
+ if (result.size() == 1) {
+ switch (result.at(0).toLatin1()) {
+ case '\n':
+ return QString("\\n");
+ case '\t':
+ return QString("\\t");
+ case '\r':
+ return QString("\\r");
+ }
+ }
+ return result;
+ }
+};
+
+static QWidget *createCapabilitiesView(const QJsonValue &capabilities)
+{
+ auto root = new Utils::JsonTreeItem("Capabilities", capabilities);
if (root->canFetchMore())
root->fetchMore();
@@ -520,19 +563,39 @@ static QWidget *createCapabilitiesView(
capabilitiesView->setModel(capabilitiesModel);
capabilitiesView->setAlternatingRowColors(true);
capabilitiesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+ capabilitiesView->setItemDelegate(new JsonTreeItemDelegate);
return capabilitiesView;
}
+static QString startupBehaviorString(BaseSettings::StartBehavior behavior)
+{
+ switch (behavior) {
+ case BaseSettings::AlwaysOn:
+ return QCoreApplication::translate("LanguageClient::BaseSettings", "Always On");
+ case BaseSettings::RequiresFile:
+ return QCoreApplication::translate("LanguageClient::BaseSettings", "Requires an Open File");
+ case BaseSettings::RequiresProject:
+ return QCoreApplication::translate("LanguageClient::BaseSettings",
+ "Start Server per Project");
+ default:
+ break;
+ }
+ return {};
+}
+
BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *parent)
: QWidget(parent)
, m_name(new QLineEdit(settings->m_name, this))
, m_mimeTypes(new QLabel(settings->m_languageFilter.mimeTypes.join(filterSeparator), this))
, m_filePattern(new QLineEdit(settings->m_languageFilter.filePattern.join(filterSeparator), this))
+ , m_startupBehavior(new QComboBox)
{
int row = 0;
auto *mainLayout = new QGridLayout;
mainLayout->addWidget(new QLabel(tr("Name:")), row, 0);
mainLayout->addWidget(m_name, row, 1);
+ auto chooser = new Core::VariableChooser(this);
+ chooser->addSupportedWidget(m_name);
mainLayout->addWidget(new QLabel(tr("Language:")), ++row, 0);
auto mimeLayout = new QHBoxLayout;
mimeLayout->addWidget(m_mimeTypes);
@@ -542,6 +605,12 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
mainLayout->addLayout(mimeLayout, row, 1);
m_filePattern->setPlaceholderText(tr("File pattern"));
mainLayout->addWidget(m_filePattern, ++row, 1);
+ mainLayout->addWidget(new QLabel(tr("Startup behavior:")), ++row, 0);
+ for (int behavior = 0; behavior < BaseSettings::LastSentinel ; ++behavior)
+ m_startupBehavior->addItem(startupBehaviorString(BaseSettings::StartBehavior(behavior)));
+ m_startupBehavior->setCurrentIndex(settings->m_startBehavior);
+ mainLayout->addWidget(m_startupBehavior, row, 1);
+
connect(addMimeTypeButton, &QPushButton::pressed,
this, &BaseSettingsWidget::showAddMimeTypeDialog);
@@ -551,9 +620,13 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
};
mainLayout->addWidget(new QLabel(tr("Capabilities:")), ++row, 0, Qt::AlignTop);
- if (Client *client = settings->m_client.data()) {
+ QVector<Client *> clients = LanguageClientManager::clientForSetting(settings);
+ if (clients.isEmpty()) {
+ mainLayout->addWidget(createInfoLabel());
+ } else { // TODO move the capabilities view into a new widget outside of the settings
+ Client *client = clients.first();
if (client->state() == Client::Initialized)
- mainLayout->addWidget(createCapabilitiesView(client->capabilities()));
+ mainLayout->addWidget(createCapabilitiesView(QJsonValue(client->capabilities())));
else
mainLayout->addWidget(createInfoLabel(), row, 1);
connect(client, &Client::finished, mainLayout, [mainLayout, row, createInfoLabel]() {
@@ -564,12 +637,9 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
[mainLayout, row](
const LanguageServerProtocol::ServerCapabilities &capabilities) {
delete mainLayout->itemAtPosition(row, 1)->widget();
- mainLayout->addWidget(createCapabilitiesView(capabilities), row, 1);
+ mainLayout->addWidget(createCapabilitiesView(QJsonValue(capabilities)), row, 1);
});
- } else {
- mainLayout->addWidget(createInfoLabel());
}
-
setLayout(mainLayout);
}
@@ -580,8 +650,13 @@ QString BaseSettingsWidget::name() const
LanguageFilter BaseSettingsWidget::filter() const
{
- return {m_mimeTypes->text().split(filterSeparator),
- m_filePattern->text().split(filterSeparator)};
+ return {m_mimeTypes->text().split(filterSeparator, QString::SkipEmptyParts),
+ m_filePattern->text().split(filterSeparator, QString::SkipEmptyParts)};
+}
+
+BaseSettings::StartBehavior BaseSettingsWidget::startupBehavior() const
+{
+ return BaseSettings::StartBehavior(m_startupBehavior->currentIndex());
}
class MimeTypeModel : public QStringListModel
@@ -692,6 +767,9 @@ StdIOSettingsWidget::StdIOSettingsWidget(const StdIOSettings *settings, QWidget
m_executable->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_executable->setPath(QDir::toNativeSeparators(settings->m_executable));
mainLayout->addWidget(m_arguments, baseRows + 1, 1);
+
+ auto chooser = new Core::VariableChooser(this);
+ chooser->addSupportedWidget(m_arguments);
}
QString StdIOSettingsWidget::executable() const
@@ -704,4 +782,23 @@ QString StdIOSettingsWidget::arguments() const
return m_arguments->text();
}
+bool LanguageFilter::isSupported(const Utils::FilePath &filePath, const QString &mimeType) const
+{
+ if (mimeTypes.contains(mimeType))
+ return true;
+ if (filePattern.isEmpty() && filePath.isEmpty())
+ return mimeTypes.isEmpty();
+ auto regexps = Utils::transform(filePattern, [](const QString &pattern){
+ return QRegExp(pattern, Utils::HostOsInfo::fileNameCaseSensitivity(), QRegExp::Wildcard);
+ });
+ return Utils::anyOf(regexps, [filePath](const QRegExp &reg){
+ return reg.exactMatch(filePath.toString()) || reg.exactMatch(filePath.fileName());
+ });
+}
+
+bool LanguageFilter::isSupported(const Core::IDocument *document) const
+{
+ return isSupported(document->filePath(), document->mimeType());
+}
+
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientsettings.h b/src/plugins/languageclient/languageclientsettings.h
index bdf54e6052..1036348cb7 100644
--- a/src/plugins/languageclient/languageclientsettings.h
+++ b/src/plugins/languageclient/languageclientsettings.h
@@ -30,14 +30,21 @@
#include <QAbstractItemModel>
#include <QLabel>
#include <QPointer>
+#include <QUuid>
#include <QWidget>
QT_BEGIN_NAMESPACE
-class QCheckBox;
+class QComboBox;
class QLineEdit;
QT_END_NAMESPACE
-namespace Utils { class PathChooser; }
+namespace Utils {
+class FilePath;
+class PathChooser;
+} // namespace Utils
+
+namespace Core { class IDocument; }
+namespace ProjectExplorer { class Project; }
namespace LanguageClient {
@@ -50,31 +57,36 @@ struct LanguageFilter
{
QStringList mimeTypes;
QStringList filePattern;
+ bool isSupported(const Utils::FilePath &filePath, const QString &mimeType) const;
+ bool isSupported(const Core::IDocument *document) const;
};
class BaseSettings
{
public:
BaseSettings() = default;
- BaseSettings(const QString &name, bool enabled, const LanguageFilter &filter)
- : m_name(name)
- , m_enabled(enabled)
- , m_languageFilter(filter)
- {}
virtual ~BaseSettings() = default;
+ enum StartBehavior {
+ AlwaysOn = 0,
+ RequiresFile,
+ RequiresProject,
+ LastSentinel
+ };
+
QString m_name = QString("New Language Server");
+ QString m_id = QUuid::createUuid().toString();
bool m_enabled = true;
+ StartBehavior m_startBehavior = RequiresFile;
LanguageFilter m_languageFilter;
- QPointer<Client> m_client; // not owned
virtual void applyFromSettingsWidget(QWidget *widget);
virtual QWidget *createSettingsWidget(QWidget *parent = nullptr) const;
virtual BaseSettings *copy() const { return new BaseSettings(*this); }
virtual bool needsRestart() const;
- virtual bool isValid() const ;
- Client *createClient() const;
+ virtual bool isValid() const;
+ Client *createClient();
virtual QVariantMap toMap() const;
virtual void fromMap(const QVariantMap &map);
@@ -85,19 +97,15 @@ protected:
BaseSettings(BaseSettings &&other) = default;
BaseSettings &operator=(const BaseSettings &other) = default;
BaseSettings &operator=(BaseSettings &&other) = default;
+
+private:
+ bool canStart(QList<const Core::IDocument *> documents) const;
};
class StdIOSettings : public BaseSettings
{
public:
StdIOSettings() = default;
- StdIOSettings(const QString &name, bool enabled, const LanguageFilter &filter,
- const QString &executable, const QString &arguments)
- : BaseSettings(name, enabled, filter)
- , m_executable(executable)
- , m_arguments(arguments)
- {}
-
~StdIOSettings() override = default;
QString m_executable;
@@ -110,6 +118,7 @@ public:
bool isValid() const override;
QVariantMap toMap() const override;
void fromMap(const QVariantMap &map) override;
+ QString arguments() const;
protected:
BaseClientInterface *createInterface() const override;
@@ -124,8 +133,9 @@ class LanguageClientSettings
{
public:
static void init();
- static QList<StdIOSettings *> fromSettings(QSettings *settings);
- static void toSettings(QSettings *settings, const QList<StdIOSettings *> &languageClientSettings);
+ static QList<BaseSettings *> fromSettings(QSettings *settings);
+ static QList<BaseSettings *> currentPageSettings();
+ static void toSettings(QSettings *settings, const QList<BaseSettings *> &languageClientSettings);
};
class BaseSettingsWidget : public QWidget
@@ -137,6 +147,9 @@ public:
QString name() const;
LanguageFilter filter() const;
+ BaseSettings::StartBehavior startupBehavior() const;
+ bool alwaysOn() const;
+ bool requiresProject() const;
private:
void showAddMimeTypeDialog();
@@ -144,6 +157,7 @@ private:
QLineEdit *m_name = nullptr;
QLabel *m_mimeTypes = nullptr;
QLineEdit *m_filePattern = nullptr;
+ QComboBox *m_startupBehavior = nullptr;
static constexpr char filterSeparator = ';';
};
diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp
index 7a28c5e3a9..317af50f74 100644
--- a/src/plugins/languageclient/languageclientutils.cpp
+++ b/src/plugins/languageclient/languageclientutils.cpp
@@ -26,17 +26,23 @@
#include "languageclientutils.h"
#include "client.h"
+#include "languageclient_global.h"
+#include "languageclientmanager.h"
#include <coreplugin/editormanager/documentmodel.h>
+#include <coreplugin/icore.h>
#include <texteditor/codeassist/textdocumentmanipulatorinterface.h>
#include <texteditor/refactoringchanges.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include <utils/textutils.h>
+#include <utils/utilsicons.h>
#include <QFile>
#include <QTextDocument>
+#include <QToolBar>
+#include <QToolButton>
using namespace LanguageServerProtocol;
using namespace Utils;
@@ -185,4 +191,84 @@ void updateCodeActionRefactoringMarker(Client *client,
}
}
+void updateEditorToolBar(Core::IEditor *editor)
+{
+ auto *textEditor = qobject_cast<BaseTextEditor *>(editor);
+ if (!textEditor)
+ return;
+ TextEditorWidget *widget = textEditor->editorWidget();
+ if (!widget)
+ return;
+
+ const Core::IDocument *document = editor->document();
+ QStringList clientsWithDoc;
+ for (auto client : LanguageClientManager::clients()) {
+ if (client->documentOpen(document))
+ clientsWithDoc << client->name();
+ }
+
+ static QMap<QWidget *, QAction *> actions;
+
+ if (actions.contains(widget)) {
+ auto action = actions[widget];
+ if (clientsWithDoc.isEmpty()) {
+ widget->toolBar()->removeAction(action);
+ actions.remove(widget);
+ } else {
+ action->setText(clientsWithDoc.join(';'));
+ }
+ } else if (!clientsWithDoc.isEmpty()) {
+ const QIcon icon
+ = Utils::Icon({{":/languageclient/images/languageclient.png",
+ Utils::Theme::IconsBaseColor}})
+ .icon();
+ actions[widget] = widget->toolBar()->addAction(icon, clientsWithDoc.join(';'), []() {
+ Core::ICore::showOptionsDialog(Constants::LANGUAGECLIENT_SETTINGS_PAGE);
+ });
+ QObject::connect(widget, &QWidget::destroyed, [widget]() {
+ actions.remove(widget);
+ });
+ }
+}
+
+const QIcon symbolIcon(int type)
+{
+ using namespace Utils::CodeModelIcon;
+ static QMap<SymbolKind, QIcon> icons;
+ if (type < int(SymbolKind::FirstSymbolKind) || type > int(SymbolKind::LastSymbolKind))
+ return {};
+ auto kind = static_cast<SymbolKind>(type);
+ if (!icons.contains(kind)) {
+ switch (kind) {
+ case SymbolKind::File: icons[kind] = Utils::Icons::NEWFILE.icon(); break;
+ case SymbolKind::Module: icons[kind] = iconForType(Namespace); break;
+ case SymbolKind::Namespace: icons[kind] = iconForType(Namespace); break;
+ case SymbolKind::Package: icons[kind] = iconForType(Namespace); break;
+ case SymbolKind::Class: icons[kind] = iconForType(Class); break;
+ case SymbolKind::Method: icons[kind] = iconForType(FuncPublic); break;
+ case SymbolKind::Property: icons[kind] = iconForType(Property); break;
+ case SymbolKind::Field: icons[kind] = iconForType(VarPublic); break;
+ case SymbolKind::Constructor: icons[kind] = iconForType(Class); break;
+ case SymbolKind::Enum: icons[kind] = iconForType(Enum); break;
+ case SymbolKind::Interface: icons[kind] = iconForType(Class); break;
+ case SymbolKind::Function: icons[kind] = iconForType(FuncPublic); break;
+ case SymbolKind::Variable: icons[kind] = iconForType(VarPublic); break;
+ case SymbolKind::Constant: icons[kind] = iconForType(VarPublic); break;
+ case SymbolKind::String: icons[kind] = iconForType(VarPublic); break;
+ case SymbolKind::Number: icons[kind] = iconForType(VarPublic); break;
+ case SymbolKind::Boolean: icons[kind] = iconForType(VarPublic); break;
+ case SymbolKind::Array: icons[kind] = iconForType(VarPublic); break;
+ case SymbolKind::Object: icons[kind] = iconForType(Class); break;
+ case SymbolKind::Key: icons[kind] = iconForType(Keyword); break;
+ case SymbolKind::Null: icons[kind] = iconForType(Keyword); break;
+ case SymbolKind::EnumMember: icons[kind] = iconForType(Enumerator); break;
+ case SymbolKind::Struct: icons[kind] = iconForType(Struct); break;
+ case SymbolKind::Event: icons[kind] = iconForType(FuncPublic); break;
+ case SymbolKind::Operator: icons[kind] = iconForType(FuncPublic); break;
+ case SymbolKind::TypeParameter: icons[kind] = iconForType(VarPublic); break;
+ }
+ }
+ return icons[kind];
+}
+
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientutils.h b/src/plugins/languageclient/languageclientutils.h
index f07b6e18bf..04925e6bf1 100644
--- a/src/plugins/languageclient/languageclientutils.h
+++ b/src/plugins/languageclient/languageclientutils.h
@@ -30,6 +30,8 @@
#include <texteditor/refactoroverlay.h>
+namespace Core { class IEditor; }
+
namespace TextEditor {
class TextDocument;
class TextDocumentManipulatorInterface;
@@ -48,5 +50,7 @@ void applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator,
void updateCodeActionRefactoringMarker(Client *client,
const LanguageServerProtocol::CodeAction &action,
const LanguageServerProtocol::DocumentUri &uri);
+void updateEditorToolBar(Core::IEditor *editor);
+const QIcon symbolIcon(int type);
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/locatorfilter.cpp b/src/plugins/languageclient/locatorfilter.cpp
new file mode 100644
index 0000000000..973e098274
--- /dev/null
+++ b/src/plugins/languageclient/locatorfilter.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** 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 "locatorfilter.h"
+
+#include "languageclient_global.h"
+#include "languageclientmanager.h"
+#include "languageclientutils.h"
+
+#include <coreplugin/editormanager/editormanager.h>
+#include <languageserverprotocol/servercapabilities.h>
+#include <texteditor/textdocument.h>
+#include <texteditor/texteditor.h>
+#include <utils/fuzzymatcher.h>
+#include <utils/linecolumn.h>
+
+#include <QFutureWatcher>
+#include <QRegularExpression>
+
+using namespace LanguageServerProtocol;
+
+namespace LanguageClient {
+
+DocumentLocatorFilter::DocumentLocatorFilter()
+{
+ setId(Constants::LANGUAGECLIENT_DOCUMENT_FILTER_ID);
+ setDisplayName(Constants::LANGUAGECLIENT_DOCUMENT_FILTER_DISPLAY_NAME);
+ setShortcutString(".");
+ setIncludedByDefault(false);
+ setPriority(ILocatorFilter::Low);
+ connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
+ this, &DocumentLocatorFilter::updateCurrentClient);
+}
+
+void DocumentLocatorFilter::updateCurrentClient()
+{
+ Core::IEditor *editor = Core::EditorManager::currentEditor();
+ resetSymbols();
+ disconnect(m_resetSymbolsConnection);
+
+ if (Client *client = LanguageClientManager::clientForEditor(editor)) {
+ if (m_symbolCache != client->documentSymbolCache()) {
+ disconnect(m_updateSymbolsConnection);
+ m_symbolCache = client->documentSymbolCache();
+ m_updateSymbolsConnection = connect(m_symbolCache,
+ &DocumentSymbolCache::gotSymbols,
+ this,
+ &DocumentLocatorFilter::updateSymbols);
+ }
+ m_resetSymbolsConnection = connect(editor->document(),
+ &Core::IDocument::contentsChanged,
+ this,
+ &DocumentLocatorFilter::resetSymbols);
+ m_currentUri = DocumentUri::fromFileName(editor->document()->filePath());
+ } else {
+ disconnect(m_updateSymbolsConnection);
+ m_symbolCache.clear();
+ m_currentUri.clear();
+ }
+}
+
+void DocumentLocatorFilter::updateSymbols(const DocumentUri &uri,
+ const DocumentSymbolsResult &symbols)
+{
+ if (uri != m_currentUri)
+ return;
+ QMutexLocker locker(&m_mutex);
+ m_currentSymbols = symbols;
+ emit symbolsUpToDate({});
+}
+
+void DocumentLocatorFilter::resetSymbols()
+{
+ QMutexLocker locker(&m_mutex);
+ m_currentSymbols.reset();
+}
+
+Core::LocatorFilterEntry generateLocatorEntry(const SymbolInformation &info,
+ Core::ILocatorFilter *filter)
+{
+ Core::LocatorFilterEntry entry;
+ entry.filter = filter;
+ entry.displayName = info.name();
+ if (Utils::optional<QString> container = info.containerName())
+ entry.extraInfo = container.value_or(QString());
+ entry.displayIcon = symbolIcon(info.kind());
+ entry.internalData = QVariant::fromValue(info.location().toLink());
+ return entry;
+}
+
+Core::LocatorFilterEntry generateLocatorEntry(const DocumentSymbol &info,
+ Core::ILocatorFilter *filter)
+{
+ Core::LocatorFilterEntry entry;
+ entry.filter = filter;
+ entry.displayName = info.name();
+ if (Utils::optional<QString> detail = info.detail())
+ entry.extraInfo = detail.value_or(QString());
+ entry.displayIcon = symbolIcon(info.kind());
+ const Position &pos = info.range().start();
+ entry.internalData = QVariant::fromValue(Utils::LineColumn(pos.line(), pos.character()));
+ return entry;
+}
+
+template<class T>
+QList<Core::LocatorFilterEntry> DocumentLocatorFilter::generateEntries(const QList<T> &list,
+ const QString &filter)
+{
+ QList<Core::LocatorFilterEntry> entries;
+ FuzzyMatcher::CaseSensitivity caseSensitivity
+ = ILocatorFilter::caseSensitivity(filter) == Qt::CaseSensitive
+ ? FuzzyMatcher::CaseSensitivity::CaseSensitive
+ : FuzzyMatcher::CaseSensitivity::CaseInsensitive;
+ const QRegularExpression regexp = FuzzyMatcher::createRegExp(filter, caseSensitivity);
+ if (!regexp.isValid())
+ return entries;
+
+ for (const T &item : list) {
+ QRegularExpressionMatch match = regexp.match(item.name());
+ if (match.hasMatch())
+ entries << generateLocatorEntry(item, this);
+ }
+ return entries;
+}
+
+void DocumentLocatorFilter::prepareSearch(const QString &/*entry*/)
+{
+ QMutexLocker locker(&m_mutex);
+ if (m_symbolCache && !m_currentSymbols.has_value()) {
+ locker.unlock();
+ m_symbolCache->requestSymbols(m_currentUri);
+ }
+}
+
+QList<Core::LocatorFilterEntry> DocumentLocatorFilter::matchesFor(
+ QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
+{
+ if (!m_symbolCache)
+ return {};
+ QMutexLocker locker(&m_mutex);
+ if (!m_currentSymbols.has_value()) {
+ QEventLoop loop;
+ connect(this, &DocumentLocatorFilter::symbolsUpToDate, &loop, [&]() { loop.exit(1); });
+ QFutureWatcher<Core::LocatorFilterEntry> watcher;
+ watcher.setFuture(future.future());
+ connect(&watcher,
+ &QFutureWatcher<Core::LocatorFilterEntry>::canceled,
+ &loop,
+ &QEventLoop::quit);
+ locker.unlock();
+ if (!loop.exec())
+ return {};
+ locker.relock();
+ }
+
+ QTC_ASSERT(m_currentSymbols.has_value(), return {});
+
+ if (auto list = Utils::get_if<QList<DocumentSymbol>>(&m_currentSymbols.value()))
+ return generateEntries(*list, entry);
+ else if (auto list = Utils::get_if<QList<SymbolInformation>>(&m_currentSymbols.value()))
+ return generateEntries(*list, entry);
+
+ return {};
+}
+
+void DocumentLocatorFilter::accept(Core::LocatorFilterEntry selection,
+ QString * /*newText*/,
+ int * /*selectionStart*/,
+ int * /*selectionLength*/) const
+{
+ if (selection.internalData.canConvert<Utils::LineColumn>()) {
+ auto lineColumn = qvariant_cast<Utils::LineColumn>(selection.internalData);
+ Core::EditorManager::openEditorAt(m_currentUri.toFileName().toString(),
+ lineColumn.line + 1,
+ lineColumn.column);
+ } else if (selection.internalData.canConvert<Utils::Link>()) {
+ auto link = qvariant_cast<Utils::Link>(selection.internalData);
+ Core::EditorManager::openEditorAt(link.targetFileName, link.targetLine, link.targetColumn);
+ }
+}
+
+void DocumentLocatorFilter::refresh(QFutureInterface<void> & /*future*/) {}
+
+WorkspaceLocatorFilter::WorkspaceLocatorFilter()
+ : WorkspaceLocatorFilter(QVector<SymbolKind>())
+{}
+
+WorkspaceLocatorFilter::WorkspaceLocatorFilter(const QVector<SymbolKind> &filter)
+ : m_filterKinds(filter)
+{
+ setId(Constants::LANGUAGECLIENT_WORKSPACE_FILTER_ID);
+ setDisplayName(Constants::LANGUAGECLIENT_WORKSPACE_FILTER_DISPLAY_NAME);
+ setShortcutString(":");
+ setIncludedByDefault(false);
+ setPriority(ILocatorFilter::Low);
+}
+
+void WorkspaceLocatorFilter::prepareSearch(const QString &entry)
+{
+ m_pendingRequests.clear();
+ m_results.clear();
+
+ WorkspaceSymbolParams params;
+ params.setQuery(entry);
+
+ QMutexLocker locker(&m_mutex);
+ for (auto client : Utils::filtered(LanguageClientManager::clients(), &Client::reachable)) {
+ if (client->capabilities().workspaceSymbolProvider().value_or(false)) {
+ WorkspaceSymbolRequest request(params);
+ request.setResponseCallback(
+ [this, client](const WorkspaceSymbolRequest::Response &response) {
+ handleResponse(client, response);
+ });
+ m_pendingRequests[client] = request.id();
+ client->sendContent(request);
+ }
+ }
+}
+
+QList<Core::LocatorFilterEntry> WorkspaceLocatorFilter::matchesFor(
+ QFutureInterface<Core::LocatorFilterEntry> &future, const QString & /*entry*/)
+{
+ QMutexLocker locker(&m_mutex);
+ if (!m_pendingRequests.isEmpty()) {
+ QEventLoop loop;
+ connect(this, &WorkspaceLocatorFilter::allRequestsFinished, &loop, [&]() { loop.exit(1); });
+ QFutureWatcher<Core::LocatorFilterEntry> watcher;
+ watcher.setFuture(future.future());
+ connect(&watcher,
+ &QFutureWatcher<Core::LocatorFilterEntry>::canceled,
+ &loop,
+ &QEventLoop::quit);
+ locker.unlock();
+ if (!loop.exec())
+ return {};
+
+ locker.relock();
+ }
+
+
+ if (!m_filterKinds.isEmpty()) {
+ m_results = Utils::filtered(m_results, [&](const SymbolInformation &info) {
+ return m_filterKinds.contains(SymbolKind(info.kind()));
+ });
+ }
+ return Utils::transform(m_results,
+ [this](const SymbolInformation &info) {
+ return generateLocatorEntry(info, this);
+ })
+ .toList();
+}
+
+void WorkspaceLocatorFilter::accept(Core::LocatorFilterEntry selection,
+ QString * /*newText*/,
+ int * /*selectionStart*/,
+ int * /*selectionLength*/) const
+{
+ if (selection.internalData.canConvert<Utils::Link>()) {
+ auto link = qvariant_cast<Utils::Link>(selection.internalData);
+ Core::EditorManager::openEditorAt(link.targetFileName, link.targetLine, link.targetColumn);
+ }
+}
+
+void WorkspaceLocatorFilter::refresh(QFutureInterface<void> & /*future*/) {}
+
+void WorkspaceLocatorFilter::handleResponse(Client *client,
+ const WorkspaceSymbolRequest::Response &response)
+{
+ QMutexLocker locker(&m_mutex);
+ m_pendingRequests.remove(client);
+ auto result = response.result().value_or(LanguageClientArray<SymbolInformation>());
+ if (!result.isNull())
+ m_results.append(result.toList().toVector());
+ if (m_pendingRequests.isEmpty())
+ emit allRequestsFinished(QPrivateSignal());
+}
+
+WorkspaceClassLocatorFilter::WorkspaceClassLocatorFilter()
+ : WorkspaceLocatorFilter({SymbolKind::Class, SymbolKind::Struct})
+{
+ setId(Constants::LANGUAGECLIENT_WORKSPACE_CLASS_FILTER_ID);
+ setDisplayName(Constants::LANGUAGECLIENT_WORKSPACE_CLASS_FILTER_DISPLAY_NAME);
+ setShortcutString("c");
+}
+
+WorkspaceMethodLocatorFilter::WorkspaceMethodLocatorFilter()
+ : WorkspaceLocatorFilter({SymbolKind::Method, SymbolKind::Function, SymbolKind::Constructor})
+{
+ setId(Constants::LANGUAGECLIENT_WORKSPACE_METHOD_FILTER_ID);
+ setDisplayName(Constants::LANGUAGECLIENT_WORKSPACE_METHOD_FILTER_DISPLAY_NAME);
+ setShortcutString("m");
+}
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/locatorfilter.h b/src/plugins/languageclient/locatorfilter.h
new file mode 100644
index 0000000000..a3aa9cd597
--- /dev/null
+++ b/src/plugins/languageclient/locatorfilter.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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 "client.h"
+
+#include <coreplugin/locator/ilocatorfilter.h>
+#include <languageserverprotocol/lsptypes.h>
+#include <languageserverprotocol/languagefeatures.h>
+#include <languageserverprotocol/workspace.h>
+
+namespace Core { class IEditor; }
+
+namespace LanguageClient {
+
+class DocumentLocatorFilter : public Core::ILocatorFilter
+{
+ Q_OBJECT
+public:
+ DocumentLocatorFilter();
+
+ void updateCurrentClient();
+ void prepareSearch(const QString &entry) override;
+ QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
+ const QString &entry) override;
+ void accept(Core::LocatorFilterEntry selection,
+ QString *newText,
+ int *selectionStart,
+ int *selectionLength) const override;
+ void refresh(QFutureInterface<void> &future) override;
+
+signals:
+ void symbolsUpToDate(QPrivateSignal);
+
+protected:
+ QPointer<DocumentSymbolCache> m_symbolCache;
+ LanguageServerProtocol::DocumentUri m_currentUri;
+
+private:
+ void updateSymbols(const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::DocumentSymbolsResult &symbols);
+ void resetSymbols();
+
+ template<class T>
+ QList<Core::LocatorFilterEntry> generateEntries(const QList<T> &list, const QString &filter);
+
+ QMutex m_mutex;
+ QMetaObject::Connection m_updateSymbolsConnection;
+ QMetaObject::Connection m_resetSymbolsConnection;
+ Utils::optional<LanguageServerProtocol::DocumentSymbolsResult> m_currentSymbols;
+};
+
+class WorkspaceLocatorFilter : public Core::ILocatorFilter
+{
+ Q_OBJECT
+public:
+ WorkspaceLocatorFilter();
+
+ void prepareSearch(const QString &entry) override;
+ QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
+ const QString &entry) override;
+ void accept(Core::LocatorFilterEntry selection,
+ QString *newText,
+ int *selectionStart,
+ int *selectionLength) const override;
+ void refresh(QFutureInterface<void> &future) override;
+
+signals:
+ void allRequestsFinished(QPrivateSignal);
+
+protected:
+ explicit WorkspaceLocatorFilter(const QVector<LanguageServerProtocol::SymbolKind> &filter);
+
+private:
+ void handleResponse(Client *client,
+ const LanguageServerProtocol::WorkspaceSymbolRequest::Response &response);
+
+ QMutex m_mutex;
+ QMap<Client *, LanguageServerProtocol::MessageId> m_pendingRequests;
+ QVector<LanguageServerProtocol::SymbolInformation> m_results;
+ QVector<LanguageServerProtocol::SymbolKind> m_filterKinds;
+};
+
+class WorkspaceClassLocatorFilter : public WorkspaceLocatorFilter
+{
+public:
+ WorkspaceClassLocatorFilter();
+};
+
+class WorkspaceMethodLocatorFilter : public WorkspaceLocatorFilter
+{
+public:
+ WorkspaceMethodLocatorFilter();
+};
+
+} // namespace LanguageClient
diff --git a/src/plugins/macros/CMakeLists.txt b/src/plugins/macros/CMakeLists.txt
new file mode 100644
index 0000000000..544b16c5dd
--- /dev/null
+++ b/src/plugins/macros/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_qtc_plugin(Macros
+ PLUGIN_DEPENDS Core TextEditor
+ SOURCES
+ actionmacrohandler.cpp actionmacrohandler.h
+ findmacrohandler.cpp findmacrohandler.h
+ imacrohandler.cpp imacrohandler.h
+ macro.cpp macro.h
+ macroevent.cpp macroevent.h
+ macrolocatorfilter.cpp macrolocatorfilter.h
+ macromanager.cpp macromanager.h
+ macrooptionspage.cpp macrooptionspage.h
+ macrooptionswidget.cpp macrooptionswidget.h macrooptionswidget.ui
+ macros.qrc
+ macrosconstants.h
+ macrosplugin.cpp macrosplugin.h
+ macrotextfind.cpp macrotextfind.h
+ savedialog.cpp savedialog.h savedialog.ui
+ texteditormacrohandler.cpp texteditormacrohandler.h
+)
diff --git a/src/plugins/macros/macrolocatorfilter.cpp b/src/plugins/macros/macrolocatorfilter.cpp
index 0296e4fe08..9c45c461fd 100644
--- a/src/plugins/macros/macrolocatorfilter.cpp
+++ b/src/plugins/macros/macrolocatorfilter.cpp
@@ -37,8 +37,8 @@
using namespace Macros;
using namespace Macros::Internal;
-MacroLocatorFilter::MacroLocatorFilter(QObject *parent)
- : Core::ILocatorFilter(parent), m_icon(QPixmap(":/macros/images/macro.png"))
+MacroLocatorFilter::MacroLocatorFilter()
+ : m_icon(QPixmap(":/macros/images/macro.png"))
{
setId("Macros");
setDisplayName(tr("Text Editing Macros"));
diff --git a/src/plugins/macros/macrolocatorfilter.h b/src/plugins/macros/macrolocatorfilter.h
index 78bf5ae938..784c217258 100644
--- a/src/plugins/macros/macrolocatorfilter.h
+++ b/src/plugins/macros/macrolocatorfilter.h
@@ -37,7 +37,7 @@ class MacroLocatorFilter : public Core::ILocatorFilter
Q_OBJECT
public:
- explicit MacroLocatorFilter(QObject *parent);
+ MacroLocatorFilter();
~MacroLocatorFilter() override;
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
diff --git a/src/plugins/macros/macromanager.cpp b/src/plugins/macros/macromanager.cpp
index acea717722..7767e1d161 100644
--- a/src/plugins/macros/macromanager.cpp
+++ b/src/plugins/macros/macromanager.cpp
@@ -57,7 +57,8 @@
#include <QFileDialog>
#include <QMessageBox>
-using namespace Macros::Internal;
+namespace Macros {
+namespace Internal {
/*!
\namespace Macros
@@ -88,7 +89,7 @@ using namespace Macros::Internal;
the action id passed to the ActionManager.
*/
-class MacroManager::MacroManagerPrivate
+class MacroManagerPrivate
{
public:
MacroManagerPrivate(MacroManager *qq);
@@ -114,7 +115,7 @@ public:
void showSaveDialog();
};
-MacroManager::MacroManagerPrivate::MacroManagerPrivate(MacroManager *qq):
+MacroManagerPrivate::MacroManagerPrivate(MacroManager *qq):
q(qq)
{
// Load existing macros
@@ -125,7 +126,7 @@ MacroManager::MacroManagerPrivate::MacroManagerPrivate(MacroManager *qq):
findHandler = new FindMacroHandler;
}
-void MacroManager::MacroManagerPrivate::initialize()
+void MacroManagerPrivate::initialize()
{
macros.clear();
QDir dir(q->macrosDirectory());
@@ -148,7 +149,7 @@ static Core::Id makeId(const QString &name)
return Core::Id(Macros::Constants::PREFIX_MACRO).withSuffix(name);
}
-void MacroManager::MacroManagerPrivate::addMacro(Macro *macro)
+void MacroManagerPrivate::addMacro(Macro *macro)
{
// Add sortcut
Core::Context context(TextEditor::Constants::C_TEXTEDITOR);
@@ -156,7 +157,7 @@ void MacroManager::MacroManagerPrivate::addMacro(Macro *macro)
Core::Command *command = Core::ActionManager::registerAction(
action, makeId(macro->displayName()), context);
command->setAttribute(Core::Command::CA_UpdateText);
- connect(action, &QAction::triggered, q, [this, macro]() {
+ QObject::connect(action, &QAction::triggered, q, [this, macro]() {
q->executeMacro(macro->displayName());
});
@@ -165,7 +166,7 @@ void MacroManager::MacroManagerPrivate::addMacro(Macro *macro)
actions[macro->displayName()] = action;
}
-void MacroManager::MacroManagerPrivate::removeMacro(const QString &name)
+void MacroManagerPrivate::removeMacro(const QString &name)
{
if (!macros.contains(name))
return;
@@ -181,7 +182,7 @@ void MacroManager::MacroManagerPrivate::removeMacro(const QString &name)
delete macro;
}
-void MacroManager::MacroManagerPrivate::changeMacroDescription(Macro *macro, const QString &description)
+void MacroManagerPrivate::changeMacroDescription(Macro *macro, const QString &description)
{
if (!macro->load())
return;
@@ -193,7 +194,7 @@ void MacroManager::MacroManagerPrivate::changeMacroDescription(Macro *macro, con
action->setText(description);
}
-bool MacroManager::MacroManagerPrivate::executeMacro(Macro *macro)
+bool MacroManagerPrivate::executeMacro(Macro *macro)
{
bool error = !macro->load();
foreach (const MacroEvent &macroEvent, macro->events()) {
@@ -210,8 +211,8 @@ bool MacroManager::MacroManagerPrivate::executeMacro(Macro *macro)
if (error) {
QMessageBox::warning(Core::ICore::mainWindow(),
- tr("Playing Macro"),
- tr("An error occurred while replaying the macro, execution stopped."));
+ MacroManager::tr("Playing Macro"),
+ MacroManager::tr("An error occurred while replaying the macro, execution stopped."));
}
// Set the focus back to the editor
@@ -222,7 +223,7 @@ bool MacroManager::MacroManagerPrivate::executeMacro(Macro *macro)
return !error;
}
-void MacroManager::MacroManagerPrivate::showSaveDialog()
+void MacroManagerPrivate::showSaveDialog()
{
QWidget *mainWindow = Core::ICore::mainWindow();
SaveDialog dialog(mainWindow);
@@ -241,10 +242,9 @@ void MacroManager::MacroManagerPrivate::showSaveDialog()
// ---------- MacroManager ------------
-MacroManager *MacroManager::m_instance = nullptr;
+MacroManager *m_instance = nullptr;
-MacroManager::MacroManager(QObject *parent) :
- QObject(parent),
+MacroManager::MacroManager() :
d(new MacroManagerPrivate(this))
{
m_instance = this;
@@ -393,3 +393,6 @@ QString MacroManager::macrosDirectory()
return path;
return QString();
}
+
+} // Internal
+} // Macros
diff --git a/src/plugins/macros/macromanager.h b/src/plugins/macros/macromanager.h
index d2b876300f..e0e197a361 100644
--- a/src/plugins/macros/macromanager.h
+++ b/src/plugins/macros/macromanager.h
@@ -34,12 +34,15 @@ namespace Internal {
class IMacroHandler;
class Macro;
class MacroOptionsWidget;
-class MacrosPlugin;
class MacroManager : public QObject
{
Q_OBJECT
+
public:
+ MacroManager();
+ ~MacroManager() override;
+
static MacroManager *instance();
static const QMap<QString, Macro *> &macros();
@@ -61,15 +64,7 @@ protected:
void changeMacro(const QString &name, const QString &description);
private:
- explicit MacroManager(QObject *parent = nullptr);
- ~MacroManager() override;
-
- static MacroManager *m_instance;
-
- class MacroManagerPrivate;
- MacroManagerPrivate* d;
-
- friend class Internal::MacrosPlugin;
+ class MacroManagerPrivate *d;
};
} // namespace Internal
diff --git a/src/plugins/macros/macrooptionspage.cpp b/src/plugins/macros/macrooptionspage.cpp
index 1cc8ec9875..25ce616fea 100644
--- a/src/plugins/macros/macrooptionspage.cpp
+++ b/src/plugins/macros/macrooptionspage.cpp
@@ -39,8 +39,7 @@ using namespace Macros;
using namespace Macros::Internal;
-MacroOptionsPage::MacroOptionsPage(QObject *parent)
- : Core::IOptionsPage(parent)
+MacroOptionsPage::MacroOptionsPage()
{
setId(Constants::M_OPTIONS_PAGE);
setDisplayName(QCoreApplication::translate("Macros", Constants::M_OPTIONS_TR_PAGE));
diff --git a/src/plugins/macros/macrooptionspage.h b/src/plugins/macros/macrooptionspage.h
index 846e700df1..eaa3c93d17 100644
--- a/src/plugins/macros/macrooptionspage.h
+++ b/src/plugins/macros/macrooptionspage.h
@@ -39,7 +39,7 @@ class MacroOptionsPage : public Core::IOptionsPage
Q_OBJECT
public:
- MacroOptionsPage(QObject *parent = nullptr);
+ MacroOptionsPage();
// IOptionsPage implementation
QWidget *widget() override;
diff --git a/src/plugins/macros/macrooptionswidget.h b/src/plugins/macros/macrooptionswidget.h
index bb8a5101d5..ed7255f1b0 100644
--- a/src/plugins/macros/macrooptionswidget.h
+++ b/src/plugins/macros/macrooptionswidget.h
@@ -38,7 +38,6 @@ QT_END_NAMESPACE
namespace Macros {
namespace Internal {
-
namespace Ui { class MacroOptionsWidget; }
class MacroOptionsWidget : public QWidget {
diff --git a/src/plugins/macros/macrosplugin.cpp b/src/plugins/macros/macrosplugin.cpp
index c56520d9cf..4dbc46905e 100644
--- a/src/plugins/macros/macrosplugin.cpp
+++ b/src/plugins/macros/macrosplugin.cpp
@@ -40,17 +40,25 @@
#include <coreplugin/id.h>
#include <coreplugin/icontext.h>
-#include <QtPlugin>
#include <QSettings>
#include <QAction>
#include <QKeySequence>
#include <QMenu>
-using namespace Macros::Internal;
+namespace Macros {
+namespace Internal {
+
+class MacrosPluginPrivate
+{
+public:
+ MacroManager macroManager;
+ MacroOptionsPage optionsPage;
+ MacroLocatorFilter locatorFilter;
+};
MacrosPlugin::~MacrosPlugin()
{
- delete m_macroManager;
+ delete d;
}
bool MacrosPlugin::initialize(const QStringList &arguments, QString *errorMessage)
@@ -58,11 +66,9 @@ bool MacrosPlugin::initialize(const QStringList &arguments, QString *errorMessag
Q_UNUSED(arguments);
Q_UNUSED(errorMessage);
- new MacroOptionsPage(this);
- new MacroLocatorFilter(this);
+ d = new MacrosPluginPrivate;
Core::Context textContext(TextEditor::Constants::C_TEXTEDITOR);
- m_macroManager = new MacroManager(this);
// Menus
Core::ActionContainer *mtools = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
@@ -76,30 +82,30 @@ bool MacrosPlugin::initialize(const QStringList &arguments, QString *errorMessag
Core::Command *command = Core::ActionManager::registerAction(startMacro, Constants::START_MACRO, textContext);
command->setDefaultKeySequence(QKeySequence(Core::useMacShortcuts ? tr("Ctrl+[") : tr("Alt+[")));
mmacrotools->addAction(command);
- connect(startMacro, &QAction::triggered, m_macroManager, &MacroManager::startMacro);
+ connect(startMacro, &QAction::triggered, &d->macroManager, &MacroManager::startMacro);
QAction *endMacro = new QAction(tr("Stop Recording Macro"), this);
endMacro->setEnabled(false);
command = Core::ActionManager::registerAction(endMacro, Constants::END_MACRO);
command->setDefaultKeySequence(QKeySequence(Core::useMacShortcuts ? tr("Ctrl+]") : tr("Alt+]")));
mmacrotools->addAction(command);
- connect(endMacro, &QAction::triggered, m_macroManager, &MacroManager::endMacro);
+ connect(endMacro, &QAction::triggered, &d->macroManager, &MacroManager::endMacro);
QAction *executeLastMacro = new QAction(tr("Play Last Macro"), this);
command = Core::ActionManager::registerAction(executeLastMacro, Constants::EXECUTE_LAST_MACRO, textContext);
command->setDefaultKeySequence(QKeySequence(Core::useMacShortcuts ? tr("Meta+R") : tr("Alt+R")));
mmacrotools->addAction(command);
- connect(executeLastMacro, &QAction::triggered, m_macroManager, &MacroManager::executeLastMacro);
+ connect(executeLastMacro, &QAction::triggered, &d->macroManager, &MacroManager::executeLastMacro);
QAction *saveLastMacro = new QAction(tr("Save Last Macro"), this);
saveLastMacro->setEnabled(false);
command = Core::ActionManager::registerAction(saveLastMacro, Constants::SAVE_LAST_MACRO, textContext);
mmacrotools->addAction(command);
- connect(saveLastMacro, &QAction::triggered, m_macroManager, &MacroManager::saveLastMacro);
+ connect(saveLastMacro, &QAction::triggered, &d->macroManager, &MacroManager::saveLastMacro);
return true;
}
-void MacrosPlugin::extensionsInitialized()
-{
-}
+
+} // Internal
+} // Macros
diff --git a/src/plugins/macros/macrosplugin.h b/src/plugins/macros/macrosplugin.h
index 02a2dd33da..f4339b9e4f 100644
--- a/src/plugins/macros/macrosplugin.h
+++ b/src/plugins/macros/macrosplugin.h
@@ -30,21 +30,19 @@
namespace Macros {
namespace Internal {
-class MacroManager;
-
class MacrosPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Macros.json")
public:
- ~MacrosPlugin() override;
+ ~MacrosPlugin() final;
- bool initialize(const QStringList &arguments, QString *errorMessage) override;
- void extensionsInitialized() override;
+ bool initialize(const QStringList &arguments, QString *errorMessage) final;
+ void extensionsInitialized() final {}
private:
- MacroManager *m_macroManager = nullptr;
+ class MacrosPluginPrivate *d = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/mercurial/CMakeLists.txt b/src/plugins/mercurial/CMakeLists.txt
new file mode 100644
index 0000000000..c0ea4343f2
--- /dev/null
+++ b/src/plugins/mercurial/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_qtc_plugin(Mercurial
+ PLUGIN_DEPENDS Core TextEditor VcsBase
+ SOURCES
+ annotationhighlighter.cpp annotationhighlighter.h
+ authenticationdialog.cpp authenticationdialog.h authenticationdialog.ui
+ commiteditor.cpp commiteditor.h
+ constants.h
+ mercurialclient.cpp mercurialclient.h
+ mercurialcommitpanel.ui
+ mercurialcommitwidget.cpp mercurialcommitwidget.h
+ mercurialcontrol.cpp mercurialcontrol.h
+ mercurialeditor.cpp mercurialeditor.h
+ mercurialplugin.cpp mercurialplugin.h
+ mercurialsettings.cpp mercurialsettings.h
+ optionspage.cpp optionspage.h optionspage.ui
+ revertdialog.cpp revertdialog.h revertdialog.ui
+ srcdestdialog.cpp srcdestdialog.h srcdestdialog.ui
+)
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index f311d824c3..7d9b8dd209 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -440,7 +440,7 @@ void MercurialClient::revertAll(const QString &workingDir, const QString &revisi
QStringList(extraOptions) << QLatin1String("--all"));
}
-bool MercurialClient::isVcsDirectory(const FileName &fileName) const
+bool MercurialClient::isVcsDirectory(const FilePath &fileName) const
{
return fileName.toFileInfo().isDir()
&& !fileName.fileName().compare(Constants::MERCURIALREPO, HostOsInfo::fileNameCaseSensitivity());
diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h
index 4c1ecc52df..ce317dcfa9 100644
--- a/src/plugins/mercurial/mercurialclient.h
+++ b/src/plugins/mercurial/mercurialclient.h
@@ -74,7 +74,7 @@ public:
void revertAll(const QString &workingDir, const QString &revision = QString(),
const QStringList &extraOptions = QStringList()) override;
- bool isVcsDirectory(const Utils::FileName &fileName) const;
+ bool isVcsDirectory(const Utils::FilePath &fileName) const;
QString findTopLevelForFile(const QFileInfo &file) const override;
void view(const QString &source, const QString &id,
diff --git a/src/plugins/mercurial/mercurialcontrol.cpp b/src/plugins/mercurial/mercurialcontrol.cpp
index d244b8ff8f..48395ad488 100644
--- a/src/plugins/mercurial/mercurialcontrol.cpp
+++ b/src/plugins/mercurial/mercurialcontrol.cpp
@@ -78,7 +78,7 @@ Core::Id MercurialControl::id() const
return {VcsBase::Constants::VCS_ID_MERCURIAL};
}
-bool MercurialControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
+bool MercurialControl::isVcsFileOrDirectory(const Utils::FilePath &fileName) const
{
return mercurialClient->isVcsDirectory(fileName);
}
@@ -99,7 +99,7 @@ bool MercurialControl::managesFile(const QString &workingDirectory, const QStrin
bool MercurialControl::isConfigured() const
{
- const Utils::FileName binary = mercurialClient->vcsBinary();
+ const Utils::FilePath binary = mercurialClient->vcsBinary();
if (binary.isEmpty())
return false;
QFileInfo fi = binary.toFileInfo();
@@ -164,7 +164,7 @@ bool MercurialControl::vcsAnnotate(const QString &file, int line)
}
Core::ShellCommand *MercurialControl::createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs)
{
diff --git a/src/plugins/mercurial/mercurialcontrol.h b/src/plugins/mercurial/mercurialcontrol.h
index f96979e0c8..4d96a32a9a 100644
--- a/src/plugins/mercurial/mercurialcontrol.h
+++ b/src/plugins/mercurial/mercurialcontrol.h
@@ -47,7 +47,7 @@ public:
QString displayName() const final;
Core::Id id() const final;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final;
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final;
bool managesDirectory(const QString &filename, QString *topLevel = nullptr) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
@@ -61,7 +61,7 @@ public:
bool vcsAnnotate(const QString &file, int line) final;
Core::ShellCommand *createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs) final;
diff --git a/src/plugins/modeleditor/CMakeLists.txt b/src/plugins/modeleditor/CMakeLists.txt
new file mode 100644
index 0000000000..69ff243b5c
--- /dev/null
+++ b/src/plugins/modeleditor/CMakeLists.txt
@@ -0,0 +1,36 @@
+add_qtc_plugin(ModelEditor
+ DEFINES MODELEDITOR_LIBRARY
+ DEPENDS Modeling Qt5::Core Qt5::Gui Qt5::Widgets
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer
+ SOURCES
+ actionhandler.cpp actionhandler.h
+ classviewcontroller.cpp classviewcontroller.h
+ componentviewcontroller.cpp componentviewcontroller.h
+ diagramsviewmanager.cpp diagramsviewmanager.h
+ dragtool.cpp dragtool.h
+ editordiagramview.cpp editordiagramview.h
+ elementtasks.cpp elementtasks.h
+ extdocumentcontroller.cpp extdocumentcontroller.h
+ extpropertiesmview.cpp extpropertiesmview.h
+ jsextension.cpp jsextension.h
+ modeldocument.cpp modeldocument.h
+ modeleditor.cpp modeleditor.h
+ modeleditor_constants.h
+ modeleditor_global.h
+ modeleditor_plugin.cpp modeleditor_plugin.h
+ modeleditorfactory.cpp modeleditorfactory.h
+ modelindexer.cpp modelindexer.h
+ modelsmanager.cpp modelsmanager.h
+ modelutilities.cpp modelutilities.h
+ openelementvisitor.cpp openelementvisitor.h
+ packageviewcontroller.cpp packageviewcontroller.h
+ pxnodecontroller.cpp pxnodecontroller.h
+ pxnodeutilities.cpp pxnodeutilities.h
+ resources/modeleditor.qrc
+ settingscontroller.cpp settingscontroller.h
+ uicontroller.cpp uicontroller.h
+ EXPLICIT_MOC
+ actionhandler.h
+ modeleditor.h
+ modeleditorfactory.h
+)
diff --git a/src/plugins/modeleditor/jsextension.h b/src/plugins/modeleditor/jsextension.h
index 74c7cbc892..6192636e3b 100644
--- a/src/plugins/modeleditor/jsextension.h
+++ b/src/plugins/modeleditor/jsextension.h
@@ -35,7 +35,7 @@ class JsExtension : public QObject
Q_OBJECT
public:
- JsExtension(QObject *parent = nullptr) : QObject(parent) { }
+ JsExtension() {}
Q_INVOKABLE QString fileNameToElementName(const QString &file);
Q_INVOKABLE QString elementNameToFileName(const QString &element);
diff --git a/src/plugins/modeleditor/modeldocument.cpp b/src/plugins/modeleditor/modeldocument.cpp
index e47c0d1a97..875a8bc5c3 100644
--- a/src/plugins/modeleditor/modeldocument.cpp
+++ b/src/plugins/modeleditor/modeldocument.cpp
@@ -96,7 +96,7 @@ bool ModelDocument::save(QString *errorString, const QString &name, bool autoSav
if (autoSave) {
d->documentController->projectController()->setModified();
} else {
- setFilePath(Utils::FileName::fromString(d->documentController->projectController()->project()->fileName()));
+ setFilePath(Utils::FilePath::fromString(d->documentController->projectController()->project()->fileName()));
emit changed();
}
@@ -152,7 +152,7 @@ Core::IDocument::OpenResult ModelDocument::load(QString *errorString, const QStr
try {
d->documentController->loadProject(fileName);
- setFilePath(Utils::FileName::fromString(d->documentController->projectController()->project()->fileName()));
+ setFilePath(Utils::FilePath::fromString(d->documentController->projectController()->project()->fileName()));
} catch (const qmt::FileNotFoundException &ex) {
*errorString = ex.errorMessage();
return OpenResult::ReadError;
diff --git a/src/plugins/modeleditor/modeleditor.cpp b/src/plugins/modeleditor/modeleditor.cpp
index 56c03ba9a1..67ee3a6294 100644
--- a/src/plugins/modeleditor/modeleditor.cpp
+++ b/src/plugins/modeleditor/modeleditor.cpp
@@ -321,7 +321,7 @@ void ModelEditor::init(QWidget *parent)
toolbarLayout->addWidget(openParentButton);
d->diagramSelector = new QComboBox(d->toolbar);
- connect(d->diagramSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(d->diagramSelector, QOverload<int>::of(&QComboBox::activated),
this, &ModelEditor::onDiagramSelectorSelected);
toolbarLayout->addWidget(d->diagramSelector, 1);
toolbarLayout->addStretch(1);
diff --git a/src/plugins/modeleditor/modeleditor_plugin.cpp b/src/plugins/modeleditor/modeleditor_plugin.cpp
index 7571703cbb..8e08854f4d 100644
--- a/src/plugins/modeleditor/modeleditor_plugin.cpp
+++ b/src/plugins/modeleditor/modeleditor_plugin.cpp
@@ -92,7 +92,7 @@ bool ModelEditorPlugin::initialize(const QStringList &arguments, QString *errorS
d->modelFactory = new ModelEditorFactory(d->uiController, this);
d->settingsController = new SettingsController(this);
- Core::JsExpander::registerQObjectForJs(QLatin1String("Modeling"), new JsExtension(this));
+ Core::JsExpander::registerGlobalObject<JsExtension>("Modeling");
connect(d->settingsController, &SettingsController::saveSettings,
d->uiController, &UiController::saveSettings);
diff --git a/src/plugins/modeleditor/modelindexer.cpp b/src/plugins/modeleditor/modelindexer.cpp
index 3fa1703ea9..e03fb4eb03 100644
--- a/src/plugins/modeleditor/modelindexer.cpp
+++ b/src/plugins/modeleditor/modelindexer.cpp
@@ -392,11 +392,11 @@ void ModelIndexer::scanProject(ProjectExplorer::Project *project)
return;
// TODO harmonize following code with findFirstModel()?
- const Utils::FileNameList files = project->files(ProjectExplorer::Project::SourceFiles);
+ const Utils::FilePathList files = project->files(ProjectExplorer::Project::SourceFiles);
QQueue<QueuedFile> filesQueue;
QSet<QueuedFile> filesSet;
- for (const Utils::FileName &file : files) {
+ for (const Utils::FilePath &file : files) {
QFileInfo fileInfo = file.toFileInfo();
Utils::MimeType mimeType = Utils::mimeTypeForFile(fileInfo);
if (mimeType.name() == QLatin1String(Constants::MIME_TYPE_MODEL)) {
@@ -474,10 +474,10 @@ QString ModelIndexer::findFirstModel(ProjectExplorer::FolderNode *folderNode)
void ModelIndexer::forgetProject(ProjectExplorer::Project *project)
{
- const Utils::FileNameList files = project->files(ProjectExplorer::Project::SourceFiles);
+ const Utils::FilePathList files = project->files(ProjectExplorer::Project::SourceFiles);
QMutexLocker locker(&d->indexerMutex);
- for (const Utils::FileName &file : files) {
+ for (const Utils::FilePath &file : files) {
const QString fileString = file.toString();
// remove file from queue
QueuedFile queuedFile(fileString, project);
diff --git a/src/plugins/modeleditor/modelsmanager.cpp b/src/plugins/modeleditor/modelsmanager.cpp
index 683006817d..768d65b2b3 100644
--- a/src/plugins/modeleditor/modelsmanager.cpp
+++ b/src/plugins/modeleditor/modelsmanager.cpp
@@ -250,7 +250,7 @@ void ModelsManager::onAboutToShowContextMenu(ProjectExplorer::Project *project,
void ModelsManager::onOpenDiagramFromProjectExplorer()
{
- if (ProjectExplorer::ProjectTree::findCurrentNode() == d->contextMenuOwnerNode) {
+ if (ProjectExplorer::ProjectTree::currentNode() == d->contextMenuOwnerNode) {
qmt::MDiagram *diagram = nullptr;
foreach (const ManagedModel &managedModel, d->managedModels) {
if ((diagram = managedModel.m_documentController->pxNodeController()->findDiagramForExplorerNode(d->contextMenuOwnerNode))) {
diff --git a/src/plugins/modeleditor/pxnodeutilities.cpp b/src/plugins/modeleditor/pxnodeutilities.cpp
index 7e6c986a50..cfd071aac7 100644
--- a/src/plugins/modeleditor/pxnodeutilities.cpp
+++ b/src/plugins/modeleditor/pxnodeutilities.cpp
@@ -66,21 +66,9 @@ void PxNodeUtilities::setDiagramSceneController(qmt::DiagramSceneController *dia
QString PxNodeUtilities::calcRelativePath(const ProjectExplorer::Node *node,
const QString &anchorFolder)
{
- QString nodePath;
-
- switch (node->nodeType()) {
- case ProjectExplorer::NodeType::File:
- {
- QFileInfo fileInfo = node->filePath().toFileInfo();
- nodePath = fileInfo.path();
- break;
- }
- case ProjectExplorer::NodeType::Folder:
- case ProjectExplorer::NodeType::VirtualFolder:
- case ProjectExplorer::NodeType::Project:
- nodePath = node->filePath().toString();
- break;
- }
+ const QString nodePath = node->asFileNode()
+ ? node->filePath().toFileInfo().path()
+ : node->filePath().toString();
return qmt::NameController::calcRelativePath(nodePath, anchorFolder);
}
diff --git a/src/plugins/nim/CMakeLists.txt b/src/plugins/nim/CMakeLists.txt
new file mode 100644
index 0000000000..ac450f76f4
--- /dev/null
+++ b/src/plugins/nim/CMakeLists.txt
@@ -0,0 +1,35 @@
+add_qtc_plugin(Nim
+ PLUGIN_DEPENDS Core TextEditor ProjectExplorer
+ SOURCES
+ editor/nimcompletionassistprovider.cpp editor/nimcompletionassistprovider.h
+ editor/nimeditorfactory.cpp editor/nimeditorfactory.h
+ editor/nimhighlighter.cpp editor/nimhighlighter.h
+ editor/nimindenter.cpp editor/nimindenter.h
+ nim.qrc
+ nimconstants.h
+ nimplugin.cpp nimplugin.h
+ project/nimbuildconfiguration.cpp project/nimbuildconfiguration.h
+ project/nimcompilerbuildstep.cpp project/nimcompilerbuildstep.h
+ project/nimcompilerbuildstepconfigwidget.cpp project/nimcompilerbuildstepconfigwidget.h project/nimcompilerbuildstepconfigwidget.ui
+ project/nimcompilercleanstep.cpp project/nimcompilercleanstep.h
+ project/nimcompilercleanstepconfigwidget.cpp project/nimcompilercleanstepconfigwidget.h project/nimcompilercleanstepconfigwidget.ui
+ project/nimproject.cpp project/nimproject.h
+ project/nimprojectnode.cpp project/nimprojectnode.h
+ project/nimrunconfiguration.cpp project/nimrunconfiguration.h
+ project/nimtoolchain.cpp project/nimtoolchain.h
+ project/nimtoolchainfactory.cpp project/nimtoolchainfactory.h
+ settings/nimcodestylepreferencesfactory.cpp settings/nimcodestylepreferencesfactory.h
+ settings/nimcodestylepreferenceswidget.cpp settings/nimcodestylepreferenceswidget.h settings/nimcodestylepreferenceswidget.ui
+ settings/nimcodestylesettingspage.cpp settings/nimcodestylesettingspage.h
+ settings/nimsettings.cpp settings/nimsettings.h
+ settings/nimtoolssettingspage.cpp settings/nimtoolssettingspage.h
+ settings/nimtoolssettingswidget.ui
+ suggest/client.cpp suggest/client.h
+ suggest/clientrequests.cpp suggest/clientrequests.h
+ suggest/nimsuggest.cpp suggest/nimsuggest.h
+ suggest/nimsuggestcache.cpp suggest/nimsuggestcache.h
+ suggest/server.cpp suggest/server.h
+ suggest/sexprlexer.h suggest/sexprparser.h
+ tools/nimlexer.cpp tools/nimlexer.h
+ tools/sourcecodestream.h
+)
diff --git a/src/plugins/nim/editor/nimcompletionassistprovider.cpp b/src/plugins/nim/editor/nimcompletionassistprovider.cpp
index ec7544bfed..9fcf30c4b0 100644
--- a/src/plugins/nim/editor/nimcompletionassistprovider.cpp
+++ b/src/plugins/nim/editor/nimcompletionassistprovider.cpp
@@ -158,7 +158,7 @@ private:
static Suggest::NimSuggest *nimSuggestInstance(const AssistInterface *interface)
{
- auto filename = Utils::FileName::fromString(interface->fileName());
+ auto filename = Utils::FilePath::fromString(interface->fileName());
return Nim::Suggest::NimSuggestCache::instance().get(filename);
}
@@ -170,7 +170,7 @@ private:
int line = 0, column = 0;
Utils::Text::convertPosition(interface->textDocument(), pos, &line, &column);
QTC_ASSERT(column >= 1, return nullptr);
- auto filename = Utils::FileName::fromString(interface->fileName());
+ auto filename = Utils::FilePath::fromString(interface->fileName());
return suggest->sug(filename.toString(), line, column - 1, dirtyFile);
}
diff --git a/src/plugins/nim/nim.pro b/src/plugins/nim/nim.pro
index e2e4fb18c1..2cb7bb2de3 100644
--- a/src/plugins/nim/nim.pro
+++ b/src/plugins/nim/nim.pro
@@ -24,7 +24,6 @@ HEADERS += \
project/nimcompilercleanstep.h \
project/nimcompilercleanstepconfigwidget.h \
project/nimrunconfiguration.h \
- project/nimbuildconfigurationwidget.h \
editor/nimeditorfactory.h \
settings/nimcodestylesettingspage.h \
settings/nimcodestylepreferencesfactory.h \
@@ -55,7 +54,6 @@ SOURCES += \
project/nimcompilercleanstep.cpp \
project/nimcompilercleanstepconfigwidget.cpp \
project/nimrunconfiguration.cpp \
- project/nimbuildconfigurationwidget.cpp \
editor/nimeditorfactory.cpp \
settings/nimcodestylesettingspage.cpp \
settings/nimcodestylepreferencesfactory.cpp \
diff --git a/src/plugins/nim/nim.qbs b/src/plugins/nim/nim.qbs
index b009e4d88f..cf5dc40930 100644
--- a/src/plugins/nim/nim.qbs
+++ b/src/plugins/nim/nim.qbs
@@ -37,7 +37,6 @@ QtcPlugin {
prefix: "project/"
files: [
"nimbuildconfiguration.h", "nimbuildconfiguration.cpp",
- "nimbuildconfigurationwidget.h", "nimbuildconfigurationwidget.cpp",
"nimcompilerbuildstep.h", "nimcompilerbuildstep.cpp",
"nimcompilerbuildstepconfigwidget.h", "nimcompilerbuildstepconfigwidget.cpp", "nimcompilerbuildstepconfigwidget.ui",
"nimcompilercleanstep.h", "nimcompilercleanstep.cpp",
diff --git a/src/plugins/nim/nimconstants.h b/src/plugins/nim/nimconstants.h
index d37cdcedb7..552e01d4b3 100644
--- a/src/plugins/nim/nimconstants.h
+++ b/src/plugins/nim/nimconstants.h
@@ -39,19 +39,11 @@ const char C_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Nim
const char C_NIMTOOLCHAIN_TYPEID[] = "Nim.NimToolChain";
const char C_NIMTOOLCHAIN_COMPILER_COMMAND_KEY[] = "Nim.NimToolChain.CompilerCommand";
-// NimRunConfiguration
-const QString C_NIMRUNCONFIGURATION_EXECUTABLE_KEY = QStringLiteral("Nim.NimRunConfiguration.Executable");
-
// NimProject
const char C_NIMPROJECT_EXCLUDEDFILES[] = "Nim.NimProjectExcludedFiles";
// NimBuildConfiguration
const char C_NIMBUILDCONFIGURATION_ID[] = "Nim.NimBuildConfiguration";
-const QString C_NIMBUILDCONFIGURATION_DISPLAY_KEY = QStringLiteral("Nim.NimBuildConfiguration.Display");
-const QString C_NIMBUILDCONFIGURATION_BUILDDIRECTORY_KEY = QStringLiteral("Nim.NimBuildConfiguration.BuildDirectory");
-
-// NimBuildConfigurationWidget
-const char C_NIMBUILDCONFIGURATIONWIDGET_DISPLAY[] = QT_TRANSLATE_NOOP("NimBuildConfigurationWidget","General");
// NimCompilerBuildStep
const char C_NIMCOMPILERBUILDSTEP_ID[] = "Nim.NimCompilerBuildStep";
diff --git a/src/plugins/nim/nimplugin.cpp b/src/plugins/nim/nimplugin.cpp
index 3afcb19b5f..d9ff187179 100644
--- a/src/plugins/nim/nimplugin.cpp
+++ b/src/plugins/nim/nimplugin.cpp
@@ -43,6 +43,7 @@
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/toolchainmanager.h>
+#include <projectexplorer/runcontrol.h>
#include <texteditor/snippets/snippetprovider.h>
using namespace Utils;
@@ -66,6 +67,7 @@ public:
NimEditorFactory editorFactory;
NimBuildConfigurationFactory buildConfigFactory;
NimRunConfigurationFactory runConfigFactory;
+ SimpleRunWorkerFactory<SimpleTargetRunner, NimRunConfiguration> runWorkerFactory;
NimCompilerBuildStepFactory buildStepFactory;
NimCompilerCleanStepFactory cleanStepFactory;
NimCodeStyleSettingsPage codeStyleSettingsPage;
diff --git a/src/plugins/nim/project/nimbuildconfiguration.cpp b/src/plugins/nim/project/nimbuildconfiguration.cpp
index 46acf4881b..0827a29327 100644
--- a/src/plugins/nim/project/nimbuildconfiguration.cpp
+++ b/src/plugins/nim/project/nimbuildconfiguration.cpp
@@ -24,7 +24,6 @@
****************************************************************************/
#include "nimbuildconfiguration.h"
-#include "nimbuildconfigurationwidget.h"
#include "nimcompilerbuildstep.h"
#include "nimproject.h"
#include "nimbuildconfiguration.h"
@@ -43,6 +42,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmacroexpander.h>
#include <projectexplorer/target.h>
+#include <projectexplorer/projectconfigurationaspects.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
@@ -51,7 +51,7 @@ using namespace Utils;
namespace Nim {
-static FileName defaultBuildDirectory(const Kit *k,
+static FilePath defaultBuildDirectory(const Kit *k,
const QString &projectFilePath,
const QString &bc,
BuildConfiguration::BuildType buildType)
@@ -62,17 +62,18 @@ static FileName defaultBuildDirectory(const Kit *k,
QString buildDirectory = expander.expand(ProjectExplorerPlugin::buildDirectoryTemplate());
if (FileUtils::isAbsolutePath(buildDirectory))
- return FileName::fromString(buildDirectory);
+ return FilePath::fromString(buildDirectory);
- auto projectDir = FileName::fromString(projectFileInfo.absoluteDir().absolutePath());
- auto result = projectDir.appendPath(buildDirectory);
-
- return result;
+ auto projectDir = FilePath::fromString(projectFileInfo.absoluteDir().absolutePath());
+ return projectDir.pathAppended(buildDirectory);
}
NimBuildConfiguration::NimBuildConfiguration(Target *target, Core::Id id)
: BuildConfiguration(target, id)
{
+ setConfigWidgetDisplayName(tr("General"));
+ setConfigWidgetHasFrame(true);
+ setBuildDirectorySettingsKey("Nim.NimBuildConfiguration.BuildDirectory");
}
void NimBuildConfiguration::initialize(const BuildInfo &info)
@@ -105,7 +106,7 @@ void NimBuildConfiguration::initialize(const BuildInfo &info)
break;
}
nimCompilerBuildStep->setDefaultCompilerOptions(defaultOption);
- Utils::FileNameList nimFiles = project->nimFiles();
+ Utils::FilePathList nimFiles = project->nimFiles();
if (!nimFiles.isEmpty())
nimCompilerBuildStep->setTargetNimFile(nimFiles.first());
buildSteps->appendStep(nimCompilerBuildStep);
@@ -118,48 +119,20 @@ void NimBuildConfiguration::initialize(const BuildInfo &info)
}
}
-
-NamedWidget *NimBuildConfiguration::createConfigWidget()
-{
- return new NimBuildConfigurationWidget(this);
-}
-
BuildConfiguration::BuildType NimBuildConfiguration::buildType() const
{
return BuildConfiguration::Unknown;
}
-bool NimBuildConfiguration::fromMap(const QVariantMap &map)
-{
- if (!BuildConfiguration::fromMap(map))
- return false;
-
- const QString displayName = map[Constants::C_NIMBUILDCONFIGURATION_DISPLAY_KEY].toString();
- const QString buildDirectory = map[Constants::C_NIMBUILDCONFIGURATION_BUILDDIRECTORY_KEY].toString();
-
- setDisplayName(displayName);
- setBuildDirectory(FileName::fromString(buildDirectory));
-
- return true;
-}
-
-QVariantMap NimBuildConfiguration::toMap() const
-{
- QVariantMap result = BuildConfiguration::toMap();
- result[Constants::C_NIMBUILDCONFIGURATION_DISPLAY_KEY] = displayName();
- result[Constants::C_NIMBUILDCONFIGURATION_BUILDDIRECTORY_KEY] = buildDirectory().toString();
- return result;
-}
-
-FileName NimBuildConfiguration::cacheDirectory() const
+FilePath NimBuildConfiguration::cacheDirectory() const
{
- return buildDirectory().appendPath(QStringLiteral("nimcache"));
+ return buildDirectory().pathAppended("nimcache");
}
-FileName NimBuildConfiguration::outFilePath() const
+FilePath NimBuildConfiguration::outFilePath() const
{
const NimCompilerBuildStep *step = nimCompilerBuildStep();
- QTC_ASSERT(step, return FileName());
+ QTC_ASSERT(step, return FilePath());
return step->outFilePath();
}
diff --git a/src/plugins/nim/project/nimbuildconfiguration.h b/src/plugins/nim/project/nimbuildconfiguration.h
index 90175647ea..3c1819e01d 100644
--- a/src/plugins/nim/project/nimbuildconfiguration.h
+++ b/src/plugins/nim/project/nimbuildconfiguration.h
@@ -40,18 +40,14 @@ class NimBuildConfiguration : public ProjectExplorer::BuildConfiguration
NimBuildConfiguration(ProjectExplorer::Target *target, Core::Id id);
void initialize(const ProjectExplorer::BuildInfo &info) override;
- ProjectExplorer::NamedWidget *createConfigWidget() override;
ProjectExplorer::BuildConfiguration::BuildType buildType() const override;
- bool fromMap(const QVariantMap &map) override;
- QVariantMap toMap() const override;
-
public:
- Utils::FileName cacheDirectory() const;
- Utils::FileName outFilePath() const;
+ Utils::FilePath cacheDirectory() const;
+ Utils::FilePath outFilePath() const;
signals:
- void outFilePathChanged(const Utils::FileName &outFilePath);
+ void outFilePathChanged(const Utils::FilePath &outFilePath);
private:
void setupBuild(const ProjectExplorer::BuildInfo *info);
diff --git a/src/plugins/nim/project/nimbuildconfigurationwidget.cpp b/src/plugins/nim/project/nimbuildconfigurationwidget.cpp
deleted file mode 100644
index e4511eba31..0000000000
--- a/src/plugins/nim/project/nimbuildconfigurationwidget.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
-** Contact: http://www.qt.io/licensing
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "nimbuildconfigurationwidget.h"
-#include "nimbuildconfiguration.h"
-
-#include "../nimconstants.h"
-
-#include <utils/pathchooser.h>
-#include <utils/detailswidget.h>
-
-#include <QVBoxLayout>
-#include <QFormLayout>
-#include <QComboBox>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Nim {
-
-NimBuildConfigurationWidget::NimBuildConfigurationWidget(NimBuildConfiguration *bc)
- : NamedWidget(nullptr)
- , m_bc(bc)
-{
- // Build UI
- auto mainLayout = new QVBoxLayout(this);
- mainLayout->setMargin(0);
-
- auto detailsWidget = new DetailsWidget();
- detailsWidget->setState(DetailsWidget::NoSummary);
- mainLayout->addWidget(detailsWidget);
-
- auto detailsInnerWidget = new QWidget();
- auto formLayout = new QFormLayout(detailsInnerWidget);
- detailsWidget->setWidget(detailsInnerWidget);
-
- m_buildDirectoryChooser = new PathChooser();
- formLayout->addRow(tr("Build directory:"), m_buildDirectoryChooser);
-
- // Connect signals
- connect(bc, &NimBuildConfiguration::buildDirectoryChanged,
- this, &NimBuildConfigurationWidget::updateUi);
- connect(m_buildDirectoryChooser, &PathChooser::pathChanged,
- this, &NimBuildConfigurationWidget::onPathEdited);
-
- setDisplayName(tr(Constants::C_NIMBUILDCONFIGURATIONWIDGET_DISPLAY));
- updateUi();
-}
-
-NimBuildConfigurationWidget::~NimBuildConfigurationWidget() = default;
-
-void NimBuildConfigurationWidget::updateUi()
-{
- m_buildDirectoryChooser->setPath(m_bc->buildDirectory().toUserOutput());
-}
-
-void NimBuildConfigurationWidget::onPathEdited(const QString &path)
-{
- m_bc->setBuildDirectory(FileName::fromUserInput(path));
-}
-
-
-}
diff --git a/src/plugins/nim/project/nimbuildconfigurationwidget.h b/src/plugins/nim/project/nimbuildconfigurationwidget.h
deleted file mode 100644
index cb6251b3ec..0000000000
--- a/src/plugins/nim/project/nimbuildconfigurationwidget.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
-** Contact: http://www.qt.io/licensing
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** 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/namedwidget.h>
-
-QT_BEGIN_NAMESPACE
-class QComboBox;
-class QLineEdit;
-class QPushButton;
-QT_END_NAMESPACE
-
-namespace Utils { class PathChooser; }
-
-namespace Nim {
-
-class NimBuildConfiguration;
-
-class NimBuildConfigurationWidget : public ProjectExplorer::NamedWidget
-{
- Q_OBJECT
-
-public:
- explicit NimBuildConfigurationWidget(NimBuildConfiguration *bc);
- ~NimBuildConfigurationWidget();
-
-private:
- void updateUi();
- void onPathEdited(const QString &path);
-
- NimBuildConfiguration *m_bc;
- Utils::PathChooser *m_buildDirectoryChooser;
-};
-
-}
diff --git a/src/plugins/nim/project/nimcompilerbuildstep.cpp b/src/plugins/nim/project/nimcompilerbuildstep.cpp
index a959ddbb1a..1ecc7e8c63 100644
--- a/src/plugins/nim/project/nimcompilerbuildstep.cpp
+++ b/src/plugins/nim/project/nimcompilerbuildstep.cpp
@@ -91,7 +91,7 @@ private:
Task task(type,
message,
- Utils::FileName::fromUserInput(filename),
+ Utils::FilePath::fromUserInput(filename),
lineNumber,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task);
@@ -135,7 +135,7 @@ bool NimCompilerBuildStep::fromMap(const QVariantMap &map)
AbstractProcessStep::fromMap(map);
m_userCompilerOptions = map[Constants::C_NIMCOMPILERBUILDSTEP_USERCOMPILEROPTIONS].toString().split('|');
m_defaultOptions = static_cast<DefaultBuildOptions>(map[Constants::C_NIMCOMPILERBUILDSTEP_DEFAULTBUILDOPTIONS].toInt());
- m_targetNimFile = FileName::fromString(map[Constants::C_NIMCOMPILERBUILDSTEP_TARGETNIMFILE].toString());
+ m_targetNimFile = FilePath::fromString(map[Constants::C_NIMCOMPILERBUILDSTEP_TARGETNIMFILE].toString());
updateProcessParameters();
return true;
}
@@ -175,12 +175,12 @@ void NimCompilerBuildStep::setDefaultCompilerOptions(NimCompilerBuildStep::Defau
updateProcessParameters();
}
-FileName NimCompilerBuildStep::targetNimFile() const
+FilePath NimCompilerBuildStep::targetNimFile() const
{
return m_targetNimFile;
}
-void NimCompilerBuildStep::setTargetNimFile(const FileName &targetNimFile)
+void NimCompilerBuildStep::setTargetNimFile(const FilePath &targetNimFile)
{
if (targetNimFile == m_targetNimFile)
return;
@@ -189,12 +189,12 @@ void NimCompilerBuildStep::setTargetNimFile(const FileName &targetNimFile)
updateProcessParameters();
}
-FileName NimCompilerBuildStep::outFilePath() const
+FilePath NimCompilerBuildStep::outFilePath() const
{
return m_outFilePath;
}
-void NimCompilerBuildStep::setOutFilePath(const FileName &outFilePath)
+void NimCompilerBuildStep::setOutFilePath(const FilePath &outFilePath)
{
if (outFilePath == m_outFilePath)
return;
@@ -217,8 +217,7 @@ void NimCompilerBuildStep::updateOutFilePath()
auto bc = qobject_cast<NimBuildConfiguration *>(buildConfiguration());
QTC_ASSERT(bc, return);
const QString targetName = Utils::HostOsInfo::withExecutableSuffix(m_targetNimFile.toFileInfo().baseName());
- FileName outFilePath = bc->buildDirectory().appendPath(targetName);
- setOutFilePath(outFilePath);
+ setOutFilePath(bc->buildDirectory().pathAppended(targetName));
}
void NimCompilerBuildStep::updateCommand()
@@ -226,16 +225,16 @@ void NimCompilerBuildStep::updateCommand()
QTC_ASSERT(target(), return);
QTC_ASSERT(target()->kit(), return);
Kit *kit = target()->kit();
- auto tc = dynamic_cast<NimToolChain*>(ToolChainKitInformation::toolChain(kit, Constants::C_NIMLANGUAGE_ID));
+ auto tc = dynamic_cast<NimToolChain*>(ToolChainKitAspect::toolChain(kit, Constants::C_NIMLANGUAGE_ID));
QTC_ASSERT(tc, return);
- processParameters()->setCommand(tc->compilerCommand().toString());
+ processParameters()->setCommand(tc->compilerCommand());
}
void NimCompilerBuildStep::updateWorkingDirectory()
{
auto bc = qobject_cast<NimBuildConfiguration *>(buildConfiguration());
QTC_ASSERT(bc, return);
- processParameters()->setWorkingDirectory(bc->buildDirectory().toString());
+ processParameters()->setWorkingDirectory(bc->buildDirectory());
}
void NimCompilerBuildStep::updateArguments()
@@ -283,7 +282,7 @@ void NimCompilerBuildStep::updateTargetNimFile()
{
if (!m_targetNimFile.isEmpty())
return;
- const Utils::FileNameList nimFiles = static_cast<NimProject *>(project())->nimFiles();
+ const Utils::FilePathList nimFiles = static_cast<NimProject *>(project())->nimFiles();
if (!nimFiles.isEmpty())
setTargetNimFile(nimFiles.at(0));
}
@@ -317,19 +316,19 @@ void NimPlugin::testNimParser_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
// negative tests
QTest::newRow("pass-through stdout")
<< "Sometext" << OutputParserTester::STDOUT
<< "Sometext\n" << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
<< "Sometext" << OutputParserTester::STDERR
<< QString() << "Sometext\n"
- << QList<Task>()
+ << Tasks()
<< QString();
// positive tests
@@ -337,9 +336,9 @@ void NimPlugin::testNimParser_data()
<< QString::fromLatin1("main.nim(23, 1) Error: undeclared identifier: 'x'")
<< OutputParserTester::STDERR
<< QString("") << QString("main.nim(23, 1) Error: undeclared identifier: 'x'\n")
- << QList<Task>({Task(Task::Error,
+ << Tasks({Task(Task::Error,
"Error: undeclared identifier: 'x'",
- Utils::FileName::fromUserInput("main.nim"), 23,
+ Utils::FilePath::fromUserInput("main.nim"), 23,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE)})
<< QString();
@@ -347,9 +346,9 @@ void NimPlugin::testNimParser_data()
<< QString::fromLatin1("lib/pure/parseopt.nim(56, 34) Warning: quoteIfContainsWhite is deprecated [Deprecated]")
<< OutputParserTester::STDERR
<< QString("") << QString("lib/pure/parseopt.nim(56, 34) Warning: quoteIfContainsWhite is deprecated [Deprecated]\n")
- << QList<Task>({Task(Task::Warning,
+ << Tasks({Task(Task::Warning,
"Warning: quoteIfContainsWhite is deprecated [Deprecated]",
- Utils::FileName::fromUserInput("lib/pure/parseopt.nim"), 56,
+ Utils::FilePath::fromUserInput("lib/pure/parseopt.nim"), 56,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE)})
<< QString();
}
@@ -360,7 +359,7 @@ void NimPlugin::testNimParser()
testbench.appendOutputParser(new NimParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/nim/project/nimcompilerbuildstep.h b/src/plugins/nim/project/nimcompilerbuildstep.h
index c370a6ba50..a866694c9a 100644
--- a/src/plugins/nim/project/nimcompilerbuildstep.h
+++ b/src/plugins/nim/project/nimcompilerbuildstep.h
@@ -53,20 +53,20 @@ public:
DefaultBuildOptions defaultCompilerOptions() const;
void setDefaultCompilerOptions(DefaultBuildOptions options);
- Utils::FileName targetNimFile() const;
- void setTargetNimFile(const Utils::FileName &targetNimFile);
+ Utils::FilePath targetNimFile() const;
+ void setTargetNimFile(const Utils::FilePath &targetNimFile);
- Utils::FileName outFilePath() const;
+ Utils::FilePath outFilePath() const;
signals:
void userCompilerOptionsChanged(const QStringList &options);
void defaultCompilerOptionsChanged(DefaultBuildOptions options);
- void targetNimFileChanged(const Utils::FileName &targetNimFile);
+ void targetNimFileChanged(const Utils::FilePath &targetNimFile);
void processParametersChanged();
- void outFilePathChanged(const Utils::FileName &outFilePath);
+ void outFilePathChanged(const Utils::FilePath &outFilePath);
private:
- void setOutFilePath(const Utils::FileName &outFilePath);
+ void setOutFilePath(const Utils::FilePath &outFilePath);
void updateOutFilePath();
void updateProcessParameters();
@@ -79,8 +79,8 @@ private:
DefaultBuildOptions m_defaultOptions;
QStringList m_userCompilerOptions;
- Utils::FileName m_targetNimFile;
- Utils::FileName m_outFilePath;
+ Utils::FilePath m_targetNimFile;
+ Utils::FilePath m_outFilePath;
};
class NimCompilerBuildStepFactory : public ProjectExplorer::BuildStepFactory
diff --git a/src/plugins/nim/project/nimcompilerbuildstepconfigwidget.cpp b/src/plugins/nim/project/nimcompilerbuildstepconfigwidget.cpp
index 600f6cf915..27acf21726 100644
--- a/src/plugins/nim/project/nimcompilerbuildstepconfigwidget.cpp
+++ b/src/plugins/nim/project/nimcompilerbuildstepconfigwidget.cpp
@@ -60,11 +60,11 @@ NimCompilerBuildStepConfigWidget::NimCompilerBuildStepConfigWidget(NimCompilerBu
this, &NimCompilerBuildStepConfigWidget::updateUi);
// Connect UI signals
- connect(m_ui->targetComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_ui->targetComboBox, QOverload<int>::of(&QComboBox::activated),
this, &NimCompilerBuildStepConfigWidget::onTargetChanged);
connect(m_ui->additionalArgumentsLineEdit, &QLineEdit::textEdited,
this, &NimCompilerBuildStepConfigWidget::onAdditionalArgumentsTextEdited);
- connect(m_ui->defaultArgumentsComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_ui->defaultArgumentsComboBox, QOverload<int>::of(&QComboBox::activated),
this, &NimCompilerBuildStepConfigWidget::onDefaultArgumentsComboBoxIndexChanged);
updateUi();
@@ -76,7 +76,7 @@ void NimCompilerBuildStepConfigWidget::onTargetChanged(int index)
{
Q_UNUSED(index);
auto data = m_ui->targetComboBox->currentData();
- FileName path = FileName::fromString(data.toString());
+ FilePath path = FilePath::fromString(data.toString());
m_buildStep->setTargetNimFile(path);
}
@@ -104,7 +104,7 @@ void NimCompilerBuildStepConfigWidget::updateCommandLineText()
ProcessParameters *parameters = m_buildStep->processParameters();
QStringList command;
- command << parameters->command();
+ command << parameters->command().toString();
command << parameters->arguments();
// Remove empty args
@@ -124,7 +124,7 @@ void NimCompilerBuildStepConfigWidget::updateTargetComboBox()
// Re enter the files
m_ui->targetComboBox->clear();
- foreach (const FileName &file, project->nimFiles())
+ foreach (const FilePath &file, project->nimFiles())
m_ui->targetComboBox->addItem(file.fileName(), file.toString());
const int index = m_ui->targetComboBox->findData(m_buildStep->targetNimFile().toString());
diff --git a/src/plugins/nim/project/nimcompilercleanstep.cpp b/src/plugins/nim/project/nimcompilercleanstep.cpp
index f07f501106..b802582108 100644
--- a/src/plugins/nim/project/nimcompilercleanstep.cpp
+++ b/src/plugins/nim/project/nimcompilercleanstep.cpp
@@ -54,7 +54,7 @@ BuildStepConfigWidget *NimCompilerCleanStep::createConfigWidget()
bool NimCompilerCleanStep::init()
{
- FileName buildDir = buildConfiguration()->buildDirectory();
+ FilePath buildDir = buildConfiguration()->buildDirectory();
bool result = buildDir.exists();
if (result)
m_buildDir = buildDir;
diff --git a/src/plugins/nim/project/nimcompilercleanstep.h b/src/plugins/nim/project/nimcompilercleanstep.h
index e250d88f45..2cbde61beb 100644
--- a/src/plugins/nim/project/nimcompilercleanstep.h
+++ b/src/plugins/nim/project/nimcompilercleanstep.h
@@ -48,7 +48,7 @@ private:
bool removeCacheDirectory();
bool removeOutFilePath();
- Utils::FileName m_buildDir;
+ Utils::FilePath m_buildDir;
};
class NimCompilerCleanStepFactory : public ProjectExplorer::BuildStepFactory
diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp
index 2af19e4d49..a6cad1657f 100644
--- a/src/plugins/nim/project/nimproject.cpp
+++ b/src/plugins/nim/project/nimproject.cpp
@@ -60,7 +60,7 @@ namespace Nim {
const int MIN_TIME_BETWEEN_PROJECT_SCANS = 4500;
-NimProject::NimProject(const FileName &fileName) : Project(Constants::C_NIM_MIMETYPE, fileName)
+NimProject::NimProject(const FilePath &fileName) : Project(Constants::C_NIM_MIMETYPE, fileName)
{
setId(Constants::C_NIMPROJECT_ID);
setDisplayName(fileName.toFileInfo().completeBaseName());
@@ -117,16 +117,16 @@ void NimProject::collectProjectFiles()
{
m_lastProjectScan.start();
QTC_ASSERT(!m_futureWatcher.future().isRunning(), return);
- FileName prjDir = projectDirectory();
+ FilePath prjDir = projectDirectory();
QFuture<QList<ProjectExplorer::FileNode *>> future = Utils::runAsync([prjDir,
excluded = m_excludedFiles] {
- return FileNode::scanForFiles(prjDir, [excluded](const FileName & fn) -> FileNode * {
+ return FileNode::scanForFiles(prjDir, [excluded](const FilePath & fn) -> FileNode * {
const QString fileName = fn.fileName();
if (excluded.contains(fn.toString())
|| fileName.endsWith(".nimproject", HostOsInfo::fileNameCaseSensitivity())
|| fileName.contains(".nimproject.user", HostOsInfo::fileNameCaseSensitivity()))
return nullptr;
- return new FileNode(fn, FileType::Source, false);
+ return new FileNode(fn, FileType::Source);
});
});
m_futureWatcher.setFuture(future);
@@ -150,11 +150,10 @@ void NimProject::updateProject()
emitParsingFinished(true);
}
-QList<Task> NimProject::projectIssues(const Kit *k) const
+Tasks NimProject::projectIssues(const Kit *k) const
{
- QList<Task> result = Project::projectIssues(k);
- auto tc = dynamic_cast<NimToolChain *>(ToolChainKitInformation::toolChain(k,
- Constants::C_NIMLANGUAGE_ID));
+ Tasks result = Project::projectIssues(k);
+ auto tc = dynamic_cast<NimToolChain *>(ToolChainKitAspect::toolChain(k, Constants::C_NIMLANGUAGE_ID));
if (!tc) {
result.append(createProjectTask(Task::TaskType::Error, tr("No Nim compiler set.")));
return result;
@@ -165,7 +164,7 @@ QList<Task> NimProject::projectIssues(const Kit *k) const
return result;
}
-FileNameList NimProject::nimFiles() const
+FilePathList NimProject::nimFiles() const
{
return files([](const ProjectExplorer::Node *n) {
return AllFiles(n) && n->filePath().endsWith(".nim");
diff --git a/src/plugins/nim/project/nimproject.h b/src/plugins/nim/project/nimproject.h
index 5670fbe533..d0143de2fd 100644
--- a/src/plugins/nim/project/nimproject.h
+++ b/src/plugins/nim/project/nimproject.h
@@ -39,10 +39,10 @@ class NimProject : public ProjectExplorer::Project
Q_OBJECT
public:
- explicit NimProject(const Utils::FileName &fileName);
+ explicit NimProject(const Utils::FilePath &fileName);
- QList<ProjectExplorer::Task> projectIssues(const ProjectExplorer::Kit *k) const final;
- Utils::FileNameList nimFiles() const;
+ ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
+ Utils::FilePathList nimFiles() const;
QVariantMap toMap() const final;
bool addFiles(const QStringList &filePaths);
diff --git a/src/plugins/nim/project/nimprojectnode.cpp b/src/plugins/nim/project/nimprojectnode.cpp
index 7604fb3a6d..6a6385b67e 100644
--- a/src/plugins/nim/project/nimprojectnode.cpp
+++ b/src/plugins/nim/project/nimprojectnode.cpp
@@ -32,25 +32,23 @@ using namespace Utils;
namespace Nim {
NimProjectNode::NimProjectNode(NimProject &project,
- const FileName &projectFilePath)
+ const FilePath &projectFilePath)
: ProjectNode(projectFilePath)
, m_project(project)
{}
bool NimProjectNode::supportsAction(ProjectAction action, const Node *node) const
{
- switch (node->nodeType()) {
- case NodeType::File:
+ if (node->asFileNode()) {
return action == ProjectAction::Rename
|| action == ProjectAction::RemoveFile;
- case NodeType::Folder:
- case NodeType::Project:
+ }
+ if (node->isFolderNodeType() || node->isProjectNodeType()) {
return action == ProjectAction::AddNewFile
|| action == ProjectAction::RemoveFile
|| action == ProjectAction::AddExistingFile;
- default:
- return ProjectNode::supportsAction(action, node);
}
+ return ProjectNode::supportsAction(action, node);
}
bool NimProjectNode::addFiles(const QStringList &filePaths, QStringList *)
diff --git a/src/plugins/nim/project/nimprojectnode.h b/src/plugins/nim/project/nimprojectnode.h
index 317d4be555..6a950bdf4f 100644
--- a/src/plugins/nim/project/nimprojectnode.h
+++ b/src/plugins/nim/project/nimprojectnode.h
@@ -27,7 +27,7 @@
#include <projectexplorer/projectnodes.h>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace Nim {
@@ -36,7 +36,7 @@ class NimProject;
class NimProjectNode : public ProjectExplorer::ProjectNode
{
public:
- NimProjectNode(NimProject &project, const Utils::FileName &projectFilePath);
+ NimProjectNode(NimProject &project, const Utils::FilePath &projectFilePath);
bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *) override;
diff --git a/src/plugins/nim/project/nimrunconfiguration.cpp b/src/plugins/nim/project/nimrunconfiguration.cpp
index c27cb75b54..7849f4dc19 100644
--- a/src/plugins/nim/project/nimrunconfiguration.cpp
+++ b/src/plugins/nim/project/nimrunconfiguration.cpp
@@ -30,6 +30,7 @@
#include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
@@ -44,12 +45,10 @@ namespace Nim {
NimRunConfiguration::NimRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- auto envAspect = addAspect<LocalEnvironmentAspect>
- (target, LocalEnvironmentAspect::BaseEnvironmentModifier());
-
+ addAspect<LocalEnvironmentAspect>(target);
addAspect<ExecutableAspect>();
addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>(envAspect);
+ addAspect<WorkingDirectoryAspect>();
addAspect<TerminalAspect>();
setDisplayName(tr("Current Build Target"));
@@ -67,9 +66,9 @@ void NimRunConfiguration::updateConfiguration()
QTC_ASSERT(buildConfiguration, return);
setActiveBuildConfiguration(buildConfiguration);
const QFileInfo outFileInfo = buildConfiguration->outFilePath().toFileInfo();
- aspect<ExecutableAspect>()->setExecutable(FileName::fromString(outFileInfo.absoluteFilePath()));
+ aspect<ExecutableAspect>()->setExecutable(FilePath::fromString(outFileInfo.absoluteFilePath()));
const QString workingDirectory = outFileInfo.absoluteDir().absolutePath();
- aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(FileName::fromString(workingDirectory));
+ aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(FilePath::fromString(workingDirectory));
}
void NimRunConfiguration::setActiveBuildConfiguration(NimBuildConfiguration *activeBuildConfiguration)
@@ -100,7 +99,6 @@ NimRunConfigurationFactory::NimRunConfigurationFactory() : FixedRunConfiguration
{
registerRunConfiguration<NimRunConfiguration>("Nim.NimRunConfiguration");
addSupportedProjectType(Constants::C_NIMPROJECT_ID);
- addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
}
} // Nim
diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp
index 6687c1eb8c..3e7fcbef72 100644
--- a/src/plugins/nim/project/nimtoolchain.cpp
+++ b/src/plugins/nim/project/nimtoolchain.cpp
@@ -39,20 +39,20 @@ using namespace Utils;
namespace Nim {
-NimToolChain::NimToolChain(ToolChain::Detection d)
- : NimToolChain(Constants::C_NIMTOOLCHAIN_TYPEID, d)
+NimToolChain::NimToolChain()
+ : NimToolChain(Constants::C_NIMTOOLCHAIN_TYPEID)
{}
-NimToolChain::NimToolChain(Core::Id typeId, ToolChain::Detection d)
- : ToolChain(typeId, d)
- , m_compilerCommand(FileName())
+NimToolChain::NimToolChain(Core::Id typeId)
+ : ToolChain(typeId)
+ , m_compilerCommand(FilePath())
, m_version(std::make_tuple(-1,-1,-1))
{
setLanguage(Constants::C_NIMLANGUAGE_ID);
}
NimToolChain::NimToolChain(const NimToolChain &other)
- : ToolChain(other.typeId(), other.detection())
+ : ToolChain(other.typeId())
, m_compilerCommand(other.m_compilerCommand)
, m_version(other.m_version)
{
@@ -71,7 +71,7 @@ Abi NimToolChain::targetAbi() const
bool NimToolChain::isValid() const
{
- if (m_compilerCommand.isNull())
+ if (m_compilerCommand.isEmpty())
return false;
QFileInfo fi = compilerCommand().toFileInfo();
return fi.isExecutable();
@@ -102,7 +102,7 @@ ToolChain::BuiltInHeaderPathsRunner NimToolChain::createBuiltInHeaderPathsRunner
return ToolChain::BuiltInHeaderPathsRunner();
}
-HeaderPaths NimToolChain::builtInHeaderPaths(const QStringList &, const FileName &) const
+HeaderPaths NimToolChain::builtInHeaderPaths(const QStringList &, const FilePath &) const
{
return {};
}
@@ -113,19 +113,18 @@ void NimToolChain::addToEnvironment(Environment &env) const
env.prependOrSetPath(compilerCommand().parentDir().toString());
}
-QString NimToolChain::makeCommand(const Environment &env) const
+FilePath NimToolChain::makeCommand(const Environment &env) const
{
- QString make = "make";
- FileName tmp = env.searchInPath(make);
- return tmp.isEmpty() ? make : tmp.toString();
+ const FilePath tmp = env.searchInPath("make");
+ return tmp.isEmpty() ? FilePath::fromString("make") : tmp;
}
-FileName NimToolChain::compilerCommand() const
+FilePath NimToolChain::compilerCommand() const
{
return m_compilerCommand;
}
-void NimToolChain::setCompilerCommand(const FileName &compilerCommand)
+void NimToolChain::setCompilerCommand(const FilePath &compilerCommand)
{
m_compilerCommand = compilerCommand;
parseVersion(compilerCommand, m_version);
@@ -141,11 +140,6 @@ std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> NimToolChain::createConf
return std::make_unique<NimToolChainConfigWidget>(this);
}
-ToolChain *NimToolChain::clone() const
-{
- return new NimToolChain(*this);
-}
-
QVariantMap NimToolChain::toMap() const
{
QVariantMap data = ToolChain::toMap();
@@ -167,11 +161,11 @@ bool NimToolChain::fromMap(const QVariantMap &data)
{
if (!ToolChain::fromMap(data))
return false;
- setCompilerCommand(FileName::fromString(data.value(Constants::C_NIMTOOLCHAIN_COMPILER_COMMAND_KEY).toString()));
+ setCompilerCommand(FilePath::fromString(data.value(Constants::C_NIMTOOLCHAIN_COMPILER_COMMAND_KEY).toString()));
return true;
}
-bool NimToolChain::parseVersion(const FileName &path, std::tuple<int, int, int> &result)
+bool NimToolChain::parseVersion(const FilePath &path, std::tuple<int, int, int> &result)
{
QProcess process;
process.start(path.toString(), {"--version"});
diff --git a/src/plugins/nim/project/nimtoolchain.h b/src/plugins/nim/project/nimtoolchain.h
index 1ebe381517..b35e073ccd 100644
--- a/src/plugins/nim/project/nimtoolchain.h
+++ b/src/plugins/nim/project/nimtoolchain.h
@@ -33,8 +33,8 @@ namespace Nim {
class NimToolChain : public ProjectExplorer::ToolChain
{
public:
- NimToolChain(Detection d);
- NimToolChain(Core::Id typeId, Detection d);
+ NimToolChain();
+ explicit NimToolChain(Core::Id typeId);
QString typeDisplayName() const override;
ProjectExplorer::Abi targetAbi() const override;
@@ -47,25 +47,24 @@ public:
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override;
ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &flags,
- const Utils::FileName &sysRoot) const final;
+ const Utils::FilePath &sysRoot) const final;
void addToEnvironment(Utils::Environment &env) const final;
- QString makeCommand(const Utils::Environment &env) const final;
- Utils::FileName compilerCommand() const final;
+ Utils::FilePath makeCommand(const Utils::Environment &env) const final;
+ Utils::FilePath compilerCommand() const final;
QString compilerVersion() const;
- void setCompilerCommand(const Utils::FileName &compilerCommand);
+ void setCompilerCommand(const Utils::FilePath &compilerCommand);
ProjectExplorer::IOutputParser *outputParser() const final;
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() final;
- ProjectExplorer::ToolChain *clone() const final;
QVariantMap toMap() const final;
bool fromMap(const QVariantMap &data) final;
- static bool parseVersion(const Utils::FileName &path, std::tuple<int, int, int> &version);
+ static bool parseVersion(const Utils::FilePath &path, std::tuple<int, int, int> &version);
private:
NimToolChain(const NimToolChain &other);
- Utils::FileName m_compilerCommand;
+ Utils::FilePath m_compilerCommand;
std::tuple<int, int, int> m_version;
};
diff --git a/src/plugins/nim/project/nimtoolchainfactory.cpp b/src/plugins/nim/project/nimtoolchainfactory.cpp
index 0eaae567f6..5fc94c4926 100644
--- a/src/plugins/nim/project/nimtoolchainfactory.cpp
+++ b/src/plugins/nim/project/nimtoolchainfactory.cpp
@@ -43,39 +43,10 @@ namespace Nim {
NimToolChainFactory::NimToolChainFactory()
{
setDisplayName(tr("Nim"));
-}
-
-bool NimToolChainFactory::canCreate()
-{
- return true;
-}
-
-ToolChain *NimToolChainFactory::create(Core::Id l)
-{
- if (l != Constants::C_NIMLANGUAGE_ID)
- return nullptr;
- auto result = new NimToolChain(ToolChain::ManualDetection);
- result->setLanguage(l);
- return result;
-}
-
-bool NimToolChainFactory::canRestore(const QVariantMap &data)
-{
- return typeIdFromMap(data) == Constants::C_NIMTOOLCHAIN_TYPEID;
-}
-
-ToolChain *NimToolChainFactory::restore(const QVariantMap &data)
-{
- auto tc = new NimToolChain(ToolChain::AutoDetection);
- if (tc->fromMap(data))
- return tc;
- delete tc;
- return nullptr;
-}
-
-QSet<Core::Id> NimToolChainFactory::supportedLanguages() const
-{
- return {Constants::C_NIMLANGUAGE_ID};
+ setSupportedToolChainType(Constants::C_NIMTOOLCHAIN_TYPEID);
+ setSupportedLanguages({Constants::C_NIMLANGUAGE_ID});
+ setToolchainConstructor([] { return new NimToolChain; });
+ setUserCreatable(true);
}
QList<ToolChain *> NimToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
@@ -83,7 +54,7 @@ QList<ToolChain *> NimToolChainFactory::autoDetect(const QList<ToolChain *> &alr
QList<ToolChain *> result;
Environment systemEnvironment = Environment::systemEnvironment();
- const FileName compilerPath = systemEnvironment.searchInPath("nim");
+ const FilePath compilerPath = systemEnvironment.searchInPath("nim");
if (compilerPath.isEmpty())
return result;
@@ -95,17 +66,19 @@ QList<ToolChain *> NimToolChainFactory::autoDetect(const QList<ToolChain *> &alr
if (!result.empty())
return result;
- auto tc = new NimToolChain(ToolChain::AutoDetection);
+ auto tc = new NimToolChain;
+ tc->setDetection(ToolChain::AutoDetection);
tc->setCompilerCommand(compilerPath);
result.append(tc);
return result;
}
-QList<ToolChain *> NimToolChainFactory::autoDetect(const FileName &compilerPath, const Core::Id &language)
+QList<ToolChain *> NimToolChainFactory::autoDetect(const FilePath &compilerPath, const Core::Id &language)
{
QList<ToolChain *> result;
if (language == Constants::C_NIMLANGUAGE_ID) {
- auto tc = new NimToolChain(ToolChain::ManualDetection);
+ auto tc = new NimToolChain;
+ tc->setDetection(ToolChain::ManualDetection); // FIXME: sure?
tc->setCompilerCommand(compilerPath);
result.append(tc);
}
@@ -170,7 +143,7 @@ void NimToolChainConfigWidget::onCompilerCommandChanged(const QString &path)
{
auto tc = static_cast<NimToolChain *>(toolChain());
Q_ASSERT(tc);
- tc->setCompilerCommand(FileName::fromString(path));
+ tc->setCompilerCommand(FilePath::fromString(path));
fillUI();
}
diff --git a/src/plugins/nim/project/nimtoolchainfactory.h b/src/plugins/nim/project/nimtoolchainfactory.h
index 4ba0a028ad..70a49cbb37 100644
--- a/src/plugins/nim/project/nimtoolchainfactory.h
+++ b/src/plugins/nim/project/nimtoolchainfactory.h
@@ -41,13 +41,8 @@ class NimToolChainFactory : public ProjectExplorer::ToolChainFactory
public:
NimToolChainFactory();
- bool canCreate() final;
- ProjectExplorer::ToolChain *create(Core::Id l) final;
- bool canRestore(const QVariantMap &data) final;
- ProjectExplorer::ToolChain *restore(const QVariantMap &data) final;
- QSet<Core::Id> supportedLanguages() const final;
QList<ProjectExplorer::ToolChain *> autoDetect(const QList<ProjectExplorer::ToolChain *> &alreadyKnown) final;
- QList<ProjectExplorer::ToolChain *> autoDetect(const Utils::FileName &compilerPath, const Core::Id &language) final;
+ QList<ProjectExplorer::ToolChain *> autoDetect(const Utils::FilePath &compilerPath, const Core::Id &language) final;
};
class NimToolChainConfigWidget : public ProjectExplorer::ToolChainConfigWidget
diff --git a/src/plugins/nim/settings/nimtoolssettingspage.cpp b/src/plugins/nim/settings/nimtoolssettingspage.cpp
index b658917395..05187f869b 100644
--- a/src/plugins/nim/settings/nimtoolssettingspage.cpp
+++ b/src/plugins/nim/settings/nimtoolssettingspage.cpp
@@ -32,9 +32,8 @@
namespace Nim {
-NimToolsSettingsWidget::NimToolsSettingsWidget(NimSettings *settings, QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::NimToolsSettingsWidget)
+NimToolsSettingsWidget::NimToolsSettingsWidget(NimSettings *settings)
+ : ui(new Ui::NimToolsSettingsWidget)
, m_settings(settings)
{
ui->setupUi(this);
@@ -56,9 +55,8 @@ void NimToolsSettingsWidget::setCommand(const QString &filename)
ui->pathWidget->setPath(filename);
}
-NimToolsSettingsPage::NimToolsSettingsPage(NimSettings *settings, QWidget *parent)
- : Core::IOptionsPage(parent)
- , m_settings(settings)
+NimToolsSettingsPage::NimToolsSettingsPage(NimSettings *settings)
+ : m_settings(settings)
{
setId(Nim::Constants::C_NIMTOOLSSETTINGSPAGE_ID);
setDisplayName(tr(Nim::Constants::C_NIMTOOLSSETTINGSPAGE_DISPLAY));
diff --git a/src/plugins/nim/settings/nimtoolssettingspage.h b/src/plugins/nim/settings/nimtoolssettingspage.h
index 4a19ed00aa..e0de799960 100644
--- a/src/plugins/nim/settings/nimtoolssettingspage.h
+++ b/src/plugins/nim/settings/nimtoolssettingspage.h
@@ -43,7 +43,7 @@ class NimToolsSettingsWidget : public QWidget
Q_OBJECT
public:
- explicit NimToolsSettingsWidget(NimSettings *settings, QWidget *parent = nullptr);
+ explicit NimToolsSettingsWidget(NimSettings *settings);
~NimToolsSettingsWidget();
@@ -60,7 +60,7 @@ class NimToolsSettingsPage : public Core::IOptionsPage
Q_OBJECT
public:
- NimToolsSettingsPage(NimSettings *settings, QWidget *parent = nullptr);
+ NimToolsSettingsPage(NimSettings *settings);
~NimToolsSettingsPage();
diff --git a/src/plugins/nim/suggest/nimsuggestcache.cpp b/src/plugins/nim/suggest/nimsuggestcache.cpp
index 6953883608..dafeffb39e 100644
--- a/src/plugins/nim/suggest/nimsuggestcache.cpp
+++ b/src/plugins/nim/suggest/nimsuggestcache.cpp
@@ -42,7 +42,7 @@ NimSuggestCache &NimSuggestCache::instance()
NimSuggestCache::~NimSuggestCache() = default;
-NimSuggest *NimSuggestCache::get(const Utils::FileName &filename)
+NimSuggest *NimSuggestCache::get(const Utils::FilePath &filename)
{
auto it = m_nimSuggestInstances.find(filename);
if (it == m_nimSuggestInstances.end()) {
diff --git a/src/plugins/nim/suggest/nimsuggestcache.h b/src/plugins/nim/suggest/nimsuggestcache.h
index c7b632e82e..cccd136b46 100644
--- a/src/plugins/nim/suggest/nimsuggestcache.h
+++ b/src/plugins/nim/suggest/nimsuggestcache.h
@@ -45,7 +45,7 @@ class NimSuggestCache : public QObject
public:
static NimSuggestCache &instance();
- NimSuggest *get(const Utils::FileName &filename);
+ NimSuggest *get(const Utils::FilePath &filename);
QString executablePath() const;
void setExecutablePath(const QString &path);
@@ -57,7 +57,7 @@ private:
void onEditorOpened(Core::IEditor *editor);
void onEditorClosed(Core::IEditor *editor);
- std::unordered_map<Utils::FileName, std::unique_ptr<Suggest::NimSuggest>> m_nimSuggestInstances;
+ std::unordered_map<Utils::FilePath, std::unique_ptr<Suggest::NimSuggest>> m_nimSuggestInstances;
QString m_executablePath;
};
diff --git a/src/plugins/nim/suggest/server.cpp b/src/plugins/nim/suggest/server.cpp
index 862513f108..8e9b79b827 100644
--- a/src/plugins/nim/suggest/server.cpp
+++ b/src/plugins/nim/suggest/server.cpp
@@ -30,8 +30,8 @@ namespace Suggest {
NimSuggestServer::NimSuggestServer(QObject *parent) : QObject(parent)
{
- connect(&m_process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>
- (&QProcess::finished), this, &NimSuggestServer::onFinished);
+ connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, &NimSuggestServer::onFinished);
connect(&m_process, &QProcess::started, this, &NimSuggestServer::onStarted);
connect(&m_process, &QProcess::readyReadStandardOutput, this,
&NimSuggestServer::onStandardOutputAvailable);
@@ -69,8 +69,8 @@ bool NimSuggestServer::start(const QString &executablePath,
void NimSuggestServer::kill()
{
- disconnect(&m_process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>
- (&QProcess::finished), this, &NimSuggestServer::onFinished);
+ disconnect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, &NimSuggestServer::onFinished);
m_process.kill();
m_process.waitForFinished();
clearState();
diff --git a/src/plugins/perforce/CMakeLists.txt b/src/plugins/perforce/CMakeLists.txt
new file mode 100644
index 0000000000..9a3dd9e59c
--- /dev/null
+++ b/src/plugins/perforce/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_qtc_plugin(Perforce
+ PLUGIN_DEPENDS Core TextEditor VcsBase
+ SOURCES
+ annotationhighlighter.cpp annotationhighlighter.h
+ changenumberdialog.cpp changenumberdialog.h changenumberdialog.ui
+ pendingchangesdialog.cpp pendingchangesdialog.h pendingchangesdialog.ui
+ perforcechecker.cpp perforcechecker.h
+ perforceeditor.cpp perforceeditor.h
+ perforceplugin.cpp perforceplugin.h
+ perforcesettings.cpp perforcesettings.h
+ perforcesubmiteditor.cpp perforcesubmiteditor.h
+ perforcesubmiteditorwidget.cpp perforcesubmiteditorwidget.h
+ perforceversioncontrol.cpp perforceversioncontrol.h
+ promptdialog.ui
+ settingspage.cpp settingspage.h settingspage.ui
+ submitpanel.ui
+)
diff --git a/src/plugins/perforce/perforcechecker.cpp b/src/plugins/perforce/perforcechecker.cpp
index 87b02e6ef3..544a132b64 100644
--- a/src/plugins/perforce/perforcechecker.cpp
+++ b/src/plugins/perforce/perforcechecker.cpp
@@ -42,7 +42,7 @@ namespace Internal {
PerforceChecker::PerforceChecker(QObject *parent) : QObject(parent)
{
connect(&m_process, &QProcess::errorOccurred, this, &PerforceChecker::slotError);
- connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &PerforceChecker::slotFinished);
}
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index e7325fc1fb..580c52d78f 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -1118,7 +1118,7 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QString &workingDir,
actualArgs.append(args);
if (flags & CommandToWindow)
- VcsOutputWindow::appendCommand(workingDir, FileName::fromString(settings().p4BinaryPath()), actualArgs);
+ VcsOutputWindow::appendCommand(workingDir, FilePath::fromString(settings().p4BinaryPath()), actualArgs);
if (flags & ShowBusyCursor)
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
diff --git a/src/plugins/perforce/perforceversioncontrol.cpp b/src/plugins/perforce/perforceversioncontrol.cpp
index e027a8ef26..87d08806b5 100644
--- a/src/plugins/perforce/perforceversioncontrol.cpp
+++ b/src/plugins/perforce/perforceversioncontrol.cpp
@@ -49,7 +49,7 @@ Core::Id PerforceVersionControl::id() const
return Core::Id(VcsBase::Constants::VCS_ID_PERFORCE);
}
-bool PerforceVersionControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
+bool PerforceVersionControl::isVcsFileOrDirectory(const Utils::FilePath &fileName) const
{
Q_UNUSED(fileName);
return false; // Perforce does not seem to litter its files into the source tree.
diff --git a/src/plugins/perforce/perforceversioncontrol.h b/src/plugins/perforce/perforceversioncontrol.h
index fa3b0c1d12..410e9a749a 100644
--- a/src/plugins/perforce/perforceversioncontrol.h
+++ b/src/plugins/perforce/perforceversioncontrol.h
@@ -41,7 +41,7 @@ public:
QString displayName() const final;
Core::Id id() const final;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final;
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final;
bool managesDirectory(const QString &directory, QString *topLevel = nullptr) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
diff --git a/src/plugins/perfprofiler/CMakeLists.txt b/src/plugins/perfprofiler/CMakeLists.txt
new file mode 100644
index 0000000000..20345cb038
--- /dev/null
+++ b/src/plugins/perfprofiler/CMakeLists.txt
@@ -0,0 +1,41 @@
+add_qtc_plugin(PerfProfiler
+ DEPENDS Tracing Qt5::QuickWidgets
+ PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
+ SOURCES
+ perfconfigeventsmodel.cpp perfconfigeventsmodel.h
+ perfconfigwidget.cpp perfconfigwidget.h
+ perfconfigwidget.ui
+ perfdatareader.cpp perfdatareader.h
+ perfevent.h
+ perfeventtype.h
+ perfloaddialog.cpp perfloaddialog.h perfloaddialog.ui
+ perfoptionspage.cpp perfoptionspage.h
+ perfprofiler.qrc
+ perfprofilerconstants.h
+ perfprofilerflamegraphmodel.cpp perfprofilerflamegraphmodel.h
+ perfprofilerflamegraphview.cpp perfprofilerflamegraphview.h
+ perfprofilerplugin.cpp perfprofilerplugin.h
+ perfprofilerruncontrol.cpp perfprofilerruncontrol.h
+ perfprofilerstatisticsmodel.cpp perfprofilerstatisticsmodel.h
+ perfprofilerstatisticsview.cpp perfprofilerstatisticsview.h
+ perfprofilertool.cpp perfprofilertool.h
+ perfprofilertracefile.cpp perfprofilertracefile.h
+ perfprofilertracemanager.cpp perfprofilertracemanager.h
+ perfprofilertraceview.cpp perfprofilertraceview.h
+ perfprofiler_global.h
+ perfresourcecounter.cpp perfresourcecounter.h
+ perfrunconfigurationaspect.cpp perfrunconfigurationaspect.h
+ perfsettings.cpp perfsettings.h
+ perftimelinemodel.cpp perftimelinemodel.h
+ perftimelinemodelmanager.cpp perftimelinemodelmanager.h
+ perftimelineresourcesrenderpass.cpp perftimelineresourcesrenderpass.h
+ perftracepointdialog.cpp perftracepointdialog.h perftracepointdialog.ui
+)
+
+extend_qtc_plugin(PerfProfiler
+ CONDITION WITH_TESTS
+ SOURCES
+ tests/perfprofilertracefile_test.cpp tests/perfprofilertracefile_test.h
+ tests/perfresourcecounter_test.cpp tests/perfresourcecounter_test.h
+ tests/tests.qrc
+)
diff --git a/src/plugins/perfprofiler/perfconfigwidget.cpp b/src/plugins/perfprofiler/perfconfigwidget.cpp
index 356948bb86..1fe3acf58d 100644
--- a/src/plugins/perfprofiler/perfconfigwidget.cpp
+++ b/src/plugins/perfprofiler/perfconfigwidget.cpp
@@ -33,6 +33,7 @@
#include <projectexplorer/devicesupport/deviceprocess.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <utils/qtcprocess.h>
@@ -75,15 +76,14 @@ PerfConfigWidget::PerfConfigWidget(PerfSettings *settings, QWidget *parent) :
m_ui->sampleMode->addItem(tr("frequency (Hz)"), QLatin1String(Constants::PerfSampleFrequency));
m_ui->sampleMode->addItem(tr("event count"), QLatin1String(Constants::PerfSampleCount));
- auto comboboxChangedSignal
- = static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged);
+ auto comboboxChangedSignal = QOverload<int>::of(&QComboBox::currentIndexChanged);
connect(m_ui->callgraphMode, comboboxChangedSignal, this, [this](int index) {
QString mode = m_ui->callgraphMode->itemData(index).toString();
m_settings->setCallgraphMode(mode);
m_ui->stackSize->setEnabled(mode == QLatin1String(Constants::PerfCallgraphDwarf));
});
- auto spinBoxChangedSignal = static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
+ auto spinBoxChangedSignal = QOverload<int>::of(&QSpinBox::valueChanged);
connect(m_ui->stackSize, spinBoxChangedSignal, m_settings, &PerfSettings::setStackSize);
connect(m_ui->period, spinBoxChangedSignal, m_settings, &PerfSettings::setPeriod);
connect(m_ui->sampleMode, comboboxChangedSignal, this, [this](int index) {
@@ -147,7 +147,7 @@ void PerfConfigWidget::setTarget(ProjectExplorer::Target *target)
ProjectExplorer::IDevice::ConstPtr device;
if (target) {
if (ProjectExplorer::Kit *kit = target->kit())
- device = ProjectExplorer::DeviceKitInformation::device(kit);
+ device = ProjectExplorer::DeviceKitAspect::device(kit);
}
if (device.isNull()) {
diff --git a/src/plugins/perfprofiler/perfdatareader.cpp b/src/plugins/perfprofiler/perfdatareader.cpp
index 52afd696b8..86c80f382c 100644
--- a/src/plugins/perfprofiler/perfdatareader.cpp
+++ b/src/plugins/perfprofiler/perfdatareader.cpp
@@ -34,12 +34,15 @@
#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
+
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>
+
#include <qtsupport/qtkitinformation.h>
#include <utils/qtcassert.h>
@@ -64,7 +67,7 @@ PerfDataReader::PerfDataReader(QObject *parent) :
m_remoteProcessStart(std::numeric_limits<qint64>::max()),
m_lastRemoteTimestamp(0)
{
- connect(&m_input, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ connect(&m_input, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, [this](int exitCode) {
emit processFinished();
// process any remaining input before signaling finished()
@@ -293,7 +296,7 @@ QStringList PerfDataReader::collectArguments(const QString &executableDirPath,
if (!executableDirPath.isEmpty())
arguments << QLatin1String("--app") << executableDirPath;
- if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(kit)) {
+ if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(kit)) {
arguments << QLatin1String("--extra") << QString::fromLatin1("%1%5%2%5%3%5%4")
.arg(QDir::toNativeSeparators(qt->libraryPath().toString()))
.arg(QDir::toNativeSeparators(qt->pluginPath().toString()))
@@ -302,7 +305,7 @@ QStringList PerfDataReader::collectArguments(const QString &executableDirPath,
.arg(QDir::listSeparator());
}
- if (auto toolChain = ProjectExplorer::ToolChainKitInformation::toolChain(
+ if (auto toolChain = ProjectExplorer::ToolChainKitAspect::toolChain(
kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID)) {
ProjectExplorer::Abi::Architecture architecture = toolChain->targetAbi().architecture();
if (architecture == ProjectExplorer::Abi::ArmArchitecture &&
@@ -313,7 +316,7 @@ QStringList PerfDataReader::collectArguments(const QString &executableDirPath,
}
}
- QString sysroot = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString();
+ QString sysroot = ProjectExplorer::SysRootKitAspect::sysRoot(kit).toString();
if (!sysroot.isEmpty())
arguments << QLatin1String("--sysroot") << sysroot;
@@ -392,11 +395,11 @@ bool PerfDataReader::feedParser(const QByteArray &input)
return true;
}
-QStringList PerfDataReader::findTargetArguments(const ProjectExplorer::RunConfiguration *rc) const
+QStringList PerfDataReader::findTargetArguments(const ProjectExplorer::RunControl *runControl) const
{
- ProjectExplorer::Kit *kit = rc->target()->kit();
+ ProjectExplorer::Kit *kit = runControl->kit();
QTC_ASSERT(kit, return QStringList());
- ProjectExplorer::BuildConfiguration *buildConfig = rc->target()->activeBuildConfiguration();
+ ProjectExplorer::BuildConfiguration *buildConfig = runControl->target()->activeBuildConfiguration();
QString buildDir = buildConfig ? buildConfig->buildDirectory().toString() : QString();
return collectArguments(buildDir, kit);
}
diff --git a/src/plugins/perfprofiler/perfdatareader.h b/src/plugins/perfprofiler/perfdatareader.h
index 41cc96bdf4..2908c97914 100644
--- a/src/plugins/perfprofiler/perfdatareader.h
+++ b/src/plugins/perfprofiler/perfdatareader.h
@@ -28,13 +28,16 @@
#include "perfprofilertracefile.h"
#include "perftimelinemodelmanager.h"
-#include <projectexplorer/target.h>
-
#include <utils/temporaryfile.h>
#include <QProcess>
#include <QQueue>
+namespace ProjectExplorer {
+class Kit;
+class RunControl;
+} // ProjectExplorer
+
namespace PerfProfiler {
namespace Internal {
@@ -52,7 +55,7 @@ public:
void startParser();
void stopParser();
- QStringList findTargetArguments(const ProjectExplorer::RunConfiguration *rc) const;
+ QStringList findTargetArguments(const ProjectExplorer::RunControl *runControl) const;
void clear();
bool feedParser(const QByteArray &input);
diff --git a/src/plugins/perfprofiler/perfevent.h b/src/plugins/perfprofiler/perfevent.h
index 7fc7942645..dcee855e38 100644
--- a/src/plugins/perfprofiler/perfevent.h
+++ b/src/plugins/perfprofiler/perfevent.h
@@ -50,9 +50,14 @@ public:
ThreadStartTypeId = -2,
ThreadEndTypeId = -3,
LostTypeId = -4,
- LastSpecialTypeId = -5
+ ContextSwitchTypeId = -5,
+ LastSpecialTypeId = -6
};
+ int numAttributes() const { return m_values.length() + 1; }
+ qint32 attributeId(int i) const { return i == 0 ? typeIndex() : m_values[i - 1].first; }
+ quint64 attributeValue(int i) const { return i == 0 ? m_value : m_values[i - 1].second; }
+
const QVector<qint32> &origFrames() const { return m_origFrames; }
quint8 origNumGuessedFrames() const { return m_origNumGuessedFrames; }
@@ -67,25 +72,27 @@ public:
quint8 numGuessedFrames() const { return m_numGuessedFrames; }
void setNumGuessedFrames(quint8 numGuessedFrames) { m_numGuessedFrames = numGuessedFrames; }
- quint64 period() const { return m_period; }
- quint64 weight() const { return m_weight; }
-
quint8 feature() const { return m_feature; }
+ quint8 extra() const { return m_extra; }
+ void setExtra(quint8 extra) { m_extra = extra; }
+
private:
friend QDataStream &operator>>(QDataStream &stream, PerfEvent &event);
friend QDataStream &operator<<(QDataStream &stream, const PerfEvent &event);
+ QVector<QPair<qint32, quint64>> m_values;
QVector<qint32> m_origFrames;
QVector<qint32> m_frames;
QHash<qint32, QVariant> m_traceData;
quint32 m_pid = 0;
quint32 m_tid = 0;
- quint64 m_period = 0;
- quint64 m_weight = 0;
+ quint64 m_value = 0;
+ quint32 m_cpu = 0;
quint8 m_origNumGuessedFrames = 0;
quint8 m_numGuessedFrames = 0;
quint8 m_feature = PerfEventType::InvalidFeature;
+ quint8 m_extra = 0;
};
inline QDataStream &operator>>(QDataStream &stream, PerfEvent &event)
@@ -105,16 +112,16 @@ inline QDataStream &operator>>(QDataStream &stream, PerfEvent &event)
case PerfEventType::ThreadStart:
case PerfEventType::ThreadEnd:
case PerfEventType::LostDefinition:
- case PerfEventType::Sample43:
case PerfEventType::Sample:
case PerfEventType::TracePointSample:
+ case PerfEventType::ContextSwitchDefinition:
break;
case PerfEventType::InvalidFeature:
QTC_ASSERT(false, return stream);
}
quint64 timestamp;
- stream >> event.m_pid >> event.m_tid >> timestamp;
+ stream >> event.m_pid >> event.m_tid >> timestamp >> event.m_cpu;
static const quint64 qint64Max = static_cast<quint64>(std::numeric_limits<qint64>::max());
event.setTimestamp(static_cast<qint64>(qMin(timestamp, qint64Max)));
@@ -129,15 +136,30 @@ inline QDataStream &operator>>(QDataStream &stream, PerfEvent &event)
case PerfEventType::LostDefinition:
event.setTypeIndex(PerfEvent::LostTypeId);
break;
+ case PerfEventType::ContextSwitchDefinition:
+ event.setTypeIndex(PerfEvent::ContextSwitchTypeId);
+ bool isSwitchOut;
+ stream >> isSwitchOut;
+ event.setExtra(isSwitchOut);
+ break;
default: {
- qint32 typeIndex;
- stream >> event.m_origFrames >> event.m_origNumGuessedFrames >> typeIndex;
- if (event.m_feature != PerfEventType::Sample43) {
- stream >> event.m_period >> event.m_weight;
- if (event.m_feature == PerfEventType::TracePointSample)
- stream >> event.m_traceData;
+ qint32 firstAttributeId;
+ stream >> event.m_origFrames >> event.m_origNumGuessedFrames;
+ QVector<QPair<qint32, quint64>> values;
+ stream >> values;
+ if (values.isEmpty()) {
+ firstAttributeId = PerfEvent::LastSpecialTypeId;
+ } else {
+ firstAttributeId = PerfEvent::LastSpecialTypeId - values.first().first;
+ event.m_value = values.first().second;
+ for (auto it = values.constBegin() + 1, end = values.constEnd(); it != end; ++it) {
+ event.m_values.push_back({ PerfEvent::LastSpecialTypeId - it->first,
+ it->second });
+ }
}
- event.setTypeIndex(PerfEvent::LastSpecialTypeId - typeIndex);
+ if (event.m_feature == PerfEventType::TracePointSample)
+ stream >> event.m_traceData;
+ event.setTypeIndex(firstAttributeId);
}
}
@@ -148,23 +170,31 @@ inline QDataStream &operator<<(QDataStream &stream, const PerfEvent &event)
{
quint8 feature = event.feature();
stream << feature << event.m_pid << event.m_tid
- << (event.timestamp() < 0ll ? 0ull : static_cast<quint64>(event.timestamp()));
+ << (event.timestamp() < 0ll ? 0ull : static_cast<quint64>(event.timestamp()))
+ << event.m_cpu;
switch (feature) {
case PerfEventType::ThreadStart:
case PerfEventType::ThreadEnd:
case PerfEventType::LostDefinition:
break;
- case PerfEventType::Sample43:
+ case PerfEventType::ContextSwitchDefinition:
+ stream << bool(event.extra());
+ break;
case PerfEventType::Sample:
- case PerfEventType::TracePointSample:
- stream << event.m_origFrames << event.m_origNumGuessedFrames
- << static_cast<qint32>(PerfEvent::LastSpecialTypeId - event.typeIndex());
- if (feature != PerfEventType::Sample43) {
- stream << event.m_period << event.m_weight;
- if (feature == PerfEventType::TracePointSample)
- stream << event.m_traceData;
+ case PerfEventType::TracePointSample: {
+ stream << event.m_origFrames << event.m_origNumGuessedFrames;
+
+ QVector<QPair<qint32, quint64>> values;
+ for (int i = 0, end = event.numAttributes(); i < end; ++i) {
+ values.push_back({ PerfEvent::LastSpecialTypeId - event.attributeId(i),
+ event.attributeValue(i) });
}
+ stream << values;
+
+ if (feature == PerfEventType::TracePointSample)
+ stream << event.m_traceData;
break;
+ }
default:
QTC_CHECK(false);
}
diff --git a/src/plugins/perfprofiler/perfeventtype.h b/src/plugins/perfprofiler/perfeventtype.h
index 2d8533edde..457b6afeb2 100644
--- a/src/plugins/perfprofiler/perfeventtype.h
+++ b/src/plugins/perfprofiler/perfeventtype.h
@@ -39,33 +39,33 @@ public:
static const qint32 staticClassId = 0x70726674; // 'prft'
enum Feature {
- Sample43, // Only used until QtC/perfparser 4.3
ThreadStart,
ThreadEnd,
Command,
LocationDefinition,
SymbolDefinition,
- AttributesDefinition,
StringDefinition,
LostDefinition,
FeaturesDefinition,
Error,
- Sample,
Progress,
TracePointFormat,
+ AttributesDefinition,
+ ContextSwitchDefinition,
+ Sample,
TracePointSample,
InvalidFeature
};
static quint64 attributeFeatures()
{
- return (1ull << Sample43) | (1ull << Sample) | (1ull << TracePointSample)
- | (1ull << AttributesDefinition);
+ return (1ull << Sample) | (1ull << TracePointSample) | (1ull << AttributesDefinition);
}
static quint64 metaFeatures()
{
- return (1ull << ThreadStart) | (1ull << ThreadEnd) | (1ull << LostDefinition);
+ return (1ull << ThreadStart) | (1ull << ThreadEnd) | (1ull << LostDefinition)
+ | (1ull << ContextSwitchDefinition);
}
static quint64 locationFeatures()
@@ -90,8 +90,10 @@ public:
struct Attribute {
quint64 config = std::numeric_limits<quint64>::max();
+ quint64 frequencyOrPeriod = std::numeric_limits<quint64>::max();
quint32 type = std::numeric_limits<quint32>::max();
qint32 name = -1;
+ bool usesFrequency = false;
};
struct Location {
@@ -126,7 +128,6 @@ public:
bool isAttribute() const
{
switch (feature()) {
- case Sample43:
case Sample:
case AttributesDefinition:
case TracePointSample:
@@ -141,6 +142,8 @@ public:
case ThreadStart:
case ThreadEnd:
case LostDefinition:
+ case ContextSwitchDefinition:
+ case InvalidFeature:
return true;
default:
return false;
@@ -178,12 +181,14 @@ private:
inline QDataStream &operator>>(QDataStream &stream, PerfEventType::Attribute &attribute)
{
- return stream >> attribute.type >> attribute.config >> attribute.name;
+ return stream >> attribute.type >> attribute.config >> attribute.name
+ >> attribute.usesFrequency >> attribute.frequencyOrPeriod;
}
inline QDataStream &operator<<(QDataStream &stream, const PerfEventType::Attribute &attribute)
{
- return stream << attribute.type << attribute.config << attribute.name;
+ return stream << attribute.type << attribute.config << attribute.name
+ << attribute.usesFrequency << attribute.frequencyOrPeriod;
}
inline QDataStream &operator>>(QDataStream &stream, PerfEventType::Location &location)
diff --git a/src/plugins/perfprofiler/perfoptionspage.cpp b/src/plugins/perfprofiler/perfoptionspage.cpp
index 8b66475f77..356b073dd6 100644
--- a/src/plugins/perfprofiler/perfoptionspage.cpp
+++ b/src/plugins/perfprofiler/perfoptionspage.cpp
@@ -33,7 +33,7 @@
namespace PerfProfiler {
namespace Internal {
-PerfOptionsPage::PerfOptionsPage(QObject *parent) : Core::IOptionsPage(parent)
+PerfOptionsPage::PerfOptionsPage()
{
setId(Constants::PerfSettingsId);
setDisplayName(QCoreApplication::translate("PerfProfiler::PerfOptionsPage", "CPU Usage"));
diff --git a/src/plugins/perfprofiler/perfoptionspage.h b/src/plugins/perfprofiler/perfoptionspage.h
index 7f5da499e8..febde556e0 100644
--- a/src/plugins/perfprofiler/perfoptionspage.h
+++ b/src/plugins/perfprofiler/perfoptionspage.h
@@ -36,7 +36,7 @@ class PerfOptionsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
- PerfOptionsPage(QObject *parent = nullptr);
+ PerfOptionsPage();
QWidget *widget();
void apply();
diff --git a/src/plugins/perfprofiler/perfprofilerconstants.h b/src/plugins/perfprofiler/perfprofilerconstants.h
index b35ba28ec8..32e174cf5d 100644
--- a/src/plugins/perfprofiler/perfprofilerconstants.h
+++ b/src/plugins/perfprofiler/perfprofilerconstants.h
@@ -66,8 +66,7 @@ const char PerfSampleFrequency[] = "-F";
const char PerfSampleCount[] = "-c";
const char PerfStreamMagic[] = "QPERFSTREAM";
-const char PerfQzfileMagic[] = "QPERFQZFILE";
-const char PerfZqfileMagic[] = "QPERFZQFILE";
+const char PerfZqfileMagic[] = "PTQFILE4.10";
} // namespace Constants
} // namespace PerfProfiler
diff --git a/src/plugins/perfprofiler/perfprofilerflamegraphmodel.cpp b/src/plugins/perfprofiler/perfprofilerflamegraphmodel.cpp
index 3a10ad67ae..79ebb32ba1 100644
--- a/src/plugins/perfprofiler/perfprofilerflamegraphmodel.cpp
+++ b/src/plugins/perfprofiler/perfprofilerflamegraphmodel.cpp
@@ -227,8 +227,12 @@ void PerfProfilerFlameGraphData::updateTraceData(const PerfEvent &event, const P
PerfProfilerFlameGraphModel::Data *data,
int numSamples)
{
- const PerfEventType::Attribute &attribute = type.attribute();
- if (attribute.type == PerfEventType::TypeTracepoint) {
+ Q_UNUSED(type);
+ for (int i = 0, end = event.numAttributes(); i < end; ++i) {
+ const PerfEventType::Attribute &attribute = manager->attribute(event.attributeId(i));
+ if (attribute.type != PerfEventType::TypeTracepoint)
+ continue;
+
const PerfProfilerTraceManager::TracePoint &tracePoint
= manager->tracePoint(static_cast<int>(attribute.config));
diff --git a/src/plugins/perfprofiler/perfprofilerplugin.cpp b/src/plugins/perfprofiler/perfprofilerplugin.cpp
index a6fc393cab..26f2272204 100644
--- a/src/plugins/perfprofiler/perfprofilerplugin.cpp
+++ b/src/plugins/perfprofiler/perfprofilerplugin.cpp
@@ -52,32 +52,44 @@
#include <QAction>
#include <QDebug>
#include <QMenu>
-#include <QtPlugin>
using namespace ProjectExplorer;
namespace PerfProfiler {
+namespace Internal {
Q_GLOBAL_STATIC(PerfSettings, perfGlobalSettings)
-bool PerfProfilerPlugin::initialize(const QStringList &arguments, QString *errorString)
+class PerfProfilerPluginPrivate
{
- Q_UNUSED(arguments)
- Q_UNUSED(errorString)
+public:
+ PerfProfilerPluginPrivate()
+ {
+ RunConfiguration::registerAspect<PerfRunConfigurationAspect>();
- (void) new Internal::PerfOptionsPage(this);
+ RunControl::registerWorkerCreator(ProjectExplorer::Constants::PERFPROFILER_RUN_MODE,
+ [](RunControl *runControl){ return new PerfProfilerRunner(runControl); });
- RunConfiguration::registerAspect<PerfRunConfigurationAspect>();
+ auto constraint = [](RunConfiguration *) { return true; };
+ RunControl::registerWorker<PerfProfilerRunner>
+ (ProjectExplorer::Constants::PERFPROFILER_RUN_MODE, constraint);
+ }
- (void) new Internal::PerfProfilerTool(this);
+ PerfOptionsPage optionsPage;
+ PerfProfilerTool profilerTool;
+};
- RunControl::registerWorkerCreator(ProjectExplorer::Constants::PERFPROFILER_RUN_MODE,
- [](RunControl *runControl){ return new Internal::PerfProfilerRunner(runControl); });
+PerfProfilerPlugin::~PerfProfilerPlugin()
+{
+ delete d;
+}
- auto constraint = [](RunConfiguration *) { return true; };
- RunControl::registerWorker<Internal::PerfProfilerRunner>
- (ProjectExplorer::Constants::PERFPROFILER_RUN_MODE, constraint);
+bool PerfProfilerPlugin::initialize(const QStringList &arguments, QString *errorString)
+{
+ Q_UNUSED(arguments)
+ Q_UNUSED(errorString)
+ d = new PerfProfilerPluginPrivate;
return true;
}
@@ -85,19 +97,20 @@ void PerfProfilerPlugin::extensionsInitialized()
{
}
-PerfProfiler::PerfSettings *PerfProfilerPlugin::globalSettings()
+PerfSettings *PerfProfilerPlugin::globalSettings()
{
return perfGlobalSettings();
}
-QList<QObject *> PerfProfiler::PerfProfilerPlugin::createTestObjects() const
+QVector<QObject *> PerfProfilerPlugin::createTestObjects() const
{
- QList<QObject *> tests;
+ QVector<QObject *> tests;
#if WITH_TESTS
- tests << new Internal::PerfProfilerTraceFileTest;
- tests << new Internal::PerfResourceCounterTest;
+ tests << new PerfProfilerTraceFileTest;
+ tests << new PerfResourceCounterTest;
#endif // WITH_TESTS
return tests;
}
+} // namespace Internal
} // namespace PerfProfiler
diff --git a/src/plugins/perfprofiler/perfprofilerplugin.h b/src/plugins/perfprofiler/perfprofilerplugin.h
index 35d79b099f..9f60f5fa32 100644
--- a/src/plugins/perfprofiler/perfprofilerplugin.h
+++ b/src/plugins/perfprofiler/perfprofilerplugin.h
@@ -30,6 +30,7 @@
#include <extensionsystem/iplugin.h>
namespace PerfProfiler {
+namespace Internal {
class PerfProfilerPlugin : public ExtensionSystem::IPlugin
{
@@ -37,11 +38,16 @@ class PerfProfilerPlugin : public ExtensionSystem::IPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "PerfProfiler.json")
public:
+ ~PerfProfilerPlugin();
+
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final;
- QList<QObject *> createTestObjects() const final;
+ QVector<QObject *> createTestObjects() const final;
static PerfSettings *globalSettings();
+
+ class PerfProfilerPluginPrivate *d = nullptr;
};
+} // namespace Internal
} // namespace PerfProfiler
diff --git a/src/plugins/perfprofiler/perfprofilerruncontrol.cpp b/src/plugins/perfprofiler/perfprofilerruncontrol.cpp
index 50aa9696a1..6f521c306a 100644
--- a/src/plugins/perfprofiler/perfprofilerruncontrol.cpp
+++ b/src/plugins/perfprofiler/perfprofilerruncontrol.cpp
@@ -84,7 +84,7 @@ public:
void start() override
{
- QStringList args = m_reader.findTargetArguments(runControl()->runConfiguration());
+ QStringList args = m_reader.findTargetArguments(runControl());
QUrl url = runControl()->property("PerfConnection").toUrl();
if (url.isValid()) {
args.append(QStringList{"--host", url.host(), "--port", QString::number(url.port())});
@@ -116,8 +116,7 @@ public:
{
setId("LocalPerfRecordWorker");
- auto runConfig = runControl->runConfiguration();
- auto perfAspect = static_cast<PerfRunConfigurationAspect *>(runConfig->aspect(Constants::PerfSettingsId));
+ auto perfAspect = static_cast<PerfRunConfigurationAspect *>(runControl->aspect(Constants::PerfSettingsId));
QTC_ASSERT(perfAspect, return);
PerfSettings *settings = static_cast<PerfSettings *>(perfAspect->currentSettings());
QTC_ASSERT(settings, return);
diff --git a/src/plugins/perfprofiler/perfprofilerruncontrol.h b/src/plugins/perfprofiler/perfprofilerruncontrol.h
index e9f434af9c..139fbac8ea 100644
--- a/src/plugins/perfprofiler/perfprofilerruncontrol.h
+++ b/src/plugins/perfprofiler/perfprofilerruncontrol.h
@@ -25,7 +25,7 @@
#pragma once
-#include <projectexplorer/devicesupport/deviceprocess.h>
+#include <projectexplorer/runcontrol.h>
namespace PerfProfiler {
namespace Internal {
diff --git a/src/plugins/perfprofiler/perfprofilertool.cpp b/src/plugins/perfprofiler/perfprofilertool.cpp
index 4feb8b0279..bb71f925da 100644
--- a/src/plugins/perfprofiler/perfprofilertool.cpp
+++ b/src/plugins/perfprofiler/perfprofilertool.cpp
@@ -69,8 +69,7 @@ namespace Internal {
static PerfProfilerTool *s_instance;
-PerfProfilerTool::PerfProfilerTool(QObject *parent) :
- QObject(parent)
+PerfProfilerTool::PerfProfilerTool()
{
s_instance = this;
m_traceManager = new PerfProfilerTraceManager(this);
@@ -158,6 +157,9 @@ PerfProfilerTool::PerfProfilerTool(QObject *parent) :
tracePointsAction->setEnabled(m_startAction->isEnabled());
});
+ connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
+ this, &PerfProfilerTool::updateRunActions);
+
m_recordButton = new QToolButton;
m_clearButton = new QToolButton;
m_filterButton = new QToolButton;
@@ -342,9 +344,6 @@ void PerfProfilerTool::createViews()
menu1->exec(m_flameGraphView->mapToGlobal(pos));
});
- connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
- this, &PerfProfilerTool::updateRunActions);
-
m_perspective.addToolBarAction(m_startAction);
m_perspective.addToolBarAction(m_stopAction);
m_perspective.addToolBarWidget(m_recordButton);
@@ -441,7 +440,7 @@ void PerfProfilerTool::onReaderStarted()
void PerfProfilerTool::onWorkerCreation(RunControl *runControl)
{
- populateFileFinder(runControl->runConfiguration());
+ populateFileFinder(runControl->project(), runControl->kit());
}
void PerfProfilerTool::updateRunActions()
@@ -541,7 +540,7 @@ void PerfProfilerTool::gotoSourceLocation(QString filePath, int lineNumber, int
QFileInfo fi(filePath);
if (!fi.isAbsolute() || !fi.exists() || !fi.isReadable()) {
- fi.setFile(m_fileFinder.findFile(filePath));
+ fi.setFile(m_fileFinder.findFile(filePath).first().toString());
if (!fi.exists() || !fi.isReadable())
return;
}
@@ -554,29 +553,29 @@ void PerfProfilerTool::gotoSourceLocation(QString filePath, int lineNumber, int
}
-static Utils::FileNameList collectQtIncludePaths(const ProjectExplorer::Kit *kit)
+static Utils::FilePathList collectQtIncludePaths(const ProjectExplorer::Kit *kit)
{
- QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(kit);
+ QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(kit);
if (qt == nullptr)
- return Utils::FileNameList();
- Utils::FileNameList paths{qt->headerPath()};
+ return Utils::FilePathList();
+ Utils::FilePathList paths{qt->headerPath()};
QDirIterator dit(paths.first().toString(), QStringList(), QDir::Dirs | QDir::NoDotAndDotDot,
QDirIterator::Subdirectories);
while (dit.hasNext()) {
dit.next();
- paths << Utils::FileName::fromString(dit.filePath());
+ paths << Utils::FilePath::fromString(dit.filePath());
}
return paths;
}
-static Utils::FileName sysroot(const Kit *kit)
+static Utils::FilePath sysroot(const Kit *kit)
{
- return SysRootKitInformation::sysRoot(kit);
+ return SysRootKitAspect::sysRoot(kit);
}
-static Utils::FileNameList sourceFiles(const Project *currentProject = nullptr)
+static Utils::FilePathList sourceFiles(const Project *currentProject = nullptr)
{
- Utils::FileNameList sourceFiles;
+ Utils::FilePathList sourceFiles;
// Have the current project first.
if (currentProject)
@@ -614,12 +613,17 @@ void PerfProfilerTool::showLoadTraceDialog()
QString filename = QFileDialog::getOpenFileName(
ICore::mainWindow(), tr("Load Trace File"),
- "", tr("Trace File (*.ptr)"));
+ "", tr("Trace File (*.ptq)"));
if (filename.isEmpty())
return;
startLoading();
- populateFileFinder();
+
+ const Project *currentProject = SessionManager::startupProject();
+ const Target *target = currentProject ? currentProject->activeTarget() : nullptr;
+ const Kit *kit = target ? target->kit() : nullptr;
+ populateFileFinder(currentProject, kit);
+
m_traceManager->loadFromTraceFile(filename);
}
@@ -629,11 +633,11 @@ void PerfProfilerTool::showSaveTraceDialog()
QString filename = QFileDialog::getSaveFileName(
ICore::mainWindow(), tr("Save Trace File"),
- "", tr("Trace File (*.ptr)"));
+ "", tr("Trace File (*.ptq)"));
if (filename.isEmpty())
return;
- if (!filename.endsWith(".ptr"))
- filename += ".ptr";
+ if (!filename.endsWith(".ptq"))
+ filename += ".ptq";
setToolActionsEnabled(false);
m_traceManager->saveToTraceFile(filename);
@@ -675,24 +679,12 @@ void PerfProfilerTool::updateTime(qint64 duration, qint64 delay)
m_delayLabel->clear();
}
-void PerfProfilerTool::populateFileFinder(const RunConfiguration *rc)
+void PerfProfilerTool::populateFileFinder(const Project *project, const Kit *kit)
{
- const Project *currentProject = nullptr;
- const Kit *kit = nullptr;
- if (rc) {
- if (const Target *target = rc->target()) {
- kit = target->kit();
- currentProject = target->project();
- }
- } else if ((currentProject = SessionManager::startupProject())) {
- if (const Target *target = currentProject->activeTarget())
- kit = target->kit();
- }
-
- m_fileFinder.setProjectFiles(sourceFiles(currentProject));
+ m_fileFinder.setProjectFiles(sourceFiles(project));
- if (currentProject)
- m_fileFinder.setProjectDirectory(currentProject->projectDirectory());
+ if (project)
+ m_fileFinder.setProjectDirectory(project->projectDirectory());
if (kit) {
m_fileFinder.setAdditionalSearchDirectories(collectQtIncludePaths(kit));
diff --git a/src/plugins/perfprofiler/perfprofilertool.h b/src/plugins/perfprofiler/perfprofilertool.h
index 7c0296b28d..8f36cfc7d0 100644
--- a/src/plugins/perfprofiler/perfprofilertool.h
+++ b/src/plugins/perfprofiler/perfprofilertool.h
@@ -48,7 +48,7 @@ class PerfProfilerTool : public QObject
{
Q_OBJECT
public:
- PerfProfilerTool(QObject *parent = nullptr);
+ PerfProfilerTool();
static PerfProfilerTool *instance();
PerfProfilerTraceManager *traceManager() const;
@@ -88,7 +88,8 @@ private:
void clear();
friend class PerfProfilerRunner;
- void populateFileFinder(const ProjectExplorer::RunConfiguration *rc = nullptr);
+ void populateFileFinder(const ProjectExplorer::Project *project,
+ const ProjectExplorer::Kit *kit);
void updateFilterMenu();
void updateRunActions();
void addLoadSaveActionsToMenu(QMenu *menu);
diff --git a/src/plugins/perfprofiler/perfprofilertracefile.cpp b/src/plugins/perfprofiler/perfprofilertracefile.cpp
index 7359e8f5d4..c6ea883c79 100644
--- a/src/plugins/perfprofiler/perfprofilertracefile.cpp
+++ b/src/plugins/perfprofiler/perfprofilertracefile.cpp
@@ -33,12 +33,11 @@
namespace PerfProfiler {
namespace Internal {
-Q_STATIC_ASSERT(sizeof(Constants::PerfStreamMagic) == sizeof(Constants::PerfQzfileMagic));
Q_STATIC_ASSERT(sizeof(Constants::PerfStreamMagic) == sizeof(Constants::PerfZqfileMagic));
PerfProfilerTraceFile::PerfProfilerTraceFile(QObject *parent) :
Timeline::TimelineTraceFile(parent), m_messageSize(0),
- m_dataStreamVersion(-1), m_compressed(false), m_mangledPackets(false)
+ m_dataStreamVersion(-1), m_compressed(false)
{
// This should result in either a direct or a queued connection, depending on where the signal
// comes from. readMessages() should always run in the GUI thread.
@@ -166,88 +165,91 @@ void PerfProfilerTraceFile::readMessages(const QByteArray &buffer)
QDataStream dataStream(buffer);
dataStream.setVersion(m_dataStreamVersion);
- while (!dataStream.atEnd()) {
- PerfEvent event;
- dataStream >> event;
-
- const qint64 timestamp = event.timestamp();
- if (timestamp > 0)
- event.setTimestamp(adjustTimestamp(timestamp));
-
- qint32 id = -1;
- switch (event.feature()) {
- case PerfEventType::LocationDefinition: {
- PerfEventType location(PerfEventType::LocationDefinition);
- dataStream >> id >> location;
- traceManager->setEventType(id, std::move(location));
- break;
- }
- case PerfEventType::SymbolDefinition: {
- PerfProfilerTraceManager::Symbol symbol;
- dataStream >> id >> symbol;
- traceManager->setSymbol(id, symbol);
- break;
- }
- case PerfEventType::AttributesDefinition: {
- PerfEventType attributes(PerfEventType::AttributesDefinition);
- dataStream >> id >> attributes;
- traceManager->setEventType(PerfEvent::LastSpecialTypeId - id, std::move(attributes));
- break;
- }
- case PerfEventType::StringDefinition: {
- QByteArray string;
- dataStream >> id >> string;
- traceManager->setString(id, string);
- break;
- }
- case PerfEventType::FeaturesDefinition: {
- PerfFeatures features;
- dataStream >> features;
- break;
- }
- case PerfEventType::Error: {
- qint32 errorCode;
- QString message;
- dataStream >> errorCode >> message;
- break;
- }
- case PerfEventType::Progress: {
- float progress;
- dataStream >> progress;
- break;
- }
- case PerfEventType::TracePointFormat: {
- PerfProfilerTraceManager::TracePoint tracePoint;
- dataStream >> id >> tracePoint;
- traceManager->setTracePoint(id, tracePoint);
- break;
- }
- case PerfEventType::Command: {
- PerfProfilerTraceManager::Thread thread;
- dataStream >> thread;
- traceManager->setThread(thread.tid, thread);
- break;
- }
- case PerfEventType::ThreadStart:
- case PerfEventType::ThreadEnd:
- case PerfEventType::LostDefinition:
- if (acceptsSamples())
- traceManager->appendEvent(std::move(event));
- break;
- case PerfEventType::Sample43:
- case PerfEventType::Sample:
- case PerfEventType::TracePointSample:
- if (acceptsSamples())
- traceManager->appendSampleEvent(std::move(event));
- break;
- }
-
- if (!m_mangledPackets) {
- if (!dataStream.atEnd())
- qWarning() << "Read only part of message";
- break;
+ PerfEvent event;
+ dataStream >> event;
+
+ const qint64 timestamp = event.timestamp();
+ if (timestamp > 0)
+ event.setTimestamp(adjustTimestamp(timestamp));
+
+ qint32 id = -1;
+ switch (event.feature()) {
+ case PerfEventType::LocationDefinition: {
+ PerfEventType location(PerfEventType::LocationDefinition);
+ dataStream >> id >> location;
+ for (int parent = location.location().parentLocationId; parent != -1;
+ parent = traceManager->location(parent).parentLocationId) {
+ if (parent == id) {
+ qWarning() << "A location cannot be its own parent location:" << id;
+ location = PerfEventType(PerfEventType::LocationDefinition);
+ break;
+ }
}
+ traceManager->setEventType(id, std::move(location));
+ break;
+ }
+ case PerfEventType::SymbolDefinition: {
+ PerfProfilerTraceManager::Symbol symbol;
+ dataStream >> id >> symbol;
+ traceManager->setSymbol(id, symbol);
+ break;
+ }
+ case PerfEventType::AttributesDefinition: {
+ PerfEventType attributes(PerfEventType::AttributesDefinition);
+ dataStream >> id >> attributes;
+ traceManager->setEventType(PerfEvent::LastSpecialTypeId - id, std::move(attributes));
+ break;
+ }
+ case PerfEventType::StringDefinition: {
+ QByteArray string;
+ dataStream >> id >> string;
+ traceManager->setString(id, string);
+ break;
+ }
+ case PerfEventType::FeaturesDefinition: {
+ PerfFeatures features;
+ dataStream >> features;
+ break;
+ }
+ case PerfEventType::Error: {
+ qint32 errorCode;
+ QString message;
+ dataStream >> errorCode >> message;
+ break;
}
+ case PerfEventType::Progress: {
+ float progress;
+ dataStream >> progress;
+ break;
+ }
+ case PerfEventType::TracePointFormat: {
+ PerfProfilerTraceManager::TracePoint tracePoint;
+ dataStream >> id >> tracePoint;
+ traceManager->setTracePoint(id, tracePoint);
+ break;
+ }
+ case PerfEventType::Command: {
+ PerfProfilerTraceManager::Thread thread;
+ dataStream >> thread;
+ traceManager->setThread(thread.tid, thread);
+ break;
+ }
+ case PerfEventType::ThreadStart:
+ case PerfEventType::ThreadEnd:
+ case PerfEventType::LostDefinition:
+ case PerfEventType::ContextSwitchDefinition:
+ if (acceptsSamples())
+ traceManager->appendEvent(std::move(event));
+ break;
+ case PerfEventType::Sample:
+ case PerfEventType::TracePointSample:
+ if (acceptsSamples())
+ traceManager->appendSampleEvent(std::move(event));
+ break;
+ }
+
+ if (!dataStream.atEnd())
+ qWarning() << "Read only part of message";
}
void PerfProfilerTraceFile::readFromDevice()
@@ -257,19 +259,18 @@ void PerfProfilerTraceFile::readFromDevice()
if (m_device->bytesAvailable() < magicSize + static_cast<int>(sizeof(qint32)))
return;
- QVarLengthArray<char> magic(magicSize);
+ QByteArray magic(magicSize, 0);
m_device->read(magic.data(), magicSize);
if (strncmp(magic.data(), Constants::PerfStreamMagic, magicSize) == 0) {
m_compressed = false;
- m_mangledPackets = false;
- } else if (strncmp(magic.data(), Constants::PerfQzfileMagic, magicSize) == 0) {
- m_compressed = true;
- m_mangledPackets = true;
} else if (strncmp(magic.data(), Constants::PerfZqfileMagic, magicSize) == 0) {
m_compressed = true;
- m_mangledPackets = false;
} else {
- fail(tr("Invalid data format"));
+ fail(tr("Invalid data format. The trace file's identification string is \"%1\"."
+ "An acceptable trace file should have \"%2\". You cannot read trace files "
+ "generated with older versions of Qt Creator.")
+ .arg(QString::fromLatin1(magic))
+ .arg(QString::fromLatin1(Constants::PerfZqfileMagic)));
return;
}
@@ -278,7 +279,10 @@ void PerfProfilerTraceFile::readFromDevice()
if (m_dataStreamVersion < 0
|| m_dataStreamVersion > QDataStream::Qt_DefaultCompiledVersion) {
- fail(tr("Invalid data format"));
+ fail(tr("Invalid data format. The trace file was written with data stream version %1. "
+ "We can read at most version %2. Please use a newer version of Qt.")
+ .arg(m_dataStreamVersion)
+ .arg(qint32(QDataStream::Qt_DefaultCompiledVersion)));
return;
}
}
@@ -296,8 +300,6 @@ void PerfProfilerTraceFile::readFromDevice()
m_messageSize = 0;
if (!m_compressed)
emit messagesAvailable(buffer);
- else if (m_mangledPackets)
- emit messagesAvailable(qUncompress(buffer));
else
emit blockAvailable(qUncompress(buffer));
diff --git a/src/plugins/perfprofiler/perfprofilertracefile.h b/src/plugins/perfprofiler/perfprofilertracefile.h
index ac58cfe168..756ba2902d 100644
--- a/src/plugins/perfprofiler/perfprofilertracefile.h
+++ b/src/plugins/perfprofiler/perfprofilertracefile.h
@@ -71,7 +71,6 @@ protected:
quint32 m_messageSize;
qint32 m_dataStreamVersion;
bool m_compressed;
- bool m_mangledPackets;
};
} // namespace Internal
diff --git a/src/plugins/perfprofiler/perfprofilertracemanager.cpp b/src/plugins/perfprofiler/perfprofilertracemanager.cpp
index 79bd1a05ad..75c31af32a 100644
--- a/src/plugins/perfprofiler/perfprofilertracemanager.cpp
+++ b/src/plugins/perfprofiler/perfprofilertracemanager.cpp
@@ -217,6 +217,10 @@ void PerfProfilerTraceManager::resetAttributes()
tr("Thread ended")));
setEventType(PerfEvent::LostTypeId, PerfEventType(PerfEventType::LostDefinition,
tr("Samples lost")));
+ setEventType(PerfEvent::ContextSwitchTypeId,
+ PerfEventType(PerfEventType::ContextSwitchDefinition, tr("Context switch")));
+ setEventType(PerfEvent::LastSpecialTypeId,
+ PerfEventType(PerfEventType::InvalidFeature, tr("Invalid")));
}
void PerfProfilerTraceManager::finalize()
@@ -279,7 +283,7 @@ void PerfProfilerTraceManager::replayPerfEvents(PerfEventLoader loader, Initiali
QTC_ASSERT(traceEvent.is<PerfEvent>(), return false);
PerfEvent &&event = traceEvent.asRvalueRef<PerfEvent>();
processSample(event);
- loader(event, eventType(event.typeIndex()));
+ loader(event, eventType(event.attributeId(0)));
return true;
});
@@ -397,13 +401,13 @@ int PerfProfilerEventTypeStorage::append(Timeline::TraceEventType &&type)
if (perfType.isLocation()) {
const size_t index = m_locations.size();
m_locations.push_back(perfType);
- QTC_ASSERT(index <= std::numeric_limits<int>::max(),
+ QTC_ASSERT(index <= size_t(std::numeric_limits<int>::max()),
return std::numeric_limits<int>::max());
return static_cast<int>(index);
} else if (perfType.isAttribute()) {
const size_t index = m_attributes.size();
m_attributes.push_back(perfType);
- QTC_ASSERT(index <= std::numeric_limits<int>::max(),
+ QTC_ASSERT(index <= size_t(std::numeric_limits<int>::max()),
return -std::numeric_limits<int>::max());
return -static_cast<int>(index);
}
@@ -414,7 +418,8 @@ int PerfProfilerEventTypeStorage::append(Timeline::TraceEventType &&type)
int PerfProfilerEventTypeStorage::size() const
{
const size_t result = m_attributes.size() + m_locations.size();
- QTC_ASSERT(result <= std::numeric_limits<int>::max(), return std::numeric_limits<int>::max());
+ QTC_ASSERT(result <= size_t(std::numeric_limits<int>::max()),
+ return std::numeric_limits<int>::max());
return static_cast<int>(result);
}
diff --git a/src/plugins/perfprofiler/perfprofilertracemanager.h b/src/plugins/perfprofiler/perfprofilertracemanager.h
index f663af3f3e..b35c6f1bd8 100644
--- a/src/plugins/perfprofiler/perfprofilertracemanager.h
+++ b/src/plugins/perfprofiler/perfprofilertracemanager.h
@@ -71,9 +71,9 @@ public:
struct Thread {
Thread(qint64 start = -1, qint64 firstEvent = -1, qint64 lastEvent = -1, quint32 pid = 0,
- quint32 tid = 0, qint32 name = -1, bool enabled = false) :
+ quint32 tid = 0, quint32 cpu = 0, qint32 name = -1, bool enabled = false) :
start(start), firstEvent(firstEvent), lastEvent(lastEvent), pid(pid), tid(tid),
- name(name), enabled(enabled)
+ cpu(cpu), name(name), enabled(enabled)
{}
qint64 start;
@@ -81,15 +81,17 @@ public:
qint64 lastEvent;
quint32 pid;
quint32 tid;
+ quint32 cpu;
qint32 name;
bool enabled;
};
struct Symbol {
- Symbol() : name(-1), binary(-1), isKernel(false) {}
+ Symbol() : name(-1), binary(-1), path(-1), isKernel(false) {}
qint32 name;
qint32 binary;
+ qint32 path;
bool isKernel;
};
@@ -217,12 +219,12 @@ private:
inline QDataStream &operator>>(QDataStream &stream, PerfProfilerTraceManager::Symbol &symbol)
{
- return stream >> symbol.name >> symbol.binary >> symbol.isKernel;
+ return stream >> symbol.name >> symbol.binary >> symbol.path >> symbol.isKernel;
}
inline QDataStream &operator<<(QDataStream &stream, const PerfProfilerTraceManager::Symbol &symbol)
{
- return stream << symbol.name << symbol.binary << symbol.isKernel;
+ return stream << symbol.name << symbol.binary << symbol.path << symbol.isKernel;
}
inline QDataStream &operator>>(QDataStream &stream,
@@ -239,14 +241,14 @@ inline QDataStream &operator<<(QDataStream &stream,
inline QDataStream &operator>>(QDataStream &stream, PerfProfilerTraceManager::Thread &thread)
{
- stream >> thread.pid >> thread.tid >> thread.start >> thread.name;
+ stream >> thread.pid >> thread.tid >> thread.start >> thread.cpu >> thread.name;
thread.enabled = (thread.pid != 0);
return stream;
}
inline QDataStream &operator<<(QDataStream &stream, const PerfProfilerTraceManager::Thread &thread)
{
- return stream << thread.pid << thread.tid << thread.start << thread.name;
+ return stream << thread.pid << thread.tid << thread.start << thread.cpu << thread.name;
}
diff --git a/src/plugins/perfprofiler/perfprofilertraceview.cpp b/src/plugins/perfprofiler/perfprofilertraceview.cpp
index a55bdd4830..69ac873686 100644
--- a/src/plugins/perfprofiler/perfprofilertraceview.cpp
+++ b/src/plugins/perfprofiler/perfprofilertraceview.cpp
@@ -74,11 +74,7 @@ PerfProfilerTraceView::PerfProfilerTraceView(QWidget *parent, PerfProfilerTool *
bool PerfProfilerTraceView::isUsable() const
{
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
return quickWindow()->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL;
-#else
- return true;
-#endif
}
void PerfProfilerTraceView::selectByTypeId(int typeId)
diff --git a/src/plugins/perfprofiler/perfresourcecounter.cpp b/src/plugins/perfprofiler/perfresourcecounter.cpp
index e9935c334c..daae6be651 100644
--- a/src/plugins/perfprofiler/perfresourcecounter.cpp
+++ b/src/plugins/perfprofiler/perfresourcecounter.cpp
@@ -29,6 +29,5 @@
namespace PerfProfiler {
namespace Internal {
-
} // namespace Internal
} // namespace PerfProfiler
diff --git a/src/plugins/perfprofiler/perfrunconfigurationaspect.cpp b/src/plugins/perfprofiler/perfrunconfigurationaspect.cpp
index 498fd61b7b..03509751f1 100644
--- a/src/plugins/perfprofiler/perfrunconfigurationaspect.cpp
+++ b/src/plugins/perfprofiler/perfrunconfigurationaspect.cpp
@@ -35,7 +35,7 @@ namespace PerfProfiler {
PerfRunConfigurationAspect::PerfRunConfigurationAspect(ProjectExplorer::Target *target)
{
setProjectSettings(new PerfSettings(target));
- setGlobalSettings(PerfProfilerPlugin::globalSettings());
+ setGlobalSettings(Internal::PerfProfilerPlugin::globalSettings());
setId(Constants::PerfSettingsId);
setDisplayName(QCoreApplication::translate("PerfProfiler::PerfRunConfigurationAspect",
"Performance Analyzer Settings"));
diff --git a/src/plugins/perfprofiler/perfsettings.h b/src/plugins/perfprofiler/perfsettings.h
index 7ccfe5638d..85d506c9a5 100644
--- a/src/plugins/perfprofiler/perfsettings.h
+++ b/src/plugins/perfprofiler/perfsettings.h
@@ -40,7 +40,7 @@ class PERFPROFILER_EXPORT PerfSettings : public ProjectExplorer::ISettingsAspect
public:
explicit PerfSettings(ProjectExplorer::Target *target = nullptr);
- ~PerfSettings();
+ ~PerfSettings() final;
void readGlobalSettings();
void writeGlobalSettings() const;
@@ -66,8 +66,8 @@ signals:
void changed();
protected:
- void toMap(QVariantMap &map) const;
- void fromMap(const QVariantMap &map);
+ void toMap(QVariantMap &map) const final;
+ void fromMap(const QVariantMap &map) final;
int m_period;
int m_stackSize;
diff --git a/src/plugins/perfprofiler/perftimelinemodel.cpp b/src/plugins/perfprofiler/perftimelinemodel.cpp
index c2a383161b..c16ff5d260 100644
--- a/src/plugins/perfprofiler/perftimelinemodel.cpp
+++ b/src/plugins/perfprofiler/perftimelinemodel.cpp
@@ -166,11 +166,12 @@ QVariantMap PerfTimelineModel::details(int index) const
manager->traceDuration()));
const int guessedFrames = -frame.numSamples;
if (guessedFrames > 0)
- result.insert(tr("Guessed"), tr("%1 frames").arg(guessedFrames));
- if (const int sampleWeight = weight(index))
- result.insert(tr("Weight"), sampleWeight);
- if (const int samplePeriod = period(index))
- result.insert(tr("Period"), samplePeriod);
+ result.insert(tr("Guessed"), tr("%n frames", nullptr, guessedFrames));
+ for (int i = 0, end = numAttributes(index); i < end; ++i) {
+ const auto &name = orUnknown(manager->string(
+ manager->attribute(attributeId(index, i)).name));
+ result.insert(QString::fromUtf8(name), attributeValue(index, i));
+ }
if (attribute.type == PerfEventType::TypeTracepoint) {
const PerfProfilerTraceManager::TracePoint &tracePoint
= manager->tracePoint(static_cast<int>(attribute.config));
@@ -198,6 +199,10 @@ QVariantMap PerfTimelineModel::details(int index) const
result.insert(tr("Details"), tr("lost sample"));
result.insert(tr("Timestamp"), Timeline::formatTime(startTime(index),
manager->traceDuration()));
+ } else if (typeId == PerfEvent::ContextSwitchTypeId) {
+ result.insert(tr("Details"), tr("context switch"));
+ result.insert(tr("Timestamp"), Timeline::formatTime(startTime(index),
+ manager->traceDuration()));
} else {
const PerfProfilerTraceManager::Symbol &symbol
= manager->symbol(manager->aggregateAddresses()
@@ -281,8 +286,11 @@ float PerfTimelineModel::relativeHeight(int index) const
void PerfTimelineModel::updateTraceData(const PerfEvent &event)
{
const PerfProfilerTraceManager *manager = traceManager();
- const PerfEventType::Attribute &attribute = manager->attribute(event.typeIndex());
- if (attribute.type == PerfEventType::TypeTracepoint) {
+ for (int i = 0; i < event.numAttributes(); ++i) {
+ const PerfEventType::Attribute &attribute = manager->attribute(event.attributeId(i));
+ if (attribute.type != PerfEventType::TypeTracepoint)
+ continue;
+
const PerfProfilerTraceManager::TracePoint &tracePoint
= manager->tracePoint(static_cast<int>(attribute.config));
@@ -400,29 +408,30 @@ void PerfTimelineModel::updateFrames(const PerfEvent &event, int numConcurrentTh
void PerfTimelineModel::addSample(const PerfEvent &event, qint64 resourceDelta, int resourceGuesses)
{
- static const int intMax = std::numeric_limits<int>::max();
- const int period = static_cast<int>(qMin(static_cast<quint64>(intMax), event.period()));
- const int weight = static_cast<int>(qMin(static_cast<quint64>(intMax), event.weight()));
-
- const int id = TimelineModel::insert(event.timestamp(), 1, event.typeIndex());
+ const int id = TimelineModel::insert(event.timestamp(), 1, event.attributeId(0));
StackFrame sample = StackFrame::sampleFrame();
+ sample.attributeValue = event.attributeValue(0);
sample.numSamples = event.numGuessedFrames() > 0 ? -event.numGuessedFrames() : 1;
- sample.period = period;
- sample.weight = weight;
sample.resourcePeak = m_resourceBlocks.currentTotal();
sample.resourceDelta = resourceDelta;
sample.resourceGuesses = resourceGuesses;
+ sample.numAttributes = event.numAttributes();
m_data.insert(id, std::move(sample));
const QHash<qint32, QVariant> &traceData = event.traceData();
if (!traceData.isEmpty())
m_extraData.insert(id, traceData);
+ for (int i = 1, end = sample.numAttributes; i < end; ++i) {
+ m_attributeValues[id].append(QPair<qint32, quint64>(event.attributeId(i),
+ event.attributeValue(i)));
+ }
+
m_lastTimestamp = event.timestamp();
}
void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThreads)
{
- switch (event.typeIndex()) {
+ switch (event.attributeId(0)) {
case PerfEvent::LostTypeId: {
QVector<int> frames;
for (int pos = m_currentStack.length() - 1; pos >= 0; --pos)
@@ -438,6 +447,11 @@ void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThrea
addSample(guessed, 0, 0);
break;
}
+ case PerfEvent::ContextSwitchTypeId: {
+ const int id = TimelineModel::insert(event.timestamp(), 1, PerfEvent::ContextSwitchTypeId);
+ m_data.insert(id, StackFrame::sampleFrame());
+ break;
+ }
case PerfEvent::ThreadStartTypeId: {
if (m_threadStartTimestamp < 0 || event.timestamp() <= m_threadStartTimestamp)
m_threadStartTimestamp = event.timestamp() - 1;
@@ -459,7 +473,7 @@ void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThrea
break;
}
default: {
- QTC_ASSERT(event.typeIndex() <= PerfEvent::LastSpecialTypeId, break);
+ QTC_ASSERT(event.attributeId(0) <= PerfEvent::LastSpecialTypeId, break);
if (event.timestamp() < 0) {
updateTraceData(event);
@@ -603,14 +617,19 @@ float PerfTimelineModel::resourceUsage(int index) const
: 0.0f;
}
-int PerfTimelineModel::period(int index) const
+qint32 PerfTimelineModel::attributeId(int index, int i) const
+{
+ return (i == 0) ? selectionId(index) : m_attributeValues[index][i].first;
+}
+
+int PerfTimelineModel::numAttributes(int index) const
{
- return m_data[index].period;
+ return m_data[index].numAttributes;
}
-int PerfTimelineModel::weight(int index) const
+quint64 PerfTimelineModel::attributeValue(int index, int i) const
{
- return m_data[index].weight;
+ return (i == 0) ? m_data[index].attributeValue : m_attributeValues[index][i].second;
}
bool PerfTimelineModel::handlesTypeId(int typeId) const
diff --git a/src/plugins/perfprofiler/perftimelinemodel.h b/src/plugins/perfprofiler/perftimelinemodel.h
index d6d5c88e99..a2ef90dc96 100644
--- a/src/plugins/perfprofiler/perftimelinemodel.h
+++ b/src/plugins/perfprofiler/perftimelinemodel.h
@@ -88,8 +88,9 @@ public:
return selectionId(index) <= PerfEvent::LastSpecialTypeId;
}
- int period(int index) const;
- int weight(int index) const;
+ int numAttributes(int index) const;
+ qint32 attributeId(int index, int i) const;
+ quint64 attributeValue(int index, int i) const;
QHash<qint32, QVariant> extraData(int index) const { return m_extraData.value(index); }
@@ -105,12 +106,12 @@ private:
int numExpectedParallelSamples = 1;
int displayRowCollapsed = MaximumSpecialRow;
int displayRowExpanded = MaximumSpecialRow;
- int period = 0;
- int weight = 0;
+ quint64 attributeValue = 0;
qint64 resourcePeak = 0;
qint64 resourceDelta = 0;
int resourceGuesses = 0;
+ int numAttributes = 0;
static StackFrame sampleFrame()
{
@@ -150,6 +151,7 @@ private:
QVector<StackFrame> m_data;
QHash<int, QHash<qint32, QVariant>> m_extraData;
+ QHash<int, QVector<QPair<qint32, quint64>>> m_attributeValues;
void computeExpandedLevels();
const PerfProfilerTraceManager *traceManager() const;
diff --git a/src/plugins/perfprofiler/perftracepointdialog.cpp b/src/plugins/perfprofiler/perftracepointdialog.cpp
index f4eef92c9b..5dc638bbbe 100644
--- a/src/plugins/perfprofiler/perftracepointdialog.cpp
+++ b/src/plugins/perfprofiler/perftracepointdialog.cpp
@@ -29,9 +29,13 @@
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
+#include <utils/qtcassert.h>
+
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
@@ -52,7 +56,7 @@ PerfTracePointDialog::PerfTracePointDialog() :
const Kit *kit = target->kit();
QTC_ASSERT(kit, return);
- m_device = DeviceKitInformation::device(kit);
+ m_device = DeviceKitAspect::device(kit);
if (!m_device) {
m_ui->textEdit->setPlainText(tr("Error: No device available for active target."));
return;
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index b85252288d..102e8eda76 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -59,7 +59,8 @@ SUBDIRS = \
languageclient \
cppcheck \
compilationdatabaseprojectmanager \
- qmlpreview
+ qmlpreview \
+ studiowelcome
qtHaveModule(serialport) {
SUBDIRS += serialterminal
@@ -85,8 +86,8 @@ qtHaveModule(designercomponents_private) {
warning("Qt Widget Designer plugin has been disabled since the Qt Designer module is not available.")
}
-DO_NOT_BUILD_QMLDESIGNER = $$(DO_NOT_BUILD_QMLDESIGNER)
-isEmpty(DO_NOT_BUILD_QMLDESIGNER):qtHaveModule(quick-private) {
+QTC_DO_NOT_BUILD_QMLDESIGNER = $$(QTC_DO_NOT_BUILD_QMLDESIGNER)
+isEmpty(QTC_DO_NOT_BUILD_QMLDESIGNER):qtHaveModule(quick-private) {
exists($$[QT_INSTALL_QML]/QtQuick/Controls/qmldir) {
SUBDIRS += qmldesigner
} else {
@@ -96,7 +97,7 @@ isEmpty(DO_NOT_BUILD_QMLDESIGNER):qtHaveModule(quick-private) {
!qtHaveModule(quick-private) {
warning("QmlDesigner plugin has been disabled since the Qt Quick module is not available.")
} else {
- warning("QmlDesigner plugin has been disabled since DO_NOT_BUILD_QMLDESIGNER is set.")
+ warning("QmlDesigner plugin has been disabled since QTC_DO_NOT_BUILD_QMLDESIGNER is set.")
}
}
@@ -109,12 +110,10 @@ exists(../shared/qbs/qbs.pro)|!isEmpty(QBS_INSTALL_DIR): \
SUBDIRS += \
clangcodemodel
-QTC_ENABLE_CLANG_LIBTOOLING=$$(QTC_ENABLE_CLANG_LIBTOOLING)
-!isEmpty(QTC_ENABLE_CLANG_LIBTOOLING) {
+QTC_DISABLE_CLANG_REFACTORING=$$(QTC_DISABLE_CLANG_REFACTORING)
+isEmpty(QTC_DISABLE_CLANG_REFACTORING) {
SUBDIRS += clangrefactoring
SUBDIRS += clangpchmanager
-} else {
- warning("Not building the clang refactoring plugin and the pch manager plugin.")
}
isEmpty(IDE_PACKAGE_MODE) {
diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt
new file mode 100644
index 0000000000..c9413c2385
--- /dev/null
+++ b/src/plugins/projectexplorer/CMakeLists.txt
@@ -0,0 +1,215 @@
+add_qtc_plugin(ProjectExplorer
+ DEPENDS QtcSsh Qt5::Qml
+ PLUGIN_DEPENDS Core TextEditor
+ SOURCES
+ abi.cpp abi.h
+ abiwidget.cpp abiwidget.h
+ abstractprocessstep.cpp abstractprocessstep.h
+ addrunconfigdialog.cpp addrunconfigdialog.h
+ allprojectsfilter.cpp allprojectsfilter.h
+ allprojectsfind.cpp allprojectsfind.h
+ ansifilterparser.cpp ansifilterparser.h
+ applicationlauncher.cpp applicationlauncher.h
+ appoutputpane.cpp appoutputpane.h
+ baseprojectwizarddialog.cpp baseprojectwizarddialog.h
+ buildconfiguration.cpp buildconfiguration.h
+ buildenvironmentwidget.cpp buildenvironmentwidget.h
+ buildinfo.cpp buildinfo.h
+ buildmanager.cpp buildmanager.h
+ buildprogress.cpp buildprogress.h
+ buildsettingspropertiespage.cpp buildsettingspropertiespage.h
+ buildstep.cpp buildstep.h
+ buildsteplist.cpp buildsteplist.h
+ buildstepspage.cpp buildstepspage.h
+ buildtargetinfo.h
+ clangparser.cpp clangparser.h
+ codestylesettingspropertiespage.cpp codestylesettingspropertiespage.h codestylesettingspropertiespage.ui
+ compileoutputwindow.cpp compileoutputwindow.h
+ configtaskhandler.cpp configtaskhandler.h
+ copytaskhandler.cpp copytaskhandler.h
+ currentprojectfilter.cpp currentprojectfilter.h
+ currentprojectfind.cpp currentprojectfind.h
+ customexecutablerunconfiguration.cpp customexecutablerunconfiguration.h
+ customparser.cpp customparser.h
+ customparserconfigdialog.cpp customparserconfigdialog.h customparserconfigdialog.ui
+ customtoolchain.cpp customtoolchain.h
+ customwizard/customwizard.cpp customwizard/customwizard.h
+ customwizard/customwizardpage.cpp customwizard/customwizardpage.h
+ customwizard/customwizardparameters.cpp customwizard/customwizardparameters.h
+ customwizard/customwizardscriptgenerator.cpp customwizard/customwizardscriptgenerator.h
+ dependenciespanel.cpp dependenciespanel.h
+ deployablefile.cpp deployablefile.h
+ deployconfiguration.cpp deployconfiguration.h
+ deploymentdata.cpp deploymentdata.h
+ deploymentdatamodel.cpp deploymentdatamodel.h
+ deploymentdataview.cpp deploymentdataview.h deploymentdataview.ui
+ devicesupport/desktopdevice.cpp devicesupport/desktopdevice.h
+ devicesupport/desktopdeviceconfigurationwidget.cpp devicesupport/desktopdeviceconfigurationwidget.h devicesupport/desktopdeviceconfigurationwidget.ui
+ 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/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/idevice.cpp devicesupport/idevice.h
+ devicesupport/idevicefactory.cpp devicesupport/idevicefactory.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/sshsettingspage.cpp devicesupport/sshsettingspage.h
+ editorconfiguration.cpp editorconfiguration.h
+ editorsettingspropertiespage.cpp editorsettingspropertiespage.h editorsettingspropertiespage.ui
+ environmentaspect.cpp environmentaspect.h
+ environmentaspectwidget.cpp environmentaspectwidget.h
+ environmentwidget.cpp environmentwidget.h
+ expanddata.cpp expanddata.h
+ extraabi.cpp extraabi.h
+ extracompiler.cpp extracompiler.h
+ fileinsessionfinder.cpp fileinsessionfinder.h
+ filterkitaspectsdialog.cpp filterkitaspectsdialog.h
+ foldernavigationwidget.cpp foldernavigationwidget.h
+ gccparser.cpp gccparser.h
+ gcctoolchain.cpp gcctoolchain.h
+ gcctoolchainfactories.h
+ gnumakeparser.cpp gnumakeparser.h
+ headerpath.h
+ importwidget.cpp importwidget.h
+ ioutputparser.cpp ioutputparser.h
+ ipotentialkit.h
+ itaskhandler.h
+ jsonwizard/jsonfieldpage.cpp jsonwizard/jsonfieldpage.h jsonwizard/jsonfieldpage_p.h
+ jsonwizard/jsonfilepage.cpp jsonwizard/jsonfilepage.h
+ jsonwizard/jsonkitspage.cpp jsonwizard/jsonkitspage.h
+ jsonwizard/jsonprojectpage.cpp jsonwizard/jsonprojectpage.h
+ jsonwizard/jsonsummarypage.cpp jsonwizard/jsonsummarypage.h
+ jsonwizard/jsonwizard.cpp jsonwizard/jsonwizard.h
+ jsonwizard/jsonwizardfactory.cpp jsonwizard/jsonwizardfactory.h
+ jsonwizard/jsonwizardfilegenerator.cpp jsonwizard/jsonwizardfilegenerator.h
+ jsonwizard/jsonwizardgeneratorfactory.cpp jsonwizard/jsonwizardgeneratorfactory.h
+ jsonwizard/jsonwizardpagefactory.cpp jsonwizard/jsonwizardpagefactory.h
+ jsonwizard/jsonwizardpagefactory_p.cpp
+ jsonwizard/jsonwizardpagefactory_p.h
+ jsonwizard/jsonwizardscannergenerator.cpp jsonwizard/jsonwizardscannergenerator.h
+ kit.cpp kit.h
+ kitchooser.cpp kitchooser.h
+ kitfeatureprovider.h
+ kitinformation.cpp kitinformation.h
+ kitmanager.cpp kitmanager.h
+ kitmanagerconfigwidget.cpp kitmanagerconfigwidget.h
+ kitmodel.cpp kitmodel.h
+ kitoptionspage.cpp kitoptionspage.h
+ ldparser.cpp ldparser.h
+ linuxiccparser.cpp linuxiccparser.h
+ localenvironmentaspect.cpp localenvironmentaspect.h
+ makestep.cpp makestep.h makestep.ui
+ miniprojecttargetselector.cpp miniprojecttargetselector.h
+ msvcparser.cpp msvcparser.h
+ msvctoolchain.cpp msvctoolchain.h
+ namedwidget.cpp namedwidget.h
+ osparser.cpp osparser.h
+ panelswidget.cpp panelswidget.h
+ parseissuesdialog.cpp parseissuesdialog.h
+ processparameters.cpp processparameters.h
+ processstep.cpp processstep.h
+ project.cpp project.h
+ projectconfiguration.cpp projectconfiguration.h
+ projectconfigurationaspects.cpp projectconfigurationaspects.h
+ projectconfigurationmodel.cpp projectconfigurationmodel.h
+ projectexplorer.cpp projectexplorer.h
+ projectexplorer.qrc
+ projectexplorer_export.h
+ projectexplorer_global.h
+ projectexplorerconstants.h
+ projectexplorericons.cpp projectexplorericons.h
+ projectexplorersettings.h
+ projectexplorersettingspage.cpp projectexplorersettingspage.h projectexplorersettingspage.ui
+ projectfilewizardextension.cpp projectfilewizardextension.h
+ projectimporter.cpp projectimporter.h
+ projectmacro.cpp projectmacro.h
+ projectmacroexpander.cpp projectmacroexpander.h
+ projectmanager.h
+ projectmodels.cpp projectmodels.h
+ projectnodes.cpp projectnodes.h
+ projectpanelfactory.cpp projectpanelfactory.h
+ projecttree.cpp projecttree.h
+ projecttreewidget.cpp projecttreewidget.h
+ projectwelcomepage.cpp projectwelcomepage.h
+ projectwindow.cpp projectwindow.h
+ projectwizardpage.cpp projectwizardpage.h projectwizardpage.ui
+ removetaskhandler.cpp removetaskhandler.h
+ runconfiguration.cpp runconfiguration.h
+ runconfigurationaspects.cpp runconfigurationaspects.h
+ runcontrol.cpp runcontrol.h
+ runsettingspropertiespage.cpp runsettingspropertiespage.h
+ selectablefilesmodel.cpp selectablefilesmodel.h
+ session.cpp session.h
+ sessiondialog.cpp sessiondialog.h sessiondialog.ui
+ sessionmodel.cpp sessionmodel.h
+ sessionview.cpp sessionview.h
+ showineditortaskhandler.cpp showineditortaskhandler.h
+ showoutputtaskhandler.cpp showoutputtaskhandler.h
+ subscription.cpp subscription.h
+ target.cpp target.h
+ targetsettingspanel.cpp targetsettingspanel.h
+ targetsetuppage.cpp targetsetuppage.h
+ targetsetupwidget.cpp targetsetupwidget.h
+ task.cpp task.h
+ taskhub.cpp taskhub.h
+ taskmodel.cpp taskmodel.h
+ taskwindow.cpp taskwindow.h
+ toolchain.cpp toolchain.h
+ toolchaincache.h
+ toolchainconfigwidget.cpp toolchainconfigwidget.h
+ toolchainmanager.cpp toolchainmanager.h
+ toolchainoptionspage.cpp toolchainoptionspage.h
+ toolchainsettingsaccessor.cpp toolchainsettingsaccessor.h
+ treescanner.cpp treescanner.h
+ userfileaccessor.cpp userfileaccessor.h
+ vcsannotatetaskhandler.cpp vcsannotatetaskhandler.h
+ waitforstopdialog.cpp waitforstopdialog.h
+ xcodebuildparser.cpp xcodebuildparser.h
+)
+
+if (TARGET libclang)
+ set(CLANG_BINDIR "$<TARGET_FILE_DIR:libclang>")
+endif()
+extend_qtc_plugin(ProjectExplorer
+ DEFINES "CLANG_BINDIR=\"${CLANG_BINDIR}\""
+)
+
+extend_qtc_plugin(ProjectExplorer
+ CONDITION WIN32
+ SOURCES windebuginterface.cpp windebuginterface.h
+ DEFINES UNICODE _UNICODE
+)
+
+extend_qtc_plugin(ProjectExplorer
+ CONDITION journald
+ DEPENDS systemd
+ SOURCES journaldwatcher.cpp journaldwatcher.h
+ DEFINES WITH_JOURNALD
+)
+
+extend_qtc_plugin(ProjectExplorer
+ CONDITION WITH_TESTS
+ SOURCES
+ jsonwizard/jsonwizard_test.cpp
+ outputparser_test.cpp outputparser_test.h
+)
+qtc_plugin_enabled(_projectexplorer_enabled ProjectExplorer)
+if (WITH_TESTS AND _projectexplorer_enabled)
+ set_source_files_properties(jsonwizard/jsonwizard_test.cpp
+ PROPERTIES HEADER_FILE_ONLY ON
+ )
+endif()
+
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index 0de4ea655d..e4e4c13e64 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -219,9 +219,9 @@ static Abi macAbiForCpu(quint32 type) {
}
}
-static QList<Abi> parseCoffHeader(const QByteArray &data)
+static Abis parseCoffHeader(const QByteArray &data)
{
- QList<Abi> result;
+ Abis result;
if (data.size() < 20)
return result;
@@ -305,9 +305,9 @@ static QList<Abi> parseCoffHeader(const QByteArray &data)
return result;
}
-static QList<Abi> abiOf(const QByteArray &data)
+static Abis abiOf(const QByteArray &data)
{
- QList<Abi> result;
+ Abis result;
if (data.size() <= 8)
return result;
@@ -626,8 +626,10 @@ bool Abi::isCompatibleWith(const Abi &other) const
if (isCompat && (osFlavor() == AndroidLinuxFlavor || other.osFlavor() == AndroidLinuxFlavor))
isCompat = (architecture() == other.architecture()) && (osFlavor() == other.osFlavor());
- if (!isCompat && compatibleMSVCFlavors(osFlavor(), other.osFlavor()))
+ if (!isCompat && wordWidth() == other.wordWidth()
+ && compatibleMSVCFlavors(osFlavor(), other.osFlavor())) {
isCompat = true;
+ }
return isCompat;
}
@@ -661,6 +663,8 @@ QString Abi::toString(const Architecture &a)
return QLatin1String("xtensa");
case X86Architecture:
return QLatin1String("x86");
+ case Mcs51Architecture:
+ return QLatin1String("mcs51");
case MipsArchitecture:
return QLatin1String("mips");
case PowerPCArchitecture:
@@ -722,6 +726,10 @@ QString Abi::toString(const BinaryFormat &bf)
return QLatin1String("mach_o");
case RuntimeQmlFormat:
return QLatin1String("qml_rt");
+ case UbrofFormat:
+ return QLatin1String("ubrof");
+ case OmfFormat:
+ return QLatin1String("omf");
case UnknownFormat:
Q_FALLTHROUGH();
default:
@@ -789,6 +797,8 @@ Abi::Architecture Abi::architectureFromString(const QStringRef &a)
return AvrArchitecture;
if (a == "x86")
return X86Architecture;
+ if (a == "mcs51")
+ return Mcs51Architecture;
if (a == "mips")
return MipsArchitecture;
if (a == "ppc")
@@ -845,6 +855,10 @@ Abi::BinaryFormat Abi::binaryFormatFromString(const QStringRef &bf)
return PEFormat;
if (bf == "mach_o")
return MachOFormat;
+ if (bf == "ubrof")
+ return UbrofFormat;
+ if (bf == "omf")
+ return OmfFormat;
if (bf == "qml_rt")
return RuntimeQmlFormat;
return UnknownFormat;
@@ -969,9 +983,9 @@ Abi Abi::hostAbi()
}
//! Extract available ABIs from a binary using heuristics.
-QList<Abi> Abi::abisOfBinary(const Utils::FileName &path)
+Abis Abi::abisOfBinary(const Utils::FilePath &path)
{
- QList<Abi> tmp;
+ Abis tmp;
if (path.isEmpty())
return tmp;
@@ -1024,8 +1038,8 @@ QList<Abi> Abi::abisOfBinary(const Utils::FileName &path)
f.close();
// Remove duplicates:
- QList<Abi> result;
- foreach (const Abi &a, tmp) {
+ Abis result;
+ for (const Abi &a : qAsConst(tmp)) {
if (!result.contains(a))
result.append(a);
}
@@ -1219,7 +1233,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary()
QFETCH(QString, file);
QFETCH(QStringList, abis);
- QList<Abi> result = Abi::abisOfBinary(Utils::FileName::fromString(file));
+ const Abis result = Abi::abisOfBinary(Utils::FilePath::fromString(file));
QCOMPARE(result.count(), abis.count());
for (int i = 0; i < abis.count(); ++i)
QCOMPARE(result.at(i).toString(), abis.at(i));
@@ -1301,26 +1315,10 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiFromTargetTriplet_data()
<< int(Abi::LinuxOS) << int(Abi::GenericFlavor)
<< int(Abi::ElfFormat) << 32;
- QTest::newRow("mipsel-linux-android") << int(Abi::MipsArchitecture)
- << int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
- << int(Abi::ElfFormat) << 32;
-
- QTest::newRow("mipsel-unknown-linux-android") << int(Abi::MipsArchitecture)
- << int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
- << int(Abi::ElfFormat) << 32;
-
QTest::newRow("mips-linux-gnu") << int(Abi::MipsArchitecture)
<< int(Abi::LinuxOS) << int(Abi::GenericFlavor)
<< int(Abi::ElfFormat) << 32;
- QTest::newRow("mips64el-linux-android") << int(Abi::MipsArchitecture)
- << int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
- << int(Abi::ElfFormat) << 64;
-
- QTest::newRow("mips64el-unknown-linux-android") << int(Abi::MipsArchitecture)
- << int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
- << int(Abi::ElfFormat) << 64;
-
QTest::newRow("mips64-linux-octeon-gnu") << int(Abi::MipsArchitecture)
<< int(Abi::LinuxOS) << int(Abi::GenericFlavor)
<< int(Abi::ElfFormat) << 64;
diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h
index 43243847c8..ddca225896 100644
--- a/src/plugins/projectexplorer/abi.h
+++ b/src/plugins/projectexplorer/abi.h
@@ -34,7 +34,7 @@
#include <vector>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ProjectExplorer {
@@ -42,6 +42,9 @@ namespace ProjectExplorer {
// ABI (documentation inside)
// --------------------------------------------------------------------------
+class Abi;
+using Abis = QVector<Abi>;
+
class PROJECTEXPLORER_EXPORT Abi
{
public:
@@ -54,6 +57,7 @@ public:
ShArchitecture,
AvrArchitecture,
XtensaArchitecture,
+ Mcs51Architecture,
UnknownArchitecture
};
@@ -108,6 +112,8 @@ public:
MachOFormat,
PEFormat,
RuntimeQmlFormat,
+ UbrofFormat,
+ OmfFormat,
UnknownFormat
};
@@ -154,7 +160,7 @@ public:
static Abi fromString(const QString &abiString);
static Abi hostAbi();
- static QList<Abi> abisOfBinary(const Utils::FileName &path);
+ static Abis abisOfBinary(const Utils::FilePath &path);
private:
diff --git a/src/plugins/projectexplorer/abiwidget.cpp b/src/plugins/projectexplorer/abiwidget.cpp
index 80b88ac03e..5df9a3ee05 100644
--- a/src/plugins/projectexplorer/abiwidget.cpp
+++ b/src/plugins/projectexplorer/abiwidget.cpp
@@ -85,7 +85,7 @@ AbiWidget::AbiWidget(QWidget *parent) : QWidget(parent),
d->m_abi->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
d->m_abi->setMinimumContentsLength(4);
layout->addWidget(d->m_abi);
- connect(d->m_abi, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(d->m_abi, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AbiWidget::mainComboBoxChanged);
d->m_architectureComboBox = new QComboBox(this);
@@ -93,7 +93,7 @@ AbiWidget::AbiWidget(QWidget *parent) : QWidget(parent),
for (int i = 0; i <= static_cast<int>(Abi::UnknownArchitecture); ++i)
d->m_architectureComboBox->addItem(Abi::toString(static_cast<Abi::Architecture>(i)), i);
d->m_architectureComboBox->setCurrentIndex(static_cast<int>(Abi::UnknownArchitecture));
- connect(d->m_architectureComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(d->m_architectureComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AbiWidget::customComboBoxesChanged);
QLabel *separator1 = new QLabel(this);
@@ -106,7 +106,7 @@ AbiWidget::AbiWidget(QWidget *parent) : QWidget(parent),
for (int i = 0; i <= static_cast<int>(Abi::UnknownOS); ++i)
d->m_osComboBox->addItem(Abi::toString(static_cast<Abi::OS>(i)), i);
d->m_osComboBox->setCurrentIndex(static_cast<int>(Abi::UnknownOS));
- connect(d->m_osComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(d->m_osComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AbiWidget::customOsComboBoxChanged);
QLabel *separator2 = new QLabel(this);
@@ -116,7 +116,7 @@ AbiWidget::AbiWidget(QWidget *parent) : QWidget(parent),
d->m_osFlavorComboBox = new QComboBox(this);
layout->addWidget(d->m_osFlavorComboBox);
- connect(d->m_osFlavorComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(d->m_osFlavorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AbiWidget::customComboBoxesChanged);
QLabel *separator3 = new QLabel(this);
@@ -129,7 +129,7 @@ AbiWidget::AbiWidget(QWidget *parent) : QWidget(parent),
for (int i = 0; i <= static_cast<int>(Abi::UnknownFormat); ++i)
d->m_binaryFormatComboBox->addItem(Abi::toString(static_cast<Abi::BinaryFormat>(i)), i);
d->m_binaryFormatComboBox->setCurrentIndex(static_cast<int>(Abi::UnknownFormat));
- connect(d->m_binaryFormatComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(d->m_binaryFormatComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AbiWidget::customComboBoxesChanged);
QLabel *separator4 = new QLabel(this);
@@ -146,17 +146,17 @@ AbiWidget::AbiWidget(QWidget *parent) : QWidget(parent),
d->m_wordWidthComboBox->addItem(Abi::toString(0), 0);
// Setup current word width of 0 by default.
d->m_wordWidthComboBox->setCurrentIndex(d->m_wordWidthComboBox->count() - 1);
- connect(d->m_wordWidthComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(d->m_wordWidthComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AbiWidget::customComboBoxesChanged);
layout->setStretchFactor(d->m_abi, 1);
- setAbis(QList<Abi>(), Abi::hostAbi());
+ setAbis(Abis(), Abi::hostAbi());
}
AbiWidget::~AbiWidget() = default;
-static Abi selectAbi(const Abi &current, const QList<Abi> &abiList)
+static Abi selectAbi(const Abi &current, const Abis &abiList)
{
if (!current.isNull())
return current;
@@ -165,7 +165,7 @@ static Abi selectAbi(const Abi &current, const QList<Abi> &abiList)
return Abi::hostAbi();
}
-void AbiWidget::setAbis(const QList<Abi> &abiList, const Abi &currentAbi)
+void AbiWidget::setAbis(const Abis &abiList, const Abi &currentAbi)
{
const Abi defaultAbi = selectAbi(currentAbi, abiList);
{
@@ -191,9 +191,9 @@ void AbiWidget::setAbis(const QList<Abi> &abiList, const Abi &currentAbi)
emitAbiChanged(defaultAbi);
}
-QList<Abi> AbiWidget::supportedAbis() const
+Abis AbiWidget::supportedAbis() const
{
- QList<Abi> result;
+ Abis result;
result.reserve(d->m_abi->count());
for (int i = 1; i < d->m_abi->count(); ++i)
result << Abi::fromString(d->m_abi->itemData(i).toString());
diff --git a/src/plugins/projectexplorer/abiwidget.h b/src/plugins/projectexplorer/abiwidget.h
index b8a64dd05c..6cd6699ce7 100644
--- a/src/plugins/projectexplorer/abiwidget.h
+++ b/src/plugins/projectexplorer/abiwidget.h
@@ -27,12 +27,13 @@
#include "projectexplorer_export.h"
+#include "abi.h"
+
#include <QWidget>
#include <memory>
namespace ProjectExplorer {
-class Abi;
namespace Internal { class AbiWidgetPrivate; }
@@ -48,9 +49,9 @@ public:
AbiWidget(QWidget *parent = nullptr);
~AbiWidget() override;
- void setAbis(const QList<Abi> &, const Abi &currentAbi);
+ void setAbis(const ProjectExplorer::Abis &, const Abi &currentAbi);
- QList<Abi> supportedAbis() const;
+ Abis supportedAbis() const;
bool isCustomAbi() const;
Abi currentAbi() const;
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index e85a9648ec..1d92fa9280 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -35,22 +35,20 @@
#include <coreplugin/reaper.h>
+#include <utils/fileinprojectfinder.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <QDir>
-#include <QTimer>
#include <QHash>
#include <QPair>
+#include <QUrl>
#include <algorithm>
#include <memory>
-namespace {
-const int CACHE_SOFT_LIMIT = 500;
-const int CACHE_HARD_LIMIT = 1000;
-} // namespace
+using namespace Utils;
namespace ProjectExplorer {
@@ -107,10 +105,8 @@ public:
std::unique_ptr<Utils::QtcProcess> m_process;
std::unique_ptr<IOutputParser> m_outputParserChain;
ProcessParameters m_param;
- QHash<QString, QPair<Utils::FileName, quint64>> m_filesCache;
- QHash<QString, Utils::FileNameList> m_candidates;
+ Utils::FileInProjectFinder m_fileFinder;
QByteArray deferredText;
- quint64 m_cacheCounter = 0;
bool m_ignoreReturnValue = false;
bool m_skipFlush = false;
@@ -194,11 +190,8 @@ void AbstractProcessStep::setIgnoreReturnValue(bool b)
bool AbstractProcessStep::init()
{
- d->m_candidates.clear();
- const Utils::FileNameList fl = project()->files(Project::AllFiles);
- for (const Utils::FileName &file : fl)
- d->m_candidates[file.fileName()].push_back(file);
-
+ d->m_fileFinder.setProjectDirectory(project()->projectDirectory());
+ d->m_fileFinder.setProjectFiles(project()->files(Project::AllFiles));
return !d->m_process;
}
@@ -209,7 +202,7 @@ bool AbstractProcessStep::init()
void AbstractProcessStep::doRun()
{
- QDir wd(d->m_param.effectiveWorkingDirectory());
+ QDir wd(d->m_param.effectiveWorkingDirectory().toString());
if (!wd.exists()) {
if (!wd.mkpath(wd.absolutePath())) {
emit addOutput(tr("Could not create directory \"%1\"")
@@ -220,8 +213,8 @@ void AbstractProcessStep::doRun()
}
}
- QString effectiveCommand = d->m_param.effectiveCommand();
- if (!QFileInfo::exists(effectiveCommand)) {
+ const CommandLine effectiveCommand{d->m_param.effectiveCommand(), d->m_param.effectiveArguments()};
+ if (!effectiveCommand.executable().exists()) {
processStartupFailed();
finish(false);
return;
@@ -231,13 +224,13 @@ void AbstractProcessStep::doRun()
d->m_process->setUseCtrlCStub(Utils::HostOsInfo::isWindowsHost());
d->m_process->setWorkingDirectory(wd.absolutePath());
d->m_process->setEnvironment(d->m_param.environment());
- d->m_process->setCommand(effectiveCommand, d->m_param.effectiveArguments());
+ d->m_process->setCommand(effectiveCommand);
connect(d->m_process.get(), &QProcess::readyReadStandardOutput,
this, &AbstractProcessStep::processReadyReadStdOutput);
connect(d->m_process.get(), &QProcess::readyReadStandardError,
this, &AbstractProcessStep::processReadyReadStdError);
- connect(d->m_process.get(), static_cast<void (QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
+ connect(d->m_process.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &AbstractProcessStep::slotProcessFinished);
d->m_process->start();
@@ -284,7 +277,7 @@ void AbstractProcessStep::cleanUp(QProcess *process)
void AbstractProcessStep::processStarted()
{
emit addOutput(tr("Starting: \"%1\" %2")
- .arg(QDir::toNativeSeparators(d->m_param.effectiveCommand()),
+ .arg(QDir::toNativeSeparators(d->m_param.effectiveCommand().toString()),
d->m_param.prettyArguments()),
BuildStep::OutputFormat::NormalMessage);
}
@@ -300,7 +293,7 @@ void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus sta
if (d->m_outputParserChain)
d->m_outputParserChain->flush();
- QString command = QDir::toNativeSeparators(d->m_param.effectiveCommand());
+ QString command = QDir::toNativeSeparators(d->m_param.effectiveCommand().toString());
if (status == QProcess::NormalExit && exitCode == 0) {
emit addOutput(tr("The process \"%1\" exited normally.").arg(command),
BuildStep::OutputFormat::NormalMessage);
@@ -322,7 +315,7 @@ void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus sta
void AbstractProcessStep::processStartupFailed()
{
emit addOutput(tr("Could not start process \"%1\" %2")
- .arg(QDir::toNativeSeparators(d->m_param.effectiveCommand()),
+ .arg(QDir::toNativeSeparators(d->m_param.effectiveCommand().toString()),
d->m_param.prettyArguments()),
BuildStep::OutputFormat::ErrorMessage);
}
@@ -437,44 +430,16 @@ void AbstractProcessStep::taskAdded(const Task &task, int linkedOutputLines, int
Task editable(task);
QString filePath = task.file.toString();
-
- auto it = d->m_filesCache.find(filePath);
- if (it != d->m_filesCache.end()) {
- editable.file = it.value().first;
- it.value().second = ++d->m_cacheCounter;
- } else if (!filePath.isEmpty() && !filePath.startsWith('<') && !QDir::isAbsolutePath(filePath)) {
- // We have no save way to decide which file in which subfolder
- // is meant. Therefore we apply following heuristics:
- // 1. Check if file is unique in whole project
- // 2. Otherwise try again without any ../
- // 3. give up.
-
- QString sourceFilePath = filePath;
- Utils::FileNameList possibleFiles = d->m_candidates.value(Utils::FileName::fromString(filePath).fileName());
-
- if (possibleFiles.count() == 1) {
- editable.file = possibleFiles.first();
- } else {
- // More then one filename, so do a better compare
- // Chop of any "../"
- while (filePath.startsWith("../"))
- filePath.remove(0, 3);
-
- int count = 0;
- Utils::FileName possibleFilePath;
- foreach (const Utils::FileName &fn, possibleFiles) {
- if (fn.endsWith(filePath)) {
- possibleFilePath = fn;
- ++count;
- }
- }
- if (count == 1)
- editable.file = possibleFilePath;
- else
- qWarning() << "Could not find absolute location of file " << filePath;
- }
-
- insertInCache(sourceFilePath, editable.file);
+ if (!filePath.isEmpty() && !filePath.startsWith('<') && !QDir::isAbsolutePath(filePath)) {
+ while (filePath.startsWith("../"))
+ filePath.remove(0, 3);
+ bool found = false;
+ const Utils::FilePathList candidates
+ = d->m_fileFinder.findFile(QUrl::fromLocalFile(filePath), &found);
+ if (found && candidates.size() == 1)
+ editable.file = candidates.first();
+ else
+ qWarning() << "Could not find absolute location of file " << filePath;
}
emit addTask(editable, linkedOutputLines, skipLines);
@@ -499,27 +464,7 @@ void AbstractProcessStep::slotProcessFinished(int, QProcess::ExitStatus)
for (const QString &l : stdOutLine.split('\n'))
stdError(l);
- purgeCache(true);
cleanUp(process);
}
-void AbstractProcessStep::purgeCache(bool useSoftLimit)
-{
- const int limit = useSoftLimit ? CACHE_SOFT_LIMIT : CACHE_HARD_LIMIT;
- if (d->m_filesCache.size() <= limit)
- return;
-
- const quint64 minCounter = d->m_cacheCounter - static_cast<quint64>(limit);
- std::remove_if(d->m_filesCache.begin(), d->m_filesCache.end(),
- [minCounter](const QPair<Utils::FileName, quint64> &entry) {
- return entry.second <= minCounter;
- });
-}
-
-void AbstractProcessStep::insertInCache(const QString &relativePath, const Utils::FileName &absPath)
-{
- purgeCache(false);
- d->m_filesCache.insert(relativePath, qMakePair(absPath, ++d->m_cacheCounter));
-}
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/abstractprocessstep.h b/src/plugins/projectexplorer/abstractprocessstep.h
index 5d76bf7f4e..b21a6bdb25 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.h
+++ b/src/plugins/projectexplorer/abstractprocessstep.h
@@ -29,7 +29,7 @@
#include <QProcess>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ProjectExplorer {
class IOutputParser;
@@ -57,6 +57,7 @@ protected:
~AbstractProcessStep() override;
bool init() override;
void doRun() override;
+ virtual void finish(bool success);
virtual void processStarted();
virtual void processFinished(int exitCode, QProcess::ExitStatus status);
@@ -68,7 +69,6 @@ protected:
void doCancel() override;
private:
- virtual void finish(bool success);
void processReadyReadStdOutput();
void processReadyReadStdError();
@@ -80,9 +80,6 @@ private:
void outputAdded(const QString &string, BuildStep::OutputFormat format);
- void purgeCache(bool useSoftLimit);
- void insertInCache(const QString &relativePath, const Utils::FileName &absPath);
-
class Private;
Private *d;
};
diff --git a/src/plugins/projectexplorer/addrunconfigdialog.cpp b/src/plugins/projectexplorer/addrunconfigdialog.cpp
new file mode 100644
index 0000000000..647959eb15
--- /dev/null
+++ b/src/plugins/projectexplorer/addrunconfigdialog.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** 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 "addrunconfigdialog.h"
+
+#include "project.h"
+#include "target.h"
+
+#include <utils/itemviews.h>
+#include <utils/qtcassert.h>
+#include <utils/treemodel.h>
+
+#include <QDialogButtonBox>
+#include <QHeaderView>
+#include <QHBoxLayout>
+#include <QItemSelectionModel>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRegExp>
+#include <QSortFilterProxyModel>
+#include <QVBoxLayout>
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+namespace Internal {
+
+const Qt::ItemDataRole IsCustomRole = Qt::UserRole;
+
+class CandidateTreeItem : public TreeItem
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::Internal::AddRunConfigDialog)
+public:
+ CandidateTreeItem(const RunConfigurationCreationInfo &rci, const FilePath &projectRoot)
+ : m_creationInfo(rci), m_projectRoot(projectRoot)
+ { }
+
+ RunConfigurationCreationInfo creationInfo() const { return m_creationInfo; }
+
+private:
+ QVariant data(int column, int role) const override
+ {
+ QTC_ASSERT(column < 2, return QVariant());
+ if (role == IsCustomRole)
+ return m_creationInfo.projectFilePath.isEmpty();
+ if (column == 0 && role == Qt::DisplayRole)
+ return m_creationInfo.displayName;
+ if (column == 1 && role == Qt::DisplayRole) {
+ FilePath displayPath = m_creationInfo.projectFilePath.relativeChildPath(m_projectRoot);
+ if (displayPath.isEmpty()) {
+ displayPath = m_creationInfo.projectFilePath;
+ QTC_CHECK(displayPath.isEmpty());
+ }
+ return displayPath.isEmpty() ? tr("[none]") : displayPath.toUserOutput();
+ }
+ return QVariant();
+ }
+
+ const RunConfigurationCreationInfo m_creationInfo;
+ const FilePath m_projectRoot;
+};
+
+class CandidatesModel : public TreeModel<TreeItem, CandidateTreeItem>
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::Internal::AddRunConfigDialog)
+public:
+ CandidatesModel(Target *target, QObject *parent) : TreeModel(parent)
+ {
+ setHeader({tr("Name"), tr("Source")});
+ for (const RunConfigurationCreationInfo &rci
+ : RunConfigurationFactory::creatorsForTarget(target)) {
+ rootItem()->appendChild(new CandidateTreeItem(rci,
+ target->project()->projectDirectory()));
+ }
+ }
+};
+
+class ProxyModel : public QSortFilterProxyModel
+{
+public:
+ ProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { }
+
+private:
+ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override
+ {
+ if (source_left.column() == 0) {
+ // Let's put the fallback candidates last.
+ const bool leftIsCustom = sourceModel()->data(source_left, IsCustomRole).toBool();
+ const bool rightIsCustom = sourceModel()->data(source_right, IsCustomRole).toBool();
+ if (leftIsCustom != rightIsCustom)
+ return rightIsCustom;
+ }
+ return QSortFilterProxyModel::lessThan(source_left, source_right);
+ }
+};
+
+class CandidatesTreeView : public TreeView
+{
+public:
+ CandidatesTreeView(QWidget *parent) : TreeView(parent)
+ {
+ setUniformRowHeights(true);
+ }
+
+private:
+ QSize sizeHint() const override
+ {
+ const int width = columnWidth(0) + columnWidth(1);
+ const int height = qMin(model()->rowCount() + 10, 10) * rowHeight(model()->index(0, 0))
+ + header()->sizeHint().height();
+ return {width, height};
+ }
+};
+
+AddRunConfigDialog::AddRunConfigDialog(Target *target, QWidget *parent)
+ : QDialog(parent), m_view(new CandidatesTreeView(this))
+{
+ setWindowTitle(tr("Create Run Configuration"));
+ const auto model = new CandidatesModel(target, this);
+ const auto proxyModel = new ProxyModel(this);
+ proxyModel->setSourceModel(model);
+ const auto filterEdit = new QLineEdit(this);
+ m_view->setSelectionMode(TreeView::SingleSelection);
+ m_view->setSelectionBehavior(TreeView::SelectRows);
+ m_view->setSortingEnabled(true);
+ m_view->setModel(proxyModel);
+ m_view->resizeColumnToContents(0);
+ m_view->resizeColumnToContents(1);
+ m_view->sortByColumn(0, Qt::AscendingOrder);
+ const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create"));
+
+ connect(filterEdit, &QLineEdit::textChanged, this, [proxyModel](const QString &text) {
+ proxyModel->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive));
+ });
+ connect(m_view, &TreeView::doubleClicked, this, [this] { accept(); });
+ const auto updateOkButton = [buttonBox, this] {
+ buttonBox->button(QDialogButtonBox::Ok)
+ ->setEnabled(m_view->selectionModel()->hasSelection());
+ };
+ connect(m_view->selectionModel(), &QItemSelectionModel::selectionChanged, this, updateOkButton);
+ updateOkButton();
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ const auto layout = new QVBoxLayout(this);
+ const auto filterLayout = new QHBoxLayout;
+ filterLayout->addWidget(new QLabel(tr("Filter candidates by name:"), this));
+ filterLayout->addWidget(filterEdit);
+ layout->addLayout(filterLayout);
+ layout->addWidget(m_view);
+ layout->addWidget(buttonBox);
+}
+
+void AddRunConfigDialog::accept()
+{
+ const QModelIndexList selected = m_view->selectionModel()->selectedRows();
+ QTC_ASSERT(selected.count() == 1, return);
+ const auto * const proxyModel = static_cast<ProxyModel *>(m_view->model());
+ const auto * const model = static_cast<CandidatesModel *>(proxyModel->sourceModel());
+ const TreeItem * const item = model->itemForIndex(proxyModel->mapToSource(selected.first()));
+ QTC_ASSERT(item, return);
+ m_creationInfo = static_cast<const CandidateTreeItem *>(item)->creationInfo();
+ QTC_ASSERT(m_creationInfo.id.isValid(), return);
+ QDialog::accept();
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/addrunconfigdialog.h b/src/plugins/projectexplorer/addrunconfigdialog.h
new file mode 100644
index 0000000000..2214bed5a1
--- /dev/null
+++ b/src/plugins/projectexplorer/addrunconfigdialog.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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 "runconfiguration.h"
+
+#include <QDialog>
+
+namespace Utils { class TreeView; }
+
+namespace ProjectExplorer {
+class Target;
+
+namespace Internal {
+
+class AddRunConfigDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ AddRunConfigDialog(Target *target, QWidget *parent);
+
+ RunConfigurationCreationInfo creationInfo() const { return m_creationInfo; }
+
+private:
+ void accept() override;
+
+ Utils::TreeView * const m_view;
+ RunConfigurationCreationInfo m_creationInfo;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/allprojectsfilter.cpp b/src/plugins/projectexplorer/allprojectsfilter.cpp
index 24371ad4e1..ab17127d73 100644
--- a/src/plugins/projectexplorer/allprojectsfilter.cpp
+++ b/src/plugins/projectexplorer/allprojectsfilter.cpp
@@ -59,7 +59,7 @@ void AllProjectsFilter::prepareSearch(const QString &entry)
if (!fileIterator()) {
QStringList paths;
for (Project *project : SessionManager::projects())
- paths.append(Utils::transform(project->files(Project::AllFiles), &Utils::FileName::toString));
+ paths.append(Utils::transform(project->files(Project::AllFiles), &Utils::FilePath::toString));
Utils::sort(paths);
setFileIterator(new BaseFileFilter::ListIterator(paths));
}
diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp
index aa0d7c6fbc..d41f21f1b7 100644
--- a/src/plugins/projectexplorer/allprojectsfind.cpp
+++ b/src/plugins/projectexplorer/allprojectsfind.cpp
@@ -88,7 +88,7 @@ Utils::FileIterator *AllProjectsFind::filesForProjects(const QStringList &nameFi
QTextCodec *projectCodec = config->useGlobalSettings()
? Core::EditorManager::defaultTextCodec()
: config->textCodec();
- const QStringList filteredFiles = filterFiles(Utils::transform(project->files(Project::AllFiles), &Utils::FileName::toString));
+ const QStringList filteredFiles = filterFiles(Utils::transform(project->files(Project::AllFiles), &Utils::FilePath::toString));
for (const QString &fileName : filteredFiles) {
QTextCodec *codec = openEditorEncodings.value(fileName);
if (!codec)
diff --git a/src/plugins/projectexplorer/ansifilterparser.cpp b/src/plugins/projectexplorer/ansifilterparser.cpp
index 402dcf6f9b..a2db2c1a6f 100644
--- a/src/plugins/projectexplorer/ansifilterparser.cpp
+++ b/src/plugins/projectexplorer/ansifilterparser.cpp
@@ -168,7 +168,7 @@ void ProjectExplorerPlugin::testAnsiFilterOutputParser()
QFETCH(QString, childStdErrLines);
testbench.testParsing(input, inputChannel,
- QList<Task>(), childStdOutLines, childStdErrLines,
+ Tasks(), childStdOutLines, childStdErrLines,
QString());
}
diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp
index 3aef28f090..3a9cde2baf 100644
--- a/src/plugins/projectexplorer/applicationlauncher.cpp
+++ b/src/plugins/projectexplorer/applicationlauncher.cpp
@@ -39,6 +39,7 @@
#include "devicesupport/deviceprocess.h"
#include "projectexplorer.h"
#include "projectexplorersettings.h"
+#include "runcontrol.h"
#include <QTextCodec>
#include <QTimer>
@@ -63,7 +64,6 @@ using namespace Internal;
namespace Internal {
-
class ApplicationLauncherPrivate : public QObject
{
public:
@@ -126,7 +126,7 @@ public:
ApplicationLauncherPrivate::ApplicationLauncherPrivate(ApplicationLauncher *parent)
: q(parent), m_outputCodec(QTextCodec::codecForLocale())
{
- if (ProjectExplorerPlugin::projectExplorerSettings().mergeStdErrAndStdOut){
+ if (ProjectExplorerPlugin::appOutputSettings().mergeChannels) {
m_guiProcess.setProcessChannelMode(QProcess::MergedChannels);
} else {
m_guiProcess.setProcessChannelMode(QProcess::SeparateChannels);
@@ -137,7 +137,7 @@ ApplicationLauncherPrivate::ApplicationLauncherPrivate(ApplicationLauncher *pare
this, &ApplicationLauncherPrivate::readLocalStandardOutput);
connect(&m_guiProcess, &QProcess::errorOccurred,
this, &ApplicationLauncherPrivate::localGuiProcessError);
- connect(&m_guiProcess, static_cast<void (QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&m_guiProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &ApplicationLauncherPrivate::localProcessDone);
connect(&m_guiProcess, &QProcess::started,
this, &ApplicationLauncherPrivate::handleProcessStarted);
@@ -152,8 +152,7 @@ ApplicationLauncherPrivate::ApplicationLauncherPrivate(ApplicationLauncher *pare
this, &ApplicationLauncherPrivate::localConsoleProcessError);
connect(&m_consoleProcess, &ConsoleProcess::processStopped,
this, &ApplicationLauncherPrivate::localProcessDone);
- connect(&m_consoleProcess,
- static_cast<void (ConsoleProcess::*)(QProcess::ProcessError)>(&ConsoleProcess::error),
+ connect(&m_consoleProcess, QOverload<QProcess::ProcessError>::of(&ConsoleProcess::error),
q, &ApplicationLauncher::error);
#ifdef Q_OS_WIN
@@ -379,7 +378,7 @@ void ApplicationLauncherPrivate::start(const Runnable &runnable, const IDevice::
#endif
if (!m_useTerminal) {
- m_guiProcess.setCommand(runnable.executable, runnable.commandLineArguments);
+ m_guiProcess.setCommand(runnable.commandLine());
m_guiProcess.closeWriteChannel();
m_guiProcess.start();
} else {
diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp
index 34f71efc24..df9fd503ba 100644
--- a/src/plugins/projectexplorer/appoutputpane.cpp
+++ b/src/plugins/projectexplorer/appoutputpane.cpp
@@ -24,47 +24,54 @@
****************************************************************************/
#include "appoutputpane.h"
+
#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
#include "projectexplorericons.h"
-#include "projectexplorersettings.h"
-#include "runconfiguration.h"
+#include "runcontrol.h"
#include "session.h"
#include "windebuginterface.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/outputwindow.h>
-#include <coreplugin/find/basetextfind.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/find/basetextfind.h>
#include <coreplugin/icore.h>
+#include <coreplugin/outputwindow.h>
+#include <texteditor/behaviorsettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorsettings.h>
-#include <texteditor/behaviorsettings.h>
-#include <extensionsystem/pluginmanager.h>
-#include <extensionsystem/invoker.h>
+#include <extensionsystem/invoker.h>
+#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/outputformatter.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
#include <QAction>
-#include <QVBoxLayout>
+#include <QCheckBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLoggingCategory>
+#include <QMenu>
+#include <QSpinBox>
+#include <QTabBar>
#include <QTabWidget>
#include <QToolButton>
-#include <QTabBar>
-#include <QMenu>
-
-#include <QDebug>
+#include <QVBoxLayout>
-enum { debug = 0 };
+static Q_LOGGING_CATEGORY(appOutputLog, "qtc.projectexplorer.appoutput", QtWarningMsg);
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
+const char OPTIONS_PAGE_ID[] = "B.ProjectExplorer.AppOutputOptions";
+
+
static QObject *debuggerPlugin()
{
- return ExtensionSystem::PluginManager::getObjectByName(QLatin1String("DebuggerPlugin"));
+ return ExtensionSystem::PluginManager::getObjectByName("DebuggerPlugin");
}
static QString msgAttachDebuggerTooltip(const QString &handleDescription = QString())
@@ -79,13 +86,19 @@ static void replaceAllChildWidgets(QLayout *layout, const QList<QWidget *> &newC
while (QLayoutItem *child = layout->takeAt(0))
delete child;
- foreach (QWidget *widget, newChildren)
+ for (QWidget *widget : newChildren)
layout->addWidget(widget);
}
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 {
@@ -147,11 +160,11 @@ void TabWidget::slotContextMenuRequested(const QPoint &pos)
emit contextMenuRequested(pos, tabBar()->tabAt(pos));
}
-AppOutputPane::RunControlTab::RunControlTab(RunControl *rc, Core::OutputWindow *w) :
- runControl(rc), window(w)
+AppOutputPane::RunControlTab::RunControlTab(RunControl *runControl, Core::OutputWindow *w) :
+ runControl(runControl), window(w)
{
- if (rc && w)
- w->setFormatter(rc->outputFormatter());
+ if (runControl && w)
+ w->setFormatter(runControl->outputFormatter());
}
AppOutputPane::AppOutputPane() :
@@ -164,16 +177,15 @@ AppOutputPane::AppOutputPane() :
m_reRunButton(new QToolButton),
m_stopButton(new QToolButton),
m_attachButton(new QToolButton),
- m_zoomInButton(new QToolButton),
- m_zoomOutButton(new QToolButton),
+ m_settingsButton(new QToolButton),
m_formatterWidget(new QWidget)
{
- setObjectName(QLatin1String("AppOutputPane")); // Used in valgrind engine
+ setObjectName("AppOutputPane"); // Used in valgrind engine
+ loadSettings();
// Rerun
m_reRunButton->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR.icon());
m_reRunButton->setToolTip(tr("Re-run this run-configuration"));
- m_reRunButton->setAutoRaise(true);
m_reRunButton->setEnabled(false);
connect(m_reRunButton, &QToolButton::clicked,
this, &AppOutputPane::reRunRunControl);
@@ -187,7 +199,6 @@ AppOutputPane::AppOutputPane() :
cmd->setDescription(m_stopAction->toolTip());
m_stopButton->setDefaultAction(cmd->action());
- m_stopButton->setAutoRaise(true);
connect(m_stopAction, &QAction::triggered,
this, &AppOutputPane::stopRunControl);
@@ -196,24 +207,19 @@ AppOutputPane::AppOutputPane() :
m_attachButton->setToolTip(msgAttachDebuggerTooltip());
m_attachButton->setEnabled(false);
m_attachButton->setIcon(Icons::DEBUG_START_SMALL_TOOLBAR.icon());
- m_attachButton->setAutoRaise(true);
connect(m_attachButton, &QToolButton::clicked,
this, &AppOutputPane::attachToRunControl);
- m_zoomInButton->setToolTip(tr("Increase Font Size"));
- m_zoomInButton->setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
- m_zoomInButton->setAutoRaise(true);
+ connect(this, &Core::IOutputPane::zoomIn, this, &AppOutputPane::zoomIn);
+ connect(this, &Core::IOutputPane::zoomOut, this, &AppOutputPane::zoomOut);
+ connect(this, &IOutputPane::resetZoom, this, &AppOutputPane::resetZoom);
- connect(m_zoomInButton, &QToolButton::clicked,
- this, &AppOutputPane::zoomIn);
-
- m_zoomOutButton->setToolTip(tr("Decrease Font Size"));
- m_zoomOutButton->setIcon(Utils::Icons::MINUS.icon());
- m_zoomOutButton->setAutoRaise(true);
-
- connect(m_zoomOutButton, &QToolButton::clicked,
- this, &AppOutputPane::zoomOut);
+ m_settingsButton->setToolTip(tr("Open Settings Page"));
+ m_settingsButton->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
+ connect(m_settingsButton, &QToolButton::clicked, this, [] {
+ Core::ICore::showOptionsDialog(OPTIONS_PAGE_ID);
+ });
auto formatterWidgetsLayout = new QHBoxLayout;
formatterWidgetsLayout->setContentsMargins(QMargins());
@@ -236,42 +242,26 @@ AppOutputPane::AppOutputPane() :
m_mainWidget->setLayout(layout);
- connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::fontSettingsChanged,
- this, &AppOutputPane::updateFontSettings);
-
- connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
- this, &AppOutputPane::updateBehaviorSettings);
-
connect(SessionManager::instance(), &SessionManager::aboutToUnloadSession,
this, &AppOutputPane::aboutToUnloadSession);
- connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
- this, &AppOutputPane::updateFromSettings);
-
- QSettings *settings = Core::ICore::settings();
- m_zoom = settings->value(QLatin1String(SETTINGS_KEY), 0).toFloat();
- connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
- this, &AppOutputPane::saveSettings);
+ setupFilterUi("AppOutputPane.Filter");
+ setFilteringEnabled(false);
+ setZoomButtonsEnabled(false);
+ setupContext("Core.AppOutputPane", m_mainWidget);
}
AppOutputPane::~AppOutputPane()
{
- if (debug)
- qDebug() << "OutputPane::~OutputPane: Entries left" << m_runControlTabs.size();
+ qCDebug(appOutputLog) << "AppOutputPane::~AppOutputPane: Entries left" << m_runControlTabs.size();
- foreach (const RunControlTab &rt, m_runControlTabs) {
+ for (const RunControlTab &rt : qAsConst(m_runControlTabs)) {
delete rt.window;
delete rt.runControl;
}
delete m_mainWidget;
}
-void AppOutputPane::saveSettings()
-{
- QSettings *settings = Core::ICore::settings();
- settings->setValue(QLatin1String(SETTINGS_KEY), m_zoom);
-}
-
int AppOutputPane::currentIndex() const
{
if (const QWidget *w = m_tabWidget->currentWidget())
@@ -337,8 +327,8 @@ QWidget *AppOutputPane::outputWidget(QWidget *)
QList<QWidget*> AppOutputPane::toolBarWidgets() const
{
- return { m_reRunButton, m_stopButton, m_attachButton, m_zoomInButton,
- m_zoomOutButton, m_formatterWidget };
+ return QList<QWidget *>{m_reRunButton, m_stopButton, m_attachButton, m_settingsButton,
+ m_formatterWidget} + IOutputPane::toolBarWidgets();
}
QString AppOutputPane::displayName() const
@@ -381,18 +371,13 @@ void AppOutputPane::setFocus()
m_tabWidget->currentWidget()->setFocus();
}
-void AppOutputPane::updateFontSettings()
+void AppOutputPane::updateFilter()
{
- QFont f = TextEditor::TextEditorSettings::fontSettings().font();
- foreach (const RunControlTab &rcTab, m_runControlTabs)
- rcTab.window->setBaseFont(f);
-}
-
-void AppOutputPane::updateBehaviorSettings()
-{
- bool zoomEnabled = TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming;
- foreach (const RunControlTab &rcTab, m_runControlTabs)
- rcTab.window->setWheelZoomEnabled(zoomEnabled);
+ const int index = currentIndex();
+ if (index != -1) {
+ m_runControlTabs.at(index).window->updateFilterProperties(
+ filterText(), filterCaseSensitivity(), filterUsesRegexp());
+ }
}
void AppOutputPane::createNewOutputWindow(RunControl *rc)
@@ -407,8 +392,10 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
this, &AppOutputPane::slotRunControlFinished);
connect(rc, &RunControl::applicationProcessHandleChanged,
this, &AppOutputPane::enableDefaultButtons);
- connect(rc, &RunControl::appendMessageRequested,
- this, &AppOutputPane::appendMessage);
+ connect(rc, &RunControl::appendMessage,
+ this, [this, rc](const QString &out, Utils::OutputFormat format) {
+ appendMessage(rc, out, format);
+ });
// First look if we can reuse a tab
const Runnable thisRunnable = rc->runnable();
@@ -435,42 +422,55 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
m_tabWidget->setTabText(tabIndex, rc->displayName());
tab.window->scrollToBottom();
- if (debug)
- qDebug() << "OutputPane::createNewOutputWindow: Reusing tab" << tabIndex << " for " << rc;
+ qCDebug(appOutputLog) << "AppOutputPane::createNewOutputWindow: Reusing tab"
+ << tabIndex << "for" << rc;
return;
}
// Create new
static int counter = 0;
Core::Id contextId = Core::Id(C_APP_OUTPUT).withSuffix(counter++);
Core::Context context(contextId);
- Core::OutputWindow *ow = new Core::OutputWindow(context, m_tabWidget);
+ Core::OutputWindow *ow = new Core::OutputWindow(context, SETTINGS_KEY, m_tabWidget);
ow->setWindowTitle(tr("Application Output Window"));
ow->setWindowIcon(Icons::WINDOW.icon());
- ow->setWordWrapEnabled(ProjectExplorerPlugin::projectExplorerSettings().wrapAppOutput);
- ow->setMaxCharCount(ProjectExplorerPlugin::projectExplorerSettings().maxAppOutputChars);
- ow->setWheelZoomEnabled(TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
- ow->setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
- ow->setFontZoom(m_zoom);
+ ow->setWordWrapEnabled(m_settings.wrapOutput);
+ ow->setMaxCharCount(m_settings.maxCharCount);
+
+ auto updateFontSettings = [ow] {
+ ow->setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
+ };
+
+ auto updateBehaviorSettings = [ow] {
+ ow->setWheelZoomEnabled(
+ TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
+ };
+
+ updateFontSettings();
+ updateBehaviorSettings();
connect(ow, &Core::OutputWindow::wheelZoom, this, [this, ow]() {
- m_zoom = ow->fontZoom();
- foreach (const RunControlTab &tab, m_runControlTabs)
- tab.window->setFontZoom(m_zoom);
+ float fontZoom = ow->fontZoom();
+ for (const RunControlTab &tab : qAsConst(m_runControlTabs))
+ tab.window->setFontZoom(fontZoom);
});
+ connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::fontSettingsChanged,
+ this, updateFontSettings);
+ connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
+ this, updateBehaviorSettings);
auto *agg = new Aggregation::Aggregate;
agg->add(ow);
agg->add(new Core::BaseTextFind(ow));
m_runControlTabs.push_back(RunControlTab(rc, ow));
m_tabWidget->addTab(ow, rc->displayName());
- if (debug)
- qDebug() << "OutputPane::createNewOutputWindow: Adding tab for " << rc;
+ qCDebug(appOutputLog) << "AppOutputPane::createNewOutputWindow: Adding tab for" << rc;
updateCloseActions();
+ setFilteringEnabled(m_tabWidget->count() > 0);
}
void AppOutputPane::handleOldOutput(Core::OutputWindow *window) const
{
- if (ProjectExplorerPlugin::projectExplorerSettings().cleanOldAppOutput)
+ if (m_settings.cleanOldOutput)
window->clear();
else
window->grayOutOldContent();
@@ -478,9 +478,9 @@ void AppOutputPane::handleOldOutput(Core::OutputWindow *window) const
void AppOutputPane::updateFromSettings()
{
- foreach (const RunControlTab &tab, m_runControlTabs) {
- tab.window->setWordWrapEnabled(ProjectExplorerPlugin::projectExplorerSettings().wrapAppOutput);
- tab.window->setMaxCharCount(ProjectExplorerPlugin::projectExplorerSettings().maxAppOutputChars);
+ for (const RunControlTab &tab : qAsConst(m_runControlTabs)) {
+ tab.window->setWordWrapEnabled(m_settings.wrapOutput);
+ tab.window->setMaxCharCount(m_settings.maxCharCount);
}
}
@@ -492,7 +492,7 @@ void AppOutputPane::appendMessage(RunControl *rc, const QString &out, Utils::Out
QString stringToWrite;
if (format == Utils::NormalMessageFormat || format == Utils::ErrorMessageFormat) {
stringToWrite = QTime::currentTime().toString();
- stringToWrite += QLatin1String(": ");
+ stringToWrite += ": ";
}
stringToWrite += out;
window->appendMessage(stringToWrite, format);
@@ -505,6 +505,36 @@ void AppOutputPane::appendMessage(RunControl *rc, const QString &out, Utils::Out
}
}
+void AppOutputPane::setSettings(const AppOutputSettings &settings)
+{
+ m_settings = settings;
+ storeSettings();
+ updateFromSettings();
+}
+
+void AppOutputPane::storeSettings() const
+{
+ QSettings * const s = Core::ICore::settings();
+ s->setValue(POP_UP_FOR_RUN_OUTPUT_KEY, m_settings.popUpForRunOutput);
+ s->setValue(POP_UP_FOR_DEBUG_OUTPUT_KEY, m_settings.popUpForDebugOutput);
+ s->setValue(CLEAN_OLD_OUTPUT_KEY, m_settings.cleanOldOutput);
+ s->setValue(MERGE_CHANNELS_KEY, m_settings.mergeChannels);
+ s->setValue(WRAP_OUTPUT_KEY, m_settings.wrapOutput);
+ s->setValue(MAX_LINES_KEY, m_settings.maxCharCount / 100);
+}
+
+void AppOutputPane::loadSettings()
+{
+ QSettings * const s = Core::ICore::settings();
+ m_settings.popUpForRunOutput = s->value(POP_UP_FOR_RUN_OUTPUT_KEY, true).toBool();
+ m_settings.popUpForDebugOutput = s->value(POP_UP_FOR_DEBUG_OUTPUT_KEY, false).toBool();
+ m_settings.cleanOldOutput = s->value(CLEAN_OLD_OUTPUT_KEY, false).toBool();
+ m_settings.mergeChannels = s->value(MERGE_CHANNELS_KEY, false).toBool();
+ m_settings.wrapOutput = s->value(WRAP_OUTPUT_KEY, true).toBool();
+ m_settings.maxCharCount = s->value(MAX_LINES_KEY,
+ Core::Constants::DEFAULT_MAX_CHAR_COUNT).toInt() * 100;
+}
+
void AppOutputPane::showTabFor(RunControl *rc)
{
m_tabWidget->setCurrentIndex(tabWidgetIndexOf(indexOf(rc)));
@@ -552,8 +582,7 @@ void AppOutputPane::stopRunControl()
rc->forceStop();
}
- if (debug)
- qDebug() << "OutputPane::stopRunControl " << rc;
+ qCDebug(appOutputLog) << "AppOutputPane::stopRunControl" << rc;
}
void AppOutputPane::closeTabs(CloseTabMode mode)
@@ -577,8 +606,7 @@ void AppOutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode)
RunControl *runControl = m_runControlTabs[index].runControl;
Core::OutputWindow *window = m_runControlTabs[index].window;
- if (debug)
- qDebug() << "OutputPane::closeTab tab " << tabIndex << runControl << window;
+ qCDebug(appOutputLog) << "AppOutputPane::closeTab tab" << tabIndex << runControl << window;
// Prompt user to stop
if (closeTabMode == CloseTabWithPrompt) {
QWidget *tabWidget = m_tabWidget->widget(tabIndex);
@@ -599,6 +627,7 @@ void AppOutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode)
runControl->initiateFinish(); // Will self-destruct.
m_runControlTabs.removeAt(index);
updateCloseActions();
+ setFilteringEnabled(m_tabWidget->count() > 0);
if (m_runControlTabs.isEmpty())
hide();
@@ -623,22 +652,22 @@ void AppOutputPane::enableDefaultButtons()
enableButtons(currentRunControl());
}
-void AppOutputPane::zoomIn()
+void AppOutputPane::zoomIn(int range)
{
- foreach (const RunControlTab &tab, m_runControlTabs)
- tab.window->zoomIn(1);
- if (m_runControlTabs.isEmpty())
- return;
- m_zoom = m_runControlTabs.first().window->fontZoom();
+ for (const RunControlTab &tab : qAsConst(m_runControlTabs))
+ tab.window->zoomIn(range);
}
-void AppOutputPane::zoomOut()
+void AppOutputPane::zoomOut(int range)
{
- foreach (const RunControlTab &tab, m_runControlTabs)
- tab.window->zoomOut(1);
- if (m_runControlTabs.isEmpty())
- return;
- m_zoom = m_runControlTabs.first().window->fontZoom();
+ for (const RunControlTab &tab : qAsConst(m_runControlTabs))
+ tab.window->zoomOut(range);
+}
+
+void AppOutputPane::resetZoom()
+{
+ for (const RunControlTab &tab : qAsConst(m_runControlTabs))
+ tab.window->resetZoom();
}
void AppOutputPane::enableButtons(const RunControl *rc)
@@ -658,8 +687,7 @@ void AppOutputPane::enableButtons(const RunControl *rc)
m_attachButton->setEnabled(false);
m_attachButton->setToolTip(msgAttachDebuggerTooltip());
}
- m_zoomInButton->setEnabled(true);
- m_zoomOutButton->setEnabled(true);
+ setZoomButtonsEnabled(true);
replaceAllChildWidgets(m_formatterWidget->layout(), rc->outputFormatter() ?
rc->outputFormatter()->toolbarWidgets() :
@@ -670,8 +698,7 @@ void AppOutputPane::enableButtons(const RunControl *rc)
m_attachButton->setEnabled(false);
m_attachButton->setToolTip(msgAttachDebuggerTooltip());
m_stopAction->setEnabled(false);
- m_zoomInButton->setEnabled(false);
- m_zoomOutButton->setEnabled(false);
+ setZoomButtonsEnabled(false);
}
m_formatterWidget->setVisible(m_formatterWidget->layout()->count());
}
@@ -680,7 +707,10 @@ void AppOutputPane::tabChanged(int i)
{
const int index = indexOf(m_tabWidget->widget(i));
if (i != -1 && index != -1) {
- enableButtons(m_runControlTabs.at(index).runControl);
+ const RunControlTab &controlTab = m_runControlTabs[index];
+ controlTab.window->updateFilterProperties(filterText(), filterCaseSensitivity(),
+ filterUsesRegexp());
+ enableButtons(controlTab.runControl);
} else {
enableDefaultButtons();
}
@@ -729,9 +759,8 @@ void AppOutputPane::slotRunControlFinished2(RunControl *sender)
// Enable buttons for current
RunControl *current = currentRunControl();
- if (debug)
- qDebug() << "OutputPane::runControlFinished" << sender << senderIndex
- << " current " << current << m_runControlTabs.size();
+ qCDebug(appOutputLog) << "AppOutputPane::runControlFinished" << sender << senderIndex
+ << "current" << current << m_runControlTabs.size();
if (current && current == sender)
enableButtons(current);
@@ -773,5 +802,87 @@ bool AppOutputPane::canNavigate() const
return false;
}
+class AppOutputSettingsPage::SettingsWidget : public QWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::Internal::AppOutputSettingsPage)
+public:
+ SettingsWidget()
+ {
+ const AppOutputSettings &settings = ProjectExplorerPlugin::appOutputSettings();
+ m_wrapOutputCheckBox.setText(tr("Word-wrap output"));
+ m_wrapOutputCheckBox.setChecked(settings.wrapOutput);
+ m_cleanOldOutputCheckBox.setText(tr("Clear old output on a new run"));
+ m_cleanOldOutputCheckBox.setChecked(settings.cleanOldOutput);
+ m_mergeChannelsCheckBox.setText(tr("Merge stderr and stdout"));
+ m_mergeChannelsCheckBox.setChecked(settings.mergeChannels);
+ m_popUpForRunOutputCheckBox.setText(tr("Open pane on output when running"));
+ m_popUpForRunOutputCheckBox.setChecked(settings.popUpForRunOutput);
+ m_popUpForDebugOutputCheckBox.setText(tr("Open pane on output when debugging"));
+ m_popUpForDebugOutputCheckBox.setChecked(settings.popUpForDebugOutput);
+ m_maxCharsBox.setMaximum(100000000);
+ m_maxCharsBox.setValue(settings.maxCharCount);
+ const auto layout = new QVBoxLayout(this);
+ layout->addWidget(&m_wrapOutputCheckBox);
+ layout->addWidget(&m_cleanOldOutputCheckBox);
+ layout->addWidget(&m_mergeChannelsCheckBox);
+ layout->addWidget(&m_popUpForRunOutputCheckBox);
+ layout->addWidget(&m_popUpForDebugOutputCheckBox);
+ const auto maxCharsLayout = new QHBoxLayout;
+ const QString msg = tr("Limit output to %1 characters");
+ const QStringList parts = msg.split("%1") << QString() << QString();
+ maxCharsLayout->addWidget(new QLabel(parts.at(0).trimmed()));
+ maxCharsLayout->addWidget(&m_maxCharsBox);
+ maxCharsLayout->addWidget(new QLabel(parts.at(1).trimmed()));
+ maxCharsLayout->addStretch(1);
+ layout->addLayout(maxCharsLayout);
+ layout->addStretch(1);
+ }
+
+ AppOutputSettings settings() const
+ {
+ AppOutputSettings s;
+ s.wrapOutput = m_wrapOutputCheckBox.isChecked();
+ s.cleanOldOutput = m_cleanOldOutputCheckBox.isChecked();
+ s.mergeChannels = m_mergeChannelsCheckBox.isChecked();
+ s.popUpForRunOutput = m_popUpForRunOutputCheckBox.isChecked();
+ s.popUpForDebugOutput = m_popUpForDebugOutputCheckBox.isChecked();
+ s.maxCharCount = m_maxCharsBox.value();
+ return s;
+ }
+
+private:
+ QCheckBox m_wrapOutputCheckBox;
+ QCheckBox m_cleanOldOutputCheckBox;
+ QCheckBox m_mergeChannelsCheckBox;
+ QCheckBox m_popUpForRunOutputCheckBox;
+ QCheckBox m_popUpForDebugOutputCheckBox;
+ QSpinBox m_maxCharsBox;
+};
+
+AppOutputSettingsPage::AppOutputSettingsPage()
+{
+ setId(OPTIONS_PAGE_ID);
+ setDisplayName(tr("Application Output"));
+ setCategory(Constants::BUILD_AND_RUN_SETTINGS_CATEGORY);
+}
+
+QWidget *AppOutputSettingsPage::widget()
+{
+ if (!m_widget)
+ m_widget = new SettingsWidget;
+ return m_widget;
+}
+
+void AppOutputSettingsPage::apply()
+{
+ if (m_widget)
+ ProjectExplorerPlugin::setAppOutputSettings(m_widget->settings());
+}
+
+void AppOutputSettingsPage::finish()
+{
+ delete m_widget;
+}
+
#include "appoutputpane.moc"
diff --git a/src/plugins/projectexplorer/appoutputpane.h b/src/plugins/projectexplorer/appoutputpane.h
index fc7ac6e05e..6d7936042e 100644
--- a/src/plugins/projectexplorer/appoutputpane.h
+++ b/src/plugins/projectexplorer/appoutputpane.h
@@ -25,13 +25,16 @@
#pragma once
-#include <QPointer>
-#include <QVector>
+#include "projectexplorersettings.h"
#include <coreplugin/ioutputpane.h>
+#include <coreplugin/dialogs/ioptionspage.h>
#include <utils/outputformat.h>
+#include <QPointer>
+#include <QVector>
+
QT_BEGIN_NAMESPACE
class QTabWidget;
class QToolButton;
@@ -98,6 +101,9 @@ public:
void appendMessage(ProjectExplorer::RunControl *rc, const QString &out,
Utils::OutputFormat format);
+ const AppOutputSettings &settings() const { return m_settings; }
+ void setSettings(const AppOutputSettings &settings);
+
private:
void reRunRunControl();
void stopRunControl();
@@ -112,8 +118,9 @@ private:
void updateFromSettings();
void enableDefaultButtons();
- void zoomIn();
- void zoomOut();
+ void zoomIn(int range);
+ void zoomOut(int range);
+ void resetZoom();
void enableButtons(const RunControl *rc);
@@ -136,9 +143,10 @@ private:
int tabWidgetIndexOf(int runControlIndex) const;
void handleOldOutput(Core::OutputWindow *window) const;
void updateCloseActions();
- void updateFontSettings();
- void saveSettings();
- void updateBehaviorSettings();
+ void updateFilter() override;
+
+ void loadSettings();
+ void storeSettings() const;
QWidget *m_mainWidget;
TabWidget *m_tabWidget;
@@ -151,10 +159,25 @@ private:
QToolButton *m_reRunButton;
QToolButton *m_stopButton;
QToolButton *m_attachButton;
- QToolButton *m_zoomInButton;
- QToolButton *m_zoomOutButton;
+ QToolButton * const m_settingsButton;
QWidget *m_formatterWidget;
- float m_zoom;
+ AppOutputSettings m_settings;
+};
+
+class AppOutputSettingsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ AppOutputSettingsPage();
+
+private:
+ QWidget *widget() override;
+ void apply() override;
+ void finish() override;
+
+ class SettingsWidget;
+ QPointer<SettingsWidget> m_widget;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
index cb0734f226..14551d1d44 100644
--- a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
+++ b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
@@ -142,7 +142,7 @@ void BaseProjectWizardDialog::slotAccepted()
{
if (d->introPage->useAsDefaultPath()) {
// Store the path as default path for new projects if desired.
- Core::DocumentManager::setProjectsDirectory(Utils::FileName::fromString(path()));
+ Core::DocumentManager::setProjectsDirectory(Utils::FilePath::fromString(path()));
Core::DocumentManager::setUseProjectsDirectory(true);
}
}
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index 7973ed4c05..e267822b97 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -28,10 +28,12 @@
#include "buildenvironmentwidget.h"
#include "buildinfo.h"
#include "buildsteplist.h"
+#include "namedwidget.h"
#include "kit.h"
#include "kitinformation.h"
#include "kitmanager.h"
#include "project.h"
+#include "projectconfigurationaspects.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "projectmacroexpander.h"
@@ -40,13 +42,15 @@
#include <coreplugin/idocument.h>
-#include <utils/qtcassert.h>
-#include <utils/macroexpander.h>
#include <utils/algorithm.h>
-#include <utils/mimetypes/mimetype.h>
+#include <utils/detailswidget.h>
+#include <utils/macroexpander.h>
#include <utils/mimetypes/mimedatabase.h>
+#include <utils/mimetypes/mimetype.h>
+#include <utils/qtcassert.h>
#include <QDebug>
+#include <QFormLayout>
static const char BUILD_STEP_LIST_COUNT[] = "ProjectExplorer.BuildConfiguration.BuildStepListCount";
static const char BUILD_STEP_LIST_PREFIX[] = "ProjectExplorer.BuildConfiguration.BuildStepList.";
@@ -82,27 +86,74 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
// Many macroexpanders are based on the current project, so they may change the environment:
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &BuildConfiguration::updateCacheAndEmitEnvironmentChanged);
+
+ m_buildDirectoryAspect = addAspect<BaseStringAspect>();
+ m_buildDirectoryAspect->setSettingsKey(BUILDDIRECTORY_KEY);
+ m_buildDirectoryAspect->setLabelText(tr("Build directory:"));
+ m_buildDirectoryAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
+ m_buildDirectoryAspect->setExpectedKind(Utils::PathChooser::Directory);
+ m_buildDirectoryAspect->setBaseFileName(target->project()->projectDirectory());
+ m_buildDirectoryAspect->setEnvironment(environment());
+ connect(m_buildDirectoryAspect, &BaseStringAspect::changed,
+ this, &BuildConfiguration::buildDirectoryChanged);
+
+ connect(this, &BuildConfiguration::environmentChanged, this, [this] {
+ m_buildDirectoryAspect->setEnvironment(environment());
+ });
}
-Utils::FileName BuildConfiguration::buildDirectory() const
+Utils::FilePath BuildConfiguration::buildDirectory() const
{
- const QString path = QDir::cleanPath(macroExpander()->expand(environment().expandVariables(m_buildDirectory.toString())));
- return Utils::FileName::fromString(QDir::cleanPath(QDir(target()->project()->projectDirectory().toString()).absoluteFilePath(path)));
+ QString path = environment().expandVariables(m_buildDirectoryAspect->value().trimmed());
+ path = QDir::cleanPath(macroExpander()->expand(path));
+ return Utils::FilePath::fromString(QDir::cleanPath(QDir(target()->project()->projectDirectory().toString()).absoluteFilePath(path)));
}
-Utils::FileName BuildConfiguration::rawBuildDirectory() const
+Utils::FilePath BuildConfiguration::rawBuildDirectory() const
{
- return m_buildDirectory;
+ return m_buildDirectoryAspect->fileName();
}
-void BuildConfiguration::setBuildDirectory(const Utils::FileName &dir)
+void BuildConfiguration::setBuildDirectory(const Utils::FilePath &dir)
{
- if (dir == m_buildDirectory)
+ if (dir == m_buildDirectoryAspect->fileName())
return;
- m_buildDirectory = dir;
+ m_buildDirectoryAspect->setFileName(dir);
emitBuildDirectoryChanged();
}
+NamedWidget *BuildConfiguration::createConfigWidget()
+{
+ NamedWidget *named = new NamedWidget;
+ named->setDisplayName(m_configWidgetDisplayName);
+
+ QWidget *widget = nullptr;
+
+ if (m_configWidgetHasFrame) {
+ auto container = new Utils::DetailsWidget(named);
+ widget = new QWidget(container);
+ container->setState(Utils::DetailsWidget::NoSummary);
+ container->setWidget(widget);
+
+ auto vbox = new QVBoxLayout(named);
+ vbox->setMargin(0);
+ vbox->addWidget(container);
+ } else {
+ widget = named;
+ }
+
+ auto formLayout = new QFormLayout(widget);
+ formLayout->setMargin(0);
+ formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
+
+ for (ProjectConfigurationAspect *aspect : aspects()) {
+ if (aspect->isVisible())
+ aspect->addToConfigurationLayout(formLayout);
+ }
+
+ return named;
+}
+
void BuildConfiguration::initialize(const BuildInfo &info)
{
setDisplayName(info.displayName);
@@ -133,7 +184,6 @@ QVariantMap BuildConfiguration::toMap() const
QVariantMap map(ProjectConfiguration::toMap());
map.insert(QLatin1String(CLEAR_SYSTEM_ENVIRONMENT_KEY), m_clearSystemEnvironment);
map.insert(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY), Utils::EnvironmentItem::toStringList(m_userEnvironmentChanges));
- map.insert(QLatin1String(BUILDDIRECTORY_KEY), m_buildDirectory.toString());
map.insert(QLatin1String(BUILD_STEP_LIST_COUNT), m_stepLists.count());
for (int i = 0; i < m_stepLists.count(); ++i)
@@ -146,7 +196,6 @@ bool BuildConfiguration::fromMap(const QVariantMap &map)
{
m_clearSystemEnvironment = map.value(QLatin1String(CLEAR_SYSTEM_ENVIRONMENT_KEY)).toBool();
m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY)).toStringList());
- m_buildDirectory = Utils::FileName::fromString(map.value(QLatin1String(BUILDDIRECTORY_KEY)).toString());
updateCacheAndEmitEnvironmentChanged();
@@ -194,6 +243,31 @@ void BuildConfiguration::emitBuildDirectoryChanged()
}
}
+ProjectExplorer::BaseStringAspect *BuildConfiguration::buildDirectoryAspect() const
+{
+ return m_buildDirectoryAspect;
+}
+
+void BuildConfiguration::setConfigWidgetDisplayName(const QString &display)
+{
+ m_configWidgetDisplayName = display;
+}
+
+void BuildConfiguration::setBuildDirectoryHistoryCompleter(const QString &history)
+{
+ m_buildDirectoryAspect->setHistoryCompleter(history);
+}
+
+void BuildConfiguration::setConfigWidgetHasFrame(bool configWidgetHasFrame)
+{
+ m_configWidgetHasFrame = configWidgetHasFrame;
+}
+
+void BuildConfiguration::setBuildDirectorySettingsKey(const QString &key)
+{
+ m_buildDirectoryAspect->setSettingsKey(key);
+}
+
Target *BuildConfiguration::target() const
{
return static_cast<Target *>(parent());
@@ -299,20 +373,16 @@ bool BuildConfiguration::isActive() const
* PATH. This is used to in build configurations targeting broken build systems
* to provide hints about which compiler to use.
*/
-void BuildConfiguration::prependCompilerPathToEnvironment(Utils::Environment &env) const
-{
- return prependCompilerPathToEnvironment(target()->kit(), env);
-}
void BuildConfiguration::prependCompilerPathToEnvironment(Kit *k, Utils::Environment &env)
{
const ToolChain *tc
- = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!tc)
return;
- const Utils::FileName compilerDir = tc->compilerCommand().parentDir();
+ const Utils::FilePath compilerDir = tc->compilerCommand().parentDir();
if (!compilerDir.isEmpty())
env.prependOrSetPath(compilerDir.toString());
}
@@ -334,7 +404,7 @@ BuildConfigurationFactory::~BuildConfigurationFactory()
g_buildConfigurationFactories.removeOne(this);
}
-const QList<Task> BuildConfigurationFactory::reportIssues(ProjectExplorer::Kit *kit, const QString &projectPath,
+const Tasks BuildConfigurationFactory::reportIssues(ProjectExplorer::Kit *kit, const QString &projectPath,
const QString &buildDir) const
{
if (m_issueReporter)
@@ -363,7 +433,7 @@ bool BuildConfigurationFactory::supportsTargetDeviceType(Core::Id id) const
BuildConfigurationFactory *BuildConfigurationFactory::find(const Kit *k, const QString &projectPath)
{
QTC_ASSERT(k, return nullptr);
- const Core::Id deviceType = DeviceTypeKitInformation::deviceTypeId(k);
+ const Core::Id deviceType = DeviceTypeKitAspect::deviceTypeId(k);
for (BuildConfigurationFactory *factory : g_buildConfigurationFactories) {
if (Utils::mimeTypeForFile(projectPath).matchesName(factory->m_supportedProjectMimeTypeName)
&& factory->supportsTargetDeviceType(deviceType))
@@ -405,7 +475,7 @@ bool BuildConfigurationFactory::canHandle(const Target *target) const
if (containsType(target->project()->projectIssues(target->kit()), Task::TaskType::Error))
return false;
- if (!supportsTargetDeviceType(DeviceTypeKitInformation::deviceTypeId(target->kit())))
+ if (!supportsTargetDeviceType(DeviceTypeKitAspect::deviceTypeId(target->kit())))
return false;
return true;
diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h
index c40a9d82a6..c9ba394946 100644
--- a/src/plugins/projectexplorer/buildconfiguration.h
+++ b/src/plugins/projectexplorer/buildconfiguration.h
@@ -27,20 +27,20 @@
#include "projectexplorer_export.h"
#include "projectconfiguration.h"
+#include "task.h"
#include <utils/environment.h>
#include <utils/fileutils.h>
namespace ProjectExplorer {
+class BaseStringAspect;
class BuildInfo;
-class NamedWidget;
class BuildStepList;
-class Node;
class Kit;
+class NamedWidget;
+class Node;
class Target;
-class Task;
-class IOutputParser;
class PROJECTEXPLORER_EXPORT BuildConfiguration : public ProjectConfiguration
{
@@ -51,11 +51,11 @@ protected:
explicit BuildConfiguration(Target *target, Core::Id id);
public:
- Utils::FileName buildDirectory() const;
- Utils::FileName rawBuildDirectory() const;
- void setBuildDirectory(const Utils::FileName &dir);
+ Utils::FilePath buildDirectory() const;
+ Utils::FilePath rawBuildDirectory() const;
+ void setBuildDirectory(const Utils::FilePath &dir);
- virtual NamedWidget *createConfigWidget() = 0;
+ virtual NamedWidget *createConfigWidget();
virtual QList<NamedWidget *> createSubConfigWidgets();
// Maybe the BuildConfiguration is not the best place for the environment
@@ -95,10 +95,15 @@ public:
bool isActive() const override;
- void prependCompilerPathToEnvironment(Utils::Environment &env) const;
static void prependCompilerPathToEnvironment(Kit *k, Utils::Environment &env);
void updateCacheAndEmitEnvironmentChanged();
+ ProjectExplorer::BaseStringAspect *buildDirectoryAspect() const;
+ void setConfigWidgetDisplayName(const QString &display);
+ void setBuildDirectoryHistoryCompleter(const QString &history);
+ void setConfigWidgetHasFrame(bool configWidgetHasFrame);
+ void setBuildDirectorySettingsKey(const QString &key);
+
signals:
void environmentChanged();
void buildDirectoryChanged();
@@ -114,9 +119,11 @@ private:
bool m_clearSystemEnvironment = false;
QList<Utils::EnvironmentItem> m_userEnvironmentChanges;
QList<BuildStepList *> m_stepLists;
- Utils::FileName m_buildDirectory;
- Utils::FileName m_lastEmmitedBuildDirectory;
+ ProjectExplorer::BaseStringAspect *m_buildDirectoryAspect = nullptr;
+ Utils::FilePath m_lastEmmitedBuildDirectory;
mutable Utils::Environment m_cachedEnvironment;
+ QString m_configWidgetDisplayName;
+ bool m_configWidgetHasFrame = false;
};
class PROJECTEXPLORER_EXPORT BuildConfigurationFactory : public QObject
@@ -143,10 +150,10 @@ public:
static BuildConfigurationFactory *find(const Kit *k, const QString &projectPath);
static BuildConfigurationFactory *find(Target *parent);
- using IssueReporter = std::function<QList<ProjectExplorer::Task>(Kit *, const QString &, const QString &)>;
+ using IssueReporter = std::function<Tasks(Kit *, const QString &, const QString &)>;
void setIssueReporter(const IssueReporter &issueReporter);
- const QList<Task> reportIssues(ProjectExplorer::Kit *kit,
- const QString &projectPath, const QString &buildDir) const;
+ const Tasks reportIssues(ProjectExplorer::Kit *kit,
+ const QString &projectPath, const QString &buildDir) const;
protected:
virtual QList<BuildInfo> availableBuilds(const Target *parent) const = 0;
diff --git a/src/plugins/projectexplorer/buildenvironmentwidget.cpp b/src/plugins/projectexplorer/buildenvironmentwidget.cpp
index 3177f7e6b1..047412fbf3 100644
--- a/src/plugins/projectexplorer/buildenvironmentwidget.cpp
+++ b/src/plugins/projectexplorer/buildenvironmentwidget.cpp
@@ -43,7 +43,8 @@ BuildEnvironmentWidget::BuildEnvironmentWidget(BuildConfiguration *bc) :
m_clearSystemEnvironmentCheckBox = new QCheckBox(this);
m_clearSystemEnvironmentCheckBox->setText(tr("Clear system environment"));
- m_buildEnvironmentWidget = new EnvironmentWidget(this, m_clearSystemEnvironmentCheckBox);
+ m_buildEnvironmentWidget = new EnvironmentWidget(this, EnvironmentWidget::TypeLocal,
+ m_clearSystemEnvironmentCheckBox);
vbox->addWidget(m_buildEnvironmentWidget);
connect(m_buildEnvironmentWidget, &EnvironmentWidget::userChangesChanged,
diff --git a/src/plugins/projectexplorer/buildinfo.h b/src/plugins/projectexplorer/buildinfo.h
index e135959352..41dfd78180 100644
--- a/src/plugins/projectexplorer/buildinfo.h
+++ b/src/plugins/projectexplorer/buildinfo.h
@@ -46,7 +46,7 @@ public:
QString displayName;
QString typeName;
- Utils::FileName buildDirectory;
+ Utils::FilePath buildDirectory;
Core::Id kitId;
BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp
index 544677517a..eece545e07 100644
--- a/src/plugins/projectexplorer/buildmanager.cpp
+++ b/src/plugins/projectexplorer/buildmanager.cpp
@@ -143,6 +143,8 @@ void BuildManager::extensionsInitialized()
tr("Build System", "Category for build system issues listed under 'Issues'"));
TaskHub::addCategory(Constants::TASK_CATEGORY_DEPLOYMENT,
tr("Deployment", "Category for deployment issues listed under 'Issues'"));
+ TaskHub::addCategory(Constants::TASK_CATEGORY_AUTOTEST,
+ tr("Autotests", "Category for autotest issues listed under 'Issues'"));
}
BuildManager::~BuildManager()
@@ -186,6 +188,16 @@ int BuildManager::getErrorTaskCount()
return errors;
}
+void BuildManager::setCompileOutputSettings(const Internal::CompileOutputSettings &settings)
+{
+ d->m_outputWindow->setSettings(settings);
+}
+
+const Internal::CompileOutputSettings &BuildManager::compileOutputSettings()
+{
+ return d->m_outputWindow->settings();
+}
+
void BuildManager::cancel()
{
if (d->m_running) {
@@ -193,8 +205,6 @@ void BuildManager::cancel()
return;
d->m_canceling = true;
d->m_currentBuildStep->cancel();
- while (d->m_canceling)
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); // TODO: Is this really necessary?
}
}
@@ -366,7 +376,7 @@ void BuildManager::nextBuildQueue()
const QString projectName = d->m_currentBuildStep->project()->displayName();
const QString targetName = t->displayName();
addToOutputWindow(tr("Error while building/deploying project %1 (kit: %2)").arg(projectName, targetName), BuildStep::OutputFormat::Stderr);
- const QList<Task> kitTasks = t->kit()->validate();
+ const Tasks kitTasks = t->kit()->validate();
if (!kitTasks.isEmpty()) {
addToOutputWindow(tr("The kit %1 has configuration issues which might be the root cause for this problem.")
.arg(targetName), BuildStep::OutputFormat::Stderr);
@@ -436,9 +446,12 @@ bool BuildManager::buildQueueAppend(const QList<BuildStep *> &steps, QStringList
{
if (!d->m_running) {
d->m_outputWindow->clearContents();
- TaskHub::clearTasks(Constants::TASK_CATEGORY_COMPILE);
- TaskHub::clearTasks(Constants::TASK_CATEGORY_BUILDSYSTEM);
- TaskHub::clearTasks(Constants::TASK_CATEGORY_DEPLOYMENT);
+ if (ProjectExplorerPlugin::projectExplorerSettings().clearIssuesOnRebuild) {
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_COMPILE);
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_BUILDSYSTEM);
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_DEPLOYMENT);
+ TaskHub::clearTasks(Constants::TASK_CATEGORY_AUTOTEST);
+ }
foreach (const QString &str, preambleMessage)
addToOutputWindow(str, BuildStep::OutputFormat::NormalMessage, BuildStep::DontAppendNewline);
@@ -513,7 +526,7 @@ bool BuildManager::buildLists(QList<BuildStepList *> bsls, const QStringList &pr
return false;
}
- if (ProjectExplorerPlugin::projectExplorerSettings().showCompilerOutput)
+ if (d->m_outputWindow->settings().popUp)
d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
startBuildQueue();
return true;
@@ -526,7 +539,7 @@ void BuildManager::appendStep(BuildStep *step, const QString &name)
d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
return;
}
- if (ProjectExplorerPlugin::projectExplorerSettings().showCompilerOutput)
+ if (d->m_outputWindow->settings().popUp)
d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
startBuildQueue();
}
diff --git a/src/plugins/projectexplorer/buildmanager.h b/src/plugins/projectexplorer/buildmanager.h
index fc23bc851a..fe452d6965 100644
--- a/src/plugins/projectexplorer/buildmanager.h
+++ b/src/plugins/projectexplorer/buildmanager.h
@@ -32,6 +32,7 @@
#include <QStringList>
namespace ProjectExplorer {
+namespace Internal { class CompileOutputSettings; }
class Task;
class Project;
@@ -64,6 +65,9 @@ public:
static int getErrorTaskCount();
+ static void setCompileOutputSettings(const Internal::CompileOutputSettings &settings);
+ static const Internal::CompileOutputSettings &compileOutputSettings();
+
public slots:
static void cancel();
// Shows without focus
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index 772740abd2..481c37eef0 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -119,7 +119,7 @@ BuildSettingsWidget::BuildSettingsWidget(Target *target) :
updateAddButtonMenu();
updateBuildSettings();
- connect(m_buildConfigurationComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_buildConfigurationComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &BuildSettingsWidget::currentIndexChanged);
connect(m_removeButton, &QAbstractButton::clicked,
diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp
index d293b09290..35e02b8972 100644
--- a/src/plugins/projectexplorer/buildstep.cpp
+++ b/src/plugins/projectexplorer/buildstep.cpp
@@ -225,6 +225,12 @@ void BuildStep::setWidgetExpandedByDefault(bool widgetExpandedByDefault)
m_widgetExpandedByDefault = widgetExpandedByDefault;
}
+QVariant BuildStep::data(Core::Id id) const
+{
+ Q_UNUSED(id);
+ return {};
+}
+
/*!
\fn BuildStep::isImmutable()
@@ -299,7 +305,7 @@ bool BuildStepFactory::canHandle(BuildStepList *bsl) const
if (!m_supportedDeviceTypes.isEmpty()) {
Target *target = bsl->target();
QTC_ASSERT(target, return false);
- Core::Id deviceType = DeviceTypeKitInformation::deviceTypeId(target->kit());
+ Core::Id deviceType = DeviceTypeKitAspect::deviceTypeId(target->kit());
if (!m_supportedDeviceTypes.contains(deviceType))
return false;
}
diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h
index 0796b87582..0abf7d5b78 100644
--- a/src/plugins/projectexplorer/buildstep.h
+++ b/src/plugins/projectexplorer/buildstep.h
@@ -28,6 +28,7 @@
#include "projectconfiguration.h"
#include "projectexplorer_export.h"
+#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <QFutureInterface>
@@ -88,9 +89,14 @@ public:
bool widgetExpandedByDefault() const;
void setWidgetExpandedByDefault(bool widgetExpandedByDefault);
+ bool hasUserExpansionState() const { return m_wasExpanded.has_value(); }
+ bool wasUserExpanded() const { return m_wasExpanded.value_or(false); }
+ void setUserExpanded(bool expanded) { m_wasExpanded = expanded; }
+
bool isImmutable() const { return m_immutable; }
void setImmutable(bool immutable) { m_immutable = immutable; }
+ virtual QVariant data(Core::Id id) const;
signals:
/// Adds a \p task to the Issues pane.
/// Do note that for linking compile output with tasks, you should first emit the task
@@ -122,6 +128,7 @@ private:
bool m_immutable = false;
bool m_widgetExpandedByDefault = true;
bool m_runInGuiThread = true;
+ Utils::optional<bool> m_wasExpanded;
};
class PROJECTEXPLORER_EXPORT BuildStepInfo
diff --git a/src/plugins/projectexplorer/buildstepspage.cpp b/src/plugins/projectexplorer/buildstepspage.cpp
index a9897e610c..331ccd9f40 100644
--- a/src/plugins/projectexplorer/buildstepspage.cpp
+++ b/src/plugins/projectexplorer/buildstepspage.cpp
@@ -258,8 +258,11 @@ void BuildStepListWidget::init(BuildStepList *bsl)
for (int i = 0; i < bsl->count(); ++i) {
addBuildStep(i);
// addBuilStep expands the config widget by default, which we don't want here
- if (m_buildStepsData.at(i)->step->widgetExpandedByDefault())
- m_buildStepsData.at(i)->detailsWidget->setState(DetailsWidget::Collapsed);
+ if (m_buildStepsData.at(i)->step->widgetExpandedByDefault()) {
+ m_buildStepsData.at(i)->detailsWidget->setState(
+ m_buildStepsData.at(i)->step->wasUserExpanded()
+ ? DetailsWidget::Expanded : DetailsWidget::Collapsed);
+ }
}
m_noStepsLabel->setVisible(bsl->isEmpty());
@@ -323,10 +326,10 @@ void BuildStepListWidget::addBuildStep(int pos)
this, &BuildStepListWidget::updateEnabledState);
// Expand new build steps by default
- if (newStep->widgetExpandedByDefault())
- s->detailsWidget->setState(DetailsWidget::Expanded);
- else
- s->detailsWidget->setState(DetailsWidget::OnlySummary);
+ const bool expand = newStep->hasUserExpansionState()
+ ? newStep->wasUserExpanded() : newStep->widgetExpandedByDefault();
+ s->detailsWidget->setState(expand ? DetailsWidget::Expanded : DetailsWidget::OnlySummary);
+ connect(s->detailsWidget, &DetailsWidget::expanded, newStep, &BuildStep::setUserExpanded);
m_noStepsLabel->setVisible(false);
updateBuildStepButtonsState();
diff --git a/src/plugins/projectexplorer/buildtargetinfo.h b/src/plugins/projectexplorer/buildtargetinfo.h
index 38cadea991..28af0330a4 100644
--- a/src/plugins/projectexplorer/buildtargetinfo.h
+++ b/src/plugins/projectexplorer/buildtargetinfo.h
@@ -32,7 +32,6 @@
#include <utils/fileutils.h>
#include <QList>
-#include <QSet>
namespace ProjectExplorer {
@@ -43,9 +42,9 @@ public:
QString displayName;
QString displayNameUniquifier;
- Utils::FileName targetFilePath;
- Utils::FileName projectFilePath;
- Utils::FileName workingDirectory;
+ Utils::FilePath targetFilePath;
+ Utils::FilePath projectFilePath;
+ Utils::FilePath workingDirectory;
bool isQtcRunnable = true;
bool usesTerminal = false;
@@ -76,26 +75,4 @@ inline uint qHash(const BuildTargetInfo &ti)
return qHash(ti.displayName) ^ qHash(ti.buildKey);
}
-class PROJECTEXPLORER_EXPORT BuildTargetInfoList
-{
-public:
- BuildTargetInfo buildTargetInfo(const QString &buildKey) {
- return Utils::findOrDefault(list, [&buildKey](const BuildTargetInfo &ti) {
- return ti.buildKey == buildKey;
- });
- }
-
- QList<BuildTargetInfo> list;
-};
-
-inline bool operator==(const BuildTargetInfoList &til1, const BuildTargetInfoList &til2)
-{
- return til1.list.toSet() == til2.list.toSet();
-}
-
-inline bool operator!=(const BuildTargetInfoList &til1, const BuildTargetInfoList &til2)
-{
- return !(til1 == til2);
-}
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/clangparser.cpp b/src/plugins/projectexplorer/clangparser.cpp
index 98d733e69f..1859f25896 100644
--- a/src/plugins/projectexplorer/clangparser.cpp
+++ b/src/plugins/projectexplorer/clangparser.cpp
@@ -68,7 +68,7 @@ void ClangParser::stdError(const QString &line)
m_expectSnippet = true;
Task task(taskType(match.captured(3)),
match.captured(4),
- Utils::FileName(), /* filename */
+ Utils::FilePath(), /* filename */
-1, /* line */
Constants::TASK_CATEGORY_COMPILE);
newTask(task);
@@ -80,7 +80,7 @@ void ClangParser::stdError(const QString &line)
m_expectSnippet = true;
newTask(Task(Task::Unknown,
lne.trimmed(),
- Utils::FileName::fromUserInput(match.captured(2)), /* filename */
+ Utils::FilePath::fromUserInput(match.captured(2)), /* filename */
match.captured(3).toInt(), /* line */
Constants::TASK_CATEGORY_COMPILE));
return;
@@ -95,7 +95,7 @@ void ClangParser::stdError(const QString &line)
lineNo = match.captured(5).toInt(&ok);
Task task(taskType(match.captured(7)),
match.captured(8),
- Utils::FileName::fromUserInput(match.captured(1)), /* filename */
+ Utils::FilePath::fromUserInput(match.captured(1)), /* filename */
lineNo,
Core::Id(Constants::TASK_CATEGORY_COMPILE));
newTask(task);
@@ -107,7 +107,7 @@ void ClangParser::stdError(const QString &line)
m_expectSnippet = true;
Task task(Task::Error,
match.captured(1),
- Utils::FileName(),
+ Utils::FilePath(),
-1,
Core::Id(Constants::TASK_CATEGORY_COMPILE));
newTask(task);
@@ -141,7 +141,7 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
@@ -149,32 +149,32 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
QTest::newRow("pass-through stdout")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("clang++ warning")
<< QString::fromLatin1("clang++: warning: argument unused during compilation: '-mthreads'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("argument unused during compilation: '-mthreads'"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
QTest::newRow("clang++ error")
<< QString::fromLatin1("clang++: error: no input files [err_drv_no_input_files]")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("no input files [err_drv_no_input_files]"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
QTest::newRow("complex warning")
@@ -184,16 +184,16 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
" ^")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("In file included from ..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h:45:"),
- Utils::FileName::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h")), 45,
+ Utils::FilePath::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h")), 45,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("unknown attribute 'dllimport' ignored [-Wunknown-attributes]\n"
"class Q_CORE_EXPORT QSysInfo {\n"
" ^"),
- Utils::FileName::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h")), 1425,
+ Utils::FilePath::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h")), 1425,
categoryCompile))
<< QString();
QTest::newRow("note")
@@ -202,12 +202,12 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
" ^")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("instantiated from:\n"
"# define Q_CORE_EXPORT Q_DECL_IMPORT\n"
" ^"),
- Utils::FileName::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h")), 1289,
+ Utils::FilePath::fromUserInput(QLatin1String("..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qglobal.h")), 1289,
categoryCompile))
<< QString();
QTest::newRow("fatal error")
@@ -216,12 +216,12 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
" ^")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("'bits/c++config.h' file not found\n"
"#include <bits/c++config.h>\n"
" ^"),
- Utils::FileName::fromUserInput(QLatin1String("/usr/include/c++/4.6/utility")), 68,
+ Utils::FilePath::fromUserInput(QLatin1String("/usr/include/c++/4.6/utility")), 68,
categoryCompile))
<< QString();
@@ -231,12 +231,12 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("?: has lower precedence than +; + will be evaluated first [-Wparentheses]\n"
" int x = option->rect.x() + horizontal ? 2 : 6;\n"
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^"),
- Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp")), 567,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp")), 567,
categoryCompile))
<< QString();
QTest::newRow("code sign error")
@@ -245,24 +245,24 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
"CodeSign error: code signing is required for product type 'Application' in SDK 'iOS 7.0'")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Check dependencies\n")
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("No matching provisioning profiles found: No provisioning profiles with a valid signing identity (i.e. certificate and private key pair) were found."),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("code signing is required for product type 'Application' in SDK 'iOS 7.0'"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
QTest::newRow("moc note")
<< QString::fromLatin1("/home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("Note: No relevant classes found. No output generated."),
- Utils::FileName::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
categoryCompile)
)
<< QString();
@@ -274,7 +274,7 @@ void ProjectExplorerPlugin::testClangOutputParser()
testbench.appendOutputParser(new ClangParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp b/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
index 9410c49931..5c25cb83d8 100644
--- a/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
@@ -56,7 +56,7 @@ CodeStyleSettingsWidget::CodeStyleSettingsWidget(Project *project) : QWidget(),
m_ui.languageComboBox->addItem(factory->displayName());
}
- connect(m_ui.languageComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui.languageComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
m_ui.stackedWidget, &QStackedWidget::setCurrentIndex);
}
diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp
index a76ea49ea7..d92bcc4bbe 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.cpp
+++ b/src/plugins/projectexplorer/compileoutputwindow.cpp
@@ -45,12 +45,17 @@
#include <utils/theme/theme.h>
#include <utils/utilsicons.h>
+#include <QCheckBox>
+#include <QHBoxLayout>
#include <QIcon>
-#include <QTextCharFormat>
+#include <QLabel>
+#include <QPlainTextEdit>
+#include <QSpinBox>
#include <QTextBlock>
+#include <QTextCharFormat>
#include <QTextCursor>
-#include <QPlainTextEdit>
#include <QToolButton>
+#include <QVBoxLayout>
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
@@ -58,6 +63,10 @@ using namespace ProjectExplorer::Internal;
namespace {
const char SETTINGS_KEY[] = "ProjectExplorer/CompileOutput/Zoom";
const char C_COMPILE_OUTPUT[] = "ProjectExplorer.CompileOutput";
+const char POP_UP_KEY[] = "ProjectExplorer/Settings/ShowCompilerOutput";
+const char WRAP_OUTPUT_KEY[] = "ProjectExplorer/Settings/WrapBuildOutput";
+const char MAX_LINES_KEY[] = "ProjectExplorer/Settings/MaxBuildOutputLines";
+const char OPTIONS_PAGE_ID[] = "C.ProjectExplorer.CompileOutputOptions";
}
namespace ProjectExplorer {
@@ -67,31 +76,11 @@ class CompileOutputTextEdit : public Core::OutputWindow
{
Q_OBJECT
public:
- CompileOutputTextEdit(const Core::Context &context) : Core::OutputWindow(context)
+ CompileOutputTextEdit(const Core::Context &context) : Core::OutputWindow(context, SETTINGS_KEY)
{
- setWheelZoomEnabled(true);
-
- QSettings *settings = Core::ICore::settings();
- float zoom = settings->value(QLatin1String(SETTINGS_KEY), 0).toFloat();
- setFontZoom(zoom);
-
- fontSettingsChanged();
-
- connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::fontSettingsChanged,
- this, &CompileOutputTextEdit::fontSettingsChanged);
-
- connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
- this, &CompileOutputTextEdit::saveSettings);
-
setMouseTracking(true);
}
- void saveSettings()
- {
- QSettings *settings = Core::ICore::settings();
- settings->setValue(QLatin1String(SETTINGS_KEY), fontZoom());
- }
-
void addTask(const Task &task, int blocknumber)
{
m_taskids.insert(blocknumber, task.taskId);
@@ -101,11 +90,6 @@ public:
{
m_taskids.clear();
}
-private:
- void fontSettingsChanged()
- {
- setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
- }
protected:
void mouseMoveEvent(QMouseEvent *ev) override
@@ -149,8 +133,7 @@ private:
CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
m_cancelBuildButton(new QToolButton),
- m_zoomInButton(new QToolButton),
- m_zoomOutButton(new QToolButton),
+ m_settingsButton(new QToolButton),
m_formatter(new Utils::OutputFormatter)
{
Core::Context context(C_COMPILE_OUTPUT);
@@ -175,21 +158,34 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
Utils::ProxyAction::proxyActionWithIcon(cancelBuildAction,
Utils::Icons::STOP_SMALL_TOOLBAR.icon());
m_cancelBuildButton->setDefaultAction(cancelBuildProxyButton);
- m_zoomInButton->setToolTip(tr("Increase Font Size"));
- m_zoomInButton->setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
- m_zoomOutButton->setToolTip(tr("Decrease Font Size"));
- m_zoomOutButton->setIcon(Utils::Icons::MINUS.icon());
+ m_settingsButton->setToolTip(tr("Open Settings Page"));
+ m_settingsButton->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
+
+ auto updateFontSettings = [this] {
+ m_outputWindow->setBaseFont(TextEditor::TextEditorSettings::fontSettings().font());
+ };
+ auto updateZoomEnabled = [this] {
+ m_outputWindow->setWheelZoomEnabled(
+ TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
+ };
+
+ updateFontSettings();
updateZoomEnabled();
+ setupFilterUi("CompileOutputPane.Filter");
+ setFilteringEnabled(true);
- connect(TextEditor::TextEditorSettings::instance(),
- &TextEditor::TextEditorSettings::behaviorSettingsChanged,
- this, &CompileOutputWindow::updateZoomEnabled);
+ connect(this, &IOutputPane::zoomIn, m_outputWindow, &Core::OutputWindow::zoomIn);
+ connect(this, &IOutputPane::zoomOut, m_outputWindow, &Core::OutputWindow::zoomOut);
+ connect(this, &IOutputPane::resetZoom, m_outputWindow, &Core::OutputWindow::resetZoom);
+ connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::fontSettingsChanged,
+ this, updateFontSettings);
+ connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
+ this, updateZoomEnabled);
- connect(m_zoomInButton, &QToolButton::clicked,
- this, [this]() { m_outputWindow->zoomIn(1); });
- connect(m_zoomOutButton, &QToolButton::clicked,
- this, [this]() { m_outputWindow->zoomOut(1); });
+ connect(m_settingsButton, &QToolButton::clicked, this, [] {
+ Core::ICore::showOptionsDialog(OPTIONS_PAGE_ID);
+ });
auto agg = new Aggregation::Aggregate;
agg->add(m_outputWindow);
@@ -199,8 +195,8 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
m_handler = new ShowOutputTaskHandler(this);
ExtensionSystem::PluginManager::addObject(m_handler);
- connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
- this, &CompileOutputWindow::updateFromSettings);
+ setupContext(C_COMPILE_OUTPUT, m_outputWindow);
+ loadSettings();
updateFromSettings();
}
@@ -209,25 +205,14 @@ CompileOutputWindow::~CompileOutputWindow()
ExtensionSystem::PluginManager::removeObject(m_handler);
delete m_handler;
delete m_cancelBuildButton;
- delete m_zoomInButton;
- delete m_zoomOutButton;
+ delete m_settingsButton;
delete m_formatter;
}
-void CompileOutputWindow::updateZoomEnabled()
-{
- const TextEditor::BehaviorSettings &settings
- = TextEditor::TextEditorSettings::behaviorSettings();
- bool zoomEnabled = settings.m_scrollWheelZooming;
- m_zoomInButton->setEnabled(zoomEnabled);
- m_zoomOutButton->setEnabled(zoomEnabled);
- m_outputWindow->setWheelZoomEnabled(zoomEnabled);
-}
-
void CompileOutputWindow::updateFromSettings()
{
- m_outputWindow->setWordWrapEnabled(ProjectExplorerPlugin::projectExplorerSettings().wrapAppOutput);
- m_outputWindow->setMaxCharCount(ProjectExplorerPlugin::projectExplorerSettings().maxBuildOutputChars);
+ m_outputWindow->setWordWrapEnabled(m_settings.wrapOutput);
+ m_outputWindow->setMaxCharCount(m_settings.maxCharCount);
}
bool CompileOutputWindow::hasFocus() const
@@ -252,7 +237,7 @@ QWidget *CompileOutputWindow::outputWidget(QWidget *)
QList<QWidget *> CompileOutputWindow::toolBarWidgets() const
{
- return {m_cancelBuildButton, m_zoomInButton, m_zoomOutButton};
+ return QList<QWidget *>{m_cancelBuildButton, m_settingsButton} + IOutputPane::toolBarWidgets();
}
void CompileOutputWindow::appendText(const QString &text, BuildStep::OutputFormat format)
@@ -359,4 +344,101 @@ void CompileOutputWindow::flush()
m_formatter->flush();
}
+void CompileOutputWindow::setSettings(const CompileOutputSettings &settings)
+{
+ m_settings = settings;
+ storeSettings();
+ updateFromSettings();
+}
+
+void CompileOutputWindow::updateFilter()
+{
+ m_outputWindow->updateFilterProperties(filterText(), filterCaseSensitivity(),
+ filterUsesRegexp());
+}
+
+void CompileOutputWindow::loadSettings()
+{
+ QSettings * const s = Core::ICore::settings();
+ m_settings.popUp = s->value(POP_UP_KEY, false).toBool();
+ m_settings.wrapOutput = s->value(WRAP_OUTPUT_KEY, true).toBool();
+ m_settings.maxCharCount = s->value(MAX_LINES_KEY,
+ Core::Constants::DEFAULT_MAX_CHAR_COUNT).toInt() * 100;
+}
+
+void CompileOutputWindow::storeSettings() const
+{
+ QSettings * const s = Core::ICore::settings();
+ s->setValue(POP_UP_KEY, m_settings.popUp);
+ s->setValue(WRAP_OUTPUT_KEY, m_settings.wrapOutput);
+ s->setValue(MAX_LINES_KEY, m_settings.maxCharCount / 100);
+}
+
+class CompileOutputSettingsPage::SettingsWidget : public QWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::Internal::CompileOutputSettingsPage)
+public:
+ SettingsWidget()
+ {
+ 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.setChecked(settings.popUp);
+ m_maxCharsBox.setMaximum(100000000);
+ m_maxCharsBox.setValue(settings.maxCharCount);
+ const auto layout = new QVBoxLayout(this);
+ layout->addWidget(&m_wrapOutputCheckBox);
+ layout->addWidget(&m_popUpCheckBox);
+ const auto maxCharsLayout = new QHBoxLayout;
+ const QString msg = tr("Limit output to %1 characters");
+ const QStringList parts = msg.split("%1") << QString() << QString();
+ maxCharsLayout->addWidget(new QLabel(parts.at(0).trimmed()));
+ maxCharsLayout->addWidget(&m_maxCharsBox);
+ maxCharsLayout->addWidget(new QLabel(parts.at(1).trimmed()));
+ maxCharsLayout->addStretch(1);
+ layout->addLayout(maxCharsLayout);
+ layout->addStretch(1);
+ }
+
+ CompileOutputSettings settings() const
+ {
+ CompileOutputSettings s;
+ s.wrapOutput = m_wrapOutputCheckBox.isChecked();
+ s.popUp = m_popUpCheckBox.isChecked();
+ s.maxCharCount = m_maxCharsBox.value();
+ return s;
+ }
+
+private:
+ QCheckBox m_wrapOutputCheckBox;
+ QCheckBox m_popUpCheckBox;
+ QSpinBox m_maxCharsBox;
+};
+
+CompileOutputSettingsPage::CompileOutputSettingsPage()
+{
+ setId(OPTIONS_PAGE_ID);
+ setDisplayName(tr("Compile Output"));
+ setCategory(Constants::BUILD_AND_RUN_SETTINGS_CATEGORY);
+}
+
+QWidget *CompileOutputSettingsPage::widget()
+{
+ if (!m_widget)
+ m_widget = new SettingsWidget;
+ return m_widget;
+}
+
+void CompileOutputSettingsPage::apply()
+{
+ if (m_widget)
+ BuildManager::setCompileOutputSettings(m_widget->settings());
+}
+
+void CompileOutputSettingsPage::finish()
+{
+ delete m_widget;
+}
+
#include "compileoutputwindow.moc"
diff --git a/src/plugins/projectexplorer/compileoutputwindow.h b/src/plugins/projectexplorer/compileoutputwindow.h
index 9ff9c8ac92..a8a5303fc6 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.h
+++ b/src/plugins/projectexplorer/compileoutputwindow.h
@@ -26,10 +26,13 @@
#pragma once
#include "buildstep.h"
+#include "projectexplorersettings.h"
+#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/ioutputpane.h>
#include <QHash>
#include <QPair>
+#include <QPointer>
QT_BEGIN_NAMESPACE
class QPlainTextEdit;
@@ -81,17 +84,39 @@ public:
void flush();
+ const CompileOutputSettings &settings() const { return m_settings; }
+ void setSettings(const CompileOutputSettings &settings);
+
private:
+ void updateFilter() override;
+
+ void loadSettings();
+ void storeSettings() const;
void updateFromSettings();
- void updateZoomEnabled();
CompileOutputTextEdit *m_outputWindow;
QHash<unsigned int, QPair<int, int>> m_taskPositions;
ShowOutputTaskHandler *m_handler;
QToolButton *m_cancelBuildButton;
- QToolButton *m_zoomInButton;
- QToolButton *m_zoomOutButton;
+ QToolButton * const m_settingsButton;
Utils::OutputFormatter *m_formatter;
+ CompileOutputSettings m_settings;
+};
+
+class CompileOutputSettingsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ CompileOutputSettingsPage();
+
+private:
+ QWidget *widget() override;
+ void apply() override;
+ void finish() override;
+
+ class SettingsWidget;
+ QPointer<SettingsWidget> m_widget;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/currentprojectfilter.cpp b/src/plugins/projectexplorer/currentprojectfilter.cpp
index 13c0d308db..0e924eeb2a 100644
--- a/src/plugins/projectexplorer/currentprojectfilter.cpp
+++ b/src/plugins/projectexplorer/currentprojectfilter.cpp
@@ -58,7 +58,7 @@ void CurrentProjectFilter::prepareSearch(const QString &entry)
if (!fileIterator()) {
QStringList paths;
if (m_project)
- paths = Utils::transform(m_project->files(Project::AllFiles), &Utils::FileName::toString);
+ paths = Utils::transform(m_project->files(Project::AllFiles), &Utils::FilePath::toString);
setFileIterator(new BaseFileFilter::ListIterator(paths));
}
BaseFileFilter::prepareSearch(entry);
diff --git a/src/plugins/projectexplorer/currentprojectfind.cpp b/src/plugins/projectexplorer/currentprojectfind.cpp
index 75aaf3e601..ca8093f78b 100644
--- a/src/plugins/projectexplorer/currentprojectfind.cpp
+++ b/src/plugins/projectexplorer/currentprojectfind.cpp
@@ -73,7 +73,7 @@ QVariant CurrentProjectFind::additionalParameters() const
{
Project *project = ProjectTree::currentProject();
if (project && project->document())
- return qVariantFromValue(project->projectFilePath().toString());
+ return QVariant::fromValue(project->projectFilePath().toString());
return QVariant();
}
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
index aa23dc69c9..957b742474 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
@@ -31,7 +31,7 @@
#include "environmentaspect.h"
#include "localenvironmentaspect.h"
#include "project.h"
-#include "runconfigurationaspects.h"
+#include "runcontrol.h"
#include "target.h"
#include <coreplugin/icore.h>
@@ -94,8 +94,7 @@ private:
CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc)
: QDialog(Core::ICore::dialogParent()),
- m_rc(rc),
- m_workingDirectory(rc->aspect<EnvironmentAspect>())
+ m_rc(rc)
{
auto vbox = new QVBoxLayout(this);
vbox->addWidget(new QLabel(tr("Could not find the executable, please specify one.")));
@@ -146,7 +145,7 @@ CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc)
void CustomExecutableDialog::accept()
{
- auto executable = FileName::fromString(m_executableChooser->path());
+ auto executable = FilePath::fromString(m_executableChooser->path());
m_rc->aspect<ExecutableAspect>()->setExecutable(executable);
copyAspect(&m_arguments, m_rc->aspect<ArgumentsAspect>());
copyAspect(&m_workingDirectory, m_rc->aspect<WorkingDirectoryAspect>());
@@ -184,8 +183,7 @@ CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *targe
CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- auto envAspect = addAspect<LocalEnvironmentAspect>
- (target, LocalEnvironmentAspect::BaseEnvironmentModifier());
+ auto envAspect = addAspect<LocalEnvironmentAspect>(target);
auto exeAspect = addAspect<ExecutableAspect>();
exeAspect->setSettingsKey("ProjectExplorer.CustomExecutableRunConfiguration.Executable");
@@ -195,7 +193,7 @@ CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *targe
exeAspect->setEnvironment(envAspect->environment());
addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>(envAspect);
+ addAspect<WorkingDirectoryAspect>();
addAspect<TerminalAspect>();
connect(envAspect, &EnvironmentAspect::environmentChanged,
@@ -253,11 +251,11 @@ bool CustomExecutableRunConfiguration::isConfigured() const
Runnable CustomExecutableRunConfiguration::runnable() const
{
- FileName workingDirectory =
+ FilePath workingDirectory =
aspect<WorkingDirectoryAspect>()->workingDirectory(macroExpander());
Runnable r;
- r.executable = aspect<ExecutableAspect>()->executable().toString();
+ r.executable = executable().toString();
r.commandLineArguments = aspect<ArgumentsAspect>()->arguments(macroExpander());
r.environment = aspect<EnvironmentAspect>()->environment();
r.workingDirectory = workingDirectory.toString();
@@ -285,8 +283,6 @@ CustomExecutableRunConfigurationFactory::CustomExecutableRunConfigurationFactory
FixedRunConfigurationFactory(CustomExecutableRunConfiguration::tr("Custom Executable"))
{
registerRunConfiguration<CustomExecutableRunConfiguration>(CUSTOM_EXECUTABLE_ID);
-
- addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/customparser.cpp b/src/plugins/projectexplorer/customparser.cpp
index 8c0b287ce4..c408dfc2c6 100644
--- a/src/plugins/projectexplorer/customparser.cpp
+++ b/src/plugins/projectexplorer/customparser.cpp
@@ -150,12 +150,12 @@ Core::Id CustomParser::id()
return Core::Id("ProjectExplorer.OutputParser.Custom");
}
-FileName CustomParser::absoluteFilePath(const QString &filePath) const
+FilePath CustomParser::absoluteFilePath(const QString &filePath) const
{
if (m_workingDirectory.isEmpty())
- return FileName::fromUserInput(filePath);
+ return FilePath::fromUserInput(filePath);
- return FileName::fromString(FileUtils::resolvePath(m_workingDirectory, filePath));
+ return FilePath::fromString(FileUtils::resolvePath(m_workingDirectory, filePath));
}
bool CustomParser::hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
@@ -171,7 +171,7 @@ bool CustomParser::hasMatch(const QString &line, CustomParserExpression::CustomP
if (!match.hasMatch())
return false;
- const FileName fileName = absoluteFilePath(match.captured(expression.fileNameCap()));
+ const FilePath fileName = absoluteFilePath(match.captured(expression.fileNameCap()));
const int lineNumber = match.captured(expression.lineNumberCap()).toInt();
const QString message = match.captured(expression.messageCap());
@@ -215,12 +215,12 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
QTest::addColumn<int>("warningMessageCap");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
const QString simplePattern = "^([a-z]+\\.[a-z]+):(\\d+): error: ([^\\s].+)$";
- const FileName fileName = FileName::fromUserInput("main.c");
+ const FilePath fileName = FilePath::fromUserInput("main.c");
QTest::newRow("empty patterns")
<< QString::fromLatin1("Sometext")
@@ -230,7 +230,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< QString() << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stdout")
@@ -241,7 +241,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
@@ -252,7 +252,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString();
const QString simpleError = "main.c:9: error: `sfasdf' undeclared (first use this function)";
@@ -267,12 +267,12 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< QString() << QString()
- << QList<Task>{Task(Task::Error, message, fileName, 9, categoryCompile)}
+ << Tasks{Task(Task::Error, message, fileName, 9, categoryCompile)}
<< QString();
const QString pathPattern = "^([a-z\\./]+):(\\d+): error: ([^\\s].+)$";
QString workingDir = "/home/src/project";
- FileName expandedFileName = FileName::fromString("/home/src/project/main.c");
+ FilePath expandedFileName = FilePath::fromString("/home/src/project/main.c");
QTest::newRow("simple error with expanded path")
<< "main.c:9: error: `sfasdf' undeclared (first use this function)"
@@ -282,10 +282,10 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< pathPattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< QString() << QString()
- << QList<Task>{Task(Task::Error, message, expandedFileName, 9, categoryCompile)}
+ << Tasks{Task(Task::Error, message, expandedFileName, 9, categoryCompile)}
<< QString();
- expandedFileName = FileName::fromString("/home/src/project/subdir/main.c");
+ expandedFileName = FilePath::fromString("/home/src/project/subdir/main.c");
QTest::newRow("simple error with subdir path")
<< "subdir/main.c:9: error: `sfasdf' undeclared (first use this function)"
<< workingDir
@@ -294,7 +294,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< pathPattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< QString() << QString()
- << QList<Task>{Task(Task::Error, message, expandedFileName, 9, categoryCompile)}
+ << Tasks{Task(Task::Error, message, expandedFileName, 9, categoryCompile)}
<< QString();
workingDir = "/home/src/build-project";
@@ -306,7 +306,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< pathPattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< QString() << QString()
- << QList<Task>{Task(Task::Error, message, expandedFileName, 9, categoryCompile)}
+ << Tasks{Task(Task::Error, message, expandedFileName, 9, categoryCompile)}
<< QString();
QTest::newRow("simple error on wrong channel")
@@ -317,7 +317,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< simpleErrorPassThrough << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("simple error on other wrong channel")
@@ -328,7 +328,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< QString() << simpleErrorPassThrough
- << QList<Task>()
+ << Tasks()
<< QString();
const QString simpleError2 = "Error: Line 19 in main.c: `sfasdf' undeclared (first use this function)";
@@ -343,7 +343,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern2 << 2 << 1 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString()
- << QList<Task>{Task(Task::Error, message, fileName, lineNumber2, categoryCompile)}
+ << Tasks{Task(Task::Error, message, fileName, lineNumber2, categoryCompile)}
<< QString();
QTest::newRow("another simple error on stdout")
@@ -354,7 +354,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern2 << 2 << 1 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString()
- << QList<Task>{Task(Task::Error, message, fileName, lineNumber2, categoryCompile)}
+ << Tasks{Task(Task::Error, message, fileName, lineNumber2, categoryCompile)}
<< QString();
const QString simpleWarningPattern = "^([a-z]+\\.[a-z]+):(\\d+): warning: ([^\\s].+)$";
@@ -369,7 +369,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< QString() << 1 << 2 << 3
<< simpleWarningPattern << 1 << 2 << 3
<< QString() << QString()
- << QList<Task>{Task(Task::Warning, warningMessage, fileName, 1234, categoryCompile)}
+ << Tasks{Task(Task::Warning, warningMessage, fileName, 1234, categoryCompile)}
<< QString();
const QString simpleWarning2 = "Warning: `helloWorld' declared but not used (main.c:19)";
@@ -384,7 +384,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern2 << 1 << 2 << 3
<< simpleWarningPattern2 << 2 << 3 << 1
<< QString() << QString()
- << QList<Task>{Task(Task::Warning, warningMessage, fileName, lineNumber2, categoryCompile)}
+ << Tasks{Task(Task::Warning, warningMessage, fileName, lineNumber2, categoryCompile)}
<< QString();
QTest::newRow("warning on wrong channel")
@@ -395,7 +395,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< QString() << 1 << 2 << 3
<< simpleWarningPattern2 << 2 << 3 << 1
<< simpleWarningPassThrough2 << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("warning on other wrong channel")
@@ -406,7 +406,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< QString() << 1 << 2 << 3
<< simpleWarningPattern2 << 2 << 3 << 1
<< QString() << simpleWarningPassThrough2
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("error and *warning*")
@@ -417,7 +417,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern << 1 << 2 << 3
<< simpleWarningPattern << 1 << 2 << 3
<< QString() << QString()
- << QList<Task>{Task(Task::Warning, warningMessage, fileName, 1234, categoryCompile)}
+ << Tasks{Task(Task::Warning, warningMessage, fileName, 1234, categoryCompile)}
<< QString();
QTest::newRow("*error* when equal pattern")
@@ -428,11 +428,11 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< simplePattern << 1 << 2 << 3
<< simplePattern << 1 << 2 << 3
<< QString() << QString()
- << QList<Task>{Task(Task::Error, message, fileName, 9, categoryCompile)}
+ << Tasks{Task(Task::Error, message, fileName, 9, categoryCompile)}
<< QString();
const QString unitTestError = "../LedDriver/LedDriverTest.c:63: FAIL: Expected 0x0080 Was 0xffff";
- const FileName unitTestFileName = FileName::fromUserInput("../LedDriver/LedDriverTest.c");
+ const FilePath unitTestFileName = FilePath::fromUserInput("../LedDriver/LedDriverTest.c");
const QString unitTestMessage = "Expected 0x0080 Was 0xffff";
const QString unitTestPattern = "^([^:]+):(\\d+): FAIL: ([^\\s].+)$";
const int unitTestLineNumber = 63;
@@ -445,7 +445,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
<< unitTestPattern << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString()
- << QList<Task>{Task(Task::Error, unitTestMessage, unitTestFileName, unitTestLineNumber, categoryCompile)}
+ << Tasks{Task(Task::Error, unitTestMessage, unitTestFileName, unitTestLineNumber, categoryCompile)}
<< QString();
}
@@ -466,7 +466,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers()
QFETCH(int, warningMessageCap);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, outputLines);
CustomParserSettings settings;
diff --git a/src/plugins/projectexplorer/customparser.h b/src/plugins/projectexplorer/customparser.h
index b7c70d4759..dafb0e8da1 100644
--- a/src/plugins/projectexplorer/customparser.h
+++ b/src/plugins/projectexplorer/customparser.h
@@ -96,7 +96,7 @@ public:
static Core::Id id();
private:
- Utils::FileName absoluteFilePath(const QString &filePath) const;
+ Utils::FilePath absoluteFilePath(const QString &filePath) const;
bool hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
const CustomParserExpression &expression, Task::TaskType taskType);
bool parseLine(const QString &rawLine, CustomParserExpression::CustomParserChannel channel);
diff --git a/src/plugins/projectexplorer/customparserconfigdialog.cpp b/src/plugins/projectexplorer/customparserconfigdialog.cpp
index b688e8aca1..061d1814ed 100644
--- a/src/plugins/projectexplorer/customparserconfigdialog.cpp
+++ b/src/plugins/projectexplorer/customparserconfigdialog.cpp
@@ -42,20 +42,20 @@ CustomParserConfigDialog::CustomParserConfigDialog(QDialog *parent) :
connect(ui->errorPattern, &QLineEdit::textChanged, this, &CustomParserConfigDialog::changed);
connect(ui->errorOutputMessage, &QLineEdit::textChanged,
this, &CustomParserConfigDialog::changed);
- connect(ui->errorFileNameCap, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(ui->errorFileNameCap, QOverload<int>::of(&QSpinBox::valueChanged),
this, &CustomParserConfigDialog::changed);
- connect(ui->errorLineNumberCap, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(ui->errorLineNumberCap, QOverload<int>::of(&QSpinBox::valueChanged),
this, &CustomParserConfigDialog::changed);
- connect(ui->errorMessageCap, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(ui->errorMessageCap, QOverload<int>::of(&QSpinBox::valueChanged),
this, &CustomParserConfigDialog::changed);
connect(ui->warningPattern, &QLineEdit::textChanged, this, &CustomParserConfigDialog::changed);
connect(ui->warningOutputMessage, &QLineEdit::textChanged,
this, &CustomParserConfigDialog::changed);
- connect(ui->warningFileNameCap, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(ui->warningFileNameCap, QOverload<int>::of(&QSpinBox::valueChanged),
this, &CustomParserConfigDialog::changed);
- connect(ui->warningLineNumberCap, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(ui->warningLineNumberCap, QOverload<int>::of(&QSpinBox::valueChanged),
this, &CustomParserConfigDialog::changed);
- connect(ui->warningMessageCap, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(ui->warningMessageCap, QOverload<int>::of(&QSpinBox::valueChanged),
this, &CustomParserConfigDialog::changed);
changed();
diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp
index 1833875102..e1175963ea 100644
--- a/src/plugins/projectexplorer/customtoolchain.cpp
+++ b/src/plugins/projectexplorer/customtoolchain.cpp
@@ -81,17 +81,11 @@ static const char warningExampleKeyC[] = "ProjectExplorer.CustomToolChain.Warnin
// CustomToolChain
// --------------------------------------------------------------------------
-CustomToolChain::CustomToolChain(Detection d) :
- ToolChain(Constants::CUSTOM_TOOLCHAIN_TYPEID, d),
+CustomToolChain::CustomToolChain() :
+ ToolChain(Constants::CUSTOM_TOOLCHAIN_TYPEID),
m_outputParserId(GccParser::id())
{ }
-CustomToolChain::CustomToolChain(Core::Id language, Detection d) : CustomToolChain(d)
-{
- setLanguage(language);
-}
-
-
QString CustomToolChain::typeDisplayName() const
{
return Internal::CustomToolChainFactory::tr("Custom");
@@ -169,7 +163,7 @@ ToolChain::BuiltInHeaderPathsRunner CustomToolChain::createBuiltInHeaderPathsRun
const HeaderPaths builtInHeaderPaths = m_builtInHeaderPaths;
// This runner must be thread-safe!
- return [builtInHeaderPaths](const QStringList &cxxFlags, const QString &) {
+ return [builtInHeaderPaths](const QStringList &cxxFlags, const QString &, const QString &) {
HeaderPaths flagHeaderPaths;
for (const QString &cxxFlag : cxxFlags) {
if (cxxFlag.startsWith(QLatin1String("-I"))) {
@@ -182,23 +176,23 @@ ToolChain::BuiltInHeaderPathsRunner CustomToolChain::createBuiltInHeaderPathsRun
}
HeaderPaths CustomToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
- const FileName &fileName) const
+ const FilePath &fileName) const
{
- return createBuiltInHeaderPathsRunner()(cxxFlags, fileName.toString());
+ return createBuiltInHeaderPathsRunner()(cxxFlags, fileName.toString(), "");
}
void CustomToolChain::addToEnvironment(Environment &env) const
{
if (!m_compilerCommand.isEmpty()) {
- FileName path = m_compilerCommand.parentDir();
+ FilePath path = m_compilerCommand.parentDir();
env.prependOrSetPath(path.toString());
- FileName makePath = m_makeCommand.parentDir();
+ FilePath makePath = m_makeCommand.parentDir();
if (makePath != path)
env.prependOrSetPath(makePath.toString());
}
}
-FileNameList CustomToolChain::suggestedMkspecList() const
+QStringList CustomToolChain::suggestedMkspecList() const
{
return m_mkspecs;
}
@@ -235,7 +229,7 @@ void CustomToolChain::setHeaderPaths(const QStringList &list)
toolChainUpdated();
}
-void CustomToolChain::setCompilerCommand(const FileName &path)
+void CustomToolChain::setCompilerCommand(const FilePath &path)
{
if (path == m_compilerCommand)
return;
@@ -243,12 +237,12 @@ void CustomToolChain::setCompilerCommand(const FileName &path)
toolChainUpdated();
}
-FileName CustomToolChain::compilerCommand() const
+FilePath CustomToolChain::compilerCommand() const
{
return m_compilerCommand;
}
-void CustomToolChain::setMakeCommand(const FileName &path)
+void CustomToolChain::setMakeCommand(const FilePath &path)
{
if (path == m_makeCommand)
return;
@@ -256,9 +250,9 @@ void CustomToolChain::setMakeCommand(const FileName &path)
toolChainUpdated();
}
-QString CustomToolChain::makeCommand(const Environment &) const
+FilePath CustomToolChain::makeCommand(const Environment &) const
{
- return m_makeCommand.toString();
+ return m_makeCommand;
}
void CustomToolChain::setCxx11Flags(const QStringList &flags)
@@ -276,10 +270,7 @@ const QStringList &CustomToolChain::cxx11Flags() const
void CustomToolChain::setMkspecs(const QString &specs)
{
- Utils::FileNameList tmp
- = Utils::transform(specs.split(QLatin1Char(',')),
- [](QString fn) { return FileName::fromString(fn); });
-
+ const QStringList tmp = specs.split(',');
if (tmp == m_mkspecs)
return;
m_mkspecs = tmp;
@@ -288,16 +279,7 @@ void CustomToolChain::setMkspecs(const QString &specs)
QString CustomToolChain::mkspecs() const
{
- QString list;
- for (const FileName &spec : m_mkspecs)
- list.append(spec.toString() + QLatin1Char(','));
- list.chop(1);
- return list;
-}
-
-ToolChain *CustomToolChain::clone() const
-{
- return new CustomToolChain(*this);
+ return m_mkspecs.join(',');
}
QVariantMap CustomToolChain::toMap() const
@@ -333,8 +315,8 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
if (!ToolChain::fromMap(data))
return false;
- m_compilerCommand = FileName::fromString(data.value(QLatin1String(compilerCommandKeyC)).toString());
- m_makeCommand = FileName::fromString(data.value(QLatin1String(makeCommandKeyC)).toString());
+ m_compilerCommand = FilePath::fromString(data.value(QLatin1String(compilerCommandKeyC)).toString());
+ m_makeCommand = FilePath::fromString(data.value(QLatin1String(makeCommandKeyC)).toString());
m_targetAbi = Abi::fromString(data.value(QLatin1String(targetAbiKeyC)).toString());
const QStringList macros = data.value(QLatin1String(predefinedMacrosKeyC)).toStringList();
m_predefinedMacros = Macro::toMacros(macros.join('\n').toUtf8());
@@ -425,37 +407,10 @@ namespace Internal {
CustomToolChainFactory::CustomToolChainFactory()
{
setDisplayName(tr("Custom"));
-}
-
-QSet<Core::Id> CustomToolChainFactory::supportedLanguages() const
-{
- return ToolChainManager::allLanguages();
-}
-
-bool CustomToolChainFactory::canCreate()
-{
- return true;
-}
-
-ToolChain *CustomToolChainFactory::create(Core::Id language)
-{
- return new CustomToolChain(language, ToolChain::ManualDetection);
-}
-
-// Used by the ToolChainManager to restore user-generated tool chains
-bool CustomToolChainFactory::canRestore(const QVariantMap &data)
-{
- return typeIdFromMap(data) == Constants::CUSTOM_TOOLCHAIN_TYPEID;
-}
-
-ToolChain *CustomToolChainFactory::restore(const QVariantMap &data)
-{
- auto tc = new CustomToolChain(ToolChain::ManualDetection);
- if (tc->fromMap(data))
- return tc;
-
- delete tc;
- return nullptr;
+ setSupportedToolChainType(Constants::CUSTOM_TOOLCHAIN_TYPEID);
+ setSupportsAllLanguages(true);
+ setToolchainConstructor([] { return new CustomToolChain; });
+ setUserCreatable(true);
}
// --------------------------------------------------------------------------
@@ -566,7 +521,7 @@ CustomToolChainConfigWidget::CustomToolChainConfigWidget(CustomToolChain *tc) :
this, &CustomToolChainConfigWidget::updateSummaries);
connect(m_cxx11Flags, &QLineEdit::textChanged, this, &ToolChainConfigWidget::dirty);
connect(m_mkspecs, &QLineEdit::textChanged, this, &ToolChainConfigWidget::dirty);
- connect(m_errorParserComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_errorParserComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &CustomToolChainConfigWidget::errorParserChanged);
connect(m_customParserSettingsButton, &QAbstractButton::clicked,
this, &CustomToolChainConfigWidget::openCustomParserSettingsDialog);
@@ -635,8 +590,8 @@ void CustomToolChainConfigWidget::setFromToolchain()
QSignalBlocker blocker(this);
auto tc = static_cast<CustomToolChain *>(toolChain());
m_compilerCommand->setFileName(tc->compilerCommand());
- m_makeCommand->setFileName(FileName::fromString(tc->makeCommand(Environment())));
- m_abiWidget->setAbis(QList<Abi>(), tc->targetAbi());
+ m_makeCommand->setFileName(tc->makeCommand(Environment()));
+ m_abiWidget->setAbis(Abis(), tc->targetAbi());
const QStringList macroLines = Utils::transform<QList>(tc->rawPredefinedMacros(), [](const Macro &m) {
return QString::fromUtf8(m.toKeyValue(QByteArray()));
});
@@ -654,7 +609,7 @@ bool CustomToolChainConfigWidget::isDirtyImpl() const
auto tc = static_cast<CustomToolChain *>(toolChain());
Q_ASSERT(tc);
return m_compilerCommand->fileName() != tc->compilerCommand()
- || m_makeCommand->path() != tc->makeCommand(Environment())
+ || m_makeCommand->path() != tc->makeCommand(Environment()).toString()
|| m_abiWidget->currentAbi() != tc->targetAbi()
|| Macro::toMacros(m_predefinedDetails->text().toUtf8()) != tc->rawPredefinedMacros()
|| m_headerDetails->entries() != tc->headerPathsList()
diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h
index 37ca6abd15..415cf89abd 100644
--- a/src/plugins/projectexplorer/customtoolchain.h
+++ b/src/plugins/projectexplorer/customtoolchain.h
@@ -80,9 +80,9 @@ public:
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override;
HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
- const Utils::FileName &) const override;
+ const Utils::FilePath &) const override;
void addToEnvironment(Utils::Environment &env) const override;
- Utils::FileNameList suggestedMkspecList() const override;
+ QStringList suggestedMkspecList() const override;
IOutputParser *outputParser() const override;
QStringList headerPathsList() const;
void setHeaderPaths(const QStringList &list);
@@ -94,10 +94,10 @@ public:
bool operator ==(const ToolChain &) const override;
- void setCompilerCommand(const Utils::FileName &);
- Utils::FileName compilerCommand() const override;
- void setMakeCommand(const Utils::FileName &);
- QString makeCommand(const Utils::Environment &environment) const override;
+ void setCompilerCommand(const Utils::FilePath &);
+ Utils::FilePath compilerCommand() const override;
+ void setMakeCommand(const Utils::FilePath &);
+ Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
void setCxx11Flags(const QStringList &);
const QStringList &cxx11Flags() const;
@@ -105,29 +105,23 @@ public:
void setMkspecs(const QString &);
QString mkspecs() const;
- ToolChain *clone() const override;
-
Core::Id outputParserId() const;
void setOutputParserId(Core::Id parserId);
CustomParserSettings customParserSettings() const;
void setCustomParserSettings(const CustomParserSettings &settings);
static QList<CustomToolChain::Parser> parsers();
-protected:
- CustomToolChain(const CustomToolChain &) = default;
-
private:
- explicit CustomToolChain(Detection d);
- explicit CustomToolChain(Core::Id language, Detection d);
+ CustomToolChain();
- Utils::FileName m_compilerCommand;
- Utils::FileName m_makeCommand;
+ Utils::FilePath m_compilerCommand;
+ Utils::FilePath m_makeCommand;
Abi m_targetAbi;
Macros m_predefinedMacros;
HeaderPaths m_builtInHeaderPaths;
QStringList m_cxx11Flags;
- Utils::FileNameList m_mkspecs;
+ QStringList m_mkspecs;
Core::Id m_outputParserId;
CustomParserSettings m_customParserSettings;
@@ -144,14 +138,6 @@ class CustomToolChainFactory : public ToolChainFactory
public:
CustomToolChainFactory();
- QSet<Core::Id> supportedLanguages() const override;
-
- bool canCreate() override;
- ToolChain *create(Core::Id language) override;
-
- // Used by the ToolChainManager to restore user-generated tool chains
- bool canRestore(const QVariantMap &data) override;
- ToolChain *restore(const QVariantMap &data) override;
};
// --------------------------------------------------------------------------
diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp
index 9a3ea42a4e..1f92543431 100644
--- a/src/plugins/projectexplorer/customwizard/customwizard.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp
@@ -406,7 +406,7 @@ QList<Core::IWizardFactory *> CustomWizard::createWizards()
const QDir::Filters filters = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const QDir::SortFlags sortflags = QDir::Name|QDir::IgnoreCase;
- QList<QFileInfo> dirs;
+ QFileInfoList dirs;
if (userTemplateDir.exists()) {
if (CustomWizardPrivate::verbose)
verboseLog += QString::fromLatin1("### CustomWizard: userTemplateDir \"%1\" found, adding\n").arg(userTemplateDirName);
@@ -446,7 +446,7 @@ QList<Core::IWizardFactory *> CustomWizard::createWizards()
break;
}
} else {
- QList<QFileInfo> subDirs = dir.entryInfoList(filters, sortflags);
+ QFileInfoList subDirs = dir.entryInfoList(filters, sortflags);
if (!subDirs.isEmpty()) {
// There is no QList::prepend(QList)...
dirs.swap(subDirs);
diff --git a/src/plugins/projectexplorer/deployablefile.cpp b/src/plugins/projectexplorer/deployablefile.cpp
index 1d7b6132c1..d8ea6cd33a 100644
--- a/src/plugins/projectexplorer/deployablefile.cpp
+++ b/src/plugins/projectexplorer/deployablefile.cpp
@@ -34,10 +34,10 @@ using namespace Utils;
namespace ProjectExplorer {
DeployableFile::DeployableFile(const QString &localFilePath, const QString &remoteDir, Type type)
- : m_localFilePath(FileName::fromUserInput(localFilePath)), m_remoteDir(remoteDir), m_type(type)
+ : m_localFilePath(FilePath::fromUserInput(localFilePath)), m_remoteDir(remoteDir), m_type(type)
{ }
-DeployableFile::DeployableFile(const FileName &localFilePath, const QString &remoteDir, Type type)
+DeployableFile::DeployableFile(const FilePath &localFilePath, const QString &remoteDir, Type type)
: m_localFilePath(localFilePath), m_remoteDir(remoteDir), m_type(type)
{ }
diff --git a/src/plugins/projectexplorer/deployablefile.h b/src/plugins/projectexplorer/deployablefile.h
index 70d05c29e8..b1a6c6a1d6 100644
--- a/src/plugins/projectexplorer/deployablefile.h
+++ b/src/plugins/projectexplorer/deployablefile.h
@@ -45,10 +45,10 @@ public:
DeployableFile() = default;
DeployableFile(const QString &m_localFilePath, const QString &m_remoteDir,
Type type = TypeNormal);
- DeployableFile(const Utils::FileName &localFilePath, const QString &remoteDir,
+ DeployableFile(const Utils::FilePath &localFilePath, const QString &remoteDir,
Type type = TypeNormal);
- Utils::FileName localFilePath() const { return m_localFilePath; }
+ Utils::FilePath localFilePath() const { return m_localFilePath; }
QString remoteDirectory() const { return m_remoteDir; }
QString remoteFilePath() const;
@@ -57,7 +57,7 @@ public:
bool isExecutable() const;
private:
- Utils::FileName m_localFilePath;
+ Utils::FilePath m_localFilePath;
QString m_remoteDir;
Type m_type = TypeNormal;
};
diff --git a/src/plugins/projectexplorer/deployconfiguration.cpp b/src/plugins/projectexplorer/deployconfiguration.cpp
index 7619a06ca2..4d16599a12 100644
--- a/src/plugins/projectexplorer/deployconfiguration.cpp
+++ b/src/plugins/projectexplorer/deployconfiguration.cpp
@@ -162,7 +162,7 @@ bool DeployConfigurationFactory::canHandle(Target *target) const
if (!m_supportedTargetDeviceTypes.isEmpty()) {
if (!m_supportedTargetDeviceTypes.contains(
- DeviceTypeKitInformation::deviceTypeId(target->kit())))
+ DeviceTypeKitAspect::deviceTypeId(target->kit())))
return false;
}
diff --git a/src/plugins/projectexplorer/deploymentdata.cpp b/src/plugins/projectexplorer/deploymentdata.cpp
index c34b6a4044..7cdc4a1185 100644
--- a/src/plugins/projectexplorer/deploymentdata.cpp
+++ b/src/plugins/projectexplorer/deploymentdata.cpp
@@ -33,7 +33,7 @@
namespace ProjectExplorer {
-void DeploymentData::setLocalInstallRoot(const Utils::FileName &installRoot)
+void DeploymentData::setLocalInstallRoot(const Utils::FilePath &installRoot)
{
m_localInstallRoot = installRoot;
}
diff --git a/src/plugins/projectexplorer/deploymentdata.h b/src/plugins/projectexplorer/deploymentdata.h
index 7297ad84b2..e45427ebf8 100644
--- a/src/plugins/projectexplorer/deploymentdata.h
+++ b/src/plugins/projectexplorer/deploymentdata.h
@@ -28,18 +28,30 @@
#include "deployablefile.h"
#include "projectexplorer_export.h"
+#include <utils/environment.h>
+
#include <QList>
namespace ProjectExplorer {
+enum class DeploymentKnowledge { Perfect, Approximative, Bad };
+
+class PROJECTEXPLORER_EXPORT MakeInstallCommand
+{
+public:
+ Utils::FilePath command;
+ QStringList arguments;
+ Utils::Environment environment;
+};
+
class PROJECTEXPLORER_EXPORT DeploymentData
{
public:
void setFileList(const QList<DeployableFile> &files) { m_files = files; }
QList<DeployableFile> allFiles() const { return m_files; }
- void setLocalInstallRoot(const Utils::FileName &installRoot);
- Utils::FileName localInstallRoot() const { return m_localInstallRoot; }
+ void setLocalInstallRoot(const Utils::FilePath &installRoot);
+ Utils::FilePath localInstallRoot() const { return m_localInstallRoot; }
void addFile(const DeployableFile &file);
void addFile(const QString &localFilePath, const QString &remoteDirectory,
@@ -54,7 +66,7 @@ public:
private:
QList<DeployableFile> m_files;
- Utils::FileName m_localInstallRoot;
+ Utils::FilePath m_localInstallRoot;
};
inline bool operator!=(const DeploymentData &d1, const DeploymentData &d2) { return !(d1 == d2); }
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
index 283e921d92..a725658b9b 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
@@ -30,8 +30,10 @@
#include "desktopdeviceconfigurationwidget.h"
#include "desktopprocesssignaloperation.h"
+#include <coreplugin/fileutils.h>
+
#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <ssh/sshconnection.h>
@@ -58,10 +60,11 @@ DesktopDevice::DesktopDevice()
const QString portRange =
QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END);
setFreePorts(Utils::PortList::fromString(portRange));
+ setOpenTerminal([](const Utils::Environment &env, const QString &workingDir) {
+ Core::FileUtils::openTerminal(workingDir, env);
+ });
}
-DesktopDevice::DesktopDevice(const DesktopDevice &other) = default;
-
IDevice::DeviceInfo DesktopDevice::deviceInformation() const
{
return DeviceInfo();
@@ -177,9 +180,4 @@ Utils::OsType DesktopDevice::osType() const
return Utils::HostOsInfo::hostOs();
}
-IDevice::Ptr DesktopDevice::clone() const
-{
- return Ptr(new DesktopDevice(*this));
-}
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h
index da57cf95bd..dec063b5e5 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h
+++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h
@@ -53,11 +53,8 @@ public:
QUrl toolControlChannel(const ControlChannelHint &) const override;
Utils::OsType osType() const override;
- IDevice::Ptr clone() const override;
-
protected:
DesktopDevice();
- DesktopDevice(const DesktopDevice &other);
friend class ProjectExplorerPlugin;
friend class Internal::DesktopDeviceFactory;
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp
index d57b765bb0..bb9f6c8f43 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp
+++ b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp
@@ -26,7 +26,7 @@
#include "desktopdeviceprocess.h"
#include "idevice.h"
-#include "../runconfiguration.h"
+#include "../runcontrol.h"
#include <utils/environment.h>
#include <utils/qtcassert.h>
diff --git a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp
index 7935efb5fc..29e95751f6 100644
--- a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp
@@ -44,9 +44,9 @@ DeviceCheckBuildStep::DeviceCheckBuildStep(BuildStepList *bsl)
bool DeviceCheckBuildStep::init()
{
- IDevice::ConstPtr device = DeviceKitInformation::device(target()->kit());
+ IDevice::ConstPtr device = DeviceKitAspect::device(target()->kit());
if (!device) {
- Core::Id deviceTypeId = DeviceTypeKitInformation::deviceTypeId(target()->kit());
+ Core::Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(target()->kit());
IDeviceFactory *factory = IDeviceFactory::find(deviceTypeId);
if (!factory || !factory->canCreate()) {
emit addOutput(tr("No device configured."), BuildStep::OutputFormat::ErrorMessage);
@@ -71,7 +71,7 @@ bool DeviceCheckBuildStep::init()
DeviceManager *dm = DeviceManager::instance();
dm->addDevice(newDevice);
- DeviceKitInformation::setDevice(target()->kit(), newDevice);
+ DeviceKitAspect::setDevice(target()->kit(), newDevice);
}
return true;
diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
index d8c72aa354..cd6e7421aa 100644
--- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
@@ -221,14 +221,14 @@ QVariantMap DeviceManager::toMap() const
return map;
}
-Utils::FileName DeviceManager::settingsFilePath(const QString &extension)
+Utils::FilePath DeviceManager::settingsFilePath(const QString &extension)
{
- return Utils::FileName::fromString(Core::ICore::userResourcePath() + extension);
+ return Utils::FilePath::fromString(Core::ICore::userResourcePath() + extension);
}
-Utils::FileName DeviceManager::systemSettingsFilePath(const QString &deviceFileRelativePath)
+Utils::FilePath DeviceManager::systemSettingsFilePath(const QString &deviceFileRelativePath)
{
- return Utils::FileName::fromString(Core::ICore::installerResourcePath()
+ return Utils::FilePath::fromString(Core::ICore::installerResourcePath()
+ deviceFileRelativePath);
}
@@ -414,10 +414,8 @@ public:
static Core::Id testTypeId() { return "TestType"; }
private:
- TestDevice(const TestDevice &other) = default;
QString displayType() const override { return QLatin1String("blubb"); }
IDeviceWidget *createWidget() override { return nullptr; }
- Ptr clone() const override { return Ptr(new TestDevice(*this)); }
DeviceProcessSignalOperation::Ptr signalOperation() const override
{
return DeviceProcessSignalOperation::Ptr();
@@ -425,8 +423,19 @@ private:
Utils::OsType osType() const override { return Utils::HostOsInfo::hostOs(); }
};
+class TestDeviceFactory : public IDeviceFactory
+{
+public:
+ TestDeviceFactory() : IDeviceFactory(TestDevice::testTypeId())
+ {
+ setConstructionFunction([] { return IDevice::Ptr(new TestDevice); });
+ }
+};
+
void ProjectExplorerPlugin::testDeviceManager()
{
+ TestDeviceFactory factory;
+
TestDevice::Ptr dev = IDevice::Ptr(new TestDevice);
dev->setDisplayName(QLatin1String("blubbdiblubbfurz!"));
QVERIFY(dev->isAutoDetected());
diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.h b/src/plugins/projectexplorer/devicesupport/devicemanager.h
index bd9c2b606e..6f286845dd 100644
--- a/src/plugins/projectexplorer/devicesupport/devicemanager.h
+++ b/src/plugins/projectexplorer/devicesupport/devicemanager.h
@@ -33,7 +33,7 @@
#include <memory>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ProjectExplorer {
class IDevice;
@@ -96,8 +96,8 @@ private:
static void replaceInstance();
static void removeClonedInstance();
- static Utils::FileName settingsFilePath(const QString &extension);
- static Utils::FileName systemSettingsFilePath(const QString &deviceFileRelativePath);
+ static Utils::FilePath settingsFilePath(const QString &extension);
+ static Utils::FilePath systemSettingsFilePath(const QString &deviceFileRelativePath);
static void copy(const DeviceManager *source, DeviceManager *target, bool deep);
const std::unique_ptr<Internal::DeviceManagerPrivate> d;
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocess.h b/src/plugins/projectexplorer/devicesupport/deviceprocess.h
index e26151d251..4aa197666c 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocess.h
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocess.h
@@ -26,7 +26,6 @@
#pragma once
#include "../projectexplorer_export.h"
-#include "../runconfiguration.h"
#include <QObject>
#include <QProcess>
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp
index dd6a851929..2e0cf6a660 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp
@@ -185,14 +185,10 @@ DeviceProcessesDialogPrivate::DeviceProcessesDialogPrivate(KitChooser *chooser,
proxyModel.setFilterRegExp(processFilterLineEdit->text());
- connect(processFilterLineEdit,
- static_cast<void (FancyLineEdit::*)(const QString &)>(&FancyLineEdit::textChanged),
- &proxyModel,
- static_cast<void (ProcessListFilterModel::*)(const QString &)>(
- &ProcessListFilterModel::setFilterRegExp));
- connect(procView->selectionModel(),
- &QItemSelectionModel::selectionChanged,
- this, &DeviceProcessesDialogPrivate::updateButtons);
+ connect(processFilterLineEdit, QOverload<const QString &>::of(&FancyLineEdit::textChanged),
+ &proxyModel, QOverload<const QString &>::of(&ProcessListFilterModel::setFilterRegExp));
+ connect(procView->selectionModel(), &QItemSelectionModel::selectionChanged,
+ this, &DeviceProcessesDialogPrivate::updateButtons);
connect(updateListButton, &QAbstractButton::clicked,
this, &DeviceProcessesDialogPrivate::updateProcessList);
connect(kitChooser, &KitChooser::currentIndexChanged,
@@ -219,7 +215,7 @@ void DeviceProcessesDialogPrivate::setDevice(const IDevice::ConstPtr &device)
processList = device->createProcessListModel();
QTC_ASSERT(processList, return);
- proxyModel.setSourceModel(processList);
+ proxyModel.setSourceModel(processList->model());
connect(processList, &DeviceProcessList::error,
this, &DeviceProcessesDialogPrivate::handleRemoteError);
@@ -267,7 +263,7 @@ void DeviceProcessesDialogPrivate::killProcess()
void DeviceProcessesDialogPrivate::updateDevice()
{
- setDevice(DeviceKitInformation::device(kitChooser->currentKit()));
+ setDevice(DeviceKitAspect::device(kitChooser->currentKit()));
}
void DeviceProcessesDialogPrivate::handleProcessKilled()
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp
index e6075da516..0405956100 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp
@@ -27,23 +27,38 @@
#include "localprocesslist.h"
#include <utils/qtcassert.h>
+#include <utils/treemodel.h>
+
+using namespace Utils;
namespace ProjectExplorer {
namespace Internal {
enum State { Inactive, Listing, Killing };
+class DeviceProcessTreeItem : public TreeItem
+{
+public:
+ DeviceProcessTreeItem(const DeviceProcessItem &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;
+ Qt::ItemFlags fl;
+};
+
class DeviceProcessListPrivate
{
public:
DeviceProcessListPrivate(const IDevice::ConstPtr &device)
- : device(device),
- state(Inactive)
+ : device(device)
{ }
+ qint64 ownPid = -1;
const IDevice::ConstPtr device;
- QList<DeviceProcessItem> remoteProcesses;
- State state;
+ State state = Inactive;
+ TreeModel<TypedTreeItem<DeviceProcessTreeItem>, DeviceProcessTreeItem> model;
};
} // namespace Internal
@@ -51,39 +66,19 @@ public:
using namespace Internal;
DeviceProcessList::DeviceProcessList(const IDevice::ConstPtr &device, QObject *parent)
- : QAbstractItemModel(parent), d(std::make_unique<DeviceProcessListPrivate>(device))
-{ }
-
-DeviceProcessList::~DeviceProcessList() = default;
-
-QModelIndex DeviceProcessList::parent(const QModelIndex &) const
+ : QObject(parent), d(std::make_unique<DeviceProcessListPrivate>(device))
{
- return QModelIndex();
-}
-
-bool DeviceProcessList::hasChildren(const QModelIndex &parent) const
-{
- if (!parent.isValid())
- return rowCount(parent) > 0 && columnCount(parent) > 0;
- return false;
-}
-
-QModelIndex DeviceProcessList::index(int row, int column, const QModelIndex &parent) const
-{
- return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex();
+ d->model.setHeader({tr("Process ID"), tr("Command Line")});
}
+DeviceProcessList::~DeviceProcessList() = default;
void DeviceProcessList::update()
{
QTC_ASSERT(d->state == Inactive, return);
QTC_ASSERT(device(), return);
- if (!d->remoteProcesses.isEmpty()) {
- beginRemoveRows(QModelIndex(), 0, d->remoteProcesses.count() - 1);
- d->remoteProcesses.clear();
- endRemoveRows();
- }
+ d->model.clear();
d->state = Listing;
doUpdate();
}
@@ -92,22 +87,29 @@ void DeviceProcessList::reportProcessListUpdated(const QList<DeviceProcessItem>
{
QTC_ASSERT(d->state == Listing, return);
setFinished();
- if (!processes.isEmpty()) {
- beginInsertRows(QModelIndex(), 0, processes.count() - 1);
- d->remoteProcesses = processes;
- endInsertRows();
+ for (const DeviceProcessItem &process : processes) {
+ Qt::ItemFlags fl;
+ if (process.pid != d->ownPid)
+ fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ d->model.rootItem()->appendChild(new DeviceProcessTreeItem(process, fl));
}
+
emit processListUpdated();
}
void DeviceProcessList::killProcess(int row)
{
- QTC_ASSERT(row >= 0 && row < d->remoteProcesses.count(), return);
+ QTC_ASSERT(row >= 0 && row < d->model.rootItem()->childCount(), return);
QTC_ASSERT(d->state == Inactive, return);
QTC_ASSERT(device(), return);
d->state = Killing;
- doKillProcess(d->remoteProcesses.at(row));
+ doKillProcess(at(row));
+}
+
+void DeviceProcessList::setOwnPid(qint64 pid)
+{
+ d->ownPid = pid;
}
void DeviceProcessList::reportProcessKilled()
@@ -119,40 +121,21 @@ void DeviceProcessList::reportProcessKilled()
DeviceProcessItem DeviceProcessList::at(int row) const
{
- return d->remoteProcesses.at(row);
+ return d->model.rootItem()->childAt(row)->process;
}
-int DeviceProcessList::rowCount(const QModelIndex &parent) const
+QAbstractItemModel *DeviceProcessList::model() const
{
- return parent.isValid() ? 0 : d->remoteProcesses.count();
+ return &d->model;
}
-int DeviceProcessList::columnCount(const QModelIndex &) const
+QVariant DeviceProcessTreeItem::data(int column, int role) const
{
- return 2;
-}
-
-QVariant DeviceProcessList::headerData(int section, Qt::Orientation orientation,
- int role) const
-{
- if (orientation != Qt::Horizontal || role != Qt::DisplayRole || section < 0
- || section >= columnCount())
- return QVariant();
- return section == 0? tr("Process ID") : tr("Command Line");
-}
-
-QVariant DeviceProcessList::data(const QModelIndex &index, int role) const
-{
- if (!index.isValid() || index.row() >= rowCount(index.parent())
- || index.column() >= columnCount())
- return QVariant();
-
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
- const DeviceProcessItem &proc = d->remoteProcesses.at(index.row());
- if (index.column() == 0)
- return proc.pid;
+ if (column == 0)
+ return process.pid;
else
- return proc.cmdLine;
+ return process.cmdLine;
}
return QVariant();
}
diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h
index 18fa97337d..c7959dc3a5 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h
+++ b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h
@@ -46,7 +46,7 @@ public:
QString exe;
};
-class PROJECTEXPLORER_EXPORT DeviceProcessList : public QAbstractItemModel
+class PROJECTEXPLORER_EXPORT DeviceProcessList : public QObject
{
Q_OBJECT
@@ -56,7 +56,10 @@ public:
void update();
void killProcess(int row);
+ void setOwnPid(qint64 pid);
+
DeviceProcessItem at(int row) const;
+ QAbstractItemModel *model() const;
static QList<DeviceProcessItem> localProcesses();
@@ -73,15 +76,6 @@ protected:
IDevice::ConstPtr device() const;
private:
- QModelIndex index(int row, int column, const QModelIndex &parent) const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- QVariant headerData(int section, Qt::Orientation orientation,
- int role = Qt::DisplayRole) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- QModelIndex parent(const QModelIndex &) const override;
- bool hasChildren(const QModelIndex &parent) const override;
-
virtual void doUpdate() = 0;
virtual void doKillProcess(const DeviceProcessItem &process) = 0;
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
index 5cb6623f1c..af42589622 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
@@ -122,7 +122,7 @@ void DeviceSettingsWidget::initGui()
lastIndex = 0;
if (lastIndex < m_ui->configurationComboBox->count())
m_ui->configurationComboBox->setCurrentIndex(lastIndex);
- connect(m_ui->configurationComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->configurationComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &DeviceSettingsWidget::currentDeviceChanged);
currentDeviceChanged(currentIndex());
connect(m_ui->defaultDeviceButton, &QAbstractButton::clicked,
diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
index e739af3163..4344f059a5 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
+++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
@@ -27,7 +27,7 @@
#include "idevice.h"
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/portlist.h>
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp
index 54caab5f99..86d783a6d9 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp
@@ -27,6 +27,7 @@
#include "devicemanager.h"
#include "deviceprocesslist.h"
+#include "idevicefactory.h"
#include "../kit.h"
#include "../kitinformation.h"
@@ -152,6 +153,7 @@ public:
QList<Utils::Icon> deviceIcons;
QList<IDevice::DeviceAction> deviceActions;
QVariantMap extraData;
+ IDevice::OpenTerminal openTerminal;
};
} // namespace Internal
@@ -161,6 +163,11 @@ IDevice::IDevice() : d(new Internal::IDevicePrivate)
{
}
+void IDevice::setOpenTerminal(const IDevice::OpenTerminal &openTerminal)
+{
+ d->openTerminal = openTerminal;
+}
+
void IDevice::setupId(Origin origin, Core::Id id)
{
d->origin = origin;
@@ -168,11 +175,15 @@ void IDevice::setupId(Origin origin, Core::Id id)
d->id = id.isValid() ? id : newId();
}
-IDevice::IDevice(const IDevice &other)
- : QEnableSharedFromThis<IDevice>(other)
- , d(std::make_unique<Internal::IDevicePrivate>())
+bool IDevice::canOpenTerminal() const
{
- *d = *other.d;
+ return bool(d->openTerminal);
+}
+
+void IDevice::openTerminal(const Utils::Environment &env, const QString &workingDir) const
+{
+ QTC_ASSERT(canOpenTerminal(), return);
+ d->openTerminal(env, workingDir);
}
IDevice::~IDevice() = default;
@@ -249,7 +260,7 @@ Core::Id IDevice::id() const
*/
bool IDevice::isCompatibleWith(const Kit *k) const
{
- return DeviceTypeKitInformation::deviceTypeId(k) == type();
+ return DeviceTypeKitAspect::deviceTypeId(k) == type();
}
void IDevice::addDeviceAction(const DeviceAction &deviceAction)
@@ -395,6 +406,19 @@ QVariantMap IDevice::toMap() const
return map;
}
+IDevice::Ptr IDevice::clone() const
+{
+ IDeviceFactory *factory = IDeviceFactory::find(d->type);
+ QTC_ASSERT(factory, return {});
+ IDevice::Ptr device = factory->construct();
+ QTC_ASSERT(device, return {});
+ device->d->deviceState = d->deviceState;
+ device->d->deviceActions = d->deviceActions;
+ device->d->deviceIcons = d->deviceIcons;
+ device->fromMap(toMap());
+ return device;
+}
+
QString IDevice::deviceStateToString() const
{
const char context[] = "ProjectExplorer::IDevice";
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h
index 560325617c..b263544000 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.h
+++ b/src/plugins/projectexplorer/devicesupport/idevice.h
@@ -120,6 +120,7 @@ public:
// See cpp file for documentation.
class PROJECTEXPLORER_EXPORT IDevice : public QEnableSharedFromThis<IDevice>
{
+ friend class Internal::IDevicePrivate;
public:
using Ptr = QSharedPointer<IDevice>;
using ConstPtr = QSharedPointer<const IDevice>;
@@ -127,9 +128,10 @@ public:
enum Origin { ManuallyAdded, AutoDetected };
enum MachineType { Hardware, Emulator };
- IDevice &operator=(const IDevice &) = delete;
virtual ~IDevice();
+ Ptr clone() const;
+
QString displayName() const;
void setDisplayName(const QString &name);
@@ -187,7 +189,6 @@ public:
virtual void fromMap(const QVariantMap &map);
virtual QVariantMap toMap() const;
- virtual Ptr clone() const = 0;
static Core::Id typeFromMap(const QVariantMap &map);
static Core::Id idFromMap(const QVariantMap &map);
@@ -218,11 +219,19 @@ public:
void setupId(Origin origin, Core::Id id = Core::Id());
+ bool canOpenTerminal() const;
+ void openTerminal(const Utils::Environment &env, const QString &workingDir) const;
+
protected:
IDevice();
- IDevice(const IDevice &other);
+
+ using OpenTerminal = std::function<void(const Utils::Environment &, const QString &)>;
+ void setOpenTerminal(const OpenTerminal &openTerminal);
private:
+ IDevice(const IDevice &) = delete;
+ IDevice &operator=(const IDevice &) = delete;
+
int version() const;
const std::unique_ptr<Internal::IDevicePrivate> d;
diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
index b0d95c6474..832cbd5246 100644
--- a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
@@ -56,8 +56,8 @@ namespace Internal {
LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcessList(device, parent)
- , m_myPid(GetCurrentProcessId())
{
+ setOwnPid(GetCurrentProcessId());
}
QList<DeviceProcessItem> LocalProcessList::getLocalProcesses()
@@ -89,8 +89,9 @@ QList<DeviceProcessItem> LocalProcessList::getLocalProcesses()
#ifdef Q_OS_UNIX
LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcessList(device, parent)
- , m_myPid(getpid())
-{}
+{
+ setOwnPid(getpid());
+}
static bool isUnixProcessId(const QString &procname)
{
@@ -206,14 +207,6 @@ void LocalProcessList::doKillProcess(const DeviceProcessItem &process)
signalOperation->killProcess(process.pid);
}
-Qt::ItemFlags LocalProcessList::flags(const QModelIndex &index) const
-{
- Qt::ItemFlags flags = DeviceProcessList::flags(index);
- if (index.isValid() && at(index.row()).pid == m_myPid)
- flags &= ~(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
- return flags;
-}
-
void LocalProcessList::handleUpdate()
{
reportProcessListUpdated(getLocalProcesses());
diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.h b/src/plugins/projectexplorer/devicesupport/localprocesslist.h
index 599f20ed3e..8e10086849 100644
--- a/src/plugins/projectexplorer/devicesupport/localprocesslist.h
+++ b/src/plugins/projectexplorer/devicesupport/localprocesslist.h
@@ -36,7 +36,6 @@ class LocalProcessList : public DeviceProcessList
public:
explicit LocalProcessList(const IDevice::ConstPtr &device, QObject *parent = nullptr);
- Qt::ItemFlags flags(const QModelIndex &index) const override;
static QList<DeviceProcessItem> getLocalProcesses();
@@ -47,8 +46,6 @@ private:
private:
void handleUpdate();
void reportDelayedKillStatus(const QString &errorMessage);
-
- const qint64 m_myPid;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
index f094cb1473..7e8be72c65 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
@@ -26,7 +26,7 @@
#include "sshdeviceprocess.h"
#include "idevice.h"
-#include "../runconfiguration.h"
+#include "../runcontrol.h"
#include <ssh/sshconnection.h>
#include <ssh/sshconnectionmanager.h>
@@ -188,21 +188,21 @@ void SshDeviceProcess::handleConnected()
d->process = runInTerminal() && d->runnable.executable.isEmpty()
? d->connection->createRemoteShell()
- : d->connection->createRemoteProcess(fullCommandLine(d->runnable).toUtf8());
+ : d->connection->createRemoteProcess(fullCommandLine(d->runnable));
const QString display = d->displayName();
if (!display.isEmpty())
d->process->requestX11Forwarding(display);
if (runInTerminal()) {
d->process->requestTerminal();
const QStringList cmdLine = d->process->fullLocalCommandLine();
- connect(&d->consoleProcess,
- static_cast<void (ConsoleProcess::*)(QProcess::ProcessError)>(&ConsoleProcess::error),
+ connect(&d->consoleProcess, QOverload<QProcess::ProcessError>::of(&ConsoleProcess::error),
this, &DeviceProcess::error);
connect(&d->consoleProcess, &ConsoleProcess::processStarted,
this, &SshDeviceProcess::handleProcessStarted);
connect(&d->consoleProcess, &ConsoleProcess::stubStopped,
this, [this] { handleProcessFinished(d->consoleProcess.errorString()); });
- d->consoleProcess.start(cmdLine.first(), cmdLine.mid(1).join(' '));
+ d->consoleProcess.start(cmdLine.first(), cmdLine.mid(1).join(' '),
+ ConsoleProcess::MetaCharMode::Ignore);
} else {
connect(d->process.get(), &QSsh::SshRemoteProcess::started,
this, &SshDeviceProcess::handleProcessStarted);
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
index c1c7b0a45f..d8107458fd 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
@@ -54,7 +54,7 @@ void SshDeviceProcessList::doUpdate()
this, &SshDeviceProcessList::handleConnectionError);
connect(&d->process, &SshRemoteProcessRunner::processClosed,
this, &SshDeviceProcessList::handleListProcessFinished);
- d->process.run(listProcessesCommandLine().toUtf8(), device()->sshParameters());
+ d->process.run(listProcessesCommandLine(), device()->sshParameters());
}
void SshDeviceProcessList::doKillProcess(const DeviceProcessItem &process)
diff --git a/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp b/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
index 32b6b3e83e..152467c93e 100644
--- a/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshsettingspage.cpp
@@ -58,7 +58,7 @@ private:
void setupSftpPathChooser();
void setupAskpassPathChooser();
void setupKeygenPathChooser();
- void setupPathChooser(PathChooser &chooser, const FileName &initialPath, bool &changedFlag);
+ void setupPathChooser(PathChooser &chooser, const FilePath &initialPath, bool &changedFlag);
void updateCheckboxEnabled();
void updateSpinboxEnabled();
@@ -170,7 +170,7 @@ void SshSettingsWidget::setupKeygenPathChooser()
setupPathChooser(m_keygenChooser, SshSettings::keygenFilePath(), m_keygenPathChanged);
}
-void SshSettingsWidget::setupPathChooser(PathChooser &chooser, const FileName &initialPath,
+void SshSettingsWidget::setupPathChooser(PathChooser &chooser, const FilePath &initialPath,
bool &changedFlag)
{
chooser.setExpectedKind(PathChooser::ExistingCommand);
diff --git a/src/plugins/projectexplorer/editorconfiguration.cpp b/src/plugins/projectexplorer/editorconfiguration.cpp
index 43f7b79c69..40e08d368e 100644
--- a/src/plugins/projectexplorer/editorconfiguration.cpp
+++ b/src/plugins/projectexplorer/editorconfiguration.cpp
@@ -395,7 +395,7 @@ TabSettings actualTabSettings(const QString &fileName,
{
if (baseTextdocument)
return baseTextdocument->tabSettings();
- if (Project *project = SessionManager::projectForFile(Utils::FileName::fromString(fileName)))
+ if (Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(fileName)))
return project->editorConfiguration()->codeStyle()->tabSettings();
return TextEditorSettings::codeStyle()->tabSettings();
}
diff --git a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
index 83fc49dcea..ba76cb078e 100644
--- a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
@@ -43,14 +43,14 @@ EditorSettingsWidget::EditorSettingsWidget(Project *project) : QWidget(), m_proj
globalSettingsActivated(config->useGlobalSettings() ? 0 : 1);
- connect(m_ui.globalSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_ui.globalSelector, QOverload<int>::of(&QComboBox::activated),
this, &EditorSettingsWidget::globalSettingsActivated);
connect(m_ui.restoreButton, &QAbstractButton::clicked,
this, &EditorSettingsWidget::restoreDefaultValues);
connect(m_ui.showWrapColumn, &QAbstractButton::toggled,
config, &EditorConfiguration::setShowWrapColumn);
- connect(m_ui.wrapColumn, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_ui.wrapColumn, QOverload<int>::of(&QSpinBox::valueChanged),
config, &EditorConfiguration::setWrapColumn);
connect(m_ui.behaviorSettingsWidget, &TextEditor::BehaviorSettingsWidget::typingSettingsChanged,
diff --git a/src/plugins/projectexplorer/environmentaspect.cpp b/src/plugins/projectexplorer/environmentaspect.cpp
index d0b0845a3e..0b0eff1e37 100644
--- a/src/plugins/projectexplorer/environmentaspect.cpp
+++ b/src/plugins/projectexplorer/environmentaspect.cpp
@@ -30,6 +30,8 @@
#include <utils/qtcassert.h>
+using namespace Utils;
+
static const char BASE_KEY[] = "PE.EnvironmentAspect.Base";
static const char CHANGES_KEY[] = "PE.EnvironmentAspect.Changes";
@@ -53,9 +55,7 @@ int EnvironmentAspect::baseEnvironmentBase() const
void EnvironmentAspect::setBaseEnvironmentBase(int base)
{
- QTC_ASSERT(base >= 0, return);
- QTC_ASSERT(possibleBaseEnvironments().contains(base), return);
-
+ QTC_ASSERT(base >= 0 && base < m_baseEnvironments.size(), return);
if (m_base != base) {
m_base = base;
emit baseEnvironmentChanged();
@@ -64,53 +64,81 @@ void EnvironmentAspect::setBaseEnvironmentBase(int base)
void EnvironmentAspect::setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff)
{
- if (m_changes != diff) {
- m_changes = diff;
- emit userEnvironmentChangesChanged(m_changes);
+ if (m_userChanges != diff) {
+ m_userChanges = diff;
+ emit userEnvironmentChangesChanged(m_userChanges);
emit environmentChanged();
}
}
Utils::Environment EnvironmentAspect::environment() const
{
- Utils::Environment env = baseEnvironment();
- env.modify(m_changes);
+ QTC_ASSERT(m_base >= 0 && m_base < m_baseEnvironments.size(), return Environment());
+ Environment env = m_baseEnvironments.at(m_base).unmodifiedBaseEnvironment();
+ for (const EnvironmentModifier &modifier : m_modifiers)
+ modifier(env);
+ env.modify(m_userChanges);
return env;
}
-QList<int> EnvironmentAspect::possibleBaseEnvironments() const
+const QStringList EnvironmentAspect::displayNames() const
{
- return m_displayNames.keys();
+ return Utils::transform(m_baseEnvironments, &BaseEnvironment::displayName);
}
-QString EnvironmentAspect::baseEnvironmentDisplayName(int base) const
+void EnvironmentAspect::addModifier(const EnvironmentAspect::EnvironmentModifier &modifier)
{
- return m_displayNames[base];
+ m_modifiers.append(modifier);
}
-void EnvironmentAspect::addSupportedBaseEnvironment(int base, const QString &displayName)
+void EnvironmentAspect::addSupportedBaseEnvironment(const QString &displayName,
+ const std::function<Environment()> &getter)
{
- m_displayNames[base] = displayName;
+ BaseEnvironment baseEnv;
+ baseEnv.displayName = displayName;
+ baseEnv.getter = getter;
+ m_baseEnvironments.append(baseEnv);
if (m_base == -1)
- setBaseEnvironmentBase(base);
+ setBaseEnvironmentBase(m_baseEnvironments.size() - 1);
}
-void EnvironmentAspect::addPreferredBaseEnvironment(int base, const QString &displayName)
+void EnvironmentAspect::addPreferredBaseEnvironment(const QString &displayName,
+ const std::function<Environment()> &getter)
{
- m_displayNames[base] = displayName;
- setBaseEnvironmentBase(base);
+ BaseEnvironment baseEnv;
+ baseEnv.displayName = displayName;
+ baseEnv.getter = getter;
+ m_baseEnvironments.append(baseEnv);
+ setBaseEnvironmentBase(m_baseEnvironments.size() - 1);
}
void EnvironmentAspect::fromMap(const QVariantMap &map)
{
m_base = map.value(QLatin1String(BASE_KEY), -1).toInt();
- m_changes = Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(CHANGES_KEY)).toStringList());
+ m_userChanges = Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(CHANGES_KEY)).toStringList());
}
void EnvironmentAspect::toMap(QVariantMap &data) const
{
data.insert(QLatin1String(BASE_KEY), m_base);
- data.insert(QLatin1String(CHANGES_KEY), Utils::EnvironmentItem::toStringList(m_changes));
+ data.insert(QLatin1String(CHANGES_KEY), Utils::EnvironmentItem::toStringList(m_userChanges));
+}
+
+Environment EnvironmentAspect::currentUnmodifiedBaseEnvironment() const
+{
+ QTC_ASSERT(m_base >= 0 && m_base < m_baseEnvironments.size(), return Environment());
+ return m_baseEnvironments.at(m_base).unmodifiedBaseEnvironment();
+}
+
+QString EnvironmentAspect::currentDisplayName() const
+{
+ QTC_ASSERT(m_base >= 0 && m_base < m_baseEnvironments.size(), return {});
+ return m_baseEnvironments[m_base].displayName;
+}
+
+Environment EnvironmentAspect::BaseEnvironment::unmodifiedBaseEnvironment() const
+{
+ return getter ? getter() : Environment();
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/environmentaspect.h b/src/plugins/projectexplorer/environmentaspect.h
index 7d0ecbe406..6657d1dfe8 100644
--- a/src/plugins/projectexplorer/environmentaspect.h
+++ b/src/plugins/projectexplorer/environmentaspect.h
@@ -41,22 +41,32 @@ class PROJECTEXPLORER_EXPORT EnvironmentAspect : public ProjectConfigurationAspe
Q_OBJECT
public:
- // The environment the user chose as base for his modifications.
- virtual Utils::Environment baseEnvironment() const = 0;
+ EnvironmentAspect();
+
// The environment including the user's modifications.
Utils::Environment environment() const;
- QList<int> possibleBaseEnvironments() const;
- QString baseEnvironmentDisplayName(int base) const;
-
int baseEnvironmentBase() const;
void setBaseEnvironmentBase(int base);
- QList<Utils::EnvironmentItem> userEnvironmentChanges() const { return m_changes; }
+ QList<Utils::EnvironmentItem> userEnvironmentChanges() const { return m_userChanges; }
void setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff);
- void addSupportedBaseEnvironment(int base, const QString &displayName);
- void addPreferredBaseEnvironment(int base, const QString &displayName);
+ void addSupportedBaseEnvironment(const QString &displayName,
+ const std::function<Utils::Environment()> &getter);
+ void addPreferredBaseEnvironment(const QString &displayName,
+ const std::function<Utils::Environment()> &getter);
+
+ // The environment the user chose as base for his modifications.
+ Utils::Environment currentUnmodifiedBaseEnvironment() const;
+ QString currentDisplayName() const;
+
+ const QStringList displayNames() const;
+
+ using EnvironmentModifier = std::function<void(Utils::Environment &)>;
+ void addModifier(const EnvironmentModifier &);
+
+ bool isLocal() const { return m_isLocal; }
signals:
void baseEnvironmentChanged();
@@ -64,14 +74,25 @@ signals:
void environmentChanged();
protected:
- EnvironmentAspect();
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
+ void setIsLocal(bool local) { m_isLocal = local; }
+
private:
+ // One possible choice in the Environment aspect.
+ struct BaseEnvironment {
+ Utils::Environment unmodifiedBaseEnvironment() const;
+
+ std::function<Utils::Environment()> getter;
+ QString displayName;
+ };
+
+ QList<Utils::EnvironmentItem> m_userChanges;
+ QList<EnvironmentModifier> m_modifiers;
+ QList<BaseEnvironment> m_baseEnvironments;
int m_base = -1;
- QList<Utils::EnvironmentItem> m_changes;
- QMap<int, QString> m_displayNames;
+ bool m_isLocal = false;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/environmentaspectwidget.cpp b/src/plugins/projectexplorer/environmentaspectwidget.cpp
index 7b5c9e5e5f..0898a3f1b6 100644
--- a/src/plugins/projectexplorer/environmentaspectwidget.cpp
+++ b/src/plugins/projectexplorer/environmentaspectwidget.cpp
@@ -56,22 +56,15 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect, QWid
baseLayout->setMargin(0);
auto label = new QLabel(tr("Base environment for this run configuration:"), this);
baseLayout->addWidget(label);
+
m_baseEnvironmentComboBox = new QComboBox;
- QList<int> bases = m_aspect->possibleBaseEnvironments();
- int currentBase = m_aspect->baseEnvironmentBase();
- QString baseDisplayName;
- foreach (int i, bases) {
- const QString displayName = m_aspect->baseEnvironmentDisplayName(i);
- m_baseEnvironmentComboBox->addItem(displayName, i);
- if (i == currentBase) {
- m_baseEnvironmentComboBox->setCurrentIndex(m_baseEnvironmentComboBox->count() - 1);
- baseDisplayName = displayName;
- }
- }
+ for (const QString &displayName : m_aspect->displayNames())
+ m_baseEnvironmentComboBox->addItem(displayName);
if (m_baseEnvironmentComboBox->count() == 1)
m_baseEnvironmentComboBox->setEnabled(false);
+ m_baseEnvironmentComboBox->setCurrentIndex(m_aspect->baseEnvironmentBase());
- connect(m_baseEnvironmentComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_baseEnvironmentComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &EnvironmentAspectWidget::baseEnvironmentSelected);
baseLayout->addWidget(m_baseEnvironmentComboBox);
@@ -79,9 +72,11 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect, QWid
if (additionalWidget)
baseLayout->addWidget(additionalWidget);
- m_environmentWidget = new EnvironmentWidget(this, baseEnvironmentWidget);
- m_environmentWidget->setBaseEnvironment(m_aspect->baseEnvironment());
- m_environmentWidget->setBaseEnvironmentText(baseDisplayName);
+ const EnvironmentWidget::Type widgetType = aspect->isLocal()
+ ? EnvironmentWidget::TypeLocal : EnvironmentWidget::TypeRemote;
+ m_environmentWidget = new EnvironmentWidget(this, widgetType, baseEnvironmentWidget);
+ m_environmentWidget->setBaseEnvironment(m_aspect->currentUnmodifiedBaseEnvironment());
+ m_environmentWidget->setBaseEnvironmentText(m_aspect->currentDisplayName());
m_environmentWidget->setUserChanges(m_aspect->userEnvironmentChanges());
m_environmentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
topLayout->addWidget(m_environmentWidget);
@@ -110,10 +105,9 @@ QWidget *EnvironmentAspectWidget::additionalWidget() const
void EnvironmentAspectWidget::baseEnvironmentSelected(int idx)
{
m_ignoreChange = true;
- int base = m_baseEnvironmentComboBox->itemData(idx).toInt();
- m_aspect->setBaseEnvironmentBase(base);
- m_environmentWidget->setBaseEnvironment(m_aspect->baseEnvironment());
- m_environmentWidget->setBaseEnvironmentText(m_aspect->baseEnvironmentDisplayName(base));
+ m_aspect->setBaseEnvironmentBase(idx);
+ m_environmentWidget->setBaseEnvironment(m_aspect->currentUnmodifiedBaseEnvironment());
+ m_environmentWidget->setBaseEnvironmentText(m_aspect->currentDisplayName());
m_ignoreChange = false;
}
@@ -127,8 +121,8 @@ void EnvironmentAspectWidget::changeBaseEnvironment()
if (m_baseEnvironmentComboBox->itemData(i).toInt() == base)
m_baseEnvironmentComboBox->setCurrentIndex(i);
}
- m_environmentWidget->setBaseEnvironmentText(m_aspect->baseEnvironmentDisplayName(base));
- m_environmentWidget->setBaseEnvironment(m_aspect->baseEnvironment());
+ m_environmentWidget->setBaseEnvironmentText(m_aspect->currentDisplayName());
+ m_environmentWidget->setBaseEnvironment(m_aspect->currentUnmodifiedBaseEnvironment());
}
void EnvironmentAspectWidget::userChangesEdited()
@@ -149,7 +143,7 @@ void EnvironmentAspectWidget::environmentChanged()
{
if (m_ignoreChange)
return;
- m_environmentWidget->setBaseEnvironment(m_aspect->baseEnvironment());
+ m_environmentWidget->setBaseEnvironment(m_aspect->currentUnmodifiedBaseEnvironment());
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/environmentaspectwidget.h b/src/plugins/projectexplorer/environmentaspectwidget.h
index b5127d889e..6ca8164f05 100644
--- a/src/plugins/projectexplorer/environmentaspectwidget.h
+++ b/src/plugins/projectexplorer/environmentaspectwidget.h
@@ -53,6 +53,7 @@ public:
explicit EnvironmentAspectWidget(EnvironmentAspect *aspect, QWidget *additionalWidget = nullptr);
virtual EnvironmentAspect *aspect() const;
+ EnvironmentWidget *envWidget() const { return m_environmentWidget; }
QWidget *additionalWidget() const;
diff --git a/src/plugins/projectexplorer/environmentwidget.cpp b/src/plugins/projectexplorer/environmentwidget.cpp
index ad643e78be..1a6e424960 100644
--- a/src/plugins/projectexplorer/environmentwidget.cpp
+++ b/src/plugins/projectexplorer/environmentwidget.cpp
@@ -33,10 +33,13 @@
#include <utils/environmentmodel.h>
#include <utils/environmentdialog.h>
#include <utils/headerviewstretcher.h>
+#include <utils/hostosinfo.h>
#include <utils/itemviews.h>
#include <utils/tooltip/tooltip.h>
#include <QDir>
+#include <QFileDialog>
+#include <QFileInfo>
#include <QString>
#include <QPushButton>
#include <QTreeView>
@@ -124,6 +127,7 @@ public:
Utils::EnvironmentModel *m_model;
QString m_baseEnvironmentText;
+ EnvironmentWidget::OpenTerminalFunc m_openTerminalFunc;
Utils::DetailsWidget *m_detailsContainer;
QTreeView *m_environmentView;
QPushButton *m_editButton;
@@ -131,10 +135,12 @@ public:
QPushButton *m_resetButton;
QPushButton *m_unsetButton;
QPushButton *m_batchEditButton;
+ QPushButton *m_appendPathButton = nullptr;
+ QPushButton *m_prependPathButton = nullptr;
QPushButton *m_terminalButton;
};
-EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetailsWidget)
+EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additionalDetailsWidget)
: QWidget(parent), d(std::make_unique<EnvironmentWidgetPrivate>())
{
d->m_model = new Utils::EnvironmentModel();
@@ -200,6 +206,21 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetails
d->m_unsetButton->setText(tr("&Unset"));
buttonLayout->addWidget(d->m_unsetButton);
+ if (type == TypeLocal) {
+ d->m_appendPathButton = new QPushButton(this);
+ d->m_appendPathButton->setEnabled(false);
+ d->m_appendPathButton->setText(tr("Append Path..."));
+ buttonLayout->addWidget(d->m_appendPathButton);
+ d->m_prependPathButton = new QPushButton(this);
+ d->m_prependPathButton->setEnabled(false);
+ d->m_prependPathButton->setText(tr("Prepend Path..."));
+ buttonLayout->addWidget(d->m_prependPathButton);
+ connect(d->m_appendPathButton, &QAbstractButton::clicked,
+ this, &EnvironmentWidget::appendPathButtonClicked);
+ connect(d->m_prependPathButton, &QAbstractButton::clicked,
+ this, &EnvironmentWidget::prependPathButtonClicked);
+ }
+
d->m_batchEditButton = new QPushButton(this);
d->m_batchEditButton->setText(tr("&Batch Edit..."));
buttonLayout->addWidget(d->m_batchEditButton);
@@ -207,10 +228,8 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetails
d->m_terminalButton = new QPushButton(this);
d->m_terminalButton->setText(tr("Open &Terminal"));
d->m_terminalButton->setToolTip(tr("Open a terminal with this environment set up."));
+ d->m_terminalButton->setEnabled(type == TypeLocal);
buttonLayout->addWidget(d->m_terminalButton);
-#if defined(Q_OS_UNIX) && QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- d->m_terminalButton->setVisible(false);
-#endif
buttonLayout->addStretch();
horizontalLayout->addLayout(buttonLayout);
@@ -234,7 +253,14 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetails
connect(d->m_environmentView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &EnvironmentWidget::environmentCurrentIndexChanged);
connect(d->m_terminalButton, &QAbstractButton::clicked,
- this, &EnvironmentWidget::openTerminal);
+ this, [this] {
+ Utils::Environment env = d->m_model->baseEnvironment();
+ env.modify(d->m_model->userChanges());
+ if (d->m_openTerminalFunc)
+ d->m_openTerminalFunc(env);
+ else
+ Core::FileUtils::openTerminal(QDir::currentPath(), env);
+ });
connect(d->m_detailsContainer, &Utils::DetailsWidget::linkActivated,
this, &EnvironmentWidget::linkActivated);
@@ -286,6 +312,12 @@ void EnvironmentWidget::setUserChanges(const QList<Utils::EnvironmentItem> &list
updateSummaryText();
}
+void EnvironmentWidget::setOpenTerminalFunc(const EnvironmentWidget::OpenTerminalFunc &func)
+{
+ d->m_openTerminalFunc = func;
+ d->m_terminalButton->setEnabled(bool(func));
+}
+
void EnvironmentWidget::updateSummaryText()
{
QList<Utils::EnvironmentItem> list = d->m_model->userChanges();
@@ -321,6 +353,36 @@ void EnvironmentWidget::linkActivated(const QString &link)
focusIndex(idx);
}
+bool EnvironmentWidget::currentEntryIsPathList(const QModelIndex &current) const
+{
+ if (!current.isValid())
+ return false;
+
+ // Look at the name first and check it against some well-known path variables. Extend as needed.
+ const QString varName = d->m_model->indexToVariable(current);
+ if (varName.compare("PATH", Utils::HostOsInfo::fileNameCaseSensitivity()) == 0)
+ return true;
+ if (Utils::HostOsInfo::isMacHost() && varName == "DYLD_LIBRARY_PATH")
+ return true;
+ if (Utils::HostOsInfo::isAnyUnixHost() && varName == "LD_LIBRARY_PATH")
+ return true;
+
+ // Now check the value: If it's a list of strings separated by the platform's path separator
+ // and at least one of the strings is an existing directory, then that's enough proof for us.
+ QModelIndex valueIndex = current;
+ if (valueIndex.column() == 0)
+ valueIndex = valueIndex.siblingAtColumn(1);
+ const QStringList entries = d->m_model->data(valueIndex).toString()
+ .split(Utils::HostOsInfo::pathListSeparator(), QString::SkipEmptyParts);
+ if (entries.length() < 2)
+ return false;
+ for (const QString &potentialDir : entries) {
+ if (QFileInfo(potentialDir).isDir())
+ return true;
+ }
+ return false;
+}
+
void EnvironmentWidget::updateButtons()
{
environmentCurrentIndexChanged(d->m_environmentView->currentIndex());
@@ -355,6 +417,42 @@ void EnvironmentWidget::unsetEnvironmentButtonClicked()
d->m_model->unsetVariable(name);
}
+void EnvironmentWidget::amendPathList(const PathListModifier &modifier)
+{
+ const QString varName = d->m_model->indexToVariable(d->m_environmentView->currentIndex());
+ const QString dir = QDir::toNativeSeparators(
+ QFileDialog::getExistingDirectory(this, tr("Choose Directory")));
+ if (dir.isEmpty())
+ return;
+ QModelIndex index = d->m_model->variableToIndex(varName);
+ if (!index.isValid())
+ return;
+ if (index.column() == 0)
+ index = index.siblingAtColumn(1);
+ const QString value = d->m_model->data(index).toString();
+ d->m_model->setData(index, modifier(value, dir));
+}
+
+void EnvironmentWidget::appendPathButtonClicked()
+{
+ amendPathList([](const QString &pathList, const QString &dir) {
+ QString newPathList = dir;
+ if (!pathList.isEmpty())
+ newPathList.prepend(Utils::HostOsInfo::pathListSeparator()).prepend(pathList);
+ return newPathList;
+ });
+}
+
+void EnvironmentWidget::prependPathButtonClicked()
+{
+ amendPathList([](const QString &pathList, const QString &dir) {
+ QString newPathList = dir;
+ if (!pathList.isEmpty())
+ newPathList.append(Utils::HostOsInfo::pathListSeparator()).append(pathList);
+ return newPathList;
+ });
+}
+
void EnvironmentWidget::batchEditEnvironmentButtonClicked()
{
const QList<Utils::EnvironmentItem> changes = d->m_model->userChanges();
@@ -367,13 +465,6 @@ void EnvironmentWidget::batchEditEnvironmentButtonClicked()
d->m_model->setUserChanges(newChanges);
}
-void EnvironmentWidget::openTerminal()
-{
- Utils::Environment env = d->m_model->baseEnvironment();
- env.modify(d->m_model->userChanges());
- Core::FileUtils::openTerminal(QDir::currentPath(), env);
-}
-
void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &current)
{
if (current.isValid()) {
@@ -388,6 +479,10 @@ void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &curren
d->m_resetButton->setEnabled(false);
d->m_unsetButton->setEnabled(false);
}
+ if (d->m_appendPathButton) {
+ d->m_appendPathButton->setEnabled(currentEntryIsPathList(current));
+ d->m_prependPathButton->setEnabled(currentEntryIsPathList(current));
+ }
}
void EnvironmentWidget::invalidateCurrentIndex()
diff --git a/src/plugins/projectexplorer/environmentwidget.h b/src/plugins/projectexplorer/environmentwidget.h
index 3eb85bcc8d..927dc9b0c1 100644
--- a/src/plugins/projectexplorer/environmentwidget.h
+++ b/src/plugins/projectexplorer/environmentwidget.h
@@ -29,6 +29,7 @@
#include <QWidget>
+#include <functional>
#include <memory>
QT_FORWARD_DECLARE_CLASS(QModelIndex)
@@ -47,7 +48,9 @@ class PROJECTEXPLORER_EXPORT EnvironmentWidget : public QWidget
Q_OBJECT
public:
- explicit EnvironmentWidget(QWidget *parent, QWidget *additionalDetailsWidget = nullptr);
+ enum Type { TypeLocal, TypeRemote };
+ explicit EnvironmentWidget(QWidget *parent, Type type,
+ QWidget *additionalDetailsWidget = nullptr);
~EnvironmentWidget() override;
void setBaseEnvironmentText(const QString &text);
@@ -56,6 +59,9 @@ public:
QList<Utils::EnvironmentItem> userChanges() const;
void setUserChanges(const QList<Utils::EnvironmentItem> &list);
+ using OpenTerminalFunc = std::function<void(const Utils::Environment &env)>;
+ void setOpenTerminalFunc(const OpenTerminalFunc &func);
+
signals:
void userChangesChanged();
void detailsVisibleChanged(bool visible);
@@ -65,14 +71,19 @@ private:
void addEnvironmentButtonClicked();
void removeEnvironmentButtonClicked();
void unsetEnvironmentButtonClicked();
+ void appendPathButtonClicked();
+ void prependPathButtonClicked();
void batchEditEnvironmentButtonClicked();
- void openTerminal();
void environmentCurrentIndexChanged(const QModelIndex &current);
void invalidateCurrentIndex();
void updateSummaryText();
void focusIndex(const QModelIndex &index);
void updateButtons();
void linkActivated(const QString &link);
+ bool currentEntryIsPathList(const QModelIndex &current) const;
+
+ using PathListModifier = std::function<QString(const QString &oldList, const QString &newDir)>;
+ void amendPathList(const PathListModifier &modifier);
const std::unique_ptr<EnvironmentWidgetPrivate> d;
};
diff --git a/src/plugins/projectexplorer/extraabi.cpp b/src/plugins/projectexplorer/extraabi.cpp
index a1da2193fd..434994125c 100644
--- a/src/plugins/projectexplorer/extraabi.cpp
+++ b/src/plugins/projectexplorer/extraabi.cpp
@@ -65,7 +65,7 @@ AbiFlavorAccessor::AbiFlavorAccessor() :
QCoreApplication::translate("ProjectExplorer::ToolChainManager", "ABI"),
Core::Constants::IDE_DISPLAY_NAME)
{
- setBaseFilePath(FileName::fromString(Core::ICore::installerResourcePath() + "/abi.xml"));
+ setBaseFilePath(FilePath::fromString(Core::ICore::installerResourcePath() + "/abi.xml"));
addVersionUpgrader(std::make_unique<AbiFlavorUpgraderV0>());
}
diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp
index df7297c33d..adcc8f180e 100644
--- a/src/plugins/projectexplorer/extracompiler.cpp
+++ b/src/plugins/projectexplorer/extracompiler.cpp
@@ -57,9 +57,9 @@ class ExtraCompilerPrivate
{
public:
const Project *project;
- Utils::FileName source;
+ Utils::FilePath source;
FileNameToContentsHash contents;
- QList<Task> issues;
+ Tasks issues;
QDateTime compileTime;
Core::IEditor *lastEditor = nullptr;
QMetaObject::Connection activeBuildConfigConnection;
@@ -70,13 +70,13 @@ public:
void updateIssues();
};
-ExtraCompiler::ExtraCompiler(const Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent) :
+ExtraCompiler::ExtraCompiler(const Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent) :
QObject(parent), d(std::make_unique<ExtraCompilerPrivate>())
{
d->project = project;
d->source = source;
- foreach (const Utils::FileName &target, targets)
+ foreach (const Utils::FilePath &target, targets)
d->contents.insert(target, QByteArray());
d->timer.setSingleShot(true);
@@ -104,7 +104,7 @@ ExtraCompiler::ExtraCompiler(const Project *project, const Utils::FileName &sour
// Use existing target files, where possible. Otherwise run the compiler.
QDateTime sourceTime = d->source.toFileInfo().lastModified();
- foreach (const Utils::FileName &target, targets) {
+ foreach (const Utils::FilePath &target, targets) {
QFileInfo targetFileInfo(target.toFileInfo());
if (!targetFileInfo.exists()) {
d->dirty = true;
@@ -136,22 +136,22 @@ const Project *ExtraCompiler::project() const
return d->project;
}
-Utils::FileName ExtraCompiler::source() const
+Utils::FilePath ExtraCompiler::source() const
{
return d->source;
}
-QByteArray ExtraCompiler::content(const Utils::FileName &file) const
+QByteArray ExtraCompiler::content(const Utils::FilePath &file) const
{
return d->contents.value(file);
}
-Utils::FileNameList ExtraCompiler::targets() const
+Utils::FilePathList ExtraCompiler::targets() const
{
return d->contents.keys();
}
-void ExtraCompiler::forEachTarget(std::function<void (const Utils::FileName &)> func)
+void ExtraCompiler::forEachTarget(std::function<void (const Utils::FilePath &)> func)
{
for (auto it = d->contents.constBegin(), end = d->contents.constEnd(); it != end; ++it)
func(it.key());
@@ -183,7 +183,7 @@ void ExtraCompiler::onTargetsBuilt(Project *project)
if (d->compileTime.isValid() && d->compileTime >= sourceTime)
return;
- forEachTarget([&](const Utils::FileName &target) {
+ forEachTarget([&](const Utils::FilePath &target) {
QFileInfo fi(target.toFileInfo());
QDateTime generateTime = fi.exists() ? fi.lastModified() : QDateTime();
if (generateTime.isValid() && (generateTime > sourceTime)) {
@@ -255,7 +255,7 @@ Utils::Environment ExtraCompiler::buildEnvironment() const
return bc->environment();
} else {
QList<Utils::EnvironmentItem> changes =
- EnvironmentKitInformation::environmentChanges(target->kit());
+ EnvironmentKitAspect::environmentChanges(target->kit());
Utils::Environment env = Utils::Environment::systemEnvironment();
env.modify(changes);
return env;
@@ -265,7 +265,7 @@ Utils::Environment ExtraCompiler::buildEnvironment() const
return Utils::Environment::systemEnvironment();
}
-void ExtraCompiler::setCompileIssues(const QList<Task> &issues)
+void ExtraCompiler::setCompileIssues(const Tasks &issues)
{
d->issues = issues;
d->updateIssues();
@@ -299,7 +299,7 @@ void ExtraCompilerPrivate::updateIssues()
widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection, selections);
}
-void ExtraCompiler::setContent(const Utils::FileName &file, const QByteArray &contents)
+void ExtraCompiler::setContent(const Utils::FilePath &file, const QByteArray &contents)
{
auto it = d->contents.find(file);
if (it != d->contents.end()) {
@@ -322,8 +322,8 @@ ExtraCompilerFactory::~ExtraCompilerFactory()
}
void ExtraCompilerFactory::annouceCreation(const Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets)
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets)
{
for (ExtraCompilerFactoryObserver *observer : *observers)
observer->newExtraCompiler(project, source, targets);
@@ -334,8 +334,8 @@ QList<ExtraCompilerFactory *> ExtraCompilerFactory::extraCompilerFactories()
return *factories();
}
-ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent) :
+ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent) :
ExtraCompiler(project, source, targets, parent)
{ }
@@ -353,7 +353,7 @@ void ProcessExtraCompiler::run(const QByteArray &sourceContents)
runImpl(contents);
}
-void ProcessExtraCompiler::run(const Utils::FileName &fileName)
+void ProcessExtraCompiler::run(const Utils::FilePath &fileName)
{
ContentProvider contents = [fileName]() {
QFile file(fileName.toString());
@@ -364,9 +364,9 @@ void ProcessExtraCompiler::run(const Utils::FileName &fileName)
runImpl(contents);
}
-Utils::FileName ProcessExtraCompiler::workingDirectory() const
+Utils::FilePath ProcessExtraCompiler::workingDirectory() const
{
- return Utils::FileName();
+ return Utils::FilePath();
}
QStringList ProcessExtraCompiler::arguments() const
@@ -380,10 +380,10 @@ bool ProcessExtraCompiler::prepareToRun(const QByteArray &sourceContents)
return true;
}
-QList<Task> ProcessExtraCompiler::parseIssues(const QByteArray &stdErr)
+Tasks ProcessExtraCompiler::parseIssues(const QByteArray &stdErr)
{
Q_UNUSED(stdErr);
- return QList<Task>();
+ return {};
}
void ProcessExtraCompiler::runImpl(const ContentProvider &provider)
@@ -403,7 +403,7 @@ void ProcessExtraCompiler::runImpl(const ContentProvider &provider)
void ProcessExtraCompiler::runInThread(
QFutureInterface<FileNameToContentsHash> &futureInterface,
- const Utils::FileName &cmd, const Utils::FileName &workDir,
+ const Utils::FilePath &cmd, const Utils::FilePath &workDir,
const QStringList &args, const ContentProvider &provider,
const Utils::Environment &env)
{
diff --git a/src/plugins/projectexplorer/extracompiler.h b/src/plugins/projectexplorer/extracompiler.h
index 006555ffc6..ba9c6774f7 100644
--- a/src/plugins/projectexplorer/extracompiler.h
+++ b/src/plugins/projectexplorer/extracompiler.h
@@ -47,27 +47,27 @@ QT_FORWARD_DECLARE_CLASS(QThreadPool);
namespace ProjectExplorer {
class ExtraCompilerPrivate;
-using FileNameToContentsHash = QHash<Utils::FileName, QByteArray>;
+using FileNameToContentsHash = QHash<Utils::FilePath, QByteArray>;
class PROJECTEXPLORER_EXPORT ExtraCompiler : public QObject
{
Q_OBJECT
public:
- ExtraCompiler(const Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent = nullptr);
+ ExtraCompiler(const Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent = nullptr);
~ExtraCompiler() override;
const Project *project() const;
- Utils::FileName source() const;
+ Utils::FilePath source() const;
// You can set the contents from the outside. This is done if the file has been (re)created by
// the regular build process.
- void setContent(const Utils::FileName &file, const QByteArray &content);
- QByteArray content(const Utils::FileName &file) const;
+ void setContent(const Utils::FilePath &file, const QByteArray &content);
+ QByteArray content(const Utils::FilePath &file) const;
- Utils::FileNameList targets() const;
- void forEachTarget(std::function<void(const Utils::FileName &)> func);
+ Utils::FilePathList targets() const;
+ void forEachTarget(std::function<void(const Utils::FilePath &)> func);
void setCompileTime(const QDateTime &time);
QDateTime compileTime() const;
@@ -75,11 +75,11 @@ public:
static QThreadPool *extraCompilerThreadPool();
signals:
- void contentsChanged(const Utils::FileName &file);
+ void contentsChanged(const Utils::FilePath &file);
protected:
Utils::Environment buildEnvironment() const;
- void setCompileIssues(const QList<Task> &issues);
+ void setCompileIssues(const Tasks &issues);
private:
void onTargetsBuilt(Project *project);
@@ -88,7 +88,7 @@ private:
void setDirty();
// This method may not block!
virtual void run(const QByteArray &sourceContent) = 0;
- virtual void run(const Utils::FileName &file) = 0;
+ virtual void run(const Utils::FilePath &file) = 0;
const std::unique_ptr<ExtraCompilerPrivate> d;
};
@@ -98,8 +98,8 @@ class PROJECTEXPLORER_EXPORT ProcessExtraCompiler : public ExtraCompiler
Q_OBJECT
public:
- ProcessExtraCompiler(const Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent = nullptr);
+ ProcessExtraCompiler(const Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent = nullptr);
~ProcessExtraCompiler() override;
protected:
@@ -109,11 +109,11 @@ protected:
// * prepareToRun returns true
// * The process is not yet running
void run(const QByteArray &sourceContents) override;
- void run(const Utils::FileName &fileName) override;
+ void run(const Utils::FilePath &fileName) override;
// Information about the process to run:
- virtual Utils::FileName workingDirectory() const;
- virtual Utils::FileName command() const = 0;
+ virtual Utils::FilePath workingDirectory() const;
+ virtual Utils::FilePath command() const = 0;
virtual QStringList arguments() const;
virtual bool prepareToRun(const QByteArray &sourceContents);
@@ -123,13 +123,13 @@ protected:
{ Q_UNUSED(process); Q_UNUSED(sourceContents); }
virtual FileNameToContentsHash handleProcessFinished(QProcess *process) = 0;
- virtual QList<Task> parseIssues(const QByteArray &stdErr);
+ virtual Tasks parseIssues(const QByteArray &stdErr);
private:
using ContentProvider = std::function<QByteArray()>;
void runImpl(const ContentProvider &sourceContents);
void runInThread(QFutureInterface<FileNameToContentsHash> &futureInterface,
- const Utils::FileName &cmd, const Utils::FileName &workDir,
+ const Utils::FilePath &cmd, const Utils::FilePath &workDir,
const QStringList &args, const ContentProvider &provider,
const Utils::Environment &env);
void cleanUp();
@@ -146,8 +146,8 @@ protected:
~ExtraCompilerFactoryObserver();
virtual void newExtraCompiler(const Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets)
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets)
= 0;
};
@@ -162,13 +162,13 @@ public:
virtual QString sourceTag() const = 0;
virtual ExtraCompiler *create(const Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets)
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets)
= 0;
void annouceCreation(const Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets);
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets);
static QList<ExtraCompilerFactory *> extraCompilerFactories();
};
diff --git a/src/plugins/projectexplorer/fileinsessionfinder.cpp b/src/plugins/projectexplorer/fileinsessionfinder.cpp
new file mode 100644
index 0000000000..e4c62e405f
--- /dev/null
+++ b/src/plugins/projectexplorer/fileinsessionfinder.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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 "fileinsessionfinder.h"
+
+#include "project.h"
+#include "session.h"
+
+#include <utils/fileinprojectfinder.h>
+
+#include <QUrl>
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class FileInSessionFinder : public QObject
+{
+public:
+ FileInSessionFinder();
+
+ FilePathList doFindFile(const FilePath &filePath);
+ void invalidateFinder() { m_finderIsUpToDate = false; }
+
+private:
+ FileInProjectFinder m_finder;
+ bool m_finderIsUpToDate = false;
+};
+
+FileInSessionFinder::FileInSessionFinder()
+{
+ connect(SessionManager::instance(), &SessionManager::projectAdded,
+ this, [this](const Project *p) {
+ invalidateFinder();
+ connect(p, &Project::fileListChanged, this, &FileInSessionFinder::invalidateFinder);
+ });
+ connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ this, [this](const Project *p) {
+ invalidateFinder();
+ p->disconnect(this);
+ });
+}
+
+FilePathList FileInSessionFinder::doFindFile(const FilePath &filePath)
+{
+ if (!m_finderIsUpToDate) {
+ m_finder.setProjectDirectory(SessionManager::startupProject()
+ ? SessionManager::startupProject()->projectDirectory()
+ : FilePath());
+ FilePathList allFiles;
+ for (const Project * const p : SessionManager::projects())
+ allFiles << p->files(Project::AllFiles);
+ m_finder.setProjectFiles(allFiles);
+ m_finderIsUpToDate = true;
+ }
+ return m_finder.findFile(QUrl::fromLocalFile(filePath.toString()));
+}
+
+FilePathList findFileInSession(const FilePath &filePath)
+{
+ static FileInSessionFinder finder;
+ return finder.doFindFile(filePath);
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/fileinsessionfinder.h b/src/plugins/projectexplorer/fileinsessionfinder.h
new file mode 100644
index 0000000000..f14b3708f3
--- /dev/null
+++ b/src/plugins/projectexplorer/fileinsessionfinder.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** 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 <utils/fileutils.h>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+Utils::FilePathList findFileInSession(const Utils::FilePath &filePath);
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/filterkitaspectsdialog.cpp b/src/plugins/projectexplorer/filterkitaspectsdialog.cpp
new file mode 100644
index 0000000000..418ae03564
--- /dev/null
+++ b/src/plugins/projectexplorer/filterkitaspectsdialog.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** 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 "filterkitaspectsdialog.h"
+
+#include "kitmanager.h"
+
+#include <utils/itemviews.h>
+#include <utils/qtcassert.h>
+#include <utils/treemodel.h>
+
+#include <QDialogButtonBox>
+#include <QHeaderView>
+#include <QString>
+#include <QVBoxLayout>
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class FilterTreeItem : public TreeItem
+{
+public:
+ FilterTreeItem(const KitAspect *aspect, bool enabled) : m_aspect(aspect), m_enabled(enabled)
+ { }
+
+ QString displayName() const { return m_aspect->displayName(); }
+ Core::Id id() const { return m_aspect->id(); }
+ bool enabled() const { return m_enabled; }
+
+private:
+ QVariant data(int column, int role) const override
+ {
+ QTC_ASSERT(column < 2, return QVariant());
+ if (column == 0 && role == Qt::DisplayRole)
+ return displayName();
+ if (column == 1 && role == Qt::CheckStateRole)
+ return m_enabled ? Qt::Checked : Qt::Unchecked;
+ return QVariant();
+ }
+
+ bool setData(int column, const QVariant &data, int role) override
+ {
+ QTC_ASSERT(column == 1 && !m_aspect->isEssential(), return false);
+ if (role == Qt::CheckStateRole) {
+ m_enabled = data.toInt() == Qt::Checked;
+ return true;
+ }
+ return false;
+ }
+
+ Qt::ItemFlags flags(int column) const override
+ {
+ QTC_ASSERT(column < 2, return Qt::ItemFlags());
+ Qt::ItemFlags flags = Qt::ItemIsSelectable;
+ if (column == 0 || !m_aspect->isEssential())
+ flags |= Qt::ItemIsEnabled;
+ if (column == 1 && !m_aspect->isEssential())
+ flags |= Qt::ItemIsUserCheckable;
+ return flags;
+ }
+
+ const KitAspect * const m_aspect;
+ bool m_enabled;
+};
+
+class FilterKitAspectsModel : public TreeModel<TreeItem, FilterTreeItem>
+{
+public:
+ FilterKitAspectsModel(const Kit *kit, QObject *parent) : TreeModel(parent)
+ {
+ setHeader({tr("Setting"), tr("Visible")});
+ for (const KitAspect * const aspect : KitManager::kitAspects()) {
+ if (kit && !aspect->isApplicableToKit(kit))
+ continue;
+ const QSet<Core::Id> irrelevantAspects = kit ? kit->irrelevantAspects()
+ : KitManager::irrelevantAspects();
+ auto * const item = new FilterTreeItem(aspect,
+ !irrelevantAspects.contains(aspect->id()));
+ rootItem()->appendChild(item);
+ }
+ static const auto cmp = [](const TreeItem *item1, const TreeItem *item2) {
+ return static_cast<const FilterTreeItem *>(item1)->displayName()
+ < static_cast<const FilterTreeItem *>(item2)->displayName();
+ };
+ rootItem()->sortChildren(cmp);
+ }
+
+ QSet<Core::Id> disabledItems() const
+ {
+ QSet<Core::Id> ids;
+ for (int i = 0; i < rootItem()->childCount(); ++i) {
+ const FilterTreeItem * const item
+ = static_cast<FilterTreeItem *>(rootItem()->childAt(i));
+ if (!item->enabled())
+ ids << item->id();
+ }
+ return ids;
+ }
+};
+
+class FilterTreeView : public TreeView
+{
+public:
+ FilterTreeView(QWidget *parent) : TreeView(parent)
+ {
+ setUniformRowHeights(true);
+ }
+
+private:
+ QSize sizeHint() const override
+ {
+ const int width = columnWidth(0) + columnWidth(1);
+ const int height = model()->rowCount() * rowHeight(model()->index(0, 0))
+ + header()->sizeHint().height();
+ return {width, height};
+ }
+};
+
+FilterKitAspectsDialog::FilterKitAspectsDialog(const Kit *kit, QWidget *parent)
+ : QDialog(parent), m_model(new FilterKitAspectsModel(kit, this))
+{
+ auto * const layout = new QVBoxLayout(this);
+ auto * const view = new FilterTreeView(this);
+ view->setModel(m_model);
+ view->resizeColumnToContents(0);
+ layout->addWidget(view);
+ auto * const buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ layout->addWidget(buttonBox);
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+}
+
+QSet<Core::Id> FilterKitAspectsDialog::irrelevantAspects() const
+{
+ return static_cast<FilterKitAspectsModel *>(m_model)->disabledItems();
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/filterkitaspectsdialog.h b/src/plugins/projectexplorer/filterkitaspectsdialog.h
new file mode 100644
index 0000000000..441abd658d
--- /dev/null
+++ b/src/plugins/projectexplorer/filterkitaspectsdialog.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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 <coreplugin/id.h>
+
+#include <QDialog>
+
+namespace Utils { class BaseTreeModel; }
+
+namespace ProjectExplorer {
+class Kit;
+namespace Internal {
+
+class FilterKitAspectsDialog : public QDialog
+{
+public:
+ FilterKitAspectsDialog(const Kit *kit, QWidget *parent);
+ QSet<Core::Id> irrelevantAspects() const;
+
+private:
+ Utils::BaseTreeModel * const m_model;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp
index 04948cb219..6ff9c9719a 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.cpp
+++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp
@@ -168,7 +168,7 @@ bool FolderSortProxyModel::lessThan(const QModelIndex &source_left, const QModel
}
const QString leftName = src->data(source_left, QFileSystemModel::FileNameRole).toString();
const QString rightName = src->data(source_right, QFileSystemModel::FileNameRole).toString();
- return Utils::FileName::fromString(leftName) < Utils::FileName::fromString(rightName);
+ return Utils::FilePath::fromString(leftName) < Utils::FilePath::fromString(rightName);
}
FolderNavigationModel::FolderNavigationModel(QObject *parent) : QFileSystemModel(parent)
@@ -196,12 +196,13 @@ Qt::ItemFlags FolderNavigationModel::flags(const QModelIndex &index) const
return QFileSystemModel::flags(index);
}
-static QVector<FolderNode *> renamableFolderNodes(const Utils::FileName &before,
- const Utils::FileName &after)
+static QVector<FolderNode *> renamableFolderNodes(const Utils::FilePath &before,
+ const Utils::FilePath &after)
{
QVector<FolderNode *> folderNodes;
ProjectTree::forEachNode([&](Node *node) {
- if (node->nodeType() == NodeType::File && node->filePath() == before
+ if (node->asFileNode()
+ && node->filePath() == before
&& node->parentFolderNode()
&& node->parentFolderNode()->canRenameFile(before.toString(), after.toString())) {
folderNodes.append(node->parentFolderNode());
@@ -235,8 +236,8 @@ bool FolderNavigationModel::setData(const QModelIndex &index, const QVariant &va
if (success && fileInfo(index).isFile()) {
Core::DocumentManager::renamedFile(beforeFilePath, afterFilePath);
const QVector<FolderNode *> folderNodes
- = renamableFolderNodes(Utils::FileName::fromString(beforeFilePath),
- Utils::FileName::fromString(afterFilePath));
+ = renamableFolderNodes(Utils::FilePath::fromString(beforeFilePath),
+ Utils::FilePath::fromString(afterFilePath));
QVector<FolderNode *> failedNodes;
for (FolderNode *folder : folderNodes) {
if (!folder->renameFile(beforeFilePath, afterFilePath))
@@ -382,7 +383,7 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent
this,
[this](const QModelIndex &index) {
const QModelIndex sourceIndex = m_sortProxyModel->mapToSource(index);
- const auto filePath = Utils::FileName::fromString(
+ const auto filePath = Utils::FilePath::fromString(
m_fileSystemModel->filePath(sourceIndex));
// QTimer::singleShot only posts directly onto the event loop if you use the SLOT("...")
// notation, so using a singleShot with a lambda would flicker
@@ -390,9 +391,9 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent
QMetaObject::invokeMethod(this,
"setCrumblePath",
Qt::QueuedConnection,
- Q_ARG(Utils::FileName, filePath));
+ Q_ARG(Utils::FilePath, filePath));
});
- connect(m_crumbLabel, &Utils::FileCrumbLabel::pathClicked, [this](const Utils::FileName &path) {
+ connect(m_crumbLabel, &Utils::FileCrumbLabel::pathClicked, [this](const Utils::FilePath &path) {
const QModelIndex rootIndex = m_sortProxyModel->mapToSource(m_listView->rootIndex());
const QModelIndex fileIndex = m_fileSystemModel->index(path.toString());
if (!isChildOf(fileIndex, rootIndex))
@@ -418,10 +419,10 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent
connect(m_toggleRootSync, &QAbstractButton::clicked,
this, [this]() { setRootAutoSynchronization(!m_rootAutoSync); });
connect(m_rootSelector,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
[this](int index) {
- const auto directory = m_rootSelector->itemData(index).value<Utils::FileName>();
+ const auto directory = m_rootSelector->itemData(index).value<Utils::FilePath>();
m_rootSelector->setToolTip(directory.toString());
setRootDirectory(directory);
const QModelIndex rootIndex = m_sortProxyModel->mapToSource(m_listView->rootIndex());
@@ -481,7 +482,7 @@ void FolderNavigationWidget::insertRootDirectory(
m_rootSelector->insertItem(index, directory.displayName);
if (index <= previousIndex) // item was inserted, update previousIndex
++previousIndex;
- m_rootSelector->setItemData(index, qVariantFromValue(directory.path), PATH_ROLE);
+ m_rootSelector->setItemData(index, QVariant::fromValue(directory.path), PATH_ROLE);
m_rootSelector->setItemData(index, directory.id, ID_ROLE);
m_rootSelector->setItemData(index, directory.sortValue, SORT_ROLE);
m_rootSelector->setItemData(index, directory.path.toUserOutput(), Qt::ToolTipRole);
@@ -511,8 +512,8 @@ void FolderNavigationWidget::addNewItem()
const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex());
if (!current.isValid())
return;
- const auto filePath = Utils::FileName::fromString(m_fileSystemModel->filePath(current));
- const Utils::FileName path = filePath.toFileInfo().isDir() ? filePath : filePath.parentDir();
+ const auto filePath = Utils::FilePath::fromString(m_fileSystemModel->filePath(current));
+ const Utils::FilePath path = filePath.toFileInfo().isDir() ? filePath : filePath.parentDir();
Core::ICore::showNewItemDialog(ProjectExplorerPlugin::tr("New File", "Title of dialog"),
Utils::filtered(Core::IWizardFactory::allWizardFactories(),
Utils::equal(&Core::IWizardFactory::kind,
@@ -527,11 +528,12 @@ void FolderNavigationWidget::editCurrentItem()
m_listView->edit(current);
}
-static QVector<FolderNode *> removableFolderNodes(const Utils::FileName &filePath)
+static QVector<FolderNode *> removableFolderNodes(const Utils::FilePath &filePath)
{
QVector<FolderNode *> folderNodes;
ProjectTree::forEachNode([&](Node *node) {
- if (node->nodeType() == NodeType::File && node->filePath() == filePath
+ if (node->asFileNode()
+ && node->filePath() == filePath
&& node->parentFolderNode()
&& node->parentFolderNode()->supportsAction(RemoveFile, node)) {
folderNodes.append(node->parentFolderNode());
@@ -550,7 +552,7 @@ void FolderNavigationWidget::removeCurrentItem()
dialog.setDeleteFileVisible(false);
if (dialog.exec() == QDialog::Accepted) {
const QVector<FolderNode *> folderNodes = removableFolderNodes(
- Utils::FileName::fromString(filePath));
+ Utils::FilePath::fromString(filePath));
const QVector<FolderNode *> failedNodes = Utils::filtered(folderNodes,
[filePath](FolderNode *folder) {
return !folder->removeFiles(
@@ -604,19 +606,19 @@ void FolderNavigationWidget::handleCurrentEditorChanged(Core::IEditor *editor)
if (!m_autoSync || !editor || editor->document()->filePath().isEmpty()
|| editor->document()->isTemporary())
return;
- const Utils::FileName filePath = editor->document()->filePath();
+ const Utils::FilePath filePath = editor->document()->filePath();
if (m_rootAutoSync)
selectBestRootForFile(filePath);
selectFile(filePath);
}
-void FolderNavigationWidget::selectBestRootForFile(const Utils::FileName &filePath)
+void FolderNavigationWidget::selectBestRootForFile(const Utils::FilePath &filePath)
{
const int bestRootIndex = bestRootForFile(filePath);
m_rootSelector->setCurrentIndex(bestRootIndex);
}
-void FolderNavigationWidget::selectFile(const Utils::FileName &filePath)
+void FolderNavigationWidget::selectFile(const Utils::FilePath &filePath)
{
const QModelIndex fileIndex = m_sortProxyModel->mapFromSource(
m_fileSystemModel->index(filePath.toString()));
@@ -640,22 +642,22 @@ void FolderNavigationWidget::selectFile(const Utils::FileName &filePath)
}
}
-void FolderNavigationWidget::setRootDirectory(const Utils::FileName &directory)
+void FolderNavigationWidget::setRootDirectory(const Utils::FilePath &directory)
{
const QModelIndex index = m_sortProxyModel->mapFromSource(
m_fileSystemModel->setRootPath(directory.toString()));
m_listView->setRootIndex(index);
}
-int FolderNavigationWidget::bestRootForFile(const Utils::FileName &filePath)
+int FolderNavigationWidget::bestRootForFile(const Utils::FilePath &filePath)
{
int index = 0; // Computer is default
int commonLength = 0;
for (int i = 1; i < m_rootSelector->count(); ++i) {
- const auto root = m_rootSelector->itemData(i).value<Utils::FileName>();
- if (filePath.isChildOf(root) && root.length() > commonLength) {
+ const auto root = m_rootSelector->itemData(i).value<Utils::FilePath>();
+ if (filePath.isChildOf(root) && root.toString().size() > commonLength) {
index = i;
- commonLength = root.length();
+ commonLength = root.toString().size();
}
}
return index;
@@ -695,12 +697,12 @@ void FolderNavigationWidget::createNewFolder(const QModelIndex &parent)
static const QString baseName = tr("New Folder");
// find non-existing name
const QDir dir(m_fileSystemModel->filePath(parent));
- const QSet<Utils::FileName> existingItems
+ const QSet<Utils::FilePath> existingItems
= Utils::transform<QSet>(dir.entryList({baseName + '*'}, QDir::AllEntries),
[](const QString &entry) {
- return Utils::FileName::fromString(entry);
+ return Utils::FilePath::fromString(entry);
});
- const Utils::FileName name = Utils::makeUniquelyNumbered(Utils::FileName::fromString(baseName),
+ const Utils::FilePath name = Utils::makeUniquelyNumbered(Utils::FilePath::fromString(baseName),
existingItems);
// create directory and edit
const QModelIndex index = m_sortProxyModel->mapFromSource(
@@ -711,7 +713,7 @@ void FolderNavigationWidget::createNewFolder(const QModelIndex &parent)
m_listView->edit(index);
}
-void FolderNavigationWidget::setCrumblePath(const Utils::FileName &filePath)
+void FolderNavigationWidget::setCrumblePath(const Utils::FilePath &filePath)
{
const QModelIndex index = m_fileSystemModel->index(filePath.toString());
const int width = m_crumbLabel->width();
@@ -750,9 +752,9 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
QAction *actionOpenAsProject = nullptr;
QAction *newFolder = nullptr;
const bool isDir = m_fileSystemModel->isDir(current);
- const Utils::FileName filePath = hasCurrentItem ? Utils::FileName::fromString(
+ const Utils::FilePath filePath = hasCurrentItem ? Utils::FilePath::fromString(
m_fileSystemModel->filePath(current))
- : Utils::FileName();
+ : Utils::FilePath();
if (hasCurrentItem) {
const QString fileName = m_fileSystemModel->fileName(current);
if (isDir) {
@@ -761,7 +763,7 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
actionOpenProjects->setEnabled(false);
} else {
actionOpenFile = menu.addAction(tr("Open \"%1\"").arg(fileName));
- if (ProjectExplorerPlugin::isProjectFile(Utils::FileName::fromString(fileName)))
+ if (ProjectExplorerPlugin::isProjectFile(Utils::FilePath::fromString(fileName)))
actionOpenAsProject = menu.addAction(tr("Open Project \"%1\"").arg(fileName));
}
}
@@ -864,12 +866,12 @@ FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
insertRootDirectory({QLatin1String("A.Computer"),
0 /*sortValue*/,
FolderNavigationWidget::tr("Computer"),
- Utils::FileName(),
+ Utils::FilePath(),
Icons::DESKTOP_DEVICE_SMALL.icon()});
insertRootDirectory({QLatin1String("A.Home"),
10 /*sortValue*/,
FolderNavigationWidget::tr("Home"),
- Utils::FileName::fromString(QDir::homePath()),
+ Utils::FilePath::fromString(QDir::homePath()),
Utils::Icons::HOME.icon()});
updateProjectsDirectoryRoot();
connect(Core::DocumentManager::instance(),
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h
index b741de7cfe..b6268b66d6 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.h
+++ b/src/plugins/projectexplorer/foldernavigationwidget.h
@@ -63,7 +63,7 @@ public:
QString id;
int sortValue;
QString displayName;
- Utils::FileName path;
+ Utils::FilePath path;
QIcon icon;
};
@@ -119,17 +119,17 @@ protected:
void contextMenuEvent(QContextMenuEvent *ev) override;
private slots:
- void setCrumblePath(const Utils::FileName &filePath);
+ void setCrumblePath(const Utils::FilePath &filePath);
private:
bool rootAutoSynchronization() const;
void setRootAutoSynchronization(bool sync);
void setHiddenFilesFilter(bool filter);
- void selectBestRootForFile(const Utils::FileName &filePath);
+ void selectBestRootForFile(const Utils::FilePath &filePath);
void handleCurrentEditorChanged(Core::IEditor *editor);
- void selectFile(const Utils::FileName &filePath);
- void setRootDirectory(const Utils::FileName &directory);
- int bestRootForFile(const Utils::FileName &filePath);
+ void selectFile(const Utils::FilePath &filePath);
+ void setRootDirectory(const Utils::FilePath &directory);
+ int bestRootForFile(const Utils::FilePath &filePath);
void openItem(const QModelIndex &index);
QStringList projectsInDirectory(const QModelIndex &index) const;
void openProjectsInDirectory(const QModelIndex &index);
diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp
index 9b1fe34256..fff0606889 100644
--- a/src/plugins/projectexplorer/gccparser.cpp
+++ b/src/plugins/projectexplorer/gccparser.cpp
@@ -77,7 +77,7 @@ void GccParser::stdError(const QString &line)
lne == QLatin1String("* cpp failed")) {
newTask(Task(Task::Error,
lne /* description */,
- Utils::FileName() /* filename */,
+ Utils::FilePath() /* filename */,
-1 /* linenumber */,
Constants::TASK_CATEGORY_COMPILE));
return;
@@ -93,7 +93,7 @@ void GccParser::stdError(const QString &line)
} else if (description.startsWith(QLatin1String("fatal: "))) {
description = description.mid(7);
}
- Task task(type, description, Utils::FileName(), /* filename */
+ Task task(type, description, Utils::FilePath(), /* filename */
-1, /* line */ Constants::TASK_CATEGORY_COMPILE);
newTask(task);
return;
@@ -101,7 +101,7 @@ void GccParser::stdError(const QString &line)
match = m_regExp.match(lne);
if (match.hasMatch()) {
- Utils::FileName filename = Utils::FileName::fromUserInput(match.captured(1));
+ Utils::FilePath filename = Utils::FilePath::fromUserInput(match.captured(1));
int lineno = match.captured(3).toInt();
Task::TaskType type = Task::Unknown;
QString description = match.captured(8);
@@ -125,7 +125,7 @@ void GccParser::stdError(const QString &line)
if (match.hasMatch()) {
newTask(Task(Task::Unknown,
lne.trimmed() /* description */,
- Utils::FileName::fromUserInput(match.captured(1)) /* filename */,
+ Utils::FilePath::fromUserInput(match.captured(1)) /* filename */,
match.captured(3).toInt() /* linenumber */,
Constants::TASK_CATEGORY_COMPILE));
return;
@@ -199,7 +199,7 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
const Core::Id categoryCompile = Constants::TASK_CATEGORY_COMPILE;
@@ -207,18 +207,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
QTest::newRow("pass-through stdout")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("ar output")
<< QString::fromLatin1("../../../../x86/i686-unknown-linux-gnu/bin/i686-unknown-linux-gnu-ar: creating lib/libSkyView.a") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("../../../../x86/i686-unknown-linux-gnu/bin/i686-unknown-linux-gnu-ar: creating lib/libSkyView.a\n")
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("GCCE error")
@@ -227,18 +227,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"/temp/test/untitled8/main.cpp:9: error: (Each undeclared identifier is reported only once for each function it appears in.)")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("In function `int main(int, char**)':"),
- Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("`sfasdf' undeclared (first use this function)"),
- Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 9,
+ Utils::FilePath::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 9,
categoryCompile)
<< Task(Task::Error,
QLatin1String("(Each undeclared identifier is reported only once for each function it appears in.)"),
- Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 9,
+ Utils::FilePath::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 9,
categoryCompile)
)
<< QString();
@@ -246,29 +246,29 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("/src/corelib/global/qglobal.h:1635: warning: inline function `QDebug qDebug()' used but never defined")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("inline function `QDebug qDebug()' used but never defined"),
- Utils::FileName::fromUserInput(QLatin1String("/src/corelib/global/qglobal.h")), 1635,
+ Utils::FilePath::fromUserInput(QLatin1String("/src/corelib/global/qglobal.h")), 1635,
categoryCompile))
<< QString();
QTest::newRow("warning")
<< QString::fromLatin1("main.cpp:7:2: warning: Some warning")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>() << Task(Task::Warning,
+ << (Tasks() << Task(Task::Warning,
QLatin1String("Some warning"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 7,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 7,
categoryCompile))
<< QString();
QTest::newRow("GCCE #error")
<< QString::fromLatin1("C:\\temp\\test\\untitled8\\main.cpp:7: #error Symbian error")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("#error Symbian error"),
- Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8\\main.cpp")), 7,
+ Utils::FilePath::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8\\main.cpp")), 7,
categoryCompile))
<< QString();
// Symbian reports #warning(s) twice (using different syntax).
@@ -276,20 +276,20 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("C:\\temp\\test\\untitled8\\main.cpp:8: warning: #warning Symbian warning")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("#warning Symbian warning"),
- Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8\\main.cpp")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8\\main.cpp")), 8,
categoryCompile))
<< QString();
QTest::newRow("GCCE #warning2")
<< QString::fromLatin1("/temp/test/untitled8/main.cpp:8:2: warning: #warning Symbian warning")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("#warning Symbian warning"),
- Utils::FileName::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("/temp/test/untitled8/main.cpp")), 8,
categoryCompile))
<< QString();
QTest::newRow("Undefined reference (debug)")
@@ -298,18 +298,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"collect2: ld returned 1 exit status")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("In function `main':"),
- Utils::FileName::fromUserInput(QLatin1String("main.o")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("main.o")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("undefined reference to `MainWindow::doSomething()'"),
- Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8/main.cpp")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8/main.cpp")), 8,
categoryCompile)
<< Task(Task::Error,
QLatin1String("collect2: ld returned 1 exit status"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile)
)
<< QString();
@@ -319,18 +319,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"collect2: ld returned 1 exit status")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("In function `main':"),
- Utils::FileName::fromUserInput(QLatin1String("main.o")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("main.o")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("undefined reference to `MainWindow::doSomething()'"),
- Utils::FileName::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8/main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("C:\\temp\\test\\untitled8/main.cpp")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("collect2: ld returned 1 exit status"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile)
)
<< QString();
@@ -338,20 +338,20 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("c:\\Qt\\4.6\\lib/QtGuid4.dll: file not recognized: File format not recognized")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("file not recognized: File format not recognized"),
- Utils::FileName::fromUserInput(QLatin1String("c:\\Qt\\4.6\\lib/QtGuid4.dll")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\Qt\\4.6\\lib/QtGuid4.dll")), -1,
categoryCompile))
<< QString();
QTest::newRow("Invalid rpath")
<< QString::fromLatin1("g++: /usr/local/lib: No such file or directory")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("/usr/local/lib: No such file or directory"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
@@ -361,18 +361,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"../../../../master/src/plugins/debugger/gdb/gdbengine.cpp:2115: warning: unused variable 'handler'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("In member function 'void Debugger::Internal::GdbEngine::handleBreakInsert2(const Debugger::Internal::GdbResponse&)':"),
- Utils::FileName::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), -1,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("unused variable 'index'"),
- Utils::FileName::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), 2114,
+ Utils::FilePath::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), 2114,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("unused variable 'handler'"),
- Utils::FileName::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), 2115,
+ Utils::FilePath::fromUserInput(QLatin1String("../../../../master/src/plugins/debugger/gdb/gdbengine.cpp")), 2115,
categoryCompile))
<< QString();
QTest::newRow("gnumakeparser.cpp errors")
@@ -381,18 +381,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp:264: error: expected ';' before ':' token")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("In member function 'void ProjectExplorer::ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data()':"),
- Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("expected primary-expression before ':' token"),
- Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), 264,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), 264,
categoryCompile)
<< Task(Task::Error,
QLatin1String("expected ';' before ':' token"),
- Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), 264,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp")), 264,
categoryCompile))
<< QString();
QTest::newRow("distcc error(QTCREATORBUG-904)")
@@ -401,42 +401,42 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("distcc[73168] (dcc_get_hostlist) Warning: no hostlist is set; can't distribute work\n"
"distcc[73168] (dcc_build_somewhere) Warning: failed to distribute, running locally instead\n")
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("ld warning (QTCREATORBUG-905)")
<< QString::fromLatin1("ld: warning: Core::IEditor* QVariant::value<Core::IEditor*>() const has different visibility (hidden) in .obj/debug-shared/openeditorsview.o and (default) in .obj/debug-shared/editormanager.o")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Warning,
QLatin1String("Core::IEditor* QVariant::value<Core::IEditor*>() const has different visibility (hidden) in .obj/debug-shared/openeditorsview.o and (default) in .obj/debug-shared/editormanager.o"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
QTest::newRow("ld fatal")
<< QString::fromLatin1("ld: fatal: Symbol referencing errors. No output written to testproject")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Error,
QLatin1String("Symbol referencing errors. No output written to testproject"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
QTest::newRow("Teambuilder issues")
<< QString::fromLatin1("TeamBuilder Client:: error: could not find Scheduler, running Job locally...")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("TeamBuilder Client:: error: could not find Scheduler, running Job locally...\n")
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("note")
<< QString::fromLatin1("/home/dev/creator/share/qtcreator/debugger/dumper.cpp:1079: note: initialized from here")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("initialized from here"),
- Utils::FileName::fromUserInput(QLatin1String("/home/dev/creator/share/qtcreator/debugger/dumper.cpp")), 1079,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/dev/creator/share/qtcreator/debugger/dumper.cpp")), 1079,
categoryCompile))
<< QString();
QTest::newRow("static member function")
@@ -444,30 +444,30 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c:194: warning: suggest explicit braces to avoid ambiguous 'else'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In static member function 'static std::_Rb_tree_node_base* std::_Rb_global<_Dummy>::_Rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&, std::_Rb_tree_node_base*&, std::_Rb_tree_node_base*&)':"),
- Utils::FileName::fromUserInput(QLatin1String("/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c")), -1,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("suggest explicit braces to avoid ambiguous 'else'"),
- Utils::FileName::fromUserInput(QLatin1String("/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c")), 194,
+ Utils::FilePath::fromUserInput(QLatin1String("/Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c")), 194,
categoryCompile))
<< QString();
QTest::newRow("rm false positive")
<< QString::fromLatin1("rm: cannot remove `release/moc_mainwindow.cpp': No such file or directory")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("rm: cannot remove `release/moc_mainwindow.cpp': No such file or directory\n")
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("ld: missing library")
<< QString::fromLatin1("/usr/bin/ld: cannot find -ldoesnotexist")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Error,
QLatin1String("cannot find -ldoesnotexist"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
QTest::newRow("In function")
@@ -476,38 +476,38 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"../../scriptbug/main.cpp:8: warning: unused variable c")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In function void foo(i) [with i = double]:"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("instantiated from here"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 22,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 22,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("unused variable c"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 8,
categoryCompile))
<< QString();
QTest::newRow("instanciated from here")
<< QString::fromLatin1("main.cpp:10: instantiated from here ")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("instantiated from here"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 10,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 10,
categoryCompile))
<< QString();
QTest::newRow("In constructor")
<< QString::fromLatin1("/dev/creator/src/plugins/find/basetextfind.h: In constructor 'Find::BaseTextFind::BaseTextFind(QTextEdit*)':")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In constructor 'Find::BaseTextFind::BaseTextFind(QTextEdit*)':"),
- Utils::FileName::fromUserInput(QLatin1String("/dev/creator/src/plugins/find/basetextfind.h")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("/dev/creator/src/plugins/find/basetextfind.h")), -1,
categoryCompile))
<< QString();
@@ -519,26 +519,26 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"../../scriptbug/main.cpp:5: warning: unused parameter v")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("At global scope:"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("In instantiation of void bar(i) [with i = double]:"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), -1,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("instantiated from void foo(i) [with i = double]"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 8,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 8,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("instantiated from here"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 22,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 22,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("unused parameter v"),
- Utils::FileName::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 5,
+ Utils::FilePath::fromUserInput(QLatin1String("../../scriptbug/main.cpp")), 5,
categoryCompile))
<< QString();
@@ -546,10 +546,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("/home/code/test.cpp:54:38: fatal error: test.moc: No such file or directory")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Error,
QLatin1String("test.moc: No such file or directory"),
- Utils::FileName::fromUserInput(QLatin1String("/home/code/test.cpp")), 54,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/code/test.cpp")), 54,
categoryCompile))
<< QString();
@@ -560,22 +560,22 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"collect2: ld returned 1 exit status")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In function `QPlotAxis':"),
- Utils::FileName::fromUserInput(QLatin1String("debug/qplotaxis.o")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("debug/qplotaxis.o")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("undefined reference to `vtable for QPlotAxis'"),
- Utils::FileName::fromUserInput(QLatin1String("M:\\Development\\x64\\QtPlot/qplotaxis.cpp")), 26,
+ Utils::FilePath::fromUserInput(QLatin1String("M:\\Development\\x64\\QtPlot/qplotaxis.cpp")), 26,
categoryCompile)
<< Task(Task::Error,
QLatin1String("undefined reference to `vtable for QPlotAxis'"),
- Utils::FileName::fromUserInput(QLatin1String("M:\\Development\\x64\\QtPlot/qplotaxis.cpp")), 26,
+ Utils::FilePath::fromUserInput(QLatin1String("M:\\Development\\x64\\QtPlot/qplotaxis.cpp")), 26,
categoryCompile)
<< Task(Task::Error,
QLatin1String("collect2: ld returned 1 exit status"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile))
<< QString();
@@ -587,26 +587,26 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"../stl/main.cpp:31: warning: unused parameter index")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In member function typename _Vector_base<_Tp, _Alloc>::_Tp_alloc_type::const_reference Vector<_Tp, _Alloc>::at(int) [with _Tp = Point, _Alloc = Allocator<Point>]:"),
- Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../stl/main.cpp")), -1,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("instantiated from here"),
- Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), 38,
+ Utils::FilePath::fromUserInput(QLatin1String("../stl/main.cpp")), 38,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("returning reference to temporary"),
- Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), 31,
+ Utils::FilePath::fromUserInput(QLatin1String("../stl/main.cpp")), 31,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("At global scope:"),
- Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../stl/main.cpp")), -1,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("unused parameter index"),
- Utils::FileName::fromUserInput(QLatin1String("../stl/main.cpp")), 31,
+ Utils::FilePath::fromUserInput(QLatin1String("../stl/main.cpp")), 31,
categoryCompile))
<< QString();
@@ -617,22 +617,22 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"C:/Symbian_SDK/epoc32/include/e32cmn.inl:7094: warning: returning reference to temporary")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In file included from C:/Symbian_SDK/epoc32/include/e32cmn.h:6792,"),
- Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.h")), 6792,
+ Utils::FilePath::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.h")), 6792,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("from C:/Symbian_SDK/epoc32/include/e32std.h:25,"),
- Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32std.h")), 25,
+ Utils::FilePath::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32std.h")), 25,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("In member function 'SSecureId::operator const TSecureId&() const':"),
- Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.inl")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.inl")), -1,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("returning reference to temporary"),
- Utils::FileName::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.inl")), 7094,
+ Utils::FilePath::fromUserInput(QLatin1String("C:/Symbian_SDK/epoc32/include/e32cmn.inl")), 7094,
categoryCompile))
<< QString();
@@ -640,10 +640,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("../../../src/XmlUg/targetdelete.c: At top level:")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("At top level:"),
- Utils::FileName::fromUserInput(QLatin1String("../../../src/XmlUg/targetdelete.c")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../../../src/XmlUg/targetdelete.c")), -1,
categoryCompile))
<< QString();
@@ -653,18 +653,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"/Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh:1134:26: warning: no newline at end of file")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In file included from /Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h:15,"),
- Utils::FileName::fromUserInput(QLatin1String("/Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h")), 15,
+ Utils::FilePath::fromUserInput(QLatin1String("/Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h")), 15,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("from <command line>:26:"),
- Utils::FileName::fromUserInput(QLatin1String("<command line>")), 26,
+ Utils::FilePath::fromUserInput(QLatin1String("<command line>")), 26,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("no newline at end of file"),
- Utils::FileName::fromUserInput(QLatin1String("/Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh")), 1134,
+ Utils::FilePath::fromUserInput(QLatin1String("/Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh")), 1134,
categoryCompile))
<< QString();
@@ -672,10 +672,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("release/main.o:main.cpp:(.text+0x42): undefined reference to `MainWindow::doSomething()'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Error,
QLatin1String("undefined reference to `MainWindow::doSomething()'"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), -1,
categoryCompile))
<< QString();
@@ -684,14 +684,14 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"../../../src/shared/proparser/profileevaluator.cpp:2817:9: warning: case value '0' not in enumerated type 'ProFileEvaluator::Private::TestFunc'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In member function 'ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateConditionalFunction(const ProString&, const ProStringList&)':"),
- Utils::FileName::fromUserInput(QLatin1String("../../../src/shared/proparser/profileevaluator.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("../../../src/shared/proparser/profileevaluator.cpp")), -1,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("case value '0' not in enumerated type 'ProFileEvaluator::Private::TestFunc'"),
- Utils::FileName::fromUserInput(QLatin1String("../../../src/shared/proparser/profileevaluator.cpp")), 2817,
+ Utils::FilePath::fromUserInput(QLatin1String("../../../src/shared/proparser/profileevaluator.cpp")), 2817,
categoryCompile))
<< QString();
@@ -700,14 +700,14 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"./mw.h:4:0: warning: \"STUPID_DEFINE\" redefined")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In file included from <command-line>:0:0:"),
- Utils::FileName::fromUserInput(QLatin1String("<command-line>")), 0,
+ Utils::FilePath::fromUserInput(QLatin1String("<command-line>")), 0,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("\"STUPID_DEFINE\" redefined"),
- Utils::FileName::fromUserInput(QLatin1String("./mw.h")), 4,
+ Utils::FilePath::fromUserInput(QLatin1String("./mw.h")), 4,
categoryCompile))
<< QString();
QTest::newRow("instanciation with line:column info")
@@ -716,28 +716,28 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"file.h:21:5: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In function 'void UnitTest::CheckEqual(UnitTest::TestResults&, const Expected&, const Actual&, const UnitTest::TestDetails&) [with Expected = unsigned int, Actual = int]':"),
- Utils::FileName::fromUserInput(QLatin1String("file.h")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("file.h")), -1,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("instantiated from here"),
- Utils::FileName::fromUserInput(QLatin1String("file.cpp")), 87,
+ Utils::FilePath::fromUserInput(QLatin1String("file.cpp")), 87,
categoryCompile)
<< Task(Task::Warning,
QLatin1String("comparison between signed and unsigned integer expressions [-Wsign-compare]"),
- Utils::FileName::fromUserInput(QLatin1String("file.h")), 21,
+ Utils::FilePath::fromUserInput(QLatin1String("file.h")), 21,
categoryCompile))
<< QString();
QTest::newRow("linker error") // QTCREATORBUG-3107
<< QString::fromLatin1("cns5k_ins_parser_tests.cpp:(.text._ZN20CNS5kINSParserEngine21DropBytesUntilStartedEP14CircularBufferIhE[CNS5kINSParserEngine::DropBytesUntilStarted(CircularBuffer<unsigned char>*)]+0x6d): undefined reference to `CNS5kINSPacket::SOH_BYTE'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Error,
QLatin1String("undefined reference to `CNS5kINSPacket::SOH_BYTE'"),
- Utils::FileName::fromUserInput(QLatin1String("cns5k_ins_parser_tests.cpp")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("cns5k_ins_parser_tests.cpp")), -1,
categoryCompile))
<< QString();
@@ -745,10 +745,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("mainwindow.ui: Warning: The name 'pushButton' (QPushButton) is already in use, defaulting to 'pushButton1'.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Warning,
QLatin1String("The name 'pushButton' (QPushButton) is already in use, defaulting to 'pushButton1'."),
- Utils::FileName::fromUserInput(QLatin1String("mainwindow.ui")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("mainwindow.ui")), -1,
Constants::TASK_CATEGORY_COMPILE))
<< QString();
@@ -756,10 +756,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("libimf.so: warning: warning: feupdateenv is not implemented and will always fail")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Warning,
QLatin1String("warning: feupdateenv is not implemented and will always fail"),
- Utils::FileName::fromUserInput(QLatin1String("libimf.so")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("libimf.so")), -1,
Constants::TASK_CATEGORY_COMPILE))
<< QString();
@@ -770,16 +770,16 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
" ^")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In file included from /home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp:31:0:"),
- Utils::FileName::fromUserInput(QLatin1String("/home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp")), 31,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp")), 31,
categoryCompile)
<< Task(Task::Error,
QLatin1String("QtGui/QAction: No such file or directory\n"
" #include <QtGui/QAction>\n"
" ^"),
- Utils::FileName::fromUserInput(QLatin1String(".uic/ui_pluginerrorview.h")), 14,
+ Utils::FilePath::fromUserInput(QLatin1String(".uic/ui_pluginerrorview.h")), 14,
categoryCompile))
<< QString();
@@ -791,26 +791,26 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"main.cpp:7:22: error: within this context")
<< OutputParserTester::STDERR
<< QString() << QString()
- << ( QList<Task>()
+ << ( Tasks()
<< Task(Task::Unknown,
QLatin1String("In file included from /usr/include/qt4/QtCore/QString:1:0,"),
- Utils::FileName::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/QString")), 1,
+ Utils::FilePath::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/QString")), 1,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("from main.cpp:3:"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 3,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 3,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("In function 'void foo()':"),
- Utils::FileName::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/qstring.h")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/qstring.h")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("'QString::QString(const char*)' is private"),
- Utils::FileName::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/qstring.h")), 597,
+ Utils::FilePath::fromUserInput(QLatin1String("/usr/include/qt4/QtCore/qstring.h")), 597,
categoryCompile)
<< Task(Task::Error,
QLatin1String("within this context"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 7,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 7,
categoryCompile))
<< QString();
@@ -821,22 +821,22 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"collect2: error: ld returned 1 exit status")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("In function `foo()':"),
- Utils::FileName::fromUserInput(QLatin1String("foo.o")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("foo.o")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("multiple definition of `foo()'"),
- Utils::FileName::fromUserInput(QLatin1String("/home/user/test/foo.cpp")), 2,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/user/test/foo.cpp")), 2,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("first defined here"),
- Utils::FileName::fromUserInput(QLatin1String("/home/user/test/bar.cpp")), 4,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/user/test/bar.cpp")), 4,
categoryCompile)
<< Task(Task::Error,
QLatin1String("collect2: error: ld returned 1 exit status"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile)
)
<< QString();
@@ -847,18 +847,18 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
"collect2: error: ld returned 1 exit status")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("multiple definition of `foo'"),
- Utils::FileName::fromUserInput(QLatin1String("foo.o")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("foo.o")), -1,
categoryCompile)
<< Task(Task::Unknown,
QLatin1String("first defined here"),
- Utils::FileName::fromUserInput(QLatin1String("bar.o")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("bar.o")), -1,
categoryCompile)
<< Task(Task::Error,
QLatin1String("collect2: error: ld returned 1 exit status"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile)
)
<< QString();
@@ -867,10 +867,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< "obj/gtest-clang-printing.o:gtest-clang-printing.cpp:llvm::VerifyDisableABIBreakingChecks: error: undefined reference to 'llvm::DisableABIBreakingChecks'"
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("error: undefined reference to 'llvm::DisableABIBreakingChecks'"),
- Utils::FileName::fromString("gtest-clang-printing.cpp"), -1,
+ Utils::FilePath::fromString("gtest-clang-printing.cpp"), -1,
categoryCompile)
)
<< QString();
@@ -879,10 +879,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("ranlib: file: lib/libtest.a(Test0.cpp.o) has no symbols")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("file: lib/libtest.a(Test0.cpp.o) has no symbols"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile)
)
<< QString();
@@ -890,10 +890,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("/path/to/XCode/and/ranlib: file: lib/libtest.a(Test0.cpp.o) has no symbols")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("file: lib/libtest.a(Test0.cpp.o) has no symbols"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryCompile)
)
<< QString();
@@ -901,10 +901,10 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< QString::fromLatin1("/home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("Note: No relevant classes found. No output generated."),
- Utils::FileName::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
categoryCompile)
)
<< QString();
@@ -916,7 +916,7 @@ void ProjectExplorerPlugin::testGccOutputParsers()
testbench.appendOutputParser(new GccParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index c9c28846f6..66db003212 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -77,7 +77,7 @@ static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedA
static const char parentToolChainIdKeyC[] = "ProjectExplorer.ClangToolChain.ParentToolChainId";
static const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+|clang(?:\\+\\+)?)(?:-([\\d.]+))?$";
-static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, const QStringList &env)
+static QByteArray runGcc(const FilePath &gcc, const QStringList &arguments, const QStringList &env)
{
if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable())
return QByteArray();
@@ -98,7 +98,7 @@ static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, cons
return response.allOutput().toUtf8();
}
-static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc,
+static ProjectExplorer::Macros gccPredefinedMacros(const FilePath &gcc,
const QStringList &args,
const QStringList &env)
{
@@ -124,7 +124,7 @@ static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc,
return predefinedMacros;
}
-HeaderPaths GccToolChain::gccHeaderPaths(const FileName &gcc, const QStringList &arguments,
+HeaderPaths GccToolChain::gccHeaderPaths(const FilePath &gcc, const QStringList &arguments,
const QStringList &env)
{
HeaderPaths builtInHeaderPaths;
@@ -167,16 +167,9 @@ HeaderPaths GccToolChain::gccHeaderPaths(const FileName &gcc, const QStringList
return builtInHeaderPaths;
}
-void GccToolChain::toolChainUpdated()
+static Abis guessGccAbi(const QString &m, const ProjectExplorer::Macros &macros)
{
- m_predefinedMacrosCache->invalidate();
- m_headerPathsCache->invalidate();
- ToolChain::toolChainUpdated();
-}
-
-static QList<Abi> guessGccAbi(const QString &m, const ProjectExplorer::Macros &macros)
-{
- QList<Abi> abiList;
+ Abis abiList;
Abi guessed = Abi::abiFromTargetTriplet(m);
if (guessed.isNull())
@@ -203,7 +196,10 @@ static QList<Abi> guessGccAbi(const QString &m, const ProjectExplorer::Macros &m
abiList << Abi(arch, os, flavor, format, width == 64 ? 32 : 64);
} else if (arch == Abi::X86Architecture && (width == 0 || width == 64)) {
abiList << Abi(arch, os, flavor, format, 64);
- abiList << Abi(arch, os, flavor, format, 32);
+ if (width != 64 || (!m.contains("mingw")
+ && ToolChainManager::detectionSettings().detectX64AsX32)) {
+ abiList << Abi(arch, os, flavor, format, 32);
+ }
} else {
abiList << Abi(arch, os, flavor, format, width);
}
@@ -211,7 +207,7 @@ static QList<Abi> guessGccAbi(const QString &m, const ProjectExplorer::Macros &m
}
-static GccToolChain::DetectedAbisResult guessGccAbi(const FileName &path, const QStringList &env,
+static GccToolChain::DetectedAbisResult guessGccAbi(const FilePath &path, const QStringList &env,
const ProjectExplorer::Macros &macros,
const QStringList &extraArgs = QStringList())
{
@@ -226,7 +222,7 @@ static GccToolChain::DetectedAbisResult guessGccAbi(const FileName &path, const
return GccToolChain::DetectedAbisResult(guessGccAbi(machine, macros), machine);
}
-static QString gccVersion(const FileName &path, const QStringList &env)
+static QString gccVersion(const FilePath &path, const QStringList &env)
{
QStringList arguments("-dumpversion");
return QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed();
@@ -236,17 +232,15 @@ static QString gccVersion(const FileName &path, const QStringList &env)
// GccToolChain
// --------------------------------------------------------------------------
-GccToolChain::GccToolChain(Detection d) :
- GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID, d)
+GccToolChain::GccToolChain() :
+ GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID)
{ }
-GccToolChain::GccToolChain(Core::Id typeId, Detection d) :
- ToolChain(typeId, d),
- m_predefinedMacrosCache(std::make_shared<Cache<MacroInspectionReport, 64>>()),
- m_headerPathsCache(std::make_shared<Cache<HeaderPaths>>())
+GccToolChain::GccToolChain(Core::Id typeId) :
+ ToolChain(typeId)
{ }
-void GccToolChain::setCompilerCommand(const FileName &path)
+void GccToolChain::setCompilerCommand(const FilePath &path)
{
if (path == m_compilerCommand)
return;
@@ -255,12 +249,12 @@ void GccToolChain::setCompilerCommand(const FileName &path)
toolChainUpdated();
}
-void GccToolChain::setSupportedAbis(const QList<Abi> &m_abis)
+void GccToolChain::setSupportedAbis(const Abis &abis)
{
- if (m_supportedAbis == m_abis)
+ if (m_supportedAbis == abis)
return;
- m_supportedAbis = m_abis;
+ m_supportedAbis = abis;
toolChainUpdated();
}
@@ -328,14 +322,14 @@ void GccToolChain::setTargetAbi(const Abi &abi)
toolChainUpdated();
}
-QList<Abi> GccToolChain::supportedAbis() const
+Abis GccToolChain::supportedAbis() const
{
return m_supportedAbis;
}
bool GccToolChain::isValid() const
{
- if (m_compilerCommand.isNull())
+ if (m_compilerCommand.isEmpty())
return false;
QFileInfo fi = compilerCommand().toFileInfo();
@@ -347,7 +341,7 @@ static bool isNetworkCompiler(const QString &dirPath)
return dirPath.contains("icecc") || dirPath.contains("distcc");
}
-static Utils::FileName findLocalCompiler(const Utils::FileName &compilerPath,
+static Utils::FilePath findLocalCompiler(const Utils::FilePath &compilerPath,
const Environment &env)
{
// Find the "real" compiler if icecc, distcc or similar are in use. Ignore ccache, since that
@@ -359,13 +353,13 @@ static Utils::FileName findLocalCompiler(const Utils::FileName &compilerPath,
return compilerPath;
// Filter out network compilers
- const FileNameList pathComponents = Utils::filtered(env.path(), [] (const FileName &dirPath) {
+ const FilePathList pathComponents = Utils::filtered(env.path(), [] (const FilePath &dirPath) {
return !isNetworkCompiler(dirPath.toString());
});
// This effectively searches the PATH twice, once via pathComponents and once via PATH itself:
// searchInPath filters duplicates, so that will not hurt.
- const Utils::FileName path = env.searchInPath(compilerPath.fileName(), pathComponents);
+ const Utils::FilePath path = env.searchInPath(compilerPath.fileName(), pathComponents);
return path.isEmpty() ? compilerPath : path;
}
@@ -375,11 +369,11 @@ ToolChain::MacroInspectionRunner GccToolChain::createMacroInspectionRunner() con
// Using a clean environment breaks ccache/distcc/etc.
Environment env = Environment::systemEnvironment();
addToEnvironment(env);
- const Utils::FileName compilerCommand = m_compilerCommand;
+ const Utils::FilePath compilerCommand = m_compilerCommand;
const QStringList platformCodeGenFlags = m_platformCodeGenFlags;
OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter;
QTC_CHECK(reinterpretOptions);
- std::shared_ptr<Cache<MacroInspectionReport, 64>> macroCache = m_predefinedMacrosCache;
+ MacrosCache macroCache = predefinedMacrosCache();
Core::Id lang = language();
// This runner must be thread-safe!
@@ -566,63 +560,92 @@ void GccToolChain::initExtraHeaderPathsFunction(ExtraHeaderPathsFunction &&extra
m_extraHeaderPathsFunction = std::move(extraHeaderPathsFunction);
}
+HeaderPaths GccToolChain::builtInHeaderPaths(const Utils::Environment &env,
+ const Utils::FilePath &compilerCommand,
+ const QStringList &platformCodeGenFlags,
+ OptionsReinterpreter reinterpretOptions,
+ HeaderPathsCache headerCache,
+ Core::Id languageId,
+ ExtraHeaderPathsFunction extraHeaderPathsFunction,
+ const QStringList &flags,
+ const QString &sysRoot,
+ const QString &originalTargetTriple)
+{
+ QStringList arguments = gccPrepareArguments(flags,
+ sysRoot,
+ platformCodeGenFlags,
+ languageId,
+ reinterpretOptions);
+
+ // Must be clang case only.
+ if (!originalTargetTriple.isEmpty())
+ arguments << "-target" << originalTargetTriple;
+
+ const Utils::optional<HeaderPaths> cachedPaths = headerCache->check(arguments);
+ if (cachedPaths)
+ return cachedPaths.value();
+
+ HeaderPaths paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env),
+ arguments,
+ env.toStringList());
+ extraHeaderPathsFunction(paths);
+ headerCache->insert(arguments, paths);
+
+ qCDebug(gccLog) << "Reporting header paths to code model:";
+ for (const HeaderPath &hp : paths) {
+ qCDebug(gccLog) << compilerCommand.toUserOutput()
+ << (languageId == Constants::CXX_LANGUAGE_ID ? ": C++ [" : ": C [")
+ << arguments.join(", ") << "]" << hp.path;
+ }
+
+ return paths;
+}
+
ToolChain::BuiltInHeaderPathsRunner GccToolChain::createBuiltInHeaderPathsRunner() const
{
// Using a clean environment breaks ccache/distcc/etc.
Environment env = Environment::systemEnvironment();
addToEnvironment(env);
- const Utils::FileName compilerCommand = m_compilerCommand;
- const QStringList platformCodeGenFlags = m_platformCodeGenFlags;
- OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter;
- QTC_CHECK(reinterpretOptions);
- std::shared_ptr<Cache<HeaderPaths>> headerCache = m_headerPathsCache;
- Core::Id languageId = language();
-
// This runner must be thread-safe!
- return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache, languageId,
- extraHeaderPathsFunction = m_extraHeaderPathsFunction]
- (const QStringList &flags, const QString &sysRoot) {
-
- QStringList arguments = gccPrepareArguments(flags, sysRoot, platformCodeGenFlags,
- languageId, reinterpretOptions);
-
- const Utils::optional<HeaderPaths> cachedPaths = headerCache->check(arguments);
- if (cachedPaths)
- return cachedPaths.value();
-
- HeaderPaths paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env),
- arguments, env.toStringList());
- extraHeaderPathsFunction(paths);
- headerCache->insert(arguments, paths);
-
- qCDebug(gccLog) << "Reporting header paths to code model:";
- for (const HeaderPath &hp : paths) {
- qCDebug(gccLog) << compilerCommand.toUserOutput()
- << (languageId == Constants::CXX_LANGUAGE_ID ? ": C++ [" : ": C [")
- << arguments.join(", ") << "]"
- << hp.path;
- }
-
- return paths;
+ return [env,
+ compilerCommand = m_compilerCommand,
+ platformCodeGenFlags = m_platformCodeGenFlags,
+ reinterpretOptions = m_optionsReinterpreter,
+ headerCache = headerPathsCache(),
+ languageId = language(),
+ extraHeaderPathsFunction = m_extraHeaderPathsFunction](const QStringList &flags,
+ const QString &sysRoot,
+ const QString &) {
+ return builtInHeaderPaths(env,
+ compilerCommand,
+ platformCodeGenFlags,
+ reinterpretOptions,
+ headerCache,
+ languageId,
+ extraHeaderPathsFunction,
+ flags,
+ sysRoot,
+ /*target=*/""); // Target must be empty for gcc.
};
}
HeaderPaths GccToolChain::builtInHeaderPaths(const QStringList &flags,
- const FileName &sysRoot) const
+ const FilePath &sysRootPath) const
{
- return createBuiltInHeaderPathsRunner()(flags, sysRoot.toString());
+ return createBuiltInHeaderPathsRunner()(flags,
+ sysRootPath.isEmpty() ? sysRoot()
+ : sysRootPath.toString(),
+ originalTargetTriple());
}
-void GccToolChain::addCommandPathToEnvironment(const FileName &command, Environment &env)
+void GccToolChain::addCommandPathToEnvironment(const FilePath &command, Environment &env)
{
- const Utils::FileName compilerDir = command.parentDir();
+ const Utils::FilePath compilerDir = command.parentDir();
if (!compilerDir.isEmpty())
env.prependOrSetPath(compilerDir.toString());
}
-GccToolChain::GccToolChain(const GccToolChain &) = default;
-
void GccToolChain::addToEnvironment(Environment &env) const
{
// On Windows gcc invokes cc1plus which is in libexec directory.
@@ -631,50 +654,48 @@ void GccToolChain::addToEnvironment(Environment &env) const
addCommandPathToEnvironment(m_compilerCommand, env);
}
-FileNameList GccToolChain::suggestedMkspecList() const
+QStringList GccToolChain::suggestedMkspecList() const
{
- Abi abi = targetAbi();
- Abi host = Abi::hostAbi();
+ const Abi abi = targetAbi();
+ const Abi host = Abi::hostAbi();
// Cross compile: Leave the mkspec alone!
if (abi.architecture() != host.architecture()
|| abi.os() != host.os()
|| abi.osFlavor() != host.osFlavor()) // Note: This can fail:-(
- return FileNameList();
+ return {};
if (abi.os() == Abi::DarwinOS) {
QString v = version();
// prefer versioned g++ on macOS. This is required to enable building for older macOS versions
if (v.startsWith("4.0") && m_compilerCommand.endsWith("-4.0"))
- return FileNameList() << FileName::fromLatin1("macx-g++40");
+ return {"macx-g++40"};
if (v.startsWith("4.2") && m_compilerCommand.endsWith("-4.2"))
- return FileNameList() << FileName::fromLatin1("macx-g++42");
- return FileNameList() << FileName::fromLatin1("macx-g++");
+ return {"macx-g++42"};
+ return {"macx-g++"};
}
if (abi.os() == Abi::LinuxOS) {
if (abi.osFlavor() != Abi::GenericFlavor)
- return FileNameList(); // most likely not a desktop, so leave the mkspec alone.
+ return {}; // most likely not a desktop, so leave the mkspec alone.
if (abi.wordWidth() == host.wordWidth()) {
// no need to explicitly set the word width, but provide that mkspec anyway to make sure
// that the correct compiler is picked if a mkspec with a wordwidth is given.
- return FileNameList() << FileName::fromLatin1("linux-g++")
- << FileName::fromString(QString::fromLatin1("linux-g++-") + QString::number(m_targetAbi.wordWidth()));
+ return {"linux-g++", "linux-g++-" + QString::number(m_targetAbi.wordWidth())};
}
- return FileNameList() << FileName::fromString(QString::fromLatin1("linux-g++-") + QString::number(m_targetAbi.wordWidth()));
+ return {"linux-g++-" + QString::number(m_targetAbi.wordWidth())};
}
if (abi.os() == Abi::BsdOS && abi.osFlavor() == Abi::FreeBsdFlavor)
- return FileNameList() << FileName::fromLatin1("freebsd-g++");
+ return {"freebsd-g++"};
- return FileNameList();
+ return {};
}
-QString GccToolChain::makeCommand(const Environment &environment) const
+FilePath GccToolChain::makeCommand(const Environment &environment) const
{
- QString make = "make";
- FileName tmp = environment.searchInPath(make);
- return tmp.isEmpty() ? make : tmp.toString();
+ const FilePath tmp = environment.searchInPath("make");
+ return tmp.isEmpty() ? FilePath::fromString("make") : tmp;
}
IOutputParser *GccToolChain::outputParser() const
@@ -682,7 +703,7 @@ IOutputParser *GccToolChain::outputParser() const
return new GccParser;
}
-void GccToolChain::resetToolChain(const FileName &path)
+void GccToolChain::resetToolChain(const FilePath &path)
{
bool resetDisplayName = (displayName() == defaultDisplayName());
@@ -707,7 +728,7 @@ void GccToolChain::resetToolChain(const FileName &path)
toolChainUpdated();
}
-FileName GccToolChain::compilerCommand() const
+FilePath GccToolChain::compilerCommand() const
{
return m_compilerCommand;
}
@@ -751,11 +772,6 @@ QStringList GccToolChain::platformLinkerFlags() const
return m_platformLinkerFlags;
}
-ToolChain *GccToolChain::clone() const
-{
- return new GccToolChain(*this);
-}
-
QVariantMap GccToolChain::toMap() const
{
QVariantMap data = ToolChain::toMap();
@@ -764,8 +780,7 @@ QVariantMap GccToolChain::toMap() const
data.insert(compilerPlatformLinkerFlagsKeyC, m_platformLinkerFlags);
data.insert(targetAbiKeyC, m_targetAbi.toString());
data.insert(originalTargetTripleKeyC, m_originalTargetTriple);
- QStringList abiList = Utils::transform(m_supportedAbis, &Abi::toString);
- data.insert(supportedAbisKeyC, abiList);
+ data.insert(supportedAbisKeyC, Utils::transform<QStringList>(m_supportedAbis, &Abi::toString));
return data;
}
@@ -774,7 +789,7 @@ bool GccToolChain::fromMap(const QVariantMap &data)
if (!ToolChain::fromMap(data))
return false;
- m_compilerCommand = FileName::fromString(data.value(compilerCommandKeyC).toString());
+ m_compilerCommand = FilePath::fromString(data.value(compilerCommandKeyC).toString());
m_platformCodeGenFlags = data.value(compilerPlatformCodeGenFlagsKeyC).toStringList();
m_platformLinkerFlags = data.value(compilerPlatformLinkerFlagsKeyC).toStringList();
const QString targetAbiString = data.value(targetAbiKeyC).toString();
@@ -850,168 +865,154 @@ QString GccToolChain::detectVersion() const
GccToolChainFactory::GccToolChainFactory()
{
setDisplayName(tr("GCC"));
-}
-
-QSet<Core::Id> GccToolChainFactory::supportedLanguages() const
-{
- return {Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID};
-}
-
-bool GccToolChainFactory::canCreate()
-{
- return true;
-}
-
-ToolChain *GccToolChainFactory::create(Core::Id language)
-{
- ToolChain *tc = createToolChain(false);
- tc->setLanguage(language);
- return tc;
-}
-
-void GccToolChainFactory::versionProbe(const QString &name, Core::Id language, Core::Id type,
- QList<ToolChain *> &tcs, QList<ToolChain *> &known,
- const QSet<QString> &filteredNames)
-{
- if (!HostOsInfo::isLinuxHost())
- return;
- const QRegularExpression regexp(binaryRegexp);
- for (const QString &dir : QStringList({ "/usr/bin", "/usr/local/bin" })) {
- QDir binDir(dir);
- for (const QString &entry : binDir.entryList(
- {"*-" + name, name + "-*", "*-" + name + "-*"},
- QDir::Files | QDir::Executable)) {
- const QString fileName = FileName::fromString(entry).fileName();
- if (filteredNames.contains(fileName))
- continue;
- const QRegularExpressionMatch match = regexp.match(fileName);
- if (!match.hasMatch())
- continue;
- const bool isNative = fileName.startsWith(name);
- const Abi abi = isNative ? Abi::hostAbi() : Abi();
- tcs.append(autoDetectToolchains(compilerPathFromEnvironment(entry), abi, language, type,
- known));
- known.append(tcs);
- }
- }
+ setSupportedToolChainType(Constants::GCC_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID});
+ setToolchainConstructor([] { return new GccToolChain; });
+ setUserCreatable(true);
}
QList<ToolChain *> GccToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{
QList<ToolChain *> tcs;
QList<ToolChain *> known = alreadyKnown;
- tcs.append(autoDetectToolchains(compilerPathFromEnvironment("g++"), Abi::hostAbi(),
- Constants::CXX_LANGUAGE_ID, Constants::GCC_TOOLCHAIN_TYPEID,
- alreadyKnown));
- tcs.append(autoDetectToolchains(compilerPathFromEnvironment("gcc"), Abi::hostAbi(),
- Constants::C_LANGUAGE_ID, Constants::GCC_TOOLCHAIN_TYPEID,
- alreadyKnown));
- known.append(tcs);
- versionProbe("g++", Constants::CXX_LANGUAGE_ID, Constants::GCC_TOOLCHAIN_TYPEID, tcs, known);
- versionProbe("gcc", Constants::C_LANGUAGE_ID, Constants::GCC_TOOLCHAIN_TYPEID, tcs, known,
- {"c89-gcc", "c99-gcc"});
-
+ static const auto tcChecker = [](const ToolChain *tc) {
+ return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor
+ && tc->compilerCommand().fileName() != "c89-gcc"
+ && tc->compilerCommand().fileName() != "c99-gcc";
+ };
+ tcs.append(autoDetectToolchains("g++", DetectVariants::Yes, Constants::CXX_LANGUAGE_ID,
+ Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown, tcChecker));
+ tcs.append(autoDetectToolchains("gcc", DetectVariants::Yes, Constants::C_LANGUAGE_ID,
+ Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown, tcChecker));
return tcs;
}
-QList<ToolChain *> GccToolChainFactory::autoDetect(const FileName &compilerPath, const Core::Id &language)
+QList<ToolChain *> GccToolChainFactory::autoDetect(const FilePath &compilerPath, const Core::Id &language)
{
const QString fileName = compilerPath.fileName();
if ((language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|| fileName.endsWith("gcc")))
|| (language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
|| fileName.endsWith("g++"))))
- return autoDetectToolChain(compilerPath, language);
+ return autoDetectToolChain(compilerPath, language, [](const ToolChain *tc) {
+ return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor;
+ });
return QList<ToolChain *>();
}
-// Used by the ToolChainManager to restore user-generated tool chains
-bool GccToolChainFactory::canRestore(const QVariantMap &data)
-{
- return typeIdFromMap(data) == Constants::GCC_TOOLCHAIN_TYPEID;
-}
-
-ToolChain *GccToolChainFactory::restore(const QVariantMap &data)
-{
- GccToolChain *tc = createToolChain(false);
- if (tc->fromMap(data))
- return tc;
-
- delete tc;
- return nullptr;
-}
-
-GccToolChain *GccToolChainFactory::createToolChain(bool autoDetect)
-{
- return new GccToolChain(autoDetect ? ToolChain::AutoDetection : ToolChain::ManualDetection);
-}
-
-Utils::FileName GccToolChainFactory::compilerPathFromEnvironment(const QString &compilerName)
-{
- Environment systemEnvironment = Environment::systemEnvironment();
- return systemEnvironment.searchInPath(compilerName);
-}
-
-QList<ToolChain *> GccToolChainFactory::autoDetectToolchains(const FileName &compilerPath,
- const Abi &requiredAbi,
- Core::Id language,
- const Core::Id requiredTypeId,
- const QList<ToolChain *> &alreadyKnown)
+QList<ToolChain *> GccToolChainFactory::autoDetectToolchains(
+ const QString &compilerName, DetectVariants detectVariants, Core::Id language,
+ const Core::Id requiredTypeId, const QList<ToolChain *> &alreadyKnown,
+ const ToolchainChecker &checker)
{
- QList<ToolChain *> result;
-
- if (compilerPath.isEmpty())
- return result;
+ FilePathList compilerPaths;
+ QFileInfo fi(compilerName);
+ if (fi.isAbsolute()) {
+ if (fi.isFile())
+ compilerPaths << FilePath::fromString(compilerName);
+ } else {
+ const FilePathList searchPaths = Environment::systemEnvironment().path();
+ for (const FilePath &dir : searchPaths) {
+ static const QRegularExpression regexp(binaryRegexp);
+ QDir binDir(dir.toString());
+ QStringList nameFilters(compilerName);
+ if (detectVariants == DetectVariants::Yes) {
+ nameFilters
+ << compilerName + "-[1-9]*" // "clang-8", "gcc-5"
+ << ("*-*-*-" + compilerName) // "arm-none-eabi-gcc"
+ << ("*-*-*-" + compilerName + "-[1-9]*") // "arm-none-eabi-gcc-9.1.0"
+ << ("*-*-*-*-" + compilerName) // "x86_64-pc-linux-gnu-gcc"
+ << ("*-*-*-*-" + compilerName
+ + "-[1-9]*"); // "x86_64-pc-linux-gnu-gcc-7.4.1"
+ }
+ nameFilters = transform(nameFilters, [](const QString &baseName) {
+ return HostOsInfo::withExecutableSuffix(baseName);
+ });
+ const QStringList fileNames = binDir.entryList(nameFilters,
+ QDir::Files | QDir::Executable);
+ for (const QString &fileName : fileNames) {
+ if (fileName != compilerName &&
+ !regexp.match(QFileInfo(fileName).completeBaseName()).hasMatch()) {
+ continue;
+ }
+ compilerPaths << FilePath::fromString(binDir.filePath(fileName));
+ }
+ }
+ }
- result = Utils::filtered(alreadyKnown, [=](ToolChain *tc) {
- return tc->typeId() == requiredTypeId && tc->compilerCommand() == compilerPath
- && tc->language() == language;
+ QList<ToolChain *> existingCandidates
+ = filtered(alreadyKnown, [requiredTypeId, language, &checker](const ToolChain *tc) {
+ if (tc->typeId() != requiredTypeId)
+ return false;
+ if (tc->language() != language)
+ return false;
+ if (checker && !checker(tc))
+ return false;
+ return true;
});
- if (!result.isEmpty()) {
- for (ToolChain *tc : result) {
- if (tc->isAutoDetected())
- tc->setLanguage(language);
+ QList<ToolChain *> result;
+ for (const FilePath &compilerPath : compilerPaths) {
+ bool alreadyExists = false;
+ for (ToolChain * const existingTc : existingCandidates) {
+ // We have a match if the existing toolchain ultimately refers to the same file
+ // as the candidate path, either directly or via a hard or soft link.
+ // Exceptions:
+ // - clang++ is often a soft link to clang, but behaves differently.
+ // - ccache and icecc also create soft links that must not be followed here.
+ bool existingTcMatches = false;
+ const FilePath existingCommand = existingTc->compilerCommand();
+ if ((requiredTypeId == Constants::CLANG_TOOLCHAIN_TYPEID
+ && language == Constants::CXX_LANGUAGE_ID
+ && !existingCommand.fileName().contains("clang++"))
+ || compilerPath.toString().contains("icecc")
+ || compilerPath.toString().contains("ccache")) {
+ existingTcMatches = existingCommand == compilerPath;
+ } else {
+ existingTcMatches = Environment::systemEnvironment().isSameExecutable(
+ existingCommand.toString(), compilerPath.toString())
+ || (HostOsInfo::isWindowsHost() && existingCommand.toFileInfo().size()
+ == compilerPath.toFileInfo().size());
+ }
+ if (existingTcMatches) {
+ if (!result.contains(existingTc))
+ result << existingTc;
+ alreadyExists = true;
+ }
+ }
+ if (!alreadyExists) {
+ const QList<ToolChain *> newToolchains = autoDetectToolChain(compilerPath, language,
+ checker);
+ result << newToolchains;
+ existingCandidates << newToolchains;
}
- return result;
}
- result = autoDetectToolChain(compilerPath, language, requiredAbi);
-
return result;
}
-QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &compilerPath,
+QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FilePath &compilerPath,
const Core::Id language,
- const Abi &requiredAbi)
+ const ToolchainChecker &checker)
{
QList<ToolChain *> result;
Environment systemEnvironment = Environment::systemEnvironment();
GccToolChain::addCommandPathToEnvironment(compilerPath, systemEnvironment);
- const FileName localCompilerPath = findLocalCompiler(compilerPath, systemEnvironment);
+ const FilePath localCompilerPath = findLocalCompiler(compilerPath, systemEnvironment);
Macros macros
= gccPredefinedMacros(localCompilerPath, gccPredefinedMacrosOptions(language),
systemEnvironment.toStringList());
const GccToolChain::DetectedAbisResult detectedAbis = guessGccAbi(localCompilerPath,
systemEnvironment.toStringList(),
macros);
-
- const QList<Abi> abiList = detectedAbis.supportedAbis;
- if (!requiredAbi.isNull() && !abiList.contains(requiredAbi)) {
- if (requiredAbi.wordWidth() != 64
- || !abiList.contains(Abi(requiredAbi.architecture(), requiredAbi.os(), requiredAbi.osFlavor(),
- requiredAbi.binaryFormat(), 32))) {
- return result;
- }
- }
-
- for (const Abi &abi : abiList) {
- std::unique_ptr<GccToolChain> tc(createToolChain(true));
+ for (const Abi &abi : detectedAbis.supportedAbis) {
+ std::unique_ptr<GccToolChain> tc(dynamic_cast<GccToolChain *>(create()));
if (!tc)
return result;
tc->setLanguage(language);
- tc->m_predefinedMacrosCache
+ tc->setDetection(ToolChain::AutoDetection);
+ tc->predefinedMacrosCache()
->insert(QStringList(),
ToolChain::MacroInspectionReport{macros,
ToolChain::languageVersion(language, macros)});
@@ -1020,8 +1021,8 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &comp
tc->setTargetAbi(abi);
tc->setOriginalTargetTriple(detectedAbis.originalTargetTriple);
tc->setDisplayName(tc->defaultDisplayName()); // reset displayname
-
- result.append(tc.release());
+ if (!checker || checker(tc.get()))
+ result.append(tc.release());
}
return result;
}
@@ -1085,7 +1086,7 @@ void GccToolChainConfigWidget::applyImpl()
if (m_macros.isEmpty())
return;
- tc->m_predefinedMacrosCache
+ tc->predefinedMacrosCache()
->insert(tc->platformCodeGenFlags(),
ToolChain::MacroInspectionReport{m_macros,
ToolChain::languageVersion(tc->language(),
@@ -1153,8 +1154,8 @@ void GccToolChainConfigWidget::handleCompilerCommandChange()
bool haveCompiler = false;
Abi currentAbi = m_abiWidget->currentAbi();
bool customAbi = m_abiWidget->isCustomAbi() && m_abiWidget->isEnabled();
- FileName path = m_compilerCommand->fileName();
- QList<Abi> abiList;
+ FilePath path = m_compilerCommand->fileName();
+ Abis abiList;
if (!path.isEmpty()) {
QFileInfo fi(path.toFileInfo());
@@ -1165,7 +1166,7 @@ void GccToolChainConfigWidget::handleCompilerCommandChange()
GccToolChain::addCommandPathToEnvironment(path, env);
QStringList args = gccPredefinedMacrosOptions(Constants::CXX_LANGUAGE_ID)
+ splitString(m_platformCodeGenFlagsLineEdit->text());
- const FileName localCompilerPath = findLocalCompiler(path, env);
+ const FilePath localCompilerPath = findLocalCompiler(path, env);
m_macros = gccPredefinedMacros(localCompilerPath, args, env.toStringList());
abiList = guessGccAbi(localCompilerPath, env.toStringList(), m_macros,
splitString(m_platformCodeGenFlagsLineEdit->text())).supportedAbis;
@@ -1263,40 +1264,41 @@ void ClangToolChain::syncAutodetectedWithParentToolchains()
});
}
-ClangToolChain::ClangToolChain(Detection d) :
- GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, d)
+ClangToolChain::ClangToolChain() :
+ GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID)
{
syncAutodetectedWithParentToolchains();
}
-ClangToolChain::ClangToolChain(Core::Id typeId, ToolChain::Detection d) :
- GccToolChain(typeId, d)
+ClangToolChain::ClangToolChain(Core::Id typeId) :
+ GccToolChain(typeId)
{
syncAutodetectedWithParentToolchains();
}
-ClangToolChain::ClangToolChain(const ClangToolChain &other)
- : GccToolChain(other)
- , m_parentToolChainId(other.m_parentToolChainId)
-{}
+ClangToolChain::~ClangToolChain()
+{
+ QObject::disconnect(m_thisToolchainRemovedConnection);
+ QObject::disconnect(m_mingwToolchainAddedConnection);
+}
QString ClangToolChain::typeDisplayName() const
{
return ClangToolChainFactory::tr("Clang");
}
-QString ClangToolChain::makeCommand(const Environment &environment) const
+FilePath ClangToolChain::makeCommand(const Environment &environment) const
{
const QStringList makes
= HostOsInfo::isWindowsHost() ? QStringList({"mingw32-make.exe", "make.exe"}) : QStringList({"make"});
- FileName tmp;
+ FilePath tmp;
for (const QString &make : makes) {
tmp = environment.searchInPath(make);
if (!tmp.isEmpty())
- return tmp.toString();
+ return tmp;
}
- return makes.first();
+ return FilePath::fromString(makes.first());
}
/**
@@ -1323,23 +1325,16 @@ WarningFlags ClangToolChain::warningFlags(const QStringList &cflags) const
return flags;
}
-FileNameList ClangToolChain::suggestedMkspecList() const
+QStringList ClangToolChain::suggestedMkspecList() const
{
- Abi abi = targetAbi();
- if (abi.os() == Abi::DarwinOS) {
- return FileNameList()
- << FileName::fromLatin1("macx-clang")
- << FileName::fromLatin1("macx-clang-32")
- << FileName::fromLatin1("unsupported/macx-clang")
- << FileName::fromLatin1("macx-ios-clang");
- } else if (abi.os() == Abi::LinuxOS) {
- return FileNameList()
- << FileName::fromLatin1("linux-clang")
- << FileName::fromLatin1("unsupported/linux-clang");
- } else if (abi.os() == Abi::WindowsOS) {
- return FileNameList() << FileName::fromLatin1("win32-clang-g++");
- }
- return FileNameList(); // Note: Not supported by Qt yet, so default to the mkspec the Qt was build with
+ const Abi abi = targetAbi();
+ if (abi.os() == Abi::DarwinOS)
+ return {"macx-clang", "macx-clang-32", "unsupported/macx-clang", "macx-ios-clang"};
+ if (abi.os() == Abi::LinuxOS)
+ return {"linux-clang", "unsupported/linux-clang"};
+ if (abi.os() == Abi::WindowsOS)
+ return {"win32-clang-g++"};
+ return {}; // Note: Not supported by Qt yet, so default to the mkspec the Qt was build with
}
void ClangToolChain::addToEnvironment(Environment &env) const
@@ -1372,10 +1367,39 @@ QString ClangToolChain::sysRoot() const
if (!parentTC)
return QString();
- const FileName mingwCompiler = parentTC->compilerCommand();
+ const FilePath mingwCompiler = parentTC->compilerCommand();
return mingwCompiler.parentDir().parentDir().toString();
}
+ToolChain::BuiltInHeaderPathsRunner ClangToolChain::createBuiltInHeaderPathsRunner() const
+{
+ // Using a clean environment breaks ccache/distcc/etc.
+ Environment env = Environment::systemEnvironment();
+ addToEnvironment(env);
+
+ // This runner must be thread-safe!
+ return [env,
+ compilerCommand = m_compilerCommand,
+ platformCodeGenFlags = m_platformCodeGenFlags,
+ reinterpretOptions = m_optionsReinterpreter,
+ headerCache = headerPathsCache(),
+ languageId = language(),
+ extraHeaderPathsFunction = m_extraHeaderPathsFunction](const QStringList &flags,
+ const QString &sysRoot,
+ const QString &target) {
+ return builtInHeaderPaths(env,
+ compilerCommand,
+ platformCodeGenFlags,
+ reinterpretOptions,
+ headerCache,
+ languageId,
+ extraHeaderPathsFunction,
+ flags,
+ sysRoot,
+ target);
+ };
+}
+
std::unique_ptr<ToolChainConfigWidget> ClangToolChain::createConfigurationWidget()
{
return std::make_unique<ClangToolChainConfigWidget>(this);
@@ -1408,11 +1432,6 @@ IOutputParser *ClangToolChain::outputParser() const
return new ClangParser;
}
-ToolChain *ClangToolChain::clone() const
-{
- return new ClangToolChain(*this);
-}
-
// --------------------------------------------------------------------------
// ClangToolChainFactory
// --------------------------------------------------------------------------
@@ -1420,12 +1439,9 @@ ToolChain *ClangToolChain::clone() const
ClangToolChainFactory::ClangToolChainFactory()
{
setDisplayName(tr("Clang"));
-}
-
-QSet<Core::Id> ClangToolChainFactory::supportedLanguages() const
-{
- return {Constants::CXX_LANGUAGE_ID,
- Constants::C_LANGUAGE_ID};
+ setSupportedToolChainType(Constants::CLANG_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
+ setToolchainConstructor([] { return new ClangToolChain; });
}
QList<ToolChain *> ClangToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
@@ -1433,33 +1449,25 @@ QList<ToolChain *> ClangToolChainFactory::autoDetect(const QList<ToolChain *> &a
QList<ToolChain *> tcs;
QList<ToolChain *> known = alreadyKnown;
- const Abi hostAbi = Abi::hostAbi();
- tcs.append(autoDetectToolchains(compilerPathFromEnvironment("clang++"), hostAbi,
- Constants::CXX_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID,
- alreadyKnown));
- tcs.append(autoDetectToolchains(compilerPathFromEnvironment("clang"), hostAbi,
- Constants::C_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID,
- alreadyKnown));
+ tcs.append(autoDetectToolchains("clang++", DetectVariants::Yes, Constants::CXX_LANGUAGE_ID,
+ Constants::CLANG_TOOLCHAIN_TYPEID, alreadyKnown));
+ tcs.append(autoDetectToolchains("clang", DetectVariants::Yes, Constants::C_LANGUAGE_ID,
+ Constants::CLANG_TOOLCHAIN_TYPEID, alreadyKnown));
known.append(tcs);
- versionProbe("clang++", Constants::CXX_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID, tcs, known);
- versionProbe("clang", Constants::C_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID, tcs, known);
- const FileName compilerPath = FileName::fromString(Core::ICore::clangExecutable(CLANG_BINDIR));
+ const FilePath compilerPath = FilePath::fromString(Core::ICore::clangExecutable(CLANG_BINDIR));
if (!compilerPath.isEmpty()) {
- const FileName clang = compilerPath.parentDir().appendPath(
+ const FilePath clang = compilerPath.parentDir().pathAppended(
HostOsInfo::withExecutableSuffix("clang"));
- tcs.append(autoDetectToolchains(clang,
- hostAbi, Constants::CXX_LANGUAGE_ID,
- Constants::CLANG_TOOLCHAIN_TYPEID, alreadyKnown));
- tcs.append(autoDetectToolchains(clang,
- hostAbi, Constants::C_LANGUAGE_ID,
- Constants::CLANG_TOOLCHAIN_TYPEID, alreadyKnown));
+ tcs.append(autoDetectToolchains(clang.toString(), DetectVariants::No,
+ Constants::C_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID,
+ tcs));
}
return tcs;
}
-QList<ToolChain *> ClangToolChainFactory::autoDetect(const FileName &compilerPath, const Core::Id &language)
+QList<ToolChain *> ClangToolChainFactory::autoDetect(const FilePath &compilerPath, const Core::Id &language)
{
const QString fileName = compilerPath.fileName();
if ((language == Constants::C_LANGUAGE_ID && fileName.startsWith("clang") && !fileName.startsWith("clang++"))
@@ -1468,16 +1476,6 @@ QList<ToolChain *> ClangToolChainFactory::autoDetect(const FileName &compilerPat
return QList<ToolChain *>();
}
-bool ClangToolChainFactory::canRestore(const QVariantMap &data)
-{
- return typeIdFromMap(data) == Constants::CLANG_TOOLCHAIN_TYPEID;
-}
-
-GccToolChain *ClangToolChainFactory::createToolChain(bool autoDetect)
-{
- return new ClangToolChain(autoDetect ? ToolChain::AutoDetection : ToolChain::ManualDetection);
-}
-
ClangToolChainConfigWidget::ClangToolChainConfigWidget(ClangToolChain *tc) :
GccToolChainConfigWidget(tc)
{
@@ -1594,8 +1592,8 @@ void ClangToolChainConfigWidget::makeReadOnlyImpl()
// MingwToolChain
// --------------------------------------------------------------------------
-MingwToolChain::MingwToolChain(Detection d) :
- GccToolChain(Constants::MINGW_TOOLCHAIN_TYPEID, d)
+MingwToolChain::MingwToolChain() :
+ GccToolChain(Constants::MINGW_TOOLCHAIN_TYPEID)
{ }
QString MingwToolChain::typeDisplayName() const
@@ -1603,40 +1601,30 @@ QString MingwToolChain::typeDisplayName() const
return MingwToolChainFactory::tr("MinGW");
}
-FileNameList MingwToolChain::suggestedMkspecList() const
+QStringList MingwToolChain::suggestedMkspecList() const
{
if (HostOsInfo::isWindowsHost())
- return FileNameList() << FileName::fromLatin1("win32-g++");
+ return {"win32-g++"};
if (HostOsInfo::isLinuxHost()) {
if (version().startsWith("4.6."))
- return FileNameList()
- << FileName::fromLatin1("win32-g++-4.6-cross")
- << FileName::fromLatin1("unsupported/win32-g++-4.6-cross");
- else
- return FileNameList()
- << FileName::fromLatin1("win32-g++-cross")
- << FileName::fromLatin1("unsupported/win32-g++-cross");
+ return {"win32-g++-4.6-cross", "unsupported/win32-g++-4.6-cross"};
+ return {"win32-g++-cross", "unsupported/win32-g++-cross"};
}
- return FileNameList();
+ return {};
}
-QString MingwToolChain::makeCommand(const Environment &environment) const
+FilePath MingwToolChain::makeCommand(const Environment &environment) const
{
const QStringList makes
= HostOsInfo::isWindowsHost() ? QStringList({"mingw32-make.exe", "make.exe"}) : QStringList({"make"});
- FileName tmp;
+ FilePath tmp;
foreach (const QString &make, makes) {
tmp = environment.searchInPath(make);
if (!tmp.isEmpty())
- return tmp.toString();
+ return tmp;
}
- return makes.first();
-}
-
-ToolChain *MingwToolChain::clone() const
-{
- return new MingwToolChain(*this);
+ return FilePath::fromString(makes.first());
}
// --------------------------------------------------------------------------
@@ -1646,56 +1634,45 @@ ToolChain *MingwToolChain::clone() const
MingwToolChainFactory::MingwToolChainFactory()
{
setDisplayName(tr("MinGW"));
-}
-
-QSet<Core::Id> MingwToolChainFactory::supportedLanguages() const
-{
- return {Constants::CXX_LANGUAGE_ID,
- Constants::C_LANGUAGE_ID};
+ setSupportedToolChainType(Constants::MINGW_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
+ setToolchainConstructor([] { return new MingwToolChain; });
}
QList<ToolChain *> MingwToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{
Abi ha = Abi::hostAbi();
ha = Abi(ha.architecture(), Abi::WindowsOS, Abi::WindowsMSysFlavor, Abi::PEFormat, ha.wordWidth());
+ static const auto tcChecker = [](const ToolChain *tc) {
+ return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
+ };
QList<ToolChain *> result = autoDetectToolchains(
- compilerPathFromEnvironment("g++"), ha, Constants::CXX_LANGUAGE_ID,
- Constants::MINGW_TOOLCHAIN_TYPEID, alreadyKnown);
- result += autoDetectToolchains(
- compilerPathFromEnvironment("gcc"), ha, Constants::C_LANGUAGE_ID,
- Constants::MINGW_TOOLCHAIN_TYPEID, alreadyKnown);
+ "g++", DetectVariants::Yes, Constants::CXX_LANGUAGE_ID,
+ Constants::MINGW_TOOLCHAIN_TYPEID, alreadyKnown, tcChecker);
+ result += autoDetectToolchains("gcc", DetectVariants::Yes, Constants::C_LANGUAGE_ID,
+ Constants::MINGW_TOOLCHAIN_TYPEID, alreadyKnown, tcChecker);
return result;
}
-QList<ToolChain *> MingwToolChainFactory::autoDetect(const FileName &compilerPath, const Core::Id &language)
+QList<ToolChain *> MingwToolChainFactory::autoDetect(const FilePath &compilerPath, const Core::Id &language)
{
- Abi ha = Abi::hostAbi();
- ha = Abi(ha.architecture(), Abi::WindowsOS, Abi::WindowsMSysFlavor, Abi::PEFormat, ha.wordWidth());
const QString fileName = compilerPath.fileName();
if ((language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|| fileName.endsWith("gcc")))
|| (language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
|| fileName.endsWith("g++"))))
- return autoDetectToolChain(compilerPath, language, ha);
+ return autoDetectToolChain(compilerPath, language, [](const ToolChain *tc) {
+ return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
+ });
return QList<ToolChain *>();
}
-bool MingwToolChainFactory::canRestore(const QVariantMap &data)
-{
- return typeIdFromMap(data) == Constants::MINGW_TOOLCHAIN_TYPEID;
-}
-
-GccToolChain *MingwToolChainFactory::createToolChain(bool autoDetect)
-{
- return new MingwToolChain(autoDetect ? ToolChain::AutoDetection : ToolChain::ManualDetection);
-}
-
// --------------------------------------------------------------------------
// LinuxIccToolChain
// --------------------------------------------------------------------------
-LinuxIccToolChain::LinuxIccToolChain(Detection d) :
- GccToolChain(Constants::LINUXICC_TOOLCHAIN_TYPEID, d)
+LinuxIccToolChain::LinuxIccToolChain() :
+ GccToolChain(Constants::LINUXICC_TOOLCHAIN_TYPEID)
{ }
QString LinuxIccToolChain::typeDisplayName() const
@@ -1730,15 +1707,9 @@ IOutputParser *LinuxIccToolChain::outputParser() const
return new LinuxIccParser;
}
-FileNameList LinuxIccToolChain::suggestedMkspecList() const
+QStringList LinuxIccToolChain::suggestedMkspecList() const
{
- return FileNameList()
- << FileName::fromString(QString::fromLatin1("linux-icc-") + QString::number(targetAbi().wordWidth()));
-}
-
-ToolChain *LinuxIccToolChain::clone() const
-{
- return new LinuxIccToolChain(*this);
+ return {QString("linux-icc-%1").arg(targetAbi().wordWidth())};
}
// --------------------------------------------------------------------------
@@ -1748,26 +1719,22 @@ ToolChain *LinuxIccToolChain::clone() const
LinuxIccToolChainFactory::LinuxIccToolChainFactory()
{
setDisplayName(tr("Linux ICC"));
-}
-
-QSet<Core::Id> LinuxIccToolChainFactory::supportedLanguages() const
-{
- return {Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID};
+ setSupportedToolChainType(Constants::LINUXICC_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
+ setToolchainConstructor([] { return new LinuxIccToolChain; });
}
QList<ToolChain *> LinuxIccToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{
QList<ToolChain *> result
- = autoDetectToolchains(compilerPathFromEnvironment("icpc"),
- Abi::hostAbi(), Constants::CXX_LANGUAGE_ID,
+ = autoDetectToolchains("icpc", DetectVariants::No, Constants::CXX_LANGUAGE_ID,
Constants::LINUXICC_TOOLCHAIN_TYPEID, alreadyKnown);
- result += autoDetectToolchains(compilerPathFromEnvironment("icc"),
- Abi::hostAbi(), Constants::C_LANGUAGE_ID,
+ result += autoDetectToolchains("icc", DetectVariants::Yes, Constants::C_LANGUAGE_ID,
Constants::LINUXICC_TOOLCHAIN_TYPEID, alreadyKnown);
return result;
}
-QList<ToolChain *> LinuxIccToolChainFactory::autoDetect(const FileName &compilerPath, const Core::Id &language)
+QList<ToolChain *> LinuxIccToolChainFactory::autoDetect(const FilePath &compilerPath, const Core::Id &language)
{
const QString fileName = compilerPath.fileName();
if ((language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) ||
@@ -1776,16 +1743,6 @@ QList<ToolChain *> LinuxIccToolChainFactory::autoDetect(const FileName &compiler
return {};
}
-bool LinuxIccToolChainFactory::canRestore(const QVariantMap &data)
-{
- return typeIdFromMap(data) == Constants::LINUXICC_TOOLCHAIN_TYPEID;
-}
-
-GccToolChain *LinuxIccToolChainFactory::createToolChain(bool autoDetect)
-{
- return new LinuxIccToolChain(autoDetect ? ToolChain::AutoDetection : ToolChain::ManualDetection);
-}
-
GccToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, WarningFlags &flags) :
m_flags(flags)
{
@@ -1873,7 +1830,7 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
QTest::newRow("Linux 3 (64bit intel)")
<< QString::fromLatin1("x86_64-linux-gnu")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\n")
- << QStringList({"x86-linux-generic-elf-64bit", "x86-linux-generic-elf-32bit"});
+ << QStringList("x86-linux-generic-elf-64bit");
QTest::newRow("Linux 3 (64bit intel -- non 64bit)")
<< QString::fromLatin1("x86_64-linux-gnu")
<< QByteArray("#define __SIZEOF_SIZE_T__ 4\n")
@@ -1885,11 +1842,11 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
QTest::newRow("Linux 5 (QTCREATORBUG-4690)") // from QTCREATORBUG-4690
<< QString::fromLatin1("x86_64-redhat-linux6E")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\n")
- << QStringList({"x86-linux-generic-elf-64bit", "x86-linux-generic-elf-32bit"});
+ << QStringList("x86-linux-generic-elf-64bit");
QTest::newRow("Linux 6 (QTCREATORBUG-4690)") // from QTCREATORBUG-4690
<< QString::fromLatin1("x86_64-redhat-linux")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\n")
- << QStringList({"x86-linux-generic-elf-64bit", "x86-linux-generic-elf-32bit"});
+ << QStringList("x86-linux-generic-elf-64bit");
QTest::newRow("Linux 7 (arm)")
<< QString::fromLatin1("armv5tl-montavista-linux-gnueabi")
<< QByteArray("#define __SIZEOF_SIZE_T__ 4\n")
@@ -1918,7 +1875,7 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
QTest::newRow("Mingw 2 (64bit)")
<< QString::fromLatin1("i686-w64-mingw32")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\r\n")
- << QStringList({"x86-windows-msys-pe-64bit", "x86-windows-msys-pe-32bit"});
+ << QStringList({"x86-windows-msys-pe-64bit"});
QTest::newRow("Mingw 3 (32 bit)")
<< QString::fromLatin1("mingw32")
<< QByteArray("#define __SIZEOF_SIZE_T__ 4\r\n")
@@ -1926,7 +1883,7 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
QTest::newRow("Cross Mingw 1 (64bit)")
<< QString::fromLatin1("amd64-mingw32msvc")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\r\n")
- << QStringList({"x86-windows-msys-pe-64bit", "x86-windows-msys-pe-32bit"});
+ << QStringList({"x86-windows-msys-pe-64bit"});
QTest::newRow("Cross Mingw 2 (32bit)")
<< QString::fromLatin1("i586-mingw32msvc")
<< QByteArray("#define __SIZEOF_SIZE_T__ 4\r\n")
@@ -1934,11 +1891,11 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
QTest::newRow("Clang 1: windows")
<< QString::fromLatin1("x86_64-pc-win32")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\r\n")
- << QStringList({"x86-windows-msys-pe-64bit", "x86-windows-msys-pe-32bit"});
+ << QStringList("x86-windows-msys-pe-64bit");
QTest::newRow("Clang 1: linux")
<< QString::fromLatin1("x86_64-unknown-linux-gnu")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\n")
- << QStringList({"x86-linux-generic-elf-64bit", "x86-linux-generic-elf-32bit"});
+ << QStringList("x86-linux-generic-elf-64bit");
QTest::newRow("Mac 1")
<< QString::fromLatin1("i686-apple-darwin10")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\n")
@@ -1958,7 +1915,7 @@ void ProjectExplorerPlugin::testGccAbiGuessing_data()
QTest::newRow("Intel 1")
<< QString::fromLatin1("86_64 x86_64 GNU/Linux")
<< QByteArray("#define __SIZEOF_SIZE_T__ 8\n")
- << QStringList({"x86-linux-generic-elf-64bit", "x86-linux-generic-elf-32bit"});
+ << QStringList("x86-linux-generic-elf-64bit");
QTest::newRow("FreeBSD 1")
<< QString::fromLatin1("i386-portbld-freebsd9.0")
<< QByteArray("#define __SIZEOF_SIZE_T__ 4\n")
@@ -1975,7 +1932,7 @@ void ProjectExplorerPlugin::testGccAbiGuessing()
QFETCH(QByteArray, macros);
QFETCH(QStringList, abiList);
- QList<Abi> al = guessGccAbi(input, ProjectExplorer::Macro::toMacros(macros));
+ const Abis al = guessGccAbi(input, ProjectExplorer::Macro::toMacros(macros));
QCOMPARE(al.count(), abiList.count());
for (int i = 0; i < al.count(); ++i)
QCOMPARE(al.at(i).toString(), abiList.at(i));
diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h
index b34614cde8..240ae34247 100644
--- a/src/plugins/projectexplorer/gcctoolchain.h
+++ b/src/plugins/projectexplorer/gcctoolchain.h
@@ -29,7 +29,6 @@
#include "projectexplorerconstants.h"
#include "toolchain.h"
-#include "toolchaincache.h"
#include "abi.h"
#include "headerpath.h"
@@ -68,12 +67,12 @@ inline const QStringList gccPredefinedMacrosOptions(Core::Id languageId)
class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain
{
public:
- GccToolChain(Core::Id typeId, Detection d);
+ GccToolChain(Core::Id typeId);
QString typeDisplayName() const override;
Abi targetAbi() const override;
QString originalTargetTriple() const override;
QString version() const;
- QList<Abi> supportedAbis() const override;
+ Abis supportedAbis() const override;
void setTargetAbi(const Abi &);
bool isValid() const override;
@@ -86,11 +85,11 @@ public:
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override;
HeaderPaths builtInHeaderPaths(const QStringList &flags,
- const Utils::FileName &sysRoot) const override;
+ const Utils::FilePath &sysRootPath) const override;
void addToEnvironment(Utils::Environment &env) const override;
- QString makeCommand(const Utils::Environment &environment) const override;
- Utils::FileNameList suggestedMkspecList() const override;
+ Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
+ QStringList suggestedMkspecList() const override;
IOutputParser *outputParser() const override;
QVariantMap toMap() const override;
@@ -100,28 +99,25 @@ public:
bool operator ==(const ToolChain &) const override;
- void resetToolChain(const Utils::FileName &);
- Utils::FileName compilerCommand() const override;
+ void resetToolChain(const Utils::FilePath &);
+ Utils::FilePath compilerCommand() const override;
void setPlatformCodeGenFlags(const QStringList &);
QStringList extraCodeModelFlags() const override;
QStringList platformCodeGenFlags() const;
void setPlatformLinkerFlags(const QStringList &);
QStringList platformLinkerFlags() const;
- ToolChain *clone() const override;
-
- static void addCommandPathToEnvironment(const Utils::FileName &command, Utils::Environment &env);
+ static void addCommandPathToEnvironment(const Utils::FilePath &command, Utils::Environment &env);
class DetectedAbisResult {
public:
DetectedAbisResult() = default;
- DetectedAbisResult(const QList<Abi> &supportedAbis,
- const QString &originalTargetTriple = QString()) :
+ DetectedAbisResult(const Abis &supportedAbis, const QString &originalTargetTriple = {}) :
supportedAbis(supportedAbis),
originalTargetTriple(originalTargetTriple)
{ }
- QList<Abi> supportedAbis;
+ Abis supportedAbis;
QString originalTargetTriple;
};
@@ -129,10 +125,8 @@ protected:
using CacheItem = QPair<QStringList, Macros>;
using GccCache = QVector<CacheItem>;
- GccToolChain(const GccToolChain &);
-
- void setCompilerCommand(const Utils::FileName &path);
- void setSupportedAbis(const QList<Abi> &m_abis);
+ void setCompilerCommand(const Utils::FilePath &path);
+ void setSupportedAbis(const Abis &abis);
void setOriginalTargetTriple(const QString &targetTriple);
void setMacroCache(const QStringList &allCxxflags, const Macros &macroCache) const;
Macros macroCache(const QStringList &allCxxflags) const;
@@ -151,7 +145,18 @@ protected:
using ExtraHeaderPathsFunction = std::function<void(HeaderPaths &)>;
void initExtraHeaderPathsFunction(ExtraHeaderPathsFunction &&extraHeaderPathsFunction) const;
- static HeaderPaths gccHeaderPaths(const Utils::FileName &gcc, const QStringList &args,
+ static HeaderPaths builtInHeaderPaths(const Utils::Environment &env,
+ const Utils::FilePath &compilerCommand,
+ const QStringList &platformCodeGenFlags,
+ OptionsReinterpreter reinterpretOptions,
+ HeaderPathsCache headerCache,
+ Core::Id languageId,
+ ExtraHeaderPathsFunction extraHeaderPathsFunction,
+ const QStringList &flags,
+ const QString &sysRoot,
+ const QString &originalTargetTriple);
+
+ static HeaderPaths gccHeaderPaths(const Utils::FilePath &gcc, const QStringList &args,
const QStringList &env);
class WarningFlagAdder
@@ -167,10 +172,9 @@ protected:
bool m_doesEnable = false;
bool m_triggered = false;
};
- void toolChainUpdated() override;
private:
- explicit GccToolChain(Detection d);
+ explicit GccToolChain();
void updateSupportedAbis() const;
static QStringList gccPrepareArguments(const QStringList &flags,
@@ -179,22 +183,21 @@ private:
Core::Id languageId,
OptionsReinterpreter reinterpretOptions);
- Utils::FileName m_compilerCommand;
+protected:
+ Utils::FilePath m_compilerCommand;
QStringList m_platformCodeGenFlags;
QStringList m_platformLinkerFlags;
OptionsReinterpreter m_optionsReinterpreter = [](const QStringList &v) { return v; };
+ mutable ExtraHeaderPathsFunction m_extraHeaderPathsFunction = [](HeaderPaths &) {};
+private:
Abi m_targetAbi;
- mutable QList<Abi> m_supportedAbis;
+ mutable Abis m_supportedAbis;
mutable QString m_originalTargetTriple;
mutable HeaderPaths m_headerPaths;
mutable QString m_version;
- mutable std::shared_ptr<Cache<MacroInspectionReport, 64>> m_predefinedMacrosCache;
- mutable std::shared_ptr<Cache<HeaderPaths>> m_headerPathsCache;
- mutable ExtraHeaderPathsFunction m_extraHeaderPathsFunction = [](HeaderPaths &) {};
-
friend class Internal::GccToolChainConfigWidget;
friend class Internal::GccToolChainFactory;
friend class ToolChainFactory;
@@ -207,25 +210,26 @@ private:
class PROJECTEXPLORER_EXPORT ClangToolChain : public GccToolChain
{
public:
- explicit ClangToolChain(Detection d);
- ClangToolChain(Core::Id typeId, Detection d);
- ClangToolChain(const ClangToolChain &other);
+ ClangToolChain();
+ explicit ClangToolChain(Core::Id typeId);
+ ~ClangToolChain() override;
+
QString typeDisplayName() const override;
- QString makeCommand(const Utils::Environment &environment) const override;
+ Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
WarningFlags warningFlags(const QStringList &cflags) const override;
IOutputParser *outputParser() const override;
- ToolChain *clone() const override;
-
- Utils::FileNameList suggestedMkspecList() const override;
+ QStringList suggestedMkspecList() const override;
void addToEnvironment(Utils::Environment &env) const override;
QString originalTargetTriple() const override;
QString sysRoot() const override;
+ BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override;
+
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
QVariantMap toMap() const override;
@@ -253,14 +257,12 @@ class PROJECTEXPLORER_EXPORT MingwToolChain : public GccToolChain
{
public:
QString typeDisplayName() const override;
- QString makeCommand(const Utils::Environment &environment) const override;
-
- ToolChain *clone() const override;
+ Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
- Utils::FileNameList suggestedMkspecList() const override;
+ QStringList suggestedMkspecList() const override;
private:
- explicit MingwToolChain(Detection d);
+ MingwToolChain();
friend class Internal::MingwToolChainFactory;
friend class ToolChainFactory;
@@ -278,12 +280,10 @@ public:
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
IOutputParser *outputParser() const override;
- ToolChain *clone() const override;
-
- Utils::FileNameList suggestedMkspecList() const override;
+ QStringList suggestedMkspecList() const override;
private:
- explicit LinuxIccToolChain(Detection d);
+ LinuxIccToolChain();
friend class Internal::LinuxIccToolChainFactory;
friend class ToolChainFactory;
diff --git a/src/plugins/projectexplorer/gcctoolchainfactories.h b/src/plugins/projectexplorer/gcctoolchainfactories.h
index 775e0db675..e33ebcaa03 100644
--- a/src/plugins/projectexplorer/gcctoolchainfactories.h
+++ b/src/plugins/projectexplorer/gcctoolchainfactories.h
@@ -33,6 +33,8 @@
#include <QList>
#include <QSet>
+#include <functional>
+
QT_BEGIN_NAMESPACE
class QComboBox;
QT_END_NAMESPACE
@@ -51,33 +53,20 @@ class GccToolChainFactory : public ToolChainFactory
public:
GccToolChainFactory();
- QSet<Core::Id> supportedLanguages() const override;
QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown) override;
- QList<ToolChain *> autoDetect(const Utils::FileName &compilerPath, const Core::Id &language) override;
-
- bool canCreate() override;
- ToolChain *create(Core::Id language) override;
-
- bool canRestore(const QVariantMap &data) override;
- ToolChain *restore(const QVariantMap &data) override;
+ QList<ToolChain *> autoDetect(const Utils::FilePath &compilerPath, const Core::Id &language) override;
protected:
- virtual GccToolChain *createToolChain(bool autoDetect);
- void versionProbe(const QString &name,
- Core::Id language,
- Core::Id type,
- QList<ToolChain *> &tcs,
- QList<ToolChain *> &known,
- const QSet<QString> &filteredNames = {});
-
- Utils::FileName compilerPathFromEnvironment(const QString &compilerName);
-
+ enum class DetectVariants { Yes, No };
+ using ToolchainChecker = std::function<bool(const ToolChain *)>;
QList<ToolChain *> autoDetectToolchains(
- const Utils::FileName &compilerPath, const Abi &requiredAbi, Core::Id language,
- const Core::Id requiredTypeId, const QList<ToolChain *> &alreadyKnown);
- QList<ToolChain *> autoDetectToolChain(const Utils::FileName &compilerPath, const Core::Id language,
- const Abi &requiredAbi = Abi());
+ const QString &compilerName, DetectVariants detectVariants, Core::Id language,
+ const Core::Id requiredTypeId, const QList<ToolChain *> &alreadyKnown,
+ const ToolchainChecker &checker = {});
+ QList<ToolChain *> autoDetectToolChain(
+ const Utils::FilePath &compilerPath, const Core::Id language,
+ const ToolchainChecker &checker = {});
};
// --------------------------------------------------------------------------
@@ -147,15 +136,9 @@ class ClangToolChainFactory : public GccToolChainFactory
public:
ClangToolChainFactory();
- QSet<Core::Id> supportedLanguages() const override;
QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown) override;
- QList<ToolChain *> autoDetect(const Utils::FileName &compilerPath, const Core::Id &language) final;
-
- bool canRestore(const QVariantMap &data) override;
-
-protected:
- GccToolChain *createToolChain(bool autoDetect) override;
+ QList<ToolChain *> autoDetect(const Utils::FilePath &compilerPath, const Core::Id &language) final;
};
// --------------------------------------------------------------------------
@@ -168,15 +151,9 @@ class MingwToolChainFactory : public GccToolChainFactory
public:
MingwToolChainFactory();
- QSet<Core::Id> supportedLanguages() const override;
QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown) override;
- QList<ToolChain *> autoDetect(const Utils::FileName &compilerPath, const Core::Id &language) final;
-
- bool canRestore(const QVariantMap &data) override;
-
-protected:
- GccToolChain *createToolChain(bool autoDetect) override;
+ QList<ToolChain *> autoDetect(const Utils::FilePath &compilerPath, const Core::Id &language) final;
};
// --------------------------------------------------------------------------
@@ -189,15 +166,9 @@ class LinuxIccToolChainFactory : public GccToolChainFactory
public:
LinuxIccToolChainFactory();
- QSet<Core::Id> supportedLanguages() const override;
QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown) override;
- QList<ToolChain *> autoDetect(const Utils::FileName &compilerPath, const Core::Id &language) final;
-
- bool canRestore(const QVariantMap &data) override;
-
-protected:
- GccToolChain *createToolChain(bool autoDetect) override;
+ QList<ToolChain *> autoDetect(const Utils::FilePath &compilerPath, const Core::Id &language) final;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/gnumakeparser.cpp b/src/plugins/projectexplorer/gnumakeparser.cpp
index 2b9c0820cc..dc14301117 100644
--- a/src/plugins/projectexplorer/gnumakeparser.cpp
+++ b/src/plugins/projectexplorer/gnumakeparser.cpp
@@ -90,6 +90,18 @@ public:
Task::TaskType type = Task::Error;
};
+static Task::TaskType taskTypeFromDescription(const QString &description)
+{
+ if (description.contains(". Stop."))
+ return Task::Error;
+ if (description.contains("not found"))
+ return Task::Error;
+ if (description.contains("No rule to make target"))
+ return Task::Error;
+ // Extend as needed.
+ return Task::Warning;
+}
+
static Result parseDescription(const QString &description)
{
Result result;
@@ -103,7 +115,7 @@ static Result parseDescription(const QString &description)
result.isFatal = true;
} else {
result.description = description;
- result.type = Task::Error;
+ result.type = taskTypeFromDescription(description);
result.isFatal = false;
}
return result;
@@ -121,7 +133,7 @@ void GnuMakeParser::stdError(const QString &line)
++m_fatalErrorCount;
if (!m_suppressIssues) {
taskAdded(Task(res.type, res.description,
- Utils::FileName::fromUserInput(match.captured(1)) /* filename */,
+ Utils::FilePath::fromUserInput(match.captured(1)) /* filename */,
match.captured(4).toInt(), /* line */
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)), 1, 0);
}
@@ -135,7 +147,7 @@ void GnuMakeParser::stdError(const QString &line)
++m_fatalErrorCount;
if (!m_suppressIssues) {
Task task = Task(res.type, res.description,
- Utils::FileName() /* filename */, -1, /* line */
+ Utils::FilePath() /* filename */, -1, /* line */
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
taskAdded(task, 1, 0);
}
@@ -169,7 +181,7 @@ void GnuMakeParser::taskAdded(const Task &task, int linkedLines, int skippedLine
QString filePath(task.file.toString());
if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) {
- QList<QFileInfo> possibleFiles;
+ QFileInfoList possibleFiles;
foreach (const QString &dir, m_directories) {
QFileInfo candidate(dir + QLatin1Char('/') + filePath);
if (candidate.exists()
@@ -178,7 +190,7 @@ void GnuMakeParser::taskAdded(const Task &task, int linkedLines, int skippedLine
}
}
if (possibleFiles.size() == 1)
- editable.file = Utils::FileName(possibleFiles.first());
+ editable.file = Utils::FilePath::fromFileInfo(possibleFiles.first());
// Let the Makestep apply additional heuristics (based on
// files in ther project) if we cannot uniquely
// identify the file!
@@ -222,7 +234,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
QTest::addColumn<QStringList>("additionalSearchDirs");
@@ -230,14 +242,14 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QStringList()
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString()
<< QStringList();
QTest::newRow("pass-through stderr")
<< QStringList()
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< QStringList();
QTest::newRow("pass-through gcc infos")
@@ -254,7 +266,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
"../../scriptbug/main.cpp: In instantiation of void bar(i) [with i = double]:\n"
"../../scriptbug/main.cpp:8: instantiated from void foo(i) [with i = double]\n"
"../../scriptbug/main.cpp:22: instantiated from here\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< QStringList();
@@ -265,7 +277,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
"make[4]: Entering directory `/home/code/build/qt/examples/opengl/grabber'")
<< OutputParserTester::STDOUT
<< QString() << QString()
- << QList<Task>()
+ << Tasks()
<< QString()
<< QStringList({"/home/code/build/qt/examples/opengl/grabber",
"/home/code/build/qt/examples/opengl/grabber", "/test/dir"});
@@ -274,7 +286,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("make[4]: Leaving directory `/home/code/build/qt/examples/opengl/grabber'")
<< OutputParserTester::STDOUT
<< QString() << QString()
- << QList<Task>()
+ << Tasks()
<< QString()
<< QStringList("/test/dir");
QTest::newRow("make error")
@@ -282,10 +294,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("make: *** No rule to make target `hello.c', needed by `hello.o'. Stop.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QString::fromLatin1("No rule to make target `hello.c', needed by `hello.o'. Stop."),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -296,10 +308,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
"make[2]: *** [sub-projectexplorer-make_default] Error 2")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QString::fromLatin1("[.obj/debug-shared/gnumakeparser.o] Error 1"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -308,10 +320,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("Makefile:360: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QString::fromLatin1("missing separator (did you mean TAB instead of 8 spaces?). Stop."),
- Utils::FileName::fromUserInput(QLatin1String("Makefile")), 360,
+ Utils::FilePath::fromUserInput(QLatin1String("Makefile")), 360,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -321,10 +333,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
"mingw32-make: *** [debug] Error 2")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QString::fromLatin1("[debug/qplotaxis.o] Error 1"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -333,10 +345,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("mingw64-make.exe[1]: *** [dynlib.inst] Error -1073741819")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QString::fromLatin1("[dynlib.inst] Error -1073741819"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -345,10 +357,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("make[2]: warning: jobserver unavailable: using -j1. Add `+' to parent make rule.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QString::fromLatin1("jobserver unavailable: using -j1. Add `+' to parent make rule."),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -357,7 +369,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("/home/dev/creator/share/qtcreator/debugger/dumper.cpp:1079: note: initialized from here")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("/home/dev/creator/share/qtcreator/debugger/dumper.cpp:1079: note: initialized from here\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< QStringList();
QTest::newRow("Full path make exe")
@@ -365,10 +377,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("C:\\Qt\\4.6.2-Symbian\\s60sdk\\epoc32\\tools\\make.exe: *** [sis] Error 2")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QString::fromLatin1("[sis] Error 2"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -377,10 +389,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("make: g++: Command not found")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QString::fromLatin1("g++: Command not found"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -389,10 +401,10 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
<< QString::fromLatin1("Makefile:794: warning: overriding commands for target `xxxx.app/Contents/Info.plist'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QString::fromLatin1("overriding commands for target `xxxx.app/Contents/Info.plist'"),
- Utils::FileName::fromString(QLatin1String("Makefile")), 794,
+ Utils::FilePath::fromString(QLatin1String("Makefile")), 794,
Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)))
<< QString()
<< QStringList();
@@ -410,7 +422,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing()
QFETCH(QStringList, extraSearchDirs);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
@@ -455,12 +467,12 @@ void ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data()
<< QStringList()
<< Task(Task::Error,
QLatin1String("no filename, no mangling"),
- Utils::FileName(),
+ Utils::FilePath(),
-1,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Error,
QLatin1String("no filename, no mangling"),
- Utils::FileName(),
+ Utils::FilePath(),
-1,
Constants::TASK_CATEGORY_COMPILE);
QTest::newRow("no mangling")
@@ -468,12 +480,12 @@ void ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data()
<< QStringList()
<< Task(Task::Error,
QLatin1String("unknown filename, no mangling"),
- Utils::FileName::fromUserInput(QLatin1String("some/path/unknown.cpp")),
+ Utils::FilePath::fromUserInput(QLatin1String("some/path/unknown.cpp")),
-1,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Error,
QLatin1String("unknown filename, no mangling"),
- Utils::FileName::fromUserInput(QLatin1String("some/path/unknown.cpp")),
+ Utils::FilePath::fromUserInput(QLatin1String("some/path/unknown.cpp")),
-1,
Constants::TASK_CATEGORY_COMPILE);
QTest::newRow("find file")
@@ -481,12 +493,12 @@ void ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data()
<< QStringList("test")
<< Task(Task::Error,
QLatin1String("mangling"),
- Utils::FileName::fromUserInput(QLatin1String("file.cpp")),
+ Utils::FilePath::fromUserInput(QLatin1String("file.cpp")),
10,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Error,
QLatin1String("mangling"),
- Utils::FileName::fromUserInput(QLatin1String("$TMPDIR/test/file.cpp")),
+ Utils::FilePath::fromUserInput(QLatin1String("$TMPDIR/test/file.cpp")),
10,
Constants::TASK_CATEGORY_COMPILE);
}
@@ -529,7 +541,7 @@ void ProjectExplorerPlugin::testGnuMakeParserTaskMangling()
// fix up output task file:
QString filePath = outputTask.file.toString();
if (filePath.startsWith(QLatin1String("$TMPDIR/")))
- outputTask.file = Utils::FileName::fromString(filePath.replace(QLatin1String("$TMPDIR/"), tempdir));
+ outputTask.file = Utils::FilePath::fromString(filePath.replace(QLatin1String("$TMPDIR/"), tempdir));
// test mangling:
testbench.testTaskMangling(inputTask, outputTask);
diff --git a/src/plugins/projectexplorer/images/fileoverlay_py.png b/src/plugins/projectexplorer/images/fileoverlay_py.png
new file mode 100644
index 0000000000..3cda889a4b
--- /dev/null
+++ b/src/plugins/projectexplorer/images/fileoverlay_py.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/fileoverlay_py@2x.png b/src/plugins/projectexplorer/images/fileoverlay_py@2x.png
new file mode 100644
index 0000000000..071c946456
--- /dev/null
+++ b/src/plugins/projectexplorer/images/fileoverlay_py@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/importwidget.cpp b/src/plugins/projectexplorer/importwidget.cpp
index d9bd629179..eac2c44c94 100644
--- a/src/plugins/projectexplorer/importwidget.cpp
+++ b/src/plugins/projectexplorer/importwidget.cpp
@@ -29,6 +29,7 @@
#include <utils/pathchooser.h>
#include <QPushButton>
+#include <QTimer>
#include <QVBoxLayout>
namespace ProjectExplorer {
@@ -60,19 +61,32 @@ ImportWidget::ImportWidget(QWidget *parent) :
layout->addWidget(importButton);
connect(importButton, &QAbstractButton::clicked, this, &ImportWidget::handleImportRequest);
+ connect(m_pathChooser->lineEdit(), &QLineEdit::returnPressed, this, [this] {
+ if (m_pathChooser->isValid()) {
+ handleImportRequest();
+
+ // The next return should trigger the "Configure" button.
+ QTimer::singleShot(0, this, QOverload<>::of(&QWidget::setFocus));
+ }
+ });
detailsWidget->setWidget(widget);
}
-void ImportWidget::setCurrentDirectory(const Utils::FileName &dir)
+void ImportWidget::setCurrentDirectory(const Utils::FilePath &dir)
{
m_pathChooser->setBaseFileName(dir);
m_pathChooser->setFileName(dir);
}
+bool ImportWidget::lineEditHasFocus() const
+{
+ return m_pathChooser->lineEdit()->hasFocus();
+}
+
void ImportWidget::handleImportRequest()
{
- Utils::FileName dir = m_pathChooser->fileName();
+ Utils::FilePath dir = m_pathChooser->fileName();
emit importFrom(dir);
m_pathChooser->setFileName(m_pathChooser->baseFileName());
diff --git a/src/plugins/projectexplorer/importwidget.h b/src/plugins/projectexplorer/importwidget.h
index 9a55f64e1b..8999bc117d 100644
--- a/src/plugins/projectexplorer/importwidget.h
+++ b/src/plugins/projectexplorer/importwidget.h
@@ -29,7 +29,7 @@
namespace Utils {
class PathChooser;
-class FileName;
+class FilePath;
} // namespace Utils
namespace ProjectExplorer {
@@ -42,10 +42,12 @@ class ImportWidget : public QWidget
public:
explicit ImportWidget(QWidget *parent = nullptr);
- void setCurrentDirectory(const Utils::FileName &dir);
+ void setCurrentDirectory(const Utils::FilePath &dir);
+
+ bool lineEditHasFocus() const;
signals:
- void importFrom(const Utils::FileName &dir);
+ void importFrom(const Utils::FilePath &dir);
private:
void handleImportRequest();
diff --git a/src/plugins/projectexplorer/ioutputparser.cpp b/src/plugins/projectexplorer/ioutputparser.cpp
index 0da7005948..8dd6d99264 100644
--- a/src/plugins/projectexplorer/ioutputparser.cpp
+++ b/src/plugins/projectexplorer/ioutputparser.cpp
@@ -207,6 +207,11 @@ void IOutputParser::setWorkingDirectory(const QString &workingDirectory)
m_parser->setWorkingDirectory(workingDirectory);
}
+void IOutputParser::setWorkingDirectory(const Utils::FilePath &fn)
+{
+ setWorkingDirectory(fn.toString());
+}
+
void IOutputParser::flush()
{
doFlush();
diff --git a/src/plugins/projectexplorer/ioutputparser.h b/src/plugins/projectexplorer/ioutputparser.h
index 47c8f4f1c0..1872461cbb 100644
--- a/src/plugins/projectexplorer/ioutputparser.h
+++ b/src/plugins/projectexplorer/ioutputparser.h
@@ -53,6 +53,7 @@ public:
virtual bool hasFatalErrors() const;
virtual void setWorkingDirectory(const QString &workingDirectory);
+ void setWorkingDirectory(const Utils::FilePath &fn);
void flush(); // flush out pending tasks
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
index d99f5fe0ec..835f3a0429 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
@@ -388,6 +388,7 @@ QWidget *LabelField::createWidget(const QString &displayName, JsonFieldPage *pag
auto w = new QLabel;
w->setWordWrap(m_wordWrap);
w->setText(m_text);
+ w->setSizePolicy(QSizePolicy::Expanding, w->sizePolicy().verticalPolicy());
return w;
}
@@ -809,7 +810,7 @@ std::unique_ptr<QStandardItem> createStandardItemFromListItem(const QVariant &it
if (item.type() == QVariant::Map) {
QVariantMap tmp = item.toMap();
const QString key = JsonWizardFactory::localizedString(consumeValue(tmp, "trKey", QString()).toString());
- const QString value = consumeValue(tmp, "value", key).toString();
+ const QVariant value = consumeValue(tmp, "value", key);
if (key.isNull() || key.isEmpty()) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::JsonFieldPage",
@@ -919,7 +920,7 @@ void ListField::initializeData(MacroExpander *expander)
if (item.get() == currentItem)
currentItem = expandedValuesItem;
expandedValuesItem->setText(expander->expand(item->text()));
- expandedValuesItem->setData(expander->expand(item->data(ValueRole).toString()), ValueRole);
+ expandedValuesItem->setData(expander->expandVariant(item->data(ValueRole)), ValueRole);
expandedValuesItem->setData(expander->expand(item->data(IconStringRole).toString()), IconStringRole);
expandedValuesItem->setData(condition, ConditionRole);
@@ -1006,7 +1007,7 @@ void ComboBoxField::setup(JsonFieldPage *page, const QString &name)
// the selectionModel does not behave like expected and wanted - so we block signals here
// (for example there was some losing focus thing when hovering over items, ...)
selectionModel()->blockSignals(true);
- QObject::connect(w, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated), [w, this](int index) {
+ QObject::connect(w, QOverload<int>::of(&QComboBox::activated), [w, this](int index) {
w->blockSignals(true);
selectionModel()->clearSelection();
@@ -1019,8 +1020,8 @@ void ComboBoxField::setup(JsonFieldPage *page, const QString &name)
page->registerObjectAsFieldWithName<QItemSelectionModel>(name, selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
const QModelIndex i = selectionModel()->currentIndex();
if (i.isValid())
- return i.data(ValueRole).toString();
- return QString();
+ return i.data(ValueRole);
+ return QVariant();
});
QObject::connect(selectionModel(), &QItemSelectionModel::selectionChanged, page, [page]() {
emit page->completeChanged();
@@ -1057,8 +1058,8 @@ void IconListField::setup(JsonFieldPage *page, const QString &name)
page->registerObjectAsFieldWithName<QItemSelectionModel>(name, selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
const QModelIndex i = selectionModel()->currentIndex();
if (i.isValid())
- return i.data(ValueRole).toString();
- return QString();
+ return i.data(ValueRole);
+ return QVariant();
});
QObject::connect(selectionModel(), &QItemSelectionModel::selectionChanged, page, [page]() {
emit page->completeChanged();
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp
index 5faa5c3642..7501521be7 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonkitspage.cpp
@@ -107,7 +107,7 @@ void JsonKitsPage::setupProjectFiles(const JsonWizard::GeneratorFiles &files)
const QFileInfo fi(f.file.path());
const QString path = fi.absoluteFilePath();
Project *project = ProjectManager::openProject(Utils::mimeTypeForFile(fi),
- Utils::FileName::fromString(path));
+ Utils::FilePath::fromString(path));
if (project) {
if (setupProject(project))
project->saveSettings();
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp
index 45f332a2de..fcddd7ffd8 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp
@@ -52,7 +52,7 @@ bool JsonProjectPage::validatePage()
{
if (isComplete() && useAsDefaultPath()) {
// Store the path as default path for new projects if desired.
- Core::DocumentManager::setProjectsDirectory(Utils::FileName::fromString(path()));
+ Core::DocumentManager::setProjectsDirectory(Utils::FilePath::fromString(path()));
Core::DocumentManager::setUseProjectsDirectory(true);
}
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp
index a3bad8656f..7684de0795 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizard.cpp
@@ -36,11 +36,20 @@
#include <coreplugin/messagemanager.h>
#include <utils/algorithm.h>
+#include <utils/itemviews.h>
#include <utils/qtcassert.h>
+#include <utils/treemodel.h>
#include <utils/wizardpage.h>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QDir>
#include <QFileInfo>
+#include <QJSEngine>
+#include <QLabel>
#include <QMessageBox>
+#include <QPushButton>
+#include <QVBoxLayout>
#include <QVariant>
#ifdef WITH_TESTS
@@ -49,7 +58,94 @@
namespace ProjectExplorer {
-JsonWizard::JsonWizard(QWidget *parent) : Utils::Wizard(parent)
+namespace Internal {
+
+class ProjectFileTreeItem : public Utils::TreeItem
+{
+public:
+ ProjectFileTreeItem(JsonWizard::GeneratorFile *candidate) : m_candidate(candidate)
+ {
+ toggleProjectFileStatus(false);
+ }
+
+ void toggleProjectFileStatus(bool on)
+ {
+ m_candidate->file.setAttributes(m_candidate->file.attributes()
+ .setFlag(Core::GeneratedFile::OpenProjectAttribute, on));
+ }
+
+private:
+ QVariant data(int column, int role) const override
+ {
+ if (column != 0 || role != Qt::DisplayRole)
+ return QVariant();
+ return QDir::toNativeSeparators(m_candidate->file.path());
+ }
+
+ JsonWizard::GeneratorFile * const m_candidate;
+};
+
+class ProjectFilesModel : public Utils::TreeModel<Utils::TreeItem, ProjectFileTreeItem>
+{
+public:
+ ProjectFilesModel(const QList<JsonWizard::GeneratorFile *> &candidates, QObject *parent)
+ : TreeModel(parent)
+ {
+ setHeader({QCoreApplication::translate("ProjectExplorer::JsonWizard", "Project File")});
+ for (JsonWizard::GeneratorFile * const candidate : candidates)
+ rootItem()->appendChild(new ProjectFileTreeItem(candidate));
+ }
+};
+
+class ProjectFileChooser : public QDialog
+{
+public:
+ ProjectFileChooser(const QList<JsonWizard::GeneratorFile *> &candidates, QWidget *parent)
+ : QDialog(parent), m_view(new Utils::TreeView(this))
+ {
+ setWindowTitle(QCoreApplication::translate("ProjectExplorer::JsonWizard",
+ "Choose Project File"));
+ const auto model = new ProjectFilesModel(candidates, this);
+ m_view->setSelectionMode(Utils::TreeView::ExtendedSelection);
+ m_view->setSelectionBehavior(Utils::TreeView::SelectRows);
+ m_view->setModel(model);
+ const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ const auto updateOkButton = [buttonBox, this] {
+ buttonBox->button(QDialogButtonBox::Ok)
+ ->setEnabled(m_view->selectionModel()->hasSelection());
+ };
+ connect(m_view->selectionModel(), &QItemSelectionModel::selectionChanged,
+ this, updateOkButton);
+ updateOkButton();
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ const auto layout = new QVBoxLayout(this);
+ layout->addWidget(new QLabel(QCoreApplication::translate("ProjectExplorer::JsonWizard",
+ "The project contains more than one project file. "
+ "Select the one you would like to use.")));
+ layout->addWidget(m_view);
+ layout->addWidget(buttonBox);
+ }
+
+private:
+ void accept() override
+ {
+ const QModelIndexList selected = m_view->selectionModel()->selectedRows();
+ const auto * const model = static_cast<ProjectFilesModel *>(m_view->model());
+ for (const QModelIndex &index : selected) {
+ const auto item = static_cast<ProjectFileTreeItem *>(model->itemForIndex(index));
+ QTC_ASSERT(item, continue);
+ item->toggleProjectFileStatus(true);
+ }
+ QDialog::accept();
+ }
+
+ Utils::TreeView * const m_view;
+};
+
+} // namespace Internal
+
+JsonWizard::JsonWizard(QWidget *parent)
+ : Utils::Wizard(parent)
{
setMinimumSize(800, 500);
m_expander.registerExtraResolver([this](const QString &name, QString *ret) -> bool {
@@ -63,7 +159,10 @@ JsonWizard::JsonWizard(QWidget *parent) : Utils::Wizard(parent)
const QString key = QString::fromLatin1("%{") + value + QLatin1Char('}');
return m_expander.expand(key) == key ? QString() : QLatin1String("true");
});
-
+ // override default JS macro by custom one that adds Wizard specific features
+ m_jsExpander.registerObject("Wizard", new Internal::JsonWizardJsExtension(this));
+ m_jsExpander.engine().evaluate("var value = Wizard.value");
+ m_jsExpander.registerForExpander(&m_expander);
}
JsonWizard::~JsonWizard()
@@ -113,6 +212,14 @@ JsonWizard::GeneratorFiles JsonWizard::generateFileList()
return GeneratorFiles();
}
+ QList<GeneratorFile *> projectFiles;
+ for (JsonWizard::GeneratorFile &f : list) {
+ if (f.file.attributes().testFlag(Core::GeneratedFile::OpenProjectAttribute))
+ projectFiles << &f;
+ }
+ if (projectFiles.count() > 1)
+ Internal::ProjectFileChooser(projectFiles, this).exec();
+
return list;
}
@@ -392,11 +499,16 @@ void JsonWizard::openProjectForNode(Node *node)
{
using namespace Utils;
- ProjectNode *projNode = node->asProjectNode() ? node->asProjectNode() : node->parentProjectNode();
-
+ const ProjectNode *projNode = node->asProjectNode();
+ if (!projNode) {
+ if (ContainerNode * const cn = node->asContainerNode())
+ projNode = cn->rootProjectNode();
+ else
+ projNode = node->parentProjectNode();
+ }
QTC_ASSERT(projNode, return);
- Utils::optional<FileName> projFilePath = projNode->visibleAfterAddFileAction();
+ Utils::optional<FilePath> projFilePath = projNode->visibleAfterAddFileAction();
if (projFilePath && !Core::EditorManager::openEditor(projFilePath.value().toString())) {
auto errorMessage = QCoreApplication::translate("ProjectExplorer::JsonWizard",
@@ -418,4 +530,17 @@ bool JsonWizard::OptionDefinition::condition(Utils::MacroExpander &expander) con
return JsonWizard::boolFromVariant(m_condition, &expander);
}
+namespace Internal {
+
+JsonWizardJsExtension::JsonWizardJsExtension(JsonWizard *wizard)
+ : m_wizard(wizard)
+{}
+
+QVariant JsonWizardJsExtension::value(const QString &name) const
+{
+ const QVariant value = m_wizard->value(name);
+ return m_wizard->expander()->expandVariant(m_wizard->value(name));
+}
+
+} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizard.h b/src/plugins/projectexplorer/jsonwizard/jsonwizard.h
index 1f8aca7741..99a9ce4952 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizard.h
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizard.h
@@ -29,6 +29,7 @@
#include <projectexplorer/projectnodes.h>
#include <coreplugin/generatedfile.h>
+#include <coreplugin/jsexpander.h>
#include <utils/wizard.h>
#include <utils/macroexpander.h>
@@ -37,8 +38,25 @@
namespace ProjectExplorer {
+class JsonWizard;
class JsonWizardGenerator;
+namespace Internal {
+
+class JsonWizardJsExtension : public QObject
+{
+ Q_OBJECT
+public:
+ JsonWizardJsExtension(JsonWizard *wizard);
+
+ Q_INVOKABLE QVariant value(const QString &name) const;
+
+private:
+ JsonWizard *m_wizard;
+};
+
+} // namespace Internal
+
// Documentation inside.
class PROJECTEXPLORER_EXPORT JsonWizard : public Utils::Wizard
{
@@ -126,6 +144,7 @@ private:
GeneratorFiles m_files;
Utils::MacroExpander m_expander;
+ Core::JsExpander m_jsExpander;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
index 3a01d9e045..530ace9ca7 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp
@@ -34,6 +34,7 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
+#include <coreplugin/jsexpander.h>
#include <coreplugin/messagemanager.h>
#include <extensionsystem/pluginmanager.h>
@@ -46,10 +47,11 @@
#include <QDebug>
#include <QDir>
-#include <QMap>
+#include <QJSEngine>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
+#include <QMap>
#include <QUuid>
namespace ProjectExplorer {
@@ -209,7 +211,7 @@ QList<Core::IWizardFactory *> JsonWizardFactory::createWizardFactories()
const QString wizardFileName = QLatin1String(WIZARD_FILE);
QList <Core::IWizardFactory *> result;
- foreach (const Utils::FileName &path, searchPaths()) {
+ foreach (const Utils::FilePath &path, searchPaths()) {
if (path.isEmpty())
continue;
@@ -223,7 +225,7 @@ QList<Core::IWizardFactory *> JsonWizardFactory::createWizardFactories()
const QDir::Filters filters = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const QDir::SortFlags sortflags = QDir::Name|QDir::IgnoreCase;
- QList<QFileInfo> dirs = dir.entryInfoList(filters, sortflags);
+ QFileInfoList dirs = dir.entryInfoList(filters, sortflags);
while (!dirs.isEmpty()) {
const QFileInfo dirFi = dirs.takeFirst();
@@ -283,7 +285,7 @@ QList<Core::IWizardFactory *> JsonWizardFactory::createWizardFactories()
result << factory;
} else {
- QList<QFileInfo> subDirs = current.entryInfoList(filters, sortflags);
+ QFileInfoList subDirs = current.entryInfoList(filters, sortflags);
if (!subDirs.isEmpty()) {
// There is no QList::prepend(QList)...
dirs.swap(subDirs);
@@ -332,20 +334,20 @@ static QStringList environmentTemplatesPaths()
return paths;
}
-Utils::FileNameList &JsonWizardFactory::searchPaths()
+Utils::FilePathList &JsonWizardFactory::searchPaths()
{
- static Utils::FileNameList m_searchPaths = Utils::FileNameList()
- << Utils::FileName::fromString(Core::ICore::userResourcePath() + QLatin1Char('/') +
+ static Utils::FilePathList m_searchPaths = Utils::FilePathList()
+ << Utils::FilePath::fromString(Core::ICore::userResourcePath() + QLatin1Char('/') +
QLatin1String(WIZARD_PATH))
- << Utils::FileName::fromString(Core::ICore::resourcePath() + QLatin1Char('/') +
+ << Utils::FilePath::fromString(Core::ICore::resourcePath() + QLatin1Char('/') +
QLatin1String(WIZARD_PATH));
for (const QString &environmentTemplateDirName : environmentTemplatesPaths())
- m_searchPaths << Utils::FileName::fromString(environmentTemplateDirName);
+ m_searchPaths << Utils::FilePath::fromString(environmentTemplateDirName);
return m_searchPaths;
}
-void JsonWizardFactory::addWizardPath(const Utils::FileName &path)
+void JsonWizardFactory::addWizardPath(const Utils::FilePath &path)
{
searchPaths().append(path);
}
@@ -513,9 +515,17 @@ bool JsonWizardFactory::isAvailable(Core::Id platformId) const
[platformId]() { return platformId.toString(); });
expander.registerVariable("Features", tr("The features available to this wizard."),
[this, e, platformId]() { return JsonWizard::stringListToArrayString(Core::Id::toStringList(availableFeatures(platformId)), e); });
- expander.registerVariable("Plugins", tr("The plugins loaded."),
- [this, e]() { return JsonWizard::stringListToArrayString(Core::Id::toStringList(pluginFeatures()), e); });
-
+ expander.registerVariable("Plugins", tr("The plugins loaded."), [this, e]() {
+ return JsonWizard::stringListToArrayString(Core::Id::toStringList(pluginFeatures()), e);
+ });
+ Core::JsExpander jsExpander;
+ jsExpander.registerObject("Wizard",
+ new Internal::JsonWizardFactoryJsExtension(platformId,
+ availableFeatures(
+ platformId),
+ pluginFeatures()));
+ jsExpander.engine().evaluate("var value = Wizard.value");
+ jsExpander.registerForExpander(e);
return JsonWizard::boolFromVariant(m_enabledExpression, &expander);
}
@@ -660,4 +670,26 @@ bool JsonWizardFactory::initialize(const QVariantMap &data, const QDir &baseDir,
return errorMessage->isEmpty();
}
+namespace Internal {
+
+JsonWizardFactoryJsExtension::JsonWizardFactoryJsExtension(Core::Id platformId,
+ const QSet<Core::Id> &availableFeatures,
+ const QSet<Core::Id> &pluginFeatures)
+ : m_platformId(platformId)
+ , m_availableFeatures(availableFeatures)
+ , m_pluginFeatures(pluginFeatures)
+{}
+
+QVariant JsonWizardFactoryJsExtension::value(const QString &name) const
+{
+ if (name == "Platform")
+ return m_platformId.toString();
+ if (name == "Features")
+ return Core::Id::toStringList(m_availableFeatures);
+ if (name == "Plugins")
+ return Core::Id::toStringList(m_pluginFeatures);
+ return QVariant();
+}
+
+} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h
index ead93f4841..5573bb2979 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h
@@ -55,7 +55,7 @@ class PROJECTEXPLORER_EXPORT JsonWizardFactory : public Core::IWizardFactory
public:
// Add search paths for wizard.json files. All subdirs are going to be checked.
- static void addWizardPath(const Utils::FileName &path);
+ static void addWizardPath(const Utils::FilePath &path);
// actual interface of the wizard factory:
class Generator {
@@ -96,7 +96,7 @@ private:
static QList<IWizardFactory *> createWizardFactories();
static JsonWizardFactory *createWizardFactory(const QVariantMap &data, const QDir &baseDir,
QString *errorMessage);
- static Utils::FileNameList &searchPaths();
+ static Utils::FilePathList &searchPaths();
static void setVerbose(int level);
static int verbose();
@@ -119,4 +119,23 @@ private:
friend class ProjectExplorerPluginPrivate;
};
-} //namespace ProjectExplorer
+namespace Internal {
+
+class JsonWizardFactoryJsExtension : public QObject
+{
+ Q_OBJECT
+public:
+ JsonWizardFactoryJsExtension(Core::Id platformId,
+ const QSet<Core::Id> &availableFeatures,
+ const QSet<Core::Id> &pluginFeatures);
+
+ Q_INVOKABLE QVariant value(const QString &name) const;
+
+private:
+ Core::Id m_platformId;
+ QSet<Core::Id> m_availableFeatures;
+ QSet<Core::Id> m_pluginFeatures;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp
index ee7da5b419..a168fea084 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfilegenerator.cpp
@@ -127,7 +127,9 @@ Core::GeneratedFile JsonWizardFileGenerator::generateFile(const File &file,
*ret = options.value(n);
return true;
});
- nested.registerExtraResolver([expander](QString n, QString *ret) { return expander->resolveMacro(n, ret); });
+ nested.registerExtraResolver([expander](QString n, QString *ret) {
+ return expander->resolveMacro(n, ret);
+ });
gf.setContents(Utils::TemplateEngine::processText(&nested, QString::fromUtf8(reader.data()),
errorMessage));
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp
index e0a06c824e..cf84f8b5e4 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardgeneratorfactory.cpp
@@ -98,7 +98,7 @@ bool JsonWizardGenerator::formatFile(const JsonWizard *wizard, GeneratedFile *fi
Indenter *indenter = nullptr;
if (factory) {
indenter = factory->createIndenter(&doc);
- indenter->setFileName(Utils::FileName::fromString(file->path()));
+ indenter->setFileName(Utils::FilePath::fromString(file->path()));
}
if (!indenter)
indenter = new NormalIndenter(&doc);
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp
index 08d3ed1f88..9f24f00718 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.cpp
@@ -42,6 +42,8 @@
#include <QDir>
#include <QVariant>
+#include <limits>
+
namespace ProjectExplorer {
namespace Internal {
@@ -70,8 +72,6 @@ bool JsonWizardScannerGenerator::setup(const QVariant &data, QString *errorMessa
m_subDirectoryExpressions << regexp;
}
- m_firstProjectOnly = gen.value(QLatin1String("firstProjectOnly"), QLatin1String("true")).toString();
-
return true;
}
@@ -97,17 +97,28 @@ Core::GeneratedFiles JsonWizardScannerGenerator::fileList(Utils::MacroExpander *
}
}
- bool onlyFirst = JsonWizard::boolFromVariant(m_firstProjectOnly, expander);
-
result = scan(project.absolutePath(), project);
- int projectCount = 0;
+ static const auto getDepth = [](const QString &filePath) { return filePath.count('/'); };
+ int minDepth = std::numeric_limits<int>::max();
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));
- if (found && !(onlyFirst && projectCount++))
+ if (found) {
it->setAttributes(it->attributes() | Core::GeneratedFile::OpenProjectAttribute);
+ minDepth = std::min(minDepth, getDepth(it->path()));
+ }
+ }
+
+ // Project files that appear on a lower level in the file system hierarchy than
+ // other project files are not candidates for opening.
+ for (Core::GeneratedFile &f : result) {
+ if (f.attributes().testFlag(Core::GeneratedFile::OpenProjectAttribute)
+ && getDepth(f.path()) > minDepth) {
+ f.setAttributes(f.attributes().setFlag(Core::GeneratedFile::OpenProjectAttribute,
+ false));
+ }
}
return result;
@@ -130,7 +141,7 @@ Core::GeneratedFiles JsonWizardScannerGenerator::scan(const QString &dir, const
if (!directory.exists())
return result;
- QList<QFileInfo> entries = directory.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot,
+ QFileInfoList entries = directory.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot,
QDir::DirsLast | QDir::Name);
foreach (const QFileInfo &fi, entries) {
const QString relativePath = base.relativeFilePath(fi.absoluteFilePath());
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h
index e852ad1fe0..76475d4f97 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h
+++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardscannergenerator.h
@@ -43,13 +43,11 @@ public:
Core::GeneratedFiles fileList(Utils::MacroExpander *expander,
const QString &wizardDir, const QString &projectDir,
QString *errorMessage) override;
-
private:
Core::GeneratedFiles scan(const QString &dir, const QDir &base);
bool matchesSubdirectoryPattern(const QString &path);
QString m_binaryPattern;
- QString m_firstProjectOnly;
QList<QRegularExpression> m_subDirectoryExpressions;
};
diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp
index 5376f0c766..88e2e65ada 100644
--- a/src/plugins/projectexplorer/kit.cpp
+++ b/src/plugins/projectexplorer/kit.cpp
@@ -36,7 +36,10 @@
#include <utils/fileutils.h>
#include <utils/icon.h>
#include <utils/macroexpander.h>
+#include <utils/optional.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
+#include <utils/utilsicons.h>
#include <QApplication>
#include <QFileInfo>
@@ -45,6 +48,8 @@
#include <QTextStream>
#include <QUuid>
+#include <numeric>
+
using namespace Core;
using namespace Utils;
@@ -56,8 +61,10 @@ const char AUTODETECTIONSOURCE_KEY[] = "PE.Profile.AutoDetectionSource";
const char SDK_PROVIDED_KEY[] = "PE.Profile.SDK";
const char DATA_KEY[] = "PE.Profile.Data";
const char ICON_KEY[] = "PE.Profile.Icon";
+const char DEVICE_TYPE_FOR_ICON_KEY[] = "PE.Profile.DeviceTypeForIcon";
const char MUTABLE_INFO_KEY[] = "PE.Profile.MutableInfo";
const char STICKY_INFO_KEY[] = "PE.Profile.StickyInfo";
+const char IRRELEVANT_ASPECTS_KEY[] = "PE.Kit.IrrelevantAspects";
namespace ProjectExplorer {
namespace Internal {
@@ -86,8 +93,8 @@ public:
[kit] { return kit->id().toString(); });
m_macroExpander.registerVariable("Kit:FileSystemName", tr("Kit filesystem-friendly name"),
[kit] { return kit->fileSystemFriendlyName(); });
- foreach (KitInformation *ki, KitManager::kitInformation())
- ki->addToMacroExpander(kit, &m_macroExpander);
+ for (KitAspect *aspect : KitManager::kitAspects())
+ aspect->addToMacroExpander(kit, &m_macroExpander);
// This provides the same global fall back as the global expander
// without relying on the currentKit() discovery process there.
@@ -117,11 +124,13 @@ public:
bool m_hasValidityInfo = false;
bool m_mustNotify = false;
QIcon m_cachedIcon;
- FileName m_iconPath;
+ FilePath m_iconPath;
+ Id m_deviceTypeForIcon;
QHash<Id, QVariant> m_data;
QSet<Id> m_sticky;
QSet<Id> m_mutable;
+ optional<QSet<Id>> m_irrelevantAspects;
MacroExpander m_macroExpander;
};
@@ -134,8 +143,6 @@ public:
Kit::Kit(Id id) :
d(std::make_unique<Internal::KitPrivate>(id, this))
{
- foreach (KitInformation *sti, KitManager::kitInformation())
- d->m_data.insert(sti->id(), sti->defaultValue(this));
}
Kit::Kit(const QVariantMap &data) :
@@ -156,8 +163,12 @@ Kit::Kit(const QVariantMap &data) :
d->m_unexpandedDisplayName = data.value(QLatin1String(DISPLAYNAME_KEY),
d->m_unexpandedDisplayName).toString();
d->m_fileSystemFriendlyName = data.value(QLatin1String(FILESYSTEMFRIENDLYNAME_KEY)).toString();
- d->m_iconPath = FileName::fromString(data.value(QLatin1String(ICON_KEY),
+ d->m_iconPath = FilePath::fromString(data.value(QLatin1String(ICON_KEY),
d->m_iconPath.toString()).toString());
+ d->m_deviceTypeForIcon = Id::fromSetting(data.value(DEVICE_TYPE_FOR_ICON_KEY));
+ const auto it = data.constFind(IRRELEVANT_ASPECTS_KEY);
+ if (it != data.constEnd())
+ d->m_irrelevantAspects = transform<QSet<Id>>(it.value().toList(), &Id::fromSetting);
QVariantMap extra = data.value(QLatin1String(DATA_KEY)).toMap();
d->m_data.clear(); // remove default values
@@ -190,38 +201,40 @@ void Kit::unblockNotification()
kitUpdated();
}
+void Kit::copyKitCommon(Kit *target, const Kit *source)
+{
+ target->d->m_data = source->d->m_data;
+ target->d->m_iconPath = source->d->m_iconPath;
+ target->d->m_deviceTypeForIcon = source->d->m_deviceTypeForIcon;
+ target->d->m_cachedIcon = source->d->m_cachedIcon;
+ target->d->m_sticky = source->d->m_sticky;
+ target->d->m_mutable = source->d->m_mutable;
+ target->d->m_irrelevantAspects = source->d->m_irrelevantAspects;
+}
+
Kit *Kit::clone(bool keepName) const
{
auto k = new Kit;
+ copyKitCommon(k, this);
if (keepName)
k->d->m_unexpandedDisplayName = d->m_unexpandedDisplayName;
else
- k->d->m_unexpandedDisplayName = QCoreApplication::translate("ProjectExplorer::Kit", "Clone of %1")
- .arg(d->m_unexpandedDisplayName);
+ k->d->m_unexpandedDisplayName = newKitName(KitManager::kits());
k->d->m_autodetected = false;
- k->d->m_data = d->m_data;
// Do not clone m_fileSystemFriendlyName, needs to be unique
- k->d->m_hasError = d->m_hasError;
- k->d->m_cachedIcon = d->m_cachedIcon;
- k->d->m_iconPath = d->m_iconPath;
- k->d->m_sticky = d->m_sticky;
- k->d->m_mutable = d->m_mutable;
+ k->d->m_hasError = d->m_hasError; // TODO: Is this intentionally not done for copyFrom()?
return k;
}
void Kit::copyFrom(const Kit *k)
{
KitGuard g(this);
- d->m_data = k->d->m_data;
- d->m_iconPath = k->d->m_iconPath;
- d->m_cachedIcon = k->d->m_cachedIcon;
+ copyKitCommon(this, k);
d->m_autodetected = k->d->m_autodetected;
d->m_autoDetectionSource = k->d->m_autoDetectionSource;
d->m_unexpandedDisplayName = k->d->m_unexpandedDisplayName;
d->m_fileSystemFriendlyName = k->d->m_fileSystemFriendlyName;
d->m_mustNotify = true;
- d->m_sticky = k->d->m_sticky;
- d->m_mutable = k->d->m_mutable;
}
bool Kit::isValid() const
@@ -243,14 +256,12 @@ bool Kit::hasWarning() const
return d->m_hasWarning;
}
-QList<Task> Kit::validate() const
+Tasks Kit::validate() const
{
- QList<Task> result;
- QList<KitInformation *> infoList = KitManager::kitInformation();
- for (KitInformation *i : infoList) {
- QList<Task> tmp = i->validate(this);
- result.append(tmp);
- }
+ Tasks result;
+ for (KitAspect *aspect : KitManager::kitAspects())
+ result.append(aspect->validate(this));
+
d->m_hasError = containsType(result, Task::TaskType::Error);
d->m_hasWarning = containsType(result, Task::TaskType::Warning);
@@ -262,25 +273,25 @@ QList<Task> Kit::validate() const
void Kit::fix()
{
KitGuard g(this);
- foreach (KitInformation *i, KitManager::kitInformation())
- i->fix(this);
+ for (KitAspect *aspect : KitManager::kitAspects())
+ aspect->fix(this);
}
void Kit::setup()
{
KitGuard g(this);
- const QList<KitInformation *> info = KitManager::kitInformation();
- for (KitInformation * const ki : info)
- ki->setup(this);
+ const QList<KitAspect *> aspects = KitManager::kitAspects();
+ for (KitAspect * const aspect : aspects)
+ aspect->setup(this);
}
void Kit::upgrade()
{
KitGuard g(this);
- // Process the KitInfos in reverse order: They may only be based on other information lower in
- // the stack.
- for (KitInformation *ki : KitManager::kitInformation())
- ki->upgrade(this);
+ // Process the KitAspects in reverse order: They may only be based on other information
+ // lower in the stack.
+ for (KitAspect *aspect : KitManager::kitAspects())
+ aspect->upgrade(this);
}
QString Kit::unexpandedDisplayName() const
@@ -350,6 +361,15 @@ Id Kit::id() const
return d->m_id;
}
+int Kit::weight() const
+{
+ const QList<KitAspect *> &aspects = KitManager::kitAspects();
+ return std::accumulate(aspects.begin(), aspects.end(), 0,
+ [this](int sum, const KitAspect *aspect) {
+ return sum + aspect->weight(this);
+ });
+}
+
static QIcon iconForDeviceType(Core::Id deviceType)
{
const IDeviceFactory *factory = Utils::findOrDefault(IDeviceFactory::allDeviceFactories(),
@@ -364,12 +384,13 @@ QIcon Kit::icon() const
if (!d->m_cachedIcon.isNull())
return d->m_cachedIcon;
- if (!d->m_iconPath.isEmpty() && d->m_iconPath.exists()) {
+ if (!d->m_deviceTypeForIcon.isValid() && !d->m_iconPath.isEmpty() && d->m_iconPath.exists()) {
d->m_cachedIcon = QIcon(d->m_iconPath.toString());
return d->m_cachedIcon;
}
- const Core::Id deviceType = DeviceTypeKitInformation::deviceTypeId(this);
+ const Core::Id deviceType = d->m_deviceTypeForIcon.isValid()
+ ? d->m_deviceTypeForIcon : DeviceTypeKitAspect::deviceTypeId(this);
const QIcon deviceTypeIcon = iconForDeviceType(deviceType);
if (!deviceTypeIcon.isNull()) {
d->m_cachedIcon = deviceTypeIcon;
@@ -380,19 +401,43 @@ QIcon Kit::icon() const
return d->m_cachedIcon;
}
-FileName Kit::iconPath() const
+QIcon Kit::displayIcon() const
+{
+ QIcon result = icon();
+ if (hasWarning()) {
+ static const QIcon warningIcon(Utils::Icons::WARNING.icon());
+ result = warningIcon;
+ }
+ if (!isValid()) {
+ static const QIcon errorIcon(Utils::Icons::CRITICAL.icon());
+ result = errorIcon;
+ }
+ return result;
+}
+
+FilePath Kit::iconPath() const
{
return d->m_iconPath;
}
-void Kit::setIconPath(const FileName &path)
+void Kit::setIconPath(const FilePath &path)
{
if (d->m_iconPath == path)
return;
+ d->m_deviceTypeForIcon = Id();
d->m_iconPath = path;
kitUpdated();
}
+void Kit::setDeviceTypeForIcon(Id deviceType)
+{
+ if (d->m_deviceTypeForIcon == deviceType)
+ return;
+ d->m_iconPath.clear();
+ d->m_deviceTypeForIcon = deviceType;
+ kitUpdated();
+}
+
QList<Id> Kit::allKeys() const
{
return d->m_data.keys();
@@ -459,10 +504,11 @@ bool Kit::isEqual(const Kit *other) const
{
return isDataEqual(other)
&& d->m_iconPath == other->d->m_iconPath
+ && d->m_deviceTypeForIcon == other->d->m_deviceTypeForIcon
&& d->m_unexpandedDisplayName == other->d->m_unexpandedDisplayName
&& d->m_fileSystemFriendlyName == other->d->m_fileSystemFriendlyName
+ && d->m_irrelevantAspects == other->d->m_irrelevantAspects
&& d->m_mutable == other->d->m_mutable;
-
}
QVariantMap Kit::toMap() const
@@ -478,6 +524,7 @@ QVariantMap Kit::toMap() const
data.insert(QLatin1String(AUTODETECTIONSOURCE_KEY), d->m_autoDetectionSource);
data.insert(QLatin1String(SDK_PROVIDED_KEY), d->m_sdkProvided);
data.insert(QLatin1String(ICON_KEY), d->m_iconPath.toString());
+ data.insert(DEVICE_TYPE_FOR_ICON_KEY, d->m_deviceTypeForIcon.toSetting());
QStringList mutableInfo;
foreach (Id id, d->m_mutable)
@@ -489,6 +536,11 @@ QVariantMap Kit::toMap() const
stickyInfo << id.toString();
data.insert(QLatin1String(STICKY_INFO_KEY), stickyInfo);
+ if (d->m_irrelevantAspects) {
+ data.insert(IRRELEVANT_ASPECTS_KEY, transform<QVariantList>(d->m_irrelevantAspects.value(),
+ &Id::toSetting));
+ }
+
QVariantMap extra;
const IdVariantConstIt cend = d->m_data.constEnd();
@@ -501,21 +553,19 @@ QVariantMap Kit::toMap() const
void Kit::addToEnvironment(Environment &env) const
{
- QList<KitInformation *> infoList = KitManager::kitInformation();
- foreach (KitInformation *ki, infoList)
- ki->addToEnvironment(this, env);
+ for (KitAspect *aspect : KitManager::kitAspects())
+ aspect->addToEnvironment(this, env);
}
IOutputParser *Kit::createOutputParser() const
{
auto first = new OsParser;
- QList<KitInformation *> infoList = KitManager::kitInformation();
- foreach (KitInformation *ki, infoList)
- first->appendOutputParser(ki->createOutputParser(this));
+ for (KitAspect *aspect : KitManager::kitAspects())
+ first->appendOutputParser(aspect->createOutputParser(this));
return first;
}
-QString Kit::toHtml(const QList<Task> &additional) const
+QString Kit::toHtml(const Tasks &additional) const
{
QString result;
QTextStream str(&result);
@@ -526,10 +576,9 @@ QString Kit::toHtml(const QList<Task> &additional) const
str << "<p>" << ProjectExplorer::toHtml(additional + validate()) << "</p>";
str << "<table>";
- QList<KitInformation *> infoList = KitManager::kitInformation();
- foreach (KitInformation *ki, infoList) {
- KitInformation::ItemList list = ki->toUserOutput(this);
- foreach (const KitInformation::Item &j, list) {
+ for (KitAspect *aspect : KitManager::kitAspects()) {
+ const KitAspect::ItemList list = aspect->toUserOutput(this);
+ for (const KitAspect::Item &j : list) {
QString contents = j.second;
if (contents.count() > 256) {
int pos = contents.lastIndexOf("<br>", 256);
@@ -571,9 +620,9 @@ void Kit::setSdkProvided(bool sdkProvided)
void Kit::makeSticky()
{
- foreach (KitInformation *ki, KitManager::kitInformation()) {
- if (hasValue(ki->id()))
- setSticky(ki->id(), true);
+ for (KitAspect *aspect : KitManager::kitAspects()) {
+ if (hasValue(aspect->id()))
+ setSticky(aspect->id(), true);
}
}
@@ -614,11 +663,21 @@ bool Kit::isMutable(Id id) const
return d->m_mutable.contains(id);
}
+void Kit::setIrrelevantAspects(const QSet<Id> &irrelevant)
+{
+ d->m_irrelevantAspects = irrelevant;
+}
+
+QSet<Id> Kit::irrelevantAspects() const
+{
+ return d->m_irrelevantAspects.value_or(KitManager::irrelevantAspects());
+}
+
QSet<Id> Kit::supportedPlatforms() const
{
QSet<Id> platforms;
- foreach (const KitInformation *ki, KitManager::kitInformation()) {
- const QSet<Id> ip = ki->supportedPlatforms(this);
+ for (const KitAspect *aspect : KitManager::kitAspects()) {
+ const QSet<Id> ip = aspect->supportedPlatforms(this);
if (ip.isEmpty())
continue;
if (platforms.isEmpty())
@@ -632,8 +691,8 @@ QSet<Id> Kit::supportedPlatforms() const
QSet<Id> Kit::availableFeatures() const
{
QSet<Id> features;
- foreach (const KitInformation *ki, KitManager::kitInformation())
- features |= ki->availableFeatures(this);
+ for (const KitAspect *aspect : KitManager::kitAspects())
+ features |= aspect->availableFeatures(this);
return features;
}
@@ -647,6 +706,19 @@ MacroExpander *Kit::macroExpander() const
return &d->m_macroExpander;
}
+QString Kit::newKitName(const QList<Kit *> &allKits) const
+{
+ return newKitName(unexpandedDisplayName(), allKits);
+}
+
+QString Kit::newKitName(const QString &name, const QList<Kit *> &allKits)
+{
+ const QString baseName = name.isEmpty()
+ ? QCoreApplication::translate("ProjectExplorer::Kit", "Unnamed")
+ : QCoreApplication::translate("ProjectExplorer::Kit", "Clone of %1").arg(name);
+ return Utils::makeUniquelyNumbered(baseName, transform(allKits, &Kit::unexpandedDisplayName));
+}
+
void Kit::kitUpdated()
{
if (d->m_nestedBlockingLevel > 0) {
diff --git a/src/plugins/projectexplorer/kit.h b/src/plugins/projectexplorer/kit.h
index ab9b1681f6..8e45911d17 100644
--- a/src/plugins/projectexplorer/kit.h
+++ b/src/plugins/projectexplorer/kit.h
@@ -71,7 +71,7 @@ public:
bool isValid() const;
bool hasWarning() const;
- QList<Task> validate() const;
+ Tasks validate() const;
void fix(); // Fix the individual kit information: Make sure it contains a valid value.
// Fix will not look at other information in the kit!
void setup(); // Apply advanced magic(TM). Used only once on each kit during initial setup.
@@ -90,9 +90,17 @@ public:
bool isSdkProvided() const;
Core::Id id() const;
- QIcon icon() const;
- Utils::FileName iconPath() const;
- void setIconPath(const Utils::FileName &path);
+ // The higher the weight, the more aspects have sensible values for this kit.
+ // For instance, a kit where a matching debugger was found for the toolchain will have a
+ // higher weight than one whose toolchain does not match a known debugger, assuming
+ // all other aspects are equal.
+ int weight() const;
+
+ QIcon icon() const; // Raw device icon, independent of warning or error.
+ QIcon displayIcon() const; // Error or warning or device icon.
+ Utils::FilePath iconPath() const;
+ void setIconPath(const Utils::FilePath &path);
+ void setDeviceTypeForIcon(Core::Id deviceType);
QList<Core::Id> allKeys() const;
QVariant value(Core::Id key, const QVariant &unset = QVariant()) const;
@@ -109,7 +117,7 @@ public:
void addToEnvironment(Utils::Environment &env) const;
IOutputParser *createOutputParser() const;
- QString toHtml(const QList<Task> &additional = QList<Task>()) const;
+ QString toHtml(const Tasks &additional = Tasks()) const;
Kit *clone(bool keepName = false) const;
void copyFrom(const Kit *k);
@@ -123,12 +131,19 @@ public:
void setMutable(Core::Id id, bool b);
bool isMutable(Core::Id id) const;
+ void setIrrelevantAspects(const QSet<Core::Id> &irrelevant);
+ QSet<Core::Id> irrelevantAspects() const;
+
QSet<Core::Id> supportedPlatforms() const;
QSet<Core::Id> availableFeatures() const;
bool hasFeatures(const QSet<Core::Id> &features) const;
Utils::MacroExpander *macroExpander() const;
+ QString newKitName(const QList<Kit *> &allKits) const;
+ static QString newKitName(const QString &name, const QList<Kit *> &allKits);
+
private:
+ static void copyKitCommon(Kit *target, const Kit *source);
void setSdkProvided(bool sdkProvided);
// Unimplemented.
@@ -142,7 +157,7 @@ private:
const std::unique_ptr<Internal::KitPrivate> d;
- friend class KitInformation;
+ friend class KitAspect;
friend class KitManager;
friend class Internal::KitManagerPrivate;
friend class Internal::KitModel; // needed for setAutoDetected() when cloning kits
diff --git a/src/plugins/projectexplorer/kitchooser.cpp b/src/plugins/projectexplorer/kitchooser.cpp
index 9e0b4b25f1..c3a0204fba 100644
--- a/src/plugins/projectexplorer/kitchooser.cpp
+++ b/src/plugins/projectexplorer/kitchooser.cpp
@@ -25,7 +25,6 @@
#include "kitchooser.h"
-#include "kitconfigwidget.h"
#include "kitinformation.h"
#include "kitmanager.h"
#include "project.h"
@@ -52,7 +51,7 @@ KitChooser::KitChooser(QWidget *parent) :
{
m_chooser = new QComboBox(this);
m_chooser->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
- m_manageButton = new QPushButton(KitConfigWidget::msgManage(), this);
+ m_manageButton = new QPushButton(KitAspectWidget::msgManage(), this);
auto layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
@@ -60,9 +59,9 @@ KitChooser::KitChooser(QWidget *parent) :
layout->addWidget(m_manageButton);
setFocusProxy(m_manageButton);
- connect(m_chooser, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_chooser, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &KitChooser::onCurrentIndexChanged);
- connect(m_chooser, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_chooser, QOverload<int>::of(&QComboBox::activated),
this, &KitChooser::onActivated);
connect(m_manageButton, &QAbstractButton::clicked, this, &KitChooser::onManageButtonClicked);
connect(KitManager::instance(), &KitManager::kitsChanged, this, &KitChooser::populate);
@@ -73,6 +72,11 @@ void KitChooser::onManageButtonClicked()
Core::ICore::showOptionsDialog(Constants::KITS_SETTINGS_PAGE_ID, this);
}
+void KitChooser::setShowIcons(bool showIcons)
+{
+ m_showIcons = showIcons;
+}
+
void KitChooser::onCurrentIndexChanged()
{
const Id id = Id::fromSetting(m_chooser->currentData());
@@ -128,9 +132,12 @@ void KitChooser::populate()
foreach (Kit *kit, KitManager::sortKits(KitManager::kits())) {
if (m_kitPredicate(kit)) {
m_chooser->addItem(kitText(kit), kit->id().toSetting());
- m_chooser->setItemData(m_chooser->count() - 1, kitToolTip(kit), Qt::ToolTipRole);
+ const int pos = m_chooser->count() - 1;
+ m_chooser->setItemData(pos, kitToolTip(kit), Qt::ToolTipRole);
+ if (m_showIcons)
+ m_chooser->setItemData(pos, kit->displayIcon(), Qt::DecorationRole);
if (!didActivate && kit->id() == lastKit) {
- m_chooser->setCurrentIndex(m_chooser->count() - 1);
+ m_chooser->setCurrentIndex(pos);
didActivate = true;
}
}
diff --git a/src/plugins/projectexplorer/kitchooser.h b/src/plugins/projectexplorer/kitchooser.h
index bd7b8ce5cf..046c18f571 100644
--- a/src/plugins/projectexplorer/kitchooser.h
+++ b/src/plugins/projectexplorer/kitchooser.h
@@ -54,8 +54,10 @@ public:
Core::Id currentKitId() const;
void setKitPredicate(const Kit::Predicate &predicate);
+ void setShowIcons(bool showIcons);
Kit *currentKit() const;
+ bool hasStartupKit() const { return m_hasStartupKit; }
signals:
void currentIndexChanged();
@@ -77,6 +79,7 @@ private:
QComboBox *m_chooser;
QPushButton *m_manageButton;
bool m_hasStartupKit = false;
+ bool m_showIcons = false;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitconfigwidget.cpp b/src/plugins/projectexplorer/kitconfigwidget.cpp
deleted file mode 100644
index 4b9fbebd60..0000000000
--- a/src/plugins/projectexplorer/kitconfigwidget.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 "kitconfigwidget.h"
-
-#include "kit.h"
-#include "kitinformation.h"
-
-namespace ProjectExplorer {
-
-KitConfigWidget::KitConfigWidget(Kit *kit, const KitInformation *ki) : m_kit(kit),
- m_kitInformation(ki), m_isSticky(kit->isSticky(ki->id()))
-{ }
-
-Core::Id KitConfigWidget::kitInformationId() const
-{
- return m_kitInformation->id();
-}
-
-bool KitConfigWidget::isMutable() const
-{
- return m_kit->isMutable(m_kitInformation->id());
-}
-
-void KitConfigWidget::setMutable(bool b)
-{
- m_kit->setMutable(m_kitInformation->id(), b);
-}
-
-QString KitConfigWidget::msgManage()
-{
- return tr("Manage...");
-}
-
-void KitConfigWidget::setPalette(const QPalette &p)
-{
- if (mainWidget())
- mainWidget()->setPalette(p);
- if (buttonWidget())
- buttonWidget()->setPalette(p);
-}
-
-void KitConfigWidget::setStyle(QStyle *s)
-{
- if (mainWidget())
- mainWidget()->setStyle(s);
- if (buttonWidget())
- buttonWidget()->setStyle(s);
-}
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitconfigwidget.h b/src/plugins/projectexplorer/kitconfigwidget.h
deleted file mode 100644
index 05c7ea058b..0000000000
--- a/src/plugins/projectexplorer/kitconfigwidget.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 "projectexplorer_export.h"
-
-#include <coreplugin/id.h>
-
-#include <QWidget>
-
-namespace ProjectExplorer {
-
-class Kit;
-class KitInformation;
-
-// --------------------------------------------------------------------------
-// KitConfigWidget
-// --------------------------------------------------------------------------
-
-class PROJECTEXPLORER_EXPORT KitConfigWidget : public QObject
-{
- Q_OBJECT
-
-public:
- KitConfigWidget(Kit *kit, const KitInformation *ki);
-
- Core::Id kitInformationId() const;
-
- virtual QString displayName() const = 0;
- virtual QString toolTip() const { return QString(); }
- virtual void makeReadOnly() = 0;
- virtual void refresh() = 0;
- virtual bool visibleInKit() { return true; }
-
- virtual QWidget *mainWidget() const = 0;
- virtual QWidget *buttonWidget() const { return nullptr; }
-
- bool isSticky() const { return m_isSticky; }
- bool isMutable() const;
- void setMutable(bool b);
-
- static QString msgManage();
-
- Kit *kit() const { return m_kit; }
-
- virtual void setPalette(const QPalette &p);
- virtual void setStyle(QStyle *s);
-
-signals:
- void dirty();
-
-protected:
- Kit *m_kit;
- const KitInformation *m_kitInformation;
- bool m_isSticky;
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp
index f4da43f095..4ca258df1a 100644
--- a/src/plugins/projectexplorer/kitinformation.cpp
+++ b/src/plugins/projectexplorer/kitinformation.cpp
@@ -28,20 +28,32 @@
#include "abi.h"
#include "devicesupport/desktopdevice.h"
#include "devicesupport/devicemanager.h"
+#include "devicesupport/devicemanagermodel.h"
+#include "devicesupport/idevicefactory.h"
#include "projectexplorerconstants.h"
#include "kit.h"
-#include "kitinformationconfigwidget.h"
#include "toolchain.h"
#include "toolchainmanager.h"
+#include <coreplugin/icore.h>
+#include <coreplugin/variablechooser.h>
#include <ssh/sshconnection.h>
-
#include <utils/algorithm.h>
+#include <utils/environment.h>
+#include <utils/environmentdialog.h>
#include <utils/macroexpander.h>
+#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
+#include <QCheckBox>
+#include <QComboBox>
#include <QDir>
#include <QFileInfo>
+#include <QFontMetrics>
+#include <QGridLayout>
+#include <QLabel>
+#include <QPushButton>
+#include <QVBoxLayout>
namespace ProjectExplorer {
@@ -50,26 +62,70 @@ const char KITINFORMATION_ID_V2[] = "PE.Profile.ToolChains";
const char KITINFORMATION_ID_V3[] = "PE.Profile.ToolChainsV3";
// --------------------------------------------------------------------------
-// SysRootKitInformation:
+// SysRootKitAspect:
// --------------------------------------------------------------------------
-SysRootKitInformation::SysRootKitInformation()
+namespace Internal {
+class SysRootKitAspectWidget : public KitAspectWidget
{
- setObjectName(QLatin1String("SysRootInformation"));
- setId(SysRootKitInformation::id());
- setPriority(31000);
-}
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::SysRootKitAspect)
+
+public:
+ SysRootKitAspectWidget(Kit *k, const KitAspect *ki) : KitAspectWidget(k, ki)
+ {
+ m_chooser = new Utils::PathChooser;
+ m_chooser->setExpectedKind(Utils::PathChooser::ExistingDirectory);
+ m_chooser->setHistoryCompleter(QLatin1String("PE.SysRoot.History"));
+ m_chooser->setFileName(SysRootKitAspect::sysRoot(k));
+ connect(m_chooser, &Utils::PathChooser::pathChanged,
+ this, &SysRootKitAspectWidget::pathWasChanged);
+ }
+
+ ~SysRootKitAspectWidget() override { delete m_chooser; }
+
+private:
+ void makeReadOnly() override { m_chooser->setReadOnly(true); }
+ QWidget *buttonWidget() const override { return m_chooser->buttonAtIndex(0); }
+ QWidget *mainWidget() const override { return m_chooser->lineEdit(); }
+
+ void refresh() override
+ {
+ if (!m_ignoreChange)
+ m_chooser->setFileName(SysRootKitAspect::sysRoot(m_kit));
+ }
+
+ void setPalette(const QPalette &p) override
+ {
+ KitAspectWidget::setPalette(p);
+ m_chooser->setOkColor(p.color(QPalette::Active, QPalette::Text));
+ }
+
+ void pathWasChanged()
+ {
+ m_ignoreChange = true;
+ SysRootKitAspect::setSysRoot(m_kit, m_chooser->fileName());
+ m_ignoreChange = false;
+ }
+
+ Utils::PathChooser *m_chooser;
+ bool m_ignoreChange = false;
+};
+} // namespace Internal
-QVariant SysRootKitInformation::defaultValue(const Kit *k) const
+SysRootKitAspect::SysRootKitAspect()
{
- Q_UNUSED(k)
- return QString();
+ setObjectName(QLatin1String("SysRootInformation"));
+ setId(SysRootKitAspect::id());
+ setDisplayName(tr("Sysroot"));
+ setDescription(tr("The root directory of the system image to use.<br>"
+ "Leave empty when building for the desktop."));
+ setPriority(31000);
}
-QList<Task> SysRootKitInformation::validate(const Kit *k) const
+Tasks SysRootKitAspect::validate(const Kit *k) const
{
- QList<Task> result;
- const Utils::FileName dir = SysRootKitInformation::sysRoot(k);
+ Tasks result;
+ const Utils::FilePath dir = SysRootKitAspect::sysRoot(k);
if (dir.isEmpty())
return result;
@@ -80,65 +136,65 @@ QList<Task> SysRootKitInformation::validate(const Kit *k) const
if (!fi.exists()) {
result << Task(Task::Warning, tr("Sys Root \"%1\" does not exist in the file system.").arg(dir.toUserOutput()),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
} else if (!fi.isDir()) {
result << Task(Task::Warning, tr("Sys Root \"%1\" is not a directory.").arg(dir.toUserOutput()),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
} else if (QDir(dir.toString()).entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) {
result << Task(Task::Warning, tr("Sys Root \"%1\" is empty.").arg(dir.toUserOutput()),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
}
return result;
}
-KitConfigWidget *SysRootKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *SysRootKitAspect::createConfigWidget(Kit *k) const
{
QTC_ASSERT(k, return nullptr);
- return new Internal::SysRootInformationConfigWidget(k, this);
+ return new Internal::SysRootKitAspectWidget(k, this);
}
-KitInformation::ItemList SysRootKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList SysRootKitAspect::toUserOutput(const Kit *k) const
{
- return ItemList() << qMakePair(tr("Sys Root"), sysRoot(k).toUserOutput());
+ return {{tr("Sys Root"), sysRoot(k).toUserOutput()}};
}
-void SysRootKitInformation::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
+void SysRootKitAspect::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
{
QTC_ASSERT(kit, return);
expander->registerFileVariables("SysRoot", tr("Sys Root"), [kit]() -> QString {
- return SysRootKitInformation::sysRoot(kit).toString();
+ return SysRootKitAspect::sysRoot(kit).toString();
});
}
-Core::Id SysRootKitInformation::id()
+Core::Id SysRootKitAspect::id()
{
return "PE.Profile.SysRoot";
}
-Utils::FileName SysRootKitInformation::sysRoot(const Kit *k)
+Utils::FilePath SysRootKitAspect::sysRoot(const Kit *k)
{
if (!k)
- return Utils::FileName();
+ return Utils::FilePath();
- if (!k->value(SysRootKitInformation::id()).toString().isEmpty())
- return Utils::FileName::fromString(k->value(SysRootKitInformation::id()).toString());
+ if (!k->value(SysRootKitAspect::id()).toString().isEmpty())
+ return Utils::FilePath::fromString(k->value(SysRootKitAspect::id()).toString());
- for (ToolChain *tc : ToolChainKitInformation::toolChains(k)) {
+ for (ToolChain *tc : ToolChainKitAspect::toolChains(k)) {
if (!tc->sysRoot().isEmpty())
- return Utils::FileName::fromString(tc->sysRoot());
+ return Utils::FilePath::fromString(tc->sysRoot());
}
- return Utils::FileName();
+ return Utils::FilePath();
}
-void SysRootKitInformation::setSysRoot(Kit *k, const Utils::FileName &v)
+void SysRootKitAspect::setSysRoot(Kit *k, const Utils::FilePath &v)
{
if (!k)
return;
- for (ToolChain *tc : ToolChainKitInformation::toolChains(k)) {
+ for (ToolChain *tc : ToolChainKitAspect::toolChains(k)) {
if (!tc->sysRoot().isEmpty()) {
// It's the sysroot from toolchain, don't set it.
if (tc->sysRoot() == v.toString())
@@ -148,21 +204,145 @@ void SysRootKitInformation::setSysRoot(Kit *k, const Utils::FileName &v)
break;
}
}
- k->setValue(SysRootKitInformation::id(), v.toString());
+ k->setValue(SysRootKitAspect::id(), v.toString());
}
// --------------------------------------------------------------------------
-// ToolChainKitInformation:
+// ToolChainKitAspect:
// --------------------------------------------------------------------------
-ToolChainKitInformation::ToolChainKitInformation()
+namespace Internal {
+class ToolChainKitAspectWidget : public KitAspectWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::ToolChainKitAspect)
+
+public:
+ ToolChainKitAspectWidget(Kit *k, const KitAspect *ki) : KitAspectWidget(k, ki)
+ {
+ m_mainWidget = new QWidget;
+ m_mainWidget->setContentsMargins(0, 0, 0, 0);
+
+ auto layout = new QGridLayout(m_mainWidget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setColumnStretch(1, 2);
+
+ QList<Core::Id> languageList = ToolChainManager::allLanguages().toList();
+ Utils::sort(languageList, [](Core::Id l1, Core::Id l2) {
+ return ToolChainManager::displayNameOfLanguageId(l1)
+ < ToolChainManager::displayNameOfLanguageId(l2);
+ });
+ QTC_ASSERT(!languageList.isEmpty(), return);
+ int row = 0;
+ foreach (Core::Id l, languageList) {
+ layout->addWidget(new QLabel(ToolChainManager::displayNameOfLanguageId(l) + ':'), row, 0);
+ auto cb = new QComboBox;
+ cb->setSizePolicy(QSizePolicy::Ignored, cb->sizePolicy().verticalPolicy());
+ cb->setToolTip(ki->description());
+
+ m_languageComboboxMap.insert(l, cb);
+ layout->addWidget(cb, row, 1);
+ ++row;
+
+ connect(cb, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, [this, l](int idx) { currentToolChainChanged(l, idx); });
+ }
+
+ refresh();
+
+ m_manageButton = new QPushButton(KitAspectWidget::msgManage());
+ m_manageButton->setContentsMargins(0, 0, 0, 0);
+ connect(m_manageButton, &QAbstractButton::clicked,
+ this, &ToolChainKitAspectWidget::manageToolChains);
+ }
+
+ ~ToolChainKitAspectWidget() override
+ {
+ delete m_mainWidget;
+ delete m_manageButton;
+ }
+
+private:
+ QWidget *mainWidget() const override { return m_mainWidget; }
+ QWidget *buttonWidget() const override { return m_manageButton; }
+
+ void refresh() override
+ {
+ m_ignoreChanges = true;
+ foreach (Core::Id l, m_languageComboboxMap.keys()) {
+ const QList<ToolChain *> ltcList
+ = ToolChainManager::toolChains(Utils::equal(&ToolChain::language, l));
+
+ QComboBox *cb = m_languageComboboxMap.value(l);
+ cb->clear();
+ cb->addItem(tr("<No compiler>"), QByteArray());
+
+ foreach (ToolChain *tc, ltcList)
+ cb->addItem(tc->displayName(), tc->id());
+
+ cb->setEnabled(cb->count() > 1 && !m_isReadOnly);
+ const int index = indexOf(cb, ToolChainKitAspect::toolChain(m_kit, l));
+ cb->setCurrentIndex(index);
+ }
+ m_ignoreChanges = false;
+ }
+
+ void makeReadOnly() override
+ {
+ m_isReadOnly = true;
+ foreach (Core::Id l, m_languageComboboxMap.keys()) {
+ m_languageComboboxMap.value(l)->setEnabled(false);
+ }
+ }
+
+ void manageToolChains()
+ {
+ Core::ICore::showOptionsDialog(Constants::TOOLCHAIN_SETTINGS_PAGE_ID, buttonWidget());
+ }
+
+ void currentToolChainChanged(Core::Id language, int idx)
+ {
+ if (m_ignoreChanges || idx < 0)
+ return;
+
+ const QByteArray id = m_languageComboboxMap.value(language)->itemData(idx).toByteArray();
+ ToolChain *tc = ToolChainManager::findToolChain(id);
+ QTC_ASSERT(!tc || tc->language() == language, return);
+ if (tc)
+ ToolChainKitAspect::setToolChain(m_kit, tc);
+ else
+ ToolChainKitAspect::clearToolChain(m_kit, language);
+ }
+
+ int indexOf(QComboBox *cb, const ToolChain *tc)
+ {
+ const QByteArray id = tc ? tc->id() : QByteArray();
+ for (int i = 0; i < cb->count(); ++i) {
+ if (id == cb->itemData(i).toByteArray())
+ return i;
+ }
+ return -1;
+ }
+
+ QWidget *m_mainWidget = nullptr;
+ QPushButton *m_manageButton = nullptr;
+ QHash<Core::Id, QComboBox *> m_languageComboboxMap;
+ bool m_ignoreChanges = false;
+ bool m_isReadOnly = false;
+};
+} // namespace Internal
+
+ToolChainKitAspect::ToolChainKitAspect()
{
setObjectName(QLatin1String("ToolChainInformation"));
- setId(ToolChainKitInformation::id());
+ setId(ToolChainKitAspect::id());
+ setDisplayName(tr("Compiler"));
+ setDescription(tr("The compiler to use for building.<br>"
+ "Make sure the compiler will produce binaries compatible "
+ "with the target device, Qt version and other libraries used."));
setPriority(30000);
connect(KitManager::instance(), &KitManager::kitsLoaded,
- this, &ToolChainKitInformation::kitsWereLoaded);
+ this, &ToolChainKitAspect::kitsWereLoaded);
}
// language id -> tool chain id
@@ -189,20 +369,14 @@ static QVariant defaultToolChainValue()
return result;
}
-QVariant ToolChainKitInformation::defaultValue(const Kit *k) const
+Tasks ToolChainKitAspect::validate(const Kit *k) const
{
- Q_UNUSED(k);
- return defaultToolChainValue();
-}
-
-QList<Task> ToolChainKitInformation::validate(const Kit *k) const
-{
- QList<Task> result;
+ Tasks result;
const QList<ToolChain*> tcList = toolChains(k);
if (tcList.isEmpty()) {
- result << Task(Task::Warning, ToolChainKitInformation::msgNoToolChainInTarget(),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
+ result << Task(Task::Warning, ToolChainKitAspect::msgNoToolChainInTarget(),
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
} else {
QSet<Abi> targetAbis;
foreach (ToolChain *tc, tcList) {
@@ -212,13 +386,13 @@ QList<Task> ToolChainKitInformation::validate(const Kit *k) const
if (targetAbis.count() != 1) {
result << Task(Task::Error, tr("Compilers produce code for different ABIs: %1")
.arg(Utils::transform(targetAbis, &Abi::toString).toList().join(", ")),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
return result;
}
-void ToolChainKitInformation::upgrade(Kit *k)
+void ToolChainKitAspect::upgrade(Kit *k)
{
QTC_ASSERT(k, return);
@@ -238,7 +412,7 @@ void ToolChainKitInformation::upgrade(Kit *k)
// Used up to 4.1:
newValue.insert(Deprecated::Toolchain::languageId(Deprecated::Toolchain::Cxx), oldValue.toString());
- const Core::Id typeId = DeviceTypeKitInformation::deviceTypeId(k);
+ const Core::Id typeId = DeviceTypeKitAspect::deviceTypeId(k);
if (typeId == Constants::DESKTOP_DEVICE_TYPE) {
// insert default C compiler which did not exist before
newValue.insert(Deprecated::Toolchain::languageId(Deprecated::Toolchain::C),
@@ -253,7 +427,7 @@ void ToolChainKitInformation::upgrade(Kit *k)
// upgrade 4.2 to 4.3 (keep old settings around for now)
{
const QVariant oldValue = k->value(oldIdV2);
- const QVariant value = k->value(ToolChainKitInformation::id());
+ const QVariant value = k->value(ToolChainKitAspect::id());
if (value.isNull() && !oldValue.isNull()) {
QVariantMap newValue = oldValue.toMap();
QVariantMap::iterator it = newValue.find(Deprecated::Toolchain::languageId(Deprecated::Toolchain::C));
@@ -262,14 +436,14 @@ void ToolChainKitInformation::upgrade(Kit *k)
it = newValue.find(Deprecated::Toolchain::languageId(Deprecated::Toolchain::Cxx));
if (it != newValue.end())
newValue.insert(Core::Id(Constants::CXX_LANGUAGE_ID).toString(), it.value());
- k->setValue(ToolChainKitInformation::id(), newValue);
- k->setSticky(ToolChainKitInformation::id(), k->isSticky(oldIdV2));
+ k->setValue(ToolChainKitAspect::id(), newValue);
+ k->setSticky(ToolChainKitAspect::id(), k->isSticky(oldIdV2));
}
}
// upgrade 4.3-temporary-master-state to 4.3:
{
- const QVariantMap valueMap = k->value(ToolChainKitInformation::id()).toMap();
+ const QVariantMap valueMap = k->value(ToolChainKitAspect::id()).toMap();
QVariantMap result;
for (const QString &key : valueMap.keys()) {
const int pos = key.lastIndexOf('.');
@@ -278,11 +452,11 @@ void ToolChainKitInformation::upgrade(Kit *k)
else
result.insert(key, valueMap.value(key));
}
- k->setValue(ToolChainKitInformation::id(), result);
+ k->setValue(ToolChainKitAspect::id(), result);
}
}
-void ToolChainKitInformation::fix(Kit *k)
+void ToolChainKitAspect::fix(Kit *k)
{
QTC_ASSERT(ToolChainManager::isLoaded(), return);
foreach (const Core::Id& l, ToolChainManager::allLanguages()) {
@@ -303,12 +477,14 @@ static Core::Id findLanguage(const QString &ls)
[lsUpper](Core::Id l) { return lsUpper == l.toString().toUpper(); });
}
-void ToolChainKitInformation::setup(Kit *k)
+void ToolChainKitAspect::setup(Kit *k)
{
QTC_ASSERT(ToolChainManager::isLoaded(), return);
QTC_ASSERT(k, return);
- const QVariantMap value = k->value(ToolChainKitInformation::id()).toMap();
+ QVariantMap value = k->value(id()).toMap();
+ if (value.empty())
+ value = defaultToolChainValue().toMap();
for (auto i = value.constBegin(); i != value.constEnd(); ++i) {
Core::Id l = findLanguage(i.key());
@@ -333,32 +509,32 @@ void ToolChainKitInformation::setup(Kit *k)
}
}
-KitConfigWidget *ToolChainKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *ToolChainKitAspect::createConfigWidget(Kit *k) const
{
QTC_ASSERT(k, return nullptr);
- return new Internal::ToolChainInformationConfigWidget(k, this);
+ return new Internal::ToolChainKitAspectWidget(k, this);
}
-QString ToolChainKitInformation::displayNamePostfix(const Kit *k) const
+QString ToolChainKitAspect::displayNamePostfix(const Kit *k) const
{
ToolChain *tc = toolChain(k, Constants::CXX_LANGUAGE_ID);
return tc ? tc->displayName() : QString();
}
-KitInformation::ItemList ToolChainKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList ToolChainKitAspect::toUserOutput(const Kit *k) const
{
ToolChain *tc = toolChain(k, Constants::CXX_LANGUAGE_ID);
- return ItemList() << qMakePair(tr("Compiler"), tc ? tc->displayName() : tr("None"));
+ return {{tr("Compiler"), tc ? tc->displayName() : tr("None")}};
}
-void ToolChainKitInformation::addToEnvironment(const Kit *k, Utils::Environment &env) const
+void ToolChainKitAspect::addToEnvironment(const Kit *k, Utils::Environment &env) const
{
ToolChain *tc = toolChain(k, Constants::CXX_LANGUAGE_ID);
if (tc)
tc->addToEnvironment(env);
}
-void ToolChainKitInformation::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
+void ToolChainKitAspect::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
{
QTC_ASSERT(kit, return);
@@ -388,7 +564,7 @@ void ToolChainKitInformation::addToMacroExpander(Kit *kit, Utils::MacroExpander
}
-IOutputParser *ToolChainKitInformation::createOutputParser(const Kit *k) const
+IOutputParser *ToolChainKitAspect::createOutputParser(const Kit *k) const
{
for (const Core::Id langId : {Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID}) {
if (const ToolChain * const tc = toolChain(k, langId))
@@ -397,7 +573,7 @@ IOutputParser *ToolChainKitInformation::createOutputParser(const Kit *k) const
return nullptr;
}
-QSet<Core::Id> ToolChainKitInformation::availableFeatures(const Kit *k) const
+QSet<Core::Id> ToolChainKitAspect::availableFeatures(const Kit *k) const
{
QSet<Core::Id> result;
for (ToolChain *tc : toolChains(k))
@@ -405,30 +581,30 @@ QSet<Core::Id> ToolChainKitInformation::availableFeatures(const Kit *k) const
return result;
}
-Core::Id ToolChainKitInformation::id()
+Core::Id ToolChainKitAspect::id()
{
return KITINFORMATION_ID_V3;
}
-QByteArray ToolChainKitInformation::toolChainId(const Kit *k, Core::Id language)
+QByteArray ToolChainKitAspect::toolChainId(const Kit *k, Core::Id language)
{
QTC_ASSERT(ToolChainManager::isLoaded(), return nullptr);
if (!k)
return QByteArray();
- QVariantMap value = k->value(ToolChainKitInformation::id()).toMap();
+ QVariantMap value = k->value(ToolChainKitAspect::id()).toMap();
return value.value(language.toString(), QByteArray()).toByteArray();
}
-ToolChain *ToolChainKitInformation::toolChain(const Kit *k, Core::Id language)
+ToolChain *ToolChainKitAspect::toolChain(const Kit *k, Core::Id language)
{
return ToolChainManager::findToolChain(toolChainId(k, language));
}
-QList<ToolChain *> ToolChainKitInformation::toolChains(const Kit *k)
+QList<ToolChain *> ToolChainKitAspect::toolChains(const Kit *k)
{
QTC_ASSERT(k, return QList<ToolChain *>());
- const QVariantMap value = k->value(ToolChainKitInformation::id()).toMap();
+ const QVariantMap value = k->value(ToolChainKitAspect::id()).toMap();
const QList<ToolChain *> tcList
= Utils::transform(ToolChainManager::allLanguages().toList(),
[&value](Core::Id l) -> ToolChain * {
@@ -437,18 +613,18 @@ QList<ToolChain *> ToolChainKitInformation::toolChains(const Kit *k)
return Utils::filtered(tcList, [](ToolChain *tc) { return tc; });
}
-void ToolChainKitInformation::setToolChain(Kit *k, ToolChain *tc)
+void ToolChainKitAspect::setToolChain(Kit *k, ToolChain *tc)
{
QTC_ASSERT(tc, return);
QTC_ASSERT(k, return);
- QVariantMap result = k->value(ToolChainKitInformation::id()).toMap();
+ QVariantMap result = k->value(ToolChainKitAspect::id()).toMap();
result.insert(tc->language().toString(), tc->id());
k->setValue(id(), result);
}
/**
- * @brief ToolChainKitInformation::setAllToolChainsToMatch
+ * @brief ToolChainKitAspect::setAllToolChainsToMatch
*
* Set up all toolchains to be similar to the one toolchain provided. Similar ideally means
* that all toolchains use the "same" compiler from the same installation, but we will
@@ -457,7 +633,7 @@ void ToolChainKitInformation::setToolChain(Kit *k, ToolChain *tc)
* @param k The kit to set up
* @param tc The toolchain to match other languages for.
*/
-void ToolChainKitInformation::setAllToolChainsToMatch(Kit *k, ToolChain *tc)
+void ToolChainKitAspect::setAllToolChainsToMatch(Kit *k, ToolChain *tc)
{
QTC_ASSERT(tc, return);
QTC_ASSERT(k, return);
@@ -465,7 +641,7 @@ void ToolChainKitInformation::setAllToolChainsToMatch(Kit *k, ToolChain *tc)
const QList<ToolChain *> allTcList = ToolChainManager::toolChains();
QTC_ASSERT(allTcList.contains(tc), return);
- QVariantMap result = k->value(ToolChainKitInformation::id()).toMap();
+ QVariantMap result = k->value(ToolChainKitAspect::id()).toMap();
result.insert(tc->language().toString(), tc->id());
for (Core::Id l : ToolChainManager::allLanguages()) {
@@ -496,17 +672,17 @@ void ToolChainKitInformation::setAllToolChainsToMatch(Kit *k, ToolChain *tc)
k->setValue(id(), result);
}
-void ToolChainKitInformation::clearToolChain(Kit *k, Core::Id language)
+void ToolChainKitAspect::clearToolChain(Kit *k, Core::Id language)
{
QTC_ASSERT(language.isValid(), return);
QTC_ASSERT(k, return);
- QVariantMap result = k->value(ToolChainKitInformation::id()).toMap();
+ QVariantMap result = k->value(ToolChainKitAspect::id()).toMap();
result.insert(language.toString(), QByteArray());
k->setValue(id(), result);
}
-Abi ToolChainKitInformation::targetAbi(const Kit *k)
+Abi ToolChainKitAspect::targetAbi(const Kit *k)
{
QList<ToolChain *> tcList = toolChains(k);
// Find the best possible ABI for all the tool chains...
@@ -539,29 +715,29 @@ Abi ToolChainKitInformation::targetAbi(const Kit *k)
return candidates.at(0); // Use basically a random Abi...
}
-QString ToolChainKitInformation::msgNoToolChainInTarget()
+QString ToolChainKitAspect::msgNoToolChainInTarget()
{
return tr("No compiler set in kit.");
}
-void ToolChainKitInformation::kitsWereLoaded()
+void ToolChainKitAspect::kitsWereLoaded()
{
foreach (Kit *k, KitManager::kits())
fix(k);
connect(ToolChainManager::instance(), &ToolChainManager::toolChainRemoved,
- this, &ToolChainKitInformation::toolChainRemoved);
+ this, &ToolChainKitAspect::toolChainRemoved);
connect(ToolChainManager::instance(), &ToolChainManager::toolChainUpdated,
- this, &ToolChainKitInformation::toolChainUpdated);
+ this, &ToolChainKitAspect::toolChainUpdated);
}
-void ToolChainKitInformation::toolChainUpdated(ToolChain *tc)
+void ToolChainKitAspect::toolChainUpdated(ToolChain *tc)
{
for (Kit *k : KitManager::kits([tc](const Kit *k) { return toolChain(k, tc->language()) == tc; }))
notifyAboutUpdate(k);
}
-void ToolChainKitInformation::toolChainRemoved(ToolChain *tc)
+void ToolChainKitAspect::toolChainRemoved(ToolChain *tc)
{
Q_UNUSED(tc);
foreach (Kit *k, KitManager::kits())
@@ -569,35 +745,83 @@ void ToolChainKitInformation::toolChainRemoved(ToolChain *tc)
}
// --------------------------------------------------------------------------
-// DeviceTypeKitInformation:
+// DeviceTypeKitAspect:
// --------------------------------------------------------------------------
+namespace Internal {
+class DeviceTypeKitAspectWidget : public KitAspectWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::DeviceTypeKitAspect)
+
+public:
+ DeviceTypeKitAspectWidget(Kit *workingCopy, const KitAspect *ki)
+ : KitAspectWidget(workingCopy, ki), m_comboBox(new QComboBox)
+ {
+ for (IDeviceFactory *factory : IDeviceFactory::allDeviceFactories())
+ m_comboBox->addItem(factory->displayName(), factory->deviceType().toSetting());
+ m_comboBox->setToolTip(ki->description());
+ refresh();
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &DeviceTypeKitAspectWidget::currentTypeChanged);
+ }
-DeviceTypeKitInformation::DeviceTypeKitInformation()
+ ~DeviceTypeKitAspectWidget() override { delete m_comboBox; }
+
+private:
+ QWidget *mainWidget() const override { return m_comboBox; }
+ void makeReadOnly() override { m_comboBox->setEnabled(false); }
+
+ void refresh() override
+ {
+ Core::Id devType = DeviceTypeKitAspect::deviceTypeId(m_kit);
+ if (!devType.isValid())
+ m_comboBox->setCurrentIndex(-1);
+ for (int i = 0; i < m_comboBox->count(); ++i) {
+ if (m_comboBox->itemData(i) == devType.toSetting()) {
+ m_comboBox->setCurrentIndex(i);
+ break;
+ }
+ }
+ }
+
+ void currentTypeChanged(int idx)
+ {
+ Core::Id type = idx < 0 ? Core::Id() : Core::Id::fromSetting(m_comboBox->itemData(idx));
+ DeviceTypeKitAspect::setDeviceTypeId(m_kit, type);
+ }
+
+ QComboBox *m_comboBox;
+};
+} // namespace Internal
+
+DeviceTypeKitAspect::DeviceTypeKitAspect()
{
setObjectName(QLatin1String("DeviceTypeInformation"));
- setId(DeviceTypeKitInformation::id());
+ setId(DeviceTypeKitAspect::id());
+ setDisplayName(tr("Device type"));
+ setDescription(tr("The type of device to run applications on."));
setPriority(33000);
+ makeEssential();
}
-QVariant DeviceTypeKitInformation::defaultValue(const Kit *k) const
+void DeviceTypeKitAspect::setup(Kit *k)
{
- Q_UNUSED(k);
- return QByteArray(Constants::DESKTOP_DEVICE_TYPE);
+ if (k && !k->hasValue(id()))
+ k->setValue(id(), QByteArray(Constants::DESKTOP_DEVICE_TYPE));
}
-QList<Task> DeviceTypeKitInformation::validate(const Kit *k) const
+Tasks DeviceTypeKitAspect::validate(const Kit *k) const
{
Q_UNUSED(k);
- return QList<Task>();
+ return {};
}
-KitConfigWidget *DeviceTypeKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *DeviceTypeKitAspect::createConfigWidget(Kit *k) const
{
QTC_ASSERT(k, return nullptr);
- return new Internal::DeviceTypeInformationConfigWidget(k, this);
+ return new Internal::DeviceTypeKitAspectWidget(k, this);
}
-KitInformation::ItemList DeviceTypeKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList DeviceTypeKitAspect::toUserOutput(const Kit *k) const
{
QTC_ASSERT(k, return {});
Core::Id type = deviceTypeId(k);
@@ -606,60 +830,133 @@ KitInformation::ItemList DeviceTypeKitInformation::toUserOutput(const Kit *k) co
if (IDeviceFactory *factory = IDeviceFactory::find(type))
typeDisplayName = factory->displayName();
}
- return ItemList() << qMakePair(tr("Device type"), typeDisplayName);
+ return {{tr("Device type"), typeDisplayName}};
}
-const Core::Id DeviceTypeKitInformation::id()
+const Core::Id DeviceTypeKitAspect::id()
{
return "PE.Profile.DeviceType";
}
-const Core::Id DeviceTypeKitInformation::deviceTypeId(const Kit *k)
+const Core::Id DeviceTypeKitAspect::deviceTypeId(const Kit *k)
{
- return k ? Core::Id::fromSetting(k->value(DeviceTypeKitInformation::id())) : Core::Id();
+ return k ? Core::Id::fromSetting(k->value(DeviceTypeKitAspect::id())) : Core::Id();
}
-void DeviceTypeKitInformation::setDeviceTypeId(Kit *k, Core::Id type)
+void DeviceTypeKitAspect::setDeviceTypeId(Kit *k, Core::Id type)
{
QTC_ASSERT(k, return);
- k->setValue(DeviceTypeKitInformation::id(), type.toSetting());
+ k->setValue(DeviceTypeKitAspect::id(), type.toSetting());
}
-Kit::Predicate DeviceTypeKitInformation::deviceTypePredicate(Core::Id type)
-{
- return [type](const Kit *kit) { return type.isValid() && deviceTypeId(kit) == type; };
-}
-
-QSet<Core::Id> DeviceTypeKitInformation::supportedPlatforms(const Kit *k) const
+QSet<Core::Id> DeviceTypeKitAspect::supportedPlatforms(const Kit *k) const
{
return {deviceTypeId(k)};
}
-QSet<Core::Id> DeviceTypeKitInformation::availableFeatures(const Kit *k) const
+QSet<Core::Id> DeviceTypeKitAspect::availableFeatures(const Kit *k) const
{
- Core::Id id = DeviceTypeKitInformation::deviceTypeId(k);
+ Core::Id id = DeviceTypeKitAspect::deviceTypeId(k);
if (id.isValid())
return {id.withPrefix("DeviceType.")};
return QSet<Core::Id>();
}
// --------------------------------------------------------------------------
-// DeviceKitInformation:
+// DeviceKitAspect:
// --------------------------------------------------------------------------
+namespace Internal {
+class DeviceKitAspectWidget : public KitAspectWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::DeviceKitAspect)
-DeviceKitInformation::DeviceKitInformation()
+public:
+ DeviceKitAspectWidget(Kit *workingCopy, const KitAspect *ki)
+ : KitAspectWidget(workingCopy, ki), m_comboBox(new QComboBox),
+ m_model(new DeviceManagerModel(DeviceManager::instance()))
+ {
+ m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
+ m_comboBox->setModel(m_model);
+ m_manageButton = new QPushButton(KitAspectWidget::msgManage());
+ refresh();
+ m_comboBox->setToolTip(ki->description());
+
+ connect(m_model, &QAbstractItemModel::modelAboutToBeReset,
+ this, &DeviceKitAspectWidget::modelAboutToReset);
+ connect(m_model, &QAbstractItemModel::modelReset,
+ this, &DeviceKitAspectWidget::modelReset);
+ connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &DeviceKitAspectWidget::currentDeviceChanged);
+ connect(m_manageButton, &QAbstractButton::clicked,
+ this, &DeviceKitAspectWidget::manageDevices);
+ }
+
+ ~DeviceKitAspectWidget() override
+ {
+ delete m_comboBox;
+ delete m_model;
+ delete m_manageButton;
+ }
+
+private:
+ QWidget *mainWidget() const override { return m_comboBox; }
+ QWidget *buttonWidget() const override { return m_manageButton; }
+ void makeReadOnly() override { m_comboBox->setEnabled(false); }
+
+ void refresh() override
+ {
+ m_model->setTypeFilter(DeviceTypeKitAspect::deviceTypeId(m_kit));
+ m_comboBox->setCurrentIndex(m_model->indexOf(DeviceKitAspect::device(m_kit)));
+ }
+
+ void manageDevices()
+ {
+ Core::ICore::showOptionsDialog(Constants::DEVICE_SETTINGS_PAGE_ID, buttonWidget());
+ }
+
+ void modelAboutToReset()
+ {
+ m_selectedId = m_model->deviceId(m_comboBox->currentIndex());
+ m_ignoreChange = true;
+ }
+
+ void modelReset()
+ {
+ m_comboBox->setCurrentIndex(m_model->indexForId(m_selectedId));
+ m_ignoreChange = false;
+ }
+
+ void currentDeviceChanged()
+ {
+ if (m_ignoreChange)
+ return;
+ DeviceKitAspect::setDeviceId(m_kit, m_model->deviceId(m_comboBox->currentIndex()));
+ }
+
+ bool m_isReadOnly = false;
+ bool m_ignoreChange = false;
+ QComboBox *m_comboBox;
+ QPushButton *m_manageButton;
+ DeviceManagerModel *m_model;
+ Core::Id m_selectedId;
+};
+} // namespace Internal
+
+DeviceKitAspect::DeviceKitAspect()
{
setObjectName(QLatin1String("DeviceInformation"));
- setId(DeviceKitInformation::id());
+ setId(DeviceKitAspect::id());
+ setDisplayName(tr("Device"));
+ setDescription(tr("The device to run the applications on."));
setPriority(32000);
connect(KitManager::instance(), &KitManager::kitsLoaded,
- this, &DeviceKitInformation::kitsWereLoaded);
+ this, &DeviceKitAspect::kitsWereLoaded);
}
-QVariant DeviceKitInformation::defaultValue(const Kit *k) const
+QVariant DeviceKitAspect::defaultValue(const Kit *k) const
{
- Core::Id type = DeviceTypeKitInformation::deviceTypeId(k);
+ Core::Id type = DeviceTypeKitAspect::deviceTypeId(k);
// Use default device if that is compatible:
IDevice::ConstPtr dev = DeviceManager::instance()->defaultDevice(type);
if (dev && dev->isCompatibleWith(k))
@@ -674,23 +971,23 @@ QVariant DeviceKitInformation::defaultValue(const Kit *k) const
return QString();
}
-QList<Task> DeviceKitInformation::validate(const Kit *k) const
+Tasks DeviceKitAspect::validate(const Kit *k) const
{
- IDevice::ConstPtr dev = DeviceKitInformation::device(k);
- QList<Task> result;
+ IDevice::ConstPtr dev = DeviceKitAspect::device(k);
+ Tasks result;
if (dev.isNull())
result.append(Task(Task::Warning, tr("No device set."),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)));
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)));
else if (!dev->isCompatibleWith(k))
result.append(Task(Task::Error, tr("Device is incompatible with this kit."),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)));
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)));
return result;
}
-void DeviceKitInformation::fix(Kit *k)
+void DeviceKitAspect::fix(Kit *k)
{
- IDevice::ConstPtr dev = DeviceKitInformation::device(k);
+ IDevice::ConstPtr dev = DeviceKitAspect::device(k);
if (!dev.isNull() && !dev->isCompatibleWith(k)) {
qWarning("Device is no longer compatible with kit \"%s\", removing it.",
qPrintable(k->displayName()));
@@ -698,109 +995,109 @@ void DeviceKitInformation::fix(Kit *k)
}
}
-void DeviceKitInformation::setup(Kit *k)
+void DeviceKitAspect::setup(Kit *k)
{
QTC_ASSERT(DeviceManager::instance()->isLoaded(), return);
- IDevice::ConstPtr dev = DeviceKitInformation::device(k);
+ IDevice::ConstPtr dev = DeviceKitAspect::device(k);
if (!dev.isNull() && dev->isCompatibleWith(k))
return;
setDeviceId(k, Core::Id::fromSetting(defaultValue(k)));
}
-KitConfigWidget *DeviceKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *DeviceKitAspect::createConfigWidget(Kit *k) const
{
QTC_ASSERT(k, return nullptr);
- return new Internal::DeviceInformationConfigWidget(k, this);
+ return new Internal::DeviceKitAspectWidget(k, this);
}
-QString DeviceKitInformation::displayNamePostfix(const Kit *k) const
+QString DeviceKitAspect::displayNamePostfix(const Kit *k) const
{
IDevice::ConstPtr dev = device(k);
return dev.isNull() ? QString() : dev->displayName();
}
-KitInformation::ItemList DeviceKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList DeviceKitAspect::toUserOutput(const Kit *k) const
{
IDevice::ConstPtr dev = device(k);
- return ItemList() << qMakePair(tr("Device"), dev.isNull() ? tr("Unconfigured") : dev->displayName());
+ return {{tr("Device"), dev.isNull() ? tr("Unconfigured") : dev->displayName()}};
}
-void DeviceKitInformation::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
+void DeviceKitAspect::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
{
QTC_ASSERT(kit, return);
expander->registerVariable("Device:HostAddress", tr("Host address"),
[kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? device->sshParameters().host() : QString();
});
expander->registerVariable("Device:SshPort", tr("SSH port"),
[kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? QString::number(device->sshParameters().port()) : QString();
});
expander->registerVariable("Device:UserName", tr("User name"),
[kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? device->sshParameters().userName() : QString();
});
expander->registerVariable("Device:KeyFile", tr("Private key file"),
[kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? device->sshParameters().privateKeyFile : QString();
});
expander->registerVariable("Device:Name", tr("Device name"),
[kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? device->displayName() : QString();
});
}
-Core::Id DeviceKitInformation::id()
+Core::Id DeviceKitAspect::id()
{
return "PE.Profile.Device";
}
-IDevice::ConstPtr DeviceKitInformation::device(const Kit *k)
+IDevice::ConstPtr DeviceKitAspect::device(const Kit *k)
{
QTC_ASSERT(DeviceManager::instance()->isLoaded(), return IDevice::ConstPtr());
return DeviceManager::instance()->find(deviceId(k));
}
-Core::Id DeviceKitInformation::deviceId(const Kit *k)
+Core::Id DeviceKitAspect::deviceId(const Kit *k)
{
- return k ? Core::Id::fromSetting(k->value(DeviceKitInformation::id())) : Core::Id();
+ return k ? Core::Id::fromSetting(k->value(DeviceKitAspect::id())) : Core::Id();
}
-void DeviceKitInformation::setDevice(Kit *k, IDevice::ConstPtr dev)
+void DeviceKitAspect::setDevice(Kit *k, IDevice::ConstPtr dev)
{
setDeviceId(k, dev ? dev->id() : Core::Id());
}
-void DeviceKitInformation::setDeviceId(Kit *k, Core::Id id)
+void DeviceKitAspect::setDeviceId(Kit *k, Core::Id id)
{
QTC_ASSERT(k, return);
- k->setValue(DeviceKitInformation::id(), id.toSetting());
+ k->setValue(DeviceKitAspect::id(), id.toSetting());
}
-void DeviceKitInformation::kitsWereLoaded()
+void DeviceKitAspect::kitsWereLoaded()
{
foreach (Kit *k, KitManager::kits())
fix(k);
DeviceManager *dm = DeviceManager::instance();
- connect(dm, &DeviceManager::deviceListReplaced, this, &DeviceKitInformation::devicesChanged);
- connect(dm, &DeviceManager::deviceAdded, this, &DeviceKitInformation::devicesChanged);
- connect(dm, &DeviceManager::deviceRemoved, this, &DeviceKitInformation::devicesChanged);
- connect(dm, &DeviceManager::deviceUpdated, this, &DeviceKitInformation::deviceUpdated);
+ connect(dm, &DeviceManager::deviceListReplaced, this, &DeviceKitAspect::devicesChanged);
+ connect(dm, &DeviceManager::deviceAdded, this, &DeviceKitAspect::devicesChanged);
+ connect(dm, &DeviceManager::deviceRemoved, this, &DeviceKitAspect::devicesChanged);
+ connect(dm, &DeviceManager::deviceUpdated, this, &DeviceKitAspect::deviceUpdated);
connect(KitManager::instance(), &KitManager::kitUpdated,
- this, &DeviceKitInformation::kitUpdated);
+ this, &DeviceKitAspect::kitUpdated);
connect(KitManager::instance(), &KitManager::unmanagedKitUpdated,
- this, &DeviceKitInformation::kitUpdated);
+ this, &DeviceKitAspect::kitUpdated);
}
-void DeviceKitInformation::deviceUpdated(Core::Id id)
+void DeviceKitAspect::deviceUpdated(Core::Id id)
{
foreach (Kit *k, KitManager::kits()) {
if (deviceId(k) == id)
@@ -808,59 +1105,160 @@ void DeviceKitInformation::deviceUpdated(Core::Id id)
}
}
-void DeviceKitInformation::kitUpdated(Kit *k)
+void DeviceKitAspect::kitUpdated(Kit *k)
{
setup(k); // Set default device if necessary
}
-void DeviceKitInformation::devicesChanged()
+void DeviceKitAspect::devicesChanged()
{
foreach (Kit *k, KitManager::kits())
setup(k); // Set default device if necessary
}
// --------------------------------------------------------------------------
-// EnvironmentKitInformation:
+// EnvironmentKitAspect:
// --------------------------------------------------------------------------
-
-EnvironmentKitInformation::EnvironmentKitInformation()
+namespace Internal {
+class EnvironmentKitAspectWidget : public KitAspectWidget
{
- setObjectName(QLatin1String("EnvironmentKitInformation"));
- setId(EnvironmentKitInformation::id());
- setPriority(29000);
-}
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::EnvironmentKitAspect)
-QVariant EnvironmentKitInformation::defaultValue(const Kit *k) const
+public:
+ EnvironmentKitAspectWidget(Kit *workingCopy, const KitAspect *ki)
+ : KitAspectWidget(workingCopy, ki),
+ m_summaryLabel(new QLabel),
+ m_manageButton(new QPushButton),
+ m_mainWidget(new QWidget)
+ {
+ auto *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(m_summaryLabel);
+ if (Utils::HostOsInfo::isWindowsHost())
+ initMSVCOutputSwitch(layout);
+ m_mainWidget->setLayout(layout);
+ refresh();
+ m_manageButton->setText(tr("Change..."));
+ connect(m_manageButton, &QAbstractButton::clicked,
+ this, &EnvironmentKitAspectWidget::editEnvironmentChanges);
+ }
+
+private:
+ QWidget *mainWidget() const override { return m_mainWidget; }
+ QWidget *buttonWidget() const override { return m_manageButton; }
+ void makeReadOnly() override { m_manageButton->setEnabled(false); }
+
+ void refresh() override
+ {
+ const QList<Utils::EnvironmentItem> changes = currentEnvironment();
+ QString shortSummary = Utils::EnvironmentItem::toStringList(changes).join(QLatin1String("; "));
+ QFontMetrics fm(m_summaryLabel->font());
+ shortSummary = fm.elidedText(shortSummary, Qt::ElideRight, m_summaryLabel->width());
+ m_summaryLabel->setText(shortSummary.isEmpty() ? tr("No changes to apply.") : shortSummary);
+ }
+
+ void editEnvironmentChanges()
+ {
+ bool ok;
+ Utils::MacroExpander *expander = m_kit->macroExpander();
+ Utils::EnvironmentDialog::Polisher polisher = [expander](QWidget *w) {
+ Core::VariableChooser::addSupportForChildWidgets(w, expander);
+ };
+ QList<Utils::EnvironmentItem>
+ changes = Utils::EnvironmentDialog::getEnvironmentItems(&ok,
+ m_summaryLabel,
+ currentEnvironment(),
+ QString(),
+ polisher);
+ if (!ok)
+ return;
+
+ if (Utils::HostOsInfo::isWindowsHost()) {
+ const Utils::EnvironmentItem forceMSVCEnglishItem("VSLANG", "1033");
+ if (m_vslangCheckbox->isChecked() && changes.indexOf(forceMSVCEnglishItem) < 0)
+ changes.append(forceMSVCEnglishItem);
+ }
+
+ EnvironmentKitAspect::setEnvironmentChanges(m_kit, changes);
+ }
+
+ QList<Utils::EnvironmentItem> currentEnvironment() const
+ {
+ QList<Utils::EnvironmentItem> changes = EnvironmentKitAspect::environmentChanges(m_kit);
+
+ if (Utils::HostOsInfo::isWindowsHost()) {
+ const Utils::EnvironmentItem forceMSVCEnglishItem("VSLANG", "1033");
+ if (changes.indexOf(forceMSVCEnglishItem) >= 0) {
+ m_vslangCheckbox->setCheckState(Qt::Checked);
+ changes.removeAll(forceMSVCEnglishItem);
+ }
+ }
+
+ Utils::sort(changes, [](const Utils::EnvironmentItem &lhs, const Utils::EnvironmentItem &rhs)
+ { return QString::localeAwareCompare(lhs.name, rhs.name) < 0; });
+ return changes;
+ }
+
+ void initMSVCOutputSwitch(QVBoxLayout *layout)
+ {
+ m_vslangCheckbox = new QCheckBox(tr("Force UTF-8 MSVC compiler output"));
+ layout->addWidget(m_vslangCheckbox);
+ m_vslangCheckbox->setToolTip(tr("Either switches MSVC to English or keeps the language and "
+ "just forces UTF-8 output (may vary depending on the used MSVC "
+ "compiler)."));
+ connect(m_vslangCheckbox, &QCheckBox::toggled, this, [this](bool checked) {
+ QList<Utils::EnvironmentItem> changes
+ = EnvironmentKitAspect::environmentChanges(m_kit);
+ const Utils::EnvironmentItem forceMSVCEnglishItem("VSLANG", "1033");
+ if (!checked && changes.indexOf(forceMSVCEnglishItem) >= 0)
+ changes.removeAll(forceMSVCEnglishItem);
+ if (checked && changes.indexOf(forceMSVCEnglishItem) < 0)
+ changes.append(forceMSVCEnglishItem);
+ EnvironmentKitAspect::setEnvironmentChanges(m_kit, changes);
+ });
+ }
+
+ QLabel *m_summaryLabel;
+ QPushButton *m_manageButton;
+ QCheckBox *m_vslangCheckbox;
+ QWidget *m_mainWidget;
+};
+} // namespace Internal
+
+EnvironmentKitAspect::EnvironmentKitAspect()
{
- Q_UNUSED(k)
- return QStringList();
+ setObjectName(QLatin1String("EnvironmentKitAspect"));
+ setId(EnvironmentKitAspect::id());
+ setDisplayName(tr("Environment"));
+ setDescription(tr("Additional build environment settings when using this kit."));
+ setPriority(29000);
}
-QList<Task> EnvironmentKitInformation::validate(const Kit *k) const
+Tasks EnvironmentKitAspect::validate(const Kit *k) const
{
- QList<Task> result;
+ Tasks result;
QTC_ASSERT(k, return result);
- const QVariant variant = k->value(EnvironmentKitInformation::id());
+ const QVariant variant = k->value(EnvironmentKitAspect::id());
if (!variant.isNull() && !variant.canConvert(QVariant::List)) {
result.append(Task(Task::Error, tr("The environment setting value is invalid."),
- Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)));
+ Utils::FilePath(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)));
}
return result;
}
-void EnvironmentKitInformation::fix(Kit *k)
+void EnvironmentKitAspect::fix(Kit *k)
{
QTC_ASSERT(k, return);
- const QVariant variant = k->value(EnvironmentKitInformation::id());
+ const QVariant variant = k->value(EnvironmentKitAspect::id());
if (!variant.isNull() && !variant.canConvert(QVariant::List)) {
qWarning("Kit \"%s\" has a wrong environment value set.", qPrintable(k->displayName()));
setEnvironmentChanges(k, QList<Utils::EnvironmentItem>());
}
}
-void EnvironmentKitInformation::addToEnvironment(const Kit *k, Utils::Environment &env) const
+void EnvironmentKitAspect::addToEnvironment(const Kit *k, Utils::Environment &env) const
{
const QStringList values
= Utils::transform(Utils::EnvironmentItem::toStringList(environmentChanges(k)),
@@ -868,34 +1266,34 @@ void EnvironmentKitInformation::addToEnvironment(const Kit *k, Utils::Environmen
env.modify(Utils::EnvironmentItem::fromStringList(values));
}
-KitConfigWidget *EnvironmentKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *EnvironmentKitAspect::createConfigWidget(Kit *k) const
{
QTC_ASSERT(k, return nullptr);
- return new Internal::KitEnvironmentConfigWidget(k, this);
+ return new Internal::EnvironmentKitAspectWidget(k, this);
}
-KitInformation::ItemList EnvironmentKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList EnvironmentKitAspect::toUserOutput(const Kit *k) const
{
return { qMakePair(tr("Environment"),
Utils::EnvironmentItem::toStringList(environmentChanges(k)).join("<br>")) };
}
-Core::Id EnvironmentKitInformation::id()
+Core::Id EnvironmentKitAspect::id()
{
return "PE.Profile.Environment";
}
-QList<Utils::EnvironmentItem> EnvironmentKitInformation::environmentChanges(const Kit *k)
+QList<Utils::EnvironmentItem> EnvironmentKitAspect::environmentChanges(const Kit *k)
{
if (k)
- return Utils::EnvironmentItem::fromStringList(k->value(EnvironmentKitInformation::id()).toStringList());
+ return Utils::EnvironmentItem::fromStringList(k->value(EnvironmentKitAspect::id()).toStringList());
return QList<Utils::EnvironmentItem>();
}
-void EnvironmentKitInformation::setEnvironmentChanges(Kit *k, const QList<Utils::EnvironmentItem> &changes)
+void EnvironmentKitAspect::setEnvironmentChanges(Kit *k, const QList<Utils::EnvironmentItem> &changes)
{
if (k)
- k->setValue(EnvironmentKitInformation::id(), Utils::EnvironmentItem::toStringList(changes));
+ k->setValue(EnvironmentKitAspect::id(), Utils::EnvironmentItem::toStringList(changes));
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitinformation.h b/src/plugins/projectexplorer/kitinformation.h
index c32dbefa27..037b4b9394 100644
--- a/src/plugins/projectexplorer/kitinformation.h
+++ b/src/plugins/projectexplorer/kitinformation.h
@@ -37,52 +37,46 @@
namespace ProjectExplorer {
-class KitConfigWidget;
+class KitAspectWidget;
// --------------------------------------------------------------------------
// SysRootInformation:
// --------------------------------------------------------------------------
-class PROJECTEXPLORER_EXPORT SysRootKitInformation : public KitInformation
+class PROJECTEXPLORER_EXPORT SysRootKitAspect : public KitAspect
{
Q_OBJECT
public:
- SysRootKitInformation();
-
- QVariant defaultValue(const Kit *k) const override;
-
- QList<Task> validate(const Kit *k) const override;
-
- KitConfigWidget *createConfigWidget(Kit *k) const override;
+ SysRootKitAspect();
+ Tasks validate(const Kit *k) const override;
+ KitAspectWidget *createConfigWidget(Kit *k) const override;
ItemList toUserOutput(const Kit *k) const override;
void addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const override;
static Core::Id id();
- static Utils::FileName sysRoot(const Kit *k);
- static void setSysRoot(Kit *k, const Utils::FileName &v);
+ static Utils::FilePath sysRoot(const Kit *k);
+ static void setSysRoot(Kit *k, const Utils::FilePath &v);
};
// --------------------------------------------------------------------------
// ToolChainInformation:
// --------------------------------------------------------------------------
-class PROJECTEXPLORER_EXPORT ToolChainKitInformation : public KitInformation
+class PROJECTEXPLORER_EXPORT ToolChainKitAspect : public KitAspect
{
Q_OBJECT
public:
- ToolChainKitInformation();
+ ToolChainKitAspect();
- QVariant defaultValue(const Kit *k) const override;
-
- QList<Task> validate(const Kit *k) const override;
+ Tasks validate(const Kit *k) const override;
void upgrade(Kit *k) override;
void fix(Kit *k) override;
void setup(Kit *k) override;
- KitConfigWidget *createConfigWidget(Kit *k) const override;
+ KitAspectWidget *createConfigWidget(Kit *k) const override;
QString displayNamePostfix(const Kit *k) const override;
@@ -114,27 +108,22 @@ private:
// DeviceTypeInformation:
// --------------------------------------------------------------------------
-class PROJECTEXPLORER_EXPORT DeviceTypeKitInformation : public KitInformation
+class PROJECTEXPLORER_EXPORT DeviceTypeKitAspect : public KitAspect
{
Q_OBJECT
public:
- DeviceTypeKitInformation();
-
- QVariant defaultValue(const Kit *k) const override;
-
- QList<Task> validate(const Kit *k) const override;
-
- KitConfigWidget *createConfigWidget(Kit *k) const override;
+ DeviceTypeKitAspect();
+ void setup(Kit *k) override;
+ Tasks validate(const Kit *k) const override;
+ KitAspectWidget *createConfigWidget(Kit *k) const override;
ItemList toUserOutput(const Kit *k) const override;
static const Core::Id id();
static const Core::Id deviceTypeId(const Kit *k);
static void setDeviceTypeId(Kit *k, Core::Id type);
- static Kit::Predicate deviceTypePredicate(Core::Id type);
-
QSet<Core::Id> supportedPlatforms(const Kit *k) const override;
QSet<Core::Id> availableFeatures(const Kit *k) const override;
};
@@ -143,20 +132,18 @@ public:
// DeviceInformation:
// --------------------------------------------------------------------------
-class PROJECTEXPLORER_EXPORT DeviceKitInformation : public KitInformation
+class PROJECTEXPLORER_EXPORT DeviceKitAspect : public KitAspect
{
Q_OBJECT
public:
- DeviceKitInformation();
+ DeviceKitAspect();
- QVariant defaultValue(const Kit *k) const override;
-
- QList<Task> validate(const Kit *k) const override;
+ Tasks validate(const Kit *k) const override;
void fix(Kit *k) override;
void setup(Kit *k) override;
- KitConfigWidget *createConfigWidget(Kit *k) const override;
+ KitAspectWidget *createConfigWidget(Kit *k) const override;
QString displayNamePostfix(const Kit *k) const override;
@@ -171,6 +158,8 @@ public:
static void setDeviceId(Kit *k, Core::Id dataId);
private:
+ QVariant defaultValue(const Kit *k) const;
+
void kitsWereLoaded();
void deviceUpdated(Core::Id dataId);
void devicesChanged();
@@ -178,23 +167,21 @@ private:
};
// --------------------------------------------------------------------------
-// EnvironmentKitInformation:
+// EnvironmentKitAspect:
// --------------------------------------------------------------------------
-class PROJECTEXPLORER_EXPORT EnvironmentKitInformation : public KitInformation
+class PROJECTEXPLORER_EXPORT EnvironmentKitAspect : public KitAspect
{
Q_OBJECT
public:
- EnvironmentKitInformation();
-
- QVariant defaultValue(const Kit *k) const override;
+ EnvironmentKitAspect();
- QList<Task> validate(const Kit *k) const override;
+ Tasks validate(const Kit *k) const override;
void fix(Kit *k) override;
void addToEnvironment(const Kit *k, Utils::Environment &env) const override;
- KitConfigWidget *createConfigWidget(Kit *k) const override;
+ KitAspectWidget *createConfigWidget(Kit *k) const override;
ItemList toUserOutput(const Kit *k) const override;
diff --git a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp b/src/plugins/projectexplorer/kitinformationconfigwidget.cpp
deleted file mode 100644
index a366d84646..0000000000
--- a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "kitinformationconfigwidget.h"
-
-#include "devicesupport/devicemanager.h"
-#include "devicesupport/devicemanagermodel.h"
-#include "devicesupport/idevicefactory.h"
-#include "projectexplorerconstants.h"
-#include "kit.h"
-#include "kitinformation.h"
-#include "toolchain.h"
-#include "toolchainmanager.h"
-#include "environmentwidget.h"
-
-#include <coreplugin/icore.h>
-#include <coreplugin/variablechooser.h>
-
-#include <utils/algorithm.h>
-#include <utils/fancylineedit.h>
-#include <utils/environment.h>
-#include <utils/qtcassert.h>
-#include <utils/pathchooser.h>
-#include <utils/environmentdialog.h>
-
-#include <QCheckBox>
-#include <QComboBox>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QFontMetrics>
-#include <QLabel>
-#include <QPlainTextEdit>
-#include <QPushButton>
-#include <QVBoxLayout>
-
-using namespace Core;
-
-namespace ProjectExplorer {
-namespace Internal {
-
-// --------------------------------------------------------------------------
-// SysRootInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-SysRootInformationConfigWidget::SysRootInformationConfigWidget(Kit *k, const KitInformation *ki) :
- KitConfigWidget(k, ki)
-{
- m_chooser = new Utils::PathChooser;
- m_chooser->setExpectedKind(Utils::PathChooser::ExistingDirectory);
- m_chooser->setHistoryCompleter(QLatin1String("PE.SysRoot.History"));
- m_chooser->setFileName(SysRootKitInformation::sysRoot(k));
- connect(m_chooser, &Utils::PathChooser::pathChanged,
- this, &SysRootInformationConfigWidget::pathWasChanged);
-}
-
-SysRootInformationConfigWidget::~SysRootInformationConfigWidget()
-{
- delete m_chooser;
-}
-
-QString SysRootInformationConfigWidget::displayName() const
-{
- return tr("Sysroot");
-}
-
-QString SysRootInformationConfigWidget::toolTip() const
-{
- return tr("The root directory of the system image to use.<br>"
- "Leave empty when building for the desktop.");
-}
-
-void SysRootInformationConfigWidget::setPalette(const QPalette &p)
-{
- KitConfigWidget::setPalette(p);
- m_chooser->setOkColor(p.color(QPalette::Active, QPalette::Text));
-}
-
-void SysRootInformationConfigWidget::refresh()
-{
- if (!m_ignoreChange)
- m_chooser->setFileName(SysRootKitInformation::sysRoot(m_kit));
-}
-
-void SysRootInformationConfigWidget::makeReadOnly()
-{
- m_chooser->setReadOnly(true);
-}
-
-QWidget *SysRootInformationConfigWidget::mainWidget() const
-{
- return m_chooser->lineEdit();
-}
-
-QWidget *SysRootInformationConfigWidget::buttonWidget() const
-{
- return m_chooser->buttonAtIndex(0);
-}
-
-void SysRootInformationConfigWidget::pathWasChanged()
-{
- m_ignoreChange = true;
- SysRootKitInformation::setSysRoot(m_kit, m_chooser->fileName());
- m_ignoreChange = false;
-}
-
-// --------------------------------------------------------------------------
-// ToolChainInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-ToolChainInformationConfigWidget::ToolChainInformationConfigWidget(Kit *k, const KitInformation *ki) :
- KitConfigWidget(k, ki)
-{
- m_mainWidget = new QWidget;
- m_mainWidget->setContentsMargins(0, 0, 0, 0);
-
- auto layout = new QGridLayout(m_mainWidget);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setColumnStretch(1, 2);
-
- int row = 0;
- QList<Core::Id> languageList = ToolChainManager::allLanguages().toList();
- Utils::sort(languageList, [](Core::Id l1, Core::Id l2) {
- return ToolChainManager::displayNameOfLanguageId(l1) < ToolChainManager::displayNameOfLanguageId(l2);
- });
-
- QTC_ASSERT(!languageList.isEmpty(), return);
-
- foreach (Core::Id l, languageList) {
- layout->addWidget(new QLabel(ToolChainManager::displayNameOfLanguageId(l) + ':'), row, 0);
- auto cb = new QComboBox;
- cb->setSizePolicy(QSizePolicy::Ignored, cb->sizePolicy().verticalPolicy());
- cb->setToolTip(toolTip());
-
- m_languageComboboxMap.insert(l, cb);
- layout->addWidget(cb, row, 1);
- ++row;
-
- connect(cb, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, [this, l](int idx) { currentToolChainChanged(l, idx); });
- }
-
- refresh();
-
- m_manageButton = new QPushButton(KitConfigWidget::msgManage());
- m_manageButton->setContentsMargins(0, 0, 0, 0);
- connect(m_manageButton, &QAbstractButton::clicked,
- this, &ToolChainInformationConfigWidget::manageToolChains);
-}
-
-ToolChainInformationConfigWidget::~ToolChainInformationConfigWidget()
-{
- delete m_mainWidget;
- delete m_manageButton;
-}
-
-QString ToolChainInformationConfigWidget::displayName() const
-{
- return tr("Compiler");
-}
-
-QString ToolChainInformationConfigWidget::toolTip() const
-{
- return tr("The compiler to use for building.<br>"
- "Make sure the compiler will produce binaries compatible with the target device, "
- "Qt version and other libraries used.");
-}
-
-void ToolChainInformationConfigWidget::refresh()
-{
- m_ignoreChanges = true;
-
- foreach (Core::Id l, m_languageComboboxMap.keys()) {
- const QList<ToolChain *> ltcList
- = ToolChainManager::toolChains(Utils::equal(&ToolChain::language, l));
-
- QComboBox *cb = m_languageComboboxMap.value(l);
- cb->clear();
- cb->addItem(tr("<No compiler>"), QByteArray());
-
- foreach (ToolChain *tc, ltcList)
- cb->addItem(tc->displayName(), tc->id());
-
- cb->setEnabled(cb->count() > 1 && !m_isReadOnly);
- const int index = indexOf(cb, ToolChainKitInformation::toolChain(m_kit, l));
- cb->setCurrentIndex(index);
- }
- m_ignoreChanges = false;
-}
-
-void ToolChainInformationConfigWidget::makeReadOnly()
-{
- m_isReadOnly = true;
- foreach (Core::Id l, m_languageComboboxMap.keys()) {
- m_languageComboboxMap.value(l)->setEnabled(false);
- }
-}
-
-QWidget *ToolChainInformationConfigWidget::mainWidget() const
-{
- return m_mainWidget;
-}
-
-QWidget *ToolChainInformationConfigWidget::buttonWidget() const
-{
- return m_manageButton;
-}
-
-void ToolChainInformationConfigWidget::manageToolChains()
-{
- ICore::showOptionsDialog(Constants::TOOLCHAIN_SETTINGS_PAGE_ID, buttonWidget());
-}
-
-void ToolChainInformationConfigWidget::currentToolChainChanged(Id language, int idx)
-{
- if (m_ignoreChanges || idx < 0)
- return;
-
- const QByteArray id = m_languageComboboxMap.value(language)->itemData(idx).toByteArray();
- ToolChain *tc = ToolChainManager::findToolChain(id);
- QTC_ASSERT(!tc || tc->language() == language, return);
- if (tc)
- ToolChainKitInformation::setToolChain(m_kit, tc);
- else
- ToolChainKitInformation::clearToolChain(m_kit, language);
-}
-
-int ToolChainInformationConfigWidget::indexOf(QComboBox *cb, const ToolChain *tc)
-{
- const QByteArray id = tc ? tc->id() : QByteArray();
- for (int i = 0; i < cb->count(); ++i) {
- if (id == cb->itemData(i).toByteArray())
- return i;
- }
- return -1;
-}
-
-// --------------------------------------------------------------------------
-// DeviceTypeInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-DeviceTypeInformationConfigWidget::DeviceTypeInformationConfigWidget(Kit *workingCopy, const KitInformation *ki) :
- KitConfigWidget(workingCopy, ki), m_comboBox(new QComboBox)
-{
- for (IDeviceFactory *factory : IDeviceFactory::allDeviceFactories())
- m_comboBox->addItem(factory->displayName(), factory->deviceType().toSetting());
-
- m_comboBox->setToolTip(toolTip());
-
- refresh();
- connect(m_comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &DeviceTypeInformationConfigWidget::currentTypeChanged);
-}
-
-DeviceTypeInformationConfigWidget::~DeviceTypeInformationConfigWidget()
-{
- delete m_comboBox;
-}
-
-QWidget *DeviceTypeInformationConfigWidget::mainWidget() const
-{
- return m_comboBox;
-}
-
-QString DeviceTypeInformationConfigWidget::displayName() const
-{
- return tr("Device type");
-}
-
-QString DeviceTypeInformationConfigWidget::toolTip() const
-{
- return tr("The type of device to run applications on.");
-}
-
-void DeviceTypeInformationConfigWidget::refresh()
-{
- Id devType = DeviceTypeKitInformation::deviceTypeId(m_kit);
- if (!devType.isValid())
- m_comboBox->setCurrentIndex(-1);
- for (int i = 0; i < m_comboBox->count(); ++i) {
- if (m_comboBox->itemData(i) == devType.toSetting()) {
- m_comboBox->setCurrentIndex(i);
- break;
- }
- }
-}
-
-void DeviceTypeInformationConfigWidget::makeReadOnly()
-{
- m_comboBox->setEnabled(false);
-}
-
-void DeviceTypeInformationConfigWidget::currentTypeChanged(int idx)
-{
- Id type = idx < 0 ? Id() : Id::fromSetting(m_comboBox->itemData(idx));
- DeviceTypeKitInformation::setDeviceTypeId(m_kit, type);
-}
-
-// --------------------------------------------------------------------------
-// DeviceInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-DeviceInformationConfigWidget::DeviceInformationConfigWidget(Kit *workingCopy, const KitInformation *ki) :
- KitConfigWidget(workingCopy, ki),
- m_comboBox(new QComboBox),
- m_model(new DeviceManagerModel(DeviceManager::instance()))
-{
- m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
- m_comboBox->setModel(m_model);
-
- m_manageButton = new QPushButton(KitConfigWidget::msgManage());
-
- refresh();
- m_comboBox->setToolTip(toolTip());
-
- connect(m_model, &QAbstractItemModel::modelAboutToBeReset,
- this, &DeviceInformationConfigWidget::modelAboutToReset);
- connect(m_model, &QAbstractItemModel::modelReset,
- this, &DeviceInformationConfigWidget::modelReset);
- connect(m_comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &DeviceInformationConfigWidget::currentDeviceChanged);
- connect(m_manageButton, &QAbstractButton::clicked,
- this, &DeviceInformationConfigWidget::manageDevices);
-}
-
-DeviceInformationConfigWidget::~DeviceInformationConfigWidget()
-{
- delete m_comboBox;
- delete m_model;
- delete m_manageButton;
-}
-
-QWidget *DeviceInformationConfigWidget::mainWidget() const
-{
- return m_comboBox;
-}
-
-QString DeviceInformationConfigWidget::displayName() const
-{
- return tr("Device");
-}
-
-QString DeviceInformationConfigWidget::toolTip() const
-{
- return tr("The device to run the applications on.");
-}
-
-void DeviceInformationConfigWidget::refresh()
-{
- m_model->setTypeFilter(DeviceTypeKitInformation::deviceTypeId(m_kit));
- m_comboBox->setCurrentIndex(m_model->indexOf(DeviceKitInformation::device(m_kit)));
-}
-
-void DeviceInformationConfigWidget::makeReadOnly()
-{
- m_comboBox->setEnabled(false);
-}
-
-QWidget *DeviceInformationConfigWidget::buttonWidget() const
-{
- return m_manageButton;
-}
-
-void DeviceInformationConfigWidget::manageDevices()
-{
- ICore::showOptionsDialog(Constants::DEVICE_SETTINGS_PAGE_ID, buttonWidget());
-}
-
-void DeviceInformationConfigWidget::modelAboutToReset()
-{
- m_selectedId = m_model->deviceId(m_comboBox->currentIndex());
- m_ignoreChange = true;
-}
-
-void DeviceInformationConfigWidget::modelReset()
-{
- m_comboBox->setCurrentIndex(m_model->indexForId(m_selectedId));
- m_ignoreChange = false;
-}
-
-void DeviceInformationConfigWidget::currentDeviceChanged()
-{
- if (m_ignoreChange)
- return;
- DeviceKitInformation::setDeviceId(m_kit, m_model->deviceId(m_comboBox->currentIndex()));
-}
-
-// --------------------------------------------------------------------
-// KitEnvironmentConfigWidget:
-// --------------------------------------------------------------------
-
-KitEnvironmentConfigWidget::KitEnvironmentConfigWidget(Kit *workingCopy, const KitInformation *ki) :
- KitConfigWidget(workingCopy, ki),
- m_summaryLabel(new QLabel),
- m_manageButton(new QPushButton),
- m_mainWidget(new QWidget)
-{
- auto *layout = new QVBoxLayout;
- layout->setContentsMargins(0, 0, 0, 0);
- layout->addWidget(m_summaryLabel);
- if (Utils::HostOsInfo::isWindowsHost())
- initMSVCOutputSwitch(layout);
-
- m_mainWidget->setLayout(layout);
-
- refresh();
- m_manageButton->setText(tr("Change..."));
- connect(m_manageButton, &QAbstractButton::clicked,
- this, &KitEnvironmentConfigWidget::editEnvironmentChanges);
-}
-
-QWidget *KitEnvironmentConfigWidget::mainWidget() const
-{
- return m_mainWidget;
-}
-
-QString KitEnvironmentConfigWidget::displayName() const
-{
- return tr("Environment");
-}
-
-QString KitEnvironmentConfigWidget::toolTip() const
-{
- return tr("Additional build environment settings when using this kit.");
-}
-
-void KitEnvironmentConfigWidget::refresh()
-{
- const QList<Utils::EnvironmentItem> changes = currentEnvironment();
- QString shortSummary = Utils::EnvironmentItem::toStringList(changes).join(QLatin1String("; "));
- QFontMetrics fm(m_summaryLabel->font());
- shortSummary = fm.elidedText(shortSummary, Qt::ElideRight, m_summaryLabel->width());
- m_summaryLabel->setText(shortSummary.isEmpty() ? tr("No changes to apply.") : shortSummary);
-}
-
-void KitEnvironmentConfigWidget::makeReadOnly()
-{
- m_manageButton->setEnabled(false);
-}
-
-QList<Utils::EnvironmentItem> KitEnvironmentConfigWidget::currentEnvironment() const
-{
- QList<Utils::EnvironmentItem> changes = EnvironmentKitInformation::environmentChanges(m_kit);
-
- if (Utils::HostOsInfo::isWindowsHost()) {
- const Utils::EnvironmentItem forceMSVCEnglishItem("VSLANG", "1033");
- if (changes.indexOf(forceMSVCEnglishItem) >= 0) {
- m_vslangCheckbox->setCheckState(Qt::Checked);
- changes.removeAll(forceMSVCEnglishItem);
- }
- }
-
- Utils::sort(changes, [](const Utils::EnvironmentItem &lhs, const Utils::EnvironmentItem &rhs)
- { return QString::localeAwareCompare(lhs.name, rhs.name) < 0; });
- return changes;
-}
-
-void KitEnvironmentConfigWidget::editEnvironmentChanges()
-{
- bool ok;
- Utils::MacroExpander *expander = m_kit->macroExpander();
- Utils::EnvironmentDialog::Polisher polisher = [expander](QWidget *w) {
- Core::VariableChooser::addSupportForChildWidgets(w, expander);
- };
- QList<Utils::EnvironmentItem>
- changes = Utils::EnvironmentDialog::getEnvironmentItems(&ok,
- m_summaryLabel,
- currentEnvironment(),
- QString(),
- polisher);
- if (!ok)
- return;
-
- if (Utils::HostOsInfo::isWindowsHost()) {
- const Utils::EnvironmentItem forceMSVCEnglishItem("VSLANG", "1033");
- if (m_vslangCheckbox->isChecked() && changes.indexOf(forceMSVCEnglishItem) < 0)
- changes.append(forceMSVCEnglishItem);
- }
-
- EnvironmentKitInformation::setEnvironmentChanges(m_kit, changes);
-}
-
-QWidget *KitEnvironmentConfigWidget::buttonWidget() const
-{
- return m_manageButton;
-}
-
-void KitEnvironmentConfigWidget::initMSVCOutputSwitch(QVBoxLayout *layout)
-{
- m_vslangCheckbox = new QCheckBox(tr("Force UTF-8 MSVC compiler output"));
- layout->addWidget(m_vslangCheckbox);
- m_vslangCheckbox->setToolTip(tr("Either switches MSVC to English or keeps the language and "
- "just forces UTF-8 output (may vary depending on the used MSVC "
- "compiler)."));
- connect(m_vslangCheckbox, &QCheckBox::toggled, this, [this](bool checked) {
- QList<Utils::EnvironmentItem> changes
- = EnvironmentKitInformation::environmentChanges(m_kit);
- const Utils::EnvironmentItem forceMSVCEnglishItem("VSLANG", "1033");
- if (!checked && changes.indexOf(forceMSVCEnglishItem) >= 0)
- changes.removeAll(forceMSVCEnglishItem);
- if (checked && changes.indexOf(forceMSVCEnglishItem) < 0)
- changes.append(forceMSVCEnglishItem);
- EnvironmentKitInformation::setEnvironmentChanges(m_kit, changes);
- });
-}
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitinformationconfigwidget.h b/src/plugins/projectexplorer/kitinformationconfigwidget.h
deleted file mode 100644
index 5fb6016d8c..0000000000
--- a/src/plugins/projectexplorer/kitinformationconfigwidget.h
+++ /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.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "kitconfigwidget.h"
-#include "toolchain.h"
-
-#include <coreplugin/id.h>
-
-#include <utils/environment.h>
-
-QT_BEGIN_NAMESPACE
-class QCheckBox;
-class QComboBox;
-class QLabel;
-class QPlainTextEdit;
-class QPushButton;
-class QVBoxLayout;
-QT_END_NAMESPACE
-
-namespace Utils { class PathChooser; }
-
-namespace ProjectExplorer {
-
-class DeviceManagerModel;
-
-namespace Internal {
-
-// --------------------------------------------------------------------------
-// SysRootInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-class SysRootInformationConfigWidget : public KitConfigWidget
-{
- Q_OBJECT
-
-public:
- SysRootInformationConfigWidget(Kit *k, const KitInformation *ki);
- ~SysRootInformationConfigWidget() override;
-
- QString displayName() const override;
- void refresh() override;
- void makeReadOnly() override;
- QWidget *buttonWidget() const override;
- QWidget *mainWidget() const override;
- QString toolTip() const override;
-
- void setPalette(const QPalette &p) override;
-
-private:
- void pathWasChanged();
-
- Utils::PathChooser *m_chooser;
- bool m_ignoreChange = false;
-};
-
-// --------------------------------------------------------------------------
-// ToolChainInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-class ToolChainInformationConfigWidget : public KitConfigWidget
-{
- Q_OBJECT
-
-public:
- ToolChainInformationConfigWidget(Kit *k, const KitInformation *ki);
- ~ToolChainInformationConfigWidget() override;
-
- QString displayName() const override;
- void refresh() override;
- void makeReadOnly() override;
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
- QString toolTip() const override;
-
-private:
- void manageToolChains();
- void currentToolChainChanged(Core::Id language, int idx);
-
- int indexOf(QComboBox *cb, const ToolChain *tc);
-
- QWidget *m_mainWidget = nullptr;
- QPushButton *m_manageButton = nullptr;
- QHash<Core::Id, QComboBox *> m_languageComboboxMap;
- bool m_ignoreChanges = false;
- bool m_isReadOnly = false;
-};
-
-// --------------------------------------------------------------------------
-// DeviceTypeInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-class DeviceTypeInformationConfigWidget : public KitConfigWidget
-{
- Q_OBJECT
-
-public:
- DeviceTypeInformationConfigWidget(Kit *workingCopy, const KitInformation *ki);
- ~DeviceTypeInformationConfigWidget() override;
-
- QWidget *mainWidget() const override;
- QString displayName() const override;
- QString toolTip() const override;
- void refresh() override;
- void makeReadOnly() override;
-
-private:
- void currentTypeChanged(int idx);
-
- QComboBox *m_comboBox;
-};
-
-// --------------------------------------------------------------------------
-// DeviceInformationConfigWidget:
-// --------------------------------------------------------------------------
-
-class DeviceInformationConfigWidget : public KitConfigWidget
-{
- Q_OBJECT
-
-public:
- DeviceInformationConfigWidget(Kit *workingCopy, const KitInformation *ki);
- ~DeviceInformationConfigWidget() override;
-
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
- QString displayName() const override;
- QString toolTip() const override;
- void refresh() override;
- void makeReadOnly() override;
-
-private:
- void manageDevices();
- void modelAboutToReset();
- void modelReset();
- void currentDeviceChanged();
-
- bool m_isReadOnly = false;
- bool m_ignoreChange = false;
- QComboBox *m_comboBox;
- QPushButton *m_manageButton;
- DeviceManagerModel *m_model;
- Core::Id m_selectedId;
-};
-
-class KitEnvironmentConfigWidget : public KitConfigWidget
-{
- Q_OBJECT
-
-public:
- KitEnvironmentConfigWidget(Kit *workingCopy, const KitInformation *ki);
-
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
- QString displayName() const override;
- QString toolTip() const override;
- void refresh() override;
- void makeReadOnly() override;
-
-private:
- void editEnvironmentChanges();
- QList<Utils::EnvironmentItem> currentEnvironment() const;
-
- void initMSVCOutputSwitch(QVBoxLayout *layout);
-
- QLabel *m_summaryLabel;
- QPushButton *m_manageButton;
- QCheckBox *m_vslangCheckbox;
- QWidget *m_mainWidget;
-};
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp
index 0b6e5a8b16..91d04b6f5d 100644
--- a/src/plugins/projectexplorer/kitmanager.cpp
+++ b/src/plugins/projectexplorer/kitmanager.cpp
@@ -25,12 +25,16 @@
#include "kitmanager.h"
+#include "abi.h"
#include "devicesupport/idevicefactory.h"
#include "kit.h"
#include "kitfeatureprovider.h"
+#include "kitinformation.h"
#include "kitmanagerconfigwidget.h"
#include "project.h"
+#include "projectexplorerconstants.h"
#include "task.h"
+#include "toolchainmanager.h"
#include <coreplugin/icore.h>
@@ -40,24 +44,37 @@
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
+#include <QHash>
#include <QSettings>
+#include <QStyle>
using namespace Core;
using namespace Utils;
using namespace ProjectExplorer::Internal;
namespace ProjectExplorer {
+
+class KitList
+{
+public:
+ Core::Id defaultKit;
+ std::vector<std::unique_ptr<Kit>> kits;
+};
+
+static KitList restoreKitsHelper(const Utils::FilePath &fileName);
+
namespace Internal {
const char KIT_DATA_KEY[] = "Profile.";
const char KIT_COUNT_KEY[] = "Profile.Count";
const char KIT_FILE_VERSION_KEY[] = "Version";
const char KIT_DEFAULT_KEY[] = "Profile.Default";
+const char KIT_IRRELEVANT_ASPECTS_KEY[] = "Kit.IrrelevantAspects";
const char KIT_FILENAME[] = "/profiles.xml";
-static FileName settingsFileName()
+static FilePath settingsFileName()
{
- return FileName::fromString(ICore::userResourcePath() + KIT_FILENAME);
+ return FilePath::fromString(ICore::userResourcePath() + KIT_FILENAME);
}
// --------------------------------------------------------------------------
@@ -71,9 +88,37 @@ public:
bool m_initialized = false;
std::vector<std::unique_ptr<Kit>> m_kitList;
std::unique_ptr<PersistentSettingsWriter> m_writer;
+ QSet<Id> m_irrelevantAspects;
+
+ void addKitAspect(KitAspect *ki)
+ {
+ QTC_ASSERT(!m_aspectList.contains(ki), return);
+ m_aspectList.append(ki);
+ m_aspectListIsSorted = false;
+ }
- // Sorted by priority, in descending order.
- std::vector<std::unique_ptr<KitInformation>> m_informationList;
+ void removeKitAspect(KitAspect *ki)
+ {
+ int removed = m_aspectList.removeAll(ki);
+ QTC_CHECK(removed == 1);
+ }
+
+ const QList<KitAspect *> kitAspects()
+ {
+ if (!m_aspectListIsSorted) {
+ Utils::sort(m_aspectList, [](const KitAspect *a, const KitAspect *b) {
+ return a->priority() > b->priority();
+ });
+ m_aspectListIsSorted = true;
+ }
+ return m_aspectList;
+ }
+
+private:
+ // Sorted by priority, in descending order...
+ QList<KitAspect *> m_aspectList;
+ // ... if this here is set:
+ bool m_aspectListIsSorted = true;
};
} // namespace Internal
@@ -87,11 +132,12 @@ static KitManager *m_instance = nullptr;
KitManager *KitManager::instance()
{
+ if (!m_instance)
+ m_instance = new KitManager;
return m_instance;
}
-KitManager::KitManager(QObject *parent)
- : QObject(parent)
+KitManager::KitManager()
{
d = new KitManagerPrivate;
QTC_CHECK(!m_instance);
@@ -104,6 +150,14 @@ KitManager::KitManager(QObject *parent)
connect(this, &KitManager::kitUpdated, this, &KitManager::kitsChanged);
}
+void KitManager::destroy()
+{
+ delete d;
+ d = nullptr;
+ delete m_instance;
+ m_instance = nullptr;
+}
+
void KitManager::restoreKits()
{
QTC_ASSERT(!d->m_initialized, return );
@@ -114,7 +168,7 @@ void KitManager::restoreKits()
Core::Id defaultUserKit;
std::vector<std::unique_ptr<Kit>> kitsToCheck;
{
- KitList userKits = restoreKits(settingsFileName());
+ KitList userKits = restoreKitsHelper(settingsFileName());
defaultUserKit = userKits.defaultKit;
for (auto &k : userKits.kits) {
@@ -129,8 +183,8 @@ void KitManager::restoreKits()
// read all kits from SDK
{
- KitList system
- = restoreKits(FileName::fromString(ICore::installerResourcePath() + KIT_FILENAME));
+ KitList system = restoreKitsHelper
+ (FilePath::fromString(ICore::installerResourcePath() + KIT_FILENAME));
// SDK kits need to get updated with the user-provided extra settings:
for (auto &current : system.kits) {
@@ -153,11 +207,11 @@ void KitManager::restoreKits()
Kit *ptr = i->get();
// Overwrite settings that the SDK sets to those values:
- foreach (const KitInformation *ki, KitManager::kitInformation()) {
+ for (const KitAspect *aspect : KitManager::kitAspects()) {
// Copy sticky settings over:
- if (ptr->isSticky(ki->id())) {
- ptr->setValue(ki->id(), toStore->value(ki->id()));
- ptr->setSticky(ki->id(), true);
+ if (ptr->isSticky(aspect->id())) {
+ ptr->setValue(aspect->id(), toStore->value(aspect->id()));
+ ptr->setSticky(aspect->id(), true);
}
}
toStore = std::move(*i);
@@ -171,16 +225,69 @@ void KitManager::restoreKits()
// Delete all loaded autodetected kits that were not rediscovered:
kitsToCheck.clear();
- if (resultList.size() == 0) {
- auto defaultKit = std::make_unique<Kit>(); // One kit using default values
- defaultKit->setUnexpandedDisplayName(tr("Desktop"));
- defaultKit->setSdkProvided(false);
- defaultKit->setAutoDetected(false);
+ if (resultList.empty()) {
+ // No kits exist yet, so let's try to autoconfigure some from the toolchains we know.
+ // We consider only host toolchains, because for other ones we lack the knowledge how to
+ // map them to their respective device type.
+ static const auto isHostToolchain = [](const ToolChain *tc) {
+ static const Abi hostAbi = Abi::hostAbi();
+ const Abi tcAbi = tc->targetAbi();
+ return tcAbi.os() == hostAbi.os() && tcAbi.architecture() == hostAbi.architecture()
+ && (tcAbi.os() != Abi::LinuxOS || tcAbi.osFlavor() == hostAbi.osFlavor());
+ };
+ const QList<ToolChain *> allToolchains = ToolChainManager::toolChains(isHostToolchain);
+ QHash<Abi, QHash<Core::Id, ToolChain *>> uniqueToolchains;
+
+ // On Linux systems, we usually detect a plethora of same-ish toolchains. The following
+ // algorithm gives precedence to icecc and ccache and otherwise simply chooses the one with
+ // the shortest path. This should also take care of ensuring matching C/C++ pairs.
+ // TODO: This should not need to be done here. Instead, it should be a convenience
+ // operation on some lower level, e.g. in the toolchain class(es).
+ // Also, we shouldn't detect so many doublets in the first place.
+ for (ToolChain * const tc : allToolchains) {
+ ToolChain *&bestTc = uniqueToolchains[tc->targetAbi()][tc->language()];
+ if (!bestTc) {
+ bestTc = tc;
+ continue;
+ }
+ const QString bestFilePath = bestTc->compilerCommand().toString();
+ const QString currentFilePath = tc->compilerCommand().toString();
+ if (bestFilePath.contains("icecc"))
+ continue;
+ if (currentFilePath.contains("icecc")) {
+ bestTc = tc;
+ continue;
+ }
- defaultKit->setup();
+ if (bestFilePath.contains("ccache"))
+ continue;
+ if (currentFilePath.contains("ccache")) {
+ bestTc = tc;
+ continue;
+ }
+ if (bestFilePath.length() > currentFilePath.length())
+ bestTc = tc;
+ }
- completeKit(defaultKit.get()); // Store manual kits
- resultList.emplace_back(std::move(defaultKit));
+ int maxWeight = 0;
+ for (auto it = uniqueToolchains.cbegin(); it != uniqueToolchains.cend(); ++it) {
+ auto kit = std::make_unique<Kit>();
+ kit->setSdkProvided(false);
+ kit->setAutoDetected(false); // TODO: Why false? What does autodetected mean here?
+ for (ToolChain * const tc : it.value())
+ ToolChainKitAspect::setToolChain(kit.get(), tc);
+ kit->setUnexpandedDisplayName(tr("Desktop (%1)").arg(it.key().toString()));
+ kit->setup();
+ if (kit->weight() < maxWeight)
+ continue;
+ if (kit->weight() > maxWeight) {
+ maxWeight = kit->weight();
+ resultList.clear();
+ }
+ resultList.emplace_back(std::move(kit));
+ }
+ if (resultList.size() == 1)
+ resultList.front()->setUnexpandedDisplayName(tr("Desktop"));
}
Kit *k = Utils::findOrDefault(resultList, Utils::equal(&Kit::id, defaultUserKit));
@@ -191,19 +298,17 @@ void KitManager::restoreKits()
d->m_writer = std::make_unique<PersistentSettingsWriter>(settingsFileName(), "QtCreatorProfiles");
d->m_initialized = true;
- emit kitsLoaded();
- emit kitsChanged();
+ emit m_instance->kitsLoaded();
+ emit m_instance->kitsChanged();
}
KitManager::~KitManager()
{
- delete d;
- d = nullptr;
- m_instance = nullptr;
}
void KitManager::saveKits()
{
+ QTC_ASSERT(d, return);
if (!d->m_writer) // ignore save requests while we are not initialized.
return;
@@ -221,6 +326,8 @@ void KitManager::saveKits()
data.insert(QLatin1String(KIT_COUNT_KEY), count);
data.insert(QLatin1String(KIT_DEFAULT_KEY),
d->m_defaultKit ? QString::fromLatin1(d->m_defaultKit->id().name()) : QString());
+ data.insert(KIT_IRRELEVANT_ASPECTS_KEY,
+ transform<QVariantList>(d->m_irrelevantAspects, &Id::toSetting));
d->m_writer->save(data, ICore::mainWindow());
}
@@ -229,28 +336,27 @@ bool KitManager::isLoaded()
return d->m_initialized;
}
-void KitManager::registerKitInformation(std::unique_ptr<KitInformation> &&ki)
+void KitManager::registerKitAspect(KitAspect *ki)
{
- QTC_ASSERT(ki->id().isValid(), return );
- QTC_ASSERT(!Utils::contains(d->m_informationList, ki.get()), return );
-
- auto it = std::lower_bound(std::begin(d->m_informationList),
- std::end(d->m_informationList),
- ki,
- [](const std::unique_ptr<KitInformation> &a,
- const std::unique_ptr<KitInformation> &b) {
- return a->priority() > b->priority();
- });
- d->m_informationList.insert(it, std::move(ki));
+ instance();
+ QTC_ASSERT(d, return);
+ d->addKitAspect(ki);
- foreach (Kit *k, kits()) {
- if (!k->hasValue(ki->id()))
- k->setValue(ki->id(), ki->defaultValue(k));
- else
- ki->fix(k);
- }
+ // Adding this aspect to possibly already existing kits is currently not
+ // needed here as kits are only created after all aspects are created
+ // in *Plugin::initialize().
+ // Make sure we notice when this assumption breaks:
+ QTC_CHECK(d->m_kitList.empty());
+}
- return;
+void KitManager::deregisterKitAspect(KitAspect *ki)
+{
+ // Happens regularly for the aspects from the ProjectExplorerPlugin as these
+ // are destroyed after the manual call to KitManager::destroy() there, but as
+ // this here is just for sanity reasons that the KitManager does not access
+ // a destroyed aspect, a destroyed KitManager is not a problem.
+ if (d)
+ d->removeKitAspect(ki);
}
QSet<Id> KitManager::supportedPlatforms()
@@ -291,7 +397,7 @@ QList<Kit *> KitManager::sortKits(const QList<Kit *> &kits)
return Utils::transform(sortList, &QPair<QString, Kit *>::second);
}
-KitManager::KitList KitManager::restoreKits(const FileName &fileName)
+static KitList restoreKitsHelper(const FilePath &fileName)
{
KitList result;
@@ -336,6 +442,9 @@ KitManager::KitList KitManager::restoreKits(const FileName &fileName)
if (Utils::contains(result.kits, [id](const std::unique_ptr<Kit> &k) { return k->id() == id; }))
result.defaultKit = id;
+ const auto it = data.constFind(KIT_IRRELEVANT_ASPECTS_KEY);
+ if (it != data.constEnd())
+ d->m_irrelevantAspects = transform<QSet<Id>>(it.value().toList(), &Id::fromSetting);
return result;
}
@@ -366,20 +475,19 @@ Kit *KitManager::defaultKit()
return d->m_defaultKit;
}
-QList<KitInformation *> KitManager::kitInformation()
+const QList<KitAspect *> KitManager::kitAspects()
{
- return Utils::toRawPointer<QList>(d->m_informationList);
+ return d->kitAspects();
}
-KitManagerConfigWidget *KitManager::createConfigWidget(Kit *k)
+const QSet<Id> KitManager::irrelevantAspects()
{
- auto *result = new KitManagerConfigWidget(k);
- foreach (KitInformation *ki, kitInformation())
- result->addConfigWidget(ki->createConfigWidget(result->workingCopy()));
-
- result->updateVisibility();
+ return d->m_irrelevantAspects;
+}
- return result;
+void KitManager::setIrrelevantAspects(const QSet<Id> &aspects)
+{
+ d->m_irrelevantAspects = aspects;
}
void KitManager::notifyAboutUpdate(Kit *k)
@@ -393,18 +501,16 @@ void KitManager::notifyAboutUpdate(Kit *k)
emit m_instance->unmanagedKitUpdated(k);
}
-bool KitManager::registerKit(std::unique_ptr<Kit> &&k)
+Kit *KitManager::registerKit(const std::function<void (Kit *)> &init, Core::Id id)
{
- QTC_ASSERT(isLoaded(), return false);
+ QTC_ASSERT(isLoaded(), return nullptr);
- if (!k)
- return true;
-
- QTC_ASSERT(k->id().isValid(), return false);
+ auto k = std::make_unique<Kit>(id);
+ QTC_ASSERT(k->id().isValid(), return nullptr);
Kit *kptr = k.get();
- if (Utils::contains(d->m_kitList, kptr))
- return false;
+ if (init)
+ init(kptr);
// make sure we have all the information in our kits:
completeKit(kptr);
@@ -415,7 +521,7 @@ bool KitManager::registerKit(std::unique_ptr<Kit> &&k)
setDefaultKit(kptr);
emit m_instance->kitAdded(kptr);
- return true;
+ return kptr;
}
void KitManager::deregisterKit(Kit *k)
@@ -444,61 +550,106 @@ void KitManager::completeKit(Kit *k)
{
QTC_ASSERT(k, return);
KitGuard g(k);
- for (const std::unique_ptr<KitInformation> &ki : d->m_informationList) {
+ for (KitAspect *ki : d->kitAspects()) {
ki->upgrade(k);
if (!k->hasValue(ki->id()))
- k->setValue(ki->id(), ki->defaultValue(k));
+ ki->setup(k);
else
ki->fix(k);
}
}
// --------------------------------------------------------------------
-// KitInformation:
+// KitAspect:
// --------------------------------------------------------------------
-void KitInformation::addToEnvironment(const Kit *k, Environment &env) const
+KitAspect::KitAspect()
+{
+ KitManager::registerKitAspect(this);
+}
+
+KitAspect::~KitAspect()
+{
+ KitManager::deregisterKitAspect(this);
+}
+
+int KitAspect::weight(const Kit *k) const
+{
+ return k->value(id()).isValid() ? 1 : 0;
+}
+
+void KitAspect::addToEnvironment(const Kit *k, Environment &env) const
{
Q_UNUSED(k);
Q_UNUSED(env);
}
-IOutputParser *KitInformation::createOutputParser(const Kit *k) const
+IOutputParser *KitAspect::createOutputParser(const Kit *k) const
{
Q_UNUSED(k);
return nullptr;
}
-QString KitInformation::displayNamePostfix(const Kit *k) const
+QString KitAspect::displayNamePostfix(const Kit *k) const
{
Q_UNUSED(k);
return QString();
}
-QSet<Id> KitInformation::supportedPlatforms(const Kit *k) const
+QSet<Id> KitAspect::supportedPlatforms(const Kit *k) const
{
Q_UNUSED(k);
return QSet<Id>();
}
-QSet<Id> KitInformation::availableFeatures(const Kit *k) const
+QSet<Id> KitAspect::availableFeatures(const Kit *k) const
{
Q_UNUSED(k);
return QSet<Id>();
}
-void KitInformation::addToMacroExpander(Kit *k, MacroExpander *expander) const
+void KitAspect::addToMacroExpander(Kit *k, MacroExpander *expander) const
{
Q_UNUSED(k);
Q_UNUSED(expander);
}
-void KitInformation::notifyAboutUpdate(Kit *k)
+void KitAspect::notifyAboutUpdate(Kit *k)
{
if (k)
k->kitUpdated();
}
+KitAspectWidget::KitAspectWidget(Kit *kit, const KitAspect *ki) : m_kit(kit),
+ m_kitInformation(ki), m_isSticky(kit->isSticky(ki->id()))
+{ }
+
+Core::Id KitAspectWidget::kitInformationId() const
+{
+ return m_kitInformation->id();
+}
+
+QString KitAspectWidget::msgManage()
+{
+ return tr("Manage...");
+}
+
+void KitAspectWidget::setPalette(const QPalette &p)
+{
+ if (mainWidget())
+ mainWidget()->setPalette(p);
+ if (buttonWidget())
+ buttonWidget()->setPalette(p);
+}
+
+void KitAspectWidget::setStyle(QStyle *s)
+{
+ if (mainWidget())
+ mainWidget()->setStyle(s);
+ if (buttonWidget())
+ buttonWidget()->setStyle(s);
+}
+
// --------------------------------------------------------------------
// KitFeatureProvider:
// --------------------------------------------------------------------
diff --git a/src/plugins/projectexplorer/kitmanager.h b/src/plugins/projectexplorer/kitmanager.h
index 189dc1c216..4cc80230c6 100644
--- a/src/plugins/projectexplorer/kitmanager.h
+++ b/src/plugins/projectexplorer/kitmanager.h
@@ -34,34 +34,38 @@
#include <QObject>
#include <QPair>
+#include <QSet>
#include <functional>
+QT_BEGIN_NAMESPACE
+class QStyle;
+QT_END_NAMESPACE
+
namespace Utils {
class Environment;
-class FileName;
+class FilePath;
class MacroExpander;
} // namespace Utils
namespace ProjectExplorer {
class Task;
class IOutputParser;
-class KitConfigWidget;
+class KitAspectWidget;
class KitManager;
namespace Internal {
-class KitManagerConfigWidget;
class KitModel;
} // namespace Internal
/**
- * @brief The KitInformation class
+ * @brief The KitAspect class
*
* One piece of information stored in the kit.
*
- * This needs to get registered with the \a KitManager.
+ * They auto-register with the \a KitManager for their life time
*/
-class PROJECTEXPLORER_EXPORT KitInformation : public QObject
+class PROJECTEXPLORER_EXPORT KitAspect : public QObject
{
Q_OBJECT
@@ -71,11 +75,12 @@ public:
Core::Id id() const { return m_id; }
int priority() const { return m_priority; }
-
- virtual QVariant defaultValue(const Kit *) const = 0;
+ QString displayName() const { return m_displayName; }
+ QString description() const { return m_description; }
+ bool isEssential() const { return m_essential; }
// called to find issues with the kit
- virtual QList<Task> validate(const Kit *) const = 0;
+ virtual Tasks validate(const Kit *) const = 0;
// called after restoring a kit, so upgrading of kit information settings can be done
virtual void upgrade(Kit *) { return; }
// called to fix issues with this kitinformation. Does not modify the rest of the kit.
@@ -83,9 +88,11 @@ public:
// called on initial setup of a kit.
virtual void setup(Kit *) { return; }
+ virtual int weight(const Kit *k) const;
+
virtual ItemList toUserOutput(const Kit *) const = 0;
- virtual KitConfigWidget *createConfigWidget(Kit *) const = 0;
+ virtual KitAspectWidget *createConfigWidget(Kit *) const = 0;
virtual void addToEnvironment(const Kit *k, Utils::Environment &env) const;
virtual IOutputParser *createOutputParser(const Kit *k) const;
@@ -97,14 +104,59 @@ public:
virtual void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const;
+ virtual bool isApplicableToKit(const Kit *) const { return true; }
+
protected:
+ KitAspect();
+ ~KitAspect();
+
void setId(Core::Id id) { m_id = id; }
+ void setDisplayName(const QString &name) { m_displayName = name; }
+ void setDescription(const QString &desc) { m_description = desc; }
+ void makeEssential() { m_essential = true; }
void setPriority(int priority) { m_priority = priority; }
void notifyAboutUpdate(Kit *k);
private:
+ QString m_displayName;
+ QString m_description;
Core::Id m_id;
int m_priority = 0; // The higher the closer to the top.
+ bool m_essential = false;
+};
+
+class PROJECTEXPLORER_EXPORT KitAspectWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ KitAspectWidget(Kit *kit, const KitAspect *ki);
+
+ Core::Id kitInformationId() const;
+
+ virtual void makeReadOnly() = 0;
+ virtual void refresh() = 0;
+ bool visibleInKit() { return m_kitInformation->isApplicableToKit(m_kit); }
+
+ virtual QWidget *mainWidget() const = 0;
+ virtual QWidget *buttonWidget() const { return nullptr; }
+
+ bool isSticky() const { return m_isSticky; }
+
+ static QString msgManage();
+
+ Kit *kit() const { return m_kit; }
+
+ virtual void setPalette(const QPalette &p);
+ virtual void setStyle(QStyle *s);
+
+signals:
+ void dirty();
+
+protected:
+ Kit *m_kit;
+ const KitAspect *m_kitInformation;
+ bool m_isSticky;
};
class PROJECTEXPLORER_EXPORT KitManager : public QObject
@@ -120,19 +172,14 @@ public:
static Kit *kit(Core::Id id);
static Kit *defaultKit();
- static QList<KitInformation *> kitInformation();
+ static const QList<KitAspect *> kitAspects();
+ static const QSet<Core::Id> irrelevantAspects();
+ static void setIrrelevantAspects(const QSet<Core::Id> &aspects);
- static Internal::KitManagerConfigWidget *createConfigWidget(Kit *k);
-
- static bool registerKit(std::unique_ptr<Kit> &&k);
+ static Kit *registerKit(const std::function<void(Kit *)> &init, Core::Id id = {});
static void deregisterKit(Kit *k);
static void setDefaultKit(Kit *k);
- template<typename KI, typename... Args>
- static void registerKitInformation(Args&&... args) {
- registerKitInformation(std::make_unique<KI>(std::forward<Args>(args)...));
- }
-
static QSet<Core::Id> supportedPlatforms();
static QSet<Core::Id> availableFeatures(Core::Id platformId);
@@ -157,20 +204,16 @@ signals:
void kitsLoaded();
private:
- explicit KitManager(QObject *parent = nullptr);
+ KitManager();
+
+ static void destroy();
- static void registerKitInformation(std::unique_ptr<KitInformation> &&ki);
+ static void registerKitAspect(KitAspect *ki);
+ static void deregisterKitAspect(KitAspect *ki);
// Make sure the this is only called after all
- // KitInformation are registered!
- void restoreKits();
- class KitList
- {
- public:
- Core::Id defaultKit;
- std::vector<std::unique_ptr<Kit>> kits;
- };
- KitList restoreKits(const Utils::FileName &fileName);
+ // KitAspects are registered!
+ static void restoreKits();
static void notifyAboutUpdate(Kit *k);
static void completeKit(Kit *k);
@@ -178,7 +221,7 @@ private:
friend class ProjectExplorerPlugin; // for constructor
friend class Kit;
friend class Internal::KitModel;
- friend class KitInformation; // for notifyAbutUpdate
+ friend class KitAspect; // for notifyAboutUpdate and self-registration
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
index 473c8455e2..cdd508b078 100644
--- a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
+++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
@@ -24,18 +24,22 @@
****************************************************************************/
#include "kitmanagerconfigwidget.h"
-#include "projectexplorerconstants.h"
+#include "devicesupport/idevicefactory.h"
#include "kit.h"
+#include "kitinformation.h"
#include "kitmanager.h"
+#include "projectexplorerconstants.h"
#include "task.h"
#include <coreplugin/variablechooser.h>
#include <utils/algorithm.h>
#include <utils/detailswidget.h>
-#include <utils/qtcassert.h>
#include <utils/macroexpander.h>
+#include <utils/pathchooser.h>
+#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
#include <QAction>
#include <QRegularExpression>
@@ -44,7 +48,9 @@
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
+#include <QMenu>
#include <QPainter>
+#include <QPushButton>
#include <QToolButton>
#include <QScrollArea>
#include <QSizePolicy>
@@ -92,11 +98,10 @@ KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
mainLayout->setMargin(1);
mainLayout->addWidget(inner, 0, 0);
- toolTip = tr("Kit name and icon.");
- label = createLabel(tr("Name:"), toolTip);
+ label = createLabel(tr("Name:"), tr("Kit name and icon."));
m_layout->addWidget(label, 0, LabelColumn, alignment);
- m_iconButton->setToolTip(toolTip);
- auto setIconAction = new QAction(tr("Select Icon File"), this);
+ m_iconButton->setToolTip(tr("Kit icon."));
+ auto setIconAction = new QAction(tr("Select Icon..."), this);
m_iconButton->addAction(setIconAction);
auto resetIconAction = new QAction(tr("Reset to Device Default Icon"), this);
m_iconButton->addAction(resetIconAction);
@@ -121,6 +126,15 @@ KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
auto chooser = new Core::VariableChooser(this);
chooser->addSupportedWidget(m_nameEdit);
chooser->addMacroExpanderProvider([this]() { return m_modifiedKit->macroExpander(); });
+
+ for (KitAspect *aspect : KitManager::kitAspects())
+ addAspectToWorkingCopy(aspect);
+
+ updateVisibility();
+
+ if (k && k->isAutoDetected())
+ makeStickySubWidgetsReadOnly();
+ setVisible(false);
}
KitManagerConfigWidget::~KitManagerConfigWidget()
@@ -142,28 +156,29 @@ QString KitManagerConfigWidget::displayName() const
return m_cachedDisplayName;
}
-QIcon KitManagerConfigWidget::icon() const
+QIcon KitManagerConfigWidget::displayIcon() const
{
- return m_modifiedKit->icon();
+ // Special case: Extra warning if there are no errors but name is not unique.
+ if (m_modifiedKit->isValid() && !m_hasUniqueName) {
+ static const QIcon warningIcon(Utils::Icons::WARNING.icon());
+ return warningIcon;
+ }
+
+ return m_modifiedKit->displayIcon();
}
void KitManagerConfigWidget::apply()
{
- bool mustSetDefault = m_isDefaultKit;
- bool mustRegister = false;
- auto toRegister = std::make_unique<Kit>();
- if (!m_kit) {
- mustRegister = true;
- m_kit = toRegister.get();
+ const auto copyIntoKit = [this](Kit *k) { k->copyFrom(m_modifiedKit.get()); };
+ if (m_kit) {
+ copyIntoKit(m_kit);
+ } else {
+ m_isRegistering = true;
+ m_kit = KitManager::registerKit(copyIntoKit);
+ m_isRegistering = false;
}
- m_kit->copyFrom(m_modifiedKit.get()); //m_isDefaultKit is reset in discard() here.
- if (mustRegister)
- KitManager::registerKit(std::move(toRegister));
-
- if (mustSetDefault)
+ if (m_isDefaultKit)
KitManager::setDefaultKit(m_kit);
-
- m_isDefaultKit = mustSetDefault;
emit dirty();
}
@@ -191,42 +206,35 @@ bool KitManagerConfigWidget::isDirty() const
|| m_isDefaultKit != (KitManager::defaultKit() == m_kit);
}
-bool KitManagerConfigWidget::isValid() const
-{
- return m_modifiedKit->isValid();
-}
-
-bool KitManagerConfigWidget::hasWarning() const
-{
- return m_modifiedKit->hasWarning() || !m_hasUniqueName;
-}
-
QString KitManagerConfigWidget::validityMessage() const
{
- QList<Task> tmp;
+ Tasks tmp;
if (!m_hasUniqueName) {
- tmp.append(Task(Task::Warning, tr("Display name is not unique."), Utils::FileName(), -1,
+ tmp.append(Task(Task::Warning, tr("Display name is not unique."), Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE));
}
return m_modifiedKit->toHtml(tmp);
}
-void KitManagerConfigWidget::addConfigWidget(KitConfigWidget *widget)
+void KitManagerConfigWidget::addAspectToWorkingCopy(KitAspect *aspect)
{
+ QTC_ASSERT(aspect, return);
+ KitAspectWidget *widget = aspect->createConfigWidget(workingCopy());
QTC_ASSERT(widget, return);
QTC_ASSERT(!m_widgets.contains(widget), return);
- const QString name = widget->displayName() + ':';
- QString toolTip = widget->toolTip();
+ const QString name = aspect->displayName() + ':';
+ QString toolTip = aspect->description();
auto action = new QAction(tr("Mark as Mutable"), nullptr);
action->setCheckable(true);
- action->setChecked(widget->isMutable());
+ action->setChecked(workingCopy()->isMutable(aspect->id()));
+
action->setEnabled(!widget->isSticky());
widget->mainWidget()->addAction(action);
widget->mainWidget()->setContextMenuPolicy(Qt::ActionsContextMenu);
- connect(action, &QAction::toggled, this, [this, widget, action] {
- widget->setMutable(action->isChecked());
+ connect(action, &QAction::toggled, this, [this, aspect, action] {
+ workingCopy()->setMutable(aspect->id(), action->isChecked());
emit dirty();
});
@@ -249,8 +257,9 @@ void KitManagerConfigWidget::updateVisibility()
{
int count = m_widgets.count();
for (int i = 0; i < count; ++i) {
- KitConfigWidget *widget = m_widgets.at(i);
- bool visible = widget->visibleInKit();
+ KitAspectWidget *widget = m_widgets.at(i);
+ const bool visible = widget->visibleInKit()
+ && !m_modifiedKit->irrelevantAspects().contains(widget->kitInformationId());
widget->mainWidget()->setVisible(visible);
if (widget->buttonWidget())
widget->buttonWidget()->setVisible(visible);
@@ -265,7 +274,7 @@ void KitManagerConfigWidget::setHasUniqueName(bool unique)
void KitManagerConfigWidget::makeStickySubWidgetsReadOnly()
{
- foreach (KitConfigWidget *w, m_widgets) {
+ foreach (KitAspectWidget *w, m_widgets) {
if (w->isSticky())
w->makeReadOnly();
}
@@ -303,24 +312,49 @@ void KitManagerConfigWidget::removeKit()
void KitManagerConfigWidget::setIcon()
{
- const QString path = QFileDialog::getOpenFileName(this, tr("Select Icon"),
- m_modifiedKit->iconPath().toString(),
- tr("Images (*.png *.xpm *.jpg)"));
- if (path.isEmpty())
- return;
-
- const QIcon icon(path);
- if (icon.isNull())
- return;
-
- m_iconButton->setIcon(icon);
- m_modifiedKit->setIconPath(Utils::FileName::fromString(path));
- emit dirty();
+ const Core::Id deviceType = DeviceTypeKitAspect::deviceTypeId(m_modifiedKit.get());
+ QList<IDeviceFactory *> allDeviceFactories = IDeviceFactory::allDeviceFactories();
+ if (deviceType.isValid()) {
+ const auto less = [deviceType](const IDeviceFactory *f1, const IDeviceFactory *f2) {
+ if (f1->deviceType() == deviceType)
+ return true;
+ if (f2->deviceType() == deviceType)
+ return false;
+ return f1->displayName() < f2->displayName();
+ };
+ Utils::sort(allDeviceFactories, less);
+ }
+ QMenu iconMenu;
+ for (const IDeviceFactory * const factory : qAsConst(allDeviceFactories)) {
+ if (factory->icon().isNull())
+ continue;
+ iconMenu.addAction(factory->icon(), tr("Default for %1").arg(factory->displayName()),
+ [this, factory] {
+ m_iconButton->setIcon(factory->icon());
+ m_modifiedKit->setDeviceTypeForIcon(factory->deviceType());
+ emit dirty();
+ });
+ }
+ iconMenu.addSeparator();
+ iconMenu.addAction(Utils::PathChooser::browseButtonLabel(), [this] {
+ const QString path = QFileDialog::getOpenFileName(this, tr("Select Icon"),
+ m_modifiedKit->iconPath().toString(),
+ tr("Images (*.png *.xpm *.jpg)"));
+ if (path.isEmpty())
+ return;
+ const QIcon icon(path);
+ if (icon.isNull())
+ return;
+ m_iconButton->setIcon(icon);
+ m_modifiedKit->setIconPath(Utils::FilePath::fromString(path));
+ emit dirty();
+ });
+ iconMenu.exec(mapToGlobal(m_iconButton->pos()));
}
void KitManagerConfigWidget::resetIcon()
{
- m_modifiedKit->setIconPath(Utils::FileName());
+ m_modifiedKit->setIconPath(Utils::FilePath());
emit dirty();
}
@@ -348,7 +382,7 @@ void KitManagerConfigWidget::workingCopyWasUpdated(Kit *k)
k->fix();
m_fixingKit = false;
- foreach (KitConfigWidget *w, m_widgets)
+ foreach (KitAspectWidget *w, m_widgets)
w->refresh();
m_cachedDisplayName.clear();
@@ -376,7 +410,7 @@ void KitManagerConfigWidget::kitWasUpdated(Kit *k)
void KitManagerConfigWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event);
- foreach (KitConfigWidget *widget, m_widgets)
+ foreach (KitAspectWidget *widget, m_widgets)
widget->refresh();
}
diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.h b/src/plugins/projectexplorer/kitmanagerconfigwidget.h
index 026a8e25b4..cf1b6b44d6 100644
--- a/src/plugins/projectexplorer/kitmanagerconfigwidget.h
+++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.h
@@ -25,7 +25,7 @@
#pragma once
-#include "kitconfigwidget.h"
+#include "kitmanager.h"
#include <QWidget>
@@ -52,19 +52,18 @@ public:
~KitManagerConfigWidget() override;
QString displayName() const;
- QIcon icon() const;
+ QIcon displayIcon() const;
void apply();
void discard();
bool isDirty() const;
- bool isValid() const;
- bool hasWarning() const;
QString validityMessage() const;
- void addConfigWidget(KitConfigWidget *widget);
+ void addAspectToWorkingCopy(KitAspect *aspect);
void makeStickySubWidgetsReadOnly();
Kit *workingCopy() const;
bool configures(Kit *k) const;
+ bool isRegistering() const { return m_isRegistering; }
void setIsDefaultKit(bool d);
bool isDefaultKit() const;
void removeKit();
@@ -97,13 +96,14 @@ private:
QToolButton *m_iconButton;
QLineEdit *m_nameEdit;
QLineEdit *m_fileSystemFriendlyNameLineEdit;
- QList<KitConfigWidget *> m_widgets;
+ QList<KitAspectWidget *> m_widgets;
QList<QLabel *> m_labels;
Kit *m_kit;
std::unique_ptr<Kit> m_modifiedKit;
bool m_isDefaultKit = false;
bool m_fixingKit = false;
bool m_hasUniqueName = true;
+ bool m_isRegistering = false;
QList<QAction *> m_actions;
mutable QString m_cachedDisplayName;
};
diff --git a/src/plugins/projectexplorer/kitmodel.cpp b/src/plugins/projectexplorer/kitmodel.cpp
index dbc04d559f..5f157dcbb3 100644
--- a/src/plugins/projectexplorer/kitmodel.cpp
+++ b/src/plugins/projectexplorer/kitmodel.cpp
@@ -44,14 +44,21 @@ namespace Internal {
class KitNode : public TreeItem
{
public:
- KitNode(Kit *k)
+ KitNode(Kit *k, KitModel *m)
{
- widget = KitManager::createConfigWidget(k);
- if (widget) {
- if (k && k->isAutoDetected())
- widget->makeStickySubWidgetsReadOnly();
- widget->setVisible(false);
- }
+ widget = new KitManagerConfigWidget(k);
+
+ QObject::connect(widget, &KitManagerConfigWidget::dirty, m, [this] { update(); });
+
+ QObject::connect(widget, &KitManagerConfigWidget::isAutoDetectedChanged, m, [this, m] {
+ TreeItem *oldParent = parent();
+ TreeItem *newParent =
+ m->rootItem()->childAt(widget->workingCopy()->isAutoDetected() ? 0 : 1);
+ if (oldParent && oldParent != newParent) {
+ m->takeItem(this);
+ newParent->appendChild(this);
+ }
+ });
}
~KitNode() override
@@ -78,15 +85,7 @@ public:
return baseName;
}
if (role == Qt::DecorationRole) {
- if (!widget->isValid()) {
- static const QIcon errorIcon(Utils::Icons::CRITICAL.icon());
- return errorIcon;
- }
- if (widget->hasWarning()) {
- static const QIcon warningIcon(Utils::Icons::WARNING.icon());
- return warningIcon;
- }
- return widget->icon();
+ return widget->displayIcon();
}
if (role == Qt::ToolTipRole) {
return widget->validityMessage();
@@ -164,35 +163,6 @@ KitManagerConfigWidget *KitModel::widget(const QModelIndex &index)
return n ? n->widget : nullptr;
}
-void KitModel::isAutoDetectedChanged()
-{
- auto w = qobject_cast<KitManagerConfigWidget *>(sender());
- int idx = -1;
- idx = Utils::indexOf(*m_manualRoot, [w](TreeItem *node) {
- return static_cast<KitNode *>(node)->widget == w;
- });
- TreeItem *oldParent = nullptr;
- TreeItem *newParent = w->workingCopy()->isAutoDetected() ? m_autoRoot : m_manualRoot;
- if (idx != -1) {
- oldParent = m_manualRoot;
- } else {
- idx = Utils::indexOf(*m_autoRoot, [w](TreeItem *node) {
- return static_cast<KitNode *>(node)->widget == w;
- });
- if (idx != -1) {
- oldParent = m_autoRoot;
- }
- }
-
- if (oldParent && oldParent != newParent) {
- beginMoveRows(indexForItem(oldParent), idx, idx, indexForItem(newParent), newParent->childCount());
- TreeItem *n = oldParent->childAt(idx);
- takeItem(n);
- newParent->appendChild(n);
- endMoveRows();
- }
-}
-
void KitModel::validateKitNames()
{
QHash<QString, int> nameHash;
@@ -248,10 +218,12 @@ void KitModel::markForRemoval(Kit *k)
delete node;
else
m_toRemoveList.append(node);
+ validateKitNames();
}
Kit *KitModel::markForAddition(Kit *baseKit)
{
+ const QString newName = newKitName(baseKit ? baseKit->unexpandedDisplayName() : QString());
KitNode *node = createNode(nullptr);
m_manualRoot->appendChild(node);
Kit *k = node->widget->workingCopy();
@@ -260,10 +232,10 @@ Kit *KitModel::markForAddition(Kit *baseKit)
k->copyFrom(baseKit);
k->setAutoDetected(false); // Make sure we have a manual kit!
k->setSdkProvided(false);
- k->setUnexpandedDisplayName(tr("Clone of %1").arg(k->unexpandedDisplayName()));
} else {
k->setup();
}
+ k->setUnexpandedDisplayName(newName);
if (!m_defaultNode)
setDefaultNode(node);
@@ -271,6 +243,22 @@ Kit *KitModel::markForAddition(Kit *baseKit)
return k;
}
+void KitModel::updateVisibility()
+{
+ forItemsAtLevel<2>([](const TreeItem *ti) {
+ static_cast<const KitNode *>(ti)->widget->updateVisibility();
+ });
+}
+
+QString KitModel::newKitName(const QString &sourceName) const
+{
+ QList<Kit *> allKits;
+ forItemsAtLevel<2>([&allKits](const TreeItem *ti) {
+ allKits << static_cast<const KitNode *>(ti)->widget->workingCopy();
+ });
+ return Kit::newKitName(sourceName, allKits);
+}
+
KitNode *KitModel::findWorkingCopy(Kit *k) const
{
return findItemAtLevel<2>([k](KitNode *n) { return n->widget->workingCopy() == k; });
@@ -278,15 +266,8 @@ KitNode *KitModel::findWorkingCopy(Kit *k) const
KitNode *KitModel::createNode(Kit *k)
{
- auto node = new KitNode(k);
+ auto node = new KitNode(k, this);
m_parentLayout->addWidget(node->widget);
- connect(node->widget, &KitManagerConfigWidget::dirty, [this, node] {
- if (m_autoRoot->indexOf(node) != -1 || m_manualRoot->indexOf(node) != -1)
- node->update();
- });
- connect(node->widget, &KitManagerConfigWidget::isAutoDetectedChanged,
- this, &KitModel::isAutoDetectedChanged);
-
return node;
}
@@ -307,7 +288,7 @@ void KitModel::addKit(Kit *k)
{
for (TreeItem *n : *m_manualRoot) {
// Was added by us
- if (static_cast<KitNode *>(n)->widget->configures(k))
+ if (static_cast<KitNode *>(n)->widget->isRegistering())
return;
}
@@ -333,6 +314,7 @@ void KitModel::removeKit(Kit *k)
if (m_defaultNode == n)
m_defaultNode = nullptr;
delete n;
+ validateKitNames();
return;
}
}
diff --git a/src/plugins/projectexplorer/kitmodel.h b/src/plugins/projectexplorer/kitmodel.h
index 8070eefe30..6e9dbed6f4 100644
--- a/src/plugins/projectexplorer/kitmodel.h
+++ b/src/plugins/projectexplorer/kitmodel.h
@@ -69,6 +69,10 @@ public:
void markForRemoval(Kit *k);
Kit *markForAddition(Kit *baseKit);
+ void updateVisibility();
+
+ QString newKitName(const QString &sourceName) const;
+
signals:
void kitStateChanged();
@@ -78,7 +82,6 @@ private:
void removeKit(ProjectExplorer::Kit *k);
void changeDefaultKit();
void validateKitNames();
- void isAutoDetectedChanged();
KitNode *findWorkingCopy(Kit *k) const;
KitNode *createNode(Kit *k);
diff --git a/src/plugins/projectexplorer/kitoptionspage.cpp b/src/plugins/projectexplorer/kitoptionspage.cpp
index 262d6c2706..d9ebe3f0e0 100644
--- a/src/plugins/projectexplorer/kitoptionspage.cpp
+++ b/src/plugins/projectexplorer/kitoptionspage.cpp
@@ -25,6 +25,7 @@
#include "kitoptionspage.h"
+#include "filterkitaspectsdialog.h"
#include "kitmodel.h"
#include "kit.h"
#include "projectexplorerconstants.h"
@@ -32,6 +33,8 @@
#include "kitmanagerconfigwidget.h"
#include "kitmanager.h"
+#include <utils/qtcassert.h>
+
#include <QHBoxLayout>
#include <QHeaderView>
#include <QItemSelectionModel>
@@ -67,10 +70,12 @@ public:
QPushButton *m_cloneButton = nullptr;
QPushButton *m_delButton = nullptr;
QPushButton *m_makeDefaultButton = nullptr;
+ QPushButton *m_filterButton = nullptr;
+ QPushButton *m_defaultFilterButton = nullptr;
KitModel *m_model = nullptr;
QItemSelectionModel *m_selectionModel = nullptr;
- QWidget *m_currentWidget = nullptr;
+ KitManagerConfigWidget *m_currentWidget = nullptr;
};
KitOptionsPageWidget::KitOptionsPageWidget()
@@ -85,6 +90,12 @@ KitOptionsPageWidget::KitOptionsPageWidget()
m_cloneButton = new QPushButton(KitOptionsPage::tr("Clone"), this);
m_delButton = new QPushButton(KitOptionsPage::tr("Remove"), this);
m_makeDefaultButton = new QPushButton(KitOptionsPage::tr("Make Default"), this);
+ m_filterButton = new QPushButton(KitOptionsPage::tr("Settings Filter..."), this);
+ m_filterButton->setToolTip(KitOptionsPage::tr(
+ "Choose which settings to display for this kit."));
+ m_defaultFilterButton = new QPushButton(KitOptionsPage::tr("Default Settings Filter..."), this);
+ m_defaultFilterButton->setToolTip(KitOptionsPage::tr(
+ "Choose which kit settings to display by default."));
auto buttonLayout = new QVBoxLayout;
buttonLayout->setSpacing(6);
@@ -93,6 +104,8 @@ KitOptionsPageWidget::KitOptionsPageWidget()
buttonLayout->addWidget(m_cloneButton);
buttonLayout->addWidget(m_delButton);
buttonLayout->addWidget(m_makeDefaultButton);
+ buttonLayout->addWidget(m_filterButton);
+ buttonLayout->addWidget(m_defaultFilterButton);
buttonLayout->addStretch();
auto horizontalLayout = new QHBoxLayout;
@@ -131,14 +144,28 @@ KitOptionsPageWidget::KitOptionsPageWidget()
this, &KitOptionsPageWidget::removeKit);
connect(m_makeDefaultButton, &QAbstractButton::clicked,
this, &KitOptionsPageWidget::makeDefaultKit);
-
+ connect(m_filterButton, &QAbstractButton::clicked, this, [this] {
+ QTC_ASSERT(m_currentWidget, return);
+ FilterKitAspectsDialog dlg(m_currentWidget->workingCopy(), this);
+ if (dlg.exec() == QDialog::Accepted) {
+ m_currentWidget->workingCopy()->setIrrelevantAspects(dlg.irrelevantAspects());
+ m_currentWidget->updateVisibility();
+ }
+ });
+ connect(m_defaultFilterButton, &QAbstractButton::clicked, this, [this] {
+ FilterKitAspectsDialog dlg(nullptr, this);
+ if (dlg.exec() == QDialog::Accepted) {
+ KitManager::setIrrelevantAspects(dlg.irrelevantAspects());
+ m_model->updateVisibility();
+ }
+ });
updateState();
}
void KitOptionsPageWidget::kitSelectionChanged()
{
QModelIndex current = currentIndex();
- QWidget *newWidget = m_model->widget(current);
+ KitManagerConfigWidget * const newWidget = m_model->widget(current);
if (newWidget == m_currentWidget)
return;
@@ -216,6 +243,7 @@ void KitOptionsPageWidget::updateState()
m_cloneButton->setEnabled(canCopy);
m_delButton->setEnabled(canDelete);
m_makeDefaultButton->setEnabled(canMakeDefault);
+ m_filterButton->setEnabled(canCopy);
}
QModelIndex KitOptionsPageWidget::currentIndex() const
diff --git a/src/plugins/projectexplorer/ldparser.cpp b/src/plugins/projectexplorer/ldparser.cpp
index 6da77cee9c..9ce56bf7dd 100644
--- a/src/plugins/projectexplorer/ldparser.cpp
+++ b/src/plugins/projectexplorer/ldparser.cpp
@@ -68,7 +68,7 @@ void LdParser::stdError(const QString &line)
if (lne.startsWith(QLatin1String("collect2:"))) {
Task task = Task(Task::Error,
lne /* description */,
- Utils::FileName() /* filename */,
+ Utils::FilePath() /* filename */,
-1 /* linenumber */,
Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
@@ -79,7 +79,7 @@ void LdParser::stdError(const QString &line)
if (match.hasMatch()) {
QString description = match.captured(2);
Task task(Task::Warning, description,
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
return;
@@ -95,7 +95,7 @@ void LdParser::stdError(const QString &line)
} else if (description.startsWith(QLatin1String("fatal: "))) {
description = description.mid(7);
}
- Task task(type, description, Utils::FileName() /* filename */, -1 /* line */,
+ Task task(type, description, Utils::FilePath() /* filename */, -1 /* line */,
Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
return;
@@ -107,12 +107,12 @@ void LdParser::stdError(const QString &line)
int lineno = match.captured(7).toInt(&ok);
if (!ok)
lineno = -1;
- Utils::FileName filename = Utils::FileName::fromUserInput(match.captured(1));
+ Utils::FilePath filename = Utils::FilePath::fromUserInput(match.captured(1));
const QString sourceFileName = match.captured(4);
if (!sourceFileName.isEmpty()
&& !sourceFileName.startsWith(QLatin1String("(.text"))
&& !sourceFileName.startsWith(QLatin1String("(.data"))) {
- filename = Utils::FileName::fromUserInput(sourceFileName);
+ filename = Utils::FilePath::fromUserInput(sourceFileName);
}
QString description = match.captured(8).trimmed();
Task::TaskType type = Task::Error;
diff --git a/src/plugins/projectexplorer/linuxiccparser.cpp b/src/plugins/projectexplorer/linuxiccparser.cpp
index 04dbb6c65f..6572f47d66 100644
--- a/src/plugins/projectexplorer/linuxiccparser.cpp
+++ b/src/plugins/projectexplorer/linuxiccparser.cpp
@@ -81,7 +81,7 @@ void LinuxIccParser::stdError(const QString &line)
else if (category == QLatin1String("warning"))
type = Task::Warning;
m_temporary = Task(type, m_firstLine.cap(6).trimmed(),
- Utils::FileName::fromUserInput(m_firstLine.cap(1)),
+ Utils::FilePath::fromUserInput(m_firstLine.cap(1)),
m_firstLine.cap(2).toInt(),
Constants::TASK_CATEGORY_COMPILE);
@@ -141,25 +141,25 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
QTest::newRow("pass-through stdout")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("pch creation")
<< QString::fromLatin1("\".pch/Qt5Core.pchi.cpp\": creating precompiled header file \".pch/Qt5Core.pchi\"")
<< OutputParserTester::STDERR
<< QString() << QString()
- << QList<Task>()
+ << Tasks()
<< QString();
QTest::newRow("undeclared function")
@@ -169,10 +169,10 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers_data()
"\n")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("\n")
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("identifier \"f\" is undefined\nf(0);"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 13,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 13,
Constants::TASK_CATEGORY_COMPILE))
<< QString();
@@ -185,10 +185,10 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers_data()
"\n")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("\n")
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("identifier \"f\" is undefined\nf(0);"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 13,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 13,
Constants::TASK_CATEGORY_COMPILE))
<< QString();
@@ -200,10 +200,10 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers_data()
"\n")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("\n")
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("function \"AClass::privatefunc\" (declared at line 4 of \"main.h\") is inaccessible\nb.privatefunc();"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 53,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 53,
Constants::TASK_CATEGORY_COMPILE))
<< QString();
@@ -214,20 +214,20 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers_data()
"\n")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("\n")
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("use of \"=\" where \"==\" may have been intended\nwhile (a = true)"),
- Utils::FileName::fromUserInput(QLatin1String("main.cpp")), 41,
+ Utils::FilePath::fromUserInput(QLatin1String("main.cpp")), 41,
Constants::TASK_CATEGORY_COMPILE))
<< QString();
QTest::newRow("moc note")
<< QString::fromLatin1("/home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("Note: No relevant classes found. No output generated."),
- Utils::FileName::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
Constants::TASK_CATEGORY_COMPILE)
)
<< QString();
@@ -239,7 +239,7 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers()
testbench.appendOutputParser(new LinuxIccParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/projectexplorer/localenvironmentaspect.cpp b/src/plugins/projectexplorer/localenvironmentaspect.cpp
index 2a6eee97c5..366b938ed4 100644
--- a/src/plugins/projectexplorer/localenvironmentaspect.cpp
+++ b/src/plugins/projectexplorer/localenvironmentaspect.cpp
@@ -32,54 +32,39 @@
#include <utils/qtcassert.h>
-namespace ProjectExplorer {
+using namespace Utils;
-enum BaseEnvironmentBase {
- CleanEnvironmentBase = 0,
- SystemEnvironmentBase,
- BuildEnvironmentBase
-};
+namespace ProjectExplorer {
-Utils::Environment LocalEnvironmentAspect::baseEnvironment() const
+LocalEnvironmentAspect::LocalEnvironmentAspect(Target *target)
{
- int base = baseEnvironmentBase();
- Utils::Environment env;
- if (base == static_cast<int>(BuildEnvironmentBase)) {
- if (BuildConfiguration *bc = m_target->activeBuildConfiguration()) {
+ setIsLocal(true);
+ addSupportedBaseEnvironment(tr("Clean Environment"), {});
+
+ addSupportedBaseEnvironment(tr("System Environment"), [] {
+ return Environment::systemEnvironment();
+ });
+
+ addPreferredBaseEnvironment(tr("Build Environment"), [target] {
+ Environment env;
+ if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
env = bc->environment();
} else { // Fallback for targets without buildconfigurations:
- env = Utils::Environment::systemEnvironment();
- m_target->kit()->addToEnvironment(env);
+ env = Environment::systemEnvironment();
+ target->kit()->addToEnvironment(env);
}
- } else if (base == static_cast<int>(SystemEnvironmentBase)) {
- env = Utils::Environment::systemEnvironment();
- }
-
- if (m_baseEnvironmentModifier)
- m_baseEnvironmentModifier(env);
+ return env;
+ });
- return env;
+ target->subscribeSignal(&BuildConfiguration::environmentChanged,
+ this, &LocalEnvironmentAspect::buildEnvironmentHasChanged);
+ connect(target, &Target::activeBuildConfigurationChanged,
+ this, &LocalEnvironmentAspect::buildEnvironmentHasChanged);
}
void LocalEnvironmentAspect::buildEnvironmentHasChanged()
{
- if (baseEnvironmentBase() == static_cast<int>(BuildEnvironmentBase))
- emit environmentChanged();
-}
-
-LocalEnvironmentAspect::LocalEnvironmentAspect(Target *target,
- const BaseEnvironmentModifier &modifier) :
- m_baseEnvironmentModifier(modifier),
- m_target(target)
-{
- addPreferredBaseEnvironment(BuildEnvironmentBase, tr("Build Environment"));
- addSupportedBaseEnvironment(SystemEnvironmentBase, tr("System Environment"));
- addSupportedBaseEnvironment(CleanEnvironmentBase, tr("Clean Environment"));
-
- m_target->subscribeSignal(&BuildConfiguration::environmentChanged,
- this, &LocalEnvironmentAspect::buildEnvironmentHasChanged);
- connect(m_target, &Target::activeBuildConfigurationChanged,
- this, &LocalEnvironmentAspect::buildEnvironmentHasChanged);
+ emit environmentChanged();
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/localenvironmentaspect.h b/src/plugins/projectexplorer/localenvironmentaspect.h
index 967a985e8f..05653899b2 100644
--- a/src/plugins/projectexplorer/localenvironmentaspect.h
+++ b/src/plugins/projectexplorer/localenvironmentaspect.h
@@ -34,16 +34,9 @@ class PROJECTEXPLORER_EXPORT LocalEnvironmentAspect : public EnvironmentAspect
Q_OBJECT
public:
- using BaseEnvironmentModifier = std::function<void(Utils::Environment &)>;
- LocalEnvironmentAspect(Target *parent, const BaseEnvironmentModifier &modifier);
-
- Utils::Environment baseEnvironment() const override;
+ explicit LocalEnvironmentAspect(Target *parent);
void buildEnvironmentHasChanged();
-
-private:
- BaseEnvironmentModifier m_baseEnvironmentModifier;
- Target *m_target;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp
index b909962ce9..fecaacc89c 100644
--- a/src/plugins/projectexplorer/makestep.cpp
+++ b/src/plugins/projectexplorer/makestep.cpp
@@ -47,6 +47,7 @@
#include <QThread>
using namespace Core;
+using namespace Utils;
const char BUILD_TARGETS_SUFFIX[] = ".BuildTargets";
const char MAKE_ARGUMENTS_SUFFIX[] = ".MakeArguments";
@@ -78,7 +79,7 @@ bool MakeStep::init()
if (!bc)
emit addTask(Task::buildConfigurationMissingTask());
- const QString make = effectiveMakeCommand();
+ const FilePath make = effectiveMakeCommand();
if (make.isEmpty())
emit addTask(makeCommandMissingTask());
@@ -89,7 +90,7 @@ bool MakeStep::init()
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
- pp->setWorkingDirectory(bc->buildDirectory().toString());
+ pp->setWorkingDirectory(bc->buildDirectory());
pp->setEnvironment(environment(bc));
pp->setCommand(make);
pp->setArguments(allArguments());
@@ -104,7 +105,7 @@ bool MakeStep::init()
IOutputParser *parser = target()->kit()->createOutputParser();
if (parser)
appendOutputParser(parser);
- outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory());
+ outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory().toString());
return AbstractProcessStep::init();
}
@@ -126,7 +127,7 @@ QString MakeStep::defaultDisplayName()
static const QList<ToolChain *> preferredToolChains(const Kit *kit)
{
- QList<ToolChain *> tcs = ToolChainKitInformation::toolChains(kit);
+ QList<ToolChain *> tcs = ToolChainKitAspect::toolChains(kit);
// prefer CXX, then C, then others
Utils::sort(tcs, [](ToolChain *tcA, ToolChain *tcB) {
if (tcA->language() == tcB->language())
@@ -142,18 +143,18 @@ static const QList<ToolChain *> preferredToolChains(const Kit *kit)
return tcs;
}
-QString MakeStep::defaultMakeCommand() const
+FilePath MakeStep::defaultMakeCommand() const
{
BuildConfiguration *bc = buildConfiguration();
if (!bc)
- return QString();
+ return {};
const Utils::Environment env = environment(bc);
for (const ToolChain *tc : preferredToolChains(target()->kit())) {
- const QString make = tc->makeCommand(env);
+ FilePath make = tc->makeCommand(env);
if (!make.isEmpty())
return make;
}
- return QString();
+ return {};
}
QString MakeStep::msgNoMakeCommand()
@@ -165,7 +166,7 @@ Task MakeStep::makeCommandMissingTask()
{
return Task(Task::Error,
msgNoMakeCommand(),
- Utils::FileName(),
+ Utils::FilePath(),
-1,
Constants::TASK_CATEGORY_BUILDSYSTEM);
}
@@ -174,9 +175,7 @@ bool MakeStep::isJobCountSupported() const
{
const QList<ToolChain *> tcs = preferredToolChains(target()->kit());
const ToolChain *tc = tcs.isEmpty() ? nullptr : tcs.constFirst();
- return tc
- && (tc->targetAbi().os() != Abi::WindowsOS
- || tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor);
+ return tc && tc->isJobCountSupported();
}
int MakeStep::jobCount() const
@@ -261,7 +260,7 @@ Utils::Environment MakeStep::environment(BuildConfiguration *bc) const
return env;
}
-void MakeStep::setMakeCommand(const QString &command)
+void MakeStep::setMakeCommand(const FilePath &command)
{
m_makeCommand = command;
}
@@ -272,7 +271,7 @@ QVariantMap MakeStep::toMap() const
map.insert(id().withSuffix(BUILD_TARGETS_SUFFIX).toString(), m_buildTargets);
map.insert(id().withSuffix(MAKE_ARGUMENTS_SUFFIX).toString(), m_makeArguments);
- map.insert(id().withSuffix(MAKE_COMMAND_SUFFIX).toString(), m_makeCommand);
+ map.insert(id().withSuffix(MAKE_COMMAND_SUFFIX).toString(), m_makeCommand.toString());
map.insert(id().withSuffix(CLEAN_SUFFIX).toString(), m_clean);
const QString jobCountKey = id().withSuffix(JOBCOUNT_SUFFIX).toString();
if (m_userJobCount != defaultJobCount())
@@ -287,7 +286,8 @@ bool MakeStep::fromMap(const QVariantMap &map)
{
m_buildTargets = map.value(id().withSuffix(BUILD_TARGETS_SUFFIX).toString()).toStringList();
m_makeArguments = map.value(id().withSuffix(MAKE_ARGUMENTS_SUFFIX).toString()).toString();
- m_makeCommand = map.value(id().withSuffix(MAKE_COMMAND_SUFFIX).toString()).toString();
+ m_makeCommand = FilePath::fromString(
+ map.value(id().withSuffix(MAKE_COMMAND_SUFFIX).toString()).toString());
m_clean = map.value(id().withSuffix(CLEAN_SUFFIX).toString()).toBool();
m_overrideMakeflags = map.value(id().withSuffix(OVERRIDE_MAKEFLAGS_SUFFIX).toString(), false).toBool();
m_userJobCount = map.value(id().withSuffix(JOBCOUNT_SUFFIX).toString(), defaultJobCount()).toInt();
@@ -325,12 +325,12 @@ void MakeStep::setUserArguments(const QString &args)
m_makeArguments = args;
}
-QString MakeStep::makeCommand() const
+FilePath MakeStep::makeCommand() const
{
return m_makeCommand;
}
-QString MakeStep::effectiveMakeCommand() const
+FilePath MakeStep::effectiveMakeCommand() const
{
if (!m_makeCommand.isEmpty())
return m_makeCommand;
@@ -387,7 +387,7 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep)
m_ui->makeLineEdit->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_ui->makeLineEdit->setBaseDirectory(Utils::PathChooser::homePath());
m_ui->makeLineEdit->setHistoryCompleter("PE.MakeCommand.History");
- m_ui->makeLineEdit->setPath(m_makeStep->makeCommand());
+ m_ui->makeLineEdit->setPath(m_makeStep->makeCommand().toString());
m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());
m_ui->nonOverrideWarning->setToolTip("<html><body><p>" +
tr("<code>MAKEFLAGS</code> specifies parallel jobs. Check \"%1\" to override.")
@@ -460,7 +460,7 @@ void MakeStepConfigWidget::updateDetails()
{
BuildConfiguration *bc = m_makeStep->buildConfiguration();
- const QString defaultMake = m_makeStep->defaultMakeCommand();
+ const QString defaultMake = m_makeStep->defaultMakeCommand().toString();
if (defaultMake.isEmpty())
m_ui->makeLabel->setText(tr("Make:"));
else
@@ -485,14 +485,14 @@ void MakeStepConfigWidget::updateDetails()
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
- param.setWorkingDirectory(bc->buildDirectory().toString());
+ param.setWorkingDirectory(bc->buildDirectory());
param.setCommand(m_makeStep->effectiveMakeCommand());
-
param.setArguments(m_makeStep->allArguments());
param.setEnvironment(m_makeStep->environment(bc));
if (param.commandMissing())
- setSummaryText(tr("<b>Make:</b> %1 not found in the environment.").arg(param.command())); // Override display text
+ setSummaryText(tr("<b>Make:</b> %1 not found in the environment.")
+ .arg(param.command().toString())); // Override display text
else
setSummaryText(param.summaryInWorkdir(displayName()));
}
@@ -505,7 +505,7 @@ void MakeStepConfigWidget::itemChanged(QListWidgetItem *item)
void MakeStepConfigWidget::makeLineEditTextEdited()
{
- m_makeStep->setMakeCommand(m_ui->makeLineEdit->rawPath());
+ m_makeStep->setMakeCommand(FilePath::fromString(m_ui->makeLineEdit->rawPath()));
updateDetails();
}
diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h
index 036b55e254..e44b52851e 100644
--- a/src/plugins/projectexplorer/makestep.h
+++ b/src/plugins/projectexplorer/makestep.h
@@ -28,6 +28,8 @@
#include "abstractprocessstep.h"
#include "projectexplorer_global.h"
+#include <utils/fileutils.h>
+
QT_FORWARD_DECLARE_CLASS(QListWidgetItem);
namespace Utils { class Environment; }
@@ -56,16 +58,16 @@ public:
QString allArguments() const;
QString userArguments() const;
void setUserArguments(const QString &args);
- QString makeCommand() const;
- void setMakeCommand(const QString &command);
- QString effectiveMakeCommand() const;
+ Utils::FilePath makeCommand() const;
+ void setMakeCommand(const Utils::FilePath &command);
+ Utils::FilePath effectiveMakeCommand() const;
void setClean(bool clean);
bool isClean() const;
static QString defaultDisplayName();
- QString defaultMakeCommand() const;
+ Utils::FilePath defaultMakeCommand() const;
static QString msgNoMakeCommand();
static Task makeCommandMissingTask();
@@ -80,16 +82,18 @@ public:
Utils::Environment environment(BuildConfiguration *bc) const;
+protected:
+ bool fromMap(const QVariantMap &map) override;
+
private:
QVariantMap toMap() const override;
- bool fromMap(const QVariantMap &map) override;
static int defaultJobCount();
QStringList jobArguments() const;
QStringList m_buildTargets;
QStringList m_availableTargets;
QString m_makeArguments;
- QString m_makeCommand;
+ Utils::FilePath m_makeCommand;
int m_userJobCount = 4;
bool m_overrideMakeflags = false;
bool m_clean = false;
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index 7d0573b0ac..aa01c0f9b6 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -25,10 +25,8 @@
#include "buildconfiguration.h"
#include "deployconfiguration.h"
-#include "kitconfigwidget.h"
#include "kit.h"
#include "kitmanager.h"
-#include "kitmanager.h"
#include "miniprojecttargetselector.h"
#include "projectexplorer.h"
#include "projectexplorericons.h"
@@ -298,7 +296,7 @@ void ProjectListWidget::addProject(Project *project)
setCurrentItem(item);
QFontMetrics fn(font());
- int width = fn.width(displayName) + padding();
+ int width = fn.horizontalAdvance(displayName) + padding();
if (width > optimalWidth())
setOptimalWidth(width);
@@ -333,7 +331,7 @@ void ProjectListWidget::removeProject(Project *project)
// recheck optimal width
int width = 0;
for (int i = 0; i < count(); ++i)
- width = qMax(fn.width(item(i)->text()) + padding(), width);
+ width = qMax(fn.horizontalAdvance(item(i)->text()) + padding(), width);
setOptimalWidth(width);
m_ignoreIndexChange = false;
@@ -377,7 +375,7 @@ void ProjectListWidget::projectDisplayNameChanged(Project *project)
QFontMetrics fn(font());
int width = 0;
for (int i = 0; i < count(); ++i)
- width = qMax(fn.width(item(i)->text()) + padding(), width);
+ width = qMax(fn.horizontalAdvance(item(i)->text()) + padding(), width);
setOptimalWidth(width);
m_ignoreIndexChange = false;
@@ -424,7 +422,7 @@ void GenericListWidget::setProjectConfigurations(const QList<ProjectConfiguratio
int width = 0;
foreach (ProjectConfiguration *pc, list) {
addProjectConfiguration(pc);
- width = qMax(width, fn.width(pc->displayName()) + padding());
+ width = qMax(width, fn.horizontalAdvance(pc->displayName()) + padding());
}
setOptimalWidth(width);
setActiveProjectConfiguration(active);
@@ -463,7 +461,7 @@ void GenericListWidget::addProjectConfiguration(ProjectConfiguration *pc)
connect(pc, &ProjectConfiguration::toolTipChanged, this, &GenericListWidget::toolTipChanged);
QFontMetrics fn(font());
- int width = fn.width(pc->displayName()) + padding();
+ int width = fn.horizontalAdvance(pc->displayName()) + padding();
if (width > optimalWidth())
setOptimalWidth(width);
@@ -481,7 +479,7 @@ void GenericListWidget::removeProjectConfiguration(ProjectConfiguration *pc)
int width = 0;
for (int i = 0; i < count(); ++i) {
auto *p = item(i)->data(Qt::UserRole).value<ProjectConfiguration *>();
- width = qMax(width, fn.width(p->displayName()) + padding());
+ width = qMax(width, fn.horizontalAdvance(p->displayName()) + padding());
}
setOptimalWidth(width);
@@ -534,7 +532,7 @@ void GenericListWidget::displayNameChanged()
int width = 0;
for (int i = 0; i < count(); ++i) {
auto *p = item(i)->data(Qt::UserRole).value<ProjectConfiguration *>();
- width = qMax(width, fn.width(p->displayName()) + padding());
+ width = qMax(width, fn.horizontalAdvance(p->displayName()) + padding());
}
setOptimalWidth(width);
@@ -579,7 +577,7 @@ KitAreaWidget::~KitAreaWidget()
void KitAreaWidget::setKit(Kit *k)
{
- foreach (KitConfigWidget *w, m_widgets)
+ foreach (KitAspectWidget *w, m_widgets)
delete(w);
m_widgets.clear();
@@ -591,11 +589,11 @@ void KitAreaWidget::setKit(Kit *k)
m_labels.clear();
int row = 0;
- foreach (KitInformation *ki, KitManager::kitInformation()) {
- if (k && k->isMutable(ki->id())) {
- KitConfigWidget *widget = ki->createConfigWidget(k);
+ for (KitAspect *aspect : KitManager::kitAspects()) {
+ if (k && k->isMutable(aspect->id())) {
+ KitAspectWidget *widget = aspect->createConfigWidget(k);
m_widgets << widget;
- QLabel *label = new QLabel(widget->displayName());
+ QLabel *label = new QLabel(aspect->displayName());
m_labels << label;
widget->setStyle(QStyleFactory::create(QLatin1String("fusion")));
@@ -619,10 +617,10 @@ void KitAreaWidget::updateKit(Kit *k)
return;
bool addedMutables = false;
- QList<Core::Id> knownIdList = Utils::transform(m_widgets, &KitConfigWidget::kitInformationId);
+ QList<Core::Id> knownIdList = Utils::transform(m_widgets, &KitAspectWidget::kitInformationId);
- foreach (KitInformation *ki, KitManager::kitInformation()) {
- Core::Id currentId = ki->id();
+ for (KitAspect *aspect : KitManager::kitAspects()) {
+ const Core::Id currentId = aspect->id();
if (m_kit->isMutable(currentId) && !knownIdList.removeOne(currentId)) {
addedMutables = true;
break;
@@ -635,7 +633,7 @@ void KitAreaWidget::updateKit(Kit *k)
setKit(m_kit);
} else {
// Refresh all widgets if the number of mutable settings did not change
- foreach (KitConfigWidget *w, m_widgets)
+ foreach (KitAspectWidget *w, m_widgets)
w->refresh();
}
}
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h
index 0c2e51a4f4..032f69f7eb 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.h
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.h
@@ -37,7 +37,7 @@ QT_END_NAMESPACE
namespace ProjectExplorer {
class Kit;
-class KitConfigWidget;
+class KitAspectWidget;
class Project;
class Target;
class BuildConfiguration;
@@ -101,7 +101,7 @@ private:
QGridLayout *m_layout;
Kit *m_kit = nullptr;
- QList<KitConfigWidget *> m_widgets;
+ QList<KitAspectWidget *> m_widgets;
QList<QLabel *> m_labels;
};
diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp
index b99880252a..2d3095c168 100644
--- a/src/plugins/projectexplorer/msvcparser.cpp
+++ b/src/plugins/projectexplorer/msvcparser.cpp
@@ -35,11 +35,11 @@ using namespace Utils;
// As of MSVC 2015: "foo.cpp(42) :" -> "foo.cpp(42):"
static const char FILE_POS_PATTERN[] = "^(?:\\d+>)?(cl|LINK|.+[^ ]) ?: ";
-static QPair<FileName, int> parseFileName(const QString &input)
+static QPair<FilePath, int> parseFileName(const QString &input)
{
QString fileName = input;
if (fileName.startsWith("LINK") || fileName.startsWith("cl"))
- return qMakePair(FileName(), -1);
+ return qMakePair(FilePath(), -1);
// Extract linenumber (if it is there):
int linenumber = -1;
@@ -59,7 +59,7 @@ static QPair<FileName, int> parseFileName(const QString &input)
}
}
const QString normalized = FileUtils::normalizePathName(fileName);
- return qMakePair(FileName::fromUserInput(normalized), linenumber);
+ return qMakePair(FilePath::fromUserInput(normalized), linenumber);
}
using namespace ProjectExplorer;
@@ -78,7 +78,7 @@ static bool handleNmakeJomMessage(const QString &line, Task *task)
*task = Task(Task::Error,
line.mid(matchLength).trimmed(), /* description */
- FileName(), /* fileName */
+ FilePath(), /* fileName */
-1, /* linenumber */
Constants::TASK_CATEGORY_COMPILE);
return true;
@@ -146,7 +146,7 @@ void MsvcParser::stdOutput(const QString &line)
if (!match.captured(1).isEmpty())
description.chop(1); // Remove trailing quote
m_lastTask = Task(Task::Unknown, description,
- FileName::fromUserInput(match.captured(2)), /* fileName */
+ FilePath::fromUserInput(match.captured(2)), /* fileName */
match.captured(3).toInt(), /* linenumber */
Constants::TASK_CATEGORY_COMPILE);
m_lines = 1;
@@ -178,7 +178,7 @@ bool MsvcParser::processCompileLine(const QString &line)
QRegularExpressionMatch match = m_compileRegExp.match(line);
if (match.hasMatch()) {
- QPair<FileName, int> position = parseFileName(match.captured(1));
+ QPair<FilePath, int> position = parseFileName(match.captured(1));
m_lastTask = Task(taskType(match.captured(2)),
match.captured(3) + match.captured(4).trimmed(), // description
position.first, position.second,
@@ -261,7 +261,7 @@ void ClangClParser::stdError(const QString &lineIn)
QRegularExpressionMatch match = m_compileRegExp.match(line);
if (match.hasMatch()) {
doFlush();
- const QPair<FileName, int> position = parseFileName(match.captured(1));
+ const QPair<FilePath, int> position = parseFileName(match.captured(1));
m_lastTask = Task(taskType(match.captured(2)), match.captured(3).trimmed(),
position.first, position.second,
Constants::TASK_CATEGORY_COMPILE);
@@ -307,28 +307,28 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
QTest::newRow("pass-through stdout")
<< "Sometext" << OutputParserTester::STDOUT
<< "Sometext\n" << ""
- << QList<Task>()
+ << Tasks()
<< "";
QTest::newRow("pass-through stderr")
<< "Sometext" << OutputParserTester::STDERR
<< "" << "Sometext\n"
- << QList<Task>()
+ << Tasks()
<< "";
QTest::newRow("labeled error")
<< "qmlstandalone\\main.cpp(54) : error C4716: 'findUnresolvedModule' : must return a value"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"C4716: 'findUnresolvedModule' : must return a value",
- FileName::fromUserInput("qmlstandalone\\main.cpp"), 54,
+ FilePath::fromUserInput("qmlstandalone\\main.cpp"), 54,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -336,10 +336,10 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "qmlstandalone\\main.cpp(54): error C4716: 'findUnresolvedModule' : must return a value"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"C4716: 'findUnresolvedModule' : must return a value",
- FileName::fromUserInput("qmlstandalone\\main.cpp"), 54,
+ FilePath::fromUserInput("qmlstandalone\\main.cpp"), 54,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -347,10 +347,10 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "1>qmlstandalone\\main.cpp(54) : error C4716: 'findUnresolvedModule' : must return a value"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"C4716: 'findUnresolvedModule' : must return a value",
- FileName::fromUserInput("qmlstandalone\\main.cpp"), 54,
+ FilePath::fromUserInput("qmlstandalone\\main.cpp"), 54,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -358,10 +358,10 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "x:\\src\\plugins\\projectexplorer\\msvcparser.cpp(69) : warning C4100: 'something' : unreferenced formal parameter"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
"C4100: 'something' : unreferenced formal parameter",
- FileName::fromUserInput("x:\\src\\plugins\\projectexplorer\\msvcparser.cpp"), 69,
+ FilePath::fromUserInput("x:\\src\\plugins\\projectexplorer\\msvcparser.cpp"), 69,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -370,10 +370,10 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "1>x:\\src\\plugins\\projectexplorer\\msvcparser.cpp(69) : warning C4100: 'something' : unreferenced formal parameter"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
"C4100: 'something' : unreferenced formal parameter",
- FileName::fromUserInput("x:\\src\\plugins\\projectexplorer\\msvcparser.cpp"), 69,
+ FilePath::fromUserInput("x:\\src\\plugins\\projectexplorer\\msvcparser.cpp"), 69,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -382,14 +382,14 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
" x:\\src\\plugins\\texteditor\\completionsupport.h(39) : see declaration of 'TextEditor::CompletionItem'"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
"C4099: 'TextEditor::CompletionItem' : type name first seen using 'struct' now seen using 'class'",
- FileName::fromUserInput("x:\\src\\plugins\\texteditor\\icompletioncollector.h"), 50,
+ FilePath::fromUserInput("x:\\src\\plugins\\texteditor\\icompletioncollector.h"), 50,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Unknown,
"see declaration of 'TextEditor::CompletionItem'",
- FileName::fromUserInput("x:\\src\\plugins\\texteditor\\completionsupport.h"), 39,
+ FilePath::fromUserInput("x:\\src\\plugins\\texteditor\\completionsupport.h"), 39,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -398,14 +398,14 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
" x:\\src\\plugins\\texteditor\\completionsupport.h(39) : see declaration of 'TextEditor::CompletionItem'"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
"C4099: 'TextEditor::CompletionItem' : type name first seen using 'struct' now seen using 'class'",
- FileName::fromUserInput("x:\\src\\plugins\\texteditor\\icompletioncollector.h"), 50,
+ FilePath::fromUserInput("x:\\src\\plugins\\texteditor\\icompletioncollector.h"), 50,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Unknown,
"see declaration of 'TextEditor::CompletionItem'",
- FileName::fromUserInput("x:\\src\\plugins\\texteditor\\completionsupport.h"), 39,
+ FilePath::fromUserInput("x:\\src\\plugins\\texteditor\\completionsupport.h"), 39,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -413,10 +413,10 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "LINK : fatal error LNK1146: no argument specified with option '/LIBPATH:'"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"LNK1146: no argument specified with option '/LIBPATH:'",
- FileName(), -1,
+ FilePath(), -1,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -425,10 +425,10 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "cl : Command line warning D9002 : ignoring unknown option '-fopenmp'"
<< OutputParserTester::STDERR
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
"D9002 : ignoring unknown option '-fopenmp'",
- FileName(), -1,
+ FilePath(), -1,
Constants::TASK_CATEGORY_COMPILE))
<< "";
QTest::newRow("complex error")
@@ -440,7 +440,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
" No constructor could take the source type, or constructor overload resolution was ambiguous"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"C2440: 'initializing' : cannot convert from 'int' to 'std::_Tree<_Traits>::iterator'\n"
"with\n"
@@ -448,27 +448,27 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
" _Traits=std::_Tmap_traits<int,double,std::less<int>,std::allocator<std::pair<const int,double>>,false>\n"
"]\n"
"No constructor could take the source type, or constructor overload resolution was ambiguous",
- FileName::fromUserInput("..\\untitled\\main.cpp"), 19,
+ FilePath::fromUserInput("..\\untitled\\main.cpp"), 19,
Constants::TASK_CATEGORY_COMPILE))
<< "";
QTest::newRow("Linker error 1")
<< "main.obj : error LNK2019: unresolved external symbol \"public: void __thiscall Data::doit(void)\" (?doit@Data@@QAEXXZ) referenced in function _main"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"LNK2019: unresolved external symbol \"public: void __thiscall Data::doit(void)\" (?doit@Data@@QAEXXZ) referenced in function _main",
- FileName::fromUserInput("main.obj"), -1,
+ FilePath::fromUserInput("main.obj"), -1,
Constants::TASK_CATEGORY_COMPILE))
<< "";
QTest::newRow("Linker error 2")
<< "debug\\Experimentation.exe : fatal error LNK1120: 1 unresolved externals"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"LNK1120: 1 unresolved externals",
- FileName::fromUserInput("debug\\Experimentation.exe"), -1,
+ FilePath::fromUserInput("debug\\Experimentation.exe"), -1,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -476,20 +476,20 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< "Error: dependent '..\\..\\..\\..\\creator-2.5\\src\\plugins\\coreplugin\\ifile.h' does not exist."
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"dependent '..\\..\\..\\..\\creator-2.5\\src\\plugins\\coreplugin\\ifile.h' does not exist.",
- FileName(), -1,
+ FilePath(), -1,
Constants::TASK_CATEGORY_COMPILE))
<< "";
QTest::newRow("jom error")
<< "Error: dependent 'main.cpp' does not exist."
<< OutputParserTester::STDERR
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"dependent 'main.cpp' does not exist.",
- FileName(), -1,
+ FilePath(), -1,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -504,14 +504,14 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
" ]"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
"C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'",
- FileName::fromUserInput("c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE\\xutility"), 2227,
+ FilePath::fromUserInput("c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE\\xutility"), 2227,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Unknown,
"see declaration of 'std::_Copy_impl'",
- FileName::fromUserInput("c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE\\xutility"), 2212,
+ FilePath::fromUserInput("c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE\\xutility"), 2212,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Unknown,
"see reference to function template instantiation '_OutIt std::copy<const unsigned char*,unsigned short*>(_InIt,_InIt,_OutIt)' being compiled\n"
@@ -520,7 +520,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
" _OutIt=unsigned short *,\n"
" _InIt=const unsigned char *\n"
"]",
- FileName::fromUserInput("symbolgroupvalue.cpp"), 2314,
+ FilePath::fromUserInput("symbolgroupvalue.cpp"), 2314,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -530,25 +530,25 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
" or 'D:\\Project\\types.h(71) : Types::UINT64'"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"C2872: 'UINT64' : ambiguous symbol",
- FileName::fromUserInput("D:\\Project\\file.h"), 98,
+ FilePath::fromUserInput("D:\\Project\\file.h"), 98,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Unknown,
"could be unsigned __int64 UINT64",
- FileName::fromUserInput("C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include\\basetsd.h"), 83,
+ FilePath::fromUserInput("C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include\\basetsd.h"), 83,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Unknown,
"or Types::UINT64",
- FileName::fromUserInput("D:\\Project\\types.h"), 71,
+ FilePath::fromUserInput("D:\\Project\\types.h"), 71,
Constants::TASK_CATEGORY_COMPILE))
<< "";
QTest::newRow("ignore moc note")
<< "/home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated."
<< OutputParserTester::STDERR
<< "" << "/home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated.\n"
- << (QList<ProjectExplorer::Task>())
+ << (Tasks())
<< "";
QTest::newRow("error with note")
@@ -556,14 +556,14 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
"main.cpp(6): note: see declaration of 'func'"
<< OutputParserTester::STDOUT
<< "" << ""
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Error,
"C2733: 'func': second C linkage of overloaded function not allowed",
- FileName::fromUserInput("main.cpp"), 7,
+ FilePath::fromUserInput("main.cpp"), 7,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Unknown,
"see declaration of 'func'",
- FileName::fromUserInput("main.cpp"), 6,
+ FilePath::fromUserInput("main.cpp"), 6,
Constants::TASK_CATEGORY_COMPILE))
<< "";
@@ -571,10 +571,10 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
<< QString::fromUtf8("cl: командная строка warning D9025: переопределение \"/MDd\" на \"/MTd\"")
<< OutputParserTester::STDERR
<< "" << ""
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Warning,
QString::fromUtf8("D9025: переопределение \"/MDd\" на \"/MTd\""),
- FileName(), -1, Constants::TASK_CATEGORY_COMPILE))
+ FilePath(), -1, Constants::TASK_CATEGORY_COMPILE))
<< "";
}
@@ -584,7 +584,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers()
testbench.appendOutputParser(new MsvcParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
@@ -600,7 +600,7 @@ void ProjectExplorerPlugin::testClangClOutputParsers_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
const QString warning1 = "private field 'm_version' is not used [-Wunused-private-field]\n"
@@ -643,21 +643,21 @@ void ProjectExplorerPlugin::testClangClOutputParsers_data()
<< input
<< OutputParserTester::STDERR
<< "" << expectedStderr
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning, warning1.trimmed(),
- FileName::fromUserInput("./qwindowseglcontext.h"), 282,
+ FilePath::fromUserInput("./qwindowseglcontext.h"), 282,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Warning, warning2.trimmed(),
- FileName::fromUserInput(".\\qwindowsclipboard.cpp"), 60,
+ FilePath::fromUserInput(".\\qwindowsclipboard.cpp"), 60,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Warning, warning3.trimmed(),
- FileName::fromUserInput(".\\qwindowsclipboard.cpp"), 61,
+ FilePath::fromUserInput(".\\qwindowsclipboard.cpp"), 61,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Error, expectedError1,
- FileName::fromUserInput(".\\qwindowsgdinativeinterface.cpp"), 48,
+ FilePath::fromUserInput(".\\qwindowsgdinativeinterface.cpp"), 48,
Constants::TASK_CATEGORY_COMPILE)
<< Task(Task::Error, error2.trimmed(),
- FileName::fromUserInput(".\\qwindowsgdinativeinterface.cpp"), 51,
+ FilePath::fromUserInput(".\\qwindowsgdinativeinterface.cpp"), 51,
Constants::TASK_CATEGORY_COMPILE))
<< "";
}
@@ -668,7 +668,7 @@ void ProjectExplorerPlugin::testClangClOutputParsers()
testbench.appendOutputParser(new ClangClParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 9c86a70686..24b528154d 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -60,10 +60,13 @@
#include <QComboBox>
#include <QFormLayout>
+using namespace Utils;
+
#define KEY_ROOT "ProjectExplorer.MsvcToolChain."
static const char varsBatKeyC[] = KEY_ROOT "VarsBat";
static const char varsBatArgKeyC[] = KEY_ROOT "VarsBatArg";
static const char supportedAbiKeyC[] = KEY_ROOT "SupportedAbi";
+static const char supportedAbisKeyC[] = KEY_ROOT "SupportedAbis";
static const char environModsKeyC[] = KEY_ROOT "environmentModifications";
enum { debug = 0 };
@@ -206,7 +209,7 @@ static Utils::optional<VisualStudioInstallation> installationFromPathAndVersion(
installation.vsName = versionString;
installation.vcVarsPath = vcVarsPath;
installation.vcVarsAll = vcVarsAllPath;
- return std::move(installation);
+ return installation;
}
// Detect build tools introduced with MSVC2017
@@ -349,33 +352,50 @@ static QVector<VisualStudioInstallation> detectVisualStudio()
return detectVisualStudioFromRegistry();
}
+static unsigned char wordWidthForPlatform(MsvcToolChain::Platform platform)
+{
+ switch (platform) {
+ case ProjectExplorer::Internal::MsvcToolChain::x86:
+ case ProjectExplorer::Internal::MsvcToolChain::arm:
+ case ProjectExplorer::Internal::MsvcToolChain::x86_arm:
+ case ProjectExplorer::Internal::MsvcToolChain::amd64_arm:
+ case ProjectExplorer::Internal::MsvcToolChain::amd64_x86:
+ return 32;
+ case ProjectExplorer::Internal::MsvcToolChain::amd64:
+ case ProjectExplorer::Internal::MsvcToolChain::x86_amd64:
+ case ProjectExplorer::Internal::MsvcToolChain::ia64:
+ case ProjectExplorer::Internal::MsvcToolChain::x86_ia64:
+ return 64;
+ }
+
+ return 0;
+}
+
+static Abi::Architecture archForPlatform(MsvcToolChain::Platform platform)
+{
+ switch (platform) {
+ case ProjectExplorer::Internal::MsvcToolChain::x86:
+ case ProjectExplorer::Internal::MsvcToolChain::amd64:
+ case ProjectExplorer::Internal::MsvcToolChain::x86_amd64:
+ case ProjectExplorer::Internal::MsvcToolChain::amd64_x86:
+ return Abi::X86Architecture;
+ case ProjectExplorer::Internal::MsvcToolChain::arm:
+ case ProjectExplorer::Internal::MsvcToolChain::x86_arm:
+ case ProjectExplorer::Internal::MsvcToolChain::amd64_arm:
+ return Abi::ArmArchitecture;
+ case ProjectExplorer::Internal::MsvcToolChain::ia64:
+ case ProjectExplorer::Internal::MsvcToolChain::x86_ia64:
+ return Abi::ItaniumArchitecture;
+ }
+
+ return Abi::UnknownArchitecture;
+}
+
static Abi findAbiOfMsvc(MsvcToolChain::Type type,
MsvcToolChain::Platform platform,
const QString &version)
{
- Abi::Architecture arch = Abi::X86Architecture;
Abi::OSFlavor flavor = Abi::UnknownFlavor;
- int wordWidth = 64;
-
- switch (platform) {
- case MsvcToolChain::x86:
- case MsvcToolChain::amd64_x86:
- wordWidth = 32;
- break;
- case MsvcToolChain::ia64:
- case MsvcToolChain::x86_ia64:
- arch = Abi::ItaniumArchitecture;
- break;
- case MsvcToolChain::amd64:
- case MsvcToolChain::x86_amd64:
- break;
- case MsvcToolChain::arm:
- case MsvcToolChain::x86_arm:
- case MsvcToolChain::amd64_arm:
- arch = Abi::ArmArchitecture;
- wordWidth = 32;
- break;
- };
QString msvcVersionString = version;
if (type == MsvcToolChain::WindowsSDK) {
@@ -400,7 +420,8 @@ static Abi findAbiOfMsvc(MsvcToolChain::Type type,
flavor = Abi::WindowsMsvc2008Flavor;
else
flavor = Abi::WindowsMsvc2005Flavor;
- const Abi result = Abi(arch, Abi::WindowsOS, flavor, Abi::PEFormat, wordWidth);
+ const Abi result = Abi(archForPlatform(platform), Abi::WindowsOS, flavor, Abi::PEFormat,
+ wordWidthForPlatform(platform));
if (!result.isValid())
qWarning("Unable to completely determine the ABI of MSVC version %s (%s).",
qPrintable(version),
@@ -592,7 +613,7 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList &cxxflags,
cpp.setEnvironment(env.toStringList());
cpp.setWorkingDirectory(Utils::TemporaryDirectory::masterDirectoryPath());
QStringList arguments;
- const Utils::FileName binary = env.searchInPath(QLatin1String("cl.exe"));
+ const Utils::FilePath binary = env.searchInPath(QLatin1String("cl.exe"));
if (binary.isEmpty()) {
qWarning("%s: The compiler binary cl.exe could not be found in the path.", Q_FUNC_INFO);
return predefinedMacros;
@@ -748,10 +769,46 @@ void MsvcToolChain::updateEnvironmentModifications(QList<Utils::EnvironmentItem>
Utils::EnvironmentItem::sort(&modifications);
if (modifications != m_environmentModifications) {
m_environmentModifications = modifications;
+ rescanForCompiler();
toolChainUpdated();
}
}
+void MsvcToolChain::detectInstalledAbis()
+{
+ static QMap<QString, Abis> abiCache;
+ const QString vcVarsBase
+ = QDir::fromNativeSeparators(m_vcvarsBat).left(m_vcvarsBat.lastIndexOf('/'));
+ if (abiCache.contains(vcVarsBase)) {
+ m_supportedAbis = abiCache.value(vcVarsBase);
+ return;
+ }
+
+ QTC_ASSERT(m_supportedAbis.isEmpty(), return);
+ const Abi baseAbi = targetAbi();
+ for (MsvcPlatform platform : platforms) {
+ bool toolchainInstalled = false;
+ QString perhapsVcVarsPath = vcVarsBase + QLatin1Char('/') + QLatin1String(platform.bat);
+ const Platform p = platform.platform;
+ if (QFileInfo(perhapsVcVarsPath).isFile()) {
+ toolchainInstalled = true;
+ } else {
+ // MSVC 2015 and below had various versions of vcvars scripts in subfolders. Try these
+ // as fallbacks.
+ perhapsVcVarsPath = vcVarsBase + platform.prefix + QLatin1Char('/')
+ + QLatin1String(platform.bat);
+ toolchainInstalled = QFileInfo(perhapsVcVarsPath).isFile();
+ }
+ if (hostSupportsPlatform(platform.platform) && toolchainInstalled) {
+ Abi newAbi(archForPlatform(p), baseAbi.os(), baseAbi.osFlavor(), baseAbi.binaryFormat(),
+ wordWidthForPlatform(p));
+ if (!m_supportedAbis.contains(newAbi))
+ m_supportedAbis.append(newAbi);
+ }
+ }
+ abiCache.insert(vcVarsBase, m_supportedAbis);
+}
+
Utils::Environment MsvcToolChain::readEnvironmentSetting(const Utils::Environment &env) const
{
Utils::Environment resultEnv = env;
@@ -780,67 +837,34 @@ Utils::Environment MsvcToolChain::readEnvironmentSetting(const Utils::Environmen
MsvcToolChain::MsvcToolChain(const QString &name,
const Abi &abi,
const QString &varsBat,
- const QString &varsBatArg,
- Core::Id l,
- Detection d)
- : MsvcToolChain(Constants::MSVC_TOOLCHAIN_TYPEID, name, abi, varsBat, varsBatArg, l, d)
+ const QString &varsBatArg)
+ : MsvcToolChain(Constants::MSVC_TOOLCHAIN_TYPEID, name, abi, varsBat, varsBatArg)
{}
-MsvcToolChain::MsvcToolChain(const MsvcToolChain &other)
- : ToolChain(other)
- , m_headerPathsMutex(new QMutex)
- , m_environmentModifications(other.m_environmentModifications)
- , m_debuggerCommand(other.m_debuggerCommand)
- , m_predefinedMacrosCache(other.m_predefinedMacrosCache)
- , m_lastEnvironment(other.m_lastEnvironment)
- , m_resultEnvironment(other.m_resultEnvironment)
- , m_abi(other.m_abi)
- , m_vcvarsBat(other.m_vcvarsBat)
- , m_varsBatArg(other.m_varsBatArg)
-{
- if (other.m_envModWatcher.isRunning()) {
- initEnvModWatcher(other.m_envModWatcher.future());
- } else if (m_environmentModifications.isEmpty() && other.m_envModWatcher.future().isFinished()
- && !other.m_envModWatcher.future().isCanceled()) {
- const GenerateEnvResult &result = m_envModWatcher.result();
- if (result.error) {
- const QString &errorMessage = *result.error;
- if (!errorMessage.isEmpty())
- TaskHub::addTask(Task::Error, errorMessage, Constants::TASK_CATEGORY_COMPILE);
- } else {
- updateEnvironmentModifications(result.environmentItems);
- }
- }
-
- setDisplayName(other.displayName());
-}
-
static void addToAvailableMsvcToolchains(const MsvcToolChain *toolchain)
{
if (toolchain->typeId() != Constants::MSVC_TOOLCHAIN_TYPEID)
return;
- g_availableMsvcToolchains.push_back(toolchain);
+ if (!g_availableMsvcToolchains.contains(toolchain))
+ g_availableMsvcToolchains.push_back(toolchain);
}
MsvcToolChain::MsvcToolChain(Core::Id typeId,
const QString &name,
const Abi &abi,
const QString &varsBat,
- const QString &varsBatArg,
- Core::Id l,
- Detection d)
- : ToolChain(typeId, d)
+ const QString &varsBatArg)
+ : ToolChain(typeId)
, m_headerPathsMutex(new QMutex)
- , m_predefinedMacrosCache(std::make_shared<Cache<MacroInspectionReport, 64>>())
, m_lastEnvironment(Utils::Environment::systemEnvironment())
, m_abi(abi)
, m_vcvarsBat(varsBat)
, m_varsBatArg(varsBatArg)
{
+ detectInstalledAbis();
addToAvailableMsvcToolchains(this);
- setLanguage(l);
initEnvModWatcher(Utils::runAsync(envModThreadPool(),
&MsvcToolChain::environmentModifications,
varsBat,
@@ -852,9 +876,7 @@ MsvcToolChain::MsvcToolChain(Core::Id typeId,
}
MsvcToolChain::MsvcToolChain(Core::Id typeId)
- : ToolChain(typeId, ManualDetection)
- , m_predefinedMacrosCache(std::make_shared<Cache<MacroInspectionReport, 64>>())
- , m_lastEnvironment(Utils::Environment::systemEnvironment())
+ : ToolChain(typeId)
{}
void MsvcToolChain::inferWarningsForLevel(int warningLevel, WarningFlags &flags)
@@ -876,11 +898,6 @@ void MsvcToolChain::inferWarningsForLevel(int warningLevel, WarningFlags &flags)
flags |= WarningFlags::UnusedParams;
}
-void MsvcToolChain::toolChainUpdated()
-{
- m_predefinedMacrosCache->invalidate();
-}
-
MsvcToolChain::MsvcToolChain()
: MsvcToolChain(Constants::MSVC_TOOLCHAIN_TYPEID)
{}
@@ -896,6 +913,19 @@ Abi MsvcToolChain::targetAbi() const
return m_abi;
}
+Abis MsvcToolChain::supportedAbis() const
+{
+ return m_supportedAbis;
+}
+
+void MsvcToolChain::setTargetAbi(const Abi &abi)
+{
+ if (m_abi == abi)
+ return;
+
+ m_abi = abi;
+}
+
bool MsvcToolChain::isValid() const
{
if (m_vcvarsBat.isEmpty())
@@ -915,53 +945,52 @@ QString MsvcToolChain::typeDisplayName() const
return MsvcToolChainFactory::tr("MSVC");
}
-Utils::FileNameList MsvcToolChain::suggestedMkspecList() const
+QStringList MsvcToolChain::suggestedMkspecList() const
{
- Utils::FileNameList result;
- result << Utils::FileName::fromLatin1("win32-msvc"); // Common MSVC mkspec introduced in 5.8.1
+ QStringList result = {"win32-msvc"}; // Common MSVC mkspec introduced in 5.8.1
switch (m_abi.osFlavor()) {
case Abi::WindowsMsvc2005Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2005");
+ result << "win32-msvc2005";
break;
case Abi::WindowsMsvc2008Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2008");
+ result << "win32-msvc2008";
break;
case Abi::WindowsMsvc2010Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2010");
+ result << "win32-msvc2010";
break;
case Abi::WindowsMsvc2012Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2012")
- << Utils::FileName::fromLatin1("win32-msvc2010");
+ result << "win32-msvc2012"
+ << "win32-msvc2010";
break;
case Abi::WindowsMsvc2013Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2013")
- << Utils::FileName::fromLatin1("winphone-arm-msvc2013")
- << Utils::FileName::fromLatin1("winphone-x86-msvc2013")
- << Utils::FileName::fromLatin1("winrt-arm-msvc2013")
- << Utils::FileName::fromLatin1("winrt-x86-msvc2013")
- << Utils::FileName::fromLatin1("winrt-x64-msvc2013")
- << Utils::FileName::fromLatin1("win32-msvc2012")
- << Utils::FileName::fromLatin1("win32-msvc2010");
+ result << "win32-msvc2013"
+ << "winphone-arm-msvc2013"
+ << "winphone-x86-msvc2013"
+ << "winrt-arm-msvc2013"
+ << "winrt-x86-msvc2013"
+ << "winrt-x64-msvc2013"
+ << "win32-msvc2012"
+ << "win32-msvc2010";
break;
case Abi::WindowsMsvc2015Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2015")
- << Utils::FileName::fromLatin1("winphone-arm-msvc2015")
- << Utils::FileName::fromLatin1("winphone-x86-msvc2015")
- << Utils::FileName::fromLatin1("winrt-arm-msvc2015")
- << Utils::FileName::fromLatin1("winrt-x86-msvc2015")
- << Utils::FileName::fromLatin1("winrt-x64-msvc2015");
+ result << "win32-msvc2015"
+ << "winphone-arm-msvc2015"
+ << "winphone-x86-msvc2015"
+ << "winrt-arm-msvc2015"
+ << "winrt-x86-msvc2015"
+ << "winrt-x64-msvc2015";
break;
case Abi::WindowsMsvc2017Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2017")
- << Utils::FileName::fromLatin1("winrt-arm-msvc2017")
- << Utils::FileName::fromLatin1("winrt-x86-msvc2017")
- << Utils::FileName::fromLatin1("winrt-x64-msvc2017");
+ result << "win32-msvc2017"
+ << "winrt-arm-msvc2017"
+ << "winrt-x86-msvc2017"
+ << "winrt-x64-msvc2017";
break;
case Abi::WindowsMsvc2019Flavor:
- result << Utils::FileName::fromLatin1("win32-msvc2019")
- << Utils::FileName::fromLatin1("winrt-arm-msvc2019")
- << Utils::FileName::fromLatin1("winrt-x86-msvc2019")
- << Utils::FileName::fromLatin1("winrt-x64-msvc2019");
+ result << "win32-msvc2019"
+ << "winrt-arm-msvc2019"
+ << "winrt-x86-msvc2019"
+ << "winrt-x64-msvc2019";
break;
default:
result.clear();
@@ -977,6 +1006,7 @@ QVariantMap MsvcToolChain::toMap() const
if (!m_varsBatArg.isEmpty())
data.insert(QLatin1String(varsBatArgKeyC), m_varsBatArg);
data.insert(QLatin1String(supportedAbiKeyC), m_abi.toString());
+ data.insert(supportedAbisKeyC, Utils::transform<QStringList>(m_supportedAbis, &Abi::toString));
Utils::EnvironmentItem::sort(&m_environmentModifications);
data.insert(QLatin1String(environModsKeyC),
Utils::EnvironmentItem::toVariantList(m_environmentModifications));
@@ -989,34 +1019,40 @@ bool MsvcToolChain::fromMap(const QVariantMap &data)
return false;
m_vcvarsBat = QDir::fromNativeSeparators(data.value(QLatin1String(varsBatKeyC)).toString());
m_varsBatArg = data.value(QLatin1String(varsBatArgKeyC)).toString();
- addToAvailableMsvcToolchains(this);
const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString();
m_abi = Abi::fromString(abiString);
+ const QStringList abiList = data.value(supportedAbisKeyC).toStringList();
+ m_supportedAbis.clear();
+ for (const QString &a : abiList) {
+ Abi abi = Abi::fromString(a);
+ if (!abi.isValid())
+ continue;
+ m_supportedAbis.append(abi);
+ }
m_environmentModifications = Utils::EnvironmentItem::itemsFromVariantList(
data.value(QLatin1String(environModsKeyC)).toList());
+ rescanForCompiler();
initEnvModWatcher(Utils::runAsync(envModThreadPool(),
&MsvcToolChain::environmentModifications,
m_vcvarsBat,
m_varsBatArg));
- return !m_vcvarsBat.isEmpty() && m_abi.isValid();
-}
+ // supported Abis were not stored in the map in previous versions of the settings. Re-detect
+ if (m_supportedAbis.isEmpty())
+ detectInstalledAbis();
-std::unique_ptr<ToolChainConfigWidget> MsvcToolChain::createConfigurationWidget()
-{
- return std::make_unique<MsvcToolChainConfigWidget>(this);
-}
+ const bool valid = !m_vcvarsBat.isEmpty() && m_abi.isValid() && !m_supportedAbis.isEmpty();
+ if (valid)
+ addToAvailableMsvcToolchains(this);
-bool MsvcToolChain::canClone() const
-{
- return true;
+ return valid;
}
-ToolChain *MsvcToolChain::clone() const
+std::unique_ptr<ToolChainConfigWidget> MsvcToolChain::createConfigurationWidget()
{
- return new MsvcToolChain(*this);
+ return std::make_unique<MsvcToolChainConfigWidget>(this);
}
bool static hasFlagEffectOnMacros(const QString &flag)
@@ -1037,7 +1073,7 @@ ToolChain::MacroInspectionRunner MsvcToolChain::createMacroInspectionRunner() co
{
Utils::Environment env(m_lastEnvironment);
addToEnvironment(env);
- std::shared_ptr<Cache<MacroInspectionReport, 64>> macroCache = m_predefinedMacrosCache;
+ MacrosCache macroCache = predefinedMacrosCache();
const Core::Id lang = language();
// This runner must be thread-safe!
@@ -1131,7 +1167,7 @@ ToolChain::BuiltInHeaderPathsRunner MsvcToolChain::createBuiltInHeaderPathsRunne
Utils::Environment env(m_lastEnvironment);
addToEnvironment(env);
- return [this, env](const QStringList &, const QString &) {
+ return [this, env](const QStringList &, const QString &, const QString &) {
QMutexLocker locker(m_headerPathsMutex);
if (m_headerPaths.isEmpty()) {
foreach (const QString &path,
@@ -1144,9 +1180,9 @@ ToolChain::BuiltInHeaderPathsRunner MsvcToolChain::createBuiltInHeaderPathsRunne
}
HeaderPaths MsvcToolChain::builtInHeaderPaths(const QStringList &cxxflags,
- const Utils::FileName &sysRoot) const
+ const Utils::FilePath &sysRoot) const
{
- return createBuiltInHeaderPathsRunner()(cxxflags, sysRoot.toString());
+ return createBuiltInHeaderPathsRunner()(cxxflags, sysRoot.toString(), "");
}
void MsvcToolChain::addToEnvironment(Utils::Environment &env) const
@@ -1174,44 +1210,49 @@ static QString wrappedMakeCommand(const QString &command)
return wrapperPath;
}
-QString MsvcToolChain::makeCommand(const Utils::Environment &environment) const
+FilePath MsvcToolChain::makeCommand(const Environment &environment) const
{
bool useJom = ProjectExplorerPlugin::projectExplorerSettings().useJom;
const QString jom("jom.exe");
const QString nmake("nmake.exe");
- Utils::FileName tmp;
+ Utils::FilePath tmp;
- QString command;
+ FilePath command;
if (useJom) {
tmp = environment.searchInPath(jom,
- {Utils::FileName::fromString(
+ {Utils::FilePath::fromString(
QCoreApplication::applicationDirPath())});
if (!tmp.isEmpty())
- command = tmp.toString();
+ command = tmp;
}
if (command.isEmpty()) {
tmp = environment.searchInPath(nmake);
if (!tmp.isEmpty())
- command = tmp.toString();
+ command = tmp;
}
if (command.isEmpty())
- command = useJom ? jom : nmake;
+ command = FilePath::fromString(useJom ? jom : nmake);
if (environment.hasKey("VSLANG"))
- return wrappedMakeCommand(command);
+ return FilePath::fromString(wrappedMakeCommand(command.toString()));
return command;
}
-Utils::FileName MsvcToolChain::compilerCommand() const
+Utils::FilePath MsvcToolChain::compilerCommand() const
+{
+ return m_compilerCommand;
+}
+
+void MsvcToolChain::rescanForCompiler()
{
Utils::Environment env = Utils::Environment::systemEnvironment();
addToEnvironment(env);
- Utils::FileName clexe
- = env.searchInPath(QLatin1String("cl.exe"), {}, [](const Utils::FileName &name) {
+ m_compilerCommand
+ = env.searchInPath(QLatin1String("cl.exe"), {}, [](const Utils::FilePath &name) {
QDir dir(QDir::cleanPath(name.toFileInfo().absolutePath() + QStringLiteral("/..")));
do {
if (QFile::exists(dir.absoluteFilePath(QStringLiteral("vcvarsall.bat")))
@@ -1220,7 +1261,6 @@ Utils::FileName MsvcToolChain::compilerCommand() const
} while (dir.cdUp() && !dir.isRoot());
return false;
});
- return clexe;
}
IOutputParser *MsvcToolChain::outputParser() const
@@ -1228,6 +1268,20 @@ IOutputParser *MsvcToolChain::outputParser() const
return new MsvcParser;
}
+void MsvcToolChain::changeVcVarsCall(const QString &varsBat, const QString &varsBatArg)
+{
+ m_vcvarsBat = varsBat;
+ m_varsBatArg = varsBatArg;
+
+ if (!varsBat.isEmpty()) {
+ detectInstalledAbis();
+ initEnvModWatcher(Utils::runAsync(envModThreadPool(),
+ &ClangClToolChain::environmentModifications,
+ m_vcvarsBat,
+ m_varsBatArg));
+ }
+}
+
// --------------------------------------------------------------------------
// MsvcBasedToolChainConfigWidget: Creates a simple GUI without error label
// to display name and varsBat. Derived classes should add the error label and
@@ -1269,9 +1323,148 @@ void MsvcBasedToolChainConfigWidget::setFromMsvcToolChain()
MsvcToolChainConfigWidget::MsvcToolChainConfigWidget(ToolChain *tc)
: MsvcBasedToolChainConfigWidget(tc)
+ , m_varsBatPathCombo(new QComboBox(this))
+ , m_varsBatArchCombo(new QComboBox(this))
+ , m_varsBatArgumentsEdit(new QLineEdit(this))
+ , m_abiWidget(new AbiWidget)
{
+ m_mainLayout->removeRow(m_mainLayout->rowCount() - 1);
+
+ QHBoxLayout *hLayout = new QHBoxLayout();
+ m_varsBatPathCombo->setObjectName("varsBatCombo");
+ m_varsBatPathCombo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ m_varsBatPathCombo->setEditable(true);
+ for (const MsvcToolChain *tmpTc : g_availableMsvcToolchains) {
+ const QString nativeVcVars = QDir::toNativeSeparators(tmpTc->varsBat());
+ if (!tmpTc->varsBat().isEmpty()
+ && m_varsBatPathCombo->findText(nativeVcVars) == -1) {
+ m_varsBatPathCombo->addItem(nativeVcVars);
+ }
+ }
+ const bool isAmd64
+ = Utils::HostOsInfo::hostArchitecture() == Utils::HostOsInfo::HostArchitectureAMD64;
+ // TODO: Add missing values to MsvcToolChain::Platform
+ m_varsBatArchCombo->addItem(tr("<empty>"), isAmd64 ? MsvcToolChain::amd64 : MsvcToolChain::x86);
+ m_varsBatArchCombo->addItem("x86", MsvcToolChain::x86);
+ m_varsBatArchCombo->addItem("amd64", MsvcToolChain::amd64);
+ m_varsBatArchCombo->addItem("arm", MsvcToolChain::arm);
+ m_varsBatArchCombo->addItem("x86_amd64", MsvcToolChain::x86_amd64);
+ m_varsBatArchCombo->addItem("x86_arm", MsvcToolChain::x86_arm);
+// m_varsBatArchCombo->addItem("x86_arm64", MsvcToolChain::x86_arm64);
+ m_varsBatArchCombo->addItem("amd64_x86", MsvcToolChain::amd64_x86);
+ m_varsBatArchCombo->addItem("amd64_arm", MsvcToolChain::amd64_arm);
+// m_varsBatArchCombo->addItem("amd64_arm64", MsvcToolChain::amd64_arm64);
+ m_varsBatArchCombo->addItem("ia64", MsvcToolChain::ia64);
+ m_varsBatArchCombo->addItem("x86_ia64", MsvcToolChain::x86_ia64);
+ m_varsBatArgumentsEdit->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ m_varsBatArgumentsEdit->setToolTip(tr("Additional arguments for the vcvarsall.bat call"));
+ hLayout->addWidget(m_varsBatPathCombo);
+ hLayout->addWidget(m_varsBatArchCombo);
+ hLayout->addWidget(m_varsBatArgumentsEdit);
+ m_mainLayout->addRow(tr("Initialization:"), hLayout);
+ m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
addErrorLabel();
setFromMsvcToolChain();
+
+ connect(m_varsBatPathCombo, &QComboBox::currentTextChanged,
+ this, &MsvcToolChainConfigWidget::handleVcVarsChange);
+ connect(m_varsBatArchCombo, &QComboBox::currentTextChanged,
+ this, &MsvcToolChainConfigWidget::handleVcVarsArchChange);
+ connect(m_varsBatArgumentsEdit, &QLineEdit::textChanged,
+ this, &ToolChainConfigWidget::dirty);
+ connect(m_abiWidget, &AbiWidget::abiChanged, this, &ToolChainConfigWidget::dirty);
+}
+
+void MsvcToolChainConfigWidget::applyImpl()
+{
+ auto *tc = static_cast<MsvcToolChain *>(toolChain());
+ QTC_ASSERT(tc, return );
+ tc->setTargetAbi(m_abiWidget->currentAbi());
+ const QString vcVars = QDir::fromNativeSeparators(m_varsBatPathCombo->currentText());
+ tc->changeVcVarsCall(vcVars, vcVarsArguments());
+ setFromMsvcToolChain();
+}
+
+void MsvcToolChainConfigWidget::discardImpl()
+{
+ setFromMsvcToolChain();
+}
+
+bool MsvcToolChainConfigWidget::isDirtyImpl() const
+{
+ auto msvcToolChain = static_cast<MsvcToolChain *>(toolChain());
+
+ return msvcToolChain->varsBat() != QDir::fromNativeSeparators(m_varsBatPathCombo->currentText())
+ || msvcToolChain->varsBatArg() != vcVarsArguments()
+ || msvcToolChain->targetAbi() != m_abiWidget->currentAbi();
+}
+
+void MsvcToolChainConfigWidget::makeReadOnlyImpl()
+{
+ m_varsBatPathCombo->setEnabled(false);
+ m_varsBatArchCombo->setEnabled(false);
+ m_varsBatArgumentsEdit->setEnabled(false);
+ m_abiWidget->setEnabled(false);
+}
+
+void MsvcToolChainConfigWidget::setFromMsvcToolChain()
+{
+ const auto *tc = static_cast<const MsvcToolChain *>(toolChain());
+ QTC_ASSERT(tc, return );
+ m_nameDisplayLabel->setText(tc->displayName());
+ QString args = tc->varsBatArg();
+ QStringList argList = args.split(' ');
+ for (int i = 0; i < argList.count(); ++i) {
+ if (m_varsBatArchCombo->findText(argList.at(i).trimmed()) != -1) {
+ const QString arch = argList.takeAt(i);
+ m_varsBatArchCombo->setCurrentText(arch);
+ args = argList.join(QLatin1Char(' '));
+ break;
+ }
+ }
+ m_varsBatPathCombo->setCurrentText(QDir::toNativeSeparators(tc->varsBat()));
+ m_varsBatArgumentsEdit->setText(args);
+ m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
+}
+
+void MsvcToolChainConfigWidget::handleVcVarsChange(const QString &vcVars)
+{
+ const QString normalizedVcVars = QDir::fromNativeSeparators(vcVars);
+ const auto *currentTc = static_cast<const MsvcToolChain *>(toolChain());
+ QTC_ASSERT(currentTc, return );
+ const MsvcToolChain::Platform platform = m_varsBatArchCombo->currentData().value<MsvcToolChain::Platform>();
+ const Abi::Architecture arch = archForPlatform(platform);
+ const unsigned char wordWidth = wordWidthForPlatform(platform);
+
+ for (const MsvcToolChain *tc : g_availableMsvcToolchains) {
+ if (tc->varsBat() == normalizedVcVars && tc->targetAbi().wordWidth() == wordWidth
+ && tc->targetAbi().architecture() == arch) {
+ m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
+ break;
+ }
+ }
+ emit dirty();
+}
+
+void MsvcToolChainConfigWidget::handleVcVarsArchChange(const QString &)
+{
+ Abi currentAbi = m_abiWidget->currentAbi();
+ const MsvcToolChain::Platform platform = m_varsBatArchCombo->currentData().value<MsvcToolChain::Platform>();
+ Abi newAbi(archForPlatform(platform), currentAbi.os(), currentAbi.osFlavor(),
+ currentAbi.binaryFormat(), wordWidthForPlatform(platform));
+ if (currentAbi != newAbi)
+ m_abiWidget->setAbis(m_abiWidget->supportedAbis(), newAbi);
+ emit dirty();
+}
+
+QString MsvcToolChainConfigWidget::vcVarsArguments() const
+{
+ QString varsBatArg
+ = m_varsBatArchCombo->currentText() == tr("<empty>")
+ ? "" : m_varsBatArchCombo->currentText();
+ if (!m_varsBatArgumentsEdit->text().isEmpty())
+ varsBatArg += QLatin1Char(' ') + m_varsBatArgumentsEdit->text();
+ return varsBatArg;
}
// --------------------------------------------------------------------------
@@ -1284,6 +1477,7 @@ ClangClToolChainConfigWidget::ClangClToolChainConfigWidget(ToolChain *tc) :
{
m_mainLayout->removeRow(m_mainLayout->rowCount() - 1);
+ m_varsBatDisplayCombo->setObjectName("varsBatCombo");
m_varsBatDisplayCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_mainLayout->addRow(tr("Initialization:"), m_varsBatDisplayCombo);
@@ -1326,7 +1520,7 @@ void ClangClToolChainConfigWidget::setFromClangClToolChain()
if (clangClToolChain->isAutoDetected())
m_llvmDirLabel->setText(QDir::toNativeSeparators(clangClToolChain->clangPath()));
else
- m_compilerCommand->setFileName(Utils::FileName::fromString(clangClToolChain->clangPath()));
+ m_compilerCommand->setFileName(Utils::FilePath::fromString(clangClToolChain->clangPath()));
}
static const MsvcToolChain *findMsvcToolChain(unsigned char wordWidth, Abi::OSFlavor flavor)
@@ -1418,7 +1612,9 @@ static QList<ToolChain *> detectClangClToolChainInPath(const QString &clangClPat
clangClPath);
}));
if (!tc) {
- tc = new ClangClToolChain(name, clangClPath, language, ToolChain::AutoDetection);
+ tc = new ClangClToolChain(name, clangClPath);
+ tc->setDetection(ToolChain::AutoDetection);
+ tc->setLanguage(language);
tc->resetMsvcToolChain(toolChain);
}
res << tc;
@@ -1433,7 +1629,7 @@ static QString compilerFromPath(const QString &path)
void ClangClToolChainConfigWidget::applyImpl()
{
- Utils::FileName clangClPath = m_compilerCommand->fileName();
+ Utils::FilePath clangClPath = m_compilerCommand->fileName();
auto clangClToolChain = static_cast<ClangClToolChain *>(toolChain());
clangClToolChain->setClangPath(clangClPath.toString());
@@ -1479,10 +1675,8 @@ void ClangClToolChainConfigWidget::makeReadOnlyImpl()
// --------------------------------------------------------------------------
ClangClToolChain::ClangClToolChain(const QString &name,
- const QString &clangPath,
- Core::Id language,
- Detection d)
- : MsvcToolChain(Constants::CLANG_CL_TOOLCHAIN_TYPEID, name, Abi(), "", "", language, d)
+ const QString &clangPath)
+ : MsvcToolChain(Constants::CLANG_CL_TOOLCHAIN_TYPEID, name, Abi(), "", "")
, m_clangPath(clangPath)
{}
@@ -1503,9 +1697,9 @@ void ClangClToolChain::addToEnvironment(Utils::Environment &env) const
env.prependOrSetPath(path.canonicalPath());
}
-Utils::FileName ClangClToolChain::compilerCommand() const
+Utils::FilePath ClangClToolChain::compilerCommand() const
{
- return Utils::FileName::fromString(m_clangPath);
+ return Utils::FilePath::fromString(m_clangPath);
}
QString ClangClToolChain::typeDisplayName() const
@@ -1513,11 +1707,10 @@ QString ClangClToolChain::typeDisplayName() const
return QCoreApplication::translate("ProjectExplorer::ClangToolChainFactory", "Clang");
}
-QList<Utils::FileName> ClangClToolChain::suggestedMkspecList() const
+QStringList ClangClToolChain::suggestedMkspecList() const
{
- const QString mkspec = QLatin1String("win32-clang-") + Abi::toString(targetAbi().osFlavor());
- return QList<Utils::FileName>{Utils::FileName::fromString(mkspec),
- Utils::FileName::fromString("win32-clang-msvc")};
+ const QString mkspec = "win32-clang-" + Abi::toString(targetAbi().osFlavor());
+ return {mkspec, "win32-clang-msvc"};
}
IOutputParser *ClangClToolChain::outputParser() const
@@ -1525,11 +1718,6 @@ IOutputParser *ClangClToolChain::outputParser() const
return new ClangClParser;
}
-ToolChain *ClangClToolChain::clone() const
-{
- return new ClangClToolChain(*this);
-}
-
static inline QString llvmDirKey()
{
return QStringLiteral("ProjectExplorer.ClangClToolChain.LlvmDir");
@@ -1563,18 +1751,12 @@ void ClangClToolChain::resetMsvcToolChain(const MsvcToolChain *base)
{
if (!base) {
m_abi = Abi();
- m_vcvarsBat.clear();
- setVarsBatArg("");
+ changeVcVarsCall("");
return;
}
- m_abi = base->targetAbi();
- m_vcvarsBat = base->varsBat();
- setVarsBatArg(base->varsBatArg());
- initEnvModWatcher(Utils::runAsync(envModThreadPool(),
- &ClangClToolChain::environmentModifications,
- m_vcvarsBat,
- base->varsBatArg()));
+ m_abi = base->targetAbi();
+ changeVcVarsCall(base->varsBat(), base->varsBatArg());
}
bool ClangClToolChain::operator==(const ToolChain &other) const
@@ -1618,12 +1800,6 @@ Utils::LanguageVersion ClangClToolChain::msvcLanguageVersion(const QStringList &
return MsvcToolChain::msvcLanguageVersion(cxxflags, language, macros);
}
-void ClangClToolChain::toolChainUpdated()
-{
- MsvcToolChain::toolChainUpdated();
- ToolChain::toolChainUpdated();
-}
-
ClangClToolChain::BuiltInHeaderPathsRunner ClangClToolChain::createBuiltInHeaderPathsRunner() const
{
{
@@ -1641,11 +1817,9 @@ ClangClToolChain::BuiltInHeaderPathsRunner ClangClToolChain::createBuiltInHeader
MsvcToolChainFactory::MsvcToolChainFactory()
{
setDisplayName(tr("MSVC"));
-}
-
-QSet<Core::Id> MsvcToolChainFactory::supportedLanguages() const
-{
- return {Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID};
+ setSupportedToolChainType(Constants::MSVC_TOOLCHAIN_TYPEID);
+ setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID});
+ setToolchainConstructor([] { return new MsvcToolChain; });
}
QString MsvcToolChainFactory::vcVarsBatFor(const QString &basePath,
@@ -1668,8 +1842,7 @@ static QList<ToolChain *> findOrCreateToolChain(const QList<ToolChain *> &alread
const QString &name,
const Abi &abi,
const QString &varsBat,
- const QString &varsBatArg,
- ToolChain::Detection d = ToolChain::ManualDetection)
+ const QString &varsBatArg)
{
QList<ToolChain *> res;
for (auto language : {Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}) {
@@ -1683,8 +1856,10 @@ static QList<ToolChain *> findOrCreateToolChain(const QList<ToolChain *> &alread
auto mtc = static_cast<MsvcToolChain *>(tc);
return mtc->varsBat() == varsBat && mtc->varsBatArg() == varsBatArg;
});
- if (!tc)
- tc = new MsvcToolChain(name, abi, varsBat, varsBatArg, language, d);
+ if (!tc) {
+ tc = new MsvcToolChain(name, abi, varsBat, varsBatArg);
+ tc->setLanguage(language);
+ }
res << tc;
}
return res;
@@ -1719,12 +1894,13 @@ static void detectCppBuildTools2015(QList<ToolChain *> *list)
e.format,
e.wordSize);
for (auto language : {Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}) {
- list->append(new MsvcToolChain(name + QLatin1String(e.postFix),
- abi,
- vcVarsBat,
- QLatin1String(e.varsBatArg),
- language,
- ToolChain::AutoDetection));
+ auto tc = new MsvcToolChain(name + QLatin1String(e.postFix),
+ abi,
+ vcVarsBat,
+ QLatin1String(e.varsBatArg));
+ tc->setDetection(ToolChain::AutoDetection);
+ tc->setLanguage(language);
+ list->append(tc);
}
}
}
@@ -1770,8 +1946,7 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
platform.first,
sdkKey),
fi.absoluteFilePath(),
- "/" + platform.second,
- ToolChain::AutoDetection));
+ "/" + platform.second));
}
// Make sure the default is front.
if (folder == defaultSdkPath)
@@ -1806,23 +1981,28 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
generateDisplayName(i.vsName, MsvcToolChain::VS, platform),
findAbiOfMsvc(MsvcToolChain::VS, platform, i.vsName),
i.vcVarsAll,
- platformName(platform),
- ToolChain::AutoDetection));
+ platformName(platform)));
}
}
}
detectCppBuildTools2015(&results);
+ for (ToolChain *tc : results)
+ tc->setDetection(ToolChain::AutoDetection);
+
return results;
}
ClangClToolChainFactory::ClangClToolChainFactory()
{
setDisplayName(tr("clang-cl"));
+ setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID});
+ setSupportedToolChainType(Constants::CLANG_CL_TOOLCHAIN_TYPEID);
+ setToolchainConstructor([] { return new ClangClToolChain; });
}
-bool ClangClToolChainFactory::canCreate()
+bool ClangClToolChainFactory::canCreate() const
{
return !g_availableMsvcToolchains.isEmpty();
}
@@ -1842,9 +2022,9 @@ QList<ToolChain *> ClangClToolChainFactory::autoDetect(const QList<ToolChain *>
QString qtCreatorsClang = Core::ICore::clangExecutable(CLANG_BINDIR);
if (!qtCreatorsClang.isEmpty()) {
- qtCreatorsClang = Utils::FileName::fromString(qtCreatorsClang)
+ qtCreatorsClang = Utils::FilePath::fromString(qtCreatorsClang)
.parentDir()
- .appendPath("clang-cl.exe")
+ .pathAppended("clang-cl.exe")
.toString();
results.append(detectClangClToolChainInPath(qtCreatorsClang, alreadyKnown, "", true));
known.append(results);
@@ -1861,16 +2041,16 @@ QList<ToolChain *> ClangClToolChainFactory::autoDetect(const QList<ToolChain *>
}
const Utils::Environment systemEnvironment = Utils::Environment::systemEnvironment();
- const Utils::FileName clangClPath = systemEnvironment.searchInPath("clang-cl");
+ const Utils::FilePath clangClPath = systemEnvironment.searchInPath("clang-cl");
if (!clangClPath.isEmpty())
results.append(detectClangClToolChainInPath(clangClPath.toString(), known, ""));
return results;
}
-ToolChain *ClangClToolChainFactory::create(Core::Id l)
+ToolChain *ClangClToolChainFactory::create()
{
- return new ClangClToolChain("clang-cl", "", l, ToolChain::ManualDetection);
+ return new ClangClToolChain("clang-cl", "");
}
bool MsvcToolChain::operator==(const ToolChain &other) const
@@ -1926,7 +2106,7 @@ Utils::optional<QString> MsvcToolChain::generateEnvironmentSettings(const Utils:
runEnv.unset(QLatin1String("ORIGINALPATH"));
run.setEnvironment(runEnv.toStringList());
run.setTimeoutS(30);
- Utils::FileName cmdPath = Utils::FileName::fromUserInput(
+ Utils::FilePath cmdPath = Utils::FilePath::fromUserInput(
QString::fromLocal8Bit(qgetenv("COMSPEC")));
if (cmdPath.isEmpty())
cmdPath = env.searchInPath(QLatin1String("cmd.exe"));
@@ -1984,36 +2164,15 @@ Utils::optional<QString> MsvcToolChain::generateEnvironmentSettings(const Utils:
return Utils::nullopt;
}
-bool MsvcToolChainFactory::canRestore(const QVariantMap &data)
-{
- const Core::Id id = typeIdFromMap(data);
- return id == Constants::MSVC_TOOLCHAIN_TYPEID;
-}
-
-template<class ToolChainType>
-ToolChainType *readFromMap(const QVariantMap &data)
+bool MsvcToolChainFactory::canCreate() const
{
- auto result = new ToolChainType;
- if (result->fromMap(data))
- return result;
- delete result;
- return nullptr;
-}
-
-ToolChain *MsvcToolChainFactory::restore(const QVariantMap &data)
-{
- return readFromMap<MsvcToolChain>(data);
-}
-
-bool ClangClToolChainFactory::canRestore(const QVariantMap &data)
-{
- const Core::Id id = typeIdFromMap(data);
- return id == Constants::CLANG_CL_TOOLCHAIN_TYPEID;
+ return !g_availableMsvcToolchains.isEmpty();
}
-ToolChain *ClangClToolChainFactory::restore(const QVariantMap &data)
+ToolChain *MsvcToolChainFactory::create()
{
- return readFromMap<ClangClToolChain>(data);
+ return new MsvcToolChain("Microsoft Visual C++ Compiler",
+ Abi::hostAbi(), g_availableMsvcToolchains.first()->varsBat(), "");
}
MsvcToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, WarningFlags &flags)
@@ -2056,3 +2215,5 @@ bool MsvcToolChain::WarningFlagAdder::triggered() const
} // namespace Internal
} // namespace ProjectExplorer
+
+Q_DECLARE_METATYPE(ProjectExplorer::Internal::MsvcToolChain::Platform)
diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h
index 10caaadfee..bc0adb00ba 100644
--- a/src/plugins/projectexplorer/msvctoolchain.h
+++ b/src/plugins/projectexplorer/msvctoolchain.h
@@ -26,8 +26,8 @@
#pragma once
#include "abi.h"
+#include "abiwidget.h"
#include "toolchain.h"
-#include "toolchaincache.h"
#include "toolchainconfigwidget.h"
#include <QFutureWatcher>
@@ -59,20 +59,19 @@ public:
explicit MsvcToolChain(const QString &name,
const Abi &abi,
const QString &varsBat,
- const QString &varsBatArg,
- Core::Id l,
- Detection d = ManualDetection);
- MsvcToolChain(const MsvcToolChain &other);
+ const QString &varsBatArg);
MsvcToolChain();
~MsvcToolChain() override;
Abi targetAbi() const override;
+ Abis supportedAbis() const override;
+ void setTargetAbi(const Abi &abi);
bool isValid() const override;
QString originalTargetTriple() const override;
- Utils::FileNameList suggestedMkspecList() const override;
+ QStringList suggestedMkspecList() const override;
QString typeDisplayName() const override;
@@ -81,34 +80,33 @@ public:
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
- bool canClone() const override;
- ToolChain *clone() const override;
-
MacroInspectionRunner createMacroInspectionRunner() const override;
Macros predefinedMacros(const QStringList &cxxflags) const override;
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
WarningFlags warningFlags(const QStringList &cflags) const override;
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override;
HeaderPaths builtInHeaderPaths(const QStringList &cxxflags,
- const Utils::FileName &sysRoot) const override;
+ const Utils::FilePath &sysRoot) const override;
void addToEnvironment(Utils::Environment &env) const override;
- QString makeCommand(const Utils::Environment &environment) const override;
- Utils::FileName compilerCommand() const override;
+ Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
+ Utils::FilePath compilerCommand() const override;
IOutputParser *outputParser() const override;
QString varsBatArg() const { return m_varsBatArg; }
QString varsBat() const { return m_vcvarsBat; }
void setVarsBatArg(const QString &varsBA) { m_varsBatArg = varsBA; }
+ void changeVcVarsCall(const QString &varsBat, const QString &varsBatArgs = QString());
bool operator==(const ToolChain &) const override;
+ bool isJobCountSupported() const override { return false; }
+
static void cancelMsvcToolChainDetection();
static Utils::optional<QString> generateEnvironmentSettings(const Utils::Environment &env,
const QString &batchFile,
const QString &batchArgs,
QMap<QString, QString> &envPairs);
-
protected:
class WarningFlagAdder
{
@@ -128,13 +126,10 @@ protected:
const QString &name,
const Abi &abi,
const QString &varsBat,
- const QString &varsBatArg,
- Core::Id l,
- Detection d);
+ const QString &varsBatArg);
explicit MsvcToolChain(Core::Id typeId);
static void inferWarningsForLevel(int warningLevel, WarningFlags &flags);
- void toolChainUpdated() override;
Utils::Environment readEnvironmentSetting(const Utils::Environment &env) const;
// Function must be thread-safe!
@@ -160,37 +155,37 @@ protected:
private:
void updateEnvironmentModifications(QList<Utils::EnvironmentItem> modifications);
+ void rescanForCompiler();
+ void detectInstalledAbis();
mutable QList<Utils::EnvironmentItem> m_environmentModifications;
mutable QFutureWatcher<GenerateEnvResult> m_envModWatcher;
- Utils::FileName m_debuggerCommand;
-
- mutable std::shared_ptr<Cache<MacroInspectionReport, 64>> m_predefinedMacrosCache;
-
mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment.
mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC
+ Utils::FilePath m_compilerCommand;
+
protected:
Abi m_abi;
+ Abis m_supportedAbis;
QString m_vcvarsBat;
QString m_varsBatArg; // Argument
};
-class ClangClToolChain : public MsvcToolChain
+class PROJECTEXPLORER_EXPORT ClangClToolChain : public MsvcToolChain
{
public:
- ClangClToolChain(const QString &name, const QString &llvmDir, Core::Id language, Detection d);
+ ClangClToolChain(const QString &name, const QString &llvmDir);
ClangClToolChain();
bool isValid() const override;
QString typeDisplayName() const override;
- QList<Utils::FileName> suggestedMkspecList() const override;
+ QStringList suggestedMkspecList() const override;
void addToEnvironment(Utils::Environment &env) const override;
- Utils::FileName compilerCommand() const override;
+ Utils::FilePath compilerCommand() const override;
IOutputParser *outputParser() const override;
- ToolChain *clone() const override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &data) override;
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
@@ -210,9 +205,6 @@ public:
bool operator==(const ToolChain &) const override;
private:
- void toolChainUpdated() override;
-
-private:
QString m_clangPath;
};
@@ -226,19 +218,18 @@ class MsvcToolChainFactory : public ToolChainFactory
public:
MsvcToolChainFactory();
- QSet<Core::Id> supportedLanguages() const override;
QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown) override;
- bool canRestore(const QVariantMap &data) override;
- ToolChain *restore(const QVariantMap &data) override;
+ bool canCreate() const override;
+ ToolChain *create() override;
static QString vcVarsBatFor(const QString &basePath,
MsvcToolChain::Platform platform,
const QVersionNumber &v);
};
-class ClangClToolChainFactory : public MsvcToolChainFactory
+class ClangClToolChainFactory : public ToolChainFactory
{
Q_OBJECT
@@ -247,11 +238,8 @@ public:
QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown) override;
- bool canRestore(const QVariantMap &data) override;
- ToolChain *restore(const QVariantMap &data) override;
-
- bool canCreate() override;
- ToolChain *create(Core::Id l) override;
+ bool canCreate() const override;
+ ToolChain *create() override;
};
// --------------------------------------------------------------------------
@@ -288,6 +276,24 @@ class MsvcToolChainConfigWidget : public MsvcBasedToolChainConfigWidget
public:
explicit MsvcToolChainConfigWidget(ToolChain *);
+
+private:
+ void applyImpl() override;
+ void discardImpl() override;
+ bool isDirtyImpl() const override;
+ void makeReadOnlyImpl() override;
+
+ void setFromMsvcToolChain();
+
+ void handleVcVarsChange(const QString &vcVars);
+ void handleVcVarsArchChange(const QString &arch);
+
+ QString vcVarsArguments() const;
+
+ QComboBox *m_varsBatPathCombo;
+ QComboBox *m_varsBatArchCombo;
+ QLineEdit *m_varsBatArgumentsEdit;
+ AbiWidget *m_abiWidget;
};
// --------------------------------------------------------------------------
@@ -304,6 +310,7 @@ public:
protected:
void applyImpl() override;
void discardImpl() override;
+ bool isDirtyImpl() const override { return false; }
void makeReadOnlyImpl() override;
private:
diff --git a/src/plugins/projectexplorer/namedwidget.h b/src/plugins/projectexplorer/namedwidget.h
index 26c9550f7e..870941c73b 100644
--- a/src/plugins/projectexplorer/namedwidget.h
+++ b/src/plugins/projectexplorer/namedwidget.h
@@ -39,13 +39,11 @@ public:
explicit NamedWidget(QWidget *parent = nullptr);
QString displayName() const;
+ void setDisplayName(const QString &displayName);
signals:
void displayNameChanged(const QString &);
-protected:
- void setDisplayName(const QString &displayName);
-
private:
QString m_displayName;
};
diff --git a/src/plugins/projectexplorer/osparser.cpp b/src/plugins/projectexplorer/osparser.cpp
index 9190f45d73..ecbef759ef 100644
--- a/src/plugins/projectexplorer/osparser.cpp
+++ b/src/plugins/projectexplorer/osparser.cpp
@@ -41,7 +41,7 @@ void OsParser::stdError(const QString &line)
if (Utils::HostOsInfo::isLinuxHost()) {
const QString trimmed = line.trimmed();
if (trimmed.contains(QLatin1String(": error while loading shared libraries:"))) {
- emit addTask(Task(Task::Error, trimmed, Utils::FileName(), -1,
+ emit addTask(Task(Task::Error, trimmed, Utils::FilePath(), -1,
Constants::TASK_CATEGORY_COMPILE));
}
}
@@ -55,7 +55,7 @@ void OsParser::stdOutput(const QString &line)
if (trimmed == QLatin1String("The process cannot access the file because it is being used by another process.")) {
emit addTask(Task(Task::Error, tr("The process cannot access the file because it is being used by another process.\n"
"Please close all running instances of your application before starting a build."),
- Utils::FileName(), -1, Constants::TASK_CATEGORY_COMPILE));
+ Utils::FilePath(), -1, Constants::TASK_CATEGORY_COMPILE));
m_hasFatalError = true;
}
}
diff --git a/src/plugins/projectexplorer/outputparser_test.cpp b/src/plugins/projectexplorer/outputparser_test.cpp
index cb2a9772c3..765a087650 100644
--- a/src/plugins/projectexplorer/outputparser_test.cpp
+++ b/src/plugins/projectexplorer/outputparser_test.cpp
@@ -32,7 +32,7 @@
namespace ProjectExplorer {
-static inline QByteArray msgFileComparisonFail(const Utils::FileName &f1, const Utils::FileName &f2)
+static inline QByteArray msgFileComparisonFail(const Utils::FilePath &f1, const Utils::FilePath &f2)
{
const QString result = '"' + f1.toUserOutput() + "\" != \"" + f2.toUserOutput() + '"';
return result.toLocal8Bit();
@@ -43,7 +43,7 @@ OutputParserTester::OutputParserTester() = default;
// test functions:
void OutputParserTester::testParsing(const QString &lines,
Channel inputChannel,
- QList<Task> tasks,
+ Tasks tasks,
const QString &childStdOutLines,
const QString &childStdErrLines,
const QString &outputLines)
diff --git a/src/plugins/projectexplorer/outputparser_test.h b/src/plugins/projectexplorer/outputparser_test.h
index 7836331632..43920d0ebf 100644
--- a/src/plugins/projectexplorer/outputparser_test.h
+++ b/src/plugins/projectexplorer/outputparser_test.h
@@ -50,7 +50,7 @@ public:
// test functions:
void testParsing(const QString &lines, Channel inputChannel,
- QList<Task> tasks,
+ Tasks tasks,
const QString &childStdOutLines,
const QString &childStdErrLines,
const QString &outputLines);
@@ -76,7 +76,7 @@ private:
QString m_receivedStdErrChildLine;
QString m_receivedStdOutChildLine;
- QList<Task> m_receivedTasks;
+ Tasks m_receivedTasks;
QString m_receivedOutput;
friend class TestTerminator;
diff --git a/src/plugins/projectexplorer/parseissuesdialog.cpp b/src/plugins/projectexplorer/parseissuesdialog.cpp
new file mode 100644
index 0000000000..7b0d3758e6
--- /dev/null
+++ b/src/plugins/projectexplorer/parseissuesdialog.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** 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 "parseissuesdialog.h"
+
+#include "ioutputparser.h"
+#include "kitinformation.h"
+#include "kitchooser.h"
+#include "kitmanager.h"
+#include "projectexplorerconstants.h"
+#include "taskhub.h"
+
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <utils/runextensions.h>
+
+#include <QButtonGroup>
+#include <QCheckBox>
+#include <QDialogButtonBox>
+#include <QFile>
+#include <QFileDialog>
+#include <QGroupBox>
+#include <QLabel>
+#include <QMessageBox>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QVBoxLayout>
+
+#include <memory>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class ParseIssuesDialog::Private
+{
+public:
+ QPlainTextEdit compileOutputEdit;
+ QCheckBox stderrCheckBox;
+ QCheckBox clearTasksCheckBox;
+ KitChooser kitChooser;
+};
+
+ParseIssuesDialog::ParseIssuesDialog(QWidget *parent) : QDialog(parent), d(new Private)
+{
+ setWindowTitle(tr("Parse Build Output"));
+
+ d->stderrCheckBox.setText(tr("Output went to stderr"));
+ d->stderrCheckBox.setChecked(true);
+
+ d->clearTasksCheckBox.setText(tr("Clear existing tasks"));
+ d->clearTasksCheckBox.setChecked(true);
+
+ const auto loadFileButton = new QPushButton(tr("Load from File..."));
+ connect(loadFileButton, &QPushButton::clicked, this, [this] {
+ const QString filePath = QFileDialog::getOpenFileName(this, tr("Choose File"));
+ if (filePath.isEmpty())
+ return;
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ QMessageBox::critical(this, tr("Could Not Open File"),
+ tr("Could not open file: \"%1\": %2")
+ .arg(filePath, file.errorString()));
+ return;
+ }
+ d->compileOutputEdit.setPlainText(QString::fromLocal8Bit(file.readAll()));
+ });
+
+ d->kitChooser.populate();
+ if (!d->kitChooser.hasStartupKit()) {
+ for (const Kit * const k : KitManager::kits()) {
+ if (DeviceTypeKitAspect::deviceTypeId(k) == Constants::DESKTOP_DEVICE_TYPE) {
+ d->kitChooser.setCurrentKitId(k->id());
+ break;
+ }
+ }
+ }
+
+ const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ buttonBox->button(QDialogButtonBox::Ok)->setEnabled(d->kitChooser.currentKit());
+
+ const auto layout = new QVBoxLayout(this);
+ const auto outputGroupBox = new QGroupBox(tr("Build Output"));
+ layout->addWidget(outputGroupBox);
+ const auto outputLayout = new QHBoxLayout(outputGroupBox);
+ outputLayout->addWidget(&d->compileOutputEdit);
+ const auto buttonsWidget = new QWidget;
+ const auto outputButtonsLayout = new QVBoxLayout(buttonsWidget);
+ outputLayout->addWidget(buttonsWidget);
+ outputButtonsLayout->addWidget(loadFileButton);
+ outputButtonsLayout->addWidget(&d->stderrCheckBox);
+ outputButtonsLayout->addStretch(1);
+
+ // TODO: Only very few parsers are available from a Kit (basically just the Toolchain one).
+ // If we introduced factories for IOutputParsers, we could offer the user
+ // to combine arbitrary parsers here.
+ const auto parserGroupBox = new QGroupBox(tr("Parsing Options"));
+ layout->addWidget(parserGroupBox);
+ const auto parserLayout = new QVBoxLayout(parserGroupBox);
+ const auto kitChooserWidget = new QWidget;
+ const auto kitChooserLayout = new QHBoxLayout(kitChooserWidget);
+ kitChooserLayout->setContentsMargins(0, 0, 0, 0);
+ kitChooserLayout->addWidget(new QLabel(tr("Use parsers from kit:")));
+ kitChooserLayout->addWidget(&d->kitChooser);
+ parserLayout->addWidget(kitChooserWidget);
+ parserLayout->addWidget(&d->clearTasksCheckBox);
+
+ layout->addWidget(buttonBox);
+}
+
+ParseIssuesDialog::~ParseIssuesDialog()
+{
+ delete d;
+}
+
+static void parse(QFutureInterface<void> &future, const QString &output,
+ const std::unique_ptr<IOutputParser> &parser, bool isStderr)
+{
+ const QStringList lines = output.split('\n');
+ future.setProgressRange(0, lines.count());
+ const auto parserFunc = isStderr ? &IOutputParser::stdError : &IOutputParser::stdOutput;
+ for (const QString &line : lines) {
+ (parser.get()->*parserFunc)(line);
+ future.setProgressValue(future.progressValue() + 1);
+ if (future.isCanceled())
+ return;
+ }
+}
+
+void ParseIssuesDialog::accept()
+{
+ std::unique_ptr<IOutputParser> parser(d->kitChooser.currentKit()->createOutputParser());
+ if (!parser) {
+ QMessageBox::critical(this, tr("Cannot Parse"), tr("Cannot parse: The chosen kit does "
+ "not provide an output parser."));
+ return;
+ }
+ if (d->clearTasksCheckBox.isChecked())
+ TaskHub::clearTasks();
+ connect(parser.get(), &IOutputParser::addTask, [](const Task &t) { TaskHub::addTask(t); });
+ const QFuture<void> f = Utils::runAsync(&parse, d->compileOutputEdit.toPlainText(),
+ std::move(parser), d->stderrCheckBox.isChecked());
+ Core::ProgressManager::addTask(f, tr("Parsing build output"),
+ "ProgressExplorer.ParseExternalBuildOutput");
+ QDialog::accept();
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/parseissuesdialog.h b/src/plugins/projectexplorer/parseissuesdialog.h
new file mode 100644
index 0000000000..555727c3b9
--- /dev/null
+++ b/src/plugins/projectexplorer/parseissuesdialog.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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 <QDialog>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class ParseIssuesDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ ParseIssuesDialog(QWidget *parent = nullptr);
+ ~ParseIssuesDialog() override;
+
+private:
+ void accept() override;
+
+ class Private;
+ Private * const d;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/processparameters.cpp b/src/plugins/projectexplorer/processparameters.cpp
index db56c57cdb..f535cc120e 100644
--- a/src/plugins/projectexplorer/processparameters.cpp
+++ b/src/plugins/projectexplorer/processparameters.cpp
@@ -44,7 +44,9 @@
\sa ProjectExplorer::AbstractProcessStep
*/
-using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace ProjectExplorer {
ProcessParameters::ProcessParameters() :
m_macroExpander(nullptr),
@@ -52,11 +54,19 @@ ProcessParameters::ProcessParameters() :
{
}
+void ProcessParameters::setCommandLine(const CommandLine &cmdLine)
+{
+ m_command = cmdLine.executable();
+ m_arguments = cmdLine.arguments();
+ m_effectiveCommand.clear();
+ m_effectiveArguments.clear();
+}
+
/*!
Sets the executable to run.
*/
-void ProcessParameters::setCommand(const QString &cmd)
+void ProcessParameters::setCommand(const Utils::FilePath &cmd)
{
m_command = cmd;
m_effectiveCommand.clear();
@@ -78,7 +88,7 @@ void ProcessParameters::setArguments(const QString &arguments)
Should be called from init().
*/
-void ProcessParameters::setWorkingDirectory(const QString &workingDirectory)
+void ProcessParameters::setWorkingDirectory(const FilePath &workingDirectory)
{
m_workingDirectory = workingDirectory;
m_effectiveWorkingDirectory.clear();
@@ -103,13 +113,14 @@ void ProcessParameters::setWorkingDirectory(const QString &workingDirectory)
Gets the fully expanded working directory.
*/
-QString ProcessParameters::effectiveWorkingDirectory() const
+FilePath ProcessParameters::effectiveWorkingDirectory() const
{
if (m_effectiveWorkingDirectory.isEmpty()) {
- QString wds = m_workingDirectory;
+ QString wds = m_workingDirectory.toString();
if (m_macroExpander)
wds = m_macroExpander->expand(wds);
- m_effectiveWorkingDirectory = QDir::cleanPath(m_environment.expandVariables(wds));
+ m_effectiveWorkingDirectory
+ = FilePath::fromString(QDir::cleanPath(m_environment.expandVariables(wds)));
}
return m_effectiveWorkingDirectory;
}
@@ -118,14 +129,15 @@ QString ProcessParameters::effectiveWorkingDirectory() const
Gets the fully expanded command name to run.
*/
-QString ProcessParameters::effectiveCommand() const
+FilePath ProcessParameters::effectiveCommand() const
{
if (m_effectiveCommand.isEmpty()) {
- QString cmd = m_command;
+ FilePath cmd = m_command;
if (m_macroExpander)
cmd = m_macroExpander->expand(cmd);
m_effectiveCommand =
- m_environment.searchInPath(cmd, {Utils::FileName::fromString(effectiveWorkingDirectory())}).toString();
+ m_environment.searchInPath(cmd.toString(),
+ {effectiveWorkingDirectory()});
m_commandMissing = m_effectiveCommand.isEmpty();
if (m_commandMissing)
m_effectiveCommand = cmd;
@@ -155,16 +167,16 @@ QString ProcessParameters::effectiveArguments() const
QString ProcessParameters::prettyCommand() const
{
- QString cmd = m_command;
+ QString cmd = m_command.toString();
if (m_macroExpander)
cmd = m_macroExpander->expand(cmd);
- return Utils::FileName::fromString(cmd).fileName();
+ return Utils::FilePath::fromString(cmd).fileName();
}
QString ProcessParameters::prettyArguments() const
{
QString margs = effectiveArguments();
- QString workDir = effectiveWorkingDirectory();
+ QString workDir = effectiveWorkingDirectory().toString();
Utils::QtcProcess::SplitError err;
Utils::QtcProcess::Arguments args =
Utils::QtcProcess::prepareArgs(margs, &err, Utils::HostOsInfo::hostOs(), &m_environment, &workDir);
@@ -187,7 +199,7 @@ QString ProcessParameters::summaryInWorkdir(const QString &displayName) const
.arg(displayName,
Utils::QtcProcess::quoteArg(prettyCommand()),
prettyArguments(),
- QDir::toNativeSeparators(effectiveWorkingDirectory()));
+ QDir::toNativeSeparators(effectiveWorkingDirectory().toString()));
}
void ProcessParameters::resolveAll()
@@ -196,3 +208,5 @@ void ProcessParameters::resolveAll()
effectiveArguments();
effectiveWorkingDirectory();
}
+
+} // ProcessExplorer
diff --git a/src/plugins/projectexplorer/processparameters.h b/src/plugins/projectexplorer/processparameters.h
index fd43e03bf7..c87ede7d5b 100644
--- a/src/plugins/projectexplorer/processparameters.h
+++ b/src/plugins/projectexplorer/processparameters.h
@@ -28,8 +28,12 @@
#include "projectexplorer_export.h"
#include <utils/environment.h>
+#include <utils/fileutils.h>
-namespace Utils { class MacroExpander; }
+namespace Utils {
+class CommandLine;
+class MacroExpander;
+} // Utils
namespace ProjectExplorer {
@@ -39,14 +43,16 @@ class PROJECTEXPLORER_EXPORT ProcessParameters
public:
ProcessParameters();
- void setCommand(const QString &cmd);
- QString command() const { return m_command; }
+ void setCommandLine(const Utils::CommandLine &cmdLine);
+
+ void setCommand(const Utils::FilePath &cmd);
+ Utils::FilePath command() const { return m_command; }
void setArguments(const QString &arguments);
QString arguments() const { return m_arguments; }
- void setWorkingDirectory(const QString &workingDirectory);
- QString workingDirectory() const { return m_workingDirectory; }
+ void setWorkingDirectory(const Utils::FilePath &workingDirectory);
+ Utils::FilePath workingDirectory() const { return m_workingDirectory; }
void setEnvironment(const Utils::Environment &env) { m_environment = env; }
Utils::Environment environment() const { return m_environment; }
@@ -55,9 +61,9 @@ public:
Utils::MacroExpander *macroExpander() const { return m_macroExpander; }
/// Get the fully expanded working directory:
- QString effectiveWorkingDirectory() const;
+ Utils::FilePath effectiveWorkingDirectory() const;
/// Get the fully expanded command name to run:
- QString effectiveCommand() const;
+ Utils::FilePath effectiveCommand() const;
/// Get the fully expanded arguments to use:
QString effectiveArguments() const;
@@ -71,14 +77,14 @@ public:
void resolveAll();
private:
- QString m_workingDirectory;
- QString m_command;
+ Utils::FilePath m_workingDirectory;
+ Utils::FilePath m_command;
QString m_arguments;
Utils::Environment m_environment;
Utils::MacroExpander *m_macroExpander;
- mutable QString m_effectiveWorkingDirectory;
- mutable QString m_effectiveCommand;
+ mutable Utils::FilePath m_effectiveWorkingDirectory;
+ mutable Utils::FilePath m_effectiveCommand;
mutable QString m_effectiveArguments;
mutable bool m_commandMissing;
};
diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp
index c6c6057f4b..231cb831bb 100644
--- a/src/plugins/projectexplorer/processstep.cpp
+++ b/src/plugins/projectexplorer/processstep.cpp
@@ -24,114 +24,106 @@
****************************************************************************/
#include "processstep.h"
-#include "buildstep.h"
#include "buildconfiguration.h"
+#include "buildstep.h"
+#include "kit.h"
#include "processparameters.h"
#include "projectexplorerconstants.h"
#include "target.h"
-#include "kit.h"
#include <coreplugin/variablechooser.h>
#include <utils/macroexpander.h>
-#include <QDebug>
+#include <QFormLayout>
-using namespace ProjectExplorer;
-using namespace ProjectExplorer::Internal;
+namespace ProjectExplorer {
-namespace {
const char PROCESS_STEP_ID[] = "ProjectExplorer.ProcessStep";
const char PROCESS_COMMAND_KEY[] = "ProjectExplorer.ProcessStep.Command";
const char PROCESS_WORKINGDIRECTORY_KEY[] = "ProjectExplorer.ProcessStep.WorkingDirectory";
const char PROCESS_ARGUMENTS_KEY[] = "ProjectExplorer.ProcessStep.Arguments";
-}
ProcessStep::ProcessStep(BuildStepList *bsl)
: AbstractProcessStep(bsl, PROCESS_STEP_ID)
{
//: Default ProcessStep display name
setDefaultDisplayName(tr("Custom Process Step"));
- if (m_workingDirectory.isEmpty())
- m_workingDirectory = Constants::DEFAULT_WORKING_DIR;
+
+ m_command = addAspect<BaseStringAspect>();
+ m_command->setSettingsKey(PROCESS_COMMAND_KEY);
+ m_command->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
+ m_command->setLabelText(tr("Command:"));
+ m_command->setExpectedKind(Utils::PathChooser::Command);
+ m_command->setHistoryCompleter("PE.ProcessStepCommand.History");
+
+ m_arguments = addAspect<BaseStringAspect>();
+ m_arguments->setSettingsKey(PROCESS_ARGUMENTS_KEY);
+ m_arguments->setDisplayStyle(BaseStringAspect::LineEditDisplay);
+ m_arguments->setLabelText(tr("Arguments:"));
+
+ m_workingDirectory = addAspect<BaseStringAspect>();
+ m_workingDirectory->setSettingsKey(PROCESS_WORKINGDIRECTORY_KEY);
+ m_workingDirectory->setValue(Constants::DEFAULT_WORKING_DIR);
+ m_workingDirectory->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
+ m_workingDirectory->setLabelText(tr("Working directory:"));
+ m_workingDirectory->setExpectedKind(Utils::PathChooser::Directory);
}
bool ProcessStep::init()
{
- BuildConfiguration *bc = buildConfiguration();
- ProcessParameters *pp = processParameters();
- pp->setMacroExpander(bc ? bc->macroExpander() : Utils::globalMacroExpander());
- pp->setEnvironment(bc ? bc->environment() : Utils::Environment::systemEnvironment());
- pp->setWorkingDirectory(workingDirectory());
- pp->setCommand(m_command);
- pp->setArguments(m_arguments);
- pp->resolveAll();
-
+ setupProcessParameters(processParameters());
setOutputParser(target()->kit()->createOutputParser());
return AbstractProcessStep::init();
}
-void ProcessStep::doRun()
+void ProcessStep::setupProcessParameters(ProcessParameters *pp)
{
- AbstractProcessStep::doRun();
-}
+ BuildConfiguration *bc = buildConfiguration();
-BuildStepConfigWidget *ProcessStep::createConfigWidget()
-{
- return new ProcessStepConfigWidget(this);
-}
+ QString command = m_command->value();
+ QString arguments = m_arguments->value();
+ QString workingDirectory = m_workingDirectory->value();
+ if (workingDirectory.isEmpty()) {
+ if (bc)
+ workingDirectory = Constants::DEFAULT_WORKING_DIR;
+ else
+ workingDirectory = Constants::DEFAULT_WORKING_DIR_ALTERNATE;
+ }
-QString ProcessStep::command() const
-{
- return m_command;
+ pp->setMacroExpander(bc ? bc->macroExpander() : Utils::globalMacroExpander());
+ pp->setEnvironment(bc ? bc->environment() : Utils::Environment::systemEnvironment());
+ pp->setWorkingDirectory(Utils::FilePath::fromString(workingDirectory));
+ pp->setCommand(Utils::FilePath::fromString(command));
+ pp->setArguments(arguments);
+ pp->resolveAll();
}
-QString ProcessStep::arguments() const
+BuildStepConfigWidget *ProcessStep::createConfigWidget()
{
- return m_arguments;
-}
+ auto widget = AbstractProcessStep::createConfigWidget();
-QString ProcessStep::workingDirectory() const
-{
- return m_workingDirectory;
-}
+ Core::VariableChooser::addSupportForChildWidgets(widget, macroExpander());
-void ProcessStep::setCommand(const QString &command)
-{
- m_command = command;
-}
+ auto updateDetails = [this, widget] {
+ QString display = displayName();
+ if (display.isEmpty())
+ display = tr("Custom Process Step");
+ ProcessParameters param;
+ setupProcessParameters(&param);
+ widget->setSummaryText(param.summary(display));
+ };
-void ProcessStep::setArguments(const QString &arguments)
-{
- m_arguments = arguments;
-}
+ updateDetails();
-void ProcessStep::setWorkingDirectory(const QString &workingDirectory)
-{
- if (workingDirectory.isEmpty())
- if (buildConfiguration())
- m_workingDirectory = Constants::DEFAULT_WORKING_DIR;
- else
- m_workingDirectory = Constants::DEFAULT_WORKING_DIR_ALTERNATE;
- else
- m_workingDirectory = workingDirectory;
-}
+ connect(m_command, &ProjectConfigurationAspect::changed,
+ widget, updateDetails);
+ connect(m_workingDirectory, &ProjectConfigurationAspect::changed,
+ widget, updateDetails);
+ connect(m_arguments, &ProjectConfigurationAspect::changed,
+ widget, updateDetails);
-QVariantMap ProcessStep::toMap() const
-{
- QVariantMap map(AbstractProcessStep::toMap());
- map.insert(PROCESS_COMMAND_KEY, command());
- map.insert(PROCESS_ARGUMENTS_KEY, arguments());
- map.insert(PROCESS_WORKINGDIRECTORY_KEY, workingDirectory());
- return map;
-}
-
-bool ProcessStep::fromMap(const QVariantMap &map)
-{
- setCommand(map.value(PROCESS_COMMAND_KEY).toString());
- setArguments(map.value(PROCESS_ARGUMENTS_KEY).toString());
- setWorkingDirectory(map.value(PROCESS_WORKINGDIRECTORY_KEY).toString());
- return AbstractProcessStep::fromMap(map);
+ return widget;
}
//*******
@@ -144,80 +136,4 @@ ProcessStepFactory::ProcessStepFactory()
setDisplayName(ProcessStep::tr("Custom Process Step", "item in combobox"));
}
-//*******
-// ProcessStepConfigWidget
-//*******
-
-ProcessStepConfigWidget::ProcessStepConfigWidget(ProcessStep *step)
- : BuildStepConfigWidget(step), m_step(step)
-{
- m_ui.setupUi(this);
- m_ui.command->setExpectedKind(Utils::PathChooser::Command);
- m_ui.command->setHistoryCompleter("PE.ProcessStepCommand.History");
- m_ui.workingDirectory->setExpectedKind(Utils::PathChooser::Directory);
-
- BuildConfiguration *bc = m_step->buildConfiguration();
- Utils::Environment env = bc ? bc->environment() : Utils::Environment::systemEnvironment();
- m_ui.command->setEnvironment(env);
- m_ui.command->setPath(m_step->command());
-
- m_ui.workingDirectory->setEnvironment(env);
- m_ui.workingDirectory->setPath(m_step->workingDirectory());
-
- m_ui.commandArgumentsLineEdit->setText(m_step->arguments());
-
- updateDetails();
-
- connect(m_ui.command, &Utils::PathChooser::rawPathChanged,
- this, &ProcessStepConfigWidget::commandLineEditTextEdited);
- connect(m_ui.workingDirectory, &Utils::PathChooser::rawPathChanged,
- this, &ProcessStepConfigWidget::workingDirectoryLineEditTextEdited);
-
- connect(m_ui.commandArgumentsLineEdit, &QLineEdit::textEdited,
- this, &ProcessStepConfigWidget::commandArgumentsLineEditTextEdited);
- Core::VariableChooser::addSupportForChildWidgets(this, m_step->macroExpander());
-}
-
-void ProcessStepConfigWidget::updateDetails()
-{
- QString displayName = m_step->displayName();
- if (displayName.isEmpty())
- displayName = tr("Custom Process Step");
- ProcessParameters param;
- BuildConfiguration *bc = m_step->buildConfiguration();
- param.setMacroExpander(bc ? bc->macroExpander() : Utils::globalMacroExpander());
- param.setEnvironment(bc ? bc->environment() : Utils::Environment::systemEnvironment());
-
- param.setWorkingDirectory(m_step->workingDirectory());
- param.setCommand(m_step->command());
- param.setArguments(m_step->arguments());
- m_summaryText = param.summary(displayName);
- emit updateSummary();
-}
-
-QString ProcessStepConfigWidget::displayName() const
-{
- return m_step->displayName();
-}
-
-QString ProcessStepConfigWidget::summaryText() const
-{
- return m_summaryText;
-}
-
-void ProcessStepConfigWidget::commandLineEditTextEdited()
-{
- m_step->setCommand(m_ui.command->rawPath());
- updateDetails();
-}
-
-void ProcessStepConfigWidget::workingDirectoryLineEditTextEdited()
-{
- m_step->setWorkingDirectory(m_ui.workingDirectory->rawPath());
-}
-
-void ProcessStepConfigWidget::commandArgumentsLineEditTextEdited()
-{
- m_step->setArguments(m_ui.commandArgumentsLineEdit->text());
- updateDetails();
-}
+} // ProjectExplorer
diff --git a/src/plugins/projectexplorer/processstep.h b/src/plugins/projectexplorer/processstep.h
index 3bff8fbdca..241d440ad2 100644
--- a/src/plugins/projectexplorer/processstep.h
+++ b/src/plugins/projectexplorer/processstep.h
@@ -25,11 +25,11 @@
#pragma once
-#include "ui_processstep.h"
#include "abstractprocessstep.h"
+#include "projectconfigurationaspects.h"
+#include "projectexplorer_export.h"
namespace ProjectExplorer {
-namespace Internal {
class ProcessStepFactory : public BuildStepFactory
{
@@ -37,7 +37,7 @@ public:
ProcessStepFactory();
};
-class ProcessStep : public AbstractProcessStep
+class PROJECTEXPLORER_EXPORT ProcessStep : public AbstractProcessStep
{
Q_OBJECT
friend class ProcessStepFactory;
@@ -47,41 +47,13 @@ public:
BuildStepConfigWidget *createConfigWidget() override;
- QString command() const;
- QString arguments() const;
- QString workingDirectory() const;
-
- void setCommand(const QString &command);
- void setArguments(const QString &arguments);
- void setWorkingDirectory(const QString &workingDirectory);
-
private:
bool init() override;
- void doRun() override;
- QVariantMap toMap() const override;
- bool fromMap(const QVariantMap &map) override;
-
- QString m_command;
- QString m_arguments;
- QString m_workingDirectory;
-};
+ void setupProcessParameters(ProcessParameters *pp);
-class ProcessStepConfigWidget : public BuildStepConfigWidget
-{
- Q_OBJECT
-public:
- ProcessStepConfigWidget(ProcessStep *step);
- virtual QString displayName() const;
- virtual QString summaryText() const;
-private:
- void commandLineEditTextEdited();
- void workingDirectoryLineEditTextEdited();
- void commandArgumentsLineEditTextEdited();
- void updateDetails();
- ProcessStep *m_step;
- Ui::ProcessStepWidget m_ui;
- QString m_summaryText;
+ ProjectExplorer::BaseStringAspect *m_command;
+ ProjectExplorer::BaseStringAspect *m_arguments;
+ ProjectExplorer::BaseStringAspect *m_workingDirectory;
};
-} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/processstep.ui b/src/plugins/projectexplorer/processstep.ui
deleted file mode 100644
index bcbaf740dd..0000000000
--- a/src/plugins/projectexplorer/processstep.ui
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ProjectExplorer::Internal::ProcessStepWidget</class>
- <widget class="QWidget" name="ProjectExplorer::Internal::ProcessStepWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>262</width>
- <height>85</height>
- </rect>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="commandLabel">
- <property name="text">
- <string>Command:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="Utils::PathChooser" name="command" native="true"/>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="commandArgumentsLabel">
- <property name="text">
- <string>Arguments:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="commandArgumentsLineEdit"/>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="workingDirecoryLabel">
- <property name="text">
- <string>Working directory:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="Utils::PathChooser" name="workingDirectory" native="true"/>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>Utils::PathChooser</class>
- <extends>QWidget</extends>
- <header location="global">utils/pathchooser.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index 94484f3493..d909c4b909 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -30,6 +30,7 @@
#include "deployconfiguration.h"
#include "editorconfiguration.h"
#include "kit.h"
+#include "makestep.h"
#include "projectexplorer.h"
#include "projectnodes.h"
#include "target.h"
@@ -51,6 +52,8 @@
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
+#include <QFileDialog>
+
#include <limits>
#include <memory>
@@ -112,7 +115,7 @@ const Project::NodeMatcher Project::GeneratedFiles = [](const Node *node) {
// ProjectDocument:
// --------------------------------------------------------------------
-ProjectDocument::ProjectDocument(const QString &mimeType, const Utils::FileName &fileName,
+ProjectDocument::ProjectDocument(const QString &mimeType, const Utils::FilePath &fileName,
const ProjectDocument::ProjectCallback &callback) :
m_callback(callback)
{
@@ -149,7 +152,7 @@ bool ProjectDocument::reload(QString *errorString, Core::IDocument::ReloadFlag f
class ProjectPrivate
{
public:
- ProjectPrivate(const QString &mimeType, const Utils::FileName &fileName,
+ ProjectPrivate(const QString &mimeType, const Utils::FilePath &fileName,
const ProjectDocument::ProjectCallback &callback)
{
m_document = std::make_unique<ProjectDocument>(mimeType, fileName, callback);
@@ -177,6 +180,7 @@ public:
Kit::Predicate m_preferredKitPredicate;
Utils::MacroExpander m_macroExpander;
+ Utils::FilePath m_rootProjectDirectory;
mutable QVector<const Node *> m_sortedNodeList;
};
@@ -186,7 +190,7 @@ ProjectPrivate::~ProjectPrivate()
std::unique_ptr<ProjectNode> oldNode = std::move(m_rootProjectNode);
}
-Project::Project(const QString &mimeType, const Utils::FileName &fileName,
+Project::Project(const QString &mimeType, const Utils::FilePath &fileName,
const ProjectDocument::ProjectCallback &callback) :
d(new ProjectPrivate(mimeType, fileName, callback))
{
@@ -229,9 +233,9 @@ Core::IDocument *Project::document() const
return d->m_document.get();
}
-Utils::FileName Project::projectFilePath() const
+Utils::FilePath Project::projectFilePath() const
{
- QTC_ASSERT(document(), return Utils::FileName());
+ QTC_ASSERT(document(), return Utils::FilePath());
return document()->filePath();
}
@@ -327,9 +331,9 @@ Target *Project::target(Kit *k) const
return Utils::findOrDefault(d->m_targets, Utils::equal(&Target::kit, k));
}
-QList<Task> Project::projectIssues(const Kit *k) const
+Tasks Project::projectIssues(const Kit *k) const
{
- QList<Task> result;
+ Tasks result;
if (!k->isValid())
result.append(createProjectTask(Task::TaskType::Error, tr("Kit is not valid.")));
return {};
@@ -580,19 +584,19 @@ Project::RestoreResult Project::restoreSettings(QString *errorMessage)
/*!
* Returns a sorted list of all files matching the predicate \a filter.
*/
-Utils::FileNameList Project::files(const Project::NodeMatcher &filter) const
+Utils::FilePathList Project::files(const Project::NodeMatcher &filter) const
{
- Utils::FileNameList result;
+ Utils::FilePathList result;
if (d->m_sortedNodeList.empty() && filter(containerNode()))
result.append(projectFilePath());
- Utils::FileName lastAdded;
+ Utils::FilePath lastAdded;
for (const Node *n : qAsConst(d->m_sortedNodeList)) {
if (filter && !filter(n))
continue;
// Remove duplicates:
- const Utils::FileName path = n->filePath();
+ const Utils::FilePath path = n->filePath();
if (path == lastAdded)
continue; // skip duplicates
lastAdded = path;
@@ -635,7 +639,7 @@ QVariantMap Project::toMap() const
This includes the absolute path.
*/
-Utils::FileName Project::projectDirectory() const
+Utils::FilePath Project::projectDirectory() const
{
return projectDirectory(projectFilePath());
}
@@ -646,20 +650,37 @@ Utils::FileName Project::projectDirectory() const
This includes the absolute path.
*/
-Utils::FileName Project::projectDirectory(const Utils::FileName &top)
+Utils::FilePath Project::projectDirectory(const Utils::FilePath &top)
{
if (top.isEmpty())
- return Utils::FileName();
- return Utils::FileName::fromString(top.toFileInfo().absoluteDir().path());
+ return Utils::FilePath();
+ return Utils::FilePath::fromString(top.toFileInfo().absoluteDir().path());
+}
+
+void Project::changeRootProjectDirectory()
+{
+ Utils::FilePath rootPath = Utils::FilePath::fromString(
+ QFileDialog::getExistingDirectory(Core::ICore::dialogParent(),
+ tr("Select the Root Directory"),
+ rootProjectDirectory().toString(),
+ QFileDialog::ShowDirsOnly
+ | QFileDialog::DontResolveSymlinks));
+ if (rootPath != d->m_rootProjectDirectory) {
+ d->m_rootProjectDirectory = rootPath;
+ setNamedSettings(Constants::PROJECT_ROOT_PATH_KEY, d->m_rootProjectDirectory.toString());
+ emit rootProjectDirectoryChanged();
+ }
}
/*!
- Returns the common root directory that contains all files which belongs to a project.
+ Returns the common root directory that contains all files which belong to a project.
*/
-
-Utils::FileName Project::rootProjectDirectory() const
+Utils::FilePath Project::rootProjectDirectory() const
{
- return projectDirectory(); // TODO parse all files and find the common path
+ if (!d->m_rootProjectDirectory.isEmpty())
+ return d->m_rootProjectDirectory;
+
+ return projectDirectory();
}
ProjectNode *Project::rootProjectNode() const
@@ -701,6 +722,9 @@ Project::RestoreResult Project::fromMap(const QVariantMap &map, QString *errorMe
createTargetFromMap(map, i);
}
+ d->m_rootProjectDirectory = Utils::FilePath::fromString(
+ namedSettings(Constants::PROJECT_ROOT_PATH_KEY).toString());
+
return RestoreResult::Ok;
}
@@ -729,11 +753,11 @@ QStringList Project::filesGeneratedFrom(const QString &file) const
return QStringList();
}
-bool Project::isKnownFile(const Utils::FileName &filename) const
+bool Project::isKnownFile(const Utils::FilePath &filename) const
{
if (d->m_sortedNodeList.empty())
return filename == projectFilePath();
- const FileNode element(filename, FileType::Unknown, false);
+ const FileNode element(filename, FileType::Unknown);
return std::binary_search(std::begin(d->m_sortedNodeList), std::end(d->m_sortedNodeList),
&element, nodeLessThan);
}
@@ -778,7 +802,7 @@ void Project::projectLoaded()
Task Project::createProjectTask(Task::TaskType type, const QString &description)
{
- return Task(type, description, Utils::FileName(), -1, Core::Id());
+ return Task(type, description, Utils::FilePath(), -1, Core::Id());
}
Core::Context Project::projectContext() const
@@ -824,6 +848,20 @@ bool Project::knowsAllBuildExecutables() const
return true;
}
+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->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
+ ->firstOfType<MakeStep>()) {
+ cmd.command = makeStep->effectiveMakeCommand();
+ }
+ }
+ cmd.arguments << "install" << ("INSTALL_ROOT=" + QDir::toNativeSeparators(installRoot));
+ return cmd;
+}
+
void Project::setup(const QList<BuildInfo> &infoList)
{
std::vector<std::unique_ptr<Target>> toRegister;
@@ -921,18 +959,18 @@ void Project::setPreferredKitPredicate(const Kit::Predicate &predicate)
namespace ProjectExplorer {
-static Utils::FileName constructTestPath(const char *basePath)
+static Utils::FilePath constructTestPath(const char *basePath)
{
- Utils::FileName drive;
+ Utils::FilePath drive;
if (Utils::HostOsInfo::isWindowsHost())
- drive = Utils::FileName::fromString("C:");
+ drive = Utils::FilePath::fromString("C:");
return drive + QLatin1String(basePath);
}
-const Utils::FileName TEST_PROJECT_PATH = constructTestPath("/tmp/foobar/baz.project");
-const Utils::FileName TEST_PROJECT_NONEXISTING_FILE = constructTestPath("/tmp/foobar/nothing.cpp");
-const Utils::FileName TEST_PROJECT_CPP_FILE = constructTestPath("/tmp/foobar/main.cpp");
-const Utils::FileName TEST_PROJECT_GENERATED_FILE = constructTestPath("/tmp/foobar/generated.foo");
+const Utils::FilePath TEST_PROJECT_PATH = constructTestPath("/tmp/foobar/baz.project");
+const Utils::FilePath TEST_PROJECT_NONEXISTING_FILE = constructTestPath("/tmp/foobar/nothing.cpp");
+const Utils::FilePath TEST_PROJECT_CPP_FILE = constructTestPath("/tmp/foobar/main.cpp");
+const Utils::FilePath TEST_PROJECT_GENERATED_FILE = constructTestPath("/tmp/foobar/generated.foo");
const QString TEST_PROJECT_MIMETYPE = "application/vnd.test.qmakeprofile";
const QString TEST_PROJECT_DISPLAYNAME = "testProjectFoo";
const char TEST_PROJECT_ID[] = "Test.Project.Id";
@@ -958,12 +996,6 @@ public:
bool needsConfiguration() const final { return false; }
};
-class TestProjectNode : public ProjectNode
-{
-public:
- TestProjectNode(const Utils::FileName &dir) : ProjectNode(dir) { }
-};
-
void ProjectExplorerPlugin::testProject_setup()
{
TestProject project;
@@ -1060,11 +1092,12 @@ void ProjectExplorerPlugin::testProject_parsingFail()
std::unique_ptr<ProjectNode> createFileTree(Project *project)
{
- std::unique_ptr<ProjectNode> root = std::make_unique<TestProjectNode>(project->projectDirectory());
+ std::unique_ptr<ProjectNode> root = std::make_unique<ProjectNode>(project->projectDirectory());
std::vector<std::unique_ptr<FileNode>> nodes;
- nodes.emplace_back(std::make_unique<FileNode>(TEST_PROJECT_PATH, FileType::Project, false));
- nodes.emplace_back(std::make_unique<FileNode>(TEST_PROJECT_CPP_FILE, FileType::Source, false));
- nodes.emplace_back(std::make_unique<FileNode>(TEST_PROJECT_GENERATED_FILE, FileType::Source, true));
+ nodes.emplace_back(std::make_unique<FileNode>(TEST_PROJECT_PATH, FileType::Project));
+ nodes.emplace_back(std::make_unique<FileNode>(TEST_PROJECT_CPP_FILE, FileType::Source));
+ nodes.emplace_back(std::make_unique<FileNode>(TEST_PROJECT_GENERATED_FILE, FileType::Source));
+ nodes.back()->setIsGenerated(true);
root->addNestedNodes(std::move(nodes));
return root;
@@ -1079,7 +1112,7 @@ void ProjectExplorerPlugin::testProject_projectTree()
QCOMPARE(fileSpy.count(), 0);
QVERIFY(!project.rootProjectNode());
- project.setRootProjectNode(std::make_unique<TestProjectNode>(project.projectDirectory()));
+ project.setRootProjectNode(std::make_unique<ProjectNode>(project.projectDirectory()));
QCOMPARE(fileSpy.count(), 0);
QVERIFY(!project.rootProjectNode());
@@ -1095,14 +1128,14 @@ void ProjectExplorerPlugin::testProject_projectTree()
QCOMPARE(project.isKnownFile(TEST_PROJECT_CPP_FILE), true);
QCOMPARE(project.isKnownFile(TEST_PROJECT_GENERATED_FILE), true);
- Utils::FileNameList allFiles = project.files(Project::AllFiles);
+ Utils::FilePathList allFiles = project.files(Project::AllFiles);
QCOMPARE(allFiles.count(), 3);
QVERIFY(allFiles.contains(TEST_PROJECT_PATH));
QVERIFY(allFiles.contains(TEST_PROJECT_CPP_FILE));
QVERIFY(allFiles.contains(TEST_PROJECT_GENERATED_FILE));
QCOMPARE(project.files(Project::GeneratedFiles), {TEST_PROJECT_GENERATED_FILE});
- Utils::FileNameList sourceFiles = project.files(Project::SourceFiles);
+ Utils::FilePathList sourceFiles = project.files(Project::SourceFiles);
QCOMPARE(sourceFiles.count(), 2);
QVERIFY(sourceFiles.contains(TEST_PROJECT_PATH));
QVERIFY(sourceFiles.contains(TEST_PROJECT_CPP_FILE));
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index cf9590ad68..e66e049c0c 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -27,6 +27,7 @@
#include "projectexplorer_export.h"
+#include "deploymentdata.h"
#include "kit.h"
#include "subscription.h"
@@ -63,7 +64,7 @@ class PROJECTEXPLORER_EXPORT ProjectDocument : public Core::IDocument
public:
using ProjectCallback = std::function<void()>;
- ProjectDocument(const QString &mimeType, const Utils::FileName &fileName,
+ ProjectDocument(const QString &mimeType, const Utils::FilePath &fileName,
const ProjectCallback &callback = {});
Core::IDocument::ReloadBehavior reloadBehavior(Core::IDocument::ChangeTrigger state,
@@ -90,7 +91,7 @@ public:
isParsingRole
};
- Project(const QString &mimeType, const Utils::FileName &fileName,
+ Project(const QString &mimeType, const Utils::FilePath &fileName,
const ProjectDocument::ProjectCallback &callback = {});
~Project() override;
@@ -100,10 +101,13 @@ public:
QString mimeType() const;
Core::IDocument *document() const;
- Utils::FileName projectFilePath() const;
- Utils::FileName projectDirectory() const;
- Utils::FileName rootProjectDirectory() const;
- static Utils::FileName projectDirectory(const Utils::FileName &top);
+ Utils::FilePath projectFilePath() const;
+ Utils::FilePath projectDirectory() const;
+ static Utils::FilePath projectDirectory(const Utils::FilePath &top);
+
+ // This does not affect nodes, only the root path.
+ void changeRootProjectDirectory();
+ Utils::FilePath rootProjectDirectory() const;
virtual ProjectNode *rootProjectNode() const;
ContainerNode *containerNode() const;
@@ -122,7 +126,7 @@ public:
Target *activeTarget() const;
Target *target(Core::Id id) const;
Target *target(Kit *k) const;
- virtual QList<Task> projectIssues(const Kit *k) const;
+ virtual Tasks projectIssues(const Kit *k) const;
std::unique_ptr<Target> createTarget(Kit *k);
static bool copySteps(Target *sourceTarget, Target *newTarget);
@@ -137,9 +141,9 @@ public:
static const NodeMatcher SourceFiles;
static const NodeMatcher GeneratedFiles;
- Utils::FileNameList files(const NodeMatcher &matcher) const;
+ Utils::FilePathList files(const NodeMatcher &matcher) const;
virtual QStringList filesGeneratedFrom(const QString &sourceFile) const;
- bool isKnownFile(const Utils::FileName &filename) const;
+ bool isKnownFile(const Utils::FilePath &filename) const;
virtual QVariantMap toMap() const;
@@ -162,6 +166,10 @@ public:
// of configuration.
virtual bool knowsAllBuildExecutables() const;
+ virtual DeploymentKnowledge deploymentKnowledge() const { return DeploymentKnowledge::Bad; }
+ virtual bool hasMakeInstallEquivalent() const { return false; }
+ virtual MakeInstallCommand makeInstallCommand(const Target *target, const QString &installRoot);
+
void setup(const QList<BuildInfo> &infoList);
Utils::MacroExpander *macroExpander() const;
@@ -221,6 +229,8 @@ signals:
void parsingStarted();
void parsingFinished(bool success);
+ void rootProjectDirectoryChanged();
+
protected:
virtual RestoreResult fromMap(const QVariantMap &map, QString *errorMessage);
void createTargetFromMap(const QVariantMap &map, int index);
diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp
index d51084f1ed..3d05c9ff87 100644
--- a/src/plugins/projectexplorer/projectconfiguration.cpp
+++ b/src/plugins/projectexplorer/projectconfiguration.cpp
@@ -181,26 +181,13 @@ ProjectConfigurationAspect *ProjectConfiguration::aspect(Core::Id id) const
return m_aspects.aspect(id);
}
-Core::Id ProjectExplorer::idFromMap(const QVariantMap &map)
-{
- return Core::Id::fromSetting(map.value(QLatin1String(CONFIGURATION_ID_KEY)));
-}
-
-// StatefulProjectConfiguration
-
-bool StatefulProjectConfiguration::isEnabled() const
+void ProjectConfiguration::acquaintAspects()
{
- return m_isEnabled;
+ for (ProjectConfigurationAspect *aspect : m_aspects)
+ aspect->acquaintSiblings(m_aspects);
}
-StatefulProjectConfiguration::StatefulProjectConfiguration(QObject *parent, Core::Id id) :
- ProjectConfiguration(parent, id)
-{ }
-
-void StatefulProjectConfiguration::setEnabled(bool enabled)
+Core::Id ProjectExplorer::idFromMap(const QVariantMap &map)
{
- if (enabled == m_isEnabled)
- return;
- m_isEnabled = enabled;
- emit enabledChanged();
+ return Core::Id::fromSetting(map.value(QLatin1String(CONFIGURATION_ID_KEY)));
}
diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h
index 685661d482..2d5be2299d 100644
--- a/src/plugins/projectexplorer/projectconfiguration.h
+++ b/src/plugins/projectexplorer/projectconfiguration.h
@@ -41,6 +41,7 @@ QT_END_NAMESPACE
namespace ProjectExplorer {
class Project;
+class ProjectConfigurationAspects;
class PROJECTEXPLORER_EXPORT ProjectConfigurationAspect : public QObject
{
@@ -68,6 +69,7 @@ public:
virtual void fromMap(const QVariantMap &) {}
virtual void toMap(QVariantMap &) const {}
virtual void addToConfigurationLayout(QFormLayout *) {}
+ virtual void acquaintSiblings(const ProjectConfigurationAspects &) {}
signals:
void changed();
@@ -168,6 +170,8 @@ public:
ProjectConfigurationAspect *aspect(Core::Id id) const;
template <typename T> T *aspect() const { return m_aspects.aspect<T>(); }
+ void acquaintAspects();
+
signals:
void displayNameChanged();
void toolTipChanged();
@@ -183,29 +187,6 @@ private:
Utils::MacroExpander m_macroExpander;
};
-class PROJECTEXPLORER_EXPORT StatefulProjectConfiguration : public ProjectConfiguration
-{
- Q_OBJECT
-
-public:
- StatefulProjectConfiguration() = default;
-
- bool isEnabled() const;
-
- virtual QString disabledReason() const = 0;
-
-signals:
- void enabledChanged();
-
-protected:
- StatefulProjectConfiguration(QObject *parent, Core::Id id);
-
- void setEnabled(bool enabled);
-
-private:
- bool m_isEnabled = false;
-};
-
// helper function:
PROJECTEXPLORER_EXPORT Core::Id idFromMap(const QVariantMap &map);
diff --git a/src/plugins/projectexplorer/projectconfigurationaspects.cpp b/src/plugins/projectexplorer/projectconfigurationaspects.cpp
index c6f9ad9552..a4cec91d28 100644
--- a/src/plugins/projectexplorer/projectconfigurationaspects.cpp
+++ b/src/plugins/projectexplorer/projectconfigurationaspects.cpp
@@ -79,15 +79,17 @@ public:
QPointer<PathChooser> m_pathChooserDisplay;
QPointer<QTextEdit> m_textEditDisplay;
QPixmap m_labelPixmap;
+ Utils::FilePath m_baseFileName;
};
class BaseIntegerAspectPrivate
{
public:
- QVariant m_value;
+ qint64 m_value = 0;
QVariant m_minimumValue;
QVariant m_maximumValue;
int m_displayIntegerBase = 10;
+ qint64 m_displayScaleFactor = 1;
QString m_label;
QString m_prefix;
QString m_suffix;
@@ -136,9 +138,14 @@ void BaseStringAspect::toMap(QVariantMap &map) const
d->m_checker->toMap(map);
}
-FileName BaseStringAspect::fileName() const
+FilePath BaseStringAspect::fileName() const
{
- return FileName::fromString(d->m_value);
+ return FilePath::fromString(d->m_value);
+}
+
+void BaseStringAspect::setFileName(const FilePath &val)
+{
+ setValue(val.toString());
}
void BaseStringAspect::setLabelText(const QString &labelText)
@@ -207,6 +214,13 @@ void BaseStringAspect::setEnvironment(const Environment &env)
d->m_pathChooserDisplay->setEnvironment(env);
}
+void BaseStringAspect::setBaseFileName(const FilePath &baseFileName)
+{
+ d->m_baseFileName = baseFileName;
+ if (d->m_pathChooserDisplay)
+ d->m_pathChooserDisplay->setBaseFileName(baseFileName);
+}
+
void BaseStringAspect::addToConfigurationLayout(QFormLayout *layout)
{
QTC_CHECK(!d->m_label);
@@ -225,6 +239,7 @@ void BaseStringAspect::addToConfigurationLayout(QFormLayout *layout)
if (!d->m_historyCompleterKey.isEmpty())
d->m_pathChooserDisplay->setHistoryCompleter(d->m_historyCompleterKey);
d->m_pathChooserDisplay->setEnvironment(d->m_environment);
+ d->m_pathChooserDisplay->setBaseFileName(d->m_baseFileName);
connect(d->m_pathChooserDisplay, &PathChooser::pathChanged,
this, &BaseStringAspect::setValue);
hbox->addWidget(d->m_pathChooserDisplay);
@@ -277,7 +292,7 @@ void BaseStringAspect::update()
const bool enabled = !d->m_checker || d->m_checker->value();
if (d->m_pathChooserDisplay) {
- d->m_pathChooserDisplay->setFileName(FileName::fromString(displayedString));
+ d->m_pathChooserDisplay->setFileName(FilePath::fromString(displayedString));
d->m_pathChooserDisplay->setEnabled(enabled);
}
@@ -357,6 +372,7 @@ bool BaseBoolAspect::defaultValue() const
void BaseBoolAspect::setDefaultValue(bool defaultValue)
{
d->m_defaultValue = defaultValue;
+ d->m_value = defaultValue;
}
bool BaseBoolAspect::value() const
@@ -397,23 +413,24 @@ void BaseIntegerAspect::addToConfigurationLayout(QFormLayout *layout)
{
QTC_CHECK(!d->m_spinBox);
d->m_spinBox = new QSpinBox(layout->parentWidget());
- d->m_spinBox->setValue(d->m_value.toInt());
+ d->m_spinBox->setValue(int(d->m_value / d->m_displayScaleFactor));
d->m_spinBox->setDisplayIntegerBase(d->m_displayIntegerBase);
d->m_spinBox->setPrefix(d->m_prefix);
d->m_spinBox->setSuffix(d->m_suffix);
if (d->m_maximumValue.isValid() && d->m_maximumValue.isValid())
- d->m_spinBox->setRange(d->m_minimumValue.toInt(), d->m_maximumValue.toInt());
+ d->m_spinBox->setRange(int(d->m_minimumValue.toLongLong() / d->m_displayScaleFactor),
+ int(d->m_maximumValue.toLongLong() / d->m_displayScaleFactor));
layout->addRow(d->m_label, d->m_spinBox);
- connect(d->m_spinBox.data(), static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(d->m_spinBox.data(), QOverload<int>::of(&QSpinBox::valueChanged),
this, [this](int value) {
- d->m_value = value;
+ d->m_value = value * d->m_displayScaleFactor;
emit changed();
});
}
void BaseIntegerAspect::fromMap(const QVariantMap &map)
{
- d->m_value = map.value(settingsKey());
+ d->m_value = map.value(settingsKey()).toLongLong();
}
void BaseIntegerAspect::toMap(QVariantMap &data) const
@@ -421,19 +438,19 @@ void BaseIntegerAspect::toMap(QVariantMap &data) const
data.insert(settingsKey(), d->m_value);
}
-int BaseIntegerAspect::value() const
+qint64 BaseIntegerAspect::value() const
{
- return d->m_value.toInt();
+ return d->m_value;
}
-void BaseIntegerAspect::setValue(int value)
+void BaseIntegerAspect::setValue(qint64 value)
{
d->m_value = value;
if (d->m_spinBox)
- d->m_spinBox->setValue(d->m_value.toInt());
+ d->m_spinBox->setValue(int(d->m_value / d->m_displayScaleFactor));
}
-void BaseIntegerAspect::setRange(int min, int max)
+void BaseIntegerAspect::setRange(qint64 min, qint64 max)
{
d->m_minimumValue = min;
d->m_maximumValue = max;
@@ -459,4 +476,9 @@ void BaseIntegerAspect::setDisplayIntegerBase(int base)
d->m_displayIntegerBase = base;
}
+void BaseIntegerAspect::setDisplayScaleFactor(qint64 factor)
+{
+ d->m_displayScaleFactor = factor;
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectconfigurationaspects.h b/src/plugins/projectexplorer/projectconfigurationaspects.h
index 593f6d3ed5..250482b44e 100644
--- a/src/plugins/projectexplorer/projectconfigurationaspects.h
+++ b/src/plugins/projectexplorer/projectconfigurationaspects.h
@@ -89,6 +89,7 @@ public:
void setHistoryCompleter(const QString &historyCompleterKey);
void setExpectedKind(const Utils::PathChooser::Kind expectedKind);
void setEnvironment(const Utils::Environment &env);
+ void setBaseFileName(const Utils::FilePath &baseFileName);
bool isChecked() const;
void makeCheckable(const QString &optionalLabel, const QString &optionalBaseKey);
@@ -104,8 +105,8 @@ public:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
- Utils::FileName fileName() const;
- void setFileName(const Utils::FileName &val);
+ Utils::FilePath fileName() const;
+ void setFileName(const Utils::FilePath &val);
private:
void update();
@@ -123,14 +124,15 @@ public:
void addToConfigurationLayout(QFormLayout *layout) override;
- int value() const;
- void setValue(int val);
+ qint64 value() const;
+ void setValue(qint64 val);
- void setRange(int min, int max);
+ void setRange(qint64 min, qint64 max);
void setLabel(const QString &label);
void setPrefix(const QString &prefix);
void setSuffix(const QString &suffix);
void setDisplayIntegerBase(int base);
+ void setDisplayScaleFactor(qint64 factor);
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 3d619eab82..488a9fe117 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -25,7 +25,9 @@
#include "projectexplorer.h"
+#include "appoutputpane.h"
#include "buildsteplist.h"
+#include "compileoutputwindow.h"
#include "configtaskhandler.h"
#include "customexecutablerunconfiguration.h"
#include "customwizard/customwizard.h"
@@ -48,6 +50,7 @@
#include "kitfeatureprovider.h"
#include "kitmanager.h"
#include "kitoptionspage.h"
+#include "parseissuesdialog.h"
#include "target.h"
#include "toolchainmanager.h"
#include "toolchainoptionspage.h"
@@ -98,31 +101,32 @@
#include "projectwelcomepage.h"
#include <app/app_version.h>
-#include <extensionsystem/pluginspec.h>
-#include <extensionsystem/pluginmanager.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/id.h>
-#include <coreplugin/idocumentfactory.h>
-#include <coreplugin/idocument.h>
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/documentmanager.h>
-#include <coreplugin/imode.h>
-#include <coreplugin/modemanager.h>
-#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/diffservice.h>
+#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/fileutils.h>
#include <coreplugin/findplaceholder.h>
-#include <coreplugin/vcsmanager.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/id.h>
+#include <coreplugin/idocument.h>
+#include <coreplugin/idocumentfactory.h>
+#include <coreplugin/imode.h>
#include <coreplugin/iversioncontrol.h>
-#include <coreplugin/fileutils.h>
-#include <coreplugin/diffservice.h>
+#include <coreplugin/locator/directoryfilter.h>
+#include <coreplugin/modemanager.h>
+#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>
-#include <ssh/sshconnection.h>
-#include <ssh/sshsettings.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
@@ -244,6 +248,11 @@ const char PROJECT_OPEN_LOCATIONS_CONTEXT_MENU[] = "Project.P.OpenLocation.CtxM
const char DEFAULT_BUILD_DIRECTORY_TEMPLATE[] = "../%{JS: Util.asciify(\"build-%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}\")}";
const char DEFAULT_BUILD_DIRECTORY_TEMPLATE_KEY[] = "Directories/BuildDirectory.Template";
+const char TERMINAL_MODE_SETTINGS_KEY[] = "ProjectExplorer/Settings/TerminalMode";
+const char CLOSE_FILES_WITH_PROJECT_SETTINGS_KEY[]
+ = "ProjectExplorer/Settings/CloseFilesWithProject";
+const char CLEAR_ISSUES_ON_REBUILD_SETTINGS_KEY[] = "ProjectExplorer/Settings/ClearIssuesOnRebuild";
+
} // namespace Constants
@@ -259,11 +268,20 @@ static Utils::optional<Utils::Environment> buildEnv(const Project *project)
return project->activeTarget()->activeBuildConfiguration()->environment();
}
-static Utils::optional<Utils::Environment> runEnv(const Project *project)
+static bool canOpenTerminalWithRunEnv(const Project *project)
{
- if (!project || !project->activeTarget() || !project->activeTarget()->activeRunConfiguration())
- return {};
- return project->activeTarget()->activeRunConfiguration()->runnable().environment;
+ if (!project)
+ return false;
+ const Target * const target = project->activeTarget();
+ if (!target)
+ return false;
+ const RunConfiguration * const runConfig = target->activeRunConfiguration();
+ if (!runConfig)
+ return false;
+ IDevice::ConstPtr device = runConfig->runnable().device;
+ if (!device)
+ device = DeviceKitAspect::device(target->kit());
+ return device && device->canOpenTerminal();
}
static Target *activeTarget()
@@ -316,6 +334,8 @@ class ProjectExplorerPluginPrivate : public QObject
Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::ProjectExplorerPlugin)
public:
+ ProjectExplorerPluginPrivate();
+
void deploy(QList<Project *>);
int queue(QList<Project *>, QList<Id> stepIds);
void updateContextMenuActions();
@@ -352,6 +372,7 @@ public:
void handleAddExistingFiles();
void addExistingDirectory();
void addNewSubproject();
+ void addExistingProjects();
void removeProject();
void openFile();
void searchOnFileSystem();
@@ -370,6 +391,7 @@ public:
void updateUnloadProjectMenu();
using EnvironmentGetter = std::function<Utils::optional<Utils::Environment>(const Project *project)>;
void openTerminalHere(const EnvironmentGetter &env);
+ void openTerminalHereWithRunEnv();
void invalidateProject(ProjectExplorer::Project *project);
@@ -434,6 +456,7 @@ public:
QAction *m_addExistingFilesAction;
QAction *m_addExistingDirectoryAction;
QAction *m_addNewSubprojectAction;
+ QAction *m_addExistingProjectsAction;
QAction *m_removeFileAction;
QAction *m_duplicateFileAction;
QAction *m_removeProjectAction;
@@ -464,7 +487,7 @@ public:
int m_activeRunControlCount = 0;
int m_shutdownWatchDogId = -1;
- QHash<QString, std::function<Project *(const Utils::FileName &)>> m_projectCreators;
+ QHash<QString, std::function<Project *(const Utils::FilePath &)>> m_projectCreators;
QList<QPair<QString, QString> > m_recentProjects; // pair of filename, displayname
static const int m_maxRecentProjects = 25;
@@ -478,7 +501,6 @@ public:
bool m_shuttingDown = false;
Core::Id m_runMode = Constants::NO_RUN_MODE;
- KitManager *m_kitManager = nullptr;
ToolChainManager *m_toolChainManager = nullptr;
QStringList m_arguments;
@@ -532,6 +554,7 @@ public:
AllProjectsFilter m_allProjectsFilter;
CurrentProjectFilter m_currentProjectFilter;
+ DirectoryFilter m_allProjectDirectoriesFilter;
ProcessStepFactory m_processStepFactory;
@@ -539,11 +562,15 @@ public:
CurrentProjectFind m_curretProjectFind;
CustomExecutableRunConfigurationFactory m_customExecutableRunConfigFactory;
+ SimpleRunWorkerFactory<SimpleTargetRunner, CustomExecutableRunConfiguration>
+ m_customExecutableRunWorkerFactory;
ProjectFileWizardExtension m_projectFileWizardExtension;
// Settings pages
ProjectExplorerSettingsPage m_projectExplorerSettingsPage;
+ AppOutputSettingsPage m_appOutputSettingsPage;
+ CompileOutputSettingsPage m_compileOutputSettingsPage;
DeviceSettingsPage m_deviceSettingsPage;
SshSettingsPage m_sshSettingsPage;
@@ -552,6 +579,12 @@ public:
DefaultDeployConfigurationFactory m_defaultDeployConfigFactory;
IDocumentFactory m_documentFactory;
+
+ DeviceTypeKitAspect deviceTypeKitAspect;
+ DeviceKitAspect deviceeKitAspect;
+ ToolChainKitAspect toolChainKitAspect;
+ SysRootKitAspect sysRootKitAspect;
+ EnvironmentKitAspect environmentKitAspect;
};
static ProjectExplorerPlugin *m_instance = nullptr;
@@ -568,7 +601,7 @@ ProjectExplorerPlugin::~ProjectExplorerPlugin()
JsonWizardFactory::destroyAllFactories();
// Force sequence of deletion:
- delete dd->m_kitManager; // remove all the profile information
+ KitManager::destroy(); // remove all the profile information
delete dd->m_toolChainManager;
ProjectPanelFactory::destroyFactories();
delete dd;
@@ -595,7 +628,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
CustomWizard::setVerbose(arguments.count(QLatin1String("-customwizard-verbose")));
JsonWizardFactory::setVerbose(arguments.count(QLatin1String("-customwizard-verbose")));
- dd->m_kitManager = new KitManager; // register before ToolChainManager
dd->m_toolChainManager = new ToolChainManager;
// Register languages
@@ -604,13 +636,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
IWizardFactory::registerFeatureProvider(new KitFeatureProvider);
- // Register KitInformation:
- KitManager::registerKitInformation<DeviceTypeKitInformation>();
- KitManager::registerKitInformation<DeviceKitInformation>();
- KitManager::registerKitInformation<ToolChainKitInformation>();
- KitManager::registerKitInformation<SysRootKitInformation>();
- KitManager::registerKitInformation<EnvironmentKitInformation>();
-
IWizardFactory::registerFactoryCreator([]() -> QList<IWizardFactory *> {
QList<IWizardFactory *> result;
result << CustomWizard::createWizards();
@@ -640,8 +665,21 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd, &ProjectExplorerPluginPrivate::updateActions);
connect(sessionManager, &SessionManager::sessionLoaded,
dd, &ProjectExplorerPluginPrivate::updateActions);
- connect(sessionManager, &SessionManager::sessionLoaded,
- dd, &ProjectExplorerPluginPrivate::updateWelcomePage);
+ connect(sessionManager,
+ &SessionManager::sessionLoaded,
+ dd,
+ &ProjectExplorerPluginPrivate::updateWelcomePage);
+
+ connect(sessionManager, &SessionManager::projectAdded, dd, [](ProjectExplorer::Project *project) {
+ dd->m_allProjectDirectoriesFilter.addDirectory(project->projectDirectory().toString());
+ });
+ connect(sessionManager,
+ &SessionManager::projectRemoved,
+ dd,
+ [](ProjectExplorer::Project *project) {
+ dd->m_allProjectDirectoriesFilter.removeDirectory(
+ project->projectDirectory().toString());
+ });
ProjectTree *tree = &dd->m_projectTree;
connect(tree, &ProjectTree::currentProjectChanged,
@@ -652,7 +690,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd, &ProjectExplorerPluginPrivate::updateActions);
connect(tree, &ProjectTree::currentProjectChanged, this, [](Project *project) {
TextEditor::FindInFiles::instance()->setBaseDirectory(project ? project->projectDirectory()
- : Utils::FileName());
+ : Utils::FilePath());
});
// For JsonWizard:
@@ -807,13 +845,11 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
mfileContextMenu->appendGroup(Constants::G_PROJECT_TREE);
// Open Terminal submenu
-#if !defined(Q_OS_UNIX) || QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
ActionContainer * const openTerminal =
ActionManager::createMenu(ProjectExplorer::Constants::M_OPENTERMINALCONTEXT);
openTerminal->setOnAllDisabledBehavior(ActionContainer::Show);
dd->m_openTerminalMenu = openTerminal->menu();
- dd->m_openTerminalMenu->setTitle(FileUtils::msgTerminalAction());
-#endif
+ dd->m_openTerminalMenu->setTitle(FileUtils::msgTerminalWithAction());
// "open with" submenu
ActionContainer * const openWith =
@@ -881,27 +917,19 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
-#if !defined(Q_OS_UNIX) || QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
// Open Terminal Here menu
- mfileContextMenu->addMenu(openTerminal, Constants::G_FILE_OPEN);
- mfolderContextMenu->addMenu(openTerminal, Constants::G_FOLDER_FILES);
-
- dd->m_openTerminalHere = new QAction(tr("System Environment"), this);
- cmd = ActionManager::registerAction(dd->m_openTerminalHere, Constants::OPENTERMINALHERE,
- projecTreeContext);
- dd->m_openTerminalMenu->addAction(dd->m_openTerminalHere);
-#else
- dd->m_openTerminalHere = new QAction(FileUtils::msgTerminalAction(), this);
+ dd->m_openTerminalHere = new QAction(FileUtils::msgTerminalHereAction(), this);
cmd = ActionManager::registerAction(dd->m_openTerminalHere, Constants::OPENTERMINALHERE,
projecTreeContext);
mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
-#endif
+
+ mfileContextMenu->addMenu(openTerminal, Constants::G_FILE_OPEN);
+ mfolderContextMenu->addMenu(openTerminal, Constants::G_FOLDER_FILES);
dd->m_openTerminalHereBuildEnv = new QAction(tr("Build Environment"), this);
dd->m_openTerminalHereRunEnv = new QAction(tr("Run Environment"), this);
-#if !defined(Q_OS_UNIX) || QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
cmd = ActionManager::registerAction(dd->m_openTerminalHereBuildEnv,
"ProjectExplorer.OpenTerminalHereBuildEnv",
projecTreeContext);
@@ -911,7 +939,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
"ProjectExplorer.OpenTerminalHereRunEnv",
projecTreeContext);
dd->m_openTerminalMenu->addAction(dd->m_openTerminalHereRunEnv);
-#endif
// Open With menu
mfileContextMenu->addMenu(openWith, Constants::G_FILE_OPEN);
@@ -1141,6 +1168,13 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
+ // add existing projects action
+ dd->m_addExistingProjectsAction = new QAction(tr("Add Existing Projects..."), this);
+ cmd = ActionManager::registerAction(dd->m_addExistingProjectsAction,
+ "ProjectExplorer.AddExistingProjects", projecTreeContext);
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+ msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
+
// add existing directory action
dd->m_addExistingDirectoryAction = new QAction(tr("Add Existing Directory..."), this);
cmd = ActionManager::registerAction(dd->m_addExistingDirectoryAction,
@@ -1306,18 +1340,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
s->value(QLatin1String("ProjectExplorer/Settings/DeployBeforeRun"), true).toBool();
dd->m_projectExplorerSettings.saveBeforeBuild =
s->value(QLatin1String("ProjectExplorer/Settings/SaveBeforeBuild"), false).toBool();
- dd->m_projectExplorerSettings.showCompilerOutput =
- s->value(QLatin1String("ProjectExplorer/Settings/ShowCompilerOutput"), false).toBool();
- dd->m_projectExplorerSettings.showRunOutput =
- s->value(QLatin1String("ProjectExplorer/Settings/ShowRunOutput"), true).toBool();
- dd->m_projectExplorerSettings.showDebugOutput =
- s->value(QLatin1String("ProjectExplorer/Settings/ShowDebugOutput"), false).toBool();
- dd->m_projectExplorerSettings.cleanOldAppOutput =
- s->value(QLatin1String("ProjectExplorer/Settings/CleanOldAppOutput"), false).toBool();
- dd->m_projectExplorerSettings.mergeStdErrAndStdOut =
- s->value(QLatin1String("ProjectExplorer/Settings/MergeStdErrAndStdOut"), false).toBool();
- dd->m_projectExplorerSettings.wrapAppOutput =
- s->value(QLatin1String("ProjectExplorer/Settings/WrapAppOutput"), true).toBool();
dd->m_projectExplorerSettings.useJom =
s->value(QLatin1String("ProjectExplorer/Settings/UseJom"), true).toBool();
dd->m_projectExplorerSettings.autorestoreLastSession =
@@ -1328,12 +1350,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
s->value(QLatin1String("ProjectExplorer/Settings/PromptToStopRunControl"), false).toBool();
dd->m_projectExplorerSettings.automaticallyCreateRunConfigurations =
s->value(QLatin1String("ProjectExplorer/Settings/AutomaticallyCreateRunConfigurations"), true).toBool();
- dd->m_projectExplorerSettings.maxAppOutputChars =
- s->value(QLatin1String("ProjectExplorer/Settings/MaxAppOutputLines"),
- Core::Constants::DEFAULT_MAX_CHAR_COUNT).toInt() * 100;
- dd->m_projectExplorerSettings.maxBuildOutputChars =
- s->value(QLatin1String("ProjectExplorer/Settings/MaxBuildOutputLines"),
- Core::Constants::DEFAULT_MAX_CHAR_COUNT).toInt() * 100;
dd->m_projectExplorerSettings.environmentId =
QUuid(s->value(QLatin1String("ProjectExplorer/Settings/EnvironmentId")).toByteArray());
if (dd->m_projectExplorerSettings.environmentId.isNull())
@@ -1343,6 +1359,12 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
if (tmp < 0 || tmp > ProjectExplorerSettings::StopSameBuildDir)
tmp = Utils::HostOsInfo::isWindowsHost() ? 1 : 0;
dd->m_projectExplorerSettings.stopBeforeBuild = ProjectExplorerSettings::StopBeforeBuild(tmp);
+ dd->m_projectExplorerSettings.terminalMode = static_cast<TerminalMode>(s->value(
+ Constants::TERMINAL_MODE_SETTINGS_KEY, int(TerminalMode::Smart)).toInt());
+ dd->m_projectExplorerSettings.closeSourceFilesWithProject
+ = s->value(Constants::CLOSE_FILES_WITH_PROJECT_SETTINGS_KEY, true).toBool();
+ dd->m_projectExplorerSettings.clearIssuesOnRebuild
+ = s->value(Constants::CLEAR_ISSUES_ON_REBUILD_SETTINGS_KEY, true).toBool();
dd->m_projectExplorerSettings.buildDirectoryTemplate
= s->value(Constants::DEFAULT_BUILD_DIRECTORY_TEMPLATE_KEY).toString();
if (dd->m_projectExplorerSettings.buildDirectoryTemplate.isEmpty())
@@ -1448,6 +1470,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd, &ProjectExplorerPluginPrivate::addExistingDirectory);
connect(dd->m_addNewSubprojectAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::addNewSubproject);
+ connect(dd->m_addExistingProjectsAction, &QAction::triggered,
+ dd, &ProjectExplorerPluginPrivate::addExistingProjects);
connect(dd->m_removeProjectAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::removeProject);
connect(dd->m_openFileAction, &QAction::triggered,
@@ -1459,11 +1483,11 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(dd->m_openTerminalHere, &QAction::triggered, dd, []() { dd->openTerminalHere(sysEnv); });
connect(dd->m_openTerminalHereBuildEnv, &QAction::triggered, dd, []() { dd->openTerminalHere(buildEnv); });
- connect(dd->m_openTerminalHereRunEnv, &QAction::triggered, dd, []() { dd->openTerminalHere(runEnv); });
+ connect(dd->m_openTerminalHereRunEnv, &QAction::triggered, dd, []() { dd->openTerminalHereWithRunEnv(); });
connect(dd->m_filePropertiesAction, &QAction::triggered, this, []() {
- const Node *currentNode = ProjectTree::findCurrentNode();
- QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
+ const Node *currentNode = ProjectTree::currentNode();
+ QTC_ASSERT(currentNode && currentNode->asFileNode(), return);
DocumentManager::showFilePropertiesDialog(currentNode->filePath());
});
connect(dd->m_removeFileAction, &QAction::triggered,
@@ -1502,7 +1526,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
expander->registerFileVariables(Constants::VAR_CURRENTPROJECT_PREFIX,
tr("Current project's main file."),
[]() -> QString {
- Utils::FileName projectFilePath;
+ Utils::FilePath projectFilePath;
if (Project *project = ProjectTree::currentProject())
projectFilePath = project->projectFilePath();
return projectFilePath.toString();
@@ -1547,7 +1571,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
tr("The host address of the device in the currently active kit."),
[]() -> QString {
Kit *kit = currentKit();
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? device->sshParameters().host() : QString();
});
@@ -1555,7 +1579,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
tr("The SSH port of the device in the currently active kit."),
[]() -> QString {
Kit *kit = currentKit();
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? QString::number(device->sshParameters().port()) : QString();
});
@@ -1563,7 +1587,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
tr("The username with which to log into the device in the currently active kit."),
[]() -> QString {
Kit *kit = currentKit();
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? device->sshParameters().userName() : QString();
});
@@ -1573,7 +1597,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
"in the currently active kit."),
[]() -> QString {
Kit *kit = currentKit();
- const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
return device ? device->sshParameters().privateKeyFile : QString();
});
@@ -1598,14 +1622,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
tr("The currently active run configuration's executable (if applicable)."),
[]() -> QString {
if (Target *target = activeTarget()) {
- if (RunConfiguration *rc = target->activeRunConfiguration()) {
- // TODO: This duplicates code and is not always correct, but see
- // QTCREATORBUG-18317.
- // Solution: Re-introduce RunConfiguration::executable()?
- if (auto executableAspect = rc->aspect<ExecutableAspect>())
- return executableAspect->executable().toString();
- return QString();
- }
+ if (RunConfiguration *rc = target->activeRunConfiguration())
+ return rc->executable().toString();
}
return QString();
});
@@ -1718,7 +1736,7 @@ void ProjectExplorerPlugin::unloadProject(Project *project)
if (!DocumentManager::saveModifiedDocumentSilently(document))
return;
- if (!dd->closeAllFilesInProject(project))
+ if (projectExplorerSettings().closeSourceFilesWithProject && !dd->closeAllFilesInProject(project))
return;
dd->addToRecentProjects(document->filePath().toString(), project->displayName());
@@ -1729,7 +1747,7 @@ void ProjectExplorerPlugin::unloadProject(Project *project)
void ProjectExplorerPluginPrivate::closeAllProjects()
{
- if (!EditorManager::closeAllEditors())
+ if (!EditorManager::closeAllDocuments())
return; // Action has been cancelled
SessionManager::closeAllProjects();
@@ -1778,16 +1796,16 @@ void ProjectExplorerPlugin::extensionsInitialized()
QSsh::SshSettings::loadSettings(Core::ICore::settings());
const auto searchPathRetriever = [] {
- Utils::FileNameList searchPaths;
- searchPaths << Utils::FileName::fromString(Core::ICore::libexecPath());
+ Utils::FilePathList searchPaths;
+ searchPaths << Utils::FilePath::fromString(Core::ICore::libexecPath());
if (Utils::HostOsInfo::isWindowsHost()) {
const QString gitBinary = Core::ICore::settings()->value("Git/BinaryPath", "git")
.toString();
const QStringList rawGitSearchPaths = Core::ICore::settings()->value("Git/Path")
.toString().split(':', QString::SkipEmptyParts);
- const Utils::FileNameList gitSearchPaths = Utils::transform(rawGitSearchPaths,
- [](const QString &rawPath) { return Utils::FileName::fromString(rawPath); });
- const Utils::FileName fullGitPath = Utils::Environment::systemEnvironment()
+ const Utils::FilePathList gitSearchPaths = Utils::transform(rawGitSearchPaths,
+ [](const QString &rawPath) { return Utils::FilePath::fromString(rawPath); });
+ const Utils::FilePath fullGitPath = Utils::Environment::systemEnvironment()
.searchInPath(gitBinary, gitSearchPaths);
if (!fullGitPath.isEmpty()) {
searchPaths << fullGitPath.parentDir()
@@ -1798,6 +1816,16 @@ void ProjectExplorerPlugin::extensionsInitialized()
};
QSsh::SshSettings::setExtraSearchPathRetriever(searchPathRetriever);
+ const auto parseIssuesAction = new QAction(tr("Parse Build Output..."), this);
+ ActionContainer *mtools = ActionManager::actionContainer(Core::Constants::M_TOOLS);
+ Command * const cmd = ActionManager::registerAction(parseIssuesAction,
+ "ProjectExplorer.ParseIssuesAction");
+ connect(parseIssuesAction, &QAction::triggered, this, [] {
+ ParseIssuesDialog dlg(ICore::mainWindow());
+ dlg.exec();
+ });
+ mtools->addAction(cmd);
+
// delay restoring kits until UI is shown for improved perceived startup performance
QTimer::singleShot(0, this, &ProjectExplorerPlugin::restoreKits);
}
@@ -1808,7 +1836,7 @@ void ProjectExplorerPlugin::restoreKits()
ExtraAbi::load(); // Load this before Toolchains!
DeviceManager::instance()->load();
ToolChainManager::restoreToolChains();
- dd->m_kitManager->restoreKits();
+ KitManager::restoreKits();
QTimer::singleShot(0, dd, &ProjectExplorerPluginPrivate::restoreSession); // delay a bit...
}
@@ -1874,15 +1902,15 @@ void ProjectExplorerPluginPrivate::setStartupProject(Project *project)
bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project)
{
QTC_ASSERT(project, return false);
- QList<IDocument *> openFiles = DocumentModel::openedDocuments();
- Utils::erase(openFiles, [project](const IDocument *doc) {
- return !project->isKnownFile(doc->filePath());
+ QList<DocumentModel::Entry *> openFiles = DocumentModel::entries();
+ Utils::erase(openFiles, [project](const DocumentModel::Entry *entry) {
+ return entry->pinned || !project->isKnownFile(entry->fileName());
});
for (const Project * const otherProject : SessionManager::projects()) {
if (otherProject == project)
continue;
- Utils::erase(openFiles, [otherProject](const IDocument *doc) {
- return otherProject->isKnownFile(doc->filePath());
+ Utils::erase(openFiles, [otherProject](const DocumentModel::Entry *entry) {
+ return otherProject->isKnownFile(entry->fileName());
});
}
return EditorManager::closeDocuments(openFiles);
@@ -1920,20 +1948,18 @@ void ProjectExplorerPluginPrivate::savePersistentSettings()
s->setValue(QLatin1String("ProjectExplorer/Settings/BuildBeforeDeploy"), dd->m_projectExplorerSettings.buildBeforeDeploy);
s->setValue(QLatin1String("ProjectExplorer/Settings/DeployBeforeRun"), dd->m_projectExplorerSettings.deployBeforeRun);
s->setValue(QLatin1String("ProjectExplorer/Settings/SaveBeforeBuild"), dd->m_projectExplorerSettings.saveBeforeBuild);
- s->setValue(QLatin1String("ProjectExplorer/Settings/ShowCompilerOutput"), dd->m_projectExplorerSettings.showCompilerOutput);
- s->setValue(QLatin1String("ProjectExplorer/Settings/ShowRunOutput"), dd->m_projectExplorerSettings.showRunOutput);
- s->setValue(QLatin1String("ProjectExplorer/Settings/ShowDebugOutput"), dd->m_projectExplorerSettings.showDebugOutput);
- s->setValue(QLatin1String("ProjectExplorer/Settings/CleanOldAppOutput"), dd->m_projectExplorerSettings.cleanOldAppOutput);
- s->setValue(QLatin1String("ProjectExplorer/Settings/MergeStdErrAndStdOut"), dd->m_projectExplorerSettings.mergeStdErrAndStdOut);
- s->setValue(QLatin1String("ProjectExplorer/Settings/WrapAppOutput"), dd->m_projectExplorerSettings.wrapAppOutput);
s->setValue(QLatin1String("ProjectExplorer/Settings/UseJom"), dd->m_projectExplorerSettings.useJom);
s->setValue(QLatin1String("ProjectExplorer/Settings/AutoRestoreLastSession"), dd->m_projectExplorerSettings.autorestoreLastSession);
s->setValue(QLatin1String("ProjectExplorer/Settings/AddLibraryPathsToRunEnv"), dd->m_projectExplorerSettings.addLibraryPathsToRunEnv);
s->setValue(QLatin1String("ProjectExplorer/Settings/PromptToStopRunControl"), dd->m_projectExplorerSettings.prompToStopRunControl);
+ s->setValue(Constants::TERMINAL_MODE_SETTINGS_KEY,
+ int(dd->m_projectExplorerSettings.terminalMode));
+ s->setValue(Constants::CLOSE_FILES_WITH_PROJECT_SETTINGS_KEY,
+ dd->m_projectExplorerSettings.closeSourceFilesWithProject);
+ s->setValue(Constants::CLEAR_ISSUES_ON_REBUILD_SETTINGS_KEY,
+ dd->m_projectExplorerSettings.clearIssuesOnRebuild);
s->setValue(QLatin1String("ProjectExplorer/Settings/AutomaticallyCreateRunConfigurations"),
dd->m_projectExplorerSettings.automaticallyCreateRunConfigurations);
- s->setValue(QLatin1String("ProjectExplorer/Settings/MaxAppOutputLines"), dd->m_projectExplorerSettings.maxAppOutputChars / 100);
- s->setValue(QLatin1String("ProjectExplorer/Settings/MaxBuildOutputLines"), dd->m_projectExplorerSettings.maxBuildOutputChars / 100);
s->setValue(QLatin1String("ProjectExplorer/Settings/EnvironmentId"), dd->m_projectExplorerSettings.environmentId.toByteArray());
s->setValue(QLatin1String("ProjectExplorer/Settings/StopBeforeBuild"), dd->m_projectExplorerSettings.stopBeforeBuild);
@@ -2008,7 +2034,7 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
QTC_ASSERT(!fileName.isEmpty(), continue);
const QFileInfo fi(fileName);
- const auto filePath = Utils::FileName::fromString(fi.absoluteFilePath());
+ const auto filePath = Utils::FilePath::fromString(fi.absoluteFilePath());
Project *found = Utils::findOrDefault(SessionManager::projects(),
Utils::equal(&Project::projectFilePath, filePath));
if (found) {
@@ -2073,7 +2099,7 @@ void ProjectExplorerPluginPrivate::currentModeChanged(Id mode, Id oldMode)
// Saving settings directly in a mode change is not a good idea, since the mode change
// can be part of a bigger change. Save settings after that bigger change had a chance to
// complete.
- QTimer::singleShot(0, ICore::instance(), &ICore::saveSettings);
+ QTimer::singleShot(0, ICore::instance(), [] { ICore::saveSettings(ICore::ModeChanged); });
}
if (mode == Core::Constants::MODE_WELCOME)
updateWelcomePage();
@@ -2216,14 +2242,13 @@ void ProjectExplorerPluginPrivate::executeRunConfiguration(RunConfiguration *run
}
}
- RunControl::WorkerCreator producer = RunControl::producer(runConfiguration, runMode);
- QTC_ASSERT(producer, return);
- auto runControl = new RunControl(runConfiguration, runMode);
+ auto runControl = new RunControl(runMode);
+ runControl->setRunConfiguration(runConfiguration);
// A user needed interaction may have cancelled the run
// (by example asking for a process pid or server url).
- if (!producer(runControl)) {
+ if (!runControl->createMainWorker()) {
delete runControl;
return;
}
@@ -2250,8 +2275,8 @@ void ProjectExplorerPluginPrivate::startRunControl(RunControl *runControl)
m_outputPane.flash(); // one flash for starting
m_outputPane.showTabFor(runControl);
Core::Id runMode = runControl->runMode();
- bool popup = (runMode == Constants::NORMAL_RUN_MODE && dd->m_projectExplorerSettings.showRunOutput)
- || (runMode == Constants::DEBUG_RUN_MODE && m_projectExplorerSettings.showDebugOutput);
+ bool popup = (runMode == Constants::NORMAL_RUN_MODE && m_outputPane.settings().popUpForRunOutput)
+ || (runMode == Constants::DEBUG_RUN_MODE && m_outputPane.settings().popUpForDebugOutput);
m_outputPane.setBehaviorOnOutput(runControl, popup ? AppOutputPane::Popup : AppOutputPane::Flash);
connect(runControl, &QObject::destroyed, this, &ProjectExplorerPluginPrivate::checkForShutdown,
Qt::QueuedConnection);
@@ -2334,10 +2359,10 @@ QList<QPair<QString, QString> > ProjectExplorerPluginPrivate::recentProjects() c
static QString pathOrDirectoryFor(const Node *node, bool dir)
{
- Utils::FileName path = node->filePath();
+ Utils::FilePath path = node->filePath();
QString location;
const FolderNode *folder = node->asFolderNode();
- if (node->nodeType() == NodeType::VirtualFolder && folder) {
+ if (node->isVirtualFolderType() && folder) {
// Virtual Folder case
// If there are files directly below or no subfolders, take the folder path
if (!folder->fileNodes().isEmpty() || folder->folderNodes().isEmpty()) {
@@ -2515,6 +2540,16 @@ bool ProjectExplorerPlugin::saveModifiedFiles()
//NBS handle case where there is no activeBuildConfiguration
// because someone delete all build configurations
+ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate()
+ : m_allProjectDirectoriesFilter("Files in All Project Directories")
+{
+ m_allProjectDirectoriesFilter.setDisplayName(m_allProjectDirectoriesFilter.id().toString());
+ m_allProjectDirectoriesFilter.setShortcutString("a"); // shared with "Files in Any Project"
+ m_allProjectDirectoriesFilter.setIncludedByDefault(false); // but not included in default
+ m_allProjectDirectoriesFilter.setFilters({});
+ m_allProjectDirectoriesFilter.setIsCustomFilter(false);
+}
+
void ProjectExplorerPluginPrivate::deploy(QList<Project *> projects)
{
QList<Id> steps;
@@ -2561,11 +2596,11 @@ int ProjectExplorerPluginPrivate::queue(QList<Project *> projects, QList<Id> ste
BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
if (!bc)
return false;
- if (!Utils::FileName::fromString(rc->runnable().executable).isChildOf(bc->buildDirectory()))
+ if (!Utils::FilePath::fromString(rc->runnable().executable).isChildOf(bc->buildDirectory()))
return false;
IDevice::ConstPtr device = rc->runnable().device;
if (device.isNull())
- device = DeviceKitInformation::device(t->kit());
+ device = DeviceKitAspect::device(t->kit());
return !device.isNull() && device->type() == Core::Id(Constants::DESKTOP_DEVICE_TYPE);
});
}
@@ -2637,7 +2672,7 @@ void ProjectExplorerPlugin::buildProject(Project *p)
void ProjectExplorerPluginPrivate::runProjectContextMenu()
{
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
const ProjectNode *projectNode = node ? node->asProjectNode() : nullptr;
if (projectNode == ProjectTree::currentProject()->rootProjectNode() || !projectNode) {
m_instance->runProject(ProjectTree::currentProject(), Constants::NORMAL_RUN_MODE);
@@ -3015,8 +3050,7 @@ bool ProjectExplorerPlugin::canRunStartupProject(Core::Id runMode, QString *whyN
}
// shouldn't actually be shown to the user...
- RunControl::WorkerCreator producer = RunControl::producer(activeRC, runMode);
- if (!producer) {
+ if (!RunControl::canRun(activeRC, runMode)) {
if (whyNot)
*whyNot = tr("Cannot run \"%1\".").arg(activeRC->displayName());
return false;
@@ -3139,6 +3173,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_addExistingDirectoryAction->setEnabled(false);
m_addNewFileAction->setEnabled(false);
m_addNewSubprojectAction->setEnabled(false);
+ m_addExistingProjectsAction->setEnabled(false);
m_removeProjectAction->setEnabled(false);
m_removeFileAction->setEnabled(false);
m_duplicateFileAction->setEnabled(false);
@@ -3150,6 +3185,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_addExistingDirectoryAction->setVisible(true);
m_addNewFileAction->setVisible(true);
m_addNewSubprojectAction->setVisible(true);
+ m_addExistingProjectsAction->setVisible(true);
m_removeProjectAction->setVisible(true);
m_removeFileAction->setVisible(true);
m_duplicateFileAction->setVisible(false);
@@ -3168,7 +3204,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
runMenu->menu()->clear();
runMenu->menu()->menuAction()->setVisible(false);
- const Node *currentNode = ProjectTree::findCurrentNode();
+ const Node *currentNode = ProjectTree::currentNode();
if (currentNode && currentNode->managingProject()) {
ProjectNode *pn;
@@ -3179,7 +3215,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
Project *project = ProjectTree::currentProject();
m_openTerminalHereBuildEnv->setVisible(bool(buildEnv(project)));
- m_openTerminalHereRunEnv->setVisible(bool(runEnv(project)));
+ m_openTerminalHereRunEnv->setVisible(canOpenTerminalWithRunEnv(project));
if (pn && project) {
if (pn == project->rootProjectNode()) {
@@ -3187,8 +3223,9 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
} else {
QList<RunConfiguration *> runConfigs;
if (Target *t = project->activeTarget()) {
+ const QString buildKey = pn->buildKey();
for (RunConfiguration *rc : t->runConfigurations()) {
- if (rc->canRunForNode(pn))
+ if (rc->buildKey() == buildKey)
runConfigs.append(rc);
}
}
@@ -3217,10 +3254,12 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
// Also handles ProjectNode
m_addNewFileAction->setEnabled(supports(AddNewFile)
&& !ICore::isNewItemDialogRunning());
- m_addNewSubprojectAction->setEnabled(currentNode->nodeType() == NodeType::Project
+ m_addNewSubprojectAction->setEnabled(currentNode->isProjectNodeType()
&& supports(AddSubProject)
&& !ICore::isNewItemDialogRunning());
- m_removeProjectAction->setEnabled(currentNode->nodeType() == NodeType::Project
+ m_addExistingProjectsAction->setEnabled(currentNode->isProjectNodeType()
+ && supports(AddExistingProject));
+ m_removeProjectAction->setEnabled(currentNode->isProjectNodeType()
&& supports(RemoveSubProject));
m_addExistingFilesAction->setEnabled(supports(AddExistingFile));
m_addExistingDirectoryAction->setEnabled(supports(AddExistingDirectory));
@@ -3265,6 +3304,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
if (supports(HideFolderActions)) {
m_addNewFileAction->setVisible(false);
m_addNewSubprojectAction->setVisible(false);
+ m_addExistingProjectsAction->setVisible(false);
m_removeProjectAction->setVisible(false);
m_addExistingFilesAction->setVisible(false);
m_addExistingDirectoryAction->setVisible(false);
@@ -3289,7 +3329,7 @@ void ProjectExplorerPluginPrivate::updateLocationSubMenus()
QTC_CHECK(folderMenu->actions().isEmpty());
const FolderNode *const fn
- = ProjectTree::findCurrentNode() ? ProjectTree::findCurrentNode()->asFolderNode() : nullptr;
+ = ProjectTree::currentNode() ? ProjectTree::currentNode()->asFolderNode() : nullptr;
const QList<FolderNode::LocationInfo> locations
= fn ? fn->locationInfo() : QList<FolderNode::LocationInfo>();
@@ -3302,7 +3342,7 @@ void ProjectExplorerPluginPrivate::updateLocationSubMenus()
for (const FolderNode::LocationInfo &li : locations) {
const int line = li.line;
- const Utils::FileName path = li.path;
+ const Utils::FilePath path = li.path;
auto *action = new QAction(li.displayName, nullptr);
connect(action, &QAction::triggered, this, [line, path]() {
Core::EditorManager::openEditorAt(path.toString(), line);
@@ -3317,7 +3357,7 @@ void ProjectExplorerPluginPrivate::updateLocationSubMenus()
void ProjectExplorerPluginPrivate::addNewFile()
{
- Node* currentNode = ProjectTree::findCurrentNode();
+ Node *currentNode = ProjectTree::currentNode();
QTC_ASSERT(currentNode, return);
QString location = directoryFor(currentNode);
@@ -3343,11 +3383,11 @@ void ProjectExplorerPluginPrivate::addNewFile()
void ProjectExplorerPluginPrivate::addNewSubproject()
{
- Node* currentNode = ProjectTree::findCurrentNode();
+ Node* currentNode = ProjectTree::currentNode();
QTC_ASSERT(currentNode, return);
QString location = directoryFor(currentNode);
- if (currentNode->nodeType() == NodeType::Project
+ if (currentNode->isProjectNodeType()
&& currentNode->supportsAction(AddSubProject, currentNode)) {
QVariantMap map;
map.insert(QLatin1String(Constants::PREFERRED_PROJECT_NODE), QVariant::fromValue(currentNode));
@@ -3371,9 +3411,50 @@ void ProjectExplorerPluginPrivate::addNewSubproject()
}
}
+void ProjectExplorerPluginPrivate::addExistingProjects()
+{
+ Node * const currentNode = ProjectTree::currentNode();
+ if (!currentNode)
+ return;
+ ProjectNode *projectNode = currentNode->asProjectNode();
+ if (!projectNode && currentNode->asContainerNode())
+ projectNode = currentNode->asContainerNode()->rootProjectNode();
+ QTC_ASSERT(projectNode, return);
+ const QString dir = directoryFor(currentNode);
+ QStringList subProjectFilePaths = QFileDialog::getOpenFileNames(
+ ICore::mainWindow(), tr("Choose Project File"), dir,
+ projectNode->subProjectFileNamePatterns().join(";;"));
+ if (!ProjectTree::hasNode(projectNode))
+ return;
+ const QList<Node *> childNodes = projectNode->nodes();
+ Utils::erase(subProjectFilePaths, [childNodes](const QString &filePath) {
+ return Utils::anyOf(childNodes, [filePath](const Node *n) {
+ return n->filePath().toString() == filePath;
+ });
+ });
+ if (subProjectFilePaths.empty())
+ return;
+ QStringList failedProjects;
+ QStringList addedProjects;
+ for (const QString &filePath : subProjectFilePaths) {
+ if (projectNode->addSubProject(filePath))
+ addedProjects << filePath;
+ else
+ failedProjects << filePath;
+ }
+ if (!failedProjects.empty()) {
+ const QString message = tr("The following subprojects could not be added to project "
+ "\"%2\":").arg(projectNode->managingProject()->displayName());
+ QMessageBox::warning(ICore::mainWindow(), tr("Adding Subproject Failed"),
+ message + "\n " + failedProjects.join("\n "));
+ return;
+ }
+ VcsManager::promptToAdd(dir, addedProjects);
+}
+
void ProjectExplorerPluginPrivate::handleAddExistingFiles()
{
- Node *node = ProjectTree::findCurrentNode();
+ Node *node = ProjectTree::currentNode();
FolderNode *folderNode = node ? node->asFolderNode() : nullptr;
QTC_ASSERT(folderNode, return);
@@ -3388,19 +3469,17 @@ void ProjectExplorerPluginPrivate::handleAddExistingFiles()
void ProjectExplorerPluginPrivate::addExistingDirectory()
{
- Node *node = ProjectTree::findCurrentNode();
+ Node *node = ProjectTree::currentNode();
FolderNode *folderNode = node ? node->asFolderNode() : nullptr;
QTC_ASSERT(folderNode, return);
- SelectableFilesDialogAddDirectory dialog(Utils::FileName::fromString(directoryFor(node)),
- Utils::FileNameList(), ICore::mainWindow());
- const QString addFileFilter = folderNode->addFileFilter();
- if (!addFileFilter.isEmpty())
- dialog.setAddFileFilter(addFileFilter);
+ SelectableFilesDialogAddDirectory dialog(Utils::FilePath::fromString(directoryFor(node)),
+ Utils::FilePathList(), ICore::mainWindow());
+ dialog.setAddFileFilter({});
if (dialog.exec() == QDialog::Accepted)
- ProjectExplorerPlugin::addExistingFiles(folderNode, Utils::transform(dialog.selectedFiles(), &Utils::FileName::toString));
+ ProjectExplorerPlugin::addExistingFiles(folderNode, Utils::transform(dialog.selectedFiles(), &Utils::FilePath::toString));
}
void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStringList &filePaths)
@@ -3430,7 +3509,7 @@ void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStri
void ProjectExplorerPluginPrivate::removeProject()
{
- Node *node = ProjectTree::findCurrentNode();
+ Node *node = ProjectTree::currentNode();
if (!node)
return;
ProjectNode *projectNode = node->managingProject();
@@ -3444,28 +3523,28 @@ void ProjectExplorerPluginPrivate::removeProject()
void ProjectExplorerPluginPrivate::openFile()
{
- const Node *currentNode = ProjectTree::findCurrentNode();
+ const Node *currentNode = ProjectTree::currentNode();
QTC_ASSERT(currentNode, return);
EditorManager::openEditor(currentNode->filePath().toString());
}
void ProjectExplorerPluginPrivate::searchOnFileSystem()
{
- const Node *currentNode = ProjectTree::findCurrentNode();
+ const Node *currentNode = ProjectTree::currentNode();
QTC_ASSERT(currentNode, return);
TextEditor::FindInFiles::findOnFileSystem(pathFor(currentNode));
}
void ProjectExplorerPluginPrivate::showInGraphicalShell()
{
- Node *currentNode = ProjectTree::findCurrentNode();
+ Node *currentNode = ProjectTree::currentNode();
QTC_ASSERT(currentNode, return);
FileUtils::showInGraphicalShell(ICore::mainWindow(), pathFor(currentNode));
}
void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env)
{
- const Node *currentNode = ProjectTree::findCurrentNode();
+ const Node *currentNode = ProjectTree::currentNode();
QTC_ASSERT(currentNode, return);
const auto environment = env(ProjectTree::projectForNode(currentNode));
@@ -3475,21 +3554,46 @@ void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env
FileUtils::openTerminal(directoryFor(currentNode), environment.value());
}
+void ProjectExplorerPluginPrivate::openTerminalHereWithRunEnv()
+{
+ const Node *currentNode = ProjectTree::currentNode();
+ QTC_ASSERT(currentNode, return);
+
+ const Project * const project = ProjectTree::projectForNode(currentNode);
+ QTC_ASSERT(project, return);
+ const Target * const target = project->activeTarget();
+ QTC_ASSERT(target, return);
+ const RunConfiguration * const runConfig = target->activeRunConfiguration();
+ QTC_ASSERT(runConfig, return);
+
+ const Runnable runnable = runConfig->runnable();
+ IDevice::ConstPtr device = runnable.device;
+ if (!device)
+ device = DeviceKitAspect::device(target->kit());
+ QTC_ASSERT(device && device->canOpenTerminal(), return);
+ const QString workingDir = device->type() == Constants::DESKTOP_DEVICE_TYPE
+ ? directoryFor(currentNode) : runnable.workingDirectory;
+ device->openTerminal(runnable.environment, workingDir);
+}
+
void ProjectExplorerPluginPrivate::removeFile()
{
- const Node *currentNode = ProjectTree::findCurrentNode();
- QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
+ const Node *currentNode = ProjectTree::currentNode();
+ QTC_ASSERT(currentNode && currentNode->asFileNode(), return);
- const Utils::FileName filePath = currentNode->filePath();
+ const Utils::FilePath filePath = currentNode->filePath();
Utils::RemoveFileDialog removeFileDialog(filePath.toString(), ICore::mainWindow());
if (removeFileDialog.exec() == QDialog::Accepted) {
const bool deleteFile = removeFileDialog.isDeleteFileChecked();
// Re-read the current node, in case the project is re-parsed while the dialog is open
- if (currentNode != ProjectTree::findCurrentNode()) {
- currentNode = ProjectTreeWidget::nodeForFile(filePath);
- QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
+ if (!ProjectTree::hasNode(currentNode)) {
+ QMessageBox::warning(ICore::mainWindow(), tr("Removing File Failed"),
+ tr("File %1 was not removed, because the project has changed "
+ "in the meantime.\nPlease try again.")
+ .arg(filePath.toUserOutput()));
+ return;
}
// remove from project
@@ -3512,8 +3616,8 @@ void ProjectExplorerPluginPrivate::removeFile()
void ProjectExplorerPluginPrivate::duplicateFile()
{
- Node *currentNode = ProjectTree::findCurrentNode();
- QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
+ Node *currentNode = ProjectTree::currentNode();
+ QTC_ASSERT(currentNode && currentNode->asFileNode(), return);
FileNode *fileNode = currentNode->asFileNode();
QString filePath = currentNode->filePath().toString();
@@ -3543,8 +3647,8 @@ void ProjectExplorerPluginPrivate::duplicateFile()
void ProjectExplorerPluginPrivate::deleteFile()
{
- Node *currentNode = ProjectTree::findCurrentNode();
- QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
+ Node *currentNode = ProjectTree::currentNode();
+ QTC_ASSERT(currentNode && currentNode->asFileNode(), return);
FileNode *fileNode = currentNode->asFileNode();
@@ -3696,6 +3800,16 @@ const ProjectExplorerSettings &ProjectExplorerPlugin::projectExplorerSettings()
return dd->m_projectExplorerSettings;
}
+void ProjectExplorerPlugin::setAppOutputSettings(const AppOutputSettings &settings)
+{
+ dd->m_outputPane.setSettings(settings);
+}
+
+const AppOutputSettings &ProjectExplorerPlugin::appOutputSettings()
+{
+ return dd->m_outputPane.settings();
+}
+
QStringList ProjectExplorerPlugin::projectFilePatterns()
{
QStringList patterns;
@@ -3707,7 +3821,7 @@ QStringList ProjectExplorerPlugin::projectFilePatterns()
return patterns;
}
-bool ProjectExplorerPlugin::isProjectFile(const Utils::FileName &filePath)
+bool ProjectExplorerPlugin::isProjectFile(const Utils::FilePath &filePath)
{
Utils::MimeType mt = Utils::mimeTypeForFile(filePath.toString());
for (const QString &mime : dd->m_projectCreators.keys()) {
@@ -3737,16 +3851,6 @@ QString ProjectExplorerPlugin::buildDirectoryTemplate()
return dd->m_projectExplorerSettings.buildDirectoryTemplate;
}
-/*!
- Sets the current build directory template to \a directory.
-
- \sa defaultbuildDirectory
-*/
-void ProjectExplorerPlugin::setBuildDirectoryTemplate(const QString &dir)
-{
- dd->m_projectExplorerSettings.buildDirectoryTemplate = dir;
-}
-
QString ProjectExplorerPlugin::defaultBuildDirectoryTemplate()
{
return QString(Constants::DEFAULT_BUILD_DIRECTORY_TEMPLATE);
@@ -3758,12 +3862,12 @@ QList<QPair<QString, QString> > ProjectExplorerPlugin::recentProjects()
}
void ProjectManager::registerProjectCreator(const QString &mimeType,
- const std::function<Project *(const Utils::FileName &)> &creator)
+ const std::function<Project *(const Utils::FilePath &)> &creator)
{
dd->m_projectCreators[mimeType] = creator;
}
-Project *ProjectManager::openProject(const Utils::MimeType &mt, const Utils::FileName &fileName)
+Project *ProjectManager::openProject(const Utils::MimeType &mt, const Utils::FilePath &fileName)
{
if (mt.isValid()) {
for (const QString &mimeType : dd->m_projectCreators.keys()) {
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index e00fc393d0..23c2098216 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -45,7 +45,7 @@ class Id;
namespace Utils {
class ProcessHandle;
-class FileName;
+class FilePath;
}
namespace ProjectExplorer {
@@ -56,7 +56,10 @@ class Node;
class FolderNode;
class FileNode;
-namespace Internal { class ProjectExplorerSettings; }
+namespace Internal {
+class AppOutputSettings;
+class ProjectExplorerSettings;
+}
class PROJECTEXPLORER_EXPORT ProjectExplorerPlugin : public ExtensionSystem::IPlugin
{
@@ -129,13 +132,16 @@ public:
static void setProjectExplorerSettings(const Internal::ProjectExplorerSettings &pes);
static const Internal::ProjectExplorerSettings &projectExplorerSettings();
+ static void setAppOutputSettings(const Internal::AppOutputSettings &settings);
+ static const Internal::AppOutputSettings &appOutputSettings();
+
static void startRunControl(RunControl *runControl);
static void showRunErrorMessage(const QString &errorMessage);
// internal public for FlatModel
static void renameFile(Node *node, const QString &newFilePath);
static QStringList projectFilePatterns();
- static bool isProjectFile(const Utils::FileName &filePath);
+ static bool isProjectFile(const Utils::FilePath &filePath);
static QList<QPair<QString, QString> > recentProjects();
static bool canRunStartupProject(Core::Id runMode, QString *whyNot = nullptr);
@@ -164,7 +170,6 @@ public:
static void openOpenProjectDialog();
static QString buildDirectoryTemplate();
- static void setBuildDirectoryTemplate(const QString &dir);
static QString defaultBuildDirectoryTemplate();
signals:
@@ -252,6 +257,8 @@ private slots:
void testProject_parsingSuccess();
void testProject_parsingFail();
void testProject_projectTree();
+
+ void testSessionSwitch();
#endif // WITH_TESTS
};
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 8ef32ae9ba..097fcb6da5 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -10,6 +10,7 @@ include(../../shared/clang/clang_defines.pri)
HEADERS += projectexplorer.h \
abi.h \
abiwidget.h \
+ addrunconfigdialog.h \
ansifilterparser.h \
buildinfo.h \
clangparser.h \
@@ -17,6 +18,8 @@ HEADERS += projectexplorer.h \
environmentaspect.h \
environmentaspectwidget.h \
extraabi.h \
+ fileinsessionfinder.h \
+ filterkitaspectsdialog.h \
gcctoolchain.h \
importwidget.h \
userfileaccessor.h \
@@ -31,9 +34,7 @@ HEADERS += projectexplorer.h \
targetsetupwidget.h \
kit.h \
kitchooser.h \
- kitconfigwidget.h \
kitinformation.h \
- kitinformationconfigwidget.h \
kitfeatureprovider.h \
kitmanager.h \
kitmanagerconfigwidget.h \
@@ -76,6 +77,7 @@ HEADERS += projectexplorer.h \
editorconfiguration.h \
editorsettingspropertiespage.h \
runconfiguration.h \
+ runcontrol.h \
applicationlauncher.h \
runsettingspropertiespage.h \
projecttreewidget.h \
@@ -158,11 +160,14 @@ HEADERS += projectexplorer.h \
customexecutablerunconfiguration.h \
projectmacro.h \
makestep.h \
- projectconfigurationaspects.h
+ parseissuesdialog.h \
+ projectconfigurationaspects.h \
+ treescanner.h
SOURCES += projectexplorer.cpp \
abi.cpp \
abiwidget.cpp \
+ addrunconfigdialog.cpp \
ansifilterparser.cpp \
buildinfo.cpp \
clangparser.cpp \
@@ -170,6 +175,8 @@ SOURCES += projectexplorer.cpp \
environmentaspect.cpp \
environmentaspectwidget.cpp \
extraabi.cpp \
+ fileinsessionfinder.cpp \
+ filterkitaspectsdialog.cpp \
gcctoolchain.cpp \
importwidget.cpp \
projectconfigurationmodel.cpp \
@@ -184,9 +191,7 @@ SOURCES += projectexplorer.cpp \
targetsetupwidget.cpp \
kit.cpp \
kitchooser.cpp \
- kitconfigwidget.cpp \
kitinformation.cpp \
- kitinformationconfigwidget.cpp \
kitmanager.cpp \
kitmanagerconfigwidget.cpp \
kitmodel.cpp \
@@ -224,6 +229,7 @@ SOURCES += projectexplorer.cpp \
editorconfiguration.cpp \
editorsettingspropertiespage.cpp \
runconfiguration.cpp \
+ runcontrol.cpp \
applicationlauncher.cpp \
runsettingspropertiespage.cpp \
projecttreewidget.cpp \
@@ -298,9 +304,11 @@ SOURCES += projectexplorer.cpp \
customexecutablerunconfiguration.cpp \
projectmacro.cpp \
makestep.cpp \
- projectconfigurationaspects.cpp
+ parseissuesdialog.cpp \
+ projectconfigurationaspects.cpp \
+ treescanner.cpp
-FORMS += processstep.ui \
+FORMS += \
editorsettingspropertiespage.ui \
sessiondialog.ui \
projectwizardpage.ui \
@@ -344,3 +352,7 @@ journald {
RESOURCES += projectexplorer.qrc
DEFINES += PROJECTEXPLORER_LIBRARY
+
+!isEmpty(PROJECT_USER_FILE_EXTENSION) {
+ DEFINES += PROJECT_USER_FILE_EXTENSION=$${PROJECT_USER_FILE_EXTENSION}
+}
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index 5836c06c45..395c1cced9 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -24,6 +24,7 @@ Project {
"abi.cpp", "abi.h",
"abiwidget.cpp", "abiwidget.h",
"abstractprocessstep.cpp", "abstractprocessstep.h",
+ "addrunconfigdialog.cpp", "addrunconfigdialog.h",
"allprojectsfilter.cpp", "allprojectsfilter.h",
"allprojectsfind.cpp", "allprojectsfind.h",
"ansifilterparser.cpp", "ansifilterparser.h",
@@ -69,6 +70,8 @@ Project {
"expanddata.cpp", "expanddata.h",
"extraabi.cpp", "extraabi.h",
"extracompiler.cpp", "extracompiler.h",
+ "fileinsessionfinder.cpp", "fileinsessionfinder.h",
+ "filterkitaspectsdialog.cpp", "filterkitaspectsdialog.h",
"foldernavigationwidget.cpp", "foldernavigationwidget.h",
"gccparser.cpp", "gccparser.h",
"gcctoolchain.cpp", "gcctoolchain.h",
@@ -81,10 +84,8 @@ Project {
"itaskhandler.h",
"kit.cpp", "kit.h",
"kitchooser.cpp", "kitchooser.h",
- "kitconfigwidget.cpp", "kitconfigwidget.h",
"kitfeatureprovider.h",
"kitinformation.cpp", "kitinformation.h",
- "kitinformationconfigwidget.cpp", "kitinformationconfigwidget.h",
"kitmanager.cpp", "kitmanager.h",
"kitmanagerconfigwidget.cpp", "kitmanagerconfigwidget.h",
"kitmodel.cpp", "kitmodel.h",
@@ -98,8 +99,9 @@ Project {
"namedwidget.cpp", "namedwidget.h",
"osparser.cpp", "osparser.h",
"panelswidget.cpp", "panelswidget.h",
+ "parseissuesdialog.cpp", "parseissuesdialog.h",
"processparameters.cpp", "processparameters.h",
- "processstep.cpp", "processstep.h", "processstep.ui",
+ "processstep.cpp", "processstep.h",
"project.cpp", "project.h",
"projectconfiguration.cpp", "projectconfiguration.h",
"projectconfigurationaspects.cpp", "projectconfigurationaspects.h",
@@ -127,6 +129,7 @@ Project {
"projectwizardpage.cpp", "projectwizardpage.h", "projectwizardpage.ui",
"removetaskhandler.cpp", "removetaskhandler.h",
"runconfiguration.cpp", "runconfiguration.h",
+ "runcontrol.cpp", "runcontrol.h",
"runconfigurationaspects.cpp", "runconfigurationaspects.h",
"runsettingspropertiespage.cpp", "runsettingspropertiespage.h",
"selectablefilesmodel.cpp", "selectablefilesmodel.h",
@@ -151,6 +154,7 @@ Project {
"toolchainmanager.cpp", "toolchainmanager.h",
"toolchainoptionspage.cpp", "toolchainoptionspage.h",
"toolchainsettingsaccessor.cpp", "toolchainsettingsaccessor.h",
+ "treescanner.cpp", "treescanner.h",
"userfileaccessor.cpp", "userfileaccessor.h",
"vcsannotatetaskhandler.cpp", "vcsannotatetaskhandler.h",
"waitforstopdialog.cpp", "waitforstopdialog.h",
diff --git a/src/plugins/projectexplorer/projectexplorer.qrc b/src/plugins/projectexplorer/projectexplorer.qrc
index 9eb42e7ebc..29bda00509 100644
--- a/src/plugins/projectexplorer/projectexplorer.qrc
+++ b/src/plugins/projectexplorer/projectexplorer.qrc
@@ -73,6 +73,8 @@
<file>images/fileoverlay_cpp@2x.png</file>
<file>images/fileoverlay_h.png</file>
<file>images/fileoverlay_h@2x.png</file>
+ <file>images/fileoverlay_py.png</file>
+ <file>images/fileoverlay_py@2x.png</file>
<file>images/fileoverlay_unknown.png</file>
<file>images/fileoverlay_unknown@2x.png</file>
<file>images/cancelbuild_overlay.png</file>
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 34e218b149..ad2d9e049e 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -124,6 +124,7 @@ const char DEVICE_SETTINGS_PAGE_ID[] = "AA.Device Settings";
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";
// Wizard categories
const char QT_PROJECT_WIZARD_CATEGORY[] = "H.Project";
@@ -185,6 +186,7 @@ const char VAR_CURRENTBUILD_NAME[] = "CurrentBuild:Name";
const char VAR_CURRENTBUILD_TYPE[] = "CurrentBuild:Type";
const char VAR_CURRENTBUILD_ENV[] = "CurrentBuild:Env";
const char VAR_CURRENTRUN_NAME[] = "CurrentRun:Name";
+const char VAR_CURRENTRUN_WORKINGDIR[] = "CurrentRun:WorkingDir";
// JsonWizard:
const char PAGE_ID_PREFIX[] = "PE.Wizard.Page.";
@@ -209,9 +211,11 @@ const char FILEOVERLAY_QRC[]=":/projectexplorer/images/fileoverlay_qrc.png";
const char FILEOVERLAY_CPP[]=":/projectexplorer/images/fileoverlay_cpp.png";
const char FILEOVERLAY_H[]=":/projectexplorer/images/fileoverlay_h.png";
const char FILEOVERLAY_SCXML[]=":/projectexplorer/images/fileoverlay_scxml.png";
+const char FILEOVERLAY_PY[]=":/projectexplorer/images/fileoverlay_py.png";
const char FILEOVERLAY_UNKNOWN[]=":/projectexplorer/images/fileoverlay_unknown.png";
const char ADD_FILES_DIALOG_FILTER_HISTORY_KEY[] = "ProjectExplorer.AddFilesFilterKey";
+const char PROJECT_ROOT_PATH_KEY[] = "ProjectExplorer.Project.RootPath";
} // namespace Constants
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h
index 13277e9736..85e9a77abe 100644
--- a/src/plugins/projectexplorer/projectexplorersettings.h
+++ b/src/plugins/projectexplorer/projectexplorersettings.h
@@ -33,6 +33,8 @@
namespace ProjectExplorer {
namespace Internal {
+enum class TerminalMode { On, Off, Smart };
+
class ProjectExplorerSettings
{
public:
@@ -41,20 +43,15 @@ public:
bool buildBeforeDeploy = true;
bool deployBeforeRun = true;
bool saveBeforeBuild = false;
- bool showCompilerOutput = false;
- bool showRunOutput = true;
- bool showDebugOutput = false;
- bool cleanOldAppOutput = false;
- bool mergeStdErrAndStdOut = false;
- bool wrapAppOutput = true;
bool useJom = true;
bool autorestoreLastSession = false; // This option is set in the Session Manager!
bool prompToStopRunControl = false;
bool automaticallyCreateRunConfigurations = true;
bool addLibraryPathsToRunEnv = true;
- int maxAppOutputChars = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
- int maxBuildOutputChars = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
+ bool closeSourceFilesWithProject = true;
+ bool clearIssuesOnRebuild = true;
StopBeforeBuild stopBeforeBuild = StopBeforeBuild::StopNone;
+ TerminalMode terminalMode = TerminalMode::Smart;
QString buildDirectoryTemplate;
// Add a UUid which is used to identify the development environment.
@@ -68,23 +65,37 @@ inline bool operator==(const ProjectExplorerSettings &p1, const ProjectExplorerS
return p1.buildBeforeDeploy == p2.buildBeforeDeploy
&& p1.deployBeforeRun == p2.deployBeforeRun
&& p1.saveBeforeBuild == p2.saveBeforeBuild
- && p1.showCompilerOutput == p2.showCompilerOutput
- && p1.showRunOutput == p2.showRunOutput
- && p1.showDebugOutput == p2.showDebugOutput
- && p1.cleanOldAppOutput == p2.cleanOldAppOutput
- && p1.mergeStdErrAndStdOut == p2.mergeStdErrAndStdOut
- && p1.wrapAppOutput == p2.wrapAppOutput
&& p1.useJom == p2.useJom
&& p1.autorestoreLastSession == p2.autorestoreLastSession
&& p1.prompToStopRunControl == p2.prompToStopRunControl
&& p1.automaticallyCreateRunConfigurations == p2.automaticallyCreateRunConfigurations
&& p1.addLibraryPathsToRunEnv == p2.addLibraryPathsToRunEnv
- && p1.maxAppOutputChars == p2.maxAppOutputChars
- && p1.maxBuildOutputChars == p2.maxBuildOutputChars
&& p1.environmentId == p2.environmentId
&& p1.stopBeforeBuild == p2.stopBeforeBuild
+ && p1.terminalMode == p2.terminalMode
+ && p1.closeSourceFilesWithProject == p2.closeSourceFilesWithProject
+ && p1.clearIssuesOnRebuild == p2.clearIssuesOnRebuild
&& p1.buildDirectoryTemplate == p2.buildDirectoryTemplate;
}
+class AppOutputSettings
+{
+public:
+ bool popUpForRunOutput = true;
+ bool popUpForDebugOutput = false;
+ bool cleanOldOutput = false;
+ bool mergeChannels = false;
+ bool wrapOutput = false;
+ int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
+};
+
+class CompileOutputSettings
+{
+public:
+ bool popUp = false;
+ bool wrapOutput = false;
+ int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
+};
+
} // namespace ProjectExplorer
} // namespace Internal
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettingspage.cpp
index d7e506021c..73f622aedf 100644
--- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp
+++ b/src/plugins/projectexplorer/projectexplorersettingspage.cpp
@@ -57,15 +57,14 @@ public:
bool useProjectsDirectory();
void setUseProjectsDirectory(bool v);
- QString buildDirectoryTemplate() const;
- void setBuildDirectoryTemplate(const QString &bd);
-
private:
void slotDirectoryButtonGroupChanged();
void resetBuildDirectoryTemplate();
void updateBuildDirectoryResetButton();
void setJomVisible(bool);
+ QString buildDirectoryTemplate() const;
+ void setBuildDirectoryTemplate(const QString &bd);
Ui::ProjectExplorerSettingsPageUi m_ui;
mutable ProjectExplorerSettings m_settings;
@@ -79,7 +78,7 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget(QWidget *parent) :
m_ui.directoryButtonGroup->setId(m_ui.currentDirectoryRadioButton, UseCurrentDirectory);
m_ui.directoryButtonGroup->setId(m_ui.directoryRadioButton, UseProjectDirectory);
- connect(m_ui.directoryButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked),
+ connect(m_ui.directoryButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked),
this, &ProjectExplorerSettingsWidget::slotDirectoryButtonGroupChanged);
connect(m_ui.buildDirectoryResetButton, &QAbstractButton::clicked,
this, &ProjectExplorerSettingsWidget::resetBuildDirectoryTemplate);
@@ -101,19 +100,15 @@ ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const
m_settings.buildBeforeDeploy = m_ui.buildProjectBeforeDeployCheckBox->isChecked();
m_settings.deployBeforeRun = m_ui.deployProjectBeforeRunCheckBox->isChecked();
m_settings.saveBeforeBuild = m_ui.saveAllFilesCheckBox->isChecked();
- m_settings.showCompilerOutput = m_ui.showCompileOutputCheckBox->isChecked();
- m_settings.showRunOutput = m_ui.showRunOutputCheckBox->isChecked();
- m_settings.showDebugOutput = m_ui.showDebugOutputCheckBox->isChecked();
- m_settings.cleanOldAppOutput = m_ui.cleanOldAppOutputCheckBox->isChecked();
- m_settings.mergeStdErrAndStdOut = m_ui.mergeStdErrAndStdOutCheckBox->isChecked();
- m_settings.wrapAppOutput = m_ui.wrapAppOutputCheckBox->isChecked();
m_settings.useJom = m_ui.jomCheckbox->isChecked();
m_settings.addLibraryPathsToRunEnv = m_ui.addLibraryPathsToRunEnvCheckBox->isChecked();
m_settings.prompToStopRunControl = m_ui.promptToStopRunControlCheckBox->isChecked();
m_settings.automaticallyCreateRunConfigurations = m_ui.automaticallyCreateRunConfiguration->isChecked();
- m_settings.maxAppOutputChars = m_ui.maxAppOutputBox->value();
- m_settings.maxBuildOutputChars = m_ui.maxBuildOutputBox->value();
m_settings.stopBeforeBuild = static_cast<ProjectExplorerSettings::StopBeforeBuild>(m_ui.stopBeforeBuildComboBox->currentIndex());
+ m_settings.terminalMode = static_cast<TerminalMode>(m_ui.terminalModeComboBox->currentIndex());
+ m_settings.closeSourceFilesWithProject = m_ui.closeSourceFilesCheckBox->isChecked();
+ m_settings.clearIssuesOnRebuild = m_ui.clearIssuesCheckBox->isChecked();
+ m_settings.buildDirectoryTemplate = buildDirectoryTemplate();
return m_settings;
}
@@ -123,19 +118,15 @@ void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &
m_ui.buildProjectBeforeDeployCheckBox->setChecked(m_settings.buildBeforeDeploy);
m_ui.deployProjectBeforeRunCheckBox->setChecked(m_settings.deployBeforeRun);
m_ui.saveAllFilesCheckBox->setChecked(m_settings.saveBeforeBuild);
- m_ui.showCompileOutputCheckBox->setChecked(m_settings.showCompilerOutput);
- m_ui.showRunOutputCheckBox->setChecked(m_settings.showRunOutput);
- m_ui.showDebugOutputCheckBox->setChecked(m_settings.showDebugOutput);
- m_ui.cleanOldAppOutputCheckBox->setChecked(m_settings.cleanOldAppOutput);
- m_ui.mergeStdErrAndStdOutCheckBox->setChecked(m_settings.mergeStdErrAndStdOut);
- m_ui.wrapAppOutputCheckBox->setChecked(m_settings.wrapAppOutput);
m_ui.jomCheckbox->setChecked(m_settings.useJom);
m_ui.addLibraryPathsToRunEnvCheckBox->setChecked(m_settings.addLibraryPathsToRunEnv);
m_ui.promptToStopRunControlCheckBox->setChecked(m_settings.prompToStopRunControl);
m_ui.automaticallyCreateRunConfiguration->setChecked(m_settings.automaticallyCreateRunConfigurations);
- m_ui.maxAppOutputBox->setValue(m_settings.maxAppOutputChars);
- m_ui.maxBuildOutputBox->setValue(m_settings.maxBuildOutputChars);
m_ui.stopBeforeBuildComboBox->setCurrentIndex(static_cast<int>(m_settings.stopBeforeBuild));
+ m_ui.terminalModeComboBox->setCurrentIndex(static_cast<int>(m_settings.terminalMode));
+ m_ui.closeSourceFilesCheckBox->setChecked(m_settings.closeSourceFilesWithProject);
+ m_ui.clearIssuesCheckBox->setChecked(m_settings.clearIssuesOnRebuild);
+ setBuildDirectoryTemplate(pes.buildDirectoryTemplate);
}
QString ProjectExplorerSettingsWidget::projectsDirectory() const
@@ -205,7 +196,6 @@ QWidget *ProjectExplorerSettingsPage::widget()
m_widget->setSettings(ProjectExplorerPlugin::projectExplorerSettings());
m_widget->setProjectsDirectory(Core::DocumentManager::projectsDirectory().toString());
m_widget->setUseProjectsDirectory(Core::DocumentManager::useProjectsDirectory());
- m_widget->setBuildDirectoryTemplate(ProjectExplorerPlugin::buildDirectoryTemplate());
}
return m_widget;
}
@@ -215,9 +205,8 @@ void ProjectExplorerSettingsPage::apply()
if (m_widget) {
ProjectExplorerPlugin::setProjectExplorerSettings(m_widget->settings());
Core::DocumentManager::setProjectsDirectory(
- Utils::FileName::fromString(m_widget->projectsDirectory()));
+ Utils::FilePath::fromString(m_widget->projectsDirectory()));
Core::DocumentManager::setUseProjectsDirectory(m_widget->useProjectsDirectory());
- ProjectExplorerPlugin::setBuildDirectoryTemplate(m_widget->buildDirectoryTemplate());
}
}
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.ui b/src/plugins/projectexplorer/projectexplorersettingspage.ui
index 7fecbfb38e..448ad3655b 100644
--- a/src/plugins/projectexplorer/projectexplorersettingspage.ui
+++ b/src/plugins/projectexplorer/projectexplorersettingspage.ui
@@ -6,11 +6,11 @@
<rect>
<x>0</x>
<y>0</y>
- <width>831</width>
- <height>520</height>
+ <width>994</width>
+ <height>808</height>
</rect>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="directoryGroupBox">
<property name="title">
@@ -47,126 +47,56 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="buildAndRunGroupBox">
+ <widget class="QGroupBox" name="closeProjectGroupBox">
<property name="title">
- <string>Build and Run</string>
+ <string>Closing Projects</string>
</property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QCheckBox" name="saveAllFilesCheckBox">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="closeSourceFilesCheckBox">
<property name="text">
- <string>Save all files before build</string>
+ <string>Close source files along with project</string>
</property>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QCheckBox" name="cleanOldAppOutputCheckBox">
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="buildAndRunGroupBox">
+ <property name="title">
+ <string>Build and Run</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="saveAllFilesCheckBox">
<property name="text">
- <string>Clear old application output on a new run</string>
+ <string>Save all files before build</string>
</property>
</widget>
</item>
- <item row="1" column="0">
+ <item>
<widget class="QCheckBox" name="buildProjectBeforeDeployCheckBox">
<property name="text">
<string>Always build project before deploying it</string>
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QCheckBox" name="mergeStdErrAndStdOutCheckBox">
- <property name="toolTip">
- <string>Enabling this option ensures that the order of interleaved messages from stdout and stderr is preserved, at the cost of disabling highlighting of stderr.</string>
- </property>
- <property name="text">
- <string>Merge stderr and stdout</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
+ <item>
<widget class="QCheckBox" name="deployProjectBeforeRunCheckBox">
<property name="text">
<string>Always deploy project before running it</string>
</property>
</widget>
</item>
- <item row="2" column="1">
- <widget class="QCheckBox" name="wrapAppOutputCheckBox">
- <property name="text">
- <string>Word-wrap application output</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
+ <item>
<widget class="QCheckBox" name="addLibraryPathsToRunEnvCheckBox">
<property name="text">
<string>Add linker library search paths to run environment</string>
</property>
</widget>
</item>
- <item row="3" column="0">
- <widget class="QCheckBox" name="showCompileOutputCheckBox">
- <property name="text">
- <string>Open Compile Output pane when building</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QWidget" name="widget" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <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="QLabel" name="limitBuildOutputLabel">
- <property name="text">
- <string>Limit build output to</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="maxBuildOutputBox">
- <property name="minimum">
- <number>5000</number>
- </property>
- <property name="maximum">
- <number>100000000</number>
- </property>
- <property name="singleStep">
- <number>5000</number>
- </property>
- <property name="value">
- <number>10000000</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="limitBuildOutputLabel_2">
- <property name="text">
- <string>characters</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QCheckBox" name="showRunOutputCheckBox">
- <property name="text">
- <string>Open Application Output pane on output when running</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
+ <item>
<widget class="QWidget" name="widget_1" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
@@ -181,47 +111,10 @@
<property name="bottomMargin">
<number>0</number>
</property>
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Limit application output to</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="maxAppOutputBox">
- <property name="minimum">
- <number>5000</number>
- </property>
- <property name="maximum">
- <number>100000000</number>
- </property>
- <property name="singleStep">
- <number>5000</number>
- </property>
- <property name="value">
- <number>10000000</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>characters</string>
- </property>
- </widget>
- </item>
</layout>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QCheckBox" name="showDebugOutputCheckBox">
- <property name="text">
- <string>Open Application Output pane on output when debugging</string>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
+ <item>
<widget class="QCheckBox" name="promptToStopRunControlCheckBox">
<property name="toolTip">
<string>Asks before terminating the running application in response to clicking the stop button in Application Output.</string>
@@ -231,7 +124,7 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item>
<widget class="QCheckBox" name="automaticallyCreateRunConfiguration">
<property name="toolTip">
<string>Creates suitable run configurations automatically when setting up a new kit.</string>
@@ -241,55 +134,109 @@
</property>
</widget>
</item>
- <item row="8" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
+ <item>
+ <widget class="QCheckBox" name="clearIssuesCheckBox">
+ <property name="text">
+ <string>Clear issues list on new build</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
<widget class="QLabel" name="labelStopBeforeBuild">
<property name="text">
<string>Stop applications before building:</string>
</property>
</widget>
</item>
- <item>
- <widget class="QComboBox" name="stopBeforeBuildComboBox">
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <property name="text">
- <string>None</string>
- </property>
+ <widget class="QComboBox" name="stopBeforeBuildComboBox">
+ <item>
+ <property name="text">
+ <string>None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Same Project</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>All</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Same Build Directory</string>
+ </property>
+ </item>
+ </widget>
</item>
<item>
- <property name="text">
- <string>Same Project</string>
- </property>
+ <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>
+ <item row="1" column="0">
+ <widget class="QLabel" name="terminalModeLabel">
+ <property name="text">
+ <string>Default for &quot;Run in terminal&quot;:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
- <property name="text">
- <string>All</string>
- </property>
+ <widget class="QComboBox" name="terminalModeComboBox">
+ <item>
+ <property name="text">
+ <string>Enabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Deduced From Project</string>
+ </property>
+ </item>
+ </widget>
</item>
<item>
- <property name="text">
- <string>Same Build Directory</string>
- </property>
+ <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>
- </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>
+ </layout>
</item>
</layout>
</item>
- <item row="9" column="0" colspan="2">
+ <item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
@@ -322,7 +269,7 @@
</item>
</layout>
</item>
- <item row="10" column="0" colspan="2">
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>12</number>
@@ -347,17 +294,14 @@
</layout>
</item>
</layout>
+ <zorder>widget_1</zorder>
+ <zorder>automaticallyCreateRunConfiguration</zorder>
<zorder>saveAllFilesCheckBox</zorder>
<zorder>buildProjectBeforeDeployCheckBox</zorder>
<zorder>deployProjectBeforeRunCheckBox</zorder>
- <zorder>showCompileOutputCheckBox</zorder>
- <zorder>cleanOldAppOutputCheckBox</zorder>
- <zorder>mergeStdErrAndStdOutCheckBox</zorder>
- <zorder>wrapAppOutputCheckBox</zorder>
- <zorder>widget</zorder>
<zorder>promptToStopRunControlCheckBox</zorder>
- <zorder>showRunOutputCheckBox</zorder>
- <zorder>showDebugOutputCheckBox</zorder>
+ <zorder>addLibraryPathsToRunEnvCheckBox</zorder>
+ <zorder>clearIssuesCheckBox</zorder>
</widget>
</item>
<item>
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp
index 5dab7bbf99..33be4cdcfe 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.cpp
+++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp
@@ -256,7 +256,7 @@ void ProjectFileWizardExtension::applyCodeStyle(GeneratedFile *file) const
Indenter *indenter = nullptr;
if (factory) {
indenter = factory->createIndenter(&doc);
- indenter->setFileName(Utils::FileName::fromString(file->path()));
+ indenter->setFileName(Utils::FilePath::fromString(file->path()));
}
if (!indenter)
indenter = new NormalIndenter(&doc);
diff --git a/src/plugins/projectexplorer/projectimporter.cpp b/src/plugins/projectexplorer/projectimporter.cpp
index 174f6a7472..4d32dba9d6 100644
--- a/src/plugins/projectexplorer/projectimporter.cpp
+++ b/src/plugins/projectexplorer/projectimporter.cpp
@@ -71,9 +71,9 @@ static bool hasOtherUsers(Core::Id id, const QVariant &v, Kit *k)
});
}
-ProjectImporter::ProjectImporter(const Utils::FileName &path) : m_projectPath(path)
+ProjectImporter::ProjectImporter(const Utils::FilePath &path) : m_projectPath(path)
{
- useTemporaryKitInformation(ToolChainKitInformation::id(),
+ useTemporaryKitAspect(ToolChainKitAspect::id(),
[this](Kit *k, const QVariantList &vl) { cleanupTemporaryToolChains(k, vl); },
[this](Kit *k, const QVariantList &vl) { persistTemporaryToolChains(k, vl); });
}
@@ -84,7 +84,7 @@ ProjectImporter::~ProjectImporter()
removeProject(k);
}
-const QList<BuildInfo> ProjectImporter::import(const Utils::FileName &importPath, bool silent)
+const QList<BuildInfo> ProjectImporter::import(const Utils::FilePath &importPath, bool silent)
{
QList<BuildInfo> result;
@@ -97,12 +97,20 @@ const QList<BuildInfo> ProjectImporter::import(const Utils::FileName &importPath
return result;
}
- const Utils::FileName absoluteImportPath = Utils::FileName::fromString(fi.absoluteFilePath());
+ const Utils::FilePath absoluteImportPath = Utils::FilePath::fromString(fi.absoluteFilePath());
+ const auto handleFailure = [this, importPath, silent] {
+ if (silent)
+ return;
+ QMessageBox::critical(Core::ICore::mainWindow(), tr("No Build Found"),
+ tr("No build found in %1 matching project %2.")
+ .arg(importPath.toUserOutput(), projectFilePath().toUserOutput()));
+ };
qCDebug(log) << "Examining directory" << absoluteImportPath.toString();
QList<void *> dataList = examineDirectory(absoluteImportPath);
if (dataList.isEmpty()) {
qCDebug(log) << "Nothing to import found in" << absoluteImportPath.toString();
+ handleFailure();
return result;
}
@@ -141,11 +149,8 @@ const QList<BuildInfo> ProjectImporter::import(const Utils::FileName &importPath
deleteDirectoryData(dd);
dataList.clear();
- if (result.isEmpty() && !silent)
- QMessageBox::critical(Core::ICore::mainWindow(),
- QCoreApplication::translate("ProjectExplorer::ProjectImporter", "No Build Found"),
- QCoreApplication::translate("ProjectExplorer::ProjectImporter", "No build found in %1 matching project %2.")
- .arg(importPath.toUserOutput()).arg(projectFilePath().toUserOutput()));
+ if (result.isEmpty())
+ handleFailure();
return result;
}
@@ -167,7 +172,7 @@ Target *ProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
return t;
if (pickedFallback)
continue;
- if (DeviceTypeKitInformation::deviceTypeId(t->kit()) == Constants::DESKTOP_DEVICE_TYPE) {
+ if (DeviceTypeKitAspect::deviceTypeId(t->kit()) == Constants::DESKTOP_DEVICE_TYPE) {
activeTarget = t;
pickedFallback = true;
}
@@ -286,27 +291,18 @@ bool ProjectImporter::isTemporaryKit(Kit *k) const
Kit *ProjectImporter::createTemporaryKit(const KitSetupFunction &setup) const
{
- auto k = std::make_unique<Kit>();
- Kit *kptr = k.get();
UpdateGuard guard(*this);
- {
- KitGuard kitGuard(kptr);
- k->setUnexpandedDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectImporter", "Imported Kit"));;
-
- // Set up values:
- foreach (KitInformation *ki, KitManager::kitInformation())
- ki->setup(kptr);
-
- setup(kptr);
-
- foreach (KitInformation *ki, KitManager::kitInformation())
- ki->fix(kptr);
-
- markKitAsTemporary(kptr);
- addProject(kptr);
- } // ~KitGuard, sending kitUpdated
- KitManager::registerKit(std::move(k)); // potentially adds kits to other targetsetuppages
- return kptr;
+ const auto init = [&](Kit *k) {
+ KitGuard kitGuard(k);
+ k->setUnexpandedDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectImporter",
+ "Imported Kit"));
+ k->setup();
+ setup(k);
+ k->fix();
+ markKitAsTemporary(k);
+ addProject(k);
+ }; // ~KitGuard, sending kitUpdated
+ return KitManager::registerKit(init); // potentially adds kits to other targetsetuppages
}
bool ProjectImporter::findTemporaryHandler(Core::Id id) const
@@ -326,7 +322,7 @@ void ProjectImporter::cleanupTemporaryToolChains(Kit *k, const QVariantList &vl)
ToolChain *tc = toolChainFromVariant(v);
QTC_ASSERT(tc, continue);
ToolChainManager::deregisterToolChain(tc);
- ToolChainKitInformation::setToolChain(k, nullptr);
+ ToolChainKitAspect::setToolChain(k, nullptr);
}
}
@@ -335,13 +331,13 @@ void ProjectImporter::persistTemporaryToolChains(Kit *k, const QVariantList &vl)
for (const QVariant &v : vl) {
ToolChain *tmpTc = toolChainFromVariant(v);
QTC_ASSERT(tmpTc, continue);
- ToolChain *actualTc = ToolChainKitInformation::toolChain(k, tmpTc->language());
+ ToolChain *actualTc = ToolChainKitAspect::toolChain(k, tmpTc->language());
if (tmpTc && actualTc != tmpTc)
ToolChainManager::deregisterToolChain(tmpTc);
}
}
-void ProjectImporter::useTemporaryKitInformation(Core::Id id,
+void ProjectImporter::useTemporaryKitAspect(Core::Id id,
ProjectImporter::CleanupFunction cleanup,
ProjectImporter::PersistFunction persist)
{
@@ -371,7 +367,7 @@ bool ProjectImporter::hasKitWithTemporaryData(Core::Id id, const QVariant &data)
}
static ProjectImporter::ToolChainData
-createToolChains(const Utils::FileName &toolChainPath, const Core::Id &language)
+createToolChains(const Utils::FilePath &toolChainPath, const Core::Id &language)
{
ProjectImporter::ToolChainData data;
@@ -391,7 +387,7 @@ createToolChains(const Utils::FileName &toolChainPath, const Core::Id &language)
}
ProjectImporter::ToolChainData
-ProjectImporter::findOrCreateToolChains(const Utils::FileName &toolChainPath,
+ProjectImporter::findOrCreateToolChains(const Utils::FilePath &toolChainPath,
const Core::Id &language) const
{
ToolChainData result;
@@ -400,7 +396,7 @@ ProjectImporter::findOrCreateToolChains(const Utils::FileName &toolChainPath,
});
for (const ToolChain *tc : result.tcs) {
const QByteArray tcId = tc->id();
- result.areTemporary = result.areTemporary ? true : hasKitWithTemporaryData(ToolChainKitInformation::id(), tcId);
+ result.areTemporary = result.areTemporary ? true : hasKitWithTemporaryData(ToolChainKitAspect::id(), tcId);
}
if (!result.tcs.isEmpty())
return result;
diff --git a/src/plugins/projectexplorer/projectimporter.h b/src/plugins/projectexplorer/projectimporter.h
index c7df542a7a..f1cf482607 100644
--- a/src/plugins/projectexplorer/projectimporter.h
+++ b/src/plugins/projectexplorer/projectimporter.h
@@ -44,19 +44,20 @@ class ToolChain;
// Documentation inside.
class PROJECTEXPLORER_EXPORT ProjectImporter : public QObject
{
+ Q_OBJECT
public:
struct ToolChainData {
QList<ToolChain *> tcs;
bool areTemporary = false;
};
- ProjectImporter(const Utils::FileName &path);
+ ProjectImporter(const Utils::FilePath &path);
~ProjectImporter() override;
- const Utils::FileName projectFilePath() const { return m_projectPath; }
- const Utils::FileName projectDirectory() const { return m_projectPath.parentDir(); }
+ const Utils::FilePath projectFilePath() const { return m_projectPath; }
+ const Utils::FilePath projectDirectory() const { return m_projectPath.parentDir(); }
- virtual const QList<BuildInfo> import(const Utils::FileName &importPath, bool silent = false);
+ virtual const QList<BuildInfo> import(const Utils::FilePath &importPath, bool silent = false);
virtual QStringList importCandidates() = 0;
virtual Target *preferredTarget(const QList<Target *> &possibleTargets);
@@ -87,7 +88,7 @@ protected:
};
// importPath is an existing directory at this point!
- virtual QList<void *> examineDirectory(const Utils::FileName &importPath) const = 0;
+ virtual QList<void *> examineDirectory(const Utils::FilePath &importPath) const = 0;
// will get one of the results from examineDirectory
virtual bool matchKit(void *directoryData, const Kit *k) const = 0;
// will get one of the results from examineDirectory
@@ -103,13 +104,13 @@ protected:
// Handle temporary additions to Kits (Qt Versions, ToolChains, etc.)
using CleanupFunction = std::function<void(Kit *, const QVariantList &)>;
using PersistFunction = std::function<void(Kit *, const QVariantList &)>;
- void useTemporaryKitInformation(Core::Id id,
+ void useTemporaryKitAspect(Core::Id id,
CleanupFunction cleanup, PersistFunction persist);
void addTemporaryData(Core::Id id, const QVariant &cleanupData, Kit *k) const;
// Does *any* kit feature the requested data yet?
bool hasKitWithTemporaryData(Core::Id id, const QVariant &data) const;
- ToolChainData findOrCreateToolChains(const Utils::FileName &toolChainPath, const Core::Id &language) const;
+ ToolChainData findOrCreateToolChains(const Utils::FilePath &toolChainPath, const Core::Id &language) const;
private:
void markKitAsTemporary(Kit *k) const;
@@ -118,7 +119,7 @@ private:
void cleanupTemporaryToolChains(ProjectExplorer::Kit *k, const QVariantList &vl);
void persistTemporaryToolChains(ProjectExplorer::Kit *k, const QVariantList &vl);
- const Utils::FileName m_projectPath;
+ const Utils::FilePath m_projectPath;
mutable bool m_isUpdating = false;
class TemporaryInformationHandler {
diff --git a/src/plugins/projectexplorer/projectmanager.h b/src/plugins/projectexplorer/projectmanager.h
index e504b1968e..c0f91cebc7 100644
--- a/src/plugins/projectexplorer/projectmanager.h
+++ b/src/plugins/projectexplorer/projectmanager.h
@@ -32,7 +32,7 @@
#include <functional>
namespace Utils {
-class FileName;
+class FilePath;
class MimeType;
} // Utils
@@ -44,19 +44,19 @@ class PROJECTEXPLORER_EXPORT ProjectManager
{
public:
static bool canOpenProjectForMimeType(const Utils::MimeType &mt);
- static Project *openProject(const Utils::MimeType &mt, const Utils::FileName &fileName);
+ static Project *openProject(const Utils::MimeType &mt, const Utils::FilePath &fileName);
template <typename T>
static void registerProjectType(const QString &mimeType)
{
- ProjectManager::registerProjectCreator(mimeType, [](const Utils::FileName &fileName) {
+ ProjectManager::registerProjectCreator(mimeType, [](const Utils::FilePath &fileName) {
return new T(fileName);
});
}
private:
static void registerProjectCreator(const QString &mimeType,
- const std::function<Project *(const Utils::FileName &)> &);
+ const std::function<Project *(const Utils::FilePath &)> &);
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index d69d9aad6a..c3df0688ae 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -32,17 +32,31 @@
#include "session.h"
#include "target.h"
+#include <coreplugin/documentmanager.h>
#include <coreplugin/fileiconprovider.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/iversioncontrol.h>
+#include <coreplugin/vcsmanager.h>
#include <utils/utilsicons.h>
#include <utils/algorithm.h>
#include <utils/dropsupport.h>
+#include <utils/pathchooser.h>
#include <utils/stringutils.h>
#include <utils/theme/theme.h>
+#include <QButtonGroup>
+#include <QDialog>
+#include <QDialogButtonBox>
#include <QFileInfo>
#include <QFont>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QMessageBox>
#include <QMimeData>
#include <QLoggingCategory>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QVBoxLayout>
#include <functional>
@@ -188,6 +202,8 @@ Qt::ItemFlags FlatModel::flags(const QModelIndex &index) const
// either folder or file node
if (node->supportsAction(Rename, node))
f = f | Qt::ItemIsEditable;
+ } else if (node->supportsAction(ProjectAction::AddExistingFile, node)) {
+ f |= Qt::ItemIsDropEnabled;
}
}
return f;
@@ -203,8 +219,8 @@ bool FlatModel::setData(const QModelIndex &index, const QVariant &value, int rol
Node *node = nodeForIndex(index);
QTC_ASSERT(node, return false);
- Utils::FileName orgFilePath = node->filePath();
- Utils::FileName newFilePath = orgFilePath.parentDir().appendPath(value.toString());
+ const Utils::FilePath orgFilePath = node->filePath();
+ const Utils::FilePath newFilePath = orgFilePath.parentDir().pathAppended(value.toString());
ProjectExplorerPlugin::renameFile(node, newFilePath.toString());
emit renamed(orgFilePath, newFilePath);
@@ -245,7 +261,7 @@ void FlatModel::addOrRebuildProjectModel(Project *project)
if (container->childCount() == 0) {
auto projectFileNode = std::make_unique<FileNode>(project->projectFilePath(),
- FileType::Project, false);
+ FileType::Project);
seen.insert(projectFileNode.get());
container->appendChild(new WrapperNode(projectFileNode.get()));
project->containerNode()->addNestedNode(std::move(projectFileNode));
@@ -409,7 +425,7 @@ QStringList FlatModel::mimeTypes() const
QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const
{
- auto data = new Utils::DropMimeData;
+ auto data = new DropMimeData;
foreach (const QModelIndex &index, indexes) {
if (Node *node = nodeForIndex(index)) {
if (node->asFileNode())
@@ -420,6 +436,303 @@ QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const
return data;
}
+bool FlatModel::canDropMimeData(const QMimeData *data, Qt::DropAction, int, int,
+ const QModelIndex &) const
+{
+ // For now, we support only drops of Qt Creator file nodes.
+ const auto * const dropData = dynamic_cast<const DropMimeData *>(data);
+ if (!dropData)
+ return false;
+ QTC_ASSERT(!dropData->values().empty(), return false);
+ return dropData->files().size() == dropData->values().size();
+}
+
+enum class DropAction { Copy, CopyWithFiles, Move, MoveWithFiles };
+
+class DropFileDialog : public QDialog
+{
+ Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::Internal::FlatModel)
+public:
+ DropFileDialog(const FilePath &defaultTargetDir)
+ : m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)),
+ m_buttonGroup(new QButtonGroup(this))
+ {
+ setWindowTitle(tr("Choose Drop Action"));
+ const bool offerFileIo = !defaultTargetDir.isEmpty();
+ auto * const layout = new QVBoxLayout(this);
+ layout->addWidget(new QLabel(tr("You just dragged some files from one project node to "
+ "another.\nWhat should Qt Creator do now?"), this));
+ auto * const copyButton = new QRadioButton(this);
+ m_buttonGroup->addButton(copyButton, int(DropAction::Copy));
+ layout->addWidget(copyButton);
+ auto * const moveButton = new QRadioButton(this);
+ m_buttonGroup->addButton(moveButton, int(DropAction::Move));
+ layout->addWidget(moveButton);
+ if (offerFileIo) {
+ copyButton->setText(tr("Copy Only File References"));
+ moveButton->setText(tr("Move Only File References"));
+ auto * const copyWithFilesButton
+ = new QRadioButton(tr("Copy file references and files"), this);
+ m_buttonGroup->addButton(copyWithFilesButton, int(DropAction::CopyWithFiles));
+ layout->addWidget(copyWithFilesButton);
+ auto * const moveWithFilesButton
+ = new QRadioButton(tr("Move file references and files"), this);
+ m_buttonGroup->addButton(moveWithFilesButton, int(DropAction::MoveWithFiles));
+ layout->addWidget(moveWithFilesButton);
+ moveWithFilesButton->setChecked(true);
+ auto * const targetDirLayout = new QHBoxLayout;
+ layout->addLayout(targetDirLayout);
+ targetDirLayout->addWidget(new QLabel(tr("Target directory:"), this));
+ m_targetDirChooser = new PathChooser(this);
+ m_targetDirChooser->setExpectedKind(PathChooser::ExistingDirectory);
+ m_targetDirChooser->setFileName(defaultTargetDir);
+ connect(m_targetDirChooser, &PathChooser::validChanged, this, [this](bool valid) {
+ m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
+ });
+ targetDirLayout->addWidget(m_targetDirChooser);
+ connect(m_buttonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this, [this] {
+ switch (dropAction()) {
+ case DropAction::CopyWithFiles:
+ case DropAction::MoveWithFiles:
+ m_targetDirChooser->setEnabled(true);
+ m_buttonBox->button(QDialogButtonBox::Ok)
+ ->setEnabled(m_targetDirChooser->isValid());
+ break;
+ case DropAction::Copy:
+ case DropAction::Move:
+ m_targetDirChooser->setEnabled(false);
+ m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
+ break;
+ }
+ });
+ } else {
+ copyButton->setText(tr("Copy File References"));
+ moveButton->setText(tr("Move File References"));
+ moveButton->setChecked(true);
+ }
+ connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ layout->addWidget(m_buttonBox);
+ }
+
+ DropAction dropAction() const { return static_cast<DropAction>(m_buttonGroup->checkedId()); }
+ FilePath targetDir() const
+ {
+ return m_targetDirChooser ? m_targetDirChooser->fileName() : FilePath();
+ }
+
+private:
+ PathChooser *m_targetDirChooser = nullptr;
+ QDialogButtonBox * const m_buttonBox;
+ QButtonGroup * const m_buttonGroup;
+};
+
+
+bool FlatModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
+ const QModelIndex &parent)
+{
+ Q_UNUSED(action);
+
+ const auto * const dropData = dynamic_cast<const DropMimeData *>(data);
+ QTC_ASSERT(dropData, return false);
+
+ auto fileNodes = transform<QList<const Node *>>(dropData->values(),
+ [](const QVariant &v) { return v.value<Node *>(); });
+ QTC_ASSERT(!fileNodes.empty(), return true);
+
+ // The drag operation does not block event handling, so it's possible that the project
+ // was reparsed and the nodes in the drop data are now invalid. If that happens for any node,
+ // we chicken out and abort the entire operation.
+ // Note: In theory, it might be possible that the memory was reused in such an unlucky
+ // way that the pointers refer to different project nodes now, but...
+ if (!allOf(fileNodes, [](const Node *n) { return ProjectTree::hasNode(n); }))
+ return true;
+
+ // We handle only proper file nodes, i.e. no project or folder nodes and no "pseudo"
+ // file nodes that represent the project file.
+ fileNodes = filtered(fileNodes, [](const Node *n) {
+ return n->asFileNode() && n->asFileNode()->fileType() != FileType::Project;
+ });
+ if (fileNodes.empty())
+ return true;
+
+ // We can handle more than one file being dropped, as long as they have the same parent node.
+ ProjectNode * const sourceProjectNode = fileNodes.first()->parentProjectNode();
+ QTC_ASSERT(sourceProjectNode, return true);
+ if (anyOf(fileNodes, [sourceProjectNode](const Node *n) {
+ return n->parentProjectNode() != sourceProjectNode; })) {
+ return true;
+ }
+ Node *targetNode = nodeForIndex(index(row, column, parent));
+ if (!targetNode)
+ targetNode = nodeForIndex(parent);
+ QTC_ASSERT(targetNode, return true);
+ ProjectNode *targetProjectNode = targetNode->asProjectNode();
+ if (!targetProjectNode)
+ targetProjectNode = targetNode->parentProjectNode();
+ QTC_ASSERT(targetProjectNode, return true);
+ if (sourceProjectNode == targetProjectNode)
+ return true;
+
+ // Node weirdness: Sometimes the "file path" is a directory, sometimes it's a file...
+ const auto dirForProjectNode = [](const ProjectNode *pNode) {
+ const FilePath dir = pNode->filePath();
+ if (dir.toFileInfo().isDir())
+ return dir;
+ return FilePath::fromString(dir.toFileInfo().path());
+ };
+ FilePath targetDir = dirForProjectNode(targetProjectNode);
+
+ // Ask the user what to do now: Copy or add? With or without file transfer?
+ DropFileDialog dlg(targetDir == dirForProjectNode(sourceProjectNode) ? FilePath() : targetDir);
+ if (dlg.exec() != QDialog::Accepted)
+ return true;
+ if (!dlg.targetDir().isEmpty())
+ targetDir = dlg.targetDir();
+
+ // Check the nodes again.
+ if (!allOf(fileNodes, [](const Node *n) { return ProjectTree::hasNode(n); }))
+ return true;
+
+ // Some helper functions for the file operations.
+ const auto targetFilePath = [&targetDir](const QString &sourceFilePath) {
+ return targetDir.pathAppended(QFileInfo(sourceFilePath).fileName()).toString();
+ };
+
+ struct VcsInfo {
+ Core::IVersionControl *vcs = nullptr;
+ QString repoDir;
+ bool operator==(const VcsInfo &other) const {
+ return vcs == other.vcs && repoDir == other.repoDir;
+ }
+ };
+ QHash<QString, VcsInfo> vcsHash;
+ const auto vcsInfoForFile = [&vcsHash](const QString &filePath) {
+ const QString dir = QFileInfo(filePath).path();
+ const auto it = vcsHash.constFind(dir);
+ if (it != vcsHash.constEnd())
+ return it.value();
+ VcsInfo vcsInfo;
+ vcsInfo.vcs = Core::VcsManager::findVersionControlForDirectory(dir, &vcsInfo.repoDir);
+ vcsHash.insert(dir, vcsInfo);
+ return vcsInfo;
+ };
+
+ // Now do the actual work.
+ const QStringList sourceFiles = transform(fileNodes, [](const Node *n) {
+ return n->filePath().toString();
+ });
+ QStringList failedRemoveFromProject;
+ QStringList failedAddToProject;
+ QStringList failedCopyOrMove;
+ QStringList failedDelete;
+ QStringList failedVcsOp;
+ switch (dlg.dropAction()) {
+ case DropAction::CopyWithFiles: {
+ QStringList filesToAdd;
+ Core::IVersionControl * const vcs = Core::VcsManager::findVersionControlForDirectory(
+ targetDir.toString());
+ const bool addToVcs = vcs && vcs->supportsOperation(Core::IVersionControl::AddOperation);
+ for (const QString &sourceFile : sourceFiles) {
+ const QString targetFile = targetFilePath(sourceFile);
+ if (QFile::copy(sourceFile, targetFile)) {
+ filesToAdd << targetFile;
+ if (addToVcs && !vcs->vcsAdd(targetFile))
+ failedVcsOp << targetFile;
+ } else {
+ failedCopyOrMove << sourceFile;
+ }
+ }
+ targetProjectNode->addFiles(filesToAdd, &failedAddToProject);
+ break;
+ }
+ case DropAction::Copy:
+ targetProjectNode->addFiles(sourceFiles, &failedAddToProject);
+ break;
+ case DropAction::MoveWithFiles: {
+ QStringList filesToAdd;
+ QStringList filesToRemove;
+ const VcsInfo targetVcs = vcsInfoForFile(targetDir.toString());
+ const bool vcsAddPossible = targetVcs.vcs
+ && targetVcs.vcs->supportsOperation(Core::IVersionControl::AddOperation);
+ for (const QString &sourceFile : sourceFiles) {
+ const QString targetFile = targetFilePath(sourceFile);
+ const VcsInfo sourceVcs = vcsInfoForFile(sourceFile);
+ if (sourceVcs.vcs && targetVcs.vcs && sourceVcs == targetVcs
+ && sourceVcs.vcs->supportsOperation(Core::IVersionControl::MoveOperation)) {
+ if (sourceVcs.vcs->vcsMove(sourceFile, targetFile)) {
+ filesToAdd << targetFile;
+ filesToRemove << sourceFile;
+ } else {
+ failedCopyOrMove << sourceFile;
+ }
+ continue;
+ }
+ if (!QFile::copy(sourceFile, targetFile)) {
+ failedCopyOrMove << sourceFile;
+ continue;
+ }
+ filesToAdd << targetFile;
+ filesToRemove << sourceFile;
+ Core::FileChangeBlocker changeGuard(sourceFile);
+ if (sourceVcs.vcs && sourceVcs.vcs->supportsOperation(
+ Core::IVersionControl::DeleteOperation)
+ && !sourceVcs.vcs->vcsDelete(sourceFile)) {
+ failedVcsOp << sourceFile;
+ }
+ if (QFile::exists(sourceFile) && !QFile::remove(sourceFile))
+ failedDelete << sourceFile;
+ if (vcsAddPossible && !targetVcs.vcs->vcsAdd(targetFile))
+ failedVcsOp << targetFile;
+ }
+ sourceProjectNode->removeFiles(filesToRemove, &failedRemoveFromProject);
+ targetProjectNode->addFiles(filesToAdd, &failedAddToProject);
+ break;
+ }
+ case DropAction::Move:
+ sourceProjectNode->removeFiles(sourceFiles, &failedRemoveFromProject);
+ targetProjectNode->addFiles(sourceFiles, &failedAddToProject);
+ break;
+ }
+
+ // Summary for the user in case anything went wrong.
+ const auto makeUserFileList = [](const QStringList &files) {
+ return transform(files, [](const QString &f) { return QDir::toNativeSeparators(f); })
+ .join("\n ");
+ };
+ if (!failedAddToProject.empty() || !failedRemoveFromProject.empty()
+ || !failedCopyOrMove.empty() || !failedDelete.empty() || !failedVcsOp.empty()) {
+ QString message = tr("Not all operations finished successfully.");
+ if (!failedCopyOrMove.empty()) {
+ message.append('\n').append(tr("The following files could not be copied or moved:"))
+ .append("\n ").append(makeUserFileList(failedCopyOrMove));
+ }
+ if (!failedRemoveFromProject.empty()) {
+ message.append('\n').append(tr("The following files could not be removed from the "
+ "project file:"))
+ .append("\n ").append(makeUserFileList(failedRemoveFromProject));
+ }
+ if (!failedAddToProject.empty()) {
+ message.append('\n').append(tr("The following files could not be added to the "
+ "project file:"))
+ .append("\n ").append(makeUserFileList(failedAddToProject));
+ }
+ if (!failedDelete.empty()) {
+ message.append('\n').append(tr("The following files could not be deleted:"))
+ .append("\n ").append(makeUserFileList(failedDelete));
+ }
+ if (!failedVcsOp.empty()) {
+ message.append('\n').append(tr("A version control operation failed for the following "
+ "files. Please check your repository."))
+ .append("\n ").append(makeUserFileList(failedVcsOp));
+ }
+ QMessageBox::warning(Core::ICore::mainWindow(), tr("Failure Updating Project"),
+ message);
+ }
+
+ return true;
+}
+
WrapperNode *FlatModel::wrapperForNode(const Node *node) const
{
return findNonRootItem([node](WrapperNode *item) {
diff --git a/src/plugins/projectexplorer/projectmodels.h b/src/plugins/projectexplorer/projectmodels.h
index e406360f34..78753bf1da 100644
--- a/src/plugins/projectexplorer/projectmodels.h
+++ b/src/plugins/projectexplorer/projectmodels.h
@@ -67,6 +67,10 @@ public:
Qt::DropActions supportedDragActions() const override;
QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
+ bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
+ const QModelIndex &parent) const override;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
+ const QModelIndex &parent) override;
Node *nodeForIndex(const QModelIndex &index) const;
WrapperNode *wrapperForNode(const Node *node) const;
@@ -83,7 +87,7 @@ public:
void onCollapsed(const QModelIndex &idx);
signals:
- void renamed(const Utils::FileName &oldName, const Utils::FileName &newName);
+ void renamed(const Utils::FilePath &oldName, const Utils::FilePath &newName);
void requestExpansion(const QModelIndex &index);
private:
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index 286899b1b7..e6825e98be 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -52,7 +52,7 @@
namespace ProjectExplorer {
-static FolderNode *folderNode(const FolderNode *folder, const Utils::FileName &directory)
+static FolderNode *folderNode(const FolderNode *folder, const Utils::FilePath &directory)
{
return static_cast<FolderNode *>(Utils::findOrDefault(folder->folderNodes(),
[&directory](const FolderNode *fn) {
@@ -61,13 +61,13 @@ static FolderNode *folderNode(const FolderNode *folder, const Utils::FileName &d
}
static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder,
- const Utils::FileName &directory,
- const Utils::FileName &overrideBaseDir,
+ const Utils::FilePath &directory,
+ const Utils::FilePath &overrideBaseDir,
const FolderNode::FolderNodeFactory &factory)
{
- Utils::FileName path = overrideBaseDir.isEmpty() ? folder->filePath() : overrideBaseDir;
+ Utils::FilePath path = overrideBaseDir.isEmpty() ? folder->filePath() : overrideBaseDir;
- Utils::FileName directoryWithoutPrefix;
+ Utils::FilePath directoryWithoutPrefix;
bool isRelative = false;
if (path.isEmpty() || path.toFileInfo().isRoot()) {
@@ -89,7 +89,7 @@ static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder,
ProjectExplorer::FolderNode *parent = folder;
foreach (const QString &part, parts) {
- path.appendPath(part);
+ path = path.pathAppended(part);
// Find folder in subFolders
FolderNode *next = folderNode(parent, path);
if (!next) {
@@ -119,15 +119,23 @@ static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder,
\sa ProjectExplorer::NodesWatcher
*/
-Node::Node(NodeType nodeType, const Utils::FileName &filePath, int line, const QByteArray &id) :
- m_filePath(filePath), m_nodeId(id), m_line(line), m_nodeType(nodeType)
-{ }
+Node::Node() = default;
void Node::setPriority(int p)
{
m_priority = p;
}
+void Node::setFilePath(const Utils::FilePath &filePath)
+{
+ m_filePath = filePath;
+}
+
+void Node::setLine(int line)
+{
+ m_line = line;
+}
+
void Node::setListInProject(bool l)
{
if (l)
@@ -144,7 +152,7 @@ void Node::setIsGenerated(bool g)
m_flags = static_cast<NodeFlag>(m_flags & ~FlagIsGenerated);
}
-void Node::setAbsoluteFilePathAndLine(const Utils::FileName &path, int line)
+void Node::setAbsoluteFilePathAndLine(const Utils::FilePath &path, int line)
{
if (m_filePath == path && m_line == line)
return;
@@ -155,11 +163,6 @@ void Node::setAbsoluteFilePathAndLine(const Utils::FileName &path, int line)
Node::~Node() = default;
-NodeType Node::nodeType() const
-{
- return m_nodeType;
-}
-
int Node::priority() const
{
return m_priority;
@@ -212,7 +215,7 @@ const ProjectNode *Node::managingProject() const
/*!
The path of the file or folder in the filesystem the node represents.
*/
-const Utils::FileName &Node::filePath() const
+const Utils::FilePath &Node::filePath() const
{
return m_filePath;
}
@@ -222,11 +225,6 @@ int Node::line() const
return m_line;
}
-QByteArray Node::id() const
-{
- return m_nodeId;
-}
-
QString Node::displayName() const
{
return filePath().fileName();
@@ -299,7 +297,7 @@ FileType Node::fileTypeForMimeType(const Utils::MimeType &mt)
return type;
}
-FileType Node::fileTypeForFileName(const Utils::FileName &file)
+FileType Node::fileTypeForFileName(const Utils::FilePath &file)
{
return fileTypeForMimeType(Utils::mimeTypeForFile(file.toString(),
Utils::MimeMatchMode::MatchExtension));
@@ -315,13 +313,11 @@ FileType Node::fileTypeForFileName(const Utils::FileName &file)
\sa ProjectExplorer::FolderNode, ProjectExplorer::ProjectNode
*/
-FileNode::FileNode(const Utils::FileName &filePath, const FileType fileType, bool generated,
- int line, const QByteArray &id) :
- Node(NodeType::File, filePath, line, id),
+FileNode::FileNode(const Utils::FilePath &filePath, const FileType fileType) :
m_fileType(fileType)
{
+ setFilePath(filePath);
setListInProject(true);
- setIsGenerated(generated);
if (fileType == FileType::Project)
setPriority(DefaultProjectFilePriority);
else
@@ -330,7 +326,9 @@ FileNode::FileNode(const Utils::FileName &filePath, const FileType fileType, boo
FileNode *FileNode::clone() const
{
- auto fn = new FileNode(filePath(), fileType(), isGenerated(), line(), id());
+ auto fn = new FileNode(filePath(), fileType());
+ fn->setLine(line());
+ fn->setIsGenerated(isGenerated());
fn->setEnabled(isEnabled());
fn->setPriority(priority());
fn->setListInProject(listInProject());
@@ -342,8 +340,8 @@ FileType FileNode::fileType() const
return m_fileType;
}
-static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &directory,
- const std::function<FileNode *(const Utils::FileName &)> factory,
+static QList<FileNode *> scanForFilesRecursively(const Utils::FilePath &directory,
+ const std::function<FileNode *(const Utils::FilePath &)> factory,
QSet<QString> &visited, QFutureInterface<QList<FileNode*>> *future,
double progressStart, double progressRange,
const QList<Core::IVersionControl*> &versionControls)
@@ -358,7 +356,7 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
if (visitedCount == visited.count())
return result;
- const QList<QFileInfo> entries = baseDir.entryInfoList(QStringList(), QDir::AllEntries|QDir::NoDotAndDotDot);
+ const QFileInfoList entries = baseDir.entryInfoList(QStringList(), QDir::AllEntries|QDir::NoDotAndDotDot);
double progress = 0;
const double progressIncrement = progressRange / static_cast<double>(entries.count());
int lastIntProgress = 0;
@@ -366,7 +364,7 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
if (future && future->isCanceled())
return result;
- const Utils::FileName entryName = Utils::FileName::fromString(entry.absoluteFilePath());
+ const Utils::FilePath entryName = Utils::FilePath::fromString(entry.absoluteFilePath());
if (!Utils::contains(versionControls, [&entryName](const Core::IVersionControl *vc) {
return vc->isVcsFileOrDirectory(entryName);
})) {
@@ -390,8 +388,8 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
}
QList<FileNode *>
-FileNode::scanForFiles(const Utils::FileName &directory,
- const std::function<FileNode *(const Utils::FileName &)> factory,
+FileNode::scanForFiles(const Utils::FilePath &directory,
+ const std::function<FileNode *(const Utils::FilePath &)> factory,
QFutureInterface<QList<FileNode *>> *future)
{
QSet<QString> visited;
@@ -409,6 +407,14 @@ bool FileNode::supportsAction(ProjectAction action, const Node *node) const
return parentFolder && parentFolder->supportsAction(action, node);
}
+QString FileNode::displayName() const
+{
+ int l = line();
+ if (l < 0)
+ return Node::displayName();
+ return Node::displayName() + ':' + QString::number(l);
+}
+
/*!
\class ProjectExplorer::FolderNode
@@ -416,16 +422,13 @@ bool FileNode::supportsAction(ProjectAction action, const Node *node) const
\sa ProjectExplorer::FileNode, ProjectExplorer::ProjectNode
*/
-FolderNode::FolderNode(const Utils::FileName &folderPath, NodeType nodeType,
- const QString &displayName, const QByteArray &id) :
- Node(nodeType, folderPath, -1, id),
- m_displayName(displayName)
+FolderNode::FolderNode(const Utils::FilePath &folderPath)
{
+ setFilePath(folderPath);
setPriority(DefaultFolderPriority);
setListInProject(false);
setIsGenerated(false);
- if (m_displayName.isEmpty())
- m_displayName = folderPath.toUserOutput();
+ m_displayName = folderPath.toUserOutput();
}
/*!
@@ -556,7 +559,7 @@ QList<FileNode*> FolderNode::fileNodes() const
return result;
}
-FileNode *FolderNode::fileNode(const Utils::FileName &file) const
+FileNode *FolderNode::fileNode(const Utils::FilePath &file) const
{
return static_cast<FileNode *>(Utils::findOrDefault(m_nodes,
[&file](const std::unique_ptr<Node> &n) {
@@ -576,7 +579,7 @@ QList<FolderNode*> FolderNode::folderNodes() const
}
void FolderNode::addNestedNode(std::unique_ptr<FileNode> &&fileNode,
- const Utils::FileName &overrideBaseDir,
+ const Utils::FilePath &overrideBaseDir,
const FolderNodeFactory &factory)
{
FolderNode *folder = recursiveFindOrCreateFolderNode(this, fileNode->filePath().parentDir(),
@@ -585,7 +588,7 @@ void FolderNode::addNestedNode(std::unique_ptr<FileNode> &&fileNode,
}
void FolderNode::addNestedNodes(std::vector<std::unique_ptr<FileNode> > &&files,
- const Utils::FileName &overrideBaseDir,
+ const Utils::FilePath &overrideBaseDir,
const FolderNode::FolderNodeFactory &factory)
{
for (std::unique_ptr<FileNode> &f : files)
@@ -599,8 +602,12 @@ void FolderNode::addNestedNodes(std::vector<std::unique_ptr<FileNode> > &&files,
void FolderNode::compress()
{
if (auto subFolder = m_nodes.size() == 1 ? m_nodes.at(0)->asFolderNode() : nullptr) {
- if (subFolder->nodeType() != nodeType())
+ const bool sameType = (isFolderNodeType() && subFolder->isFolderNodeType())
+ || (isProjectNodeType() && subFolder->isProjectNodeType())
+ || (isVirtualFolderType() && subFolder->isVirtualFolderType());
+ if (!sameType)
return;
+
// Only one subfolder: Compress!
setDisplayName(QDir::toNativeSeparators(displayName() + "/" + subFolder->displayName()));
for (Node *n : subFolder->nodes()) {
@@ -619,16 +626,6 @@ void FolderNode::compress()
}
}
-bool FolderNode::isAncesterOf(Node *n)
-{
- if (n == this)
- return true;
- FolderNode *p = n->parentFolderNode();
- while (p && p != this)
- p = p->parentFolderNode();
- return p == this;
-}
-
bool FolderNode::replaceSubtree(Node *oldNode, std::unique_ptr<Node> &&newNode)
{
std::unique_ptr<Node> keepAlive;
@@ -676,6 +673,9 @@ const QList<FolderNode::LocationInfo> FolderNode::locationInfo() const
QString FolderNode::addFileFilter() const
{
+ if (!m_addFileFilter.isNull())
+ return m_addFileFilter;
+
FolderNode *fn = parentFolderNode();
return fn ? fn->addFileFilter() : QString();
}
@@ -762,7 +762,7 @@ bool FolderNode::showInSimpleTree() const
bool FolderNode::showWhenEmpty() const
{
- return false;
+ return m_showWhenEmpty;
}
/*!
@@ -776,18 +776,9 @@ bool FolderNode::showWhenEmpty() const
\sa ProjectExplorer::FileNode, ProjectExplorer::ProjectNode
*/
-VirtualFolderNode::VirtualFolderNode(const Utils::FileName &folderPath, int priority,
- const QByteArray &id) :
- FolderNode(folderPath, NodeType::VirtualFolder, QString(), id)
+VirtualFolderNode::VirtualFolderNode(const Utils::FilePath &folderPath) :
+ FolderNode(folderPath)
{
- setPriority(priority);
-}
-
-QString VirtualFolderNode::addFileFilter() const
-{
- if (!m_addFileFilter.isNull())
- return m_addFileFilter;
- return FolderNode::addFileFilter();
}
/*!
@@ -803,11 +794,12 @@ QString VirtualFolderNode::addFileFilter() const
/*!
Creates an uninitialized project node object.
*/
-ProjectNode::ProjectNode(const Utils::FileName &projectFilePath, const QByteArray &id) :
- FolderNode(projectFilePath, NodeType::Project, projectFilePath.fileName(), id)
+ProjectNode::ProjectNode(const Utils::FilePath &projectFilePath) :
+ FolderNode(projectFilePath)
{
setPriority(DefaultProjectPriority);
setListInProject(true);
+ setDisplayName(projectFilePath.fileName());
}
bool ProjectNode::canAddSubProject(const QString &proFilePath) const
@@ -822,6 +814,11 @@ bool ProjectNode::addSubProject(const QString &proFilePath)
return false;
}
+QStringList ProjectNode::subProjectFileNamePatterns() const
+{
+ return QStringList();
+}
+
bool ProjectNode::removeSubProject(const QString &proFilePath)
{
Q_UNUSED(proFilePath)
@@ -873,7 +870,7 @@ bool ProjectNode::deploysFolder(const QString &folder) const
return false;
}
-ProjectNode *ProjectNode::projectNode(const Utils::FileName &file) const
+ProjectNode *ProjectNode::projectNode(const Utils::FilePath &file) const
{
for (const std::unique_ptr<Node> &n: m_nodes) {
if (ProjectNode *pnode = n->asProjectNode())
@@ -907,9 +904,15 @@ void FolderNode::handleSubTreeChanged(FolderNode *node)
parent->handleSubTreeChanged(node);
}
+void FolderNode::setShowWhenEmpty(bool showWhenEmpty)
+{
+ m_showWhenEmpty = showWhenEmpty;
+}
+
ContainerNode::ContainerNode(Project *project)
- : FolderNode(project->projectDirectory(), NodeType::Project), m_project(project)
-{}
+ : FolderNode(project->projectDirectory()), m_project(project)
+{
+}
QString ContainerNode::displayName() const
{
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index c96b8f8713..ce36882aa9 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -44,13 +44,6 @@ namespace ProjectExplorer {
class Project;
-enum class NodeType : quint16 {
- File = 1,
- Folder,
- VirtualFolder,
- Project
-};
-
// File types common for qt projects
enum class FileType : quint16 {
Unknown = 0,
@@ -68,6 +61,7 @@ enum ProjectAction {
// Special value to indicate that the actions are handled by the parent
InheritedFromParent,
AddSubProject,
+ AddExistingProject,
RemoveSubProject,
// Let's the user select to which project file
// the file is added
@@ -89,7 +83,6 @@ enum ProjectAction {
HidePathActions,
HideFileActions,
HideFolderActions,
- HasSubProjectRunConfigurations
};
class FileNode;
@@ -111,8 +104,11 @@ public:
};
virtual ~Node();
- Node(const Node &other) = delete;
- NodeType nodeType() const;
+
+ virtual bool isFolderNodeType() const { return false; }
+ virtual bool isProjectNodeType() const { return false; }
+ virtual bool isVirtualFolderType() const { return false; }
+
int priority() const;
ProjectNode *parentProjectNode() const; // parent project, will be nullptr for the top-level project
@@ -125,9 +121,8 @@ public:
// or node->parentProjectNode() for all other cases.
const ProjectNode *managingProject() const; // see above.
- const Utils::FileName &filePath() const; // file system path
+ const Utils::FilePath &filePath() const; // file system path
int line() const;
- QByteArray id() const;
virtual QString displayName() const;
virtual QString tooltip() const;
bool isEnabled() const;
@@ -137,7 +132,7 @@ public:
virtual bool supportsAction(ProjectAction action, const Node *node) const;
void setEnabled(bool enabled);
- void setAbsoluteFilePathAndLine(const Utils::FileName &filePath, int line);
+ void setAbsoluteFilePathAndLine(const Utils::FilePath &filePath, int line);
virtual FileNode *asFileNode() { return nullptr; }
virtual const FileNode *asFileNode() const { return nullptr; }
@@ -154,24 +149,26 @@ public:
void setParentFolderNode(FolderNode *parentFolder);
void setListInProject(bool l);
+ void setIsGenerated(bool g);
+ void setPriority(int priority);
+ void setLine(int line);
static FileType fileTypeForMimeType(const Utils::MimeType &mt);
- static FileType fileTypeForFileName(const Utils::FileName &file);
+ static FileType fileTypeForFileName(const Utils::FilePath &file);
protected:
- Node(NodeType nodeType, const Utils::FileName &filePath, int line = -1,
- const QByteArray &id = {});
+ Node();
+ Node(const Node &other) = delete;
+ bool operator=(const Node &other) = delete;
- void setPriority(int priority);
- void setIsGenerated(bool g);
+ void setFilePath(const Utils::FilePath &filePath);
private:
FolderNode *m_parentFolderNode = nullptr;
- Utils::FileName m_filePath;
- QByteArray m_nodeId;
+ Utils::FilePath m_filePath;
int m_line = -1;
int m_priority = DefaultPriority;
- const NodeType m_nodeType;
+
enum NodeFlag : quint16 {
FlagNone = 0,
FlagIsEnabled = 1 << 0,
@@ -184,8 +181,7 @@ private:
class PROJECTEXPLORER_EXPORT FileNode : public Node
{
public:
- FileNode(const Utils::FileName &filePath, const FileType fileType, bool generated, int line = -1,
- const QByteArray &id = {});
+ FileNode(const Utils::FilePath &filePath, const FileType fileType);
FileNode *clone() const;
@@ -195,10 +191,11 @@ public:
const FileNode *asFileNode() const final { return this; }
static QList<FileNode *>
- scanForFiles(const Utils::FileName &directory,
- const std::function<FileNode *(const Utils::FileName &fileName)> factory,
+ scanForFiles(const Utils::FilePath &directory,
+ const std::function<FileNode *(const Utils::FilePath &fileName)> factory,
QFutureInterface<QList<FileNode *>> *future = nullptr);
bool supportsAction(ProjectAction action, const Node *node) const override;
+ QString displayName() const override;
private:
FileType m_fileType;
@@ -208,12 +205,13 @@ private:
class PROJECTEXPLORER_EXPORT FolderNode : public Node
{
public:
- explicit FolderNode(const Utils::FileName &folderPath, NodeType nodeType = NodeType::Folder,
- const QString &displayName = QString(), const QByteArray &id = {});
+ explicit FolderNode(const Utils::FilePath &folderPath);
QString displayName() const override;
QIcon icon() const;
+ bool isFolderNodeType() const override { return true; }
+
Node *findNode(const std::function<bool(Node *)> &filter);
QList<Node *> findNodes(const std::function<bool(Node *)> &filter);
@@ -225,21 +223,19 @@ public:
ProjectNode *findProjectNode(const std::function<bool(const ProjectNode *)> &predicate);
const QList<Node *> nodes() const;
QList<FileNode *> fileNodes() const;
- FileNode *fileNode(const Utils::FileName &file) const;
+ FileNode *fileNode(const Utils::FilePath &file) const;
QList<FolderNode *> folderNodes() const;
- using FolderNodeFactory = std::function<std::unique_ptr<FolderNode>(const Utils::FileName &)>;
+ using FolderNodeFactory = std::function<std::unique_ptr<FolderNode>(const Utils::FilePath &)>;
void addNestedNodes(std::vector<std::unique_ptr<FileNode>> &&files,
- const Utils::FileName &overrideBaseDir = Utils::FileName(),
+ const Utils::FilePath &overrideBaseDir = Utils::FilePath(),
const FolderNodeFactory &factory
- = [](const Utils::FileName &fn) { return std::make_unique<FolderNode>(fn); });
+ = [](const Utils::FilePath &fn) { return std::make_unique<FolderNode>(fn); });
void addNestedNode(std::unique_ptr<FileNode> &&fileNode,
- const Utils::FileName &overrideBaseDir = Utils::FileName(),
+ const Utils::FilePath &overrideBaseDir = Utils::FilePath(),
const FolderNodeFactory &factory
- = [](const Utils::FileName &fn) { return std::make_unique<FolderNode>(fn); });
+ = [](const Utils::FilePath &fn) { return std::make_unique<FolderNode>(fn); });
void compress();
- bool isAncesterOf(Node *n);
-
// takes ownership of newNode.
// Will delete newNode if oldNode is not a child of this node.
bool replaceSubtree(Node *oldNode, std::unique_ptr<Node> &&newNode);
@@ -249,17 +245,18 @@ public:
class LocationInfo {
public:
- LocationInfo(const QString &dn, const Utils::FileName &p, const int l = -1) :
+ LocationInfo(const QString &dn, const Utils::FilePath &p, const int l = -1) :
path(p), line(l), displayName(dn) { }
- Utils::FileName path;
+ Utils::FilePath path;
int line = -1;
QString displayName;
};
void setLocationInfo(const QList<LocationInfo> &info);
const QList<LocationInfo> locationInfo() const;
- virtual QString addFileFilter() const;
+ QString addFileFilter() const;
+ void setAddFileFilter(const QString &filter) { m_addFileFilter = filter; }
bool supportsAction(ProjectAction action, const Node *node) const override;
@@ -284,11 +281,12 @@ public:
// determines if node will be shown in the flat view, by default folder and projects aren't shown
virtual bool showInSimpleTree() const;
+
// determines if node will always be shown when hiding empty directories
- virtual bool showWhenEmpty() const;
+ bool showWhenEmpty() const;
+ void setShowWhenEmpty(bool showWhenEmpty);
void addNode(std::unique_ptr<Node> &&node);
- std::unique_ptr<Node> takeNode(Node *node);
bool isEmpty() const;
@@ -302,34 +300,41 @@ protected:
QList<LocationInfo> m_locations;
private:
+ std::unique_ptr<Node> takeNode(Node *node);
+
QString m_displayName;
+ QString m_addFileFilter;
mutable QIcon m_icon;
+ bool m_showWhenEmpty = false;
};
class PROJECTEXPLORER_EXPORT VirtualFolderNode : public FolderNode
{
public:
- explicit VirtualFolderNode(const Utils::FileName &folderPath, int priority,
- const QByteArray &id = {});
+ explicit VirtualFolderNode(const Utils::FilePath &folderPath);
- void setAddFileFilter(const QString &filter) { m_addFileFilter = filter; }
- QString addFileFilter() const override;
-
-private:
- QString m_addFileFilter;
+ bool isFolderNodeType() const override { return false; }
+ bool isVirtualFolderType() const override { return true; }
};
// Documentation inside.
class PROJECTEXPLORER_EXPORT ProjectNode : public FolderNode
{
public:
+ explicit ProjectNode(const Utils::FilePath &projectFilePath);
+
virtual bool canAddSubProject(const QString &proFilePath) const;
virtual bool addSubProject(const QString &proFile);
+ virtual QStringList subProjectFileNamePatterns() const;
virtual bool removeSubProject(const QString &proFilePath);
- virtual Utils::optional<Utils::FileName> visibleAfterAddFileAction() const {
+ virtual Utils::optional<Utils::FilePath> visibleAfterAddFileAction() const {
return Utils::nullopt;
}
+ bool isFolderNodeType() const override { return false; }
+ bool isProjectNodeType() const override { return true; }
+ bool showInSimpleTree() const override { return true; }
+
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;
bool deleteFiles(const QStringList &filePaths) override;
@@ -340,7 +345,7 @@ public:
// by default returns false
virtual bool deploysFolder(const QString &folder) const;
- ProjectNode *projectNode(const Utils::FileName &file) const;
+ ProjectNode *projectNode(const Utils::FilePath &file) const;
ProjectNode *asProjectNode() final { return this; }
const ProjectNode *asProjectNode() const final { return this; }
@@ -352,8 +357,15 @@ public:
virtual QVariant data(Core::Id role) const;
virtual bool setData(Core::Id role, const QVariant &value) const;
+ bool isProduct() const { return m_isProduct; }
+
protected:
- explicit ProjectNode(const Utils::FileName &projectFilePath, const QByteArray &id = {});
+ void setIsProduct() { m_isProduct = true; }
+
+ QString m_target;
+
+private:
+ bool m_isProduct = false;
};
class PROJECTEXPLORER_EXPORT ContainerNode : public FolderNode
@@ -364,6 +376,9 @@ public:
QString displayName() const final;
bool supportsAction(ProjectAction action, const Node *node) const final;
+ bool isFolderNodeType() const override { return false; }
+ bool isProjectNodeType() const override { return true; }
+
ContainerNode *asContainerNode() final { return this; }
const ContainerNode *asContainerNode() const final { return this; }
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index 5e853e6a78..5259a0d609 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -104,16 +104,16 @@ Project *ProjectTree::currentProject()
return s_instance->m_currentProject;
}
-Node *ProjectTree::findCurrentNode()
+Node *ProjectTree::currentNode()
{
s_instance->update();
return s_instance->m_currentNode;
}
-FileName ProjectTree::currentFilePath()
+FilePath ProjectTree::currentFilePath()
{
- Node *currentNode = findCurrentNode();
- return currentNode ? currentNode->filePath() : FileName();
+ Node *node = currentNode();
+ return node ? node->filePath() : FilePath();
}
void ProjectTree::registerWidget(ProjectTreeWidget *widget)
@@ -167,7 +167,7 @@ void ProjectTree::updateFromProjectTreeWidget(ProjectTreeWidget *widget)
void ProjectTree::updateFromDocumentManager()
{
if (Core::IDocument *document = Core::EditorManager::currentDocument()) {
- const FileName fileName = document->filePath();
+ const FilePath fileName = document->filePath();
updateFromNode(ProjectTreeWidget::nodeForFile(fileName));
} else {
updateFromNode(nullptr);
@@ -283,6 +283,12 @@ void ProjectTree::expandAll()
w->expandAll();
}
+void ProjectTree::changeProjectRootDirectory()
+{
+ if (m_currentProject)
+ m_currentProject->changeRootProjectDirectory();
+}
+
void ProjectTree::updateExternalFileWarning()
{
auto document = qobject_cast<Core::IDocument *>(sender());
@@ -296,12 +302,12 @@ void ProjectTree::updateExternalFileWarning()
}
if (!infoBar->canInfoBeAdded(externalFileId))
return;
- const FileName fileName = document->filePath();
+ const FilePath fileName = document->filePath();
const QList<Project *> projects = SessionManager::projects();
if (projects.isEmpty())
return;
for (Project *project : projects) {
- FileName projectDir = project->projectDirectory();
+ FilePath projectDir = project->projectDirectory();
if (projectDir.isEmpty())
continue;
if (fileName.isChildOf(projectDir))
@@ -309,7 +315,7 @@ void ProjectTree::updateExternalFileWarning()
// External file. Test if it under the same VCS
QString topLevel;
if (Core::VcsManager::findVersionControlForDirectory(projectDir.toString(), &topLevel)
- && fileName.isChildOf(FileName::fromString(topLevel))) {
+ && fileName.isChildOf(FilePath::fromString(topLevel))) {
return;
}
}
@@ -333,26 +339,16 @@ void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &global
if (!node) {
contextMenu = Core::ActionManager::actionContainer(Constants::M_SESSIONCONTEXT)->menu();
- } else {
- switch (node->nodeType()) {
- case NodeType::Project: {
- if ((node->parentFolderNode() && node->parentFolderNode()->asContainerNode())
- || node->asContainerNode())
- contextMenu = Core::ActionManager::actionContainer(Constants::M_PROJECTCONTEXT)->menu();
- else
- contextMenu = Core::ActionManager::actionContainer(Constants::M_SUBPROJECTCONTEXT)->menu();
- break;
- }
- case NodeType::VirtualFolder:
- case NodeType::Folder:
- contextMenu = Core::ActionManager::actionContainer(Constants::M_FOLDERCONTEXT)->menu();
- break;
- case NodeType::File:
- contextMenu = Core::ActionManager::actionContainer(Constants::M_FILECONTEXT)->menu();
- break;
- default:
- qWarning("ProjectExplorerPlugin::showContextMenu - Missing handler for node type");
- }
+ } else if (node->isProjectNodeType()) {
+ if ((node->parentFolderNode() && node->parentFolderNode()->asContainerNode())
+ || node->asContainerNode())
+ contextMenu = Core::ActionManager::actionContainer(Constants::M_PROJECTCONTEXT)->menu();
+ else
+ contextMenu = Core::ActionManager::actionContainer(Constants::M_SUBPROJECTCONTEXT)->menu();
+ } else if (node->isVirtualFolderType() || node->isFolderNodeType()) {
+ contextMenu = Core::ActionManager::actionContainer(Constants::M_FOLDERCONTEXT)->menu();
+ } else if (node->asFileNode()) {
+ contextMenu = Core::ActionManager::actionContainer(Constants::M_FILECONTEXT)->menu();
}
if (contextMenu && contextMenu->actions().count() > 0) {
@@ -433,7 +429,7 @@ Project *ProjectTree::projectForNode(const Node *node)
});
}
-Node *ProjectTree::nodeForFile(const FileName &fileName)
+Node *ProjectTree::nodeForFile(const FilePath &fileName)
{
Node *node = nullptr;
for (const Project *project : SessionManager::projects()) {
@@ -441,7 +437,7 @@ Node *ProjectTree::nodeForFile(const FileName &fileName)
projectNode->forEachGenericNode([&](Node *n) {
if (n->filePath() == fileName) {
// prefer file nodes
- if (!node || (node->nodeType() != NodeType::File && n->nodeType() == NodeType::File))
+ if (!node || (!node->asFileNode() && n->asFileNode()))
node = n;
}
});
diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h
index 238c55a910..4adcaa7571 100644
--- a/src/plugins/projectexplorer/projecttree.h
+++ b/src/plugins/projectexplorer/projecttree.h
@@ -31,7 +31,7 @@
#include <functional>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ProjectExplorer {
class FileNode;
@@ -53,8 +53,8 @@ public:
static ProjectTree *instance();
static Project *currentProject();
- static Node *findCurrentNode();
- static Utils::FileName currentFilePath();
+ static Node *currentNode();
+ static Utils::FilePath currentFilePath();
// Integration with ProjectTreeWidget
static void registerWidget(Internal::ProjectTreeWidget *widget);
@@ -76,11 +76,13 @@ public:
static void forEachNode(const std::function<void(Node *)> &task);
static Project *projectForNode(const Node *node);
- static Node *nodeForFile(const Utils::FileName &fileName);
+ static Node *nodeForFile(const Utils::FilePath &fileName);
void collapseAll();
void expandAll();
+ void changeProjectRootDirectory();
+
// for nodes to emit signals, do not call unless you are a node
static void emitSubtreeChanged(FolderNode *node);
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index af4334a21e..5e4b19f8c9 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -149,7 +149,9 @@ public:
setEditTriggers(QAbstractItemView::EditKeyPressed);
setContextMenuPolicy(Qt::CustomContextMenu);
setDragEnabled(true);
- setDragDropMode(QAbstractItemView::DragOnly);
+ setDragDropMode(QAbstractItemView::DragDrop);
+ viewport()->setAcceptDrops(true);
+ setDropIndicatorShown(true);
m_context = new IContext(this);
m_context->setContext(Context(ProjectExplorer::Constants::C_PROJECT_TREE));
m_context->setWidget(this);
@@ -296,7 +298,7 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent) : QWidget(parent)
connect(m_toggleSync, &QAbstractButton::clicked,
this, &ProjectTreeWidget::toggleAutoSynchronization);
- setCurrentItem(ProjectTree::findCurrentNode());
+ setCurrentItem(ProjectTree::currentNode());
setAutoSynchronization(true);
m_projectTreeWidgets << this;
@@ -348,11 +350,26 @@ void ProjectTreeWidget::rowsInserted(const QModelIndex &parent, int start, int e
}
}
-Node *ProjectTreeWidget::nodeForFile(const FileName &fileName)
+Node *ProjectTreeWidget::nodeForFile(const FilePath &fileName)
{
Node *bestNode = nullptr;
int bestNodeExpandCount = INT_MAX;
+ // FIXME: Check that the values used make sense in the context.
+ auto priority = [](Node *node) {
+ if (node->asFileNode())
+ return 1;
+ if (node->isFolderNodeType())
+ return 2;
+ if (node->isVirtualFolderType())
+ return 3;
+ if (node->isProjectNodeType())
+ return 4;
+ QTC_CHECK(false);
+ return 1;
+ };
+
+ // FIXME: Looks like this could be done with less cycles.
for (Project *project : SessionManager::projects()) {
if (ProjectNode *projectNode = project->rootProjectNode()) {
projectNode->forEachGenericNode([&](Node *node) {
@@ -360,10 +377,10 @@ Node *ProjectTreeWidget::nodeForFile(const FileName &fileName)
if (!bestNode) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
- } else if (node->nodeType() < bestNode->nodeType()) {
+ } else if (priority(node) < priority(bestNode)) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
- } else if (node->nodeType() == bestNode->nodeType()) {
+ } else if (priority(node) == priority(bestNode)) {
int nodeExpandCount = ProjectTreeWidget::expandedCount(node);
if (nodeExpandCount < bestNodeExpandCount) {
bestNode = node;
@@ -440,7 +457,7 @@ void ProjectTreeWidget::editCurrentItem()
editor->setSelection(0, dotIndex);
}
-void ProjectTreeWidget::renamed(const FileName &oldPath, const FileName &newPath)
+void ProjectTreeWidget::renamed(const FilePath &oldPath, const FilePath &newPath)
{
update();
Q_UNUSED(oldPath);
@@ -457,7 +474,7 @@ void ProjectTreeWidget::renamed(const FileName &oldPath, const FileName &newPath
void ProjectTreeWidget::syncFromDocumentManager()
{
// sync from document manager
- FileName fileName;
+ FilePath fileName;
if (IDocument *doc = EditorManager::currentDocument())
fileName = doc->filePath();
if (!currentNode() || currentNode()->filePath() != fileName)
@@ -522,7 +539,7 @@ void ProjectTreeWidget::showContextMenu(const QPoint &pos)
void ProjectTreeWidget::openItem(const QModelIndex &mainIndex)
{
Node *node = m_model->nodeForIndex(mainIndex);
- if (!node || node->nodeType() != NodeType::File)
+ if (!node || !node->asFileNode())
return;
IEditor *editor = EditorManager::openEditor(node->filePath().toString());
if (editor && node->line() >= 0)
diff --git a/src/plugins/projectexplorer/projecttreewidget.h b/src/plugins/projectexplorer/projecttreewidget.h
index 6de41b0adf..c4b729f097 100644
--- a/src/plugins/projectexplorer/projecttreewidget.h
+++ b/src/plugins/projectexplorer/projecttreewidget.h
@@ -62,7 +62,7 @@ public:
void sync(ProjectExplorer::Node *node);
void showMessage(ProjectExplorer::Node *node, const QString &message);
- static Node *nodeForFile(const Utils::FileName &fileName);
+ static Node *nodeForFile(const Utils::FilePath &fileName);
void toggleAutoSynchronization();
void editCurrentItem();
@@ -81,7 +81,7 @@ private:
void setCurrentItem(ProjectExplorer::Node *node);
static int expandedCount(Node *node);
void rowsInserted(const QModelIndex &parent, int start, int end);
- void renamed(const Utils::FileName &oldPath, const Utils::FileName &newPath);
+ void renamed(const Utils::FilePath &oldPath, const Utils::FilePath &newPath);
void syncFromDocumentManager();
@@ -94,7 +94,7 @@ private:
QString m_modelId;
bool m_autoSync = true;
- Utils::FileName m_delayedRename;
+ Utils::FilePath m_delayedRename;
static QList<ProjectTreeWidget *> m_projectTreeWidgets;
friend class ProjectTreeWidgetFactory;
diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp
index 2cbb9a9b9d..7827034c2a 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.cpp
+++ b/src/plugins/projectexplorer/projectwelcomepage.cpp
@@ -340,7 +340,7 @@ public:
};
for (int i = 0; i < 3; ++i) {
const QString &action = actions.at(i);
- const int ww = fm.width(action);
+ const int ww = fm.horizontalAdvance(action);
const QRect actionRect(xx, yy - 10, ww, 15);
const bool isForcedDisabled = (i != 0 && sessionName == "default");
const bool isActive = actionRect.contains(mousePos) && !isForcedDisabled;
@@ -399,7 +399,7 @@ public:
else if (m_activeActionRects[1].contains(pos))
sessionModel->renameSession(ICore::mainWindow(), sessionName);
else if (m_activeActionRects[2].contains(pos))
- sessionModel->deleteSession(sessionName);
+ sessionModel->deleteSessions(QStringList(sessionName));
return true;
}
}
@@ -475,7 +475,8 @@ public:
QString projectName = idx.data(Qt::DisplayRole).toString();
QString projectPath = idx.data(ProjectModel::FilePathRole).toString();
QFontMetrics fm(sizedFont(13, option.widget));
- int width = std::max(fm.width(projectName), fm.width(projectPath)) + 36;
+ int width = std::max(fm.horizontalAdvance(projectName),
+ fm.horizontalAdvance(projectPath)) + 36;
return QSize(width, 48);
}
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp
index 434249bee1..065de1e715 100644
--- a/src/plugins/projectexplorer/projectwindow.cpp
+++ b/src/plugins/projectexplorer/projectwindow.cpp
@@ -376,7 +376,7 @@ public:
m_projectSelection = new QComboBox;
m_projectSelection->setModel(&m_comboBoxModel);
- connect(m_projectSelection, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_projectSelection, QOverload<int>::of(&QComboBox::activated),
this, &ProjectWindowPrivate::projectSelected, Qt::QueuedConnection);
SessionManager *sessionManager = SessionManager::instance();
@@ -546,7 +546,7 @@ public:
QString importDir = QFileDialog::getExistingDirectory(ICore::mainWindow(),
ProjectWindow::tr("Import Directory"),
dir);
- FileName path = FileName::fromString(importDir);
+ FilePath path = FilePath::fromString(importDir);
Target *lastTarget = nullptr;
BuildConfiguration *lastBc = nullptr;
diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp
index 500a13a4fc..9eaf136d8b 100644
--- a/src/plugins/projectexplorer/projectwizardpage.cpp
+++ b/src/plugins/projectexplorer/projectwizardpage.cpp
@@ -171,7 +171,7 @@ BestNodeSelector::BestNodeSelector(const QString &commonDirectory, const QString
void BestNodeSelector::inspect(AddNewTree *tree, bool isContextNode)
{
FolderNode *node = tree->node();
- if (node->nodeType() == NodeType::Project) {
+ if (node->isProjectNodeType()) {
if (static_cast<ProjectNode *>(node)->deploysFolder(m_commonDirectory)) {
m_deploys = true;
m_deployText += tree->displayName() + QLatin1Char('\n');
@@ -284,9 +284,9 @@ ProjectWizardPage::ProjectWizardPage(QWidget *parent) : WizardPage(parent),
{
m_ui->setupUi(this);
m_ui->vcsManageButton->setText(ICore::msgShowOptionsDialog());
- connect(m_ui->projectComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->projectComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ProjectWizardPage::projectChanged);
- connect(m_ui->addToVersionControlComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->addToVersionControlComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ProjectWizardPage::versionControlChanged);
connect(m_ui->vcsManageButton, &QAbstractButton::clicked, this, &ProjectWizardPage::manageVcs);
setProperty(SHORT_TITLE_PROPERTY, tr("Summary"));
@@ -299,7 +299,7 @@ ProjectWizardPage::ProjectWizardPage(QWidget *parent) : WizardPage(parent),
ProjectWizardPage::~ProjectWizardPage()
{
- disconnect(m_ui->projectComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ disconnect(m_ui->projectComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ProjectWizardPage::projectChanged);
delete m_ui;
}
@@ -534,7 +534,7 @@ void ProjectWizardPage::setFiles(const QStringList &fileNames)
const bool filePath2HasDir = filePath2.contains(QLatin1Char('/'));
if (filePath1HasDir == filePath2HasDir)
- return FileName::fromString(filePath1) < FileName::fromString(filePath2);
+ return FilePath::fromString(filePath1) < FilePath::fromString(filePath2);
return filePath1HasDir;
}
);
diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp
index 2c8e238495..5c3c6fc0e9 100644
--- a/src/plugins/projectexplorer/runconfiguration.cpp
+++ b/src/plugins/projectexplorer/runconfiguration.cpp
@@ -26,6 +26,7 @@
#include "runconfiguration.h"
#include "project.h"
+#include "runcontrol.h"
#include "target.h"
#include "toolchain.h"
#include "abi.h"
@@ -55,21 +56,9 @@
#include <QLoggingCategory>
#include <QSettings>
-#ifdef Q_OS_OSX
-#include <ApplicationServices/ApplicationServices.h>
-#endif
-
-#if defined (WITH_JOURNALD)
-#include "journaldwatcher.h"
-#endif
-
using namespace Utils;
using namespace ProjectExplorer::Internal;
-namespace {
-Q_LOGGING_CATEGORY(statesLog, "qtc.projectmanager.states", QtWarningMsg)
-}
-
namespace ProjectExplorer {
///////////////////////////////////////////////////////////////////////
@@ -169,7 +158,7 @@ void GlobalOrProjectAspect::resetProjectToGlobalSettings()
static std::vector<RunConfiguration::AspectFactory> theAspectFactories;
RunConfiguration::RunConfiguration(Target *target, Core::Id id)
- : StatefulProjectConfiguration(target, id)
+ : ProjectConfiguration(target, id)
{
connect(target->project(), &Project::parsingStarted,
this, [this]() { updateEnabledState(); });
@@ -197,12 +186,26 @@ RunConfiguration::RunConfiguration(Target *target, Core::Id id)
const auto envAspect = aspect<EnvironmentAspect>();
return envAspect ? envAspect->environment().value(var) : QString();
});
+
+ expander->registerVariable(Constants::VAR_CURRENTRUN_WORKINGDIR,
+ tr("The currently active run configuration's working directory"),
+ [this, expander] {
+ const auto wdAspect = aspect<WorkingDirectoryAspect>();
+ return wdAspect ? wdAspect->workingDirectory(expander).toString() : QString();
+ });
+
expander->registerVariable(Constants::VAR_CURRENTRUN_NAME,
QCoreApplication::translate("ProjectExplorer", "The currently active run configuration's name."),
[this] { return displayName(); }, false);
for (const AspectFactory &factory : theAspectFactories)
m_aspects.append(factory(target));
+
+ m_executableGetter = [this] {
+ if (const auto executableAspect = aspect<ExecutableAspect>())
+ return executableAspect->executable();
+ return FilePath();
+ };
}
RunConfiguration::~RunConfiguration() = default;
@@ -212,12 +215,25 @@ bool RunConfiguration::isActive() const
return target()->isActive() && target()->activeRunConfiguration() == this;
}
+void RunConfiguration::setEnabled(bool enabled)
+{
+ if (enabled == m_isEnabled)
+ return;
+ m_isEnabled = enabled;
+ emit enabledChanged();
+}
+
QString RunConfiguration::disabledReason() const
{
if (target()->project()->isParsing())
return tr("The Project is currently being parsed.");
- if (!target()->project()->hasParsingData())
- return tr("The project could not be fully parsed.");
+ if (!target()->project()->hasParsingData()) {
+ QString msg = tr("The project could not be fully parsed.");
+ const FilePath projectFilePath = buildTargetInfo().projectFilePath;
+ if (!projectFilePath.exists())
+ msg += '\n' + tr("The project file \"%1\" does not exist.").arg(projectFilePath.toString());
+ return msg;
+ }
return QString();
}
@@ -311,9 +327,19 @@ QVariantMap RunConfiguration::toMap() const
return map;
}
+void RunConfiguration::setExecutableGetter(const RunConfiguration::ExecutableGetter &exeGetter)
+{
+ m_executableGetter = exeGetter;
+}
+
+FilePath RunConfiguration::executable() const
+{
+ return m_executableGetter();
+}
+
BuildTargetInfo RunConfiguration::buildTargetInfo() const
{
- return target()->applicationTargets().buildTargetInfo(m_buildKey);
+ return target()->buildTarget(m_buildKey);
}
bool RunConfiguration::fromMap(const QVariantMap &map)
@@ -366,8 +392,7 @@ bool RunConfiguration::fromMap(const QVariantMap &map)
Runnable RunConfiguration::runnable() const
{
Runnable r;
- if (auto executableAspect = aspect<ExecutableAspect>())
- r.executable = executableAspect->executable().toString();
+ r.executable = executable().toString();
if (auto argumentsAspect = aspect<ArgumentsAspect>())
r.commandLineArguments = argumentsAspect->arguments(macroExpander());
if (auto workingDirectoryAspect = aspect<WorkingDirectoryAspect>())
@@ -426,8 +451,6 @@ RunConfigurationFactory::RunConfigurationFactory()
RunConfigurationFactory::~RunConfigurationFactory()
{
g_runConfigurationFactories.removeOne(this);
- qDeleteAll(m_ownedRunWorkerFactories);
- m_ownedRunWorkerFactories.clear();
}
QString RunConfigurationFactory::decoratedTargetName(const QString &targetName, Target *target)
@@ -435,9 +458,9 @@ QString RunConfigurationFactory::decoratedTargetName(const QString &targetName,
QString displayName;
if (!targetName.isEmpty())
displayName = QFileInfo(targetName).completeBaseName();
- Core::Id devType = DeviceTypeKitInformation::deviceTypeId(target->kit());
+ Core::Id devType = DeviceTypeKitAspect::deviceTypeId(target->kit());
if (devType != Constants::DESKTOP_DEVICE_TYPE) {
- if (IDevice::ConstPtr dev = DeviceKitInformation::device(target->kit())) {
+ if (IDevice::ConstPtr dev = DeviceKitAspect::device(target->kit())) {
if (displayName.isEmpty()) {
//: Shown in Run configuration if no executable is given, %1 is device name
displayName = RunConfiguration::tr("Run on %1").arg(dev->displayName());
@@ -453,7 +476,7 @@ QString RunConfigurationFactory::decoratedTargetName(const QString &targetName,
QList<RunConfigurationCreationInfo>
RunConfigurationFactory::availableCreators(Target *parent) const
{
- const QList<BuildTargetInfo> buildTargets = parent->applicationTargets().list;
+ const QList<BuildTargetInfo> buildTargets = parent->applicationTargets();
const bool hasAnyQtcRunnable = Utils::anyOf(buildTargets,
Utils::equal(&BuildTargetInfo::isQtcRunnable, true));
return Utils::transform(buildTargets, [&](const BuildTargetInfo &ti) {
@@ -466,6 +489,7 @@ RunConfigurationFactory::availableCreators(Target *parent) const
rci.factory = this;
rci.id = m_runConfigBaseId;
rci.buildKey = ti.buildKey;
+ rci.projectFilePath = ti.projectFilePath;
rci.displayName = displayName;
rci.displayNameUniquifier = ti.displayNameUniquifier;
rci.creationMode = ti.isQtcRunnable || !hasAnyQtcRunnable
@@ -495,16 +519,6 @@ void RunConfigurationFactory::setDecorateDisplayNames(bool on)
m_decorateDisplayNames = on;
}
-RunWorkerFactory *RunConfigurationFactory::addRunWorkerFactoryHelper
- (Core::Id runMode, const std::function<RunWorker *(RunControl *)> &creator)
-{
- auto factory = new RunWorkerFactory;
- factory->addConstraint(m_ownTypeChecker);
- factory->addSupportedRunMode(runMode);
- factory->setProducer(creator);
- return factory;
-}
-
void RunConfigurationFactory::addSupportedProjectType(Core::Id id)
{
m_supportedProjectTypes.append(id);
@@ -524,7 +538,7 @@ bool RunConfigurationFactory::canHandle(Target *target) const
if (!m_supportedTargetDeviceTypes.isEmpty())
if (!m_supportedTargetDeviceTypes.contains(
- DeviceTypeKitInformation::deviceTypeId(kit)))
+ DeviceTypeKitAspect::deviceTypeId(kit)))
return false;
return true;
@@ -540,6 +554,7 @@ RunConfiguration *RunConfigurationCreationInfo::create(Target *target) const
if (!rc)
return nullptr;
+ rc->acquaintAspects();
rc->m_buildKey = buildKey;
rc->doAdditionalSetup(*this);
rc->setDisplayName(displayName);
@@ -555,6 +570,7 @@ RunConfiguration *RunConfigurationFactory::restore(Target *parent, const QVarian
if (id.name().startsWith(factory->m_runConfigBaseId.name())) {
QTC_ASSERT(factory->m_creator, continue);
RunConfiguration *rc = factory->m_creator(parent);
+ rc->acquaintAspects();
if (rc->fromMap(map))
return rc;
delete rc;
@@ -607,1413 +623,4 @@ FixedRunConfigurationFactory::availableCreators(Target *parent) const
return {rci};
}
-
-// RunWorkerFactory
-
-static QList<RunWorkerFactory *> g_runWorkerFactories;
-
-RunWorkerFactory::RunWorkerFactory()
-{
- g_runWorkerFactories.append(this);
-}
-
-RunWorkerFactory::~RunWorkerFactory()
-{
- g_runWorkerFactories.removeOne(this);
-}
-
-bool RunWorkerFactory::canRun(RunConfiguration *runConfiguration, Core::Id runMode) const
-{
- if (!m_supportedRunModes.contains(runMode))
- return false;
-
- for (const Constraint &constraint : m_constraints) {
- if (!constraint(runConfiguration))
- return false;
- }
-
- return true;
-}
-
-void RunWorkerFactory::setProducer(const WorkerCreator &producer)
-{
- m_producer = producer;
-}
-
-void RunWorkerFactory::addConstraint(const Constraint &constraint)
-{
- // Default constructed Constraints are not worth keeping.
- // FIXME: Make it a QTC_ASSERT once there is no code path
- // using this "feature" anymore.
- if (!constraint)
- return;
- m_constraints.append(constraint);
-}
-
-void RunWorkerFactory::addSupportedRunMode(Core::Id runMode)
-{
- m_supportedRunModes.append(runMode);
-}
-
-void RunWorkerFactory::destroyRemainingRunWorkerFactories()
-{
- qDeleteAll(g_runWorkerFactories);
-}
-
-/*!
- \class ProjectExplorer::RunControl
- \brief The RunControl class instances represent one item that is run.
-*/
-
-/*!
- \fn QIcon ProjectExplorer::RunControl::icon() const
- Returns the icon to be shown in the Outputwindow.
-
- TODO the icon differs currently only per "mode", so this is more flexible
- than it needs to be.
-*/
-
-
-namespace Internal {
-
-enum class RunWorkerState
-{
- Initialized, Starting, Running, Stopping, Done
-};
-
-static QString stateName(RunWorkerState s)
-{
-# define SN(x) case x: return QLatin1String(#x);
- switch (s) {
- SN(RunWorkerState::Initialized)
- SN(RunWorkerState::Starting)
- SN(RunWorkerState::Running)
- SN(RunWorkerState::Stopping)
- SN(RunWorkerState::Done)
- }
- return QString("<unknown: %1>").arg(int(s));
-# undef SN
-}
-
-class RunWorkerPrivate : public QObject
-{
-public:
- RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl);
-
- bool canStart() const;
- bool canStop() const;
- void timerEvent(QTimerEvent *ev) override;
-
- void killStartWatchdog()
- {
- if (startWatchdogTimerId != -1) {
- killTimer(startWatchdogTimerId);
- startWatchdogTimerId = -1;
- }
- }
-
- void killStopWatchdog()
- {
- if (stopWatchdogTimerId != -1) {
- killTimer(stopWatchdogTimerId);
- stopWatchdogTimerId = -1;
- }
- }
-
- void startStartWatchdog()
- {
- killStartWatchdog();
- killStopWatchdog();
-
- if (startWatchdogInterval != 0)
- startWatchdogTimerId = startTimer(startWatchdogInterval);
- }
-
- void startStopWatchdog()
- {
- killStopWatchdog();
- killStartWatchdog();
-
- if (stopWatchdogInterval != 0)
- stopWatchdogTimerId = startTimer(stopWatchdogInterval);
- }
-
- RunWorker *q;
- RunWorkerState state = RunWorkerState::Initialized;
- const QPointer<RunControl> runControl;
- QList<RunWorker *> startDependencies;
- QList<RunWorker *> stopDependencies;
- QString id;
-
- QVariantMap data;
- int startWatchdogInterval = 0;
- int startWatchdogTimerId = -1;
- std::function<void()> startWatchdogCallback;
- int stopWatchdogInterval = 0; // 5000;
- int stopWatchdogTimerId = -1;
- std::function<void()> stopWatchdogCallback;
- bool supportsReRunning = true;
- bool essential = false;
-};
-
-enum class RunControlState
-{
- Initialized, // Default value after creation.
- Starting, // Actual process/tool starts.
- Running, // All good and running.
- Stopping, // initiateStop() was called, stop application/tool
- Stopped, // all good, but stopped. Can possibly be re-started
- Finishing, // Application tab manually closed
- Finished // Final state, will self-destruct with deleteLater()
-};
-
-static QString stateName(RunControlState s)
-{
-# define SN(x) case x: return QLatin1String(#x);
- switch (s) {
- SN(RunControlState::Initialized)
- SN(RunControlState::Starting)
- SN(RunControlState::Running)
- SN(RunControlState::Stopping)
- SN(RunControlState::Stopped)
- SN(RunControlState::Finishing)
- SN(RunControlState::Finished)
- }
- return QString("<unknown: %1>").arg(int(s));
-# undef SN
-}
-
-class RunControlPrivate : public QObject
-{
-public:
- RunControlPrivate(RunControl *parent, RunConfiguration *runConfiguration, Core::Id mode)
- : q(parent), runMode(mode), runConfiguration(runConfiguration)
- {
- icon = Icons::RUN_SMALL_TOOLBAR;
- if (runConfiguration) {
- runnable = runConfiguration->runnable();
- displayName = runConfiguration->displayName();
- outputFormatter = runConfiguration->createOutputFormatter();
- device = runnable.device;
- if (!device)
- device = DeviceKitInformation::device(runConfiguration->target()->kit());
- project = runConfiguration->target()->project();
- } else {
- outputFormatter = new OutputFormatter();
- }
- }
-
- ~RunControlPrivate() override
- {
- QTC_CHECK(state == RunControlState::Finished || state == RunControlState::Initialized);
- disconnect();
- q = nullptr;
- qDeleteAll(m_workers);
- m_workers.clear();
- delete outputFormatter;
- }
-
- Q_ENUM(RunControlState)
-
- void checkState(RunControlState expectedState);
- void setState(RunControlState state);
-
- void debugMessage(const QString &msg);
-
- void initiateStart();
- void initiateReStart();
- void continueStart();
- void initiateStop();
- void forceStop();
- void continueStopOrFinish();
- void initiateFinish();
-
- void onWorkerStarted(RunWorker *worker);
- void onWorkerStopped(RunWorker *worker);
- void onWorkerFailed(RunWorker *worker, const QString &msg);
-
- void showError(const QString &msg);
-
- static bool isAllowedTransition(RunControlState from, RunControlState to);
- bool supportsReRunning() const;
-
- RunControl *q;
- QString displayName;
- Runnable runnable;
- IDevice::ConstPtr device;
- Core::Id runMode;
- Utils::Icon icon;
- const QPointer<RunConfiguration> runConfiguration; // Not owned.
- QPointer<Project> project; // Not owned.
- QPointer<Utils::OutputFormatter> outputFormatter = nullptr;
- 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
-
-using namespace Internal;
-
-RunControl::RunControl(RunConfiguration *runConfiguration, Core::Id mode) :
- d(std::make_unique<RunControlPrivate>(this, runConfiguration, mode))
-{
-#ifdef WITH_JOURNALD
- if (!device().isNull() && device()->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
- JournaldWatcher::instance()->subscribe(this, [this](const JournaldWatcher::LogEntry &entry) {
-
- if (entry.value("_MACHINE_ID") != JournaldWatcher::instance()->machineId())
- return;
-
- const QByteArray pid = entry.value("_PID");
- if (pid.isEmpty())
- return;
-
- const qint64 pidNum = static_cast<qint64>(QString::fromLatin1(pid).toInt());
- if (pidNum != d->applicationProcessHandle.pid())
- return;
-
- const QString message = QString::fromUtf8(entry.value("MESSAGE")) + "\n";
- appendMessageRequested(this, message, Utils::OutputFormat::LogMessageFormat);
- });
- }
-#endif
-}
-
-RunControl::RunControl(const IDevice::ConstPtr &device, Core::Id mode)
- : RunControl(nullptr, mode)
-{
- d->device = device;
-}
-
-RunControl::~RunControl()
-{
-#ifdef WITH_JOURNALD
- JournaldWatcher::instance()->unsubscribe(this);
-#endif
-}
-
-void RunControl::initiateStart()
-{
- emit aboutToStart();
- d->initiateStart();
-}
-
-void RunControl::initiateReStart()
-{
- emit aboutToStart();
- d->initiateReStart();
-}
-
-void RunControl::initiateStop()
-{
- d->initiateStop();
-}
-
-void RunControl::forceStop()
-{
- d->forceStop();
-}
-
-void RunControl::initiateFinish()
-{
- QTimer::singleShot(0, d.get(), &RunControlPrivate::initiateFinish);
-}
-
-using WorkerCreators = QHash<Core::Id, RunControl::WorkerCreator>;
-
-static WorkerCreators &theWorkerCreators()
-{
- static WorkerCreators creators;
- return creators;
-}
-
-void RunControl::registerWorkerCreator(Core::Id id, const WorkerCreator &workerCreator)
-{
- theWorkerCreators().insert(id, workerCreator);
- auto keys = theWorkerCreators().keys();
- Q_UNUSED(keys);
-}
-
-RunWorker *RunControl::createWorker(Core::Id id)
-{
- auto keys = theWorkerCreators().keys();
- Q_UNUSED(keys);
- WorkerCreator creator = theWorkerCreators().value(id);
- if (creator)
- return creator(this);
- creator = device()->workerCreator(id);
- if (creator)
- return creator(this);
- return nullptr;
-}
-
-RunWorkerFactory::WorkerCreator RunControl::producer(RunConfiguration *runConfig, Core::Id runMode)
-{
- const auto canRun = std::bind(&RunWorkerFactory::canRun, std::placeholders::_1, runConfig, runMode);
- const QList<RunWorkerFactory *> candidates = Utils::filtered(g_runWorkerFactories, canRun);
-
- // This is legit, there might be combinations that cannot run.
- if (candidates.empty())
- return {};
-
- // There should be at most one top-level producer feeling responsible per combination.
- // Breaking a tie should be done by tightening the restrictions on one of them.
- QTC_CHECK(candidates.size() == 1);
- return candidates.front()->producer();
-}
-
-void RunControlPrivate::initiateStart()
-{
- checkState(RunControlState::Initialized);
- setState(RunControlState::Starting);
- debugMessage("Queue: Starting");
-
- continueStart();
-}
-
-void RunControlPrivate::initiateReStart()
-{
- checkState(RunControlState::Stopped);
-
- // Re-set worked on re-runs.
- for (RunWorker *worker : m_workers) {
- if (worker->d->state == RunWorkerState::Done)
- worker->d->state = RunWorkerState::Initialized;
- }
-
- setState(RunControlState::Starting);
- debugMessage("Queue: ReStarting");
-
- continueStart();
-}
-
-void RunControlPrivate::continueStart()
-{
- checkState(RunControlState::Starting);
- bool allDone = true;
- debugMessage("Looking for next worker");
- for (RunWorker *worker : m_workers) {
- if (worker) {
- const QString &workerId = worker->d->id;
- debugMessage(" Examining worker " + workerId);
- switch (worker->d->state) {
- case RunWorkerState::Initialized:
- debugMessage(" " + workerId + " is not done yet.");
- if (worker->d->canStart()) {
- debugMessage("Starting " + workerId);
- worker->d->state = RunWorkerState::Starting;
- QTimer::singleShot(0, worker, &RunWorker::initiateStart);
- return;
- }
- allDone = false;
- debugMessage(" " + workerId + " cannot start.");
- break;
- case RunWorkerState::Starting:
- debugMessage(" " + workerId + " currently starting");
- allDone = false;
- break;
- case RunWorkerState::Running:
- debugMessage(" " + workerId + " currently running");
- break;
- case RunWorkerState::Stopping:
- debugMessage(" " + workerId + " currently stopping");
- continue;
- case RunWorkerState::Done:
- debugMessage(" " + workerId + " was done before");
- break;
- }
- } else {
- debugMessage("Found unknown deleted worker while starting");
- }
- }
- if (allDone)
- setState(RunControlState::Running);
-}
-
-void RunControlPrivate::initiateStop()
-{
- if (state != RunControlState::Starting && state != RunControlState::Running)
- qDebug() << "Unexpected initiateStop() in state" << stateName(state);
-
- setState(RunControlState::Stopping);
- debugMessage("Queue: Stopping for all workers");
-
- continueStopOrFinish();
-}
-
-void RunControlPrivate::continueStopOrFinish()
-{
- bool allDone = true;
-
- auto queueStop = [this](RunWorker *worker, const QString &message) {
- if (worker->d->canStop()) {
- debugMessage(message);
- worker->d->state = RunWorkerState::Stopping;
- QTimer::singleShot(0, worker, &RunWorker::initiateStop);
- } else {
- debugMessage(" " + worker->d->id + " is waiting for dependent workers to stop");
- }
- };
-
- for (RunWorker *worker : m_workers) {
- if (worker) {
- const QString &workerId = worker->d->id;
- debugMessage(" Examining worker " + workerId);
- switch (worker->d->state) {
- case RunWorkerState::Initialized:
- debugMessage(" " + workerId + " was Initialized, setting to Done");
- worker->d->state = RunWorkerState::Done;
- break;
- case RunWorkerState::Stopping:
- debugMessage(" " + workerId + " was already Stopping. Keeping it that way");
- allDone = false;
- break;
- case RunWorkerState::Starting:
- queueStop(worker, " " + workerId + " was Starting, queuing stop");
- allDone = false;
- break;
- case RunWorkerState::Running:
- queueStop(worker, " " + workerId + " was Running, queuing stop");
- allDone = false;
- break;
- case RunWorkerState::Done:
- debugMessage(" " + workerId + " was Done. Good.");
- break;
- }
- } else {
- debugMessage("Found unknown deleted worker");
- }
- }
-
- RunControlState targetState;
- if (state == RunControlState::Finishing) {
- targetState = RunControlState::Finished;
- } else {
- checkState(RunControlState::Stopping);
- targetState = RunControlState::Stopped;
- }
-
- if (allDone) {
- debugMessage("All Stopped");
- setState(targetState);
- } else {
- debugMessage("Not all workers Stopped. Waiting...");
- }
-}
-
-void RunControlPrivate::forceStop()
-{
- if (state == RunControlState::Finished) {
- debugMessage("Was finished, too late to force Stop");
- return;
- }
- for (RunWorker *worker : m_workers) {
- if (worker) {
- const QString &workerId = worker->d->id;
- debugMessage(" Examining worker " + workerId);
- switch (worker->d->state) {
- case RunWorkerState::Initialized:
- debugMessage(" " + workerId + " was Initialized, setting to Done");
- break;
- case RunWorkerState::Stopping:
- debugMessage(" " + workerId + " was already Stopping. Set it forcefully to Done.");
- break;
- case RunWorkerState::Starting:
- debugMessage(" " + workerId + " was Starting. Set it forcefully to Done.");
- break;
- case RunWorkerState::Running:
- debugMessage(" " + workerId + " was Running. Set it forcefully to Done.");
- break;
- case RunWorkerState::Done:
- debugMessage(" " + workerId + " was Done. Good.");
- break;
- }
- worker->d->state = RunWorkerState::Done;
- } else {
- debugMessage("Found unknown deleted worker");
- }
- }
-
- setState(RunControlState::Stopped);
- debugMessage("All Stopped");
-}
-
-void RunControlPrivate::initiateFinish()
-{
- setState(RunControlState::Finishing);
- debugMessage("Ramping down");
-
- continueStopOrFinish();
-}
-
-void RunControlPrivate::onWorkerStarted(RunWorker *worker)
-{
- worker->d->state = RunWorkerState::Running;
-
- if (state == RunControlState::Starting) {
- debugMessage(worker->d->id + " start succeeded");
- continueStart();
- return;
- }
- showError(RunControl::tr("Unexpected run control state %1 when worker %2 started.")
- .arg(stateName(state))
- .arg(worker->d->id));
-}
-
-void RunControlPrivate::onWorkerFailed(RunWorker *worker, const QString &msg)
-{
- worker->d->state = RunWorkerState::Done;
-
- showError(msg);
- switch (state) {
- case RunControlState::Initialized:
- // FIXME 1: We don't have an output pane yet, so use some other mechanism for now.
- // FIXME 2: Translation...
- QMessageBox::critical(Core::ICore::dialogParent(),
- QCoreApplication::translate("TaskHub", "Error"),
- QString("Failure during startup. Aborting.") + "<p>" + msg);
- continueStopOrFinish();
- break;
- case RunControlState::Starting:
- case RunControlState::Running:
- initiateStop();
- break;
- case RunControlState::Stopping:
- case RunControlState::Finishing:
- continueStopOrFinish();
- break;
- case RunControlState::Stopped:
- case RunControlState::Finished:
- QTC_CHECK(false); // Should not happen.
- continueStopOrFinish();
- break;
- }
-}
-
-void RunControlPrivate::onWorkerStopped(RunWorker *worker)
-{
- const QString &workerId = worker->d->id;
- switch (worker->d->state) {
- case RunWorkerState::Running:
- // That was a spontaneous stop.
- worker->d->state = RunWorkerState::Done;
- debugMessage(workerId + " stopped spontaneously.");
- break;
- case RunWorkerState::Stopping:
- worker->d->state = RunWorkerState::Done;
- debugMessage(workerId + " stopped expectedly.");
- break;
- case RunWorkerState::Done:
- worker->d->state = RunWorkerState::Done;
- debugMessage(workerId + " stopped twice. Huh? But harmless.");
- return; // Sic!
- default:
- debugMessage(workerId + " stopped unexpectedly in state"
- + stateName(worker->d->state));
- worker->d->state = RunWorkerState::Done;
- break;
- }
-
- if (state == RunControlState::Finishing || state == RunControlState::Stopping) {
- continueStopOrFinish();
- return;
- } else if (worker->isEssential()) {
- debugMessage(workerId + " is essential. Stopping all others.");
- initiateStop();
- return;
- }
-
- for (RunWorker *dependent : worker->d->stopDependencies) {
- switch (dependent->d->state) {
- case RunWorkerState::Done:
- break;
- case RunWorkerState::Initialized:
- dependent->d->state = RunWorkerState::Done;
- break;
- default:
- debugMessage("Killing " + dependent->d->id + " as it depends on stopped " + workerId);
- dependent->d->state = RunWorkerState::Stopping;
- QTimer::singleShot(0, dependent, &RunWorker::initiateStop);
- break;
- }
- }
-
- debugMessage("Checking whether all stopped");
- bool allDone = true;
- for (RunWorker *worker : m_workers) {
- if (worker) {
- const QString &workerId = worker->d->id;
- debugMessage(" Examining worker " + workerId);
- switch (worker->d->state) {
- case RunWorkerState::Initialized:
- debugMessage(" " + workerId + " was Initialized.");
- break;
- case RunWorkerState::Starting:
- debugMessage(" " + workerId + " was Starting, waiting for its response");
- allDone = false;
- break;
- case RunWorkerState::Running:
- debugMessage(" " + workerId + " was Running, waiting for its response");
- allDone = false;
- break;
- case RunWorkerState::Stopping:
- debugMessage(" " + workerId + " was already Stopping. Keeping it that way");
- allDone = false;
- break;
- case RunWorkerState::Done:
- debugMessage(" " + workerId + " was Done. Good.");
- break;
- }
- } else {
- debugMessage("Found unknown deleted worker");
- }
- }
-
- if (allDone) {
- if (state == RunControlState::Stopped) {
- debugMessage("All workers stopped, but runControl was already stopped.");
- } else {
- debugMessage("All workers stopped. Set runControl to Stopped");
- setState(RunControlState::Stopped);
- }
- } else {
- debugMessage("Not all workers stopped. Waiting...");
- }
-}
-
-void RunControlPrivate::showError(const QString &msg)
-{
- if (!msg.isEmpty())
- q->appendMessage(msg + '\n', ErrorMessageFormat);
-}
-
-Utils::OutputFormatter *RunControl::outputFormatter() const
-{
- return d->outputFormatter;
-}
-
-Core::Id RunControl::runMode() const
-{
- return d->runMode;
-}
-
-const Runnable &RunControl::runnable() const
-{
- return d->runnable;
-}
-
-void RunControl::setRunnable(const Runnable &runnable)
-{
- d->runnable = runnable;
-}
-
-QString RunControl::displayName() const
-{
- return d->displayName;
-}
-
-void RunControl::setDisplayName(const QString &displayName)
-{
- d->displayName = displayName;
-}
-
-void RunControl::setIcon(const Utils::Icon &icon)
-{
- d->icon = icon;
-}
-
-Utils::Icon RunControl::icon() const
-{
- return d->icon;
-}
-
-IDevice::ConstPtr RunControl::device() const
-{
- return d->device;
-}
-
-RunConfiguration *RunControl::runConfiguration() const
-{
- return d->runConfiguration.data();
-}
-
-Project *RunControl::project() const
-{
- return d->project.data();
-}
-
-/*!
- A handle to the application process.
-
- This is typically a process id, but should be treated as
- opaque handle to the process controled by this \c RunControl.
-*/
-
-ProcessHandle RunControl::applicationProcessHandle() const
-{
- return d->applicationProcessHandle;
-}
-
-void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
-{
- if (d->applicationProcessHandle != handle) {
- d->applicationProcessHandle = handle;
- emit applicationProcessHandleChanged(QPrivateSignal());
- }
-}
-
-/*!
- Prompts to stop. If \a optionalPrompt is passed, a \gui {Do not ask again}
- checkbox is displayed and the result is returned in \a *optionalPrompt.
-*/
-
-bool RunControl::promptToStop(bool *optionalPrompt) const
-{
- QTC_ASSERT(isRunning(), return true);
- if (optionalPrompt && !*optionalPrompt)
- return true;
-
- // Overridden.
- if (d->promptToStop)
- return d->promptToStop(optionalPrompt);
-
- const QString msg = tr("<html><head/><body><center><i>%1</i> is still running.<center/>"
- "<center>Force it to quit?</center></body></html>").arg(displayName());
- return showPromptToStopDialog(tr("Application Still Running"), msg,
- tr("Force &Quit"), tr("&Keep Running"),
- optionalPrompt);
-}
-
-void RunControl::setPromptToStop(const std::function<bool (bool *)> &promptToStop)
-{
- d->promptToStop = promptToStop;
-}
-
-bool RunControl::supportsReRunning() const
-{
- return d->supportsReRunning();
-}
-
-bool RunControlPrivate::supportsReRunning() const
-{
- for (RunWorker *worker : m_workers) {
- if (!worker->d->supportsReRunning)
- return false;
- if (worker->d->state != RunWorkerState::Done)
- return false;
- }
- return true;
-}
-
-bool RunControl::isRunning() const
-{
- return d->state == RunControlState::Running;
-}
-
-bool RunControl::isStarting() const
-{
- return d->state == RunControlState::Starting;
-}
-
-bool RunControl::isStopping() const
-{
- return d->state == RunControlState::Stopping;
-}
-
-bool RunControl::isStopped() const
-{
- return d->state == RunControlState::Stopped;
-}
-
-/*!
- Prompts to terminate the application with the \gui {Do not ask again}
- checkbox.
-*/
-
-bool RunControl::showPromptToStopDialog(const QString &title,
- const QString &text,
- const QString &stopButtonText,
- const QString &cancelButtonText,
- bool *prompt)
-{
- // Show a question message box where user can uncheck this
- // question for this class.
- Utils::CheckableMessageBox messageBox(Core::ICore::mainWindow());
- messageBox.setWindowTitle(title);
- messageBox.setText(text);
- messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::Cancel);
- if (!stopButtonText.isEmpty())
- messageBox.button(QDialogButtonBox::Yes)->setText(stopButtonText);
- if (!cancelButtonText.isEmpty())
- messageBox.button(QDialogButtonBox::Cancel)->setText(cancelButtonText);
- messageBox.setDefaultButton(QDialogButtonBox::Yes);
- if (prompt) {
- messageBox.setCheckBoxText(Utils::CheckableMessageBox::msgDoNotAskAgain());
- messageBox.setChecked(false);
- } else {
- messageBox.setCheckBoxVisible(false);
- }
- messageBox.exec();
- const bool close = messageBox.clickedStandardButton() == QDialogButtonBox::Yes;
- if (close && prompt && messageBox.isChecked())
- *prompt = false;
- return close;
-}
-
-bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlState to)
-{
- switch (from) {
- case RunControlState::Initialized:
- return to == RunControlState::Starting
- || to == RunControlState::Finishing;
- case RunControlState::Starting:
- return to == RunControlState::Running
- || to == RunControlState::Stopping
- || to == RunControlState::Finishing;
- case RunControlState::Running:
- return to == RunControlState::Stopping
- || to == RunControlState::Stopped
- || to == RunControlState::Finishing;
- case RunControlState::Stopping:
- return to == RunControlState::Stopped
- || to == RunControlState::Finishing;
- case RunControlState::Stopped:
- return to == RunControlState::Finishing;
- case RunControlState::Finishing:
- return to == RunControlState::Finished;
- case RunControlState::Finished:
- return false;
- }
- return false;
-}
-
-void RunControlPrivate::checkState(RunControlState expectedState)
-{
- if (state != expectedState)
- qDebug() << "Unexpected run control state " << stateName(expectedState)
- << " have: " << stateName(state);
-}
-
-void RunControlPrivate::setState(RunControlState newState)
-{
- if (!isAllowedTransition(state, newState))
- qDebug() << "Invalid run control state transition from " << stateName(state)
- << " to " << stateName(newState);
-
- state = newState;
-
- debugMessage("Entering state " + stateName(newState));
-
- // Extra reporting.
- switch (state) {
- case RunControlState::Running:
- emit q->started();
- break;
- case RunControlState::Stopped:
- q->setApplicationProcessHandle(Utils::ProcessHandle());
- emit q->stopped();
- break;
- case RunControlState::Finished:
- emit q->finished();
- debugMessage("All finished. Deleting myself");
- q->deleteLater();
- break;
- default:
- break;
- }
-}
-
-void RunControlPrivate::debugMessage(const QString &msg)
-{
- qCDebug(statesLog()) << msg;
-}
-
-void RunControl::appendMessage(const QString &msg, Utils::OutputFormat format)
-{
- emit appendMessageRequested(this, msg, format);
-}
-
-// SimpleTargetRunner
-
-SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
- : RunWorker(runControl)
-{
- setId("SimpleTargetRunner");
- m_runnable = runControl->runnable(); // Default value. Can be overridden using setRunnable.
- m_device = runControl->device(); // Default value. Can be overridden using setDevice.
- if (auto runConfig = runControl->runConfiguration()) {
- if (auto terminalAspect = runConfig->aspect<TerminalAspect>())
- m_useTerminal = terminalAspect->useTerminal();
- }
-}
-
-void SimpleTargetRunner::start()
-{
- m_stopReported = false;
- m_launcher.disconnect(this);
- m_launcher.setUseTerminal(m_useTerminal);
-
- const bool isDesktop = m_device.isNull()
- || m_device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
- const QString rawDisplayName = m_runnable.displayName();
- const QString displayName = isDesktop
- ? QDir::toNativeSeparators(rawDisplayName)
- : rawDisplayName;
- const QString msg = RunControl::tr("Starting %1 %2...")
- .arg(displayName).arg(m_runnable.commandLineArguments);
- appendMessage(msg, Utils::NormalMessageFormat);
-
- if (isDesktop) {
-
- connect(&m_launcher, &ApplicationLauncher::appendMessage,
- this, &SimpleTargetRunner::appendMessage);
- connect(&m_launcher, &ApplicationLauncher::processStarted,
- this, &SimpleTargetRunner::onProcessStarted);
- connect(&m_launcher, &ApplicationLauncher::processExited,
- this, &SimpleTargetRunner::onProcessFinished);
- connect(&m_launcher, &ApplicationLauncher::error,
- this, &SimpleTargetRunner::onProcessError);
-
- const QString executable = m_runnable.executable;
- if (executable.isEmpty()) {
- reportFailure(RunControl::tr("No executable specified."));
- } else {
- m_launcher.start(m_runnable);
- }
-
- } else {
-
- connect(&m_launcher, &ApplicationLauncher::reportError,
- this, [this](const QString &msg) {
- reportFailure(msg);
- });
-
- connect(&m_launcher, &ApplicationLauncher::remoteStderr,
- this, [this](const QString &output) {
- appendMessage(output, Utils::StdErrFormatSameLine, false);
- });
-
- connect(&m_launcher, &ApplicationLauncher::remoteStdout,
- this, [this](const QString &output) {
- appendMessage(output, Utils::StdOutFormatSameLine, false);
- });
-
- connect(&m_launcher, &ApplicationLauncher::finished,
- this, [this] {
- m_launcher.disconnect(this);
- reportStopped();
- });
-
- connect(&m_launcher, &ApplicationLauncher::processStarted,
- this, [this] {
- appendMessage("Application launcher started", Utils::NormalMessageFormat);
-// reportStarted();
- });
-
- connect(&m_launcher, &ApplicationLauncher::processExited,
- this, [this] {
- m_launcher.disconnect(this);
- reportStopped();
- });
-
- connect(&m_launcher, &ApplicationLauncher::remoteProcessStarted,
- this, [this] {
- reportStarted();
- });
-
- connect(&m_launcher, &ApplicationLauncher::reportProgress,
- this, [this](const QString &progressString) {
- appendMessage(progressString, Utils::NormalMessageFormat);
- });
-
- m_launcher.start(m_runnable, device());
- }
-}
-
-void SimpleTargetRunner::stop()
-{
- m_launcher.stop();
-}
-
-void SimpleTargetRunner::onProcessStarted()
-{
- // Console processes only know their pid after being started
- ProcessHandle pid = m_launcher.applicationPID();
- runControl()->setApplicationProcessHandle(pid);
- pid.activate();
- reportStarted();
-}
-
-void SimpleTargetRunner::onProcessFinished(int exitCode, QProcess::ExitStatus status)
-{
- QString msg;
- if (status == QProcess::CrashExit)
- msg = tr("%1 crashed.");
- else
- msg = tr("%2 exited with code %1").arg(exitCode);
- appendMessage(msg.arg(m_runnable.displayName()), Utils::NormalMessageFormat);
- if (!m_stopReported) {
- m_stopReported = true;
- reportStopped();
- }
-}
-
-void SimpleTargetRunner::onProcessError(QProcess::ProcessError error)
-{
- if (error == QProcess::Timedout)
- return; // No actual change on the process side.
- QString msg = userMessageForProcessError(error, m_runnable.displayName());
- appendMessage(msg, Utils::NormalMessageFormat);
- if (!m_stopReported) {
- m_stopReported = true;
- reportStopped();
- }
-}
-
-IDevice::ConstPtr SimpleTargetRunner::device() const
-{
- return m_device;
-}
-
-void SimpleTargetRunner::setRunnable(const Runnable &runnable)
-{
- m_runnable = runnable;
-}
-
-void SimpleTargetRunner::setDevice(const IDevice::ConstPtr &device)
-{
- m_device = device;
-}
-
-// RunWorkerPrivate
-
-RunWorkerPrivate::RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl)
- : q(runWorker), runControl(runControl)
-{
- runControl->d->m_workers.append(runWorker);
-}
-
-bool RunWorkerPrivate::canStart() const
-{
- if (state != RunWorkerState::Initialized)
- return false;
- for (RunWorker *worker : startDependencies) {
- QTC_ASSERT(worker, continue);
- if (worker->d->state != RunWorkerState::Done
- && worker->d->state != RunWorkerState::Running)
- return false;
- }
- return true;
-}
-
-bool RunWorkerPrivate::canStop() const
-{
- if (state != RunWorkerState::Starting && state != RunWorkerState::Running)
- return false;
- for (RunWorker *worker : stopDependencies) {
- QTC_ASSERT(worker, continue);
- if (worker->d->state != RunWorkerState::Done)
- return false;
- }
- return true;
-}
-
-void RunWorkerPrivate::timerEvent(QTimerEvent *ev)
-{
- if (ev->timerId() == startWatchdogTimerId) {
- if (startWatchdogCallback) {
- killStartWatchdog();
- startWatchdogCallback();
- } else {
- q->reportFailure(RunWorker::tr("Worker start timed out."));
- }
- return;
- }
- if (ev->timerId() == stopWatchdogTimerId) {
- if (stopWatchdogCallback) {
- killStopWatchdog();
- stopWatchdogCallback();
- } else {
- q->reportFailure(RunWorker::tr("Worker stop timed out."));
- }
- return;
- }
-}
-
-/*!
- \class ProjectExplorer::RunWorker
-
- \brief The RunWorker class encapsulates a task that forms part, or
- the whole of the operation of a tool for a certain \c RunConfiguration
- according to some \c RunMode.
-
- A typical example for a \c RunWorker is a process, either the
- application process itself, or a helper process, such as a watchdog
- or a log parser.
-
- A \c RunWorker has a simple state model covering the \c Initialized,
- \c Starting, \c Running, \c Stopping, and \c Done states.
-
- In the course of the operation of tools several \c RunWorkers
- may co-operate and form a combined state that is presented
- to the user as \c RunControl, with direct interaction made
- possible through the buttons in the \uicontrol{Application Output}
- pane.
-
- RunWorkers are typically created together with their RunControl.
- The startup order of RunWorkers under a RunControl can be
- specified by making a RunWorker dependent on others.
-
- When a RunControl starts, it calls \c initiateStart() on RunWorkers
- with fulfilled dependencies until all workers are \c Running, or in case
- of short-lived helper tasks, \c Done.
-
- A RunWorker can stop spontaneously, for example when the main application
- process ends. In this case, it typically calls \c initiateStop()
- on its RunControl, which in turn passes this to all sibling
- RunWorkers.
-
- Pressing the stop button in the \uicontrol{Application Output} pane
- also calls \c initiateStop on the RunControl.
-*/
-
-RunWorker::RunWorker(RunControl *runControl)
- : d(std::make_unique<RunWorkerPrivate>(this, runControl))
-{ }
-
-RunWorker::~RunWorker() = default;
-
-/*!
- * This function is called by the RunControl once all dependencies
- * are fulfilled.
- */
-void RunWorker::initiateStart()
-{
- d->startStartWatchdog();
- d->runControl->d->debugMessage("Initiate start for " + d->id);
- start();
-}
-
-/*!
- * This function has to be called by a RunWorker implementation
- * to notify its RunControl about the successful start of this RunWorker.
- *
- * The RunControl may start other RunWorkers in response.
- */
-void RunWorker::reportStarted()
-{
- d->killStartWatchdog();
- d->runControl->d->onWorkerStarted(this);
- emit started();
-}
-
-/*!
- * This function is called by the RunControl in its own \c initiateStop
- * implementation, which is triggered in response to pressing the
- * stop button in the \uicontrol{Application Output} pane or on direct
- * request of one of the sibling RunWorkers.
- */
-void RunWorker::initiateStop()
-{
- d->startStopWatchdog();
- d->runControl->d->debugMessage("Initiate stop for " + d->id);
- stop();
-}
-
-/*!
- * This function has to be called by a RunWorker implementation
- * to notify its RunControl about this RunWorker having stopped.
- *
- * The stop can be spontaneous, or in response to an initiateStop()
- * or an initiateFinish() call.
- *
- * The RunControl will adjust its global state in response.
- */
-void RunWorker::reportStopped()
-{
- d->killStopWatchdog();
- d->runControl->d->onWorkerStopped(this);
- emit stopped();
-}
-
-/*!
- * This function can be called by a RunWorker implementation for short-lived
- * tasks to notify its RunControl about this task being successful finished.
- * Dependent startup tasks can proceed, in cases of spontaneous or scheduled
- * stops, the effect is the same as \c reportStopped().
- *
- */
-void RunWorker::reportDone()
-{
- d->killStartWatchdog();
- d->killStopWatchdog();
- switch (d->state) {
- case RunWorkerState::Initialized:
- QTC_CHECK(false);
- d->state = RunWorkerState::Done;
- break;
- case RunWorkerState::Starting:
- reportStarted();
- reportStopped();
- break;
- case RunWorkerState::Running:
- case RunWorkerState::Stopping:
- reportStopped();
- break;
- case RunWorkerState::Done:
- break;
- }
-}
-
-/*!
- * This function can be called by a RunWorker implementation to
- * signal a problem in the operation in this worker. The
- * RunControl will start to ramp down through initiateStop().
- */
-void RunWorker::reportFailure(const QString &msg)
-{
- d->killStartWatchdog();
- d->killStopWatchdog();
- d->runControl->d->onWorkerFailed(this, 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)
-{
- if (!appendNewLine || msg.endsWith('\n'))
- d->runControl->appendMessage(msg, format);
- else
- d->runControl->appendMessage(msg + '\n', format);
-}
-
-IDevice::ConstPtr RunWorker::device() const
-{
- return d->runControl->device();
-}
-
-const Runnable &RunWorker::runnable() const
-{
- return d->runControl->runnable();
-}
-
-Core::Id RunWorker::runMode() const
-{
- return d->runControl->runMode();
-}
-
-void RunWorker::addStartDependency(RunWorker *dependency)
-{
- d->startDependencies.append(dependency);
-}
-
-void RunWorker::addStopDependency(RunWorker *dependency)
-{
- d->stopDependencies.append(dependency);
-}
-
-RunControl *RunWorker::runControl() const
-{
- return d->runControl;
-}
-
-void RunWorker::setId(const QString &id)
-{
- d->id = id;
-}
-
-void RunWorker::setStartTimeout(int ms, const std::function<void()> &callback)
-{
- d->startWatchdogInterval = ms;
- d->startWatchdogCallback = callback;
-}
-
-void RunWorker::setStopTimeout(int ms, const std::function<void()> &callback)
-{
- d->stopWatchdogInterval = ms;
- d->stopWatchdogCallback = callback;
-}
-
-void RunWorker::recordData(const QString &channel, const QVariant &data)
-{
- d->data[channel] = data;
-}
-
-QVariant RunWorker::recordedData(const QString &channel) const
-{
- return d->data[channel];
-}
-
-void RunWorker::setSupportsReRunning(bool reRunningSupported)
-{
- d->supportsReRunning = reRunningSupported;
-}
-
-bool RunWorker::supportsReRunning() const
-{
- return d->supportsReRunning;
-}
-
-QString RunWorker::userMessageForProcessError(QProcess::ProcessError error, const QString &program)
-{
- QString failedToStart = tr("The process failed to start.");
- QString msg = tr("An unknown error in the process occurred.");
- switch (error) {
- case QProcess::FailedToStart:
- msg = failedToStart + ' ' + tr("Either the "
- "invoked program \"%1\" is missing, or you may have insufficient "
- "permissions to invoke the program.").arg(program);
- break;
- case QProcess::Crashed:
- msg = tr("The process was ended forcefully.");
- break;
- case QProcess::Timedout:
- // "The last waitFor...() function timed out. "
- // "The state of QProcess is unchanged, and you can try calling "
- // "waitFor...() again."
- return QString(); // sic!
- case QProcess::WriteError:
- msg = 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::ReadError:
- msg = tr("An error occurred when attempting to read from "
- "the process. For example, the process may not be running.");
- break;
- case QProcess::UnknownError:
- break;
- }
- return msg;
-}
-
-bool RunWorker::isEssential() const
-{
- return d->essential;
-}
-
-void RunWorker::setEssential(bool essential)
-{
- d->essential = essential;
-}
-
-void RunWorker::start()
-{
- reportStarted();
-}
-
-void RunWorker::stop()
-{
- reportStopped();
-}
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index c0443ae07e..3e5cbc6b15 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -50,7 +50,7 @@ namespace Utils { class OutputFormatter; }
namespace ProjectExplorer {
class BuildConfiguration;
class GlobalOrProjectAspect;
-class Node;
+class Runnable;
class RunConfigurationFactory;
class RunConfiguration;
class RunConfigurationCreationInfo;
@@ -129,24 +129,8 @@ private:
ISettingsAspect *m_globalSettings = nullptr; // Not owned.
};
-class PROJECTEXPLORER_EXPORT Runnable
-{
-public:
- Runnable() = default;
-
- QString executable;
- QString commandLineArguments;
- QString workingDirectory;
- Utils::Environment environment;
- IDevice::ConstPtr device; // Override the kit's device. Keep unset by default.
- QHash<Core::Id, QVariant> extraData;
-
- // FIXME: Not necessarily a display name
- QString displayName() const { return executable; }
-};
-
// Documentation inside.
-class PROJECTEXPLORER_EXPORT RunConfiguration : public StatefulProjectConfiguration
+class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
{
Q_OBJECT
@@ -155,7 +139,10 @@ public:
bool isActive() const override;
- QString disabledReason() const override;
+ bool isEnabled() const { return m_isEnabled; }
+ void setEnabled(bool enabled);
+
+ virtual QString disabledReason() const;
virtual QWidget *createConfigurationWidget();
@@ -173,6 +160,10 @@ public:
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
+ using ExecutableGetter = std::function<Utils::FilePath()>;
+ void setExecutableGetter(const ExecutableGetter &exeGetter);
+ Utils::FilePath executable() const;
+
virtual Runnable runnable() const;
// Return a handle to the build system target that created this run configuration.
@@ -182,7 +173,6 @@ public:
BuildTargetInfo buildTargetInfo() const;
static RunConfiguration *startupRunConfiguration();
- virtual bool canRunForNode(const ProjectExplorer::Node *) const { return false; }
template <class T = ISettingsAspect> T *currentSettings(Core::Id id) const
{
@@ -200,6 +190,7 @@ public:
signals:
void requestRunActionsUpdate();
void configurationFinished();
+ void enabledChanged();
protected:
RunConfiguration(Target *target, Core::Id id);
@@ -221,7 +212,9 @@ private:
friend class RunConfigurationCreationInfo;
QString m_buildKey;
+ bool m_isEnabled = false;
std::function<Utils::OutputFormatter *(Project *)> m_outputFormatterCreator;
+ ExecutableGetter m_executableGetter;
};
class RunConfigurationCreationInfo
@@ -235,6 +228,7 @@ public:
QString buildKey;
QString displayName;
QString displayNameUniquifier;
+ Utils::FilePath projectFilePath;
CreationMode creationMode = AlwaysCreate;
bool useTerminal = false;
};
@@ -267,25 +261,13 @@ protected:
return new RunConfig(t, runConfigBaseId);
};
m_runConfigBaseId = runConfigBaseId;
- m_ownTypeChecker = [](RunConfiguration *runConfig) {
- return qobject_cast<RunConfig *>(runConfig) != nullptr;
- };
}
void addSupportedProjectType(Core::Id id);
void addSupportedTargetDeviceType(Core::Id id);
void setDecorateDisplayNames(bool on);
- template<class Worker>
- RunWorkerFactory *addRunWorkerFactory(Core::Id runMode)
- {
- return addRunWorkerFactoryHelper(runMode, [](RunControl *rc) { return new Worker(rc); });
- }
-
private:
- RunWorkerFactory *addRunWorkerFactoryHelper
- (Core::Id runMode, const std::function<RunWorker *(RunControl *)> &creator);
-
bool canHandle(Target *target) const;
friend class RunConfigurationCreationInfo;
@@ -294,8 +276,6 @@ private:
QList<Core::Id> m_supportedProjectTypes;
QList<Core::Id> m_supportedTargetDeviceTypes;
bool m_decorateDisplayNames = false;
- QList<RunWorkerFactory *> m_ownedRunWorkerFactories;
- std::function<bool(RunConfiguration *)> m_ownTypeChecker;
};
class PROJECTEXPLORER_EXPORT FixedRunConfigurationFactory : public RunConfigurationFactory
@@ -311,227 +291,4 @@ private:
const bool m_decorateTargetName;
};
-class PROJECTEXPLORER_EXPORT RunWorker : public QObject
-{
- Q_OBJECT
-
-public:
- explicit RunWorker(RunControl *runControl);
- ~RunWorker() override;
-
- RunControl *runControl() const;
-
- void addStartDependency(RunWorker *dependency);
- void addStopDependency(RunWorker *dependency);
-
- void setId(const QString &id);
-
- void setStartTimeout(int ms, const std::function<void()> &callback = {});
- void setStopTimeout(int ms, const std::function<void()> &callback = {});
-
- void recordData(const QString &channel, const QVariant &data);
- 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;
- Core::Id runMode() const;
-
- // States
- void initiateStart();
- void reportStarted();
-
- void initiateStop();
- void reportStopped();
-
- void reportDone();
-
- void reportFailure(const QString &msg = QString());
- void setSupportsReRunning(bool reRunningSupported);
- bool supportsReRunning() const;
-
- static QString userMessageForProcessError(QProcess::ProcessError, const QString &programName);
-
- bool isEssential() const;
- void setEssential(bool essential);
-
-signals:
- void started();
- void stopped();
-
-protected:
- void virtual start();
- void virtual stop();
- void virtual onFinished() {}
-
-private:
- friend class Internal::RunControlPrivate;
- friend class Internal::RunWorkerPrivate;
- const std::unique_ptr<Internal::RunWorkerPrivate> d;
-};
-
-class PROJECTEXPLORER_EXPORT RunWorkerFactory
-{
-public:
- using WorkerCreator = std::function<RunWorker *(RunControl *)>;
- using Constraint = std::function<bool(RunConfiguration *)>;
-
- RunWorkerFactory();
- virtual ~RunWorkerFactory();
-
- bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const;
-
- void setProducer(const WorkerCreator &producer);
- void addConstraint(const Constraint &constraint);
- void addSupportedRunMode(Core::Id runMode);
-
- WorkerCreator producer() const { return m_producer; }
-
-private:
- // FIXME: That's temporary until ownership has been transferred to
- // the individual plugins.
- friend class ProjectExplorerPlugin;
- static void destroyRemainingRunWorkerFactories();
-
- QList<Core::Id> m_supportedRunModes;
- QList<Constraint> m_constraints;
- WorkerCreator m_producer;
-};
-
-/**
- * A RunControl controls the running of an application or tool
- * on a target device. It controls start and stop, and handles
- * application output.
- *
- * RunControls are created by RunControlFactories.
- */
-
-class PROJECTEXPLORER_EXPORT RunControl : public QObject
-{
- Q_OBJECT
-
-public:
- RunControl(RunConfiguration *runConfiguration, Core::Id mode);
- RunControl(const IDevice::ConstPtr &device, Core::Id mode);
- ~RunControl() override;
-
- void initiateStart();
- void initiateReStart();
- void initiateStop();
- void forceStop();
- void initiateFinish();
-
- bool promptToStop(bool *optionalPrompt = nullptr) const;
- void setPromptToStop(const std::function<bool(bool *)> &promptToStop);
-
- bool supportsReRunning() const;
-
- virtual QString displayName() const;
- void setDisplayName(const QString &displayName);
-
- bool isRunning() const;
- bool isStarting() const;
- bool isStopping() const;
- bool isStopped() const;
-
- void setIcon(const Utils::Icon &icon);
- Utils::Icon icon() const;
-
- Utils::ProcessHandle applicationProcessHandle() const;
- void setApplicationProcessHandle(const Utils::ProcessHandle &handle);
- IDevice::ConstPtr device() const;
-
- RunConfiguration *runConfiguration() const;
- Project *project() const;
-
- Utils::OutputFormatter *outputFormatter() const;
- Core::Id runMode() const;
-
- const Runnable &runnable() const;
- void setRunnable(const Runnable &runnable);
-
- virtual void appendMessage(const QString &msg, Utils::OutputFormat format);
-
- static bool showPromptToStopDialog(const QString &title, const QString &text,
- const QString &stopButtonText = QString(),
- const QString &cancelButtonText = QString(),
- bool *prompt = nullptr);
-
- RunWorker *createWorker(Core::Id id);
-
- using WorkerCreator = RunWorkerFactory::WorkerCreator;
- using Constraint = RunWorkerFactory::Constraint;
-
- static void registerWorkerCreator(Core::Id id, const WorkerCreator &workerCreator);
-
- static void registerWorker(Core::Id runMode, const WorkerCreator &producer,
- const Constraint &constraint = {})
- {
- auto factory = new RunWorkerFactory;
- factory->setProducer(producer);
- factory->addSupportedRunMode(runMode);
- factory->addConstraint(constraint);
- }
- template <class Worker>
- static void registerWorker(Core::Id runMode, const Constraint &constraint)
- {
- auto factory = new RunWorkerFactory;
- factory->setProducer([](RunControl *rc) { return new Worker(rc); });
- factory->addSupportedRunMode(runMode);
- factory->addConstraint(constraint);
- }
-
- static WorkerCreator producer(RunConfiguration *runConfiguration, Core::Id runMode);
-
-signals:
- void appendMessageRequested(ProjectExplorer::RunControl *runControl,
- const QString &msg, Utils::OutputFormat format);
- void aboutToStart();
- void started();
- void stopped();
- void finished();
- void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
-
-private:
- friend class RunWorker;
- friend class Internal::RunWorkerPrivate;
-
- const std::unique_ptr<Internal::RunControlPrivate> d;
-};
-
-
-/**
- * A simple TargetRunner for cases where a plain ApplicationLauncher is
- * sufficient for running purposes.
- */
-
-class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public RunWorker
-{
- Q_OBJECT
-
-public:
- explicit SimpleTargetRunner(RunControl *runControl);
-
- void setRunnable(const Runnable &runnable);
-
- void setDevice(const IDevice::ConstPtr &device);
- IDevice::ConstPtr device() const;
-
-protected:
- void start() override;
- void stop() override;
-
-private:
- void onProcessStarted();
- void onProcessFinished(int exitCode, QProcess::ExitStatus status);
- void onProcessError(QProcess::ProcessError error);
-
- ApplicationLauncher m_launcher;
- Runnable m_runnable;
- IDevice::ConstPtr m_device;
- bool m_stopReported = false;
- bool m_useTerminal = false;
-};
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp
index 06aa1e583e..fe890b3a29 100644
--- a/src/plugins/projectexplorer/runconfigurationaspects.cpp
+++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp
@@ -56,6 +56,9 @@ TerminalAspect::TerminalAspect()
setDisplayName(tr("Terminal"));
setId("TerminalAspect");
setSettingsKey("RunConfiguration.UseTerminal");
+ calculateUseTerminal();
+ connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
+ this, &TerminalAspect::calculateUseTerminal);
}
void TerminalAspect::addToConfigurationLayout(QFormLayout *layout)
@@ -90,13 +93,16 @@ void TerminalAspect::toMap(QVariantMap &data) const
data.insert(settingsKey(), m_useTerminal);
}
-bool TerminalAspect::useTerminal() const
-{
- return m_useTerminal;
-}
-
-void TerminalAspect::setUseTerminal(bool useTerminal)
+void TerminalAspect::calculateUseTerminal()
{
+ if (m_userSet)
+ return;
+ bool useTerminal;
+ switch (ProjectExplorerPlugin::projectExplorerSettings().terminalMode) {
+ case Internal::TerminalMode::On: useTerminal = true; break;
+ case Internal::TerminalMode::Off: useTerminal = false; break;
+ case Internal::TerminalMode::Smart: useTerminal = m_useTerminalHint;
+ }
if (m_useTerminal != useTerminal) {
m_useTerminal = useTerminal;
emit changed();
@@ -105,6 +111,17 @@ void TerminalAspect::setUseTerminal(bool useTerminal)
m_checkBox->setChecked(m_useTerminal);
}
+bool TerminalAspect::useTerminal() const
+{
+ return m_useTerminal;
+}
+
+void TerminalAspect::setUseTerminalHint(bool hint)
+{
+ m_useTerminalHint = hint;
+ calculateUseTerminal();
+}
+
bool TerminalAspect::isUserSet() const
{
return m_userSet;
@@ -114,8 +131,7 @@ bool TerminalAspect::isUserSet() const
\class ProjectExplorer::WorkingDirectoryAspect
*/
-WorkingDirectoryAspect::WorkingDirectoryAspect(EnvironmentAspect *envAspect)
- : m_envAspect(envAspect)
+WorkingDirectoryAspect::WorkingDirectoryAspect()
{
setDisplayName(tr("Working Directory"));
setId("WorkingDirectoryAspect");
@@ -125,11 +141,6 @@ WorkingDirectoryAspect::WorkingDirectoryAspect(EnvironmentAspect *envAspect)
void WorkingDirectoryAspect::addToConfigurationLayout(QFormLayout *layout)
{
QTC_CHECK(!m_chooser);
- m_resetButton = new QToolButton(layout->parentWidget());
- m_resetButton->setToolTip(tr("Reset to Default"));
- m_resetButton->setIcon(Utils::Icons::RESET.icon());
- connect(m_resetButton.data(), &QAbstractButton::clicked, this, &WorkingDirectoryAspect::resetPath);
-
m_chooser = new PathChooser(layout->parentWidget());
m_chooser->setHistoryCompleter(settingsKey());
m_chooser->setExpectedKind(Utils::PathChooser::Directory);
@@ -142,6 +153,10 @@ void WorkingDirectoryAspect::addToConfigurationLayout(QFormLayout *layout)
m_resetButton->setEnabled(m_workingDirectory != m_defaultWorkingDirectory);
});
+ m_resetButton = new QToolButton(layout->parentWidget());
+ m_resetButton->setToolTip(tr("Reset to Default"));
+ m_resetButton->setIcon(Utils::Icons::RESET.icon());
+ connect(m_resetButton.data(), &QAbstractButton::clicked, this, &WorkingDirectoryAspect::resetPath);
m_resetButton->setEnabled(m_workingDirectory != m_defaultWorkingDirectory);
if (m_envAspect) {
@@ -157,6 +172,11 @@ void WorkingDirectoryAspect::addToConfigurationLayout(QFormLayout *layout)
layout->addRow(tr("Working directory:"), hbox);
}
+void WorkingDirectoryAspect::acquaintSiblings(const ProjectConfigurationAspects &siblings)
+{
+ m_envAspect = siblings.aspect<EnvironmentAspect>();
+}
+
QString WorkingDirectoryAspect::keyForDefaultWd() const
{
return settingsKey() + ".default";
@@ -169,8 +189,8 @@ void WorkingDirectoryAspect::resetPath()
void WorkingDirectoryAspect::fromMap(const QVariantMap &map)
{
- m_workingDirectory = FileName::fromString(map.value(settingsKey()).toString());
- m_defaultWorkingDirectory = FileName::fromString(map.value(keyForDefaultWd()).toString());
+ m_workingDirectory = FilePath::fromString(map.value(settingsKey()).toString());
+ m_defaultWorkingDirectory = FilePath::fromString(map.value(keyForDefaultWd()).toString());
if (m_workingDirectory.isEmpty())
m_workingDirectory = m_defaultWorkingDirectory;
@@ -187,32 +207,32 @@ void WorkingDirectoryAspect::toMap(QVariantMap &data) const
data.insert(keyForDefaultWd(), m_defaultWorkingDirectory.toString());
}
-FileName WorkingDirectoryAspect::workingDirectory(const MacroExpander *expander) const
+FilePath WorkingDirectoryAspect::workingDirectory(const MacroExpander *expander) const
{
const Utils::Environment env = m_envAspect ? m_envAspect->environment()
: Utils::Environment::systemEnvironment();
QString workingDir = m_workingDirectory.toUserOutput();
if (expander)
workingDir = expander->expandProcessArgs(workingDir);
- return FileName::fromString(PathChooser::expandedDirectory(workingDir, env, QString()));
+ return FilePath::fromString(PathChooser::expandedDirectory(workingDir, env, QString()));
}
-FileName WorkingDirectoryAspect::defaultWorkingDirectory() const
+FilePath WorkingDirectoryAspect::defaultWorkingDirectory() const
{
return m_defaultWorkingDirectory;
}
-FileName WorkingDirectoryAspect::unexpandedWorkingDirectory() const
+FilePath WorkingDirectoryAspect::unexpandedWorkingDirectory() const
{
return m_workingDirectory;
}
-void WorkingDirectoryAspect::setDefaultWorkingDirectory(const FileName &defaultWorkingDir)
+void WorkingDirectoryAspect::setDefaultWorkingDirectory(const FilePath &defaultWorkingDir)
{
if (defaultWorkingDir == m_defaultWorkingDirectory)
return;
- Utils::FileName oldDefaultDir = m_defaultWorkingDirectory;
+ Utils::FilePath oldDefaultDir = m_defaultWorkingDirectory;
m_defaultWorkingDirectory = defaultWorkingDir;
if (m_chooser)
m_chooser->setBaseFileName(m_defaultWorkingDirectory);
@@ -360,7 +380,7 @@ void ExecutableAspect::makeOverridable(const QString &overridingKey, const QStri
this, &ExecutableAspect::changed);
}
-FileName ExecutableAspect::executable() const
+FilePath ExecutableAspect::executable() const
{
if (m_alternativeExecutable && m_alternativeExecutable->isChecked())
return m_alternativeExecutable->fileName();
@@ -385,7 +405,7 @@ void ExecutableAspect::setPlaceHolderText(const QString &placeHolderText)
m_executable.setPlaceHolderText(placeHolderText);
}
-void ExecutableAspect::setExecutable(const FileName &executable)
+void ExecutableAspect::setExecutable(const FilePath &executable)
{
m_executable.setValue(executable.toString());
}
diff --git a/src/plugins/projectexplorer/runconfigurationaspects.h b/src/plugins/projectexplorer/runconfigurationaspects.h
index be40af6d29..77973f65f4 100644
--- a/src/plugins/projectexplorer/runconfigurationaspects.h
+++ b/src/plugins/projectexplorer/runconfigurationaspects.h
@@ -46,7 +46,7 @@ public:
void addToConfigurationLayout(QFormLayout *layout) override;
bool useTerminal() const;
- void setUseTerminal(bool useTerminal);
+ void setUseTerminalHint(bool useTerminal);
bool isUserSet() const;
@@ -54,6 +54,9 @@ private:
void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override;
+ void calculateUseTerminal();
+
+ bool m_useTerminalHint = false;
bool m_useTerminal = false;
bool m_userSet = false;
QPointer<QCheckBox> m_checkBox; // Owned by RunConfigWidget
@@ -64,14 +67,15 @@ class PROJECTEXPLORER_EXPORT WorkingDirectoryAspect : public ProjectConfiguratio
Q_OBJECT
public:
- explicit WorkingDirectoryAspect(EnvironmentAspect *envAspect = nullptr);
+ WorkingDirectoryAspect();
void addToConfigurationLayout(QFormLayout *layout) override;
+ void acquaintSiblings(const ProjectConfigurationAspects &) override;
- Utils::FileName workingDirectory(const Utils::MacroExpander *expander) const;
- Utils::FileName defaultWorkingDirectory() const;
- Utils::FileName unexpandedWorkingDirectory() const;
- void setDefaultWorkingDirectory(const Utils::FileName &defaultWorkingDir);
+ Utils::FilePath workingDirectory(const Utils::MacroExpander *expander) const;
+ Utils::FilePath defaultWorkingDirectory() const;
+ Utils::FilePath unexpandedWorkingDirectory() const;
+ void setDefaultWorkingDirectory(const Utils::FilePath &defaultWorkingDir);
Utils::PathChooser *pathChooser() const;
private:
@@ -81,9 +85,9 @@ private:
void resetPath();
QString keyForDefaultWd() const;
- EnvironmentAspect * const m_envAspect = nullptr;
- Utils::FileName m_workingDirectory;
- Utils::FileName m_defaultWorkingDirectory;
+ EnvironmentAspect *m_envAspect = nullptr;
+ Utils::FilePath m_workingDirectory;
+ Utils::FilePath m_defaultWorkingDirectory;
QPointer<Utils::PathChooser> m_chooser;
QPointer<QToolButton> m_resetButton;
};
@@ -137,8 +141,8 @@ public:
ExecutableAspect();
~ExecutableAspect() override;
- Utils::FileName executable() const;
- void setExecutable(const Utils::FileName &executable);
+ Utils::FilePath executable() const;
+ void setExecutable(const Utils::FilePath &executable);
void setSettingsKey(const QString &key);
void makeOverridable(const QString &overridingKey, const QString &useOverridableKey);
diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp
new file mode 100644
index 0000000000..f90a8fd48c
--- /dev/null
+++ b/src/plugins/projectexplorer/runcontrol.cpp
@@ -0,0 +1,1563 @@
+/****************************************************************************
+**
+** 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 "runcontrol.h"
+
+#include "project.h"
+#include "target.h"
+#include "toolchain.h"
+#include "abi.h"
+#include "buildconfiguration.h"
+#include "environmentaspect.h"
+#include "kitinformation.h"
+#include "runconfigurationaspects.h"
+#include "session.h"
+#include "kitinformation.h"
+
+#include <utils/algorithm.h>
+#include <utils/checkablemessagebox.h>
+#include <utils/detailswidget.h>
+#include <utils/outputformatter.h>
+#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
+
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/variablechooser.h>
+
+#include <QDir>
+#include <QFormLayout>
+#include <QHash>
+#include <QPushButton>
+#include <QTimer>
+#include <QLoggingCategory>
+#include <QSettings>
+
+#if defined (WITH_JOURNALD)
+#include "journaldwatcher.h"
+#endif
+
+using namespace Utils;
+using namespace ProjectExplorer::Internal;
+
+namespace {
+Q_LOGGING_CATEGORY(statesLog, "qtc.projectmanager.states", QtWarningMsg)
+}
+
+namespace ProjectExplorer {
+
+// RunWorkerFactory
+
+static QList<RunWorkerFactory *> g_runWorkerFactories;
+
+RunWorkerFactory::RunWorkerFactory()
+{
+ g_runWorkerFactories.append(this);
+}
+
+RunWorkerFactory::~RunWorkerFactory()
+{
+ g_runWorkerFactories.removeOne(this);
+}
+
+bool RunWorkerFactory::canRun(RunConfiguration *runConfiguration, Core::Id runMode) const
+{
+ if (!m_supportedRunModes.contains(runMode))
+ return false;
+
+ if (!m_supportedRunConfigurations.isEmpty()) {
+ if (!m_supportedRunConfigurations.contains(runConfiguration->id()))
+ return false;
+ }
+
+ for (const Constraint &constraint : m_constraints) {
+ if (!constraint(runConfiguration))
+ return false;
+ }
+
+ return true;
+}
+
+void RunWorkerFactory::setProducer(const WorkerCreator &producer)
+{
+ m_producer = producer;
+}
+
+void RunWorkerFactory::addConstraint(const Constraint &constraint)
+{
+ // Default constructed Constraints are not worth keeping.
+ // FIXME: Make it a QTC_ASSERT once there is no code path
+ // using this "feature" anymore.
+ if (!constraint)
+ return;
+ m_constraints.append(constraint);
+}
+
+void RunWorkerFactory::addSupportedRunMode(Core::Id runMode)
+{
+ m_supportedRunModes.append(runMode);
+}
+
+void RunWorkerFactory::setSupportedRunConfigurations(const QList<Core::Id> &ids)
+{
+ m_supportedRunConfigurations = ids;
+}
+
+void RunWorkerFactory::addSupportedRunConfiguration(Core::Id id)
+{
+ m_supportedRunConfigurations.append(id);
+}
+
+void RunWorkerFactory::destroyRemainingRunWorkerFactories()
+{
+ qDeleteAll(g_runWorkerFactories);
+}
+
+/*!
+ \class ProjectExplorer::RunControl
+ \brief The RunControl class instances represent one item that is run.
+*/
+
+/*!
+ \fn QIcon ProjectExplorer::RunControl::icon() const
+ Returns the icon to be shown in the Outputwindow.
+
+ TODO the icon differs currently only per "mode", so this is more flexible
+ than it needs to be.
+*/
+
+
+namespace Internal {
+
+enum class RunWorkerState
+{
+ Initialized, Starting, Running, Stopping, Done
+};
+
+static QString stateName(RunWorkerState s)
+{
+# define SN(x) case x: return QLatin1String(#x);
+ switch (s) {
+ SN(RunWorkerState::Initialized)
+ SN(RunWorkerState::Starting)
+ SN(RunWorkerState::Running)
+ SN(RunWorkerState::Stopping)
+ SN(RunWorkerState::Done)
+ }
+ return QString("<unknown: %1>").arg(int(s));
+# undef SN
+}
+
+class RunWorkerPrivate : public QObject
+{
+public:
+ RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl);
+
+ bool canStart() const;
+ bool canStop() const;
+ void timerEvent(QTimerEvent *ev) override;
+
+ void killStartWatchdog()
+ {
+ if (startWatchdogTimerId != -1) {
+ killTimer(startWatchdogTimerId);
+ startWatchdogTimerId = -1;
+ }
+ }
+
+ void killStopWatchdog()
+ {
+ if (stopWatchdogTimerId != -1) {
+ killTimer(stopWatchdogTimerId);
+ stopWatchdogTimerId = -1;
+ }
+ }
+
+ void startStartWatchdog()
+ {
+ killStartWatchdog();
+ killStopWatchdog();
+
+ if (startWatchdogInterval != 0)
+ startWatchdogTimerId = startTimer(startWatchdogInterval);
+ }
+
+ void startStopWatchdog()
+ {
+ killStopWatchdog();
+ killStartWatchdog();
+
+ if (stopWatchdogInterval != 0)
+ stopWatchdogTimerId = startTimer(stopWatchdogInterval);
+ }
+
+ RunWorker *q;
+ RunWorkerState state = RunWorkerState::Initialized;
+ const QPointer<RunControl> runControl;
+ QList<RunWorker *> startDependencies;
+ QList<RunWorker *> stopDependencies;
+ QString id;
+
+ QVariantMap data;
+ int startWatchdogInterval = 0;
+ int startWatchdogTimerId = -1;
+ std::function<void()> startWatchdogCallback;
+ int stopWatchdogInterval = 0; // 5000;
+ int stopWatchdogTimerId = -1;
+ std::function<void()> stopWatchdogCallback;
+ bool supportsReRunning = true;
+ bool essential = false;
+};
+
+enum class RunControlState
+{
+ Initialized, // Default value after creation.
+ Starting, // Actual process/tool starts.
+ Running, // All good and running.
+ Stopping, // initiateStop() was called, stop application/tool
+ Stopped, // all good, but stopped. Can possibly be re-started
+ Finishing, // Application tab manually closed
+ Finished // Final state, will self-destruct with deleteLater()
+};
+
+static QString stateName(RunControlState s)
+{
+# define SN(x) case x: return QLatin1String(#x);
+ switch (s) {
+ SN(RunControlState::Initialized)
+ SN(RunControlState::Starting)
+ SN(RunControlState::Running)
+ SN(RunControlState::Stopping)
+ SN(RunControlState::Stopped)
+ SN(RunControlState::Finishing)
+ SN(RunControlState::Finished)
+ }
+ return QString("<unknown: %1>").arg(int(s));
+# undef SN
+}
+
+class RunControlPrivate : public QObject
+{
+public:
+ RunControlPrivate(RunControl *parent, Core::Id mode)
+ : q(parent), runMode(mode)
+ {
+ icon = Icons::RUN_SMALL_TOOLBAR;
+ outputFormatter = new OutputFormatter();
+ }
+
+ ~RunControlPrivate() override
+ {
+ QTC_CHECK(state == RunControlState::Finished || state == RunControlState::Initialized);
+ disconnect();
+ q = nullptr;
+ qDeleteAll(m_workers);
+ m_workers.clear();
+ delete outputFormatter;
+ }
+
+ Q_ENUM(RunControlState)
+
+ void checkState(RunControlState expectedState);
+ void setState(RunControlState state);
+
+ void debugMessage(const QString &msg);
+
+ void initiateStart();
+ void initiateReStart();
+ void continueStart();
+ void initiateStop();
+ void forceStop();
+ void continueStopOrFinish();
+ void initiateFinish();
+
+ void onWorkerStarted(RunWorker *worker);
+ void onWorkerStopped(RunWorker *worker);
+ void onWorkerFailed(RunWorker *worker, const QString &msg);
+
+ void showError(const QString &msg);
+
+ static bool isAllowedTransition(RunControlState from, RunControlState to);
+ bool supportsReRunning() const;
+
+ RunControl *q;
+ QString displayName;
+ Runnable runnable;
+ IDevice::ConstPtr device;
+ Core::Id runMode;
+ Utils::Icon icon;
+ MacroExpander *macroExpander;
+ QPointer<RunConfiguration> runConfiguration; // Not owned. Avoid use.
+ Kit *kit = nullptr; // Not owned.
+ QPointer<Target> target; // Not owned.
+ QPointer<Project> project; // Not owned.
+ QPointer<Utils::OutputFormatter> outputFormatter = nullptr;
+ 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
+
+using namespace Internal;
+
+RunControl::RunControl(Core::Id mode) :
+ d(std::make_unique<RunControlPrivate>(this, mode))
+{
+}
+
+void RunControl::setRunConfiguration(RunConfiguration *runConfig)
+{
+ QTC_ASSERT(runConfig, return);
+ QTC_CHECK(!d->runConfiguration);
+ d->runConfiguration = runConfig;
+ d->runnable = runConfig->runnable();
+ d->displayName = runConfig->displayName();
+ if (auto outputFormatter = runConfig->createOutputFormatter()) {
+ delete d->outputFormatter;
+ d->outputFormatter = outputFormatter;
+ }
+ d->macroExpander = runConfig->macroExpander();
+ setTarget(runConfig->target());
+}
+
+void RunControl::setTarget(Target *target)
+{
+ QTC_ASSERT(target, return);
+ QTC_CHECK(!d->target);
+ d->target = target;
+ setKit(target->kit());
+ d->project = target->project();
+}
+
+void RunControl::setKit(Kit *kit)
+{
+ QTC_ASSERT(kit, return);
+ QTC_CHECK(!d->kit);
+ d->kit = kit;
+
+ if (d->runnable.device)
+ setDevice(d->runnable.device);
+ else
+ setDevice(DeviceKitAspect::device(kit));
+}
+
+void RunControl::setDevice(const IDevice::ConstPtr &device)
+{
+ QTC_CHECK(!d->device);
+ d->device = device;
+#ifdef WITH_JOURNALD
+ if (!device.isNull() && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
+ JournaldWatcher::instance()->subscribe(this, [this](const JournaldWatcher::LogEntry &entry) {
+
+ if (entry.value("_MACHINE_ID") != JournaldWatcher::instance()->machineId())
+ return;
+
+ const QByteArray pid = entry.value("_PID");
+ if (pid.isEmpty())
+ return;
+
+ const qint64 pidNum = static_cast<qint64>(QString::fromLatin1(pid).toInt());
+ if (pidNum != d->applicationProcessHandle.pid())
+ return;
+
+ const QString message = QString::fromUtf8(entry.value("MESSAGE")) + "\n";
+ appendMessage(message, Utils::OutputFormat::LogMessageFormat);
+ });
+ }
+#endif
+}
+
+RunControl::~RunControl()
+{
+#ifdef WITH_JOURNALD
+ JournaldWatcher::instance()->unsubscribe(this);
+#endif
+}
+
+void RunControl::initiateStart()
+{
+ emit aboutToStart();
+ d->initiateStart();
+}
+
+void RunControl::initiateReStart()
+{
+ emit aboutToStart();
+ d->initiateReStart();
+}
+
+void RunControl::initiateStop()
+{
+ d->initiateStop();
+}
+
+void RunControl::forceStop()
+{
+ d->forceStop();
+}
+
+void RunControl::initiateFinish()
+{
+ QTimer::singleShot(0, d.get(), &RunControlPrivate::initiateFinish);
+}
+
+using WorkerCreators = QHash<Core::Id, RunControl::WorkerCreator>;
+
+static WorkerCreators &theWorkerCreators()
+{
+ static WorkerCreators creators;
+ return creators;
+}
+
+void RunControl::registerWorkerCreator(Core::Id id, const WorkerCreator &workerCreator)
+{
+ theWorkerCreators().insert(id, workerCreator);
+ auto keys = theWorkerCreators().keys();
+ Q_UNUSED(keys);
+}
+
+RunWorker *RunControl::createWorker(Core::Id id)
+{
+ auto keys = theWorkerCreators().keys();
+ Q_UNUSED(keys);
+ WorkerCreator creator = theWorkerCreators().value(id);
+ if (creator)
+ return creator(this);
+ creator = device()->workerCreator(id);
+ if (creator)
+ return creator(this);
+ return nullptr;
+}
+
+bool RunControl::createMainWorker()
+{
+ const auto canRun = std::bind(&RunWorkerFactory::canRun, std::placeholders::_1,
+ d->runConfiguration, d->runMode);
+ const QList<RunWorkerFactory *> candidates = Utils::filtered(g_runWorkerFactories, canRun);
+ // There might be combinations that cannot run. But that should have been checked
+ // with canRun below.
+ QTC_ASSERT(!candidates.empty(), return false);
+
+ // There should be at most one top-level producer feeling responsible per combination.
+ // Breaking a tie should be done by tightening the restrictions on one of them.
+ QTC_CHECK(candidates.size() == 1);
+ return candidates.front()->producer()(this) != nullptr;
+}
+
+bool RunControl::canRun(RunConfiguration *runConfig, Core::Id runMode)
+{
+ const auto check = std::bind(&RunWorkerFactory::canRun, std::placeholders::_1, runConfig, runMode);
+ return Utils::contains(g_runWorkerFactories, check);
+}
+
+void RunControlPrivate::initiateStart()
+{
+ checkState(RunControlState::Initialized);
+ setState(RunControlState::Starting);
+ debugMessage("Queue: Starting");
+
+ continueStart();
+}
+
+void RunControlPrivate::initiateReStart()
+{
+ checkState(RunControlState::Stopped);
+
+ // Re-set worked on re-runs.
+ for (RunWorker *worker : m_workers) {
+ if (worker->d->state == RunWorkerState::Done)
+ worker->d->state = RunWorkerState::Initialized;
+ }
+
+ setState(RunControlState::Starting);
+ debugMessage("Queue: ReStarting");
+
+ continueStart();
+}
+
+void RunControlPrivate::continueStart()
+{
+ checkState(RunControlState::Starting);
+ bool allDone = true;
+ debugMessage("Looking for next worker");
+ for (RunWorker *worker : m_workers) {
+ if (worker) {
+ const QString &workerId = worker->d->id;
+ debugMessage(" Examining worker " + workerId);
+ switch (worker->d->state) {
+ case RunWorkerState::Initialized:
+ debugMessage(" " + workerId + " is not done yet.");
+ if (worker->d->canStart()) {
+ debugMessage("Starting " + workerId);
+ worker->d->state = RunWorkerState::Starting;
+ QTimer::singleShot(0, worker, &RunWorker::initiateStart);
+ return;
+ }
+ allDone = false;
+ debugMessage(" " + workerId + " cannot start.");
+ break;
+ case RunWorkerState::Starting:
+ debugMessage(" " + workerId + " currently starting");
+ allDone = false;
+ break;
+ case RunWorkerState::Running:
+ debugMessage(" " + workerId + " currently running");
+ break;
+ case RunWorkerState::Stopping:
+ debugMessage(" " + workerId + " currently stopping");
+ continue;
+ case RunWorkerState::Done:
+ debugMessage(" " + workerId + " was done before");
+ break;
+ }
+ } else {
+ debugMessage("Found unknown deleted worker while starting");
+ }
+ }
+ if (allDone)
+ setState(RunControlState::Running);
+}
+
+void RunControlPrivate::initiateStop()
+{
+ if (state != RunControlState::Starting && state != RunControlState::Running)
+ qDebug() << "Unexpected initiateStop() in state" << stateName(state);
+
+ setState(RunControlState::Stopping);
+ debugMessage("Queue: Stopping for all workers");
+
+ continueStopOrFinish();
+}
+
+void RunControlPrivate::continueStopOrFinish()
+{
+ bool allDone = true;
+
+ auto queueStop = [this](RunWorker *worker, const QString &message) {
+ if (worker->d->canStop()) {
+ debugMessage(message);
+ worker->d->state = RunWorkerState::Stopping;
+ QTimer::singleShot(0, worker, &RunWorker::initiateStop);
+ } else {
+ debugMessage(" " + worker->d->id + " is waiting for dependent workers to stop");
+ }
+ };
+
+ for (RunWorker *worker : m_workers) {
+ if (worker) {
+ const QString &workerId = worker->d->id;
+ debugMessage(" Examining worker " + workerId);
+ switch (worker->d->state) {
+ case RunWorkerState::Initialized:
+ debugMessage(" " + workerId + " was Initialized, setting to Done");
+ worker->d->state = RunWorkerState::Done;
+ break;
+ case RunWorkerState::Stopping:
+ debugMessage(" " + workerId + " was already Stopping. Keeping it that way");
+ allDone = false;
+ break;
+ case RunWorkerState::Starting:
+ queueStop(worker, " " + workerId + " was Starting, queuing stop");
+ allDone = false;
+ break;
+ case RunWorkerState::Running:
+ queueStop(worker, " " + workerId + " was Running, queuing stop");
+ allDone = false;
+ break;
+ case RunWorkerState::Done:
+ debugMessage(" " + workerId + " was Done. Good.");
+ break;
+ }
+ } else {
+ debugMessage("Found unknown deleted worker");
+ }
+ }
+
+ RunControlState targetState;
+ if (state == RunControlState::Finishing) {
+ targetState = RunControlState::Finished;
+ } else {
+ checkState(RunControlState::Stopping);
+ targetState = RunControlState::Stopped;
+ }
+
+ if (allDone) {
+ debugMessage("All Stopped");
+ setState(targetState);
+ } else {
+ debugMessage("Not all workers Stopped. Waiting...");
+ }
+}
+
+void RunControlPrivate::forceStop()
+{
+ if (state == RunControlState::Finished) {
+ debugMessage("Was finished, too late to force Stop");
+ return;
+ }
+ for (RunWorker *worker : m_workers) {
+ if (worker) {
+ const QString &workerId = worker->d->id;
+ debugMessage(" Examining worker " + workerId);
+ switch (worker->d->state) {
+ case RunWorkerState::Initialized:
+ debugMessage(" " + workerId + " was Initialized, setting to Done");
+ break;
+ case RunWorkerState::Stopping:
+ debugMessage(" " + workerId + " was already Stopping. Set it forcefully to Done.");
+ break;
+ case RunWorkerState::Starting:
+ debugMessage(" " + workerId + " was Starting. Set it forcefully to Done.");
+ break;
+ case RunWorkerState::Running:
+ debugMessage(" " + workerId + " was Running. Set it forcefully to Done.");
+ break;
+ case RunWorkerState::Done:
+ debugMessage(" " + workerId + " was Done. Good.");
+ break;
+ }
+ worker->d->state = RunWorkerState::Done;
+ } else {
+ debugMessage("Found unknown deleted worker");
+ }
+ }
+
+ setState(RunControlState::Stopped);
+ debugMessage("All Stopped");
+}
+
+void RunControlPrivate::initiateFinish()
+{
+ setState(RunControlState::Finishing);
+ debugMessage("Ramping down");
+
+ continueStopOrFinish();
+}
+
+void RunControlPrivate::onWorkerStarted(RunWorker *worker)
+{
+ worker->d->state = RunWorkerState::Running;
+
+ if (state == RunControlState::Starting) {
+ debugMessage(worker->d->id + " start succeeded");
+ continueStart();
+ return;
+ }
+ showError(RunControl::tr("Unexpected run control state %1 when worker %2 started.")
+ .arg(stateName(state))
+ .arg(worker->d->id));
+}
+
+void RunControlPrivate::onWorkerFailed(RunWorker *worker, const QString &msg)
+{
+ worker->d->state = RunWorkerState::Done;
+
+ showError(msg);
+ switch (state) {
+ case RunControlState::Initialized:
+ // FIXME 1: We don't have an output pane yet, so use some other mechanism for now.
+ // FIXME 2: Translation...
+ QMessageBox::critical(Core::ICore::dialogParent(),
+ QCoreApplication::translate("TaskHub", "Error"),
+ QString("Failure during startup. Aborting.") + "<p>" + msg);
+ continueStopOrFinish();
+ break;
+ case RunControlState::Starting:
+ case RunControlState::Running:
+ initiateStop();
+ break;
+ case RunControlState::Stopping:
+ case RunControlState::Finishing:
+ continueStopOrFinish();
+ break;
+ case RunControlState::Stopped:
+ case RunControlState::Finished:
+ QTC_CHECK(false); // Should not happen.
+ continueStopOrFinish();
+ break;
+ }
+}
+
+void RunControlPrivate::onWorkerStopped(RunWorker *worker)
+{
+ const QString &workerId = worker->d->id;
+ switch (worker->d->state) {
+ case RunWorkerState::Running:
+ // That was a spontaneous stop.
+ worker->d->state = RunWorkerState::Done;
+ debugMessage(workerId + " stopped spontaneously.");
+ break;
+ case RunWorkerState::Stopping:
+ worker->d->state = RunWorkerState::Done;
+ debugMessage(workerId + " stopped expectedly.");
+ break;
+ case RunWorkerState::Done:
+ worker->d->state = RunWorkerState::Done;
+ debugMessage(workerId + " stopped twice. Huh? But harmless.");
+ return; // Sic!
+ default:
+ debugMessage(workerId + " stopped unexpectedly in state"
+ + stateName(worker->d->state));
+ worker->d->state = RunWorkerState::Done;
+ break;
+ }
+
+ if (state == RunControlState::Finishing || state == RunControlState::Stopping) {
+ continueStopOrFinish();
+ return;
+ } else if (worker->isEssential()) {
+ debugMessage(workerId + " is essential. Stopping all others.");
+ initiateStop();
+ return;
+ }
+
+ for (RunWorker *dependent : worker->d->stopDependencies) {
+ switch (dependent->d->state) {
+ case RunWorkerState::Done:
+ break;
+ case RunWorkerState::Initialized:
+ dependent->d->state = RunWorkerState::Done;
+ break;
+ default:
+ debugMessage("Killing " + dependent->d->id + " as it depends on stopped " + workerId);
+ dependent->d->state = RunWorkerState::Stopping;
+ QTimer::singleShot(0, dependent, &RunWorker::initiateStop);
+ break;
+ }
+ }
+
+ debugMessage("Checking whether all stopped");
+ bool allDone = true;
+ for (RunWorker *worker : m_workers) {
+ if (worker) {
+ const QString &workerId = worker->d->id;
+ debugMessage(" Examining worker " + workerId);
+ switch (worker->d->state) {
+ case RunWorkerState::Initialized:
+ debugMessage(" " + workerId + " was Initialized.");
+ break;
+ case RunWorkerState::Starting:
+ debugMessage(" " + workerId + " was Starting, waiting for its response");
+ allDone = false;
+ break;
+ case RunWorkerState::Running:
+ debugMessage(" " + workerId + " was Running, waiting for its response");
+ allDone = false;
+ break;
+ case RunWorkerState::Stopping:
+ debugMessage(" " + workerId + " was already Stopping. Keeping it that way");
+ allDone = false;
+ break;
+ case RunWorkerState::Done:
+ debugMessage(" " + workerId + " was Done. Good.");
+ break;
+ }
+ } else {
+ debugMessage("Found unknown deleted worker");
+ }
+ }
+
+ if (allDone) {
+ if (state == RunControlState::Stopped) {
+ debugMessage("All workers stopped, but runControl was already stopped.");
+ } else {
+ debugMessage("All workers stopped. Set runControl to Stopped");
+ setState(RunControlState::Stopped);
+ }
+ } else {
+ debugMessage("Not all workers stopped. Waiting...");
+ }
+}
+
+void RunControlPrivate::showError(const QString &msg)
+{
+ if (!msg.isEmpty())
+ q->appendMessage(msg + '\n', ErrorMessageFormat);
+}
+
+Utils::OutputFormatter *RunControl::outputFormatter() const
+{
+ return d->outputFormatter;
+}
+
+Core::Id RunControl::runMode() const
+{
+ return d->runMode;
+}
+
+const Runnable &RunControl::runnable() const
+{
+ return d->runnable;
+}
+
+void RunControl::setRunnable(const Runnable &runnable)
+{
+ d->runnable = runnable;
+}
+
+QString RunControl::displayName() const
+{
+ return d->displayName;
+}
+
+void RunControl::setDisplayName(const QString &displayName)
+{
+ d->displayName = displayName;
+}
+
+void RunControl::setIcon(const Utils::Icon &icon)
+{
+ d->icon = icon;
+}
+
+Utils::Icon RunControl::icon() const
+{
+ return d->icon;
+}
+
+IDevice::ConstPtr RunControl::device() const
+{
+ return d->device;
+}
+
+RunConfiguration *RunControl::runConfiguration() const
+{
+ return d->runConfiguration.data();
+}
+
+Target *RunControl::target() const
+{
+ return d->target;
+}
+
+Project *RunControl::project() const
+{
+ return d->project;
+}
+
+Kit *RunControl::kit() const
+{
+ return d->kit;
+}
+
+MacroExpander *RunControl::macroExpander() const
+{
+ return d->macroExpander;
+}
+
+ProjectConfigurationAspect *RunControl::aspect(Core::Id id) const
+{
+ return d->runConfiguration ? d->runConfiguration->aspect(id) : nullptr;
+}
+
+ISettingsAspect *RunControl::settings(Core::Id id) const
+{
+ return d->runConfiguration ? d->runConfiguration->currentSettings(id) : nullptr;
+}
+
+QString RunControl::buildKey() const
+{
+ return d->runConfiguration ? d->runConfiguration->buildKey() : QString();
+}
+
+BuildTargetInfo RunControl::buildTargetInfo() const
+{
+ return d->runConfiguration->buildTargetInfo();
+}
+
+/*!
+ A handle to the application process.
+
+ This is typically a process id, but should be treated as
+ opaque handle to the process controled by this \c RunControl.
+*/
+
+ProcessHandle RunControl::applicationProcessHandle() const
+{
+ return d->applicationProcessHandle;
+}
+
+void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
+{
+ if (d->applicationProcessHandle != handle) {
+ d->applicationProcessHandle = handle;
+ emit applicationProcessHandleChanged(QPrivateSignal());
+ }
+}
+
+/*!
+ Prompts to stop. If \a optionalPrompt is passed, a \gui {Do not ask again}
+ checkbox is displayed and the result is returned in \a *optionalPrompt.
+*/
+
+bool RunControl::promptToStop(bool *optionalPrompt) const
+{
+ QTC_ASSERT(isRunning(), return true);
+ if (optionalPrompt && !*optionalPrompt)
+ return true;
+
+ // Overridden.
+ if (d->promptToStop)
+ return d->promptToStop(optionalPrompt);
+
+ const QString msg = tr("<html><head/><body><center><i>%1</i> is still running.<center/>"
+ "<center>Force it to quit?</center></body></html>").arg(displayName());
+ return showPromptToStopDialog(tr("Application Still Running"), msg,
+ tr("Force &Quit"), tr("&Keep Running"),
+ optionalPrompt);
+}
+
+void RunControl::setPromptToStop(const std::function<bool (bool *)> &promptToStop)
+{
+ d->promptToStop = promptToStop;
+}
+
+bool RunControl::supportsReRunning() const
+{
+ return d->supportsReRunning();
+}
+
+bool RunControlPrivate::supportsReRunning() const
+{
+ for (RunWorker *worker : m_workers) {
+ if (!worker->d->supportsReRunning)
+ return false;
+ if (worker->d->state != RunWorkerState::Done)
+ return false;
+ }
+ return true;
+}
+
+bool RunControl::isRunning() const
+{
+ return d->state == RunControlState::Running;
+}
+
+bool RunControl::isStarting() const
+{
+ return d->state == RunControlState::Starting;
+}
+
+bool RunControl::isStopping() const
+{
+ return d->state == RunControlState::Stopping;
+}
+
+bool RunControl::isStopped() const
+{
+ return d->state == RunControlState::Stopped;
+}
+
+/*!
+ Prompts to terminate the application with the \gui {Do not ask again}
+ checkbox.
+*/
+
+bool RunControl::showPromptToStopDialog(const QString &title,
+ const QString &text,
+ const QString &stopButtonText,
+ const QString &cancelButtonText,
+ bool *prompt)
+{
+ // Show a question message box where user can uncheck this
+ // question for this class.
+ Utils::CheckableMessageBox messageBox(Core::ICore::mainWindow());
+ messageBox.setWindowTitle(title);
+ messageBox.setText(text);
+ messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::Cancel);
+ if (!stopButtonText.isEmpty())
+ messageBox.button(QDialogButtonBox::Yes)->setText(stopButtonText);
+ if (!cancelButtonText.isEmpty())
+ messageBox.button(QDialogButtonBox::Cancel)->setText(cancelButtonText);
+ messageBox.setDefaultButton(QDialogButtonBox::Yes);
+ if (prompt) {
+ messageBox.setCheckBoxText(Utils::CheckableMessageBox::msgDoNotAskAgain());
+ messageBox.setChecked(false);
+ } else {
+ messageBox.setCheckBoxVisible(false);
+ }
+ messageBox.exec();
+ const bool close = messageBox.clickedStandardButton() == QDialogButtonBox::Yes;
+ if (close && prompt && messageBox.isChecked())
+ *prompt = false;
+ return close;
+}
+
+bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlState to)
+{
+ switch (from) {
+ case RunControlState::Initialized:
+ return to == RunControlState::Starting
+ || to == RunControlState::Finishing;
+ case RunControlState::Starting:
+ return to == RunControlState::Running
+ || to == RunControlState::Stopping
+ || to == RunControlState::Finishing;
+ case RunControlState::Running:
+ return to == RunControlState::Stopping
+ || to == RunControlState::Stopped
+ || to == RunControlState::Finishing;
+ case RunControlState::Stopping:
+ return to == RunControlState::Stopped
+ || to == RunControlState::Finishing;
+ case RunControlState::Stopped:
+ return to == RunControlState::Finishing;
+ case RunControlState::Finishing:
+ return to == RunControlState::Finished;
+ case RunControlState::Finished:
+ return false;
+ }
+ return false;
+}
+
+void RunControlPrivate::checkState(RunControlState expectedState)
+{
+ if (state != expectedState)
+ qDebug() << "Unexpected run control state " << stateName(expectedState)
+ << " have: " << stateName(state);
+}
+
+void RunControlPrivate::setState(RunControlState newState)
+{
+ if (!isAllowedTransition(state, newState))
+ qDebug() << "Invalid run control state transition from " << stateName(state)
+ << " to " << stateName(newState);
+
+ state = newState;
+
+ debugMessage("Entering state " + stateName(newState));
+
+ // Extra reporting.
+ switch (state) {
+ case RunControlState::Running:
+ emit q->started();
+ break;
+ case RunControlState::Stopped:
+ q->setApplicationProcessHandle(Utils::ProcessHandle());
+ emit q->stopped();
+ break;
+ case RunControlState::Finished:
+ emit q->finished();
+ debugMessage("All finished. Deleting myself");
+ q->deleteLater();
+ break;
+ default:
+ break;
+ }
+}
+
+void RunControlPrivate::debugMessage(const QString &msg)
+{
+ qCDebug(statesLog()) << msg;
+}
+
+// SimpleTargetRunner
+
+SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
+ : RunWorker(runControl)
+{
+ setId("SimpleTargetRunner");
+ m_runnable = runControl->runnable(); // Default value. Can be overridden using setRunnable.
+ m_device = runControl->device(); // Default value. Can be overridden using setDevice.
+ if (auto terminalAspect = runControl->aspect<TerminalAspect>())
+ m_useTerminal = terminalAspect->useTerminal();
+}
+
+void SimpleTargetRunner::start()
+{
+ m_stopReported = false;
+ m_launcher.disconnect(this);
+ m_launcher.setUseTerminal(m_useTerminal);
+
+ const bool isDesktop = m_device.isNull()
+ || m_device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+ const QString rawDisplayName = m_runnable.displayName();
+ const QString displayName = isDesktop
+ ? QDir::toNativeSeparators(rawDisplayName)
+ : rawDisplayName;
+ const QString msg = RunControl::tr("Starting %1 %2...")
+ .arg(displayName).arg(m_runnable.commandLineArguments);
+ appendMessage(msg, Utils::NormalMessageFormat);
+
+ if (isDesktop) {
+
+ connect(&m_launcher, &ApplicationLauncher::appendMessage,
+ this, &SimpleTargetRunner::appendMessage);
+ connect(&m_launcher, &ApplicationLauncher::processStarted,
+ this, &SimpleTargetRunner::onProcessStarted);
+ connect(&m_launcher, &ApplicationLauncher::processExited,
+ this, &SimpleTargetRunner::onProcessFinished);
+ connect(&m_launcher, &ApplicationLauncher::error,
+ this, &SimpleTargetRunner::onProcessError);
+
+ const QString executable = m_runnable.executable;
+ if (executable.isEmpty()) {
+ reportFailure(RunControl::tr("No executable specified."));
+ } else {
+ m_launcher.start(m_runnable);
+ }
+
+ } else {
+
+ connect(&m_launcher, &ApplicationLauncher::reportError,
+ this, [this](const QString &msg) {
+ reportFailure(msg);
+ });
+
+ connect(&m_launcher, &ApplicationLauncher::remoteStderr,
+ this, [this](const QString &output) {
+ appendMessage(output, Utils::StdErrFormatSameLine, false);
+ });
+
+ connect(&m_launcher, &ApplicationLauncher::remoteStdout,
+ this, [this](const QString &output) {
+ appendMessage(output, Utils::StdOutFormatSameLine, false);
+ });
+
+ connect(&m_launcher, &ApplicationLauncher::finished,
+ this, [this] {
+ m_launcher.disconnect(this);
+ reportStopped();
+ });
+
+ connect(&m_launcher, &ApplicationLauncher::processStarted,
+ this, [this] {
+ appendMessage("Application launcher started", Utils::NormalMessageFormat);
+// reportStarted();
+ });
+
+ connect(&m_launcher, &ApplicationLauncher::processExited,
+ this, [this] {
+ m_launcher.disconnect(this);
+ reportStopped();
+ });
+
+ connect(&m_launcher, &ApplicationLauncher::remoteProcessStarted,
+ this, [this] {
+ reportStarted();
+ });
+
+ connect(&m_launcher, &ApplicationLauncher::reportProgress,
+ this, [this](const QString &progressString) {
+ appendMessage(progressString, Utils::NormalMessageFormat);
+ });
+
+ m_launcher.start(m_runnable, device());
+ }
+}
+
+void SimpleTargetRunner::stop()
+{
+ m_launcher.stop();
+}
+
+void SimpleTargetRunner::onProcessStarted()
+{
+ // Console processes only know their pid after being started
+ ProcessHandle pid = m_launcher.applicationPID();
+ runControl()->setApplicationProcessHandle(pid);
+ pid.activate();
+ reportStarted();
+}
+
+void SimpleTargetRunner::onProcessFinished(int exitCode, QProcess::ExitStatus status)
+{
+ QString msg;
+ if (status == QProcess::CrashExit)
+ msg = tr("%1 crashed.");
+ else
+ msg = tr("%2 exited with code %1").arg(exitCode);
+ appendMessage(msg.arg(m_runnable.displayName()), Utils::NormalMessageFormat);
+ if (!m_stopReported) {
+ m_stopReported = true;
+ reportStopped();
+ }
+}
+
+void SimpleTargetRunner::onProcessError(QProcess::ProcessError error)
+{
+ if (error == QProcess::Timedout)
+ return; // No actual change on the process side.
+ QString msg = userMessageForProcessError(error, m_runnable.displayName());
+ appendMessage(msg, Utils::NormalMessageFormat);
+ if (!m_stopReported) {
+ m_stopReported = true;
+ reportStopped();
+ }
+}
+
+IDevice::ConstPtr SimpleTargetRunner::device() const
+{
+ return m_device;
+}
+
+void SimpleTargetRunner::setRunnable(const Runnable &runnable)
+{
+ m_runnable = runnable;
+}
+
+void SimpleTargetRunner::setDevice(const IDevice::ConstPtr &device)
+{
+ m_device = device;
+}
+
+// RunWorkerPrivate
+
+RunWorkerPrivate::RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl)
+ : q(runWorker), runControl(runControl)
+{
+ runControl->d->m_workers.append(runWorker);
+}
+
+bool RunWorkerPrivate::canStart() const
+{
+ if (state != RunWorkerState::Initialized)
+ return false;
+ for (RunWorker *worker : startDependencies) {
+ QTC_ASSERT(worker, continue);
+ if (worker->d->state != RunWorkerState::Done
+ && worker->d->state != RunWorkerState::Running)
+ return false;
+ }
+ return true;
+}
+
+bool RunWorkerPrivate::canStop() const
+{
+ if (state != RunWorkerState::Starting && state != RunWorkerState::Running)
+ return false;
+ for (RunWorker *worker : stopDependencies) {
+ QTC_ASSERT(worker, continue);
+ if (worker->d->state != RunWorkerState::Done)
+ return false;
+ }
+ return true;
+}
+
+void RunWorkerPrivate::timerEvent(QTimerEvent *ev)
+{
+ if (ev->timerId() == startWatchdogTimerId) {
+ if (startWatchdogCallback) {
+ killStartWatchdog();
+ startWatchdogCallback();
+ } else {
+ q->reportFailure(RunWorker::tr("Worker start timed out."));
+ }
+ return;
+ }
+ if (ev->timerId() == stopWatchdogTimerId) {
+ if (stopWatchdogCallback) {
+ killStopWatchdog();
+ stopWatchdogCallback();
+ } else {
+ q->reportFailure(RunWorker::tr("Worker stop timed out."));
+ }
+ return;
+ }
+}
+
+/*!
+ \class ProjectExplorer::RunWorker
+
+ \brief The RunWorker class encapsulates a task that forms part, or
+ the whole of the operation of a tool for a certain \c RunConfiguration
+ according to some \c RunMode.
+
+ A typical example for a \c RunWorker is a process, either the
+ application process itself, or a helper process, such as a watchdog
+ or a log parser.
+
+ A \c RunWorker has a simple state model covering the \c Initialized,
+ \c Starting, \c Running, \c Stopping, and \c Done states.
+
+ In the course of the operation of tools several \c RunWorkers
+ may co-operate and form a combined state that is presented
+ to the user as \c RunControl, with direct interaction made
+ possible through the buttons in the \uicontrol{Application Output}
+ pane.
+
+ RunWorkers are typically created together with their RunControl.
+ The startup order of RunWorkers under a RunControl can be
+ specified by making a RunWorker dependent on others.
+
+ When a RunControl starts, it calls \c initiateStart() on RunWorkers
+ with fulfilled dependencies until all workers are \c Running, or in case
+ of short-lived helper tasks, \c Done.
+
+ A RunWorker can stop spontaneously, for example when the main application
+ process ends. In this case, it typically calls \c initiateStop()
+ on its RunControl, which in turn passes this to all sibling
+ RunWorkers.
+
+ Pressing the stop button in the \uicontrol{Application Output} pane
+ also calls \c initiateStop on the RunControl.
+*/
+
+RunWorker::RunWorker(RunControl *runControl)
+ : d(std::make_unique<RunWorkerPrivate>(this, runControl))
+{ }
+
+RunWorker::~RunWorker() = default;
+
+/*!
+ * This function is called by the RunControl once all dependencies
+ * are fulfilled.
+ */
+void RunWorker::initiateStart()
+{
+ d->startStartWatchdog();
+ d->runControl->d->debugMessage("Initiate start for " + d->id);
+ start();
+}
+
+/*!
+ * This function has to be called by a RunWorker implementation
+ * to notify its RunControl about the successful start of this RunWorker.
+ *
+ * The RunControl may start other RunWorkers in response.
+ */
+void RunWorker::reportStarted()
+{
+ d->killStartWatchdog();
+ d->runControl->d->onWorkerStarted(this);
+ emit started();
+}
+
+/*!
+ * This function is called by the RunControl in its own \c initiateStop
+ * implementation, which is triggered in response to pressing the
+ * stop button in the \uicontrol{Application Output} pane or on direct
+ * request of one of the sibling RunWorkers.
+ */
+void RunWorker::initiateStop()
+{
+ d->startStopWatchdog();
+ d->runControl->d->debugMessage("Initiate stop for " + d->id);
+ stop();
+}
+
+/*!
+ * This function has to be called by a RunWorker implementation
+ * to notify its RunControl about this RunWorker having stopped.
+ *
+ * The stop can be spontaneous, or in response to an initiateStop()
+ * or an initiateFinish() call.
+ *
+ * The RunControl will adjust its global state in response.
+ */
+void RunWorker::reportStopped()
+{
+ d->killStopWatchdog();
+ d->runControl->d->onWorkerStopped(this);
+ emit stopped();
+}
+
+/*!
+ * This function can be called by a RunWorker implementation for short-lived
+ * tasks to notify its RunControl about this task being successful finished.
+ * Dependent startup tasks can proceed, in cases of spontaneous or scheduled
+ * stops, the effect is the same as \c reportStopped().
+ *
+ */
+void RunWorker::reportDone()
+{
+ d->killStartWatchdog();
+ d->killStopWatchdog();
+ switch (d->state) {
+ case RunWorkerState::Initialized:
+ QTC_CHECK(false);
+ d->state = RunWorkerState::Done;
+ break;
+ case RunWorkerState::Starting:
+ reportStarted();
+ reportStopped();
+ break;
+ case RunWorkerState::Running:
+ case RunWorkerState::Stopping:
+ reportStopped();
+ break;
+ case RunWorkerState::Done:
+ break;
+ }
+}
+
+/*!
+ * This function can be called by a RunWorker implementation to
+ * signal a problem in the operation in this worker. The
+ * RunControl will start to ramp down through initiateStop().
+ */
+void RunWorker::reportFailure(const QString &msg)
+{
+ d->killStartWatchdog();
+ d->killStopWatchdog();
+ d->runControl->d->onWorkerFailed(this, 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)
+{
+ if (!appendNewLine || msg.endsWith('\n'))
+ d->runControl->appendMessage(msg, format);
+ else
+ d->runControl->appendMessage(msg + '\n', format);
+}
+
+IDevice::ConstPtr RunWorker::device() const
+{
+ return d->runControl->device();
+}
+
+const Runnable &RunWorker::runnable() const
+{
+ return d->runControl->runnable();
+}
+
+void RunWorker::addStartDependency(RunWorker *dependency)
+{
+ d->startDependencies.append(dependency);
+}
+
+void RunWorker::addStopDependency(RunWorker *dependency)
+{
+ d->stopDependencies.append(dependency);
+}
+
+RunControl *RunWorker::runControl() const
+{
+ return d->runControl;
+}
+
+void RunWorker::setId(const QString &id)
+{
+ d->id = id;
+}
+
+void RunWorker::setStartTimeout(int ms, const std::function<void()> &callback)
+{
+ d->startWatchdogInterval = ms;
+ d->startWatchdogCallback = callback;
+}
+
+void RunWorker::setStopTimeout(int ms, const std::function<void()> &callback)
+{
+ d->stopWatchdogInterval = ms;
+ d->stopWatchdogCallback = callback;
+}
+
+void RunWorker::recordData(const QString &channel, const QVariant &data)
+{
+ d->data[channel] = data;
+}
+
+QVariant RunWorker::recordedData(const QString &channel) const
+{
+ return d->data[channel];
+}
+
+void RunWorker::setSupportsReRunning(bool reRunningSupported)
+{
+ d->supportsReRunning = reRunningSupported;
+}
+
+bool RunWorker::supportsReRunning() const
+{
+ return d->supportsReRunning;
+}
+
+QString RunWorker::userMessageForProcessError(QProcess::ProcessError error, const QString &program)
+{
+ QString failedToStart = tr("The process failed to start.");
+ QString msg = tr("An unknown error in the process occurred.");
+ switch (error) {
+ case QProcess::FailedToStart:
+ msg = failedToStart + ' ' + tr("Either the "
+ "invoked program \"%1\" is missing, or you may have insufficient "
+ "permissions to invoke the program.").arg(program);
+ break;
+ case QProcess::Crashed:
+ msg = tr("The process was ended forcefully.");
+ break;
+ case QProcess::Timedout:
+ // "The last waitFor...() function timed out. "
+ // "The state of QProcess is unchanged, and you can try calling "
+ // "waitFor...() again."
+ return QString(); // sic!
+ case QProcess::WriteError:
+ msg = 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::ReadError:
+ msg = tr("An error occurred when attempting to read from "
+ "the process. For example, the process may not be running.");
+ break;
+ case QProcess::UnknownError:
+ break;
+ }
+ return msg;
+}
+
+bool RunWorker::isEssential() const
+{
+ return d->essential;
+}
+
+void RunWorker::setEssential(bool essential)
+{
+ d->essential = essential;
+}
+
+void RunWorker::start()
+{
+ reportStarted();
+}
+
+void RunWorker::stop()
+{
+ reportStopped();
+}
+
+CommandLine Runnable::commandLine() const
+{
+ return CommandLine(FilePath::fromString(executable), commandLineArguments);
+}
+
+void Runnable::setCommandLine(const CommandLine &cmdLine)
+{
+ executable = cmdLine.executable().toString();
+ commandLineArguments = cmdLine.arguments();
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h
new file mode 100644
index 0000000000..fbb1c151ff
--- /dev/null
+++ b/src/plugins/projectexplorer/runcontrol.h
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** 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 "applicationlauncher.h"
+#include "buildtargetinfo.h"
+#include "devicesupport/idevice.h"
+#include "projectexplorerconstants.h"
+#include "runconfiguration.h"
+
+#include <utils/environment.h>
+#include <utils/port.h>
+#include <utils/processhandle.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+#include <utils/icon.h>
+
+#include <QHash>
+#include <QPointer>
+#include <QVariant>
+#include <QWidget>
+
+#include <functional>
+#include <memory>
+
+namespace Utils {
+class MacroExpander;
+class OutputFormatter;
+} // Utils
+
+namespace ProjectExplorer {
+class BuildConfiguration;
+class GlobalOrProjectAspect;
+class Node;
+class RunConfigurationFactory;
+class RunConfiguration;
+class RunConfigurationCreationInfo;
+class RunControl;
+class RunWorkerFactory;
+class Target;
+
+namespace Internal {
+class RunControlPrivate;
+class RunWorkerPrivate;
+} // Internal
+
+
+class PROJECTEXPLORER_EXPORT Runnable
+{
+public:
+ Runnable() = default;
+
+ Utils::CommandLine commandLine() const;
+ void setCommandLine(const Utils::CommandLine &cmdLine);
+
+ QString executable;
+ QString commandLineArguments;
+ QString workingDirectory;
+ Utils::Environment environment;
+ IDevice::ConstPtr device; // Override the kit's device. Keep unset by default.
+ QHash<Core::Id, QVariant> extraData;
+
+ // FIXME: Not necessarily a display name
+ QString displayName() const { return executable; }
+};
+
+class PROJECTEXPLORER_EXPORT RunWorker : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit RunWorker(RunControl *runControl);
+ ~RunWorker() override;
+
+ RunControl *runControl() const;
+
+ void addStartDependency(RunWorker *dependency);
+ void addStopDependency(RunWorker *dependency);
+
+ void setId(const QString &id);
+
+ void setStartTimeout(int ms, const std::function<void()> &callback = {});
+ void setStopTimeout(int ms, const std::function<void()> &callback = {});
+
+ void recordData(const QString &channel, const QVariant &data);
+ 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;
+
+ // States
+ void initiateStart();
+ void reportStarted();
+
+ void initiateStop();
+ void reportStopped();
+
+ void reportDone();
+
+ void reportFailure(const QString &msg = QString());
+ void setSupportsReRunning(bool reRunningSupported);
+ bool supportsReRunning() const;
+
+ static QString userMessageForProcessError(QProcess::ProcessError, const QString &programName);
+
+ bool isEssential() const;
+ void setEssential(bool essential);
+
+signals:
+ void started();
+ void stopped();
+
+protected:
+ void virtual start();
+ void virtual stop();
+ void virtual onFinished() {}
+
+private:
+ friend class Internal::RunControlPrivate;
+ friend class Internal::RunWorkerPrivate;
+ const std::unique_ptr<Internal::RunWorkerPrivate> d;
+};
+
+class PROJECTEXPLORER_EXPORT RunWorkerFactory
+{
+public:
+ using WorkerCreator = std::function<RunWorker *(RunControl *)>;
+ using Constraint = std::function<bool(RunConfiguration *)>;
+
+ RunWorkerFactory();
+ virtual ~RunWorkerFactory();
+
+ bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const;
+
+ void setProducer(const WorkerCreator &producer);
+ void addConstraint(const Constraint &constraint);
+ void addSupportedRunMode(Core::Id runMode);
+
+ void setSupportedRunConfigurations(const QList<Core::Id> &ids);
+ void addSupportedRunConfiguration(Core::Id id);
+
+ WorkerCreator producer() const { return m_producer; }
+
+private:
+ // FIXME: That's temporary until ownership has been transferred to
+ // the individual plugins.
+ friend class ProjectExplorerPlugin;
+ static void destroyRemainingRunWorkerFactories();
+
+ QList<Core::Id> m_supportedRunModes;
+ QList<Core::Id> m_supportedRunConfigurations;
+ QList<Constraint> m_constraints;
+ WorkerCreator m_producer;
+};
+
+/**
+ * A RunControl controls the running of an application or tool
+ * on a target device. It controls start and stop, and handles
+ * application output.
+ *
+ * RunControls are created by RunControlFactories.
+ */
+
+class PROJECTEXPLORER_EXPORT RunControl : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit RunControl(Core::Id mode);
+ ~RunControl() override;
+
+ void setRunConfiguration(RunConfiguration *runConfig);
+ void setTarget(Target *target);
+ void setKit(Kit *kit);
+
+ void initiateStart();
+ void initiateReStart();
+ void initiateStop();
+ void forceStop();
+ void initiateFinish();
+
+ bool promptToStop(bool *optionalPrompt = nullptr) const;
+ void setPromptToStop(const std::function<bool(bool *)> &promptToStop);
+
+ bool supportsReRunning() const;
+
+ virtual QString displayName() const;
+ void setDisplayName(const QString &displayName);
+
+ bool isRunning() const;
+ bool isStarting() const;
+ bool isStopping() const;
+ bool isStopped() const;
+
+ void setIcon(const Utils::Icon &icon);
+ Utils::Icon icon() const;
+
+ Utils::ProcessHandle applicationProcessHandle() const;
+ void setApplicationProcessHandle(const Utils::ProcessHandle &handle);
+ IDevice::ConstPtr 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;
+ Utils::MacroExpander *macroExpander() const;
+ ProjectConfigurationAspect *aspect(Core::Id id) const;
+ template <typename T> T *aspect() const {
+ return runConfiguration() ? runConfiguration()->aspect<T>() : nullptr;
+ }
+
+ template <typename T>
+ auto aspectData() -> decltype(T::runData(nullptr, this)) {
+ if (T *asp = aspect<T>())
+ return T::runData(asp, this);
+ return {};
+ }
+
+ ISettingsAspect *settings(Core::Id id) const;
+ QString buildKey() const;
+ BuildTargetInfo buildTargetInfo() const;
+
+ Utils::OutputFormatter *outputFormatter() const;
+ Core::Id runMode() const;
+
+ const Runnable &runnable() const;
+ void setRunnable(const Runnable &runnable);
+
+ static bool showPromptToStopDialog(const QString &title, const QString &text,
+ const QString &stopButtonText = QString(),
+ const QString &cancelButtonText = QString(),
+ bool *prompt = nullptr);
+
+ RunWorker *createWorker(Core::Id id);
+
+ using WorkerCreator = RunWorkerFactory::WorkerCreator;
+ using Constraint = RunWorkerFactory::Constraint;
+
+ static void registerWorkerCreator(Core::Id id, const WorkerCreator &workerCreator);
+
+ template <class Worker>
+ static void registerWorker(Core::Id runMode, const Constraint &constraint)
+ {
+ auto factory = new RunWorkerFactory;
+ factory->setProducer([](RunControl *rc) { return new Worker(rc); });
+ factory->addSupportedRunMode(runMode);
+ factory->addConstraint(constraint);
+ }
+
+ bool createMainWorker();
+ static bool canRun(RunConfiguration *runConfig, Core::Id runMode);
+
+signals:
+ void appendMessage(const QString &msg, Utils::OutputFormat format);
+ void aboutToStart();
+ void started();
+ void stopped();
+ void finished();
+ void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
+
+private:
+ void setDevice(const IDevice::ConstPtr &device);
+
+ friend class RunWorker;
+ friend class Internal::RunWorkerPrivate;
+
+ const std::unique_ptr<Internal::RunControlPrivate> d;
+};
+
+
+/**
+ * A simple TargetRunner for cases where a plain ApplicationLauncher is
+ * sufficient for running purposes.
+ */
+
+class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public RunWorker
+{
+ Q_OBJECT
+
+public:
+ explicit SimpleTargetRunner(RunControl *runControl);
+
+ void setRunnable(const Runnable &runnable);
+
+ void setDevice(const IDevice::ConstPtr &device);
+ IDevice::ConstPtr device() const;
+
+protected:
+ void start() override;
+ void stop() override;
+
+private:
+ void onProcessStarted();
+ void onProcessFinished(int exitCode, QProcess::ExitStatus status);
+ void onProcessError(QProcess::ProcessError error);
+
+ ApplicationLauncher m_launcher;
+ Runnable m_runnable;
+ IDevice::ConstPtr m_device;
+ bool m_stopReported = false;
+ bool m_useTerminal = false;
+};
+
+template <class RunWorker, class RunConfig>
+class SimpleRunWorkerFactory : public RunWorkerFactory
+{
+public:
+ SimpleRunWorkerFactory(Core::Id runMode = ProjectExplorer::Constants::NORMAL_RUN_MODE)
+ {
+ addSupportedRunMode(runMode);
+ addConstraint([](RunConfiguration *runConfig) {
+ return qobject_cast<RunConfig *>(runConfig) != nullptr;
+ });
+ setProducer([](RunControl *runControl) {
+ return new RunWorker(runControl);
+ });
+ }
+};
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
index 3b30bf63ad..39b2f01af6 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
@@ -25,6 +25,7 @@
#include "runsettingspropertiespage.h"
+#include "addrunconfigdialog.h"
#include "buildstepspage.h"
#include "deployconfiguration.h"
#include "runconfiguration.h"
@@ -92,7 +93,7 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
m_runConfigurationCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_runConfigurationCombo->setMinimumContentsLength(15);
- m_addRunToolButton = new QPushButton(tr("Add"), this);
+ m_addRunToolButton = new QPushButton(tr("Add..."), this);
m_removeRunToolButton = new QPushButton(tr("Remove"), this);
m_renameRunButton = new QPushButton(tr("Rename..."), this);
m_cloneRunButton = new QPushButton(tr("Clone..."), this);
@@ -161,7 +162,7 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
connect(m_addDeployMenu, &QMenu::aboutToShow,
this, &RunSettingsWidget::aboutToShowDeployMenu);
- connect(m_deployConfigurationCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_deployConfigurationCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &RunSettingsWidget::currentDeployConfigurationChanged);
connect(m_removeDeployToolButton, &QAbstractButton::clicked,
this, &RunSettingsWidget::removeDeployConfiguration);
@@ -187,8 +188,6 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
m_runLayout->addLayout(disabledHBox);
- m_addRunMenu = new QMenu(m_addRunToolButton);
- m_addRunToolButton->setMenu(m_addRunMenu);
RunConfiguration *rc = m_target->activeRunConfiguration();
m_runConfigurationCombo->setModel(m_runConfigurationsModel);
m_runConfigurationCombo->setCurrentIndex(
@@ -200,9 +199,9 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
setConfigurationWidget(rc);
- connect(m_addRunMenu, &QMenu::aboutToShow,
- this, &RunSettingsWidget::aboutToShowAddMenu);
- connect(m_runConfigurationCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_addRunToolButton, &QAbstractButton::clicked,
+ this, &RunSettingsWidget::showAddRunConfigDialog);
+ connect(m_runConfigurationCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &RunSettingsWidget::currentRunConfigurationChanged);
connect(m_removeRunToolButton, &QAbstractButton::clicked,
this, &RunSettingsWidget::removeRunConfiguration);
@@ -225,28 +224,20 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
this, &RunSettingsWidget::activeRunConfigurationChanged);
}
-void RunSettingsWidget::aboutToShowAddMenu()
+void RunSettingsWidget::showAddRunConfigDialog()
{
- m_addRunMenu->clear();
- QList<QAction *> menuActions;
- for (const RunConfigurationCreationInfo &item :
- RunConfigurationFactory::creatorsForTarget(m_target)) {
- auto action = new QAction(item.displayName, m_addRunMenu);
- connect(action, &QAction::triggered, [item, this] {
- RunConfiguration *newRC = item.create(m_target);
- if (!newRC)
- return;
- QTC_CHECK(newRC->id() == item.id);
- m_target->addRunConfiguration(newRC);
- m_target->setActiveRunConfiguration(newRC);
- m_removeRunToolButton->setEnabled(m_target->runConfigurations().size() > 1);
- });
- menuActions.append(action);
- }
-
- Utils::sort(menuActions, &QAction::text);
- foreach (QAction *action, menuActions)
- m_addRunMenu->addAction(action);
+ AddRunConfigDialog dlg(m_target, this);
+ if (dlg.exec() != QDialog::Accepted)
+ return;
+ RunConfigurationCreationInfo rci = dlg.creationInfo();
+ QTC_ASSERT(rci.id.isValid(), return);
+ RunConfiguration *newRC = rci.create(m_target);
+ if (!newRC)
+ return;
+ QTC_CHECK(newRC->id() == rci.id);
+ m_target->addRunConfiguration(newRC);
+ m_target->setActiveRunConfiguration(newRC);
+ m_removeRunToolButton->setEnabled(m_target->runConfigurations().size() > 1);
}
void RunSettingsWidget::cloneRunConfiguration()
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.h b/src/plugins/projectexplorer/runsettingspropertiespage.h
index 1857fea945..bf86fe56ba 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.h
@@ -58,7 +58,7 @@ public:
private:
void currentRunConfigurationChanged(int index);
- void aboutToShowAddMenu();
+ void showAddRunConfigDialog();
void cloneRunConfiguration();
void removeRunConfiguration();
void activeRunConfigurationChanged();
@@ -91,7 +91,6 @@ private:
NamedWidget *m_deployConfigurationWidget = nullptr;
QVBoxLayout *m_deployLayout = nullptr;
BuildStepListWidget *m_deploySteps = nullptr;
- QMenu *m_addRunMenu;
QMenu *m_addDeployMenu;
bool m_ignoreChange = false;
using RunConfigItem = QPair<QWidget *, QLabel *>;
diff --git a/src/plugins/projectexplorer/selectablefilesmodel.cpp b/src/plugins/projectexplorer/selectablefilesmodel.cpp
index b8925e4f57..28d6f4ef23 100644
--- a/src/plugins/projectexplorer/selectablefilesmodel.cpp
+++ b/src/plugins/projectexplorer/selectablefilesmodel.cpp
@@ -53,13 +53,13 @@ SelectableFilesModel::SelectableFilesModel(QObject *parent) : QAbstractItemModel
m_root = new Tree;
}
-void SelectableFilesModel::setInitialMarkedFiles(const Utils::FileNameList &files)
+void SelectableFilesModel::setInitialMarkedFiles(const Utils::FilePathList &files)
{
m_files = files.toSet();
m_allFiles = files.isEmpty();
}
-void SelectableFilesFromDirModel::startParsing(const Utils::FileName &baseDir)
+void SelectableFilesFromDirModel::startParsing(const Utils::FilePath &baseDir)
{
m_watcher.cancel();
m_watcher.waitForFinished();
@@ -87,7 +87,7 @@ void SelectableFilesFromDirModel::buildTreeFinished()
m_root = m_rootForFuture;
m_rootForFuture = nullptr;
m_outOfBaseDirFiles
- = Utils::filtered(m_files, [this](const Utils::FileName &fn) { return !fn.isChildOf(m_baseDir); });
+ = Utils::filtered(m_files, [this](const Utils::FilePath &fn) { return !fn.isChildOf(m_baseDir); });
endResetModel();
emit parsingFinished();
@@ -116,7 +116,7 @@ SelectableFilesModel::FilterState SelectableFilesModel::filter(Tree *t)
return Utils::anyOf(m_hideFilesFilter, matchesTreeName) ? FilterState::HIDDEN : FilterState::SHOWN;
}
-void SelectableFilesFromDirModel::buildTree(const Utils::FileName &baseDir, Tree *tree,
+void SelectableFilesFromDirModel::buildTree(const Utils::FilePath &baseDir, Tree *tree,
QFutureInterface<void> &fi, int symlinkDepth)
{
if (symlinkDepth == 0)
@@ -128,7 +128,7 @@ void SelectableFilesFromDirModel::buildTree(const Utils::FileName &baseDir, Tree
bool allChecked = true;
bool allUnchecked = true;
for (const QFileInfo &fileInfo : fileInfoList) {
- Utils::FileName fn = Utils::FileName(fileInfo);
+ Utils::FilePath fn = Utils::FilePath::fromFileInfo(fileInfo);
if (m_futureCount % 100) {
emit parsingProgress(fn);
if (fi.isCanceled())
@@ -302,14 +302,14 @@ Qt::ItemFlags SelectableFilesModel::flags(const QModelIndex &index) const
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
-Utils::FileNameList SelectableFilesModel::selectedPaths() const
+Utils::FilePathList SelectableFilesModel::selectedPaths() const
{
- Utils::FileNameList result;
+ Utils::FilePathList result;
collectPaths(m_root, &result);
return result;
}
-void SelectableFilesModel::collectPaths(Tree *root, Utils::FileNameList *result) const
+void SelectableFilesModel::collectPaths(Tree *root, Utils::FilePathList *result) const
{
if (root->checked == Qt::Unchecked)
return;
@@ -318,14 +318,14 @@ void SelectableFilesModel::collectPaths(Tree *root, Utils::FileNameList *result)
collectPaths(t, result);
}
-Utils::FileNameList SelectableFilesModel::selectedFiles() const
+Utils::FilePathList SelectableFilesModel::selectedFiles() const
{
- Utils::FileNameList result = m_outOfBaseDirFiles.toList();
+ Utils::FilePathList result = m_outOfBaseDirFiles.toList();
collectFiles(m_root, &result);
return result;
}
-Utils::FileNameList SelectableFilesModel::preservedFiles() const
+Utils::FilePathList SelectableFilesModel::preservedFiles() const
{
return m_outOfBaseDirFiles.toList();
}
@@ -335,7 +335,7 @@ bool SelectableFilesModel::hasCheckedFiles() const
return m_root->checked != Qt::Unchecked;
}
-void SelectableFilesModel::collectFiles(Tree *root, Utils::FileNameList *result) const
+void SelectableFilesModel::collectFiles(Tree *root, Utils::FilePathList *result) const
{
if (root->checked == Qt::Unchecked)
return;
@@ -591,8 +591,8 @@ SelectableFilesWidget::SelectableFilesWidget(QWidget *parent) :
layout->addWidget(m_progressLabel, static_cast<int>(SelectableFilesWidgetRows::Progress), 0, 1, 4);
}
-SelectableFilesWidget::SelectableFilesWidget(const Utils::FileName &path,
- const Utils::FileNameList &files, QWidget *parent) :
+SelectableFilesWidget::SelectableFilesWidget(const Utils::FilePath &path,
+ const Utils::FilePathList &files, QWidget *parent) :
SelectableFilesWidget(parent)
{
resetModel(path, files);
@@ -601,6 +601,10 @@ SelectableFilesWidget::SelectableFilesWidget(const Utils::FileName &path,
void SelectableFilesWidget::setAddFileFilter(const QString &filter)
{
m_selectFilesFilterEdit->setText(filter);
+ if (m_applyFiltersButton->isEnabled())
+ applyFilter();
+ else
+ m_filteringScheduled = true;
}
void SelectableFilesWidget::setBaseDirEditable(bool edit)
@@ -611,14 +615,14 @@ void SelectableFilesWidget::setBaseDirEditable(bool edit)
m_startParsingButton->setVisible(edit);
}
-Utils::FileNameList SelectableFilesWidget::selectedFiles() const
+Utils::FilePathList SelectableFilesWidget::selectedFiles() const
{
- return m_model ? m_model->selectedFiles() : Utils::FileNameList();
+ return m_model ? m_model->selectedFiles() : Utils::FilePathList();
}
-Utils::FileNameList SelectableFilesWidget::selectedPaths() const
+Utils::FilePathList SelectableFilesWidget::selectedPaths() const
{
- return m_model ? m_model->selectedPaths() : Utils::FileNameList();
+ return m_model ? m_model->selectedPaths() : Utils::FilePathList();
}
bool SelectableFilesWidget::hasFilesSelected() const
@@ -626,7 +630,7 @@ bool SelectableFilesWidget::hasFilesSelected() const
return m_model ? m_model->hasCheckedFiles() : false;
}
-void SelectableFilesWidget::resetModel(const Utils::FileName &path, const Utils::FileNameList &files)
+void SelectableFilesWidget::resetModel(const Utils::FilePath &path, const Utils::FilePathList &files)
{
m_view->setModel(nullptr);
@@ -675,6 +679,7 @@ void SelectableFilesWidget::enableWidgets(bool enabled)
void SelectableFilesWidget::applyFilter()
{
+ m_filteringScheduled = false;
if (m_model)
m_model->applyFilter(m_selectFilesFilterEdit->text(), m_hideFilesFilterEdit->text());
}
@@ -684,7 +689,7 @@ void SelectableFilesWidget::baseDirectoryChanged(bool validState)
m_startParsingButton->setEnabled(validState);
}
-void SelectableFilesWidget::startParsing(const Utils::FileName &baseDir)
+void SelectableFilesWidget::startParsing(const Utils::FilePath &baseDir)
{
if (!m_model)
return;
@@ -694,7 +699,7 @@ void SelectableFilesWidget::startParsing(const Utils::FileName &baseDir)
m_model->startParsing(baseDir);
}
-void SelectableFilesWidget::parsingProgress(const Utils::FileName &fileName)
+void SelectableFilesWidget::parsingProgress(const Utils::FilePath &fileName)
{
m_progressLabel->setText(tr("Generating file list...\n\n%1").arg(fileName.toUserOutput()));
}
@@ -706,11 +711,13 @@ void SelectableFilesWidget::parsingFinished()
smartExpand(m_model->index(0,0, QModelIndex()));
- const Utils::FileNameList preservedFiles = m_model->preservedFiles();
+ const Utils::FilePathList preservedFiles = m_model->preservedFiles();
m_preservedFilesLabel->setText(tr("Not showing %n files that are outside of the base directory.\n"
"These files are preserved.", nullptr, preservedFiles.count()));
enableWidgets(true);
+ if (m_filteringScheduled)
+ applyFilter();
}
void SelectableFilesWidget::smartExpand(const QModelIndex &idx)
@@ -728,8 +735,8 @@ void SelectableFilesWidget::smartExpand(const QModelIndex &idx)
// SelectableFilesDialogs
//////////
-SelectableFilesDialogEditFiles::SelectableFilesDialogEditFiles(const Utils::FileName &path,
- const Utils::FileNameList &files,
+SelectableFilesDialogEditFiles::SelectableFilesDialogEditFiles(const Utils::FilePath &path,
+ const Utils::FilePathList &files,
QWidget *parent) :
QDialog(parent),
m_filesWidget(new SelectableFilesWidget(path, files))
@@ -752,7 +759,7 @@ SelectableFilesDialogEditFiles::SelectableFilesDialogEditFiles(const Utils::File
layout->addWidget(buttonBox);
}
-Utils::FileNameList SelectableFilesDialogEditFiles::selectedFiles() const
+Utils::FilePathList SelectableFilesDialogEditFiles::selectedFiles() const
{
return m_filesWidget->selectedFiles();
}
@@ -763,8 +770,8 @@ Utils::FileNameList SelectableFilesDialogEditFiles::selectedFiles() const
//////////
-SelectableFilesDialogAddDirectory::SelectableFilesDialogAddDirectory(const Utils::FileName &path,
- const Utils::FileNameList &files,
+SelectableFilesDialogAddDirectory::SelectableFilesDialogAddDirectory(const Utils::FilePath &path,
+ const Utils::FilePathList &files,
QWidget *parent) :
SelectableFilesDialogEditFiles(path, files, parent)
{
diff --git a/src/plugins/projectexplorer/selectablefilesmodel.h b/src/plugins/projectexplorer/selectablefilesmodel.h
index 698ae03d05..a04a059ffc 100644
--- a/src/plugins/projectexplorer/selectablefilesmodel.h
+++ b/src/plugins/projectexplorer/selectablefilesmodel.h
@@ -64,7 +64,7 @@ public:
QList<Tree *> files;
QList<Tree *> visibleFiles;
QIcon icon;
- Utils::FileName fullPath;
+ Utils::FilePath fullPath;
Tree *parent = nullptr;
};
@@ -107,7 +107,7 @@ public:
SelectableFilesModel(QObject *parent);
~SelectableFilesModel() override;
- void setInitialMarkedFiles(const Utils::FileNameList &files);
+ void setInitialMarkedFiles(const Utils::FilePathList &files);
int columnCount(const QModelIndex &parent) const override;
int rowCount(const QModelIndex &parent) const override;
@@ -118,9 +118,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
- Utils::FileNameList selectedFiles() const;
- Utils::FileNameList selectedPaths() const;
- Utils::FileNameList preservedFiles() const;
+ Utils::FilePathList selectedFiles() const;
+ Utils::FilePathList selectedPaths() const;
+ Utils::FilePathList preservedFiles() const;
bool hasCheckedFiles() const;
@@ -141,14 +141,14 @@ protected:
private:
QList<Glob> parseFilter(const QString &filter);
Qt::CheckState applyFilter(const QModelIndex &idx);
- void collectFiles(Tree *root, Utils::FileNameList *result) const;
- void collectPaths(Tree *root, Utils::FileNameList *result) const;
+ void collectFiles(Tree *root, Utils::FilePathList *result) const;
+ void collectPaths(Tree *root, Utils::FilePathList *result) const;
void selectAllFiles(Tree *root);
protected:
bool m_allFiles = true;
- QSet<Utils::FileName> m_outOfBaseDirFiles;
- QSet<Utils::FileName> m_files;
+ QSet<Utils::FilePath> m_outOfBaseDirFiles;
+ QSet<Utils::FilePath> m_files;
Tree *m_root = nullptr;
private:
@@ -164,15 +164,15 @@ public:
SelectableFilesFromDirModel(QObject *parent);
~SelectableFilesFromDirModel() override;
- void startParsing(const Utils::FileName &baseDir);
+ void startParsing(const Utils::FilePath &baseDir);
void cancel();
signals:
void parsingFinished();
- void parsingProgress(const Utils::FileName &fileName);
+ void parsingProgress(const Utils::FilePath &fileName);
private:
- void buildTree(const Utils::FileName &baseDir,
+ void buildTree(const Utils::FilePath &baseDir,
Tree *tree,
QFutureInterface<void> &fi,
int symlinkDepth);
@@ -180,7 +180,7 @@ private:
void buildTreeFinished();
// Used in the future thread need to all not used after calling startParsing
- Utils::FileName m_baseDir;
+ Utils::FilePath m_baseDir;
QFutureWatcher<void> m_watcher;
Tree *m_rootForFuture = nullptr;
int m_futureCount = 0;
@@ -192,18 +192,18 @@ class PROJECTEXPLORER_EXPORT SelectableFilesWidget : public QWidget
public:
explicit SelectableFilesWidget(QWidget *parent = nullptr);
- SelectableFilesWidget(const Utils::FileName &path, const Utils::FileNameList &files,
+ SelectableFilesWidget(const Utils::FilePath &path, const Utils::FilePathList &files,
QWidget *parent = nullptr);
void setAddFileFilter(const QString &filter);
void setBaseDirEditable(bool edit);
- Utils::FileNameList selectedFiles() const;
- Utils::FileNameList selectedPaths() const;
+ Utils::FilePathList selectedFiles() const;
+ Utils::FilePathList selectedPaths() const;
bool hasFilesSelected() const;
- void resetModel(const Utils::FileName &path, const Utils::FileNameList &files);
+ void resetModel(const Utils::FilePath &path, const Utils::FilePathList &files);
void cancelParsing();
void enableFilterHistoryCompletion(const QString &keyPrefix);
@@ -216,8 +216,8 @@ private:
void applyFilter();
void baseDirectoryChanged(bool validState);
- void startParsing(const Utils::FileName &baseDir);
- void parsingProgress(const Utils::FileName &fileName);
+ void startParsing(const Utils::FilePath &baseDir);
+ void parsingProgress(const Utils::FilePath &fileName);
void parsingFinished();
void smartExpand(const QModelIndex &idx);
@@ -241,6 +241,7 @@ private:
QLabel *m_preservedFilesLabel;
QLabel *m_progressLabel;
+ bool m_filteringScheduled = false;
};
class PROJECTEXPLORER_EXPORT SelectableFilesDialogEditFiles : public QDialog
@@ -248,9 +249,9 @@ class PROJECTEXPLORER_EXPORT SelectableFilesDialogEditFiles : public QDialog
Q_OBJECT
public:
- SelectableFilesDialogEditFiles(const Utils::FileName &path, const Utils::FileNameList &files,
+ SelectableFilesDialogEditFiles(const Utils::FilePath &path, const Utils::FilePathList &files,
QWidget *parent);
- Utils::FileNameList selectedFiles() const;
+ Utils::FilePathList selectedFiles() const;
void setAddFileFilter(const QString &filter) { m_filesWidget->setAddFileFilter(filter); }
@@ -263,7 +264,7 @@ class SelectableFilesDialogAddDirectory : public SelectableFilesDialogEditFiles
Q_OBJECT
public:
- SelectableFilesDialogAddDirectory(const Utils::FileName &path, const Utils::FileNameList &files,
+ SelectableFilesDialogAddDirectory(const Utils::FilePath &path, const Utils::FilePathList &files,
QWidget *parent);
};
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index 26a70669d4..95a8fbd4e6 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -55,6 +55,12 @@
#include <QMessageBox>
#include <QPushButton>
+#ifdef WITH_TESTS
+#include <QTemporaryFile>
+#include <QTest>
+#include <vector>
+#endif
+
using namespace Core;
using namespace Utils;
using namespace ProjectExplorer::Internal;
@@ -204,7 +210,7 @@ QList<Project *> SessionManager::dependencies(const Project *project)
QList<Project *> projects;
foreach (const QString &dep, proDeps) {
- const Utils::FileName fn = Utils::FileName::fromString(dep);
+ const Utils::FilePath fn = Utils::FilePath::fromString(dep);
Project *pro = Utils::findOrDefault(d->m_projects, [&fn](Project *p) { return p->projectFilePath() == fn; });
if (pro)
projects += pro;
@@ -552,17 +558,17 @@ QString SessionManagerPrivate::sessionTitle(const QString &filePath)
}
QString SessionManagerPrivate::locationInProject(const QString &filePath) {
- const Project *project = SessionManager::projectForFile(Utils::FileName::fromString(filePath));
+ const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(filePath));
if (!project)
return QString();
- const Utils::FileName file = Utils::FileName::fromString(filePath);
- const Utils::FileName parentDir = file.parentDir();
+ const Utils::FilePath file = Utils::FilePath::fromString(filePath);
+ const Utils::FilePath parentDir = file.parentDir();
if (parentDir == project->projectDirectory())
return "@ " + project->displayName();
if (file.isChildOf(project->projectDirectory())) {
- const Utils::FileName dirInProject = parentDir.relativeChildPath(project->projectDirectory());
+ const Utils::FilePath dirInProject = parentDir.relativeChildPath(project->projectDirectory());
return "(" + dirInProject.toUserOutput() + " @ " + project->displayName() + ")";
}
@@ -632,7 +638,7 @@ QList<Project *> SessionManager::projectOrder(const Project *project)
return result;
}
-Project *SessionManager::projectForFile(const Utils::FileName &fileName)
+Project *SessionManager::projectForFile(const Utils::FilePath &fileName)
{
return Utils::findOrDefault(SessionManager::projects(),
[&fileName](const Project *p) { return p->isKnownFile(fileName); });
@@ -641,7 +647,7 @@ Project *SessionManager::projectForFile(const Utils::FileName &fileName)
void SessionManager::configureEditor(IEditor *editor, const QString &fileName)
{
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) {
- Project *project = projectForFile(Utils::FileName::fromString(fileName));
+ Project *project = projectForFile(Utils::FilePath::fromString(fileName));
// Global settings are the default.
if (project)
project->editorConfiguration()->configureEditor(textEditor);
@@ -738,7 +744,7 @@ QStringList SessionManager::sessions()
if (d->m_sessions.isEmpty()) {
// We are not initialized yet, so do that now
QDir sessionDir(ICore::userResourcePath());
- QList<QFileInfo> sessionFiles = sessionDir.entryInfoList(QStringList() << QLatin1String("*.qws"), QDir::NoFilter, QDir::Time);
+ QFileInfoList sessionFiles = sessionDir.entryInfoList(QStringList() << QLatin1String("*.qws"), QDir::NoFilter, QDir::Time);
foreach (const QFileInfo &fileInfo, sessionFiles) {
const QString &name = fileInfo.completeBaseName();
d->m_sessionDateTimes.insert(name, fileInfo.lastModified());
@@ -755,9 +761,9 @@ QDateTime SessionManager::sessionDateTime(const QString &session)
return d->m_sessionDateTimes.value(session);
}
-FileName SessionManager::sessionNameToFileName(const QString &session)
+FilePath SessionManager::sessionNameToFileName(const QString &session)
{
- return FileName::fromString(ICore::userResourcePath() + QLatin1Char('/') + session + QLatin1String(".qws"));
+ return FilePath::fromString(ICore::userResourcePath() + QLatin1Char('/') + session + QLatin1String(".qws"));
}
/*!
@@ -786,11 +792,15 @@ bool SessionManager::renameSession(const QString &original, const QString &newNa
/*!
\brief Shows a dialog asking the user to confirm deleting the session \p session
*/
-bool SessionManager::confirmSessionDelete(const QString &session)
+bool SessionManager::confirmSessionDelete(const QStringList &sessions)
{
+ const QString title = sessions.size() == 1 ? tr("Delete Session") : tr("Delete Sessions");
+ const QString question = sessions.size() == 1
+ ? tr("Delete session %1?").arg(sessions.first())
+ : tr("Delete these sessions?\n %1").arg(sessions.join("\n "));
return QMessageBox::question(ICore::mainWindow(),
- tr("Delete Session"),
- tr("Delete session %1?").arg(session),
+ title,
+ question,
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
}
@@ -808,6 +818,12 @@ bool SessionManager::deleteSession(const QString &session)
return false;
}
+void SessionManager::deleteSessions(const QStringList &sessions)
+{
+ for (const QString &session : sessions)
+ deleteSession(session);
+}
+
bool SessionManager::cloneSession(const QString &original, const QString &clone)
{
if (!d->m_sessions.contains(original))
@@ -931,7 +947,7 @@ bool SessionManager::loadSession(const QString &session)
QStringList fileList;
// Try loading the file
- FileName fileName = sessionNameToFileName(session);
+ FilePath fileName = sessionNameToFileName(session);
PersistentSettingsReader reader;
if (fileName.exists()) {
if (!reader.load(fileName)) {
@@ -1002,11 +1018,8 @@ bool SessionManager::loadSession(const QString &session)
d->m_future.setProgressRange(0, projectPathsToLoad.count() + 1/*initialization above*/ + 1/*editors*/);
d->m_future.setProgressValue(1);
-
- // if one processEvents doesn't get the job done
- // just use two!
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+
d->restoreProjects(projectPathsToLoad);
d->sessionLoadingProgress();
d->restoreDependencies(reader);
@@ -1065,7 +1078,7 @@ void SessionManagerPrivate::sessionLoadingProgress()
QStringList SessionManager::projectsForSessionName(const QString &session)
{
- const FileName fileName = sessionNameToFileName(session);
+ const FilePath fileName = sessionNameToFileName(session);
PersistentSettingsReader reader;
if (fileName.exists()) {
if (!reader.load(fileName)) {
@@ -1076,4 +1089,58 @@ QStringList SessionManager::projectsForSessionName(const QString &session)
return reader.restoreValue(QLatin1String("ProjectList")).toStringList();
}
+#ifdef WITH_TESTS
+
+void ProjectExplorerPlugin::testSessionSwitch()
+{
+ QVERIFY(SessionManager::createSession("session1"));
+ QVERIFY(SessionManager::createSession("session2"));
+ QTemporaryFile cppFile("main.cpp");
+ QVERIFY(cppFile.open());
+ cppFile.close();
+ QTemporaryFile projectFile1("XXXXXX.pro");
+ QTemporaryFile projectFile2("XXXXXX.pro");
+ struct SessionSpec {
+ SessionSpec(const QString &n, QTemporaryFile &f) : name(n), projectFile(f) {}
+ const QString name;
+ QTemporaryFile &projectFile;
+ };
+ std::vector<SessionSpec> sessionSpecs{SessionSpec("session1", projectFile1),
+ SessionSpec("session2", projectFile2)};
+ for (const SessionSpec &sessionSpec : sessionSpecs) {
+ static const QByteArray proFileContents
+ = "TEMPLATE = app\n"
+ "CONFIG -= qt\n"
+ "SOURCES = " + cppFile.fileName().toLocal8Bit();
+ QVERIFY(sessionSpec.projectFile.open());
+ sessionSpec.projectFile.write(proFileContents);
+ sessionSpec.projectFile.close();
+ QVERIFY(SessionManager::loadSession(sessionSpec.name));
+ const OpenProjectResult openResult
+ = ProjectExplorerPlugin::openProject(sessionSpec.projectFile.fileName());
+ if (openResult.errorMessage().contains("text/plain"))
+ QSKIP("This test requires the presence of QmakeProjectManager to be fully functional");
+ QVERIFY(openResult);
+ QCOMPARE(openResult.projects().count(), 1);
+ QVERIFY(openResult.project());
+ QCOMPARE(SessionManager::projects().count(), 1);
+ }
+ for (int i = 0; i < 30; ++i) {
+ QVERIFY(SessionManager::loadSession("session1"));
+ QCOMPARE(SessionManager::activeSession(), "session1");
+ QCOMPARE(SessionManager::projects().count(), 1);
+ QVERIFY(SessionManager::loadSession("session2"));
+ QCOMPARE(SessionManager::activeSession(), "session2");
+ QCOMPARE(SessionManager::projects().count(), 1);
+ }
+ QVERIFY(SessionManager::loadSession("session1"));
+ SessionManager::closeAllProjects();
+ QVERIFY(SessionManager::loadSession("session2"));
+ SessionManager::closeAllProjects();
+ QVERIFY(SessionManager::deleteSession("session1"));
+ QVERIFY(SessionManager::deleteSession("session2"));
+}
+
+#endif // WITH_TESTS
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h
index 3a49be8308..782079f9d7 100644
--- a/src/plugins/projectexplorer/session.h
+++ b/src/plugins/projectexplorer/session.h
@@ -63,8 +63,9 @@ public:
static bool createSession(const QString &session);
- static bool confirmSessionDelete(const QString &session);
+ static bool confirmSessionDelete(const QStringList &sessions);
static bool deleteSession(const QString &session);
+ static void deleteSessions(const QStringList &sessions);
static bool cloneSession(const QString &original, const QString &clone);
static bool renameSession(const QString &original, const QString &newName);
@@ -93,7 +94,7 @@ public:
static void setActiveBuildConfiguration(Target *t, BuildConfiguration *bc, SetActive cascade);
static void setActiveDeployConfiguration(Target *t, DeployConfiguration *dc, SetActive cascade);
- static Utils::FileName sessionNameToFileName(const QString &session);
+ static Utils::FilePath sessionNameToFileName(const QString &session);
static Project *startupProject();
static const QList<Project *> projects();
@@ -110,7 +111,7 @@ public:
// NBS rewrite projectOrder (dependency management)
static QList<Project *> projectOrder(const Project *project = nullptr);
- static Project *projectForFile(const Utils::FileName &fileName);
+ static Project *projectForFile(const Utils::FilePath &fileName);
static QStringList projectsForSessionName(const QString &session);
diff --git a/src/plugins/projectexplorer/sessiondialog.cpp b/src/plugins/projectexplorer/sessiondialog.cpp
index 2dfb944a35..6cda77927b 100644
--- a/src/plugins/projectexplorer/sessiondialog.cpp
+++ b/src/plugins/projectexplorer/sessiondialog.cpp
@@ -26,6 +26,8 @@
#include "sessiondialog.h"
#include "session.h"
+#include <utils/algorithm.h>
+
#include <QInputDialog>
#include <QValidator>
@@ -131,7 +133,7 @@ SessionDialog::SessionDialog(QWidget *parent) : QDialog(parent)
connect(m_ui.btClone, &QAbstractButton::clicked,
m_ui.sessionView, &SessionView::cloneCurrentSession);
connect(m_ui.btDelete, &QAbstractButton::clicked,
- m_ui.sessionView, &SessionView::deleteCurrentSession);
+ m_ui.sessionView, &SessionView::deleteSelectedSessions);
connect(m_ui.btSwitch, &QAbstractButton::clicked,
m_ui.sessionView, &SessionView::switchToCurrentSession);
connect(m_ui.btRename, &QAbstractButton::clicked,
@@ -157,21 +159,23 @@ bool SessionDialog::autoLoadSession() const
return m_ui.autoLoadCheckBox->checkState() == Qt::Checked;
}
-void SessionDialog::updateActions(const QString &session)
+void SessionDialog::updateActions(const QStringList &sessions)
{
- if (session.isEmpty()) {
+ if (sessions.isEmpty()) {
m_ui.btDelete->setEnabled(false);
m_ui.btRename->setEnabled(false);
m_ui.btClone->setEnabled(false);
m_ui.btSwitch->setEnabled(false);
- } else {
- bool isDefault = (session == QLatin1String("default"));
- bool isActive = (session == SessionManager::activeSession());
- m_ui.btDelete->setEnabled(!isActive && !isDefault);
- m_ui.btRename->setEnabled(!isDefault);
- m_ui.btClone->setEnabled(true);
- m_ui.btSwitch->setEnabled(true);
+ return;
}
+ const bool defaultIsSelected = sessions.contains("default");
+ const bool activeIsSelected = Utils::anyOf(sessions, [](const QString &session) {
+ return session == SessionManager::activeSession();
+ });
+ m_ui.btDelete->setEnabled(!defaultIsSelected && !activeIsSelected);
+ m_ui.btRename->setEnabled(sessions.size() == 1 && !defaultIsSelected);
+ m_ui.btClone->setEnabled(sessions.size() == 1);
+ m_ui.btSwitch->setEnabled(sessions.size() == 1);
}
} // namespace Internal
diff --git a/src/plugins/projectexplorer/sessiondialog.h b/src/plugins/projectexplorer/sessiondialog.h
index 654736694e..701748b55c 100644
--- a/src/plugins/projectexplorer/sessiondialog.h
+++ b/src/plugins/projectexplorer/sessiondialog.h
@@ -49,7 +49,7 @@ public:
bool autoLoadSession() const;
private:
- void updateActions(const QString &session);
+ void updateActions(const QStringList &sessions);
Ui::SessionDialog m_ui;
};
diff --git a/src/plugins/projectexplorer/sessionmodel.cpp b/src/plugins/projectexplorer/sessionmodel.cpp
index 21b3ec3f48..bcf13e96dd 100644
--- a/src/plugins/projectexplorer/sessionmodel.cpp
+++ b/src/plugins/projectexplorer/sessionmodel.cpp
@@ -55,7 +55,7 @@ int SessionModel::indexOfSession(const QString &session)
return SessionManager::sessions().indexOf(session);
}
-QString SessionModel::sessionAt(int row)
+QString SessionModel::sessionAt(int row) const
{
return SessionManager::sessions().value(row, QString());
}
@@ -209,12 +209,12 @@ void SessionModel::cloneSession(QWidget *parent, const QString &session)
});
}
-void SessionModel::deleteSession(const QString &session)
+void SessionModel::deleteSessions(const QStringList &sessions)
{
- if (!SessionManager::confirmSessionDelete(session))
+ if (!SessionManager::confirmSessionDelete(sessions))
return;
beginResetModel();
- SessionManager::deleteSession(session);
+ SessionManager::deleteSessions(sessions);
endResetModel();
}
diff --git a/src/plugins/projectexplorer/sessionmodel.h b/src/plugins/projectexplorer/sessionmodel.h
index 7feff2b433..63f9984215 100644
--- a/src/plugins/projectexplorer/sessionmodel.h
+++ b/src/plugins/projectexplorer/sessionmodel.h
@@ -53,7 +53,7 @@ public:
explicit SessionModel(QObject *parent = nullptr);
int indexOfSession(const QString &session);
- QString sessionAt(int row);
+ QString sessionAt(int row) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -72,7 +72,7 @@ public slots:
void resetSessions();
void newSession(QWidget *parent);
void cloneSession(QWidget *parent, const QString &session);
- void deleteSession(const QString &session);
+ void deleteSessions(const QStringList &sessions);
void renameSession(QWidget *parent, const QString &session);
void switchToSession(const QString &session);
diff --git a/src/plugins/projectexplorer/sessionview.cpp b/src/plugins/projectexplorer/sessionview.cpp
index 4e3bda6510..07d918ca77 100644
--- a/src/plugins/projectexplorer/sessionview.cpp
+++ b/src/plugins/projectexplorer/sessionview.cpp
@@ -27,9 +27,12 @@
#include "session.h"
+#include <utils/algorithm.h>
+
+#include <QHeaderView>
#include <QItemSelection>
+#include <QStringList>
#include <QStyledItemDelegate>
-#include <QHeaderView>
namespace ProjectExplorer {
namespace Internal {
@@ -57,7 +60,7 @@ SessionView::SessionView(QWidget *parent)
{
setItemDelegate(new RemoveItemFocusDelegate(this));
setSelectionBehavior(QAbstractItemView::SelectRows);
- setSelectionMode(QAbstractItemView::SingleSelection);
+ setSelectionMode(QAbstractItemView::ExtendedSelection);
setWordWrap(false);
setRootIsDecorated(false);
@@ -74,9 +77,8 @@ SessionView::SessionView(QWidget *parent)
connect(this, &Utils::TreeView::activated, [this](const QModelIndex &index){
emit activated(m_sessionModel.sessionAt(index.row()));
});
- connect(selectionModel(), &QItemSelectionModel::currentRowChanged, [this]
- (const QModelIndex &index) {
- emit selected(m_sessionModel.sessionAt(index.row()));
+ connect(selectionModel(), &QItemSelectionModel::selectionChanged, [this] {
+ emit selected(selectedSessions());
});
connect(&m_sessionModel, &SessionModel::sessionSwitched,
@@ -92,9 +94,14 @@ void SessionView::createNewSession()
m_sessionModel.newSession(this);
}
-void SessionView::deleteCurrentSession()
+void SessionView::deleteSelectedSessions()
+{
+ deleteSessions(selectedSessions());
+}
+
+void SessionView::deleteSessions(const QStringList &sessions)
{
- m_sessionModel.deleteSession(currentSession());
+ m_sessionModel.deleteSessions(sessions);
}
void SessionView::cloneCurrentSession()
@@ -141,5 +148,25 @@ void SessionView::showEvent(QShowEvent *event)
setFocus();
}
+void SessionView::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() != Qt::Key_Delete) {
+ TreeView::keyPressEvent(event);
+ return;
+ }
+ const QStringList sessions = selectedSessions();
+ if (!sessions.contains("default") && !Utils::anyOf(sessions,
+ [](const QString &session) { return session == SessionManager::activeSession(); })) {
+ deleteSessions(sessions);
+ }
+}
+
+QStringList SessionView::selectedSessions() const
+{
+ return Utils::transform(selectionModel()->selectedRows(), [this](const QModelIndex &index) {
+ return m_sessionModel.sessionAt(index.row());
+ });
+}
+
} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/sessionview.h b/src/plugins/projectexplorer/sessionview.h
index 0f85e6ed21..21988c3838 100644
--- a/src/plugins/projectexplorer/sessionview.h
+++ b/src/plugins/projectexplorer/sessionview.h
@@ -41,7 +41,7 @@ public:
explicit SessionView(QWidget *parent = nullptr);
void createNewSession();
- void deleteCurrentSession();
+ void deleteSelectedSessions();
void cloneCurrentSession();
void renameCurrentSession();
void switchToCurrentSession();
@@ -51,15 +51,18 @@ public:
void selectActiveSession();
void selectSession(const QString &sessionName);
-protected:
- void showEvent(QShowEvent* event) override;
-
signals:
void activated(const QString &session);
- void selected(const QString &session);
+ void selected(const QStringList &sessions);
void sessionSwitched();
private:
+ void showEvent(QShowEvent* event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+
+ void deleteSessions(const QStringList &sessions);
+ QStringList selectedSessions() const;
+
SessionModel m_sessionModel;
};
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index 70d742e34e..d02dc8c6e8 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -102,7 +102,7 @@ public:
QList<RunConfiguration *> m_runConfigurations;
RunConfiguration* m_activeRunConfiguration = nullptr;
DeploymentData m_deploymentData;
- BuildTargetInfoList m_appTargets;
+ QList<BuildTargetInfo> m_appTargets;
QVariantMap m_pluginSettings;
Kit *const m_kit;
@@ -345,19 +345,26 @@ DeploymentData Target::deploymentData() const
return d->m_deploymentData;
}
-void Target::setApplicationTargets(const BuildTargetInfoList &appTargets)
+void Target::setApplicationTargets(const QList<BuildTargetInfo> &appTargets)
{
- if (d->m_appTargets != appTargets) {
+ if (appTargets.toSet() != d->m_appTargets.toSet()) {
d->m_appTargets = appTargets;
emit applicationTargetsChanged();
}
}
-BuildTargetInfoList Target::applicationTargets() const
+const QList<BuildTargetInfo> Target::applicationTargets() const
{
return d->m_appTargets;
}
+BuildTargetInfo Target::buildTarget(const QString &buildKey) const
+{
+ return Utils::findOrDefault(d->m_appTargets, [&buildKey](const BuildTargetInfo &ti) {
+ return ti.buildKey == buildKey;
+ });
+}
+
QList<ProjectConfiguration *> Target::projectConfigurations() const
{
QList<ProjectConfiguration *> result;
@@ -452,7 +459,7 @@ void Target::setOverlayIcon(const QIcon &icon)
QString Target::overlayIconToolTip()
{
- IDevice::ConstPtr current = DeviceKitInformation::device(kit());
+ IDevice::ConstPtr current = DeviceKitAspect::device(kit());
return current.isNull() ? QString() : formatDeviceInfo(current->deviceInformation());
}
@@ -680,9 +687,14 @@ QVariant Target::additionalData(Core::Id id) const
return project()->additionalData(id, this);
}
+MakeInstallCommand Target::makeInstallCommand(const QString &installRoot) const
+{
+ return project()->makeInstallCommand(this, installRoot);
+}
+
void Target::updateDeviceState()
{
- IDevice::ConstPtr current = DeviceKitInformation::device(kit());
+ IDevice::ConstPtr current = DeviceKitAspect::device(kit());
QIcon overlay;
static const QIcon disconnected = Icons::DEVICE_DISCONNECTED_INDICATOR_OVERLAY.icon();
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index 18eb92d273..a630e28468 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -34,18 +34,13 @@
QT_FORWARD_DECLARE_CLASS(QIcon)
-namespace Utils { class Environment; }
-
namespace ProjectExplorer {
class BuildConfiguration;
-class BuildTargetInfoList;
+class BuildTargetInfo;
class DeployConfiguration;
-class DeployConfigurationFactory;
class DeploymentData;
-class BuildConfigurationFactory;
-class RunConfigurationFactory;
class Kit;
-class NamedWidget;
+class MakeInstallCommand;
class Project;
class RunConfiguration;
@@ -86,8 +81,9 @@ public:
void setDeploymentData(const DeploymentData &deploymentData);
DeploymentData deploymentData() const;
- void setApplicationTargets(const BuildTargetInfoList &appTargets);
- BuildTargetInfoList applicationTargets() const;
+ void setApplicationTargets(const QList<BuildTargetInfo> &appTargets);
+ const QList<BuildTargetInfo> applicationTargets() const;
+ BuildTargetInfo buildTarget(const QString &buildKey) const;
QList<ProjectConfiguration *> projectConfigurations() const;
@@ -121,6 +117,7 @@ public:
void setNamedSettings(const QString &name, const QVariant &value);
QVariant additionalData(Core::Id id) const;
+ MakeInstallCommand makeInstallCommand(const QString &installRoot) const;
template<typename S, typename R, typename T>
void subscribeSignal(void (S::*sig)(), R*recv, T (R::*sl)()) {
diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp
index 78d7daabc8..adaba34842 100644
--- a/src/plugins/projectexplorer/targetsettingspanel.cpp
+++ b/src/plugins/projectexplorer/targetsettingspanel.cpp
@@ -80,6 +80,12 @@ class TargetSetupPageWrapper : public QWidget
public:
explicit TargetSetupPageWrapper(Project *project);
+ void ensureSetupPage()
+ {
+ if (!m_targetSetupPage)
+ addTargetSetupPage();
+ }
+
protected:
void keyReleaseEvent(QKeyEvent *event) override
{
@@ -89,24 +95,26 @@ protected:
void keyPressEvent(QKeyEvent *event) override
{
+ if (m_targetSetupPage && m_targetSetupPage->importLineEditHasFocus())
+ return;
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
event->accept();
- done();
+ if (m_targetSetupPage)
+ done();
}
}
private:
void done()
{
+ QTC_ASSERT(m_targetSetupPage, return);
+ m_targetSetupPage->disconnect();
m_targetSetupPage->setupProject(m_project);
+ m_targetSetupPage->deleteLater();
+ m_targetSetupPage = nullptr;
Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
}
- void cancel()
- {
- ProjectExplorerPlugin::unloadProject(m_project);
- }
-
void kitUpdated(ProjectExplorer::Kit *k)
{
if (k == KitManager::defaultKit())
@@ -115,29 +123,21 @@ private:
void completeChanged()
{
- m_configureButton->setEnabled(m_targetSetupPage->isComplete());
+ m_configureButton->setEnabled(m_targetSetupPage && m_targetSetupPage->isComplete());
}
void updateNoteText();
+ void addTargetSetupPage();
- Project *m_project;
- TargetSetupPage *m_targetSetupPage;
- QPushButton *m_configureButton;
+ Project * const m_project;
+ TargetSetupPage *m_targetSetupPage = nullptr;
+ QPushButton *m_configureButton = nullptr;
+ QVBoxLayout *m_setupPageContainer = nullptr;
};
TargetSetupPageWrapper::TargetSetupPageWrapper(Project *project)
: m_project(project)
{
- m_targetSetupPage = new TargetSetupPage(this);
- m_targetSetupPage->setUseScrollArea(false);
- m_targetSetupPage->setProjectPath(project->projectFilePath().toString());
- m_targetSetupPage->setRequiredKitPredicate(project->requiredKitPredicate());
- m_targetSetupPage->setPreferredKitPredicate(project->preferredKitPredicate());
- m_targetSetupPage->setProjectImporter(project->projectImporter());
- m_targetSetupPage->initializePage();
- m_targetSetupPage->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- updateNoteText();
-
auto box = new QDialogButtonBox(this);
m_configureButton = new QPushButton(this);
@@ -150,24 +150,20 @@ TargetSetupPageWrapper::TargetSetupPageWrapper(Project *project)
auto layout = new QVBoxLayout(this);
layout->setMargin(0);
- layout->addWidget(m_targetSetupPage);
+ m_setupPageContainer = new QVBoxLayout;
+ layout->addLayout(m_setupPageContainer);
layout->addLayout(hbox);
layout->addStretch(10);
-
completeChanged();
-
connect(m_configureButton, &QAbstractButton::clicked,
this, &TargetSetupPageWrapper::done);
- connect(m_targetSetupPage, &QWizardPage::completeChanged,
- this, &TargetSetupPageWrapper::completeChanged);
- connect(KitManager::instance(), &KitManager::defaultkitChanged,
- this, &TargetSetupPageWrapper::updateNoteText);
- connect(KitManager::instance(), &KitManager::kitUpdated,
- this, &TargetSetupPageWrapper::kitUpdated);
}
void TargetSetupPageWrapper::updateNoteText()
{
+ if (!m_targetSetupPage)
+ return;
+
Kit *k = KitManager::defaultKit();
QString text;
@@ -198,6 +194,29 @@ void TargetSetupPageWrapper::updateNoteText()
m_targetSetupPage->showOptionsHint(showHint);
}
+void TargetSetupPageWrapper::addTargetSetupPage()
+{
+ m_targetSetupPage = new TargetSetupPage(this);
+ m_targetSetupPage->setUseScrollArea(false);
+ m_targetSetupPage->setProjectPath(m_project->projectFilePath().toString());
+ m_targetSetupPage->setRequiredKitPredicate(m_project->requiredKitPredicate());
+ m_targetSetupPage->setPreferredKitPredicate(m_project->preferredKitPredicate());
+ m_targetSetupPage->setProjectImporter(m_project->projectImporter());
+ m_targetSetupPage->initializePage();
+ m_targetSetupPage->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ m_setupPageContainer->addWidget(m_targetSetupPage);
+ updateNoteText();
+
+ completeChanged();
+
+ connect(m_targetSetupPage, &QWizardPage::completeChanged,
+ this, &TargetSetupPageWrapper::completeChanged);
+ connect(KitManager::instance(), &KitManager::defaultkitChanged,
+ this, &TargetSetupPageWrapper::updateNoteText);
+ connect(KitManager::instance(), &KitManager::kitUpdated,
+ this, &TargetSetupPageWrapper::kitUpdated);
+}
+
//
// TargetSettingsPanelItem
//
@@ -228,6 +247,7 @@ public:
QPointer<QWidget> m_noKitLabel;
QPointer<QWidget> m_configurePage;
QPointer<QWidget> m_configuredPage;
+ TargetSetupPageWrapper *m_targetSetupPageWrapper = nullptr;
};
void TargetGroupItemPrivate::ensureWidget()
@@ -253,12 +273,13 @@ void TargetGroupItemPrivate::ensureWidget()
}
if (!m_configurePage) {
- auto widget = new TargetSetupPageWrapper(m_project);
+ m_targetSetupPageWrapper = new TargetSetupPageWrapper(m_project);
m_configurePage = new PanelsWidget(tr("Configure Project"),
QIcon(":/projectexplorer/images/unconfigured.png"),
- widget);
- m_configurePage->setFocusProxy(widget);
+ m_targetSetupPageWrapper);
+ m_configurePage->setFocusProxy(m_targetSetupPageWrapper);
}
+ m_targetSetupPageWrapper->ensureSetupPage();
if (!m_configuredPage) {
auto widget = new QWidget;
@@ -283,7 +304,7 @@ class TargetItem : public TypedTreeItem<TreeItem, TargetGroupItem>
public:
enum { DefaultPage = 0 }; // Build page.
- TargetItem(Project *project, Id kitId, const QList<Task> &issues)
+ TargetItem(Project *project, Id kitId, const Tasks &issues)
: m_project(project), m_kitId(kitId), m_kitIssues(issues)
{
m_kitWarningForProject = containsType(m_kitIssues, Task::TaskType::Warning);
@@ -483,7 +504,7 @@ public:
int m_currentChild = DefaultPage;
bool m_kitErrorsForProject = false;
bool m_kitWarningForProject = false;
- QList<Task> m_kitIssues;
+ Tasks m_kitIssues;
private:
enum class IconOverlay {
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
index 501e0efc39..0a750199fe 100644
--- a/src/plugins/projectexplorer/targetsetuppage.cpp
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -67,10 +67,10 @@ IPotentialKit::~IPotentialKit()
}
namespace Internal {
-static Utils::FileName importDirectory(const QString &projectPath)
+static Utils::FilePath importDirectory(const QString &projectPath)
{
// Setup import widget:
- auto path = Utils::FileName::fromString(projectPath);
+ auto path = Utils::FilePath::fromString(projectPath);
path = path.parentDir(); // base dir
path = path.parentDir(); // parent dir
@@ -210,7 +210,7 @@ TargetSetupPage::TargetSetupPage(QWidget *parent) :
connect(km, &KitManager::kitRemoved, this, &TargetSetupPage::handleKitRemoval);
connect(km, &KitManager::kitUpdated, this, &TargetSetupPage::handleKitUpdate);
connect(m_importWidget, &ImportWidget::importFrom,
- this, [this](const Utils::FileName &dir) { import(dir); });
+ this, [this](const Utils::FilePath &dir) { import(dir); });
setProperty(Utils::SHORT_TITLE_PROPERTY, tr("Kits"));
}
@@ -328,6 +328,11 @@ void TargetSetupPage::setProjectImporter(ProjectImporter *importer)
initializePage();
}
+bool TargetSetupPage::importLineEditHasFocus() const
+{
+ return m_importWidget->lineEditHasFocus();
+}
+
void TargetSetupPage::setNoteText(const QString &text)
{
m_ui->descriptionLabel->setText(text);
@@ -347,7 +352,7 @@ void TargetSetupPage::setupImports()
QStringList toImport = m_importer->importCandidates();
foreach (const QString &path, toImport)
- import(Utils::FileName::fromString(path), true);
+ import(Utils::FilePath::fromString(path), true);
}
void TargetSetupPage::handleKitAddition(Kit *k)
@@ -485,7 +490,7 @@ bool TargetSetupPage::isUpdating() const
return false;
}
-void TargetSetupPage::import(const Utils::FileName &path, bool silent)
+void TargetSetupPage::import(const Utils::FilePath &path, bool silent)
{
if (!m_importer)
return;
diff --git a/src/plugins/projectexplorer/targetsetuppage.h b/src/plugins/projectexplorer/targetsetuppage.h
index 86eeb65013..102ffbd57c 100644
--- a/src/plugins/projectexplorer/targetsetuppage.h
+++ b/src/plugins/projectexplorer/targetsetuppage.h
@@ -40,7 +40,7 @@
QT_FORWARD_DECLARE_CLASS(QSpacerItem)
namespace Core { class Id; }
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ProjectExplorer {
class Kit;
@@ -70,6 +70,7 @@ public:
void setPreferredKitPredicate(const ProjectExplorer::Kit::Predicate &predicate);
void setProjectPath(const QString &dir);
void setProjectImporter(ProjectImporter *importer);
+ bool importLineEditHasFocus() const;
/// Sets whether the targetsetupage uses a scrollarea
/// to host the widgets from the factories
@@ -105,7 +106,7 @@ private:
Internal::TargetSetupWidget *addWidget(Kit *k);
void setupImports();
- void import(const Utils::FileName &path, bool silent = false);
+ void import(const Utils::FilePath &path, bool silent = false);
void setupWidgets(const QString &filterText = QString());
void reset();
diff --git a/src/plugins/projectexplorer/targetsetupwidget.cpp b/src/plugins/projectexplorer/targetsetupwidget.cpp
index 88e5b4ab06..6aa66517e3 100644
--- a/src/plugins/projectexplorer/targetsetupwidget.cpp
+++ b/src/plugins/projectexplorer/targetsetupwidget.cpp
@@ -29,7 +29,6 @@
#include "buildinfo.h"
#include "projectexplorerconstants.h"
#include "kit.h"
-#include "kitconfigwidget.h"
#include "kitmanager.h"
#include "kitoptionspage.h"
@@ -73,7 +72,7 @@ TargetSetupWidget::TargetSetupWidget(Kit *k, const QString &projectPath) :
auto panel = new Utils::FadingWidget(m_detailsWidget);
auto panelLayout = new QHBoxLayout(panel);
- m_manageButton = new QPushButton(KitConfigWidget::msgManage());
+ m_manageButton = new QPushButton(KitAspectWidget::msgManage());
panelLayout->addWidget(m_manageButton);
m_detailsWidget->setToolWidget(panel);
@@ -319,7 +318,7 @@ QPair<Task::TaskType, QString> TargetSetupWidget::findIssues(const BuildInfo &in
return qMakePair(Task::Unknown, QString());
QString buildDir = info.buildDirectory.toString();
- QList<Task> issues;
+ Tasks issues;
if (info.factory())
issues = info.factory()->reportIssues(m_kit, m_projectPath, buildDir);
diff --git a/src/plugins/projectexplorer/task.cpp b/src/plugins/projectexplorer/task.cpp
index 83409fadd5..2a323f0041 100644
--- a/src/plugins/projectexplorer/task.cpp
+++ b/src/plugins/projectexplorer/task.cpp
@@ -25,6 +25,7 @@
#include "task.h"
+#include "fileinsessionfinder.h"
#include "projectexplorerconstants.h"
#include <app/app_version.h>
@@ -34,6 +35,7 @@
#include <utils/utilsicons.h>
#include <utils/qtcassert.h>
+#include <QFileInfo>
#include <QTextStream>
namespace ProjectExplorer
@@ -60,13 +62,14 @@ unsigned int Task::s_nextId = 1;
*/
Task::Task(TaskType type_, const QString &description_,
- const Utils::FileName &file_, int line_, Core::Id category_,
+ const Utils::FilePath &file_, int line_, Core::Id category_,
const QIcon &icon, Options options) :
taskId(s_nextId), type(type_), options(options), description(description_),
- file(file_), line(line_), movedLine(line_), category(category_),
+ line(line_), movedLine(line_), category(category_),
icon(icon.isNull() ? taskTypeIcon(type_) : icon)
{
++s_nextId;
+ setFile(file_);
}
Task Task::compilerMissingTask()
@@ -76,7 +79,7 @@ Task Task::compilerMissingTask()
"%1 needs a compiler set up to build. "
"Configure a compiler in the kit options.")
.arg(Core::Constants::IDE_DISPLAY_NAME),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Constants::TASK_CATEGORY_BUILDSYSTEM);
}
@@ -87,7 +90,7 @@ Task Task::buildConfigurationMissingTask()
"%1 needs a build configuration set up to build. "
"Configure a build configuration in the project settings.")
.arg(Core::Constants::IDE_DISPLAY_NAME),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
Constants::TASK_CATEGORY_BUILDSYSTEM);
}
@@ -108,7 +111,7 @@ void Task::clear()
taskId = 0;
type = Task::Unknown;
description.clear();
- file = Utils::FileName();
+ file = Utils::FilePath();
line = -1;
movedLine = -1;
category = Core::Id();
@@ -117,6 +120,18 @@ void Task::clear()
m_mark.clear();
}
+void Task::setFile(const Utils::FilePath &file_)
+{
+ file = file_;
+ if (!file.isEmpty() && !file.toFileInfo().isAbsolute()) {
+ Utils::FilePathList possiblePaths = Internal::findFileInSession(file);
+ if (possiblePaths.length() == 1)
+ file = possiblePaths.first();
+ else
+ fileCandidates = possiblePaths;
+ }
+}
+
//
// functions
//
@@ -153,7 +168,7 @@ uint qHash(const Task &task)
return task.taskId;
}
-QString toHtml(const QList<Task> &issues)
+QString toHtml(const Tasks &issues)
{
QString result;
QTextStream str(&result);
@@ -176,7 +191,7 @@ QString toHtml(const QList<Task> &issues)
return result;
}
-bool containsType(const QList<Task> &issues, Task::TaskType type)
+bool containsType(const Tasks &issues, Task::TaskType type)
{
return Utils::contains(issues, [type](const Task &t) { return t.type == type; });
}
diff --git a/src/plugins/projectexplorer/task.h b/src/plugins/projectexplorer/task.h
index f3e1b76c88..739e90f176 100644
--- a/src/plugins/projectexplorer/task.h
+++ b/src/plugins/projectexplorer/task.h
@@ -61,7 +61,7 @@ public:
Task() = default;
Task(TaskType type, const QString &description,
- const Utils::FileName &file, int line, Core::Id category,
+ const Utils::FilePath &file, int line, Core::Id category,
const QIcon &icon = QIcon(),
Options options = AddTextMark | FlashWorthy);
@@ -70,12 +70,14 @@ public:
bool isNull() const;
void clear();
+ void setFile(const Utils::FilePath &file);
unsigned int taskId = 0;
TaskType type = Unknown;
Options options = AddTextMark | FlashWorthy;
QString description;
- Utils::FileName file;
+ Utils::FilePath file;
+ Utils::FilePathList fileCandidates;
int line = -1;
int movedLine = -1; // contains a line number if the line was moved in the editor
Core::Id category;
@@ -100,13 +102,15 @@ private:
friend class TaskHub;
};
+using Tasks = QVector<Task>;
+
bool PROJECTEXPLORER_EXPORT operator==(const Task &t1, const Task &t2);
uint PROJECTEXPLORER_EXPORT qHash(const Task &task);
bool PROJECTEXPLORER_EXPORT operator<(const Task &a, const Task &b);
-QString PROJECTEXPLORER_EXPORT toHtml(const QList<Task> &issues);
-bool PROJECTEXPLORER_EXPORT containsType(const QList<Task> &issues, Task::TaskType);
+QString PROJECTEXPLORER_EXPORT toHtml(const Tasks &issues);
+bool PROJECTEXPLORER_EXPORT containsType(const Tasks &issues, Task::TaskType);
} //namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp
index 5ed8aa9677..10b04c4d5b 100644
--- a/src/plugins/projectexplorer/taskhub.cpp
+++ b/src/plugins/projectexplorer/taskhub.cpp
@@ -79,7 +79,7 @@ public:
bool isClickable() const override;
void clicked() override;
- void updateFileName(const FileName &fileName) override;
+ void updateFileName(const FilePath &fileName) override;
void updateLineNumber(int lineNumber) override;
void removedFromEditor() override;
private:
@@ -92,10 +92,10 @@ void TaskMark::updateLineNumber(int lineNumber)
TextMark::updateLineNumber(lineNumber);
}
-void TaskMark::updateFileName(const FileName &fileName)
+void TaskMark::updateFileName(const FilePath &fileName)
{
TaskHub::updateTaskFileName(m_id, fileName.toString());
- TextMark::updateFileName(FileName::fromString(fileName.toString()));
+ TextMark::updateFileName(FilePath::fromString(fileName.toString()));
}
void TaskMark::removedFromEditor()
@@ -117,7 +117,7 @@ TaskHub::TaskHub()
{
m_instance = this;
qRegisterMetaType<ProjectExplorer::Task>("ProjectExplorer::Task");
- qRegisterMetaType<QList<ProjectExplorer::Task> >("QList<ProjectExplorer::Task>");
+ qRegisterMetaType<Tasks >("Tasks");
}
TaskHub::~TaskHub()
@@ -138,7 +138,7 @@ TaskHub *TaskHub::instance()
return m_instance;
}
-void TaskHub::addTask(Task::TaskType type, const QString &description, Core::Id category, const Utils::FileName &file, int line)
+void TaskHub::addTask(Task::TaskType type, const QString &description, Core::Id category, const Utils::FilePath &file, int line)
{
addTask(Task(type, description, file, line, category));
}
diff --git a/src/plugins/projectexplorer/taskhub.h b/src/plugins/projectexplorer/taskhub.h
index 80bb6a5219..fc2c489c1a 100644
--- a/src/plugins/projectexplorer/taskhub.h
+++ b/src/plugins/projectexplorer/taskhub.h
@@ -43,7 +43,7 @@ public:
// Convenience overload
static void addTask(Task::TaskType type, const QString &description,
Core::Id category,
- const Utils::FileName &file = Utils::FileName(),
+ const Utils::FilePath &file = Utils::FilePath(),
int line = -1);
public slots:
diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp
index dcdf1554c8..8fcc48e737 100644
--- a/src/plugins/projectexplorer/taskmodel.cpp
+++ b/src/plugins/projectexplorer/taskmodel.cpp
@@ -25,11 +25,13 @@
#include "taskmodel.h"
+#include "fileinsessionfinder.h"
#include "task.h"
#include "taskhub.h"
#include <utils/qtcassert.h>
+#include <QFileInfo>
#include <QFontMetrics>
#include <algorithm>
@@ -84,12 +86,12 @@ void TaskModel::addCategory(Core::Id categoryId, const QString &categoryName)
m_categories.insert(categoryId, data);
}
-QList<Task> TaskModel::tasks(Core::Id categoryId) const
+Tasks TaskModel::tasks(Core::Id categoryId) const
{
if (!categoryId.isValid())
return m_tasks;
- QList<Task> taskList;
+ Tasks taskList;
foreach (const Task &t, m_tasks) {
if (t.category == categoryId)
taskList.append(t);
@@ -117,17 +119,18 @@ void TaskModel::addTask(const Task &task)
endInsertRows();
}
-void TaskModel::removeTask(const Task &task)
+void TaskModel::removeTask(unsigned int id)
{
- int index = m_tasks.indexOf(task);
- if (index >= 0) {
+ for (int index = 0; index < m_tasks.length(); ++index) {
+ if (m_tasks.at(index).taskId != id)
+ continue;
const Task &t = m_tasks.at(index);
-
beginRemoveRows(QModelIndex(), index, index);
- m_categories[task.category].removeTask(t);
+ m_categories[t.category].removeTask(t);
m_categories[Core::Id()].removeTask(t);
m_tasks.removeAt(index);
endRemoveRows();
+ break;
}
}
@@ -144,7 +147,7 @@ void TaskModel::updateTaskFileName(unsigned int id, const QString &fileName)
int i = rowForId(id);
QTC_ASSERT(i != -1, return);
if (m_tasks.at(i).taskId == id) {
- m_tasks[i].file = Utils::FileName::fromString(fileName);
+ m_tasks[i].file = Utils::FilePath::fromString(fileName);
emit dataChanged(index(i, 0), index(i, 0));
}
}
@@ -294,7 +297,7 @@ int TaskModel::sizeOfFile(const QFont &font)
if (pos != -1)
filename = filename.mid(pos +1);
- m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.width(filename));
+ m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.horizontalAdvance(filename));
}
m_lastMaxSizeIndex = count - 1;
return m_maxSizeOfFileName;
@@ -305,7 +308,7 @@ int TaskModel::sizeOfLineNumber(const QFont &font)
if (m_sizeOfLineNumber == 0 || font != m_lineMeasurementFont) {
QFontMetrics fm(font);
m_lineMeasurementFont = font;
- m_sizeOfLineNumber = fm.width(QLatin1String("88888"));
+ m_sizeOfLineNumber = fm.horizontalAdvance(QLatin1String("88888"));
}
return m_sizeOfLineNumber;
}
@@ -323,174 +326,44 @@ void TaskModel::setFileNotFound(const QModelIndex &idx, bool b)
// TaskFilterModel
/////
-TaskFilterModel::TaskFilterModel(TaskModel *sourceModel, QObject *parent) : QAbstractItemModel(parent),
- m_sourceModel(sourceModel)
+TaskFilterModel::TaskFilterModel(TaskModel *sourceModel, QObject *parent)
+ : QSortFilterProxyModel(parent)
{
- Q_ASSERT(m_sourceModel);
- updateMapping();
-
- connect(m_sourceModel, &QAbstractItemModel::rowsInserted,
- this, &TaskFilterModel::handleNewRows);
-
- connect(m_sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved,
- this, &TaskFilterModel::handleRowsAboutToBeRemoved);
- connect(m_sourceModel, &QAbstractItemModel::rowsRemoved,
- this, [this](const QModelIndex &parent, int, int) {
- QTC_ASSERT(!parent.isValid(), return);
- if (m_beginRemoveRowsSent) {
- m_beginRemoveRowsSent = false;
- endRemoveRows();
- }
- });
-
- connect(m_sourceModel, &QAbstractItemModel::modelReset,
- this, &TaskFilterModel::invalidateFilter);
-
- connect(m_sourceModel, &QAbstractItemModel::dataChanged,
- this, &TaskFilterModel::handleDataChanged);
-
+ QTC_ASSERT(sourceModel, return);
+ setSourceModel(sourceModel);
m_includeUnknowns = m_includeWarnings = m_includeErrors = true;
}
-QModelIndex TaskFilterModel::index(int row, int column, const QModelIndex &parent) const
-{
- if (parent.isValid())
- return QModelIndex();
- return createIndex(row, column);
-}
-
-QModelIndex TaskFilterModel::parent(const QModelIndex &child) const
-{
- Q_UNUSED(child)
- return QModelIndex();
-}
-
-int TaskFilterModel::rowCount(const QModelIndex &parent) const
-{
- if (parent.isValid())
- return 0;
-
- return m_mapping.count();
-}
-
-int TaskFilterModel::columnCount(const QModelIndex &parent) const
-{
- if (parent.isValid())
- return 0;
- return m_sourceModel->columnCount(parent);
-}
-
-QVariant TaskFilterModel::data(const QModelIndex &index, int role) const
-{
- return m_sourceModel->data(mapToSource(index), role);
-}
-
-static QPair<int, int> findFilteredRange(int first, int last, const QList<int> &list)
+void TaskFilterModel::setFilterIncludesWarnings(bool b)
{
- auto filteredFirst = std::lower_bound(list.constBegin(), list.constEnd(), first);
- auto filteredLast = std::upper_bound(filteredFirst, list.constEnd(), last);
- return qMakePair(filteredFirst - list.constBegin(), filteredLast - list.constBegin() - 1);
+ m_includeWarnings = b;
+ m_includeUnknowns = b; // "Unknowns" are often associated with warnings
+ invalidateFilter();
}
-void TaskFilterModel::handleNewRows(const QModelIndex &index, int first, int last)
+void TaskFilterModel::updateFilterProperties(const QString &filterText,
+ Qt::CaseSensitivity caseSensitivity, bool isRegexp)
{
- QTC_ASSERT(!index.isValid(), return);
-
- const int newItemCount = last - first + 1;
-
- QList<int> newMapping;
- for (int i = first; i <= last; ++i) {
- const Task &task = m_sourceModel->task(m_sourceModel->index(i, 0));
- if (filterAcceptsTask(task))
- newMapping.append(i);
- }
-
- const int newMappingCount = newMapping.count();
- if (!newMappingCount)
+ if (filterText == m_filterText && m_filterCaseSensitivity == caseSensitivity
+ && m_filterStringIsRegexp == isRegexp) {
return;
-
- int filteredFirst = -1;
- if (last == m_sourceModel->rowCount() - 1)
- filteredFirst = m_mapping.count();
- else
- filteredFirst = std::lower_bound(m_mapping.constBegin(), m_mapping.constEnd(), first) - m_mapping.constBegin();
-
- const int filteredLast = filteredFirst + newMappingCount - 1;
- beginInsertRows(QModelIndex(), filteredFirst, filteredLast);
- if (filteredFirst == m_mapping.count()) {
- m_mapping.append(newMapping);
- } else {
- const QList<int> rest = m_mapping.mid(filteredFirst);
-
- m_mapping.reserve(m_mapping.count() + newMappingCount);
- m_mapping.erase(m_mapping.begin() + filteredFirst, m_mapping.end());
- m_mapping.append(newMapping);
- for (int pos : rest)
- m_mapping.append(pos + newItemCount);
}
- endInsertRows();
-}
-
-void TaskFilterModel::handleRowsAboutToBeRemoved(const QModelIndex &index, int first, int last)
-{
- m_beginRemoveRowsSent = false;
- QTC_ASSERT(!index.isValid(), return);
-
- const QPair<int, int> range = findFilteredRange(first, last, m_mapping);
- if (range.first <= range.second) { // remove corresponding rows in filtermodel
- beginRemoveRows(QModelIndex(), range.first, range.second);
- m_beginRemoveRowsSent = true;
- m_mapping.erase(m_mapping.begin() + range.first, m_mapping.begin() + range.second + 1);
+ m_filterText = filterText;
+ m_filterCaseSensitivity = caseSensitivity;
+ m_filterStringIsRegexp = isRegexp;
+ if (m_filterStringIsRegexp) {
+ m_filterRegexp.setPattern(m_filterText);
+ m_filterRegexp.setPatternOptions(m_filterCaseSensitivity == Qt::CaseInsensitive
+ ? QRegularExpression::CaseInsensitiveOption
+ : QRegularExpression::NoPatternOption);
}
- // adapt existing mapping to removed source indices
- const int sourceRemovedCount = (last - first) + 1;
- for (int i = range.first; i < m_mapping.count(); ++i)
- m_mapping[i] = m_mapping.at(i) - sourceRemovedCount;
-}
-
-void TaskFilterModel::handleDataChanged(const QModelIndex &top, const QModelIndex &bottom)
-{
- const QPair<int, int> range = findFilteredRange(top.row(), bottom.row(), m_mapping);
- if (range.first > range.second)
- return;
-
- emit dataChanged(index(range.first, top.column()), index(range.second, bottom.column()));
-}
-
-QModelIndex TaskFilterModel::mapFromSource(const QModelIndex &idx) const
-{
- if (!idx.isValid())
- return QModelIndex();
- auto it = std::lower_bound(m_mapping.constBegin(), m_mapping.constEnd(), idx.row());
- QTC_ASSERT(it != m_mapping.constEnd() && idx.row() == *it, return QModelIndex());
- return index(it - m_mapping.constBegin(), 0);
-}
-
-QModelIndex TaskFilterModel::mapToSource(const QModelIndex &index) const
-{
- if (!index.isValid())
- return QModelIndex();
- int row = index.row();
- QTC_ASSERT(row >= 0 && row < m_mapping.count(), return QModelIndex());
- return m_sourceModel->index(m_mapping.at(row), index.column(), index.parent());
-}
-
-void TaskFilterModel::invalidateFilter()
-{
- beginResetModel();
- updateMapping();
- endResetModel();
+ invalidateFilter();
}
-void TaskFilterModel::updateMapping() const
+bool TaskFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
- m_mapping.clear();
- for (int i = 0; i < m_sourceModel->rowCount(); ++i) {
- QModelIndex index = m_sourceModel->index(i, 0);
- const Task &task = m_sourceModel->task(index);
- if (filterAcceptsTask(task))
- m_mapping.append(i);
- }
+ Q_UNUSED(source_parent);
+ return filterAcceptsTask(taskModel()->tasks().at(source_row));
}
bool TaskFilterModel::filterAcceptsTask(const Task &task) const
@@ -508,9 +381,18 @@ bool TaskFilterModel::filterAcceptsTask(const Task &task) const
break;
}
- if (m_categoryIds.contains(task.category))
+ if (accept && m_categoryIds.contains(task.category))
accept = false;
+ if (accept && !m_filterText.isEmpty()) {
+ const auto accepts = [this](const QString &s) {
+ return m_filterStringIsRegexp ? m_filterRegexp.isValid() && s.contains(m_filterRegexp)
+ : s.contains(m_filterText, m_filterCaseSensitivity);
+ };
+ if (!accepts(task.file.toString()) && !accepts(task.description))
+ accept = false;
+ }
+
return accept;
}
diff --git a/src/plugins/projectexplorer/taskmodel.h b/src/plugins/projectexplorer/taskmodel.h
index 4b2757c289..b1044a3234 100644
--- a/src/plugins/projectexplorer/taskmodel.h
+++ b/src/plugins/projectexplorer/taskmodel.h
@@ -25,9 +25,10 @@
#pragma once
-#include <QAbstractItemModel>
+#include <QSortFilterProxyModel>
#include <QIcon>
+#include <QRegularExpression>
#include "task.h"
@@ -53,9 +54,9 @@ public:
QString categoryDisplayName(Core::Id categoryId) const;
void addCategory(Core::Id categoryId, const QString &categoryName);
- QList<Task> tasks(Core::Id categoryId = Core::Id()) const;
- void addTask(const Task &task);
- void removeTask(const Task &task);
+ Tasks tasks(Core::Id categoryId = Core::Id()) const;
+ void addTask(const Task &t);
+ void removeTask(unsigned int id);
void clearTasks(Core::Id categoryId = Core::Id());
void updateTaskFileName(unsigned int id, const QString &fileName);
void updateTaskLineNumber(unsigned int id, int line);
@@ -110,7 +111,7 @@ private:
};
QHash<Core::Id,CategoryData> m_categories; // category id to data
- QList<Task> m_tasks; // all tasks (in order of id)
+ Tasks m_tasks; // all tasks (in order of id)
QHash<QString,bool> m_fileNotFound;
QFont m_fileMeasurementFont;
@@ -120,26 +121,17 @@ private:
int m_sizeOfLineNumber = 0;
};
-class TaskFilterModel : public QAbstractItemModel
+class TaskFilterModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
TaskFilterModel(TaskModel *sourceModel, QObject *parent = nullptr);
- TaskModel *taskModel() { return m_sourceModel; }
-
- 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;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-
- bool filterIncludesUnknowns() const { return m_includeUnknowns; }
- void setFilterIncludesUnknowns(bool b) { m_includeUnknowns = b; invalidateFilter(); }
+ TaskModel *taskModel() const { return static_cast<TaskModel *>(sourceModel()); }
bool filterIncludesWarnings() const { return m_includeWarnings; }
- void setFilterIncludesWarnings(bool b) { m_includeWarnings = b; invalidateFilter(); }
+ void setFilterIncludesWarnings(bool b);
bool filterIncludesErrors() const { return m_includeErrors; }
void setFilterIncludesErrors(bool b) { m_includeErrors = b; invalidateFilter(); }
@@ -147,33 +139,27 @@ public:
QList<Core::Id> filteredCategories() const { return m_categoryIds; }
void setFilteredCategories(const QList<Core::Id> &categoryIds) { m_categoryIds = categoryIds; invalidateFilter(); }
- Task task(const QModelIndex &index) const
- { return m_sourceModel->task(mapToSource(index)); }
+ Task task(const QModelIndex &index) const { return taskModel()->task(mapToSource(index)); }
bool hasFile(const QModelIndex &index) const
- { return m_sourceModel->hasFile(mapToSource(index)); }
+ { return taskModel()->hasFile(mapToSource(index)); }
- QModelIndex mapFromSource(const QModelIndex &idx) const;
+ void updateFilterProperties(const QString &filterText, Qt::CaseSensitivity caseSensitivity,
+ bool isRegex);
private:
- void handleNewRows(const QModelIndex &index, int first, int last);
- void handleRowsAboutToBeRemoved(const QModelIndex &index, int first, int last);
- void handleDataChanged(const QModelIndex &top, const QModelIndex &bottom);
-
- QModelIndex mapToSource(const QModelIndex &index) const;
- void invalidateFilter();
- void updateMapping() const;
+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
bool filterAcceptsTask(const Task &task) const;
bool m_beginRemoveRowsSent = false;
bool m_includeUnknowns;
bool m_includeWarnings;
bool m_includeErrors;
+ bool m_filterStringIsRegexp = false;
+ Qt::CaseSensitivity m_filterCaseSensitivity = Qt::CaseInsensitive;
QList<Core::Id> m_categoryIds;
-
- mutable QList<int> m_mapping;
-
- TaskModel *m_sourceModel;
+ QString m_filterText;
+ QRegularExpression m_filterRegexp;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index 7d8010aa27..7a98d0fd33 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -38,6 +38,7 @@
#include <coreplugin/icontext.h>
#include <utils/algorithm.h>
+#include <utils/fileinprojectfinder.h>
#include <utils/qtcassert.h>
#include <utils/itemviews.h>
#include <utils/utilsicons.h>
@@ -236,7 +237,6 @@ static QToolButton *createFilterButton(const QIcon &icon, const QString &toolTip
button->setToolTip(toolTip);
button->setCheckable(true);
button->setChecked(true);
- button->setAutoRaise(true);
button->setEnabled(true);
QObject::connect(button, &QToolButton::toggled, receiver, lambda);
return button;
@@ -282,7 +282,6 @@ TaskWindow::TaskWindow() : d(std::make_unique<TaskWindowPrivate>())
d->m_categoriesButton->setIcon(Utils::Icons::FILTER.icon());
d->m_categoriesButton->setToolTip(tr("Filter by categories"));
d->m_categoriesButton->setProperty("noArrow", true);
- d->m_categoriesButton->setAutoRaise(true);
d->m_categoriesButton->setPopupMode(QToolButton::InstantPopup);
d->m_categoriesMenu = new QMenu(d->m_categoriesButton);
@@ -290,6 +289,9 @@ TaskWindow::TaskWindow() : d(std::make_unique<TaskWindowPrivate>())
d->m_categoriesButton->setMenu(d->m_categoriesMenu);
+ setupFilterUi("IssuesPane.Filter");
+ setFilteringEnabled(true);
+
TaskHub *hub = TaskHub::instance();
connect(hub, &TaskHub::categoryAdded, this, &TaskWindow::addCategory);
connect(hub, &TaskHub::taskAdded, this, &TaskWindow::addTask);
@@ -356,7 +358,7 @@ void TaskWindow::delayedInitialization()
QList<QWidget*> TaskWindow::toolBarWidgets() const
{
- return {d->m_filterWarningsButton, d->m_categoriesButton};
+ return {d->m_filterWarningsButton, d->m_categoriesButton, filterWidget()};
}
QWidget *TaskWindow::outputWidget(QWidget *)
@@ -416,7 +418,6 @@ void TaskWindow::loadSettings()
if (value.isValid()) {
bool includeWarnings = value.toBool();
d->m_filter->setFilterIncludesWarnings(includeWarnings);
- d->m_filter->setFilterIncludesUnknowns(includeWarnings);
d->m_filterWarningsButton->setDown(d->m_filter->filterIncludesWarnings());
}
}
@@ -454,7 +455,7 @@ void TaskWindow::addTask(const Task &task)
void TaskWindow::removeTask(const Task &task)
{
- d->m_model->removeTask(task);
+ d->m_model->removeTask(task.taskId);
emit tasksChanged();
navigateStateChanged();
@@ -498,6 +499,15 @@ void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
if (task.isNull())
return;
+ if (!task.file.isEmpty() && !task.file.toFileInfo().isAbsolute()
+ && !task.fileCandidates.empty()) {
+ const Utils::FilePath userChoice = Utils::chooseFileFromList(task.fileCandidates);
+ if (!userChoice.isEmpty()) {
+ task.file = userChoice;
+ updatedTaskFileName(task.taskId, task.file.toString());
+ }
+ }
+
if (d->m_defaultHandler->canHandle(task)) {
d->m_defaultHandler->handle(task);
} else {
@@ -526,7 +536,6 @@ void TaskWindow::actionTriggered()
void TaskWindow::setShowWarnings(bool show)
{
d->m_filter->setFilterIncludesWarnings(show);
- d->m_filter->setFilterIncludesUnknowns(show); // "Unknowns" are often associated with warnings
}
void TaskWindow::updateCategoriesMenu()
@@ -658,6 +667,11 @@ void TaskWindow::goToPrev()
triggerDefaultHandler(currentIndex);
}
+void TaskWindow::updateFilter()
+{
+ d->m_filter->updateFilterProperties(filterText(), filterCaseSensitivity(), filterUsesRegexp());
+}
+
bool TaskWindow::canNavigate() const
{
return true;
@@ -786,7 +800,7 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
QString bottom = index.data(TaskModel::Description).toString().split(QLatin1Char('\n')).first();
painter->setClipRect(positions.textArea());
painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), bottom);
- if (fm.width(bottom) > positions.textAreaWidth()) {
+ if (fm.horizontalAdvance(bottom) > positions.textAreaWidth()) {
// draw a gradient to mask the text
int gradientStart = positions.textAreaRight() - ELLIPSIS_GRADIENT_WIDTH + 1;
QLinearGradient lg(gradientStart, 0, gradientStart + ELLIPSIS_GRADIENT_WIDTH, 0);
@@ -840,7 +854,7 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const int pos = file.lastIndexOf(QLatin1Char('/'));
if (pos != -1)
file = file.mid(pos +1);
- const int realFileWidth = fm.width(file);
+ const int realFileWidth = fm.horizontalAdvance(file);
painter->setClipRect(positions.fileArea());
painter->drawText(qMin(positions.fileAreaLeft(), positions.fileAreaRight() - realFileWidth),
positions.top() + fm.ascent(), file);
@@ -877,7 +891,7 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
}
painter->setClipRect(positions.lineArea());
- const int realLineWidth = fm.width(lineText);
+ const int realLineWidth = fm.horizontalAdvance(lineText);
painter->drawText(positions.lineAreaRight() - realLineWidth, positions.top() + fm.ascent(), lineText);
painter->setClipRect(opt.rect);
diff --git a/src/plugins/projectexplorer/taskwindow.h b/src/plugins/projectexplorer/taskwindow.h
index 290927b47b..efefb72658 100644
--- a/src/plugins/projectexplorer/taskwindow.h
+++ b/src/plugins/projectexplorer/taskwindow.h
@@ -82,6 +82,8 @@ signals:
void tasksCleared();
private:
+ void updateFilter() override;
+
void addCategory(Core::Id categoryId, const QString &displayName, bool visible);
void addTask(const ProjectExplorer::Task &task);
void removeTask(const ProjectExplorer::Task &task);
diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp
index 212427417a..66c5ac83db 100644
--- a/src/plugins/projectexplorer/toolchain.cpp
+++ b/src/plugins/projectexplorer/toolchain.cpp
@@ -46,6 +46,8 @@ static const char LANGUAGE_KEY_V2[] = "ProjectExplorer.ToolChain.LanguageV2"; //
namespace ProjectExplorer {
namespace Internal {
+static QList<ToolChainFactory *> g_toolChainFactories;
+
// --------------------------------------------------------------------------
// ToolChainPrivate
// --------------------------------------------------------------------------
@@ -55,10 +57,11 @@ class ToolChainPrivate
public:
using Detection = ToolChain::Detection;
- explicit ToolChainPrivate(Core::Id typeId, Detection d) :
+ explicit ToolChainPrivate(Core::Id typeId) :
m_id(QUuid::createUuid().toByteArray()),
m_typeId(typeId),
- m_detection(d)
+ m_predefinedMacrosCache(new ToolChain::MacrosCache::element_type()),
+ m_headerPathsCache(new ToolChain::HeaderPathsCache::element_type())
{
QTC_ASSERT(m_typeId.isValid(), return);
QTC_ASSERT(!m_typeId.toString().contains(QLatin1Char(':')), return);
@@ -69,7 +72,10 @@ public:
mutable QString m_displayName;
Core::Id m_typeId;
Core::Id m_language;
- Detection m_detection;
+ Detection m_detection = ToolChain::UninitializedDetection;
+
+ ToolChain::MacrosCache m_predefinedMacrosCache;
+ ToolChain::HeaderPathsCache m_headerPathsCache;
};
@@ -116,20 +122,11 @@ QString languageId(Language l)
// --------------------------------------------------------------------------
-ToolChain::ToolChain(Core::Id typeId, Detection d) :
- d(std::make_unique<Internal::ToolChainPrivate>(typeId, d))
+ToolChain::ToolChain(Core::Id typeId) :
+ d(std::make_unique<Internal::ToolChainPrivate>(typeId))
{
}
-ToolChain::ToolChain(const ToolChain &other) : ToolChain(other.d->m_typeId, ManualDetection)
-{
- d->m_language = other.d->m_language;
-
- // leave the autodetection bit at false.
- d->m_displayName = QCoreApplication::translate("ProjectExplorer::ToolChain", "Clone of %1")
- .arg(other.displayName());
-}
-
void ToolChain::setLanguage(Core::Id language)
{
QTC_ASSERT(!d->m_language.isValid() || isAutoDetected(), return);
@@ -167,12 +164,12 @@ QByteArray ToolChain::id() const
return d->m_id;
}
-Utils::FileNameList ToolChain::suggestedMkspecList() const
+QStringList ToolChain::suggestedMkspecList() const
{
- return Utils::FileNameList();
+ return {};
}
-Utils::FileName ToolChain::suggestedDebugger() const
+Utils::FilePath ToolChain::suggestedDebugger() const
{
return ToolChainManager::defaultDebugger(targetAbi());
}
@@ -182,7 +179,7 @@ Core::Id ToolChain::typeId() const
return d->m_typeId;
}
-QList<Abi> ToolChain::supportedAbis() const
+Abis ToolChain::supportedAbis() const
{
return {targetAbi()};
}
@@ -192,11 +189,6 @@ Core::Id ToolChain::language() const
return d->m_language;
}
-bool ToolChain::canClone() const
-{
- return true;
-}
-
bool ToolChain::operator == (const ToolChain &tc) const
{
if (this == &tc)
@@ -208,6 +200,22 @@ bool ToolChain::operator == (const ToolChain &tc) const
&& language() == tc.language();
}
+ToolChain *ToolChain::clone() const
+{
+ for (ToolChainFactory *f : Internal::g_toolChainFactories) {
+ if (f->supportedToolChainType() == d->m_typeId) {
+ ToolChain *tc = f->create();
+ QTC_ASSERT(tc, return nullptr);
+ tc->fromMap(toMap());
+ // New ID for the clone. It's different.
+ tc->d->m_id = QUuid::createUuid().toByteArray();
+ return tc;
+ }
+ }
+ QTC_CHECK(false);
+ return nullptr;
+}
+
/*!
Used by the tool chain manager to save user-generated tool chains.
@@ -236,6 +244,9 @@ QVariantMap ToolChain::toMap() const
void ToolChain::toolChainUpdated()
{
+ d->m_predefinedMacrosCache->invalidate();
+ d->m_headerPathsCache->invalidate();
+
ToolChainManager::notifyAboutUpdate(this);
}
@@ -243,8 +254,12 @@ void ToolChain::setDetection(ToolChain::Detection de)
{
if (d->m_detection == de)
return;
- d->m_detection = de;
- toolChainUpdated();
+ if (d->m_detection == ToolChain::UninitializedDetection) {
+ d->m_detection = de;
+ } else {
+ d->m_detection = de;
+ toolChainUpdated();
+ }
}
/*!
@@ -265,7 +280,7 @@ bool ToolChain::fromMap(const QVariantMap &data)
d->m_id = id.mid(pos + 1).toUtf8();
const bool autoDetect = data.value(QLatin1String(AUTODETECT_KEY), false).toBool();
- d->m_detection = autoDetect ? AutoDetectionFromSettings : ManualDetection;
+ d->m_detection = autoDetect ? AutoDetection : ManualDetection;
if (data.contains(LANGUAGE_KEY_V2)) {
// remove hack to trim language id in 4.4: This is to fix up broken language
@@ -286,6 +301,16 @@ bool ToolChain::fromMap(const QVariantMap &data)
return true;
}
+const ToolChain::HeaderPathsCache &ToolChain::headerPathsCache() const
+{
+ return d->m_headerPathsCache;
+}
+
+const ToolChain::MacrosCache &ToolChain::predefinedMacrosCache() const
+{
+ return d->m_predefinedMacrosCache;
+}
+
static long toLanguageVersionAsLong(QByteArray dateAsByteArray)
{
dateAsByteArray.chop(1); // Strip 'L'.
@@ -357,9 +382,9 @@ Utils::LanguageVersion ToolChain::languageVersion(const Core::Id &language, cons
Used by the tool chain kit information to validate the kit.
*/
-QList<Task> ToolChain::validateKit(const Kit *) const
+Tasks ToolChain::validateKit(const Kit *) const
{
- return QList<Task>();
+ return {};
}
QString ToolChain::sysRoot() const
@@ -390,21 +415,19 @@ QString ToolChain::sysRoot() const
Used by the tool chain manager to restore user-generated tool chains.
*/
-static QList<ToolChainFactory *> g_toolChainFactories;
-
ToolChainFactory::ToolChainFactory()
{
- g_toolChainFactories.append(this);
+ Internal::g_toolChainFactories.append(this);
}
ToolChainFactory::~ToolChainFactory()
{
- g_toolChainFactories.removeOne(this);
+ Internal::g_toolChainFactories.removeOne(this);
}
const QList<ToolChainFactory *> ToolChainFactory::allToolChainFactories()
{
- return g_toolChainFactories;
+ return Internal::g_toolChainFactories;
}
QList<ToolChain *> ToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
@@ -413,31 +436,35 @@ QList<ToolChain *> ToolChainFactory::autoDetect(const QList<ToolChain *> &alread
return QList<ToolChain *>();
}
-QList<ToolChain *> ToolChainFactory::autoDetect(const Utils::FileName &compilerPath, const Core::Id &language)
+QList<ToolChain *> ToolChainFactory::autoDetect(const Utils::FilePath &compilerPath, const Core::Id &language)
{
Q_UNUSED(compilerPath);
Q_UNUSED(language);
return QList<ToolChain *>();
}
-bool ToolChainFactory::canCreate()
+bool ToolChainFactory::canCreate() const
{
- return false;
+ return m_userCreatable;
}
-ToolChain *ToolChainFactory::create(Core::Id l)
+ToolChain *ToolChainFactory::create()
{
- Q_UNUSED(l);
- return nullptr;
+ return m_toolchainConstructor ? m_toolchainConstructor() : nullptr;
}
-bool ToolChainFactory::canRestore(const QVariantMap &)
+ToolChain *ToolChainFactory::restore(const QVariantMap &data)
{
- return false;
-}
+ if (!m_toolchainConstructor)
+ return nullptr;
-ToolChain *ToolChainFactory::restore(const QVariantMap &)
-{
+ ToolChain *tc = m_toolchainConstructor();
+ QTC_ASSERT(tc, return nullptr);
+
+ if (tc->fromMap(data))
+ return tc;
+
+ delete tc;
return nullptr;
}
@@ -464,4 +491,40 @@ void ToolChainFactory::autoDetectionToMap(QVariantMap &data, bool detected)
data.insert(QLatin1String(AUTODETECT_KEY), detected);
}
+QSet<Core::Id> ToolChainFactory::supportedLanguages() const
+{
+ return m_supportsAllLanguages ? ToolChainManager::allLanguages() : m_supportedLanguages;
+}
+
+Core::Id ToolChainFactory::supportedToolChainType() const
+{
+ return m_supportedToolChainType;
+}
+
+void ToolChainFactory::setSupportedToolChainType(const Core::Id &supportedToolChain)
+{
+ m_supportedToolChainType = supportedToolChain;
+}
+
+void ToolChainFactory::setSupportedLanguages(const QSet<Core::Id> &supportedLanguages)
+{
+ m_supportedLanguages = supportedLanguages;
+}
+
+void ToolChainFactory::setSupportsAllLanguages(bool supportsAllLanguages)
+{
+ m_supportsAllLanguages = supportsAllLanguages;
+}
+
+void ToolChainFactory::setToolchainConstructor
+ (const std::function<ToolChain *()> &toolchainContructor)
+{
+ m_toolchainConstructor = toolchainContructor;
+}
+
+void ToolChainFactory::setUserCreatable(bool userCreatable)
+{
+ m_userCreatable = userCreatable;
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index 8925b449a4..1cbe478691 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -28,13 +28,15 @@
#include "projectexplorer_export.h"
#include "projectexplorer_global.h"
+#include "abi.h"
#include "headerpath.h"
#include "projectmacro.h"
+#include "task.h"
+#include "toolchaincache.h"
#include <coreplugin/id.h>
#include <utils/cpplanguage_details.h>
-#include <utils/fileutils.h>
#include <QObject>
#include <QSet>
@@ -66,7 +68,6 @@ class Abi;
class IOutputParser;
class ToolChainConfigWidget;
class ToolChainFactory;
-class Task;
class Kit;
namespace Internal { class ToolChainSettingsAccessor; }
@@ -81,7 +82,8 @@ public:
enum Detection {
ManualDetection,
AutoDetection,
- AutoDetectionFromSettings
+ AutoDetectionFromSdk,
+ UninitializedDetection,
};
using Predicate = std::function<bool(const ToolChain *)>;
@@ -96,13 +98,13 @@ public:
QByteArray id() const;
- virtual Utils::FileNameList suggestedMkspecList() const;
- virtual Utils::FileName suggestedDebugger() const;
+ virtual QStringList suggestedMkspecList() const;
+ virtual Utils::FilePath suggestedDebugger() const;
Core::Id typeId() const;
virtual QString typeDisplayName() const = 0;
virtual Abi targetAbi() const = 0;
- virtual QList<Abi> supportedAbis() const;
+ virtual ProjectExplorer::Abis supportedAbis() const;
virtual QString originalTargetTriple() const { return QString(); }
virtual QStringList extraCodeModelFlags() const { return QStringList(); }
@@ -119,43 +121,51 @@ public:
Utils::LanguageVersion languageVersion;
};
+ using MacrosCache = std::shared_ptr<Cache<ToolChain::MacroInspectionReport, 64>>;
+ using HeaderPathsCache = std::shared_ptr<Cache<HeaderPaths>>;
+
// A MacroInspectionRunner is created in the ui thread and runs in another thread.
using MacroInspectionRunner = std::function<MacroInspectionReport(const QStringList &cxxflags)>;
virtual MacroInspectionRunner createMacroInspectionRunner() const = 0;
virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0;
// A BuiltInHeaderPathsRunner is created in the ui thread and runs in another thread.
- using BuiltInHeaderPathsRunner = std::function<HeaderPaths(const QStringList &cxxflags,
- const QString &sysRoot)>;
+ using BuiltInHeaderPathsRunner = std::function<HeaderPaths(
+ const QStringList &cxxflags, const QString &sysRoot, const QString &originalTargetTriple)>;
virtual BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const = 0;
virtual HeaderPaths builtInHeaderPaths(const QStringList &cxxflags,
- const Utils::FileName &sysRoot) const = 0;
+ const Utils::FilePath &sysRoot) const = 0;
virtual void addToEnvironment(Utils::Environment &env) const = 0;
- virtual QString makeCommand(const Utils::Environment &env) const = 0;
+ virtual Utils::FilePath makeCommand(const Utils::Environment &env) const = 0;
Core::Id language() const;
- virtual Utils::FileName compilerCommand() const = 0;
+ virtual Utils::FilePath compilerCommand() const = 0;
virtual IOutputParser *outputParser() const = 0;
virtual bool operator ==(const ToolChain &) const;
virtual std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() = 0;
- virtual bool canClone() const;
- virtual ToolChain *clone() const = 0;
+ ToolChain *clone() const;
// Used by the toolchainmanager to save user-generated tool chains.
// Make sure to call this function when deriving!
virtual QVariantMap toMap() const;
- virtual QList<Task> validateKit(const Kit *k) const;
+ virtual Tasks validateKit(const Kit *k) const;
+
+ virtual bool isJobCountSupported() const { return true; }
void setLanguage(Core::Id language);
+ void setDetection(Detection d);
+
static Utils::LanguageVersion cxxLanguageVersion(const QByteArray &cplusplusMacroValue);
static Utils::LanguageVersion languageVersion(const Core::Id &language, const Macros &macros);
protected:
- explicit ToolChain(Core::Id typeId, Detection d);
- explicit ToolChain(const ToolChain &);
+ explicit ToolChain(Core::Id typeId);
+
+ const MacrosCache &predefinedMacrosCache() const;
+ const HeaderPathsCache &headerPathsCache() const;
virtual void toolChainUpdated();
@@ -163,7 +173,8 @@ protected:
virtual bool fromMap(const QVariantMap &data);
private:
- void setDetection(Detection d);
+ ToolChain(const ToolChain &) = delete;
+ ToolChain &operator=(const ToolChain &) = delete;
const std::unique_ptr<Internal::ToolChainPrivate> d;
@@ -182,27 +193,51 @@ public:
static const QList<ToolChainFactory *> allToolChainFactories();
QString displayName() const { return m_displayName; }
+ Core::Id supportedToolChainType() const;
virtual QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown);
- virtual QList<ToolChain *> autoDetect(const Utils::FileName &compilerPath, const Core::Id &language);
+ virtual QList<ToolChain *> autoDetect(const Utils::FilePath &compilerPath, const Core::Id &language);
- virtual bool canCreate();
- virtual ToolChain *create(Core::Id l);
+ virtual bool canCreate() const;
+ virtual ToolChain *create();
- virtual bool canRestore(const QVariantMap &data);
- virtual ToolChain *restore(const QVariantMap &data);
+ ToolChain *restore(const QVariantMap &data);
static QByteArray idFromMap(const QVariantMap &data);
static Core::Id typeIdFromMap(const QVariantMap &data);
static void autoDetectionToMap(QVariantMap &data, bool detected);
- virtual QSet<Core::Id> supportedLanguages() const = 0;
+ QSet<Core::Id> supportedLanguages() const;
+
+ void setUserCreatable(bool userCreatable);
protected:
void setDisplayName(const QString &name) { m_displayName = name; }
+ void setSupportedToolChainType(const Core::Id &supportedToolChainType);
+ void setSupportedLanguages(const QSet<Core::Id> &supportedLanguages);
+ void setSupportsAllLanguages(bool supportsAllLanguages);
+ void setToolchainConstructor(const std::function<ToolChain *()> &constructor);
+
+ class Candidate {
+ public:
+ Utils::FilePath compilerPath;
+ QString compilerVersion;
+
+ bool operator==(const ToolChainFactory::Candidate &other) const {
+ return compilerPath == other.compilerPath
+ && compilerVersion == other.compilerVersion;
+ }
+ };
+
+ using Candidates = QVector<Candidate>;
private:
QString m_displayName;
+ Core::Id m_supportedToolChainType;
+ QSet<Core::Id> m_supportedLanguages;
+ bool m_supportsAllLanguages = false;
+ bool m_userCreatable = false;
+ std::function<ToolChain *()> m_toolchainConstructor;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp
index caa15e6d2f..ffea568dbe 100644
--- a/src/plugins/projectexplorer/toolchainmanager.cpp
+++ b/src/plugins/projectexplorer/toolchainmanager.cpp
@@ -63,11 +63,12 @@ class ToolChainManagerPrivate
public:
~ToolChainManagerPrivate();
- QMap<QString, FileName> m_abiToDebugger;
+ QMap<QString, FilePath> m_abiToDebugger;
std::unique_ptr<ToolChainSettingsAccessor> m_accessor;
QList<ToolChain *> m_toolChains; // prioritized List
QVector<LanguageDisplayPair> m_languages;
+ ToolchainDetectionSettings m_detectionSettings;
};
ToolChainManagerPrivate::~ToolChainManagerPrivate()
@@ -83,6 +84,8 @@ static ToolChainManagerPrivate *d = nullptr;
using namespace Internal;
+const char DETECT_X64_AS_X32_KEY[] = "ProjectExplorer/Toolchains/DetectX64AsX32";
+
// --------------------------------------------------------------------------
// ToolChainManager
// --------------------------------------------------------------------------
@@ -100,6 +103,9 @@ ToolChainManager::ToolChainManager(QObject *parent) :
connect(this, &ToolChainManager::toolChainAdded, this, &ToolChainManager::toolChainsChanged);
connect(this, &ToolChainManager::toolChainRemoved, this, &ToolChainManager::toolChainsChanged);
connect(this, &ToolChainManager::toolChainUpdated, this, &ToolChainManager::toolChainsChanged);
+
+ QSettings * const s = Core::ICore::settings();
+ d->m_detectionSettings.detectX64AsX32 = s->value(DETECT_X64_AS_X32_KEY, false).toBool();
}
ToolChainManager::~ToolChainManager()
@@ -130,6 +136,8 @@ void ToolChainManager::saveToolChains()
QTC_ASSERT(d->m_accessor, return);
d->m_accessor->saveToolChains(d->m_toolChains, Core::ICore::dialogParent());
+ QSettings * const s = Core::ICore::settings();
+ s->setValue(DETECT_X64_AS_X32_KEY, d->m_detectionSettings.detectX64AsX32);
}
QList<ToolChain *> ToolChainManager::toolChains(const ToolChain::Predicate &predicate)
@@ -178,7 +186,7 @@ ToolChain *ToolChainManager::findToolChain(const QByteArray &id)
return tc;
}
-FileName ToolChainManager::defaultDebugger(const Abi &abi)
+FilePath ToolChainManager::defaultDebugger(const Abi &abi)
{
return d->m_abiToDebugger.value(abi.toString());
}
@@ -257,4 +265,14 @@ void ToolChainManager::aboutToShutdown()
#endif
}
+ToolchainDetectionSettings ToolChainManager::detectionSettings()
+{
+ return d->m_detectionSettings;
+}
+
+void ToolChainManager::setDetectionSettings(const ToolchainDetectionSettings &settings)
+{
+ d->m_detectionSettings = settings;
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/toolchainmanager.h b/src/plugins/projectexplorer/toolchainmanager.h
index 2e26431b84..4de51c2b2a 100644
--- a/src/plugins/projectexplorer/toolchainmanager.h
+++ b/src/plugins/projectexplorer/toolchainmanager.h
@@ -38,13 +38,19 @@
#include <functional>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ProjectExplorer {
class ProjectExplorerPlugin;
class Abi;
+class ToolchainDetectionSettings
+{
+public:
+ bool detectX64AsX32 = false;
+};
+
// --------------------------------------------------------------------------
// ToolChainManager
// --------------------------------------------------------------------------
@@ -62,7 +68,7 @@ public:
static QList<ToolChain *> findToolChains(const Abi &abi);
static ToolChain *findToolChain(const QByteArray &id);
- static Utils::FileName defaultDebugger(const Abi &abi);
+ static Utils::FilePath defaultDebugger(const Abi &abi);
static bool isLoaded();
@@ -76,6 +82,9 @@ public:
static void aboutToShutdown();
+ static ToolchainDetectionSettings detectionSettings();
+ static void setDetectionSettings(const ToolchainDetectionSettings &settings);
+
void saveToolChains();
signals:
diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp
index 2e41c8cd42..a16c6f216e 100644
--- a/src/plugins/projectexplorer/toolchainoptionspage.cpp
+++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp
@@ -38,15 +38,21 @@
#include <utils/detailswidget.h>
#include <utils/qtcassert.h>
#include <utils/treemodel.h>
+#include <utils/utilsicons.h>
#include <QAction>
#include <QApplication>
+#include <QCheckBox>
+#include <QCoreApplication>
+#include <QDialog>
+#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QItemSelectionModel>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
+#include <QSet>
#include <QSpacerItem>
#include <QStackedWidget>
#include <QTextStream>
@@ -84,17 +90,20 @@ public:
if (column == 0)
return toolChain->displayName();
return toolChain->typeDisplayName();
-
case Qt::FontRole: {
QFont font;
font.setBold(changed);
return font;
}
-
case Qt::ToolTipRole:
+ if (!toolChain->isValid())
+ return ToolChainOptionsPage::tr("This toolchain is no longer valid.");
return ToolChainOptionsPage::tr("<nobr><b>ABI:</b> %1").arg(
changed ? ToolChainOptionsPage::tr("not up-to-date")
: toolChain->targetAbi().toString());
+ case Qt::DecorationRole:
+ return column == 0 && !toolChain->isValid()
+ ? Utils::Icons::CRITICAL.icon() : QVariant();
}
return QVariant();
}
@@ -104,6 +113,39 @@ public:
bool changed;
};
+class DetectionSettingsDialog : public QDialog
+{
+public:
+ DetectionSettingsDialog(const ToolchainDetectionSettings &settings, QWidget *parent)
+ : QDialog(parent)
+ {
+ setWindowTitle(ToolChainOptionsPage::tr("Toolchain Auto-detection Settings"));
+ const auto layout = new QVBoxLayout(this);
+ m_detectX64AsX32CheckBox.setText(ToolChainOptionsPage::tr("Detect x86_64 GCC compilers "
+ "as x86_64 and x86"));
+ m_detectX64AsX32CheckBox.setToolTip(ToolChainOptionsPage::tr("If checked, Qt Creator will "
+ "set up two instances of each x86_64 compiler:\nOne for the native x86_64 target, "
+ "and one for a plain x86 target.\nEnable this if you plan to create 32-bit x86 "
+ "binaries without using a dedicated cross compiler."));
+ m_detectX64AsX32CheckBox.setChecked(settings.detectX64AsX32);
+ layout->addWidget(&m_detectX64AsX32CheckBox);
+ const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ layout->addWidget(buttonBox);
+ }
+
+ ToolchainDetectionSettings settings() const
+ {
+ ToolchainDetectionSettings s;
+ s.detectX64AsX32 = m_detectX64AsX32CheckBox.isChecked();
+ return s;
+ }
+
+private:
+ QCheckBox m_detectX64AsX32CheckBox;
+};
+
// --------------------------------------------------------------------------
// ToolChainOptionsWidget
// --------------------------------------------------------------------------
@@ -113,6 +155,7 @@ class ToolChainOptionsWidget : public QWidget
public:
ToolChainOptionsWidget()
{
+ m_detectionSettings = ToolChainManager::detectionSettings();
m_factories = Utils::filtered(ToolChainFactory::allToolChainFactories(),
[](ToolChainFactory *factory) { return factory->canCreate();});
@@ -169,6 +212,34 @@ public:
m_delButton = new QPushButton(ToolChainOptionsPage::tr("Remove"), this);
+ m_removeAllButton = new QPushButton(ToolChainOptionsPage::tr("Remove All"), this);
+ connect(m_removeAllButton, &QAbstractButton::clicked, this,
+ [this] {
+ QList<ToolChainTreeItem *> itemsToRemove;
+ m_model.forAllItems([&itemsToRemove](TreeItem *item) {
+ if (item->level() != 3)
+ return;
+ const auto tcItem = static_cast<ToolChainTreeItem *>(item);
+ if (tcItem->toolChain->detection() != ToolChain::AutoDetectionFromSdk)
+ itemsToRemove << tcItem;
+ });
+ for (ToolChainTreeItem * const tcItem : qAsConst(itemsToRemove))
+ markForRemoval(tcItem);
+ });
+
+ m_redetectButton = new QPushButton(ToolChainOptionsPage::tr("Re-detect"), this);
+ connect(m_redetectButton, &QAbstractButton::clicked,
+ this, &ToolChainOptionsWidget::redetectToolchains);
+
+ m_detectionSettingsButton = new QPushButton(
+ ToolChainOptionsPage::tr("Auto-detection Settings..."), this);
+ connect(m_detectionSettingsButton, &QAbstractButton::clicked, this,
+ [this] {
+ DetectionSettingsDialog dlg(m_detectionSettings, this);
+ if (dlg.exec() == QDialog::Accepted)
+ m_detectionSettings = dlg.settings();
+ });
+
m_container = new DetailsWidget(this);
m_container->setState(DetailsWidget::NoSummary);
m_container->setVisible(false);
@@ -185,6 +256,9 @@ public:
buttonLayout->addWidget(m_addButton);
buttonLayout->addWidget(m_cloneButton);
buttonLayout->addWidget(m_delButton);
+ buttonLayout->addWidget(m_removeAllButton);
+ buttonLayout->addWidget(m_redetectButton);
+ buttonLayout->addWidget(m_detectionSettingsButton);
buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
auto verticalLayout = new QVBoxLayout;
@@ -232,9 +306,11 @@ public:
return action;
}
+ void redetectToolchains();
+
void apply();
- public:
+ private:
TreeModel<TreeItem, ToolChainTreeItem> m_model;
QList<ToolChainFactory *> m_factories;
QTreeView *m_toolChainView;
@@ -243,11 +319,16 @@ public:
QPushButton *m_addButton;
QPushButton *m_cloneButton;
QPushButton *m_delButton;
+ QPushButton *m_removeAllButton;
+ QPushButton *m_redetectButton;
+ QPushButton *m_detectionSettingsButton;
QHash<Core::Id, QPair<StaticTreeItem *, StaticTreeItem *>> m_languageMap;
QList<ToolChainTreeItem *> m_toAddList;
QList<ToolChainTreeItem *> m_toRemoveList;
+
+ ToolchainDetectionSettings m_detectionSettings;
};
void ToolChainOptionsWidget::markForRemoval(ToolChainTreeItem *item)
@@ -312,6 +393,50 @@ StaticTreeItem *ToolChainOptionsWidget::parentForToolChain(ToolChain *tc)
return tc->isAutoDetected() ? nodes.first : nodes.second;
}
+void ToolChainOptionsWidget::redetectToolchains()
+{
+ QList<ToolChainTreeItem *> itemsToRemove;
+ QList<ToolChain *> knownTcs;
+ m_model.forAllItems([&itemsToRemove, &knownTcs](TreeItem *item) {
+ if (item->level() != 3)
+ return;
+ const auto tcItem = static_cast<ToolChainTreeItem *>(item);
+ if (tcItem->toolChain->isAutoDetected()
+ && tcItem->toolChain->detection() != ToolChain::AutoDetectionFromSdk) {
+ itemsToRemove << tcItem;
+ } else {
+ knownTcs << tcItem->toolChain;
+ }
+ });
+ QList<ToolChain *> toAdd;
+ QSet<ToolChain *> toDelete;
+ for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
+ for (ToolChain * const tc : f->autoDetect(knownTcs)) {
+ if (knownTcs.contains(tc) || toDelete.contains(tc))
+ continue;
+ const auto matchItem = [tc](const ToolChainTreeItem *item) {
+ return item->toolChain->compilerCommand() == tc->compilerCommand()
+ && item->toolChain->typeId() == tc->typeId()
+ && item->toolChain->language() == tc->language()
+ && item->toolChain->targetAbi() == tc->targetAbi();
+ };
+ ToolChainTreeItem * const item = findOrDefault(itemsToRemove, matchItem);
+ if (item) {
+ itemsToRemove.removeOne(item);
+ toDelete << tc;
+ continue;
+ }
+ knownTcs << tc;
+ toAdd << tc;
+ }
+ }
+ for (ToolChainTreeItem * const tcItem : qAsConst(itemsToRemove))
+ markForRemoval(tcItem);
+ for (ToolChain * const newTc : qAsConst(toAdd))
+ m_toAddList.append(insertToolChain(newTc, true));
+ qDeleteAll(toDelete);
+}
+
void ToolChainOptionsWidget::toolChainSelectionChanged()
{
ToolChainTreeItem *item = currentTreeItem();
@@ -334,14 +459,16 @@ void ToolChainOptionsWidget::apply()
// Update tool chains:
foreach (const Core::Id &l, m_languageMap.keys()) {
- StaticTreeItem *parent = m_languageMap.value(l).second;
- for (TreeItem *item : *parent) {
- auto tcItem = static_cast<ToolChainTreeItem *>(item);
- Q_ASSERT(tcItem->toolChain);
- if (tcItem->widget)
- tcItem->widget->apply();
- tcItem->changed = false;
- tcItem->update();
+ const QPair<StaticTreeItem *, StaticTreeItem *> autoAndManual = m_languageMap.value(l);
+ for (StaticTreeItem *parent : {autoAndManual.first, autoAndManual.second}) {
+ for (TreeItem *item : *parent) {
+ auto tcItem = static_cast<ToolChainTreeItem *>(item);
+ Q_ASSERT(tcItem->toolChain);
+ if (!tcItem->toolChain->isAutoDetected() && tcItem->widget)
+ tcItem->widget->apply();
+ tcItem->changed = false;
+ tcItem->update();
+ }
}
}
@@ -374,6 +501,7 @@ void ToolChainOptionsWidget::apply()
"They were not configured again.")
.arg(removedTcs.join(QLatin1String(",<br>&nbsp;"))));
}
+ ToolChainManager::setDetectionSettings(m_detectionSettings);
}
void ToolChainOptionsWidget::createToolChain(ToolChainFactory *factory, const Core::Id &language)
@@ -382,10 +510,13 @@ void ToolChainOptionsWidget::createToolChain(ToolChainFactory *factory, const Co
QTC_ASSERT(factory->canCreate(), return);
QTC_ASSERT(language.isValid(), return);
- ToolChain *tc = factory->create(language);
+ ToolChain *tc = factory->create();
if (!tc)
return;
+ tc->setDetection(ToolChain::ManualDetection);
+ tc->setLanguage(language);
+
auto item = insertToolChain(tc, true);
m_toAddList.append(item);
@@ -397,11 +528,15 @@ void ToolChainOptionsWidget::cloneToolChain()
ToolChainTreeItem *current = currentTreeItem();
if (!current)
return;
- ToolChain *tc = current->toolChain->clone();
+ ToolChain *tc = current->toolChain->clone();
if (!tc)
return;
+ tc->setDetection(ToolChain::ManualDetection);
+ tc->setDisplayName(QCoreApplication::translate("ProjectExplorer::ToolChain", "Clone of %1")
+ .arg(current->toolChain->displayName()));
+
auto item = insertToolChain(tc, true);
m_toAddList.append(item);
@@ -414,8 +549,8 @@ void ToolChainOptionsWidget::updateState()
bool canDelete = false;
if (ToolChainTreeItem *item = currentTreeItem()) {
ToolChain *tc = item->toolChain;
- canCopy = tc->isValid() && tc->canClone();
- canDelete = tc->detection() != ToolChain::AutoDetection;
+ canCopy = tc->isValid();
+ canDelete = tc->detection() != ToolChain::AutoDetectionFromSdk;
}
m_cloneButton->setEnabled(canCopy);
diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
index 80d280a122..d2c347dd37 100644
--- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
+++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
@@ -164,12 +164,9 @@ static ToolChainOperations mergeToolChainLists(const QList<ToolChain *> &systemF
const QList<ToolChain *> notRedetectedButValidUserTcs
= Utils::filtered(notRedetectedUserTcs, &ToolChain::isValid);
- const QList<ToolChain *> validManualUserTcs
- = Utils::filtered(manualUserFileTcs, &ToolChain::isValid);
-
ToolChainOperations result;
result.toDemote = notRedetectedButValidUserTcs;
- result.toRegister = stabilizeOrder(systemFileTcs + validManualUserTcs + result.toDemote // manual TCs
+ result.toRegister = stabilizeOrder(systemFileTcs + manualUserFileTcs + result.toDemote // manual TCs
+ redetectedUserTcs + newlyAutodetectedTcs, // auto TCs
userFileTcs);
@@ -187,7 +184,7 @@ ToolChainSettingsAccessor::ToolChainSettingsAccessor() :
QCoreApplication::translate("ProjectExplorer::ToolChainManager", "Tool Chains"),
Core::Constants::IDE_DISPLAY_NAME)
{
- setBaseFilePath(FileName::fromString(Core::ICore::userResourcePath() + TOOLCHAIN_FILENAME));
+ setBaseFilePath(FilePath::fromString(Core::ICore::userResourcePath() + TOOLCHAIN_FILENAME));
addVersionUpgrader(std::make_unique<ToolChainSettingsUpgraderV0>());
}
@@ -196,8 +193,10 @@ QList<ToolChain *> ToolChainSettingsAccessor::restoreToolChains(QWidget *parent)
{
// read all tool chains from SDK
const QList<ToolChain *> systemFileTcs
- = toolChains(restoreSettings(FileName::fromString(Core::ICore::installerResourcePath() + TOOLCHAIN_FILENAME),
+ = toolChains(restoreSettings(FilePath::fromString(Core::ICore::installerResourcePath() + TOOLCHAIN_FILENAME),
parent));
+ for (ToolChain * const systemTc : systemFileTcs)
+ systemTc->setDetection(ToolChain::AutoDetectionFromSdk);
// read all tool chains from user file.
const QList<ToolChain *> userFileTcs = toolChains(restoreSettings(parent));
@@ -225,7 +224,7 @@ void ToolChainSettingsAccessor::saveToolChains(const QList<ToolChain *> &toolcha
int count = 0;
for (const ToolChain *tc : toolchains) {
- if (!tc || !tc->isValid())
+ if (!tc || (!tc->isValid() && tc->isAutoDetected()))
continue;
const QVariantMap tmp = tc->toMap();
if (tmp.isEmpty())
@@ -254,18 +253,21 @@ QList<ToolChain *> ToolChainSettingsAccessor::toolChains(const QVariantMap &data
const QVariantMap tcMap = data.value(key).toMap();
bool restored = false;
- for (ToolChainFactory *f : factories) {
- if (f->canRestore(tcMap)) {
- if (ToolChain *tc = f->restore(tcMap)) {
- result.append(tc);
- restored = true;
- break;
+ const Core::Id tcType = ToolChainFactory::typeIdFromMap(tcMap);
+ if (tcType.isValid()) {
+ for (ToolChainFactory *f : factories) {
+ if (f->supportedToolChainType() == tcType) {
+ if (ToolChain *tc = f->restore(tcMap)) {
+ result.append(tc);
+ restored = true;
+ break;
+ }
}
}
}
if (!restored)
qWarning("Warning: Unable to restore compiler type '%s' for tool chain %s.",
- qPrintable(ToolChainFactory::typeIdFromMap(tcMap).toString()),
+ qPrintable(tcType.toString()),
qPrintable(QString::fromUtf8(ToolChainFactory::idFromMap(tcMap))));
}
@@ -290,11 +292,17 @@ namespace ProjectExplorer {
using TCList = QList<ToolChain *>;
+const char TestTokenKey[] = "TestTokenKey";
+const char TestToolChainType[] = "TestToolChainType";
+
+
class TTC : public ToolChain
{
public:
- TTC(ToolChain::Detection d, const QByteArray &t, bool v = true) :
- ToolChain("TestToolChainType", d),
+ TTC() : ToolChain(TestToolChainType) {}
+
+ TTC(const QByteArray &t, bool v = true) :
+ ToolChain(TestToolChainType),
token(t),
m_valid(v)
{
@@ -313,28 +321,36 @@ public:
LanguageExtensions languageExtensions(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return LanguageExtension::None; }
WarningFlags warningFlags(const QStringList &cflags) const override { Q_UNUSED(cflags); return WarningFlags::NoWarnings; }
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override { return BuiltInHeaderPathsRunner(); }
- HeaderPaths builtInHeaderPaths(const QStringList &cxxflags, const FileName &sysRoot) const override
+ HeaderPaths builtInHeaderPaths(const QStringList &cxxflags, const FilePath &sysRoot) const override
{ Q_UNUSED(cxxflags); Q_UNUSED(sysRoot); return {}; }
void addToEnvironment(Environment &env) const override { Q_UNUSED(env); }
- QString makeCommand(const Environment &env) const override { Q_UNUSED(env); return QString("make"); }
- FileName compilerCommand() const override { return Utils::FileName::fromString("/tmp/test/gcc"); }
+ FilePath makeCommand(const Environment &) const override { return FilePath::fromString("make"); }
+ FilePath compilerCommand() const override { return Utils::FilePath::fromString("/tmp/test/gcc"); }
IOutputParser *outputParser() const override { return nullptr; }
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override { return nullptr; }
- TTC *clone() const override { return new TTC(*this); }
bool operator ==(const ToolChain &other) const override {
if (!ToolChain::operator==(other))
return false;
return static_cast<const TTC *>(&other)->token == token;
}
+ bool fromMap(const QVariantMap &data) final
+ {
+ ToolChain::fromMap(data);
+ token = data.value(TestTokenKey).toByteArray();
+ return true;
+ }
+
+ QVariantMap toMap() const final
+ {
+ QVariantMap data = ToolChain::toMap();
+ data[TestTokenKey] = token;
+ return data;
+ }
+
QByteArray token;
private:
- TTC(const TTC &other) :
- ToolChain(other.typeId(), other.detection()),
- token(other.token)
- {}
-
bool m_valid = false;
static QList<TTC *> m_toolChains;
@@ -352,6 +368,17 @@ namespace ProjectExplorer {
void ProjectExplorerPlugin::testToolChainMerging_data()
{
+ class TestToolChainFactory : ToolChainFactory
+ {
+ public:
+ TestToolChainFactory() {
+ setSupportedToolChainType(TestToolChainType);
+ setToolchainConstructor([] { return new TTC; });
+ }
+ };
+
+ TestToolChainFactory factory;
+
QTest::addColumn<TCList>("system");
QTest::addColumn<TCList>("user");
QTest::addColumn<TCList>("autodetect");
@@ -359,33 +386,43 @@ void ProjectExplorerPlugin::testToolChainMerging_data()
QTest::addColumn<TCList>("toRegister");
TTC *system1 = nullptr;
- TTC *system1c = nullptr;
+ ToolChain *system1c = nullptr;
TTC *system2 = nullptr;
TTC *system3i = nullptr;
TTC *user1 = nullptr;
- TTC *user1c = nullptr;
+ ToolChain *user1c = nullptr;
TTC *user3i = nullptr;
TTC *user2 = nullptr;
TTC *auto1 = nullptr;
- TTC *auto1c = nullptr;
+ ToolChain *auto1c = nullptr;
TTC *auto1_2 = nullptr;
TTC *auto2 = nullptr;
TTC *auto3i = nullptr;
if (!TTC::hasToolChains()) {
- system1 = new TTC(ToolChain::AutoDetection, "system1"); Q_UNUSED(system1);
- system1c = system1->clone(); Q_UNUSED(system1c);
- system2 = new TTC(ToolChain::AutoDetection, "system2"); Q_UNUSED(system2);
- system3i = new TTC(ToolChain::AutoDetection, "system3", false); Q_UNUSED(system3i);
- user1 = new TTC(ToolChain::ManualDetection, "user1"); Q_UNUSED(user1);
- user1c = user1->clone(); Q_UNUSED(user1c);
- user2 = new TTC(ToolChain::ManualDetection, "user2"); Q_UNUSED(user2);
- user3i = new TTC(ToolChain::ManualDetection, "user3", false); Q_UNUSED(user3i);
- auto1 = new TTC(ToolChain::AutoDetectionFromSettings, "auto1"); Q_UNUSED(auto1);
- auto1c = auto1->clone(); Q_UNUSED(auto1c);
- auto1_2 = new TTC(ToolChain::AutoDetectionFromSettings, "auto1"); Q_UNUSED(auto1_2);
- auto2 = new TTC(ToolChain::AutoDetectionFromSettings, "auto2"); Q_UNUSED(auto2);
- auto3i = new TTC(ToolChain::AutoDetectionFromSettings, "auto3", false); Q_UNUSED(auto3i);
+ system1 = new TTC("system1");
+ system1->setDetection(ToolChain::AutoDetection);
+ system1c = system1->clone(); Q_UNUSED(system1c)
+ system2 = new TTC("system2");
+ system2->setDetection(ToolChain::AutoDetection);
+ system3i = new TTC("system3", false);
+ system3i->setDetection(ToolChain::AutoDetection);
+ user1 = new TTC("user1");
+ user1->setDetection(ToolChain::ManualDetection);
+ user1c = user1->clone(); Q_UNUSED(user1c)
+ user2 = new TTC("user2");
+ user2->setDetection(ToolChain::ManualDetection);
+ user3i = new TTC("user3", false);
+ user3i->setDetection(ToolChain::ManualDetection);
+ auto1 = new TTC("auto1");
+ auto1->setDetection(ToolChain::AutoDetection);
+ auto1c = auto1->clone();
+ auto1_2 = new TTC("auto1");
+ auto1_2->setDetection(ToolChain::AutoDetection);
+ auto2 = new TTC("auto2");
+ auto2->setDetection(ToolChain::AutoDetection);
+ auto3i = new TTC("auto3", false);
+ auto3i->setDetection(ToolChain::AutoDetection);
}
QTest::newRow("no toolchains")
@@ -424,9 +461,9 @@ void ProjectExplorerPlugin::testToolChainMerging_data()
<< (TCList()) << (TCList() << auto3i) << (TCList())
<< (TCList()) << (TCList());
- QTest::newRow("Delete invalid user")
+ QTest::newRow("invalid user")
<< (TCList()) << (TCList() << user3i) << (TCList())
- << (TCList()) << (TCList());
+ << (TCList()) << (TCList{user3i});
QTest::newRow("one of everything")
<< (TCList() << system1) << (TCList() << user1) << (TCList() << auto1)
diff --git a/src/plugins/projectexplorer/treescanner.cpp b/src/plugins/projectexplorer/treescanner.cpp
new file mode 100644
index 0000000000..7c7f634d1a
--- /dev/null
+++ b/src/plugins/projectexplorer/treescanner.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Alexander Drozdov.
+** Contact: Alexander Drozdov (adrozdoff@gmail.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 "treescanner.h"
+#include "projectexplorerconstants.h"
+
+#include <coreplugin/iversioncontrol.h>
+#include <coreplugin/vcsmanager.h>
+
+#include <cpptools/cpptoolsconstants.h>
+
+#include <utils/qtcassert.h>
+#include <utils/algorithm.h>
+#include <utils/runextensions.h>
+
+#include <memory>
+
+namespace ProjectExplorer {
+
+TreeScanner::TreeScanner(QObject *parent) : QObject(parent)
+{
+ m_factory = TreeScanner::genericFileType;
+ m_filter = [](const Utils::MimeType &mimeType, const Utils::FilePath &fn) {
+ return isWellKnownBinary(mimeType, fn) && isMimeBinary(mimeType, fn);
+ };
+
+ connect(&m_futureWatcher, &FutureWatcher::finished, this, &TreeScanner::finished);
+}
+
+TreeScanner::~TreeScanner()
+{
+ if (!m_futureWatcher.isFinished()) {
+ m_futureWatcher.cancel();
+ m_futureWatcher.waitForFinished();
+ }
+}
+
+bool TreeScanner::asyncScanForFiles(const Utils::FilePath &directory)
+{
+ if (!m_futureWatcher.isFinished())
+ return false;
+
+ auto fi = new FutureInterface();
+ m_scanFuture = fi->future();
+ m_futureWatcher.setFuture(m_scanFuture);
+
+ Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); });
+
+ return true;
+}
+
+void TreeScanner::setFilter(TreeScanner::FileFilter filter)
+{
+ if (isFinished())
+ m_filter = filter;
+}
+
+void TreeScanner::setTypeFactory(TreeScanner::FileTypeFactory factory)
+{
+ if (isFinished())
+ m_factory = factory;
+}
+
+TreeScanner::Future TreeScanner::future() const
+{
+ return m_scanFuture;
+}
+
+bool TreeScanner::isFinished() const
+{
+ return m_futureWatcher.isFinished();
+}
+
+TreeScanner::Result TreeScanner::result() const
+{
+ if (isFinished())
+ return m_scanFuture.result();
+ return Result();
+}
+
+TreeScanner::Result TreeScanner::release()
+{
+ if (isFinished()) {
+ auto result = m_scanFuture.result();
+ m_scanFuture = Future();
+ return result;
+ }
+ return Result();
+}
+
+void TreeScanner::reset()
+{
+ if (isFinished())
+ m_scanFuture = Future();
+}
+
+bool TreeScanner::isWellKnownBinary(const Utils::MimeType & /*mdb*/, const Utils::FilePath &fn)
+{
+ return fn.endsWith(QLatin1String(".a")) ||
+ fn.endsWith(QLatin1String(".o")) ||
+ fn.endsWith(QLatin1String(".d")) ||
+ fn.endsWith(QLatin1String(".exe")) ||
+ fn.endsWith(QLatin1String(".dll")) ||
+ fn.endsWith(QLatin1String(".obj")) ||
+ fn.endsWith(QLatin1String(".elf"));
+}
+
+bool TreeScanner::isMimeBinary(const Utils::MimeType &mimeType, const Utils::FilePath &/*fn*/)
+{
+ bool isBinary = false;
+ if (mimeType.isValid()) {
+ QStringList mimes;
+ mimes << mimeType.name() << mimeType.allAncestors();
+ isBinary = !mimes.contains(QLatin1String("text/plain"));
+ }
+ return isBinary;
+}
+
+FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Utils::FilePath &/*fn*/)
+{
+ return Node::fileTypeForMimeType(mimeType);
+}
+
+void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FilePath& directory,
+ const FileFilter &filter, const FileTypeFactory &factory)
+{
+ std::unique_ptr<FutureInterface> fip(fi);
+ fip->reportStarted();
+
+ Result nodes = FileNode::scanForFiles(
+ directory,
+ [&filter, &factory](const Utils::FilePath &fn) -> FileNode * {
+ const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString());
+
+ // Skip some files during scan.
+ if (filter && filter(mimeType, fn))
+ return nullptr;
+
+ // Type detection
+ FileType type = FileType::Unknown;
+ if (factory)
+ type = factory(mimeType, fn);
+
+ return new FileNode(fn, type);
+ }, fip.get());
+
+ Utils::sort(nodes, ProjectExplorer::Node::sortByPath);
+
+ fip->setProgressValue(fip->progressMaximum());
+ fip->reportResult(nodes);
+ fip->reportFinished();
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/treescanner.h b/src/plugins/projectexplorer/treescanner.h
new file mode 100644
index 0000000000..e2ad544bde
--- /dev/null
+++ b/src/plugins/projectexplorer/treescanner.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Alexander Drozdov.
+** Contact: Alexander Drozdov (adrozdoff@gmail.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 "projectexplorer_export.h"
+#include "projectnodes.h"
+
+#include <utils/mimetypes/mimedatabase.h>
+#include <utils/fileutils.h>
+
+#include <QObject>
+#include <QFuture>
+#include <QFutureWatcher>
+
+#include <functional>
+
+namespace Core { class IVersionControl; }
+
+namespace ProjectExplorer {
+
+class PROJECTEXPLORER_EXPORT TreeScanner : public QObject
+{
+ Q_OBJECT
+
+public:
+ using Result = QList<ProjectExplorer::FileNode *>;
+ using Future = QFuture<Result>;
+ using FutureWatcher = QFutureWatcher<Result>;
+ using FutureInterface = QFutureInterface<Result>;
+
+ using FileFilter = std::function<bool(const Utils::MimeType &, const Utils::FilePath &)>;
+ using FileTypeFactory = std::function<ProjectExplorer::FileType(const Utils::MimeType &, const Utils::FilePath &)>;
+
+ explicit TreeScanner(QObject *parent = nullptr);
+ ~TreeScanner() override;
+
+ // Start scanning in given directory
+ bool asyncScanForFiles(const Utils::FilePath& directory);
+
+ // Setup filter for ignored files
+ void setFilter(FileFilter filter);
+
+ // Setup factory for file types
+ void setTypeFactory(FileTypeFactory factory);
+
+ Future future() const;
+ bool isFinished() const;
+
+ // Takes not-owning result
+ Result result() const;
+ // Takes owning of result
+ Result release();
+ // Clear scan results
+ void reset();
+
+ // Standard filters helpers
+ static bool isWellKnownBinary(const Utils::MimeType &mimeType, const Utils::FilePath &fn);
+ static bool isMimeBinary(const Utils::MimeType &mimeType, const Utils::FilePath &fn);
+
+ // Standard file factory
+ static ProjectExplorer::FileType genericFileType(const Utils::MimeType &mdb, const Utils::FilePath& fn);
+
+signals:
+ void finished();
+
+private:
+ static void scanForFiles(FutureInterface *fi, const Utils::FilePath &directory,
+ const FileFilter &filter, const FileTypeFactory &factory);
+
+private:
+ FileFilter m_filter;
+ FileTypeFactory m_factory;
+
+ FutureWatcher m_futureWatcher;
+ Future m_scanFuture;
+};
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp
index 49a0ccdf7b..838507e544 100644
--- a/src/plugins/projectexplorer/userfileaccessor.cpp
+++ b/src/plugins/projectexplorer/userfileaccessor.cpp
@@ -52,6 +52,16 @@ const char OBSOLETE_VERSION_KEY[] = "ProjectExplorer.Project.Updater.FileVersion
const char SHARED_SETTINGS[] = "SharedSettings";
const char USER_STICKY_KEYS_KEY[] = "UserStickyKeys";
+#ifdef PROJECT_USER_FILE_EXTENSION
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+
+const char FILE_EXTENSION_STR[] = STRINGIFY(PROJECT_USER_FILE_EXTENSION);
+#else
+const char FILE_EXTENSION_STR[] = ".user";
+
+#endif
+
// Version 14 Move builddir into BuildConfiguration
class UserFileVersion14Upgrader : public VersionUpgrader
{
@@ -230,19 +240,18 @@ static QString makeRelative(QString path)
}
// Return complete file path of the .user file.
-static FileName externalUserFilePath(const Utils::FileName &projectFilePath, const QString &suffix)
+static FilePath externalUserFilePath(const Utils::FilePath &projectFilePath, const QString &suffix)
{
- FileName result;
static const optional<QString> externalUserFileDir = defineExternalUserFileDir();
if (externalUserFileDir) {
// Recreate the relative project file hierarchy under the shared directory.
// PersistentSettingsWriter::write() takes care of creating the path.
- result = FileName::fromString(externalUserFileDir.value());
- result.appendString('/' + makeRelative(projectFilePath.toString()));
- result.appendString(suffix);
+ return FilePath::fromString(externalUserFileDir.value()
+ + '/' + makeRelative(projectFilePath.toString())
+ + suffix);
}
- return result;
+ return {};
}
} // namespace
@@ -257,18 +266,18 @@ public:
UserFileBackUpStrategy(UserFileAccessor *accessor) : Utils::VersionedBackUpStrategy(accessor)
{ }
- FileNameList readFileCandidates(const Utils::FileName &baseFileName) const final;
+ FilePathList readFileCandidates(const Utils::FilePath &baseFileName) const final;
};
-FileNameList UserFileBackUpStrategy::readFileCandidates(const FileName &baseFileName) const
+FilePathList UserFileBackUpStrategy::readFileCandidates(const FilePath &baseFileName) const
{
const auto *const ac = static_cast<const UserFileAccessor *>(accessor());
- const FileName externalUser = ac->externalUserFile();
- const FileName projectUser = ac->projectUserFile();
+ const FilePath externalUser = ac->externalUserFile();
+ const FilePath projectUser = ac->projectUserFile();
QTC_CHECK(!baseFileName.isEmpty());
QTC_CHECK(baseFileName == externalUser || baseFileName == projectUser);
- FileNameList result = Utils::VersionedBackUpStrategy::readFileCandidates(projectUser);
+ FilePathList result = Utils::VersionedBackUpStrategy::readFileCandidates(projectUser);
if (!externalUser.isEmpty())
result.append(Utils::VersionedBackUpStrategy::readFileCandidates(externalUser));
@@ -286,8 +295,8 @@ UserFileAccessor::UserFileAccessor(Project *project) :
m_project(project)
{
// Setup:
- const FileName externalUser = externalUserFile();
- const FileName projectUser = projectUserFile();
+ const FilePath externalUser = externalUserFile();
+ const FilePath projectUser = projectUserFile();
setBaseFilePath(externalUser.isEmpty() ? projectUser : externalUser);
auto secondary
@@ -375,27 +384,25 @@ QVariant UserFileAccessor::retrieveSharedSettings() const
return project()->property(SHARED_SETTINGS);
}
-FileName UserFileAccessor::projectUserFile() const
+FilePath UserFileAccessor::projectUserFile() const
{
static const QString qtcExt = QLatin1String(qgetenv("QTC_EXTENSION"));
- FileName projectUserFile = m_project->projectFilePath();
- projectUserFile.appendString(generateSuffix(qtcExt.isEmpty() ? ".user" : qtcExt));
- return projectUserFile;
+ return m_project->projectFilePath()
+ .stringAppended(generateSuffix(qtcExt.isEmpty() ? FILE_EXTENSION_STR : qtcExt));
}
-FileName UserFileAccessor::externalUserFile() const
+FilePath UserFileAccessor::externalUserFile() const
{
static const QString qtcExt = QFile::decodeName(qgetenv("QTC_EXTENSION"));
return externalUserFilePath(m_project->projectFilePath(),
- generateSuffix(qtcExt.isEmpty() ? ".user" : qtcExt));
+ generateSuffix(qtcExt.isEmpty() ? FILE_EXTENSION_STR : qtcExt));
}
-FileName UserFileAccessor::sharedFile() const
+FilePath UserFileAccessor::sharedFile() const
{
static const QString qtcExt = QLatin1String(qgetenv("QTC_SHARED_EXTENSION"));
- FileName sharedFile = m_project->projectFilePath();
- sharedFile.appendString(generateSuffix(qtcExt.isEmpty() ? ".shared" : qtcExt));
- return sharedFile;
+ return m_project->projectFilePath()
+ .stringAppended(generateSuffix(qtcExt.isEmpty() ? ".shared" : qtcExt));
}
QVariantMap UserFileAccessor::postprocessMerge(const QVariantMap &main,
@@ -877,7 +884,7 @@ private:
class TestProject : public Project
{
public:
- TestProject() : Project("x-test/testproject", Utils::FileName::fromString("/test/project")) {
+ TestProject() : Project("x-test/testproject", Utils::FilePath::fromString("/test/project")) {
setDisplayName("Test Project");
}
@@ -974,7 +981,7 @@ void ProjectExplorerPlugin::testUserFileAccessor_mergeSettings()
sharedData.insert("shared1", "bar");
sharedData.insert("shared2", "baz");
sharedData.insert("shared3", "foooo");
- TestUserFileAccessor::RestoreData shared(FileName::fromString("/shared/data"), sharedData);
+ TestUserFileAccessor::RestoreData shared(FilePath::fromString("/shared/data"), sharedData);
QVariantMap data;
data.insert("Version", accessor.currentVersion());
@@ -983,7 +990,7 @@ void ProjectExplorerPlugin::testUserFileAccessor_mergeSettings()
data.insert("shared1", "bar1");
data.insert("unique1", 1234);
data.insert("shared3", "foo");
- TestUserFileAccessor::RestoreData user(FileName::fromString("/user/data"), data);
+ TestUserFileAccessor::RestoreData user(FilePath::fromString("/user/data"), data);
TestUserFileAccessor::RestoreData result = accessor.mergeSettings(user, shared);
QVERIFY(!result.hasIssue());
@@ -1009,10 +1016,10 @@ void ProjectExplorerPlugin::testUserFileAccessor_mergeSettingsEmptyUser()
sharedData.insert("shared1", "bar");
sharedData.insert("shared2", "baz");
sharedData.insert("shared3", "foooo");
- TestUserFileAccessor::RestoreData shared(FileName::fromString("/shared/data"), sharedData);
+ TestUserFileAccessor::RestoreData shared(FilePath::fromString("/shared/data"), sharedData);
QVariantMap data;
- TestUserFileAccessor::RestoreData user(FileName::fromString("/shared/data"), data);
+ TestUserFileAccessor::RestoreData user(FilePath::fromString("/shared/data"), data);
TestUserFileAccessor::RestoreData result = accessor.mergeSettings(user, shared);
@@ -1026,7 +1033,7 @@ void ProjectExplorerPlugin::testUserFileAccessor_mergeSettingsEmptyShared()
TestUserFileAccessor accessor(&project);
QVariantMap sharedData;
- TestUserFileAccessor::RestoreData shared(FileName::fromString("/shared/data"), sharedData);
+ TestUserFileAccessor::RestoreData shared(FilePath::fromString("/shared/data"), sharedData);
QVariantMap data;
data.insert("Version", accessor.currentVersion());
@@ -1036,7 +1043,7 @@ void ProjectExplorerPlugin::testUserFileAccessor_mergeSettingsEmptyShared()
data.insert("shared1", "bar1");
data.insert("unique1", 1234);
data.insert("shared3", "foo");
- TestUserFileAccessor::RestoreData user(FileName::fromString("/shared/data"), data);
+ TestUserFileAccessor::RestoreData user(FilePath::fromString("/shared/data"), data);
TestUserFileAccessor::RestoreData result = accessor.mergeSettings(user, shared);
diff --git a/src/plugins/projectexplorer/userfileaccessor.h b/src/plugins/projectexplorer/userfileaccessor.h
index 6544de987e..6b7d42ec1a 100644
--- a/src/plugins/projectexplorer/userfileaccessor.h
+++ b/src/plugins/projectexplorer/userfileaccessor.h
@@ -47,9 +47,9 @@ public:
virtual QVariant retrieveSharedSettings() const;
- Utils::FileName projectUserFile() const;
- Utils::FileName externalUserFile() const;
- Utils::FileName sharedFile() const;
+ Utils::FilePath projectUserFile() const;
+ Utils::FilePath externalUserFile() const;
+ Utils::FilePath sharedFile() const;
protected:
QVariantMap postprocessMerge(const QVariantMap &main,
diff --git a/src/plugins/projectexplorer/waitforstopdialog.h b/src/plugins/projectexplorer/waitforstopdialog.h
index d8c0037712..47c960dba8 100644
--- a/src/plugins/projectexplorer/waitforstopdialog.h
+++ b/src/plugins/projectexplorer/waitforstopdialog.h
@@ -29,7 +29,7 @@
#include <QDialog>
#include <QTime>
-#include "runconfiguration.h"
+#include "runcontrol.h"
QT_BEGIN_NAMESPACE
class QLabel;
diff --git a/src/plugins/projectexplorer/xcodebuildparser.cpp b/src/plugins/projectexplorer/xcodebuildparser.cpp
index a96d4bb097..ae551e259c 100644
--- a/src/plugins/projectexplorer/xcodebuildparser.cpp
+++ b/src/plugins/projectexplorer/xcodebuildparser.cpp
@@ -73,7 +73,7 @@ void XcodebuildParser::stdOutput(const QString &line)
Task task(Task::Warning,
QCoreApplication::translate("ProjectExplorer::XcodebuildParser",
"Replacing signature"),
- Utils::FileName::fromString(
+ Utils::FilePath::fromString(
lne.left(lne.size() - QLatin1String(signatureChangeEndsWithPattern).size())), /* filename */
-1, /* line */
Constants::TASK_CATEGORY_COMPILE);
@@ -96,7 +96,7 @@ void XcodebuildParser::stdError(const QString &line)
Task task(Task::Error,
QCoreApplication::translate("ProjectExplorer::XcodebuildParser",
"Xcodebuild failed."),
- Utils::FileName(), /* filename */
+ Utils::FilePath(), /* filename */
-1, /* line */
Constants::TASK_CATEGORY_COMPILE);
taskAdded(task);
@@ -139,7 +139,7 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
QTest::addColumn<ProjectExplorer::XcodebuildParser::XcodebuildStatus>("finalStatus");
@@ -147,42 +147,42 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
<< XcodebuildParser::OutsideXcodebuild
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::OutsideXcodebuild;
QTest::newRow("outside pass-through stderr")
<< XcodebuildParser::OutsideXcodebuild
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::OutsideXcodebuild;
QTest::newRow("inside pass stdout to stderr")
<< XcodebuildParser::InXcodebuild
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::InXcodebuild;
QTest::newRow("inside ignore stderr")
<< XcodebuildParser::InXcodebuild
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString()
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::InXcodebuild;
QTest::newRow("unknown pass stdout to stderr")
<< XcodebuildParser::UnknownXcodebuildState
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::UnknownXcodebuildState;
QTest::newRow("unknown ignore stderr (change?)")
<< XcodebuildParser::UnknownXcodebuildState
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString()
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::UnknownXcodebuildState;
QTest::newRow("switch outside->in->outside")
@@ -196,7 +196,7 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
"outside2")
<< OutputParserTester::STDOUT
<< QString::fromLatin1("outside\noutside2\n") << QString::fromLatin1("in xcodebuild\nin xcodebuild2\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::OutsideXcodebuild;
QTest::newRow("switch Unknown->in->outside")
@@ -208,7 +208,7 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
"outside")
<< OutputParserTester::STDOUT
<< QString::fromLatin1("outside\n") << QString::fromLatin1("unknown\nin xcodebuild\n")
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::OutsideXcodebuild;
QTest::newRow("switch in->unknown")
@@ -218,12 +218,12 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
"unknownErr")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(
Task::Error,
QCoreApplication::translate("ProjectExplorer::XcodebuildParser",
"Xcodebuild failed."),
- Utils::FileName(), /* filename */
+ Utils::FilePath(), /* filename */
-1, /* line */
Constants::TASK_CATEGORY_COMPILE))
<< QString()
@@ -235,12 +235,12 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
"unknownErr")
<< OutputParserTester::STDERR
<< QString() << QString::fromLatin1("outErr\n")
- << (QList<Task>()
+ << (Tasks()
<< Task(
Task::Error,
QCoreApplication::translate("ProjectExplorer::XcodebuildParser",
"Xcodebuild failed."),
- Utils::FileName(), /* filename */
+ Utils::FilePath(), /* filename */
-1, /* line */
Constants::TASK_CATEGORY_COMPILE))
<< QString()
@@ -249,11 +249,11 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
<< XcodebuildParser::InXcodebuild
<< QString::fromLatin1("/somepath/somefile.app: replacing existing signature") << OutputParserTester::STDOUT
<< QString() << QString()
- << (QList<Task>()
+ << (Tasks()
<< Task(Task::Warning,
QCoreApplication::translate("ProjectExplorer::XcodebuildParser",
"Replacing signature"),
- Utils::FileName::fromString(QLatin1String("/somepath/somefile.app")), /* filename */
+ Utils::FilePath::fromString(QLatin1String("/somepath/somefile.app")), /* filename */
-1, /* line */
Constants::TASK_CATEGORY_COMPILE))
<< QString()
@@ -262,7 +262,7 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing_data()
<< XcodebuildParser::OutsideXcodebuild
<< QString::fromLatin1("/somepath/somefile.app: replacing existing signature") << OutputParserTester::STDOUT
<< QString::fromLatin1("/somepath/somefile.app: replacing existing signature\n") << QString()
- << QList<Task>()
+ << Tasks()
<< QString()
<< XcodebuildParser::OutsideXcodebuild;
}
@@ -282,7 +282,7 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing()
QFETCH(OutputParserTester::Channel, inputChannel);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, outputLines);
QFETCH(ProjectExplorer::XcodebuildParser::XcodebuildStatus, finalStatus);
diff --git a/src/plugins/pythoneditor/CMakeLists.txt b/src/plugins/pythoneditor/CMakeLists.txt
new file mode 100644
index 0000000000..1f0022ca15
--- /dev/null
+++ b/src/plugins/pythoneditor/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_qtc_plugin(PythonEditor
+ PLUGIN_DEPENDS Core QtSupport ProjectExplorer TextEditor
+ SOURCES
+ pythoneditor.cpp pythoneditor.h
+ pythoneditorconstants.h
+ pythoneditorplugin.cpp pythoneditorplugin.h
+ pythonformattoken.h
+ pythonhighlighter.cpp pythonhighlighter.h
+ pythonindenter.cpp pythonindenter.h
+ pythonscanner.cpp pythonscanner.h
+)
diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp
index 4a9220b86f..d07c68cd9a 100644
--- a/src/plugins/pythoneditor/pythoneditorplugin.cpp
+++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp
@@ -39,6 +39,7 @@
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/localenvironmentaspect.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/project.h>
@@ -82,7 +83,7 @@ class PythonProject : public Project
{
Q_OBJECT
public:
- explicit PythonProject(const Utils::FileName &filename);
+ explicit PythonProject(const Utils::FilePath &filename);
bool addFiles(const QStringList &filePaths);
bool removeFiles(const QStringList &filePaths);
@@ -93,6 +94,9 @@ public:
bool needsConfiguration() const final { return false; }
bool needsBuildConfigurations() const final { return false; }
+ bool writePyProjectFile(const QString &fileName, QString &content,
+ const QStringList &rawList, QString *errorMessage);
+
private:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
bool setupTarget(Target *t) override
@@ -117,8 +121,6 @@ class PythonProjectNode : public ProjectNode
public:
PythonProjectNode(PythonProject *project);
- bool showInSimpleTree() const override;
- QString addFileFilter() const override;
bool supportsAction(ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *) override;
bool removeFiles(const QStringList &filePaths, QStringList *) override;
@@ -176,7 +178,7 @@ private:
tc.insertText('\n' + match.captured(1));
tc.insertText(match.captured(2), linkFormat(frm, match.captured(2)));
- const auto fileName = FileName::fromString(match.captured(3));
+ const auto fileName = FilePath::fromString(match.captured(3));
const int lineNumber = match.capturedRef(4).toInt();
Task task(Task::Warning,
QString(), fileName, lineNumber, id);
@@ -272,11 +274,14 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Core::Id id)
scriptAspect->setLabelText(tr("Script:"));
scriptAspect->setDisplayStyle(BaseStringAspect::LabelDisplay);
- addAspect<LocalEnvironmentAspect>(target, LocalEnvironmentAspect::BaseEnvironmentModifier());
+ addAspect<LocalEnvironmentAspect>(target);
addAspect<ArgumentsAspect>();
addAspect<TerminalAspect>();
setOutputFormatter<PythonOutputFormatter>();
+ setExecutableGetter([this] {
+ return FilePath::fromString(aspect<InterpreterAspect>()->value());
+ });
connect(target, &Target::applicationTargetsChanged,
this, &PythonRunConfiguration::updateTargetInformation);
@@ -294,11 +299,12 @@ void PythonRunConfiguration::updateTargetInformation()
Runnable PythonRunConfiguration::runnable() const
{
+ CommandLine cmd{executable(), {}};
+ cmd.addArg(mainScript());
+ cmd.addArgs(aspect<ArgumentsAspect>()->arguments(macroExpander()));
+
Runnable r;
- QtcProcess::addArg(&r.commandLineArguments, mainScript());
- QtcProcess::addArgs(&r.commandLineArguments,
- aspect<ArgumentsAspect>()->arguments(macroExpander()));
- r.executable = aspect<InterpreterAspect>()->value();
+ r.setCommandLine(cmd);
r.environment = aspect<EnvironmentAspect>()->environment();
return r;
}
@@ -310,11 +316,10 @@ public:
{
registerRunConfiguration<PythonRunConfiguration>("PythonEditor.RunConfiguration.");
addSupportedProjectType(PythonProjectId);
- addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
}
};
-PythonProject::PythonProject(const FileName &fileName) :
+PythonProject::PythonProject(const FilePath &fileName) :
Project(Constants::C_PY_MIMETYPE, fileName, [this]() { refresh(); })
{
setId(PythonProjectId);
@@ -322,7 +327,7 @@ PythonProject::PythonProject(const FileName &fileName) :
setDisplayName(fileName.toFileInfo().completeBaseName());
}
-static QStringList readLines(const Utils::FileName &projectFile)
+static QStringList readLines(const Utils::FilePath &projectFile)
{
const QString projectFileName = projectFile.fileName();
QSet<QString> visited = { projectFileName };
@@ -332,7 +337,7 @@ static QStringList readLines(const Utils::FileName &projectFile)
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
- forever {
+ while (true) {
const QString line = stream.readLine();
if (line.isNull())
break;
@@ -346,7 +351,7 @@ static QStringList readLines(const Utils::FileName &projectFile)
return lines;
}
-static QStringList readLinesJson(const Utils::FileName &projectFile,
+static QStringList readLinesJson(const Utils::FilePath &projectFile,
QString *errorMessage)
{
const QString projectFileName = projectFile.fileName();
@@ -403,15 +408,59 @@ bool PythonProject::saveRawFileList(const QStringList &rawFileList)
bool PythonProject::saveRawList(const QStringList &rawList, const QString &fileName)
{
FileChangeBlocker changeGuarg(fileName);
- // Make sure we can open the file for writing
- FileSaver saver(fileName, QIODevice::Text);
- if (!saver.hasError()) {
- QTextStream stream(saver.file());
- foreach (const QString &filePath, rawList)
- stream << filePath << '\n';
- saver.setResult(&stream);
+ bool result = false;
+
+ // New project file
+ if (fileName.endsWith(".pyproject")) {
+ FileSaver saver(fileName, QIODevice::ReadOnly | QIODevice::Text);
+ if (!saver.hasError()) {
+ QString content = QTextStream(saver.file()).readAll();
+ if (saver.finalize(ICore::mainWindow())) {
+ QString errorMessage;
+ result = writePyProjectFile(fileName, content, rawList, &errorMessage);
+ if (!errorMessage.isEmpty())
+ Core::MessageManager::write(errorMessage);
+ }
+ }
+ } else { // Old project file
+ FileSaver saver(fileName, QIODevice::WriteOnly | QIODevice::Text);
+ if (!saver.hasError()) {
+ QTextStream stream(saver.file());
+ for (const QString &filePath : rawList)
+ stream << filePath << '\n';
+ saver.setResult(&stream);
+ result = saver.finalize(ICore::mainWindow());
+ }
}
- return saver.finalize(ICore::mainWindow());
+
+ return result;
+}
+
+bool PythonProject::writePyProjectFile(const QString &fileName, QString &content,
+ const QStringList &rawList, QString *errorMessage)
+{
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ *errorMessage = PythonProject::tr("Unable to open \"%1\" for reading: %2")
+ .arg(fileName, file.errorString());
+ return false;
+ }
+
+ // Build list of files with the current rawList for the JSON file
+ QString files("[");
+ for (const QString &f : rawList)
+ if (!f.endsWith(".pyproject"))
+ files += QString("\"%1\",").arg(f);
+ files = files.left(files.lastIndexOf(',')); // Removing leading comma
+ files += ']';
+
+ // Removing everything inside square parenthesis
+ // to replace it with the new list of files for the JSON file.
+ QRegularExpression pattern(R"(\[.*\])");
+ content.replace(pattern, files);
+ file.write(content.toUtf8());
+
+ return true;
}
bool PythonProject::addFiles(const QStringList &filePaths)
@@ -419,20 +468,17 @@ bool PythonProject::addFiles(const QStringList &filePaths)
QStringList newList = m_rawFileList;
const QDir baseDir(projectDirectory().toString());
- foreach (const QString &filePath, filePaths)
+ for (const QString &filePath : filePaths)
newList.append(baseDir.relativeFilePath(filePath));
- const bool result = saveRawList(newList, projectFilePath().toString());
- refresh();
-
- return result;
+ return saveRawFileList(newList);
}
bool PythonProject::removeFiles(const QStringList &filePaths)
{
QStringList newList = m_rawFileList;
- foreach (const QString &filePath, filePaths) {
+ for (const QString &filePath : filePaths) {
const QHash<QString, QString>::iterator i = m_rawListEntries.find(filePath);
if (i != m_rawListEntries.end())
newList.removeOne(i.value());
@@ -445,7 +491,7 @@ bool PythonProject::setFiles(const QStringList &filePaths)
{
QStringList newList;
const QDir baseDir(projectDirectory().toString());
- foreach (const QString &filePath, filePaths)
+ for (const QString &filePath : filePaths)
newList.append(baseDir.relativeFilePath(filePath));
return saveRawFileList(newList);
@@ -470,7 +516,7 @@ bool PythonProject::renameFile(const QString &filePath, const QString &newFilePa
void PythonProject::parseProject()
{
m_rawListEntries.clear();
- const Utils::FileName filePath = projectFilePath();
+ const Utils::FilePath filePath = projectFilePath();
// The PySide project file is JSON based
if (filePath.endsWith(".pyproject")) {
QString errorMessage;
@@ -492,9 +538,9 @@ void PythonProject::parseProject()
class PythonFileNode : public FileNode
{
public:
- PythonFileNode(const Utils::FileName &filePath, const QString &nodeDisplayName,
+ PythonFileNode(const Utils::FilePath &filePath, const QString &nodeDisplayName,
FileType fileType = FileType::Source)
- : FileNode(filePath, fileType, false)
+ : FileNode(filePath, fileType)
, m_displayName(nodeDisplayName)
{}
@@ -509,20 +555,20 @@ void PythonProject::refresh(Target *target)
parseProject();
const QDir baseDir(projectDirectory().toString());
- BuildTargetInfoList appTargets;
+ QList<BuildTargetInfo> appTargets;
auto newRoot = std::make_unique<PythonProjectNode>(this);
for (const QString &f : qAsConst(m_files)) {
const QString displayName = baseDir.relativeFilePath(f);
const FileType fileType = f.endsWith(".pyproject") || f.endsWith(".pyqtc") ? FileType::Project
: FileType::Source;
- newRoot->addNestedNode(std::make_unique<PythonFileNode>(FileName::fromString(f),
+ newRoot->addNestedNode(std::make_unique<PythonFileNode>(FilePath::fromString(f),
displayName, fileType));
if (fileType == FileType::Source) {
BuildTargetInfo bti;
bti.buildKey = f;
- bti.targetFilePath = FileName::fromString(f);
+ bti.targetFilePath = FilePath::fromString(f);
bti.projectFilePath = projectFilePath();
- appTargets.list.append(bti);
+ appTargets.append(bti);
}
}
setRootProjectNode(std::move(newRoot));
@@ -569,14 +615,14 @@ QStringList PythonProject::processEntries(const QStringList &paths,
QFileInfo fileInfo;
QStringList absolutePaths;
- foreach (const QString &path, paths) {
+ for (const QString &path : paths) {
QString trimmedPath = path.trimmed();
if (trimmedPath.isEmpty())
continue;
expandEnvironmentVariables(env, trimmedPath);
- trimmedPath = FileName::fromUserInput(trimmedPath).toString();
+ trimmedPath = FilePath::fromUserInput(trimmedPath).toString();
fileInfo.setFile(projectDir, trimmedPath);
if (fileInfo.exists()) {
@@ -609,6 +655,7 @@ PythonProjectNode::PythonProjectNode(PythonProject *project)
, m_project(project)
{
setDisplayName(project->projectFilePath().toFileInfo().completeBaseName());
+ setAddFileFilter("*.py");
}
QHash<QString, QStringList> sortFilesIntoPaths(const QString &base, const QSet<QString> &files)
@@ -616,13 +663,13 @@ QHash<QString, QStringList> sortFilesIntoPaths(const QString &base, const QSet<Q
QHash<QString, QStringList> filesInPath;
const QDir baseDir(base);
- foreach (const QString &absoluteFileName, files) {
+ for (const QString &absoluteFileName : files) {
const QFileInfo fileInfo(absoluteFileName);
- const FileName absoluteFilePath = FileName::fromString(fileInfo.path());
+ const FilePath absoluteFilePath = FilePath::fromString(fileInfo.path());
QString relativeFilePath;
if (absoluteFilePath.isChildOf(baseDir)) {
- relativeFilePath = absoluteFilePath.relativeChildPath(FileName::fromString(base)).toString();
+ relativeFilePath = absoluteFilePath.relativeChildPath(FilePath::fromString(base)).toString();
} else {
// 'file' is not part of the project.
relativeFilePath = baseDir.relativeFilePath(absoluteFilePath.toString());
@@ -635,30 +682,18 @@ QHash<QString, QStringList> sortFilesIntoPaths(const QString &base, const QSet<Q
return filesInPath;
}
-bool PythonProjectNode::showInSimpleTree() const
-{
- return true;
-}
-
-QString PythonProjectNode::addFileFilter() const
-{
- return QLatin1String("*.py");
-}
-
bool PythonProjectNode::supportsAction(ProjectAction action, const Node *node) const
{
- switch (node->nodeType()) {
- case NodeType::File:
+ if (node->asFileNode()) {
return action == ProjectAction::Rename
|| action == ProjectAction::RemoveFile;
- case NodeType::Folder:
- case NodeType::Project:
+ }
+ if (node->isFolderNodeType() || node->isProjectNodeType()) {
return action == ProjectAction::AddNewFile
|| action == ProjectAction::RemoveFile
|| action == ProjectAction::AddExistingFile;
- default:
- return ProjectNode::supportsAction(action, node);
}
+ return ProjectNode::supportsAction(action, node);
}
bool PythonProjectNode::addFiles(const QStringList &filePaths, QStringList *)
@@ -692,6 +727,7 @@ class PythonEditorPluginPrivate
public:
PythonEditorFactory editorFactory;
PythonRunConfigurationFactory runConfigFactory;
+ SimpleRunWorkerFactory<SimpleTargetRunner, PythonRunConfiguration> runWorkerFactory;
};
PythonEditorPlugin::~PythonEditorPlugin()
@@ -713,11 +749,10 @@ bool PythonEditorPlugin::initialize(const QStringList &arguments, QString *error
void PythonEditorPlugin::extensionsInitialized()
{
- // Initialize editor actions handler
// Add MIME overlay icons (these icons displayed at Project dock panel)
- const QIcon icon = QIcon::fromTheme(C_PY_MIME_ICON);
- if (!icon.isNull())
- Core::FileIconProvider::registerIconOverlayForMimeType(icon, C_PY_MIMETYPE);
+ QString imageFile = creatorTheme()->imageFile(Theme::IconOverlayPro,
+ ProjectExplorer::Constants::FILEOVERLAY_PY);
+ FileIconProvider::registerIconOverlayForSuffix(imageFile, "py");
TaskHub::addCategory(PythonErrorTaskCategory, "Python", true);
}
diff --git a/src/plugins/qbsprojectmanager/CMakeLists.txt b/src/plugins/qbsprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..e02a516f1a
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/CMakeLists.txt
@@ -0,0 +1,38 @@
+find_package(Qbs)
+
+add_qtc_plugin(QbsProjectManager
+ CONDITION TARGET Qbs::QbsCore
+ DEPENDS Qbs::QbsCore Qt5::Widgets qmljs
+ DEFINES
+ QBS_INSTALL_DIR="${QBS_INSTALL_DIR}"
+ IDE_LIBRARY_BASENAME="${IDE_LIBRARY_BASE_PATH}"
+ PLUGIN_DEPENDS Core ProjectExplorer CppTools QtSupport QmlJSTools
+ SOURCES
+ customqbspropertiesdialog.cpp customqbspropertiesdialog.h customqbspropertiesdialog.ui
+ defaultpropertyprovider.cpp defaultpropertyprovider.h
+ propertyprovider.h
+ qbsbuildconfiguration.cpp qbsbuildconfiguration.h
+ qbsbuildstep.cpp qbsbuildstep.h
+ qbsbuildstepconfigwidget.ui
+ qbscleanstep.cpp qbscleanstep.h
+ qbscleanstepconfigwidget.ui
+ qbsinstallstep.cpp qbsinstallstep.h
+ qbsinstallstepconfigwidget.ui
+ qbskitinformation.cpp qbskitinformation.h
+ qbslogsink.cpp qbslogsink.h
+ qbsnodes.cpp qbsnodes.h
+ qbsnodetreebuilder.cpp qbsnodetreebuilder.h
+ qbsparser.cpp qbsparser.h
+ qbspmlogging.cpp qbspmlogging.h
+ qbsprofilessettingspage.cpp qbsprofilessettingspage.h
+ qbsprofilessettingswidget.ui
+ qbsproject.cpp qbsproject.h
+ qbsprojectimporter.cpp qbsprojectimporter.h
+ qbsprojectmanager.cpp qbsprojectmanager.h qbsprojectmanager.qrc
+ qbsprojectmanager_global.h
+ qbsprojectmanagerconstants.h
+ qbsprojectmanagerplugin.cpp qbsprojectmanagerplugin.h
+ qbsprojectmanagersettings.cpp qbsprojectmanagersettings.h
+ qbsprojectparser.cpp qbsprojectparser.h
+ qbsrunconfiguration.cpp qbsrunconfiguration.h
+)
diff --git a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp
index a014d7a758..1444c3d98f 100644
--- a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp
+++ b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp
@@ -29,18 +29,21 @@
#include "qbsprojectmanagerconstants.h"
#include <coreplugin/messagemanager.h>
+#include <baremetal/baremetalconstants.h>
#include <projectexplorer/abi.h>
#include <projectexplorer/gcctoolchain.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/msvctoolchain.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <qbs.h>
+#include <android/androidconstants.h>
#include <ios/iosconstants.h>
#include <winrt/winrtconstants.h>
@@ -76,7 +79,7 @@ static QString extractToolchainPrefix(QString *compilerName)
static QString targetPlatform(const ProjectExplorer::Abi &abi, const ProjectExplorer::Kit *k)
{
- const Core::Id device = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(k);
+ const Core::Id device = ProjectExplorer::DeviceTypeKitAspect::deviceTypeId(k);
switch (abi.os()) {
case ProjectExplorer::Abi::WindowsOS:
return QLatin1String("windows");
@@ -122,14 +125,26 @@ static QString targetPlatform(const ProjectExplorer::Abi &abi, const ProjectExpl
static QStringList toolchainList(const ProjectExplorer::ToolChain *tc)
{
QStringList list;
- if (tc->typeId() == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID)
+ if (tc->typeId() == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID
+ || (tc->typeId() == Android::Constants::ANDROID_TOOLCHAIN_ID
+ && tc->compilerCommand().toString().contains("clang"))) {
list << QLatin1String("clang") << QLatin1String("llvm") << QLatin1String("gcc");
- else if (tc->typeId() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID)
+ } else if (tc->typeId() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID
+ || tc->typeId() == Android::Constants::ANDROID_TOOLCHAIN_ID) {
list << QLatin1String("gcc"); // TODO: Detect llvm-gcc
- else if (tc->typeId() == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID)
+ } else if (tc->typeId() == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) {
list << QLatin1String("mingw") << QLatin1String("gcc");
- else if (tc->typeId() == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
+ } else if (tc->typeId() == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) {
+ list << QLatin1String("clang-cl") << QLatin1String("msvc");
+ } else if (tc->typeId() == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
list << QLatin1String("msvc");
+ } else if (tc->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID) {
+ list << QLatin1String("iar");
+ } else if (tc->typeId() == BareMetal::Constants::KEIL_TOOLCHAIN_TYPEID) {
+ list << QLatin1String("keil");
+ } else if (tc->typeId() == BareMetal::Constants::SDCC_TOOLCHAIN_TYPEID) {
+ list << QLatin1String("sdcc");
+ }
return list;
}
@@ -138,6 +153,22 @@ static QString architecture(const ProjectExplorer::Abi &targetAbi)
if (targetAbi.architecture() != ProjectExplorer::Abi::UnknownArchitecture) {
QString architecture = ProjectExplorer::Abi::toString(targetAbi.architecture());
+ if (targetAbi.osFlavor() == ProjectExplorer::Abi::AndroidLinuxFlavor) {
+ switch (targetAbi.architecture()) {
+ case ProjectExplorer::Abi::X86Architecture:
+ if (targetAbi.wordWidth() == 64)
+ architecture += "_64";
+ return architecture;
+ case ProjectExplorer::Abi::ArmArchitecture:
+ if (targetAbi.wordWidth() == 64)
+ architecture += "64";
+ else
+ architecture += "v7a";
+ return architecture;
+ default:
+ break;
+ }
+ }
// We have to be conservative tacking on suffixes to arch names because an arch that is
// already 64-bit may get an incorrect name as a result (i.e. Itanium)
if (targetAbi.wordWidth() == 64) {
@@ -195,7 +226,7 @@ QVariantMap DefaultPropertyProvider::properties(const ProjectExplorer::Kit *k,
{
QTC_ASSERT(k, return defaultData);
QVariantMap data = autoGeneratedProperties(k, defaultData);
- const QVariantMap customProperties = QbsKitInformation::properties(k);
+ const QVariantMap customProperties = QbsKitAspect::properties(k);
for (QVariantMap::ConstIterator it = customProperties.constBegin();
it != customProperties.constEnd(); ++it) {
data.insert(it.key(), it.value());
@@ -222,14 +253,14 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
{
QVariantMap data = defaultData;
- const QString sysroot = ProjectExplorer::SysRootKitInformation::sysRoot(k).toUserOutput();
+ const QString sysroot = ProjectExplorer::SysRootKitAspect::sysRoot(k).toUserOutput();
if (!sysroot.isEmpty())
data.insert(QLatin1String(QBS_SYSROOT), sysroot);
ProjectExplorer::ToolChain *tcC
- = ProjectExplorer::ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID);
+ = ProjectExplorer::ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID);
ProjectExplorer::ToolChain *tcCxx
- = ProjectExplorer::ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ = ProjectExplorer::ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!tcC && !tcCxx)
return data;
@@ -241,101 +272,119 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
if (!archs.isEmpty())
data.insert(QLatin1String(QBS_ARCHITECTURES), archs);
if (mainTc->targetAbi() !=
- ProjectExplorer::Abi::abiFromTargetTriplet(mainTc->originalTargetTriple())) {
+ ProjectExplorer::Abi::abiFromTargetTriplet(mainTc->originalTargetTriple())
+ || targetAbi.osFlavor() == ProjectExplorer::Abi::AndroidLinuxFlavor) {
data.insert(QLatin1String(QBS_ARCHITECTURE), architecture(mainTc->targetAbi()));
}
data.insert(QLatin1String(QBS_TARGETPLATFORM), targetPlatform(targetAbi, k));
QStringList toolchain = toolchainList(mainTc);
-
- Utils::FileName cCompilerPath;
- if (tcC)
- cCompilerPath = tcC->compilerCommand();
-
- Utils::FileName cxxCompilerPath;
- if (tcCxx)
- cxxCompilerPath = tcCxx->compilerCommand();
-
- const QFileInfo cFileInfo = cCompilerPath.toFileInfo();
- const QFileInfo cxxFileInfo = cxxCompilerPath.toFileInfo();
- QString cCompilerName = cFileInfo.fileName();
- QString cxxCompilerName = cxxFileInfo.fileName();
- const QString cToolchainPrefix = extractToolchainPrefix(&cCompilerName);
- const QString cxxToolchainPrefix = extractToolchainPrefix(&cxxCompilerName);
-
- QFileInfo mainFileInfo;
- QString mainCompilerName;
- QString mainToolchainPrefix;
- if (tcCxx) {
- mainFileInfo = cxxFileInfo;
- mainCompilerName = cxxCompilerName;
- mainToolchainPrefix = cxxToolchainPrefix;
+ if (targetAbi.osFlavor() == ProjectExplorer::Abi::AndroidLinuxFlavor) {
+ const ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitAspect::device(k);
+ if (dev) {
+ const QString sdkDir = k->value(Android::Constants::ANDROID_KIT_SDK).toString();
+ if (!sdkDir.isEmpty())
+ data.insert("Android.sdk.sdkDir", sdkDir);
+ const QString ndkDir = k->value(Android::Constants::ANDROID_KIT_NDK).toString();
+ if (!ndkDir.isEmpty()) {
+ data.insert("Android.sdk.ndkDir", ndkDir);
+ data.insert("Android.ndk.ndkDir", ndkDir);
+ }
+ }
} else {
- mainFileInfo = cFileInfo;
- mainCompilerName = cCompilerName;
- mainToolchainPrefix = cToolchainPrefix;
- }
+ Utils::FilePath cCompilerPath;
+ if (tcC)
+ cCompilerPath = tcC->compilerCommand();
+
+ Utils::FilePath cxxCompilerPath;
+ if (tcCxx)
+ cxxCompilerPath = tcCxx->compilerCommand();
+
+ const QFileInfo cFileInfo = cCompilerPath.toFileInfo();
+ const QFileInfo cxxFileInfo = cxxCompilerPath.toFileInfo();
+ QString cCompilerName = cFileInfo.fileName();
+ QString cxxCompilerName = cxxFileInfo.fileName();
+ const QString cToolchainPrefix = extractToolchainPrefix(&cCompilerName);
+ const QString cxxToolchainPrefix = extractToolchainPrefix(&cxxCompilerName);
+
+ QFileInfo mainFileInfo;
+ QString mainCompilerName;
+ QString mainToolchainPrefix;
+ if (tcCxx) {
+ mainFileInfo = cxxFileInfo;
+ mainCompilerName = cxxCompilerName;
+ mainToolchainPrefix = cxxToolchainPrefix;
+ } else {
+ mainFileInfo = cFileInfo;
+ mainCompilerName = cCompilerName;
+ mainToolchainPrefix = cToolchainPrefix;
+ }
- if (!mainToolchainPrefix.isEmpty())
- data.insert(QLatin1String(CPP_TOOLCHAINPREFIX), mainToolchainPrefix);
+ if (!mainToolchainPrefix.isEmpty())
+ data.insert(QLatin1String(CPP_TOOLCHAINPREFIX), mainToolchainPrefix);
- if (toolchain.contains(QLatin1String("msvc"))) {
- data.insert(QLatin1String(CPP_COMPILERNAME), mainCompilerName);
- } else {
- if (!mainCompilerName.isEmpty())
+ if (toolchain.contains(QLatin1String("clang-cl"))) {
data.insert(QLatin1String(CPP_COMPILERNAME), mainCompilerName);
- if (!cCompilerName.isEmpty())
- data.insert(QLatin1String(CPP_CCOMPILERNAME), cCompilerName);
- if (!cxxCompilerName.isEmpty())
- data.insert(QLatin1String(CPP_CXXCOMPILERNAME), cxxCompilerName);
- }
-
- if (tcC && tcCxx && cFileInfo.absolutePath() != cxxFileInfo.absolutePath()) {
- Core::MessageManager::write(tr("C and C++ compiler paths differ. C compiler may not work."),
- Core::MessageManager::ModeSwitch);
- }
- data.insert(QLatin1String(CPP_TOOLCHAINPATH), mainFileInfo.absolutePath());
+ const auto clangClToolchain =
+ static_cast<ProjectExplorer::Internal::ClangClToolChain *>(mainTc);
+ data.insert(QLatin1String(CPP_VCVARSALLPATH), clangClToolchain->varsBat());
+ } else if (toolchain.contains(QLatin1String("msvc"))) {
+ data.insert(QLatin1String(CPP_COMPILERNAME), mainCompilerName);
+ } else {
+ if (!mainCompilerName.isEmpty())
+ data.insert(QLatin1String(CPP_COMPILERNAME), mainCompilerName);
+ if (!cCompilerName.isEmpty())
+ data.insert(QLatin1String(CPP_CCOMPILERNAME), cCompilerName);
+ if (!cxxCompilerName.isEmpty())
+ data.insert(QLatin1String(CPP_CXXCOMPILERNAME), cxxCompilerName);
+ }
- if (auto gcc = dynamic_cast<ProjectExplorer::GccToolChain *>(mainTc)) {
- QStringList compilerFlags = gcc->platformCodeGenFlags();
- filterCompilerLinkerFlags(targetAbi, compilerFlags);
- data.insert(QLatin1String(CPP_PLATFORMCOMMONCOMPILERFLAGS), compilerFlags);
+ if (tcC && tcCxx && cFileInfo.absolutePath() != cxxFileInfo.absolutePath()) {
+ Core::MessageManager::write(tr("C and C++ compiler paths differ. C compiler may not work."),
+ Core::MessageManager::ModeSwitch);
+ }
+ data.insert(QLatin1String(CPP_TOOLCHAINPATH), mainFileInfo.absolutePath());
- QStringList linkerFlags = gcc->platformLinkerFlags();
- filterCompilerLinkerFlags(targetAbi, linkerFlags);
- data.insert(QLatin1String(CPP_PLATFORMLINKERFLAGS), linkerFlags);
- }
+ if (auto gcc = dynamic_cast<ProjectExplorer::GccToolChain *>(mainTc)) {
+ QStringList compilerFlags = gcc->platformCodeGenFlags();
+ filterCompilerLinkerFlags(targetAbi, compilerFlags);
+ data.insert(QLatin1String(CPP_PLATFORMCOMMONCOMPILERFLAGS), compilerFlags);
- if (targetAbi.os() == ProjectExplorer::Abi::DarwinOS) {
- // Reverse engineer the Xcode developer path from the compiler path
- const QRegularExpression compilerRe(
- QStringLiteral("^(?<developerpath>.*)/Toolchains/(?:.+)\\.xctoolchain/usr/bin$"));
- const QRegularExpressionMatch compilerReMatch = compilerRe.match(cxxFileInfo.absolutePath());
- if (compilerReMatch.hasMatch()) {
- const QString developerPath = compilerReMatch.captured(QStringLiteral("developerpath"));
- data.insert(QLatin1String(XCODE_DEVELOPERPATH), developerPath);
- toolchain.insert(0, QStringLiteral("xcode"));
-
- // If the sysroot is part of this developer path, set the canonical SDK name
- const QDir sysrootdir(QDir::cleanPath(sysroot));
- const QString sysrootAbs = sysrootdir.absolutePath();
- const QSettings sdkSettings(
- sysrootdir.absoluteFilePath(QStringLiteral("SDKSettings.plist")),
- QSettings::NativeFormat);
- const QString version(
- sdkSettings.value(QStringLiteral("Version")).toString());
- QString canonicalName(
- sdkSettings.value(QStringLiteral("CanonicalName")).toString());
- canonicalName.chop(version.size());
- if (!canonicalName.isEmpty() && !version.isEmpty()
- && sysrootAbs.startsWith(developerPath)) {
- if (sysrootAbs.endsWith(QStringLiteral("/%1.sdk").arg(canonicalName + version),
- Qt::CaseInsensitive)) {
- data.insert(QLatin1String(XCODE_SDK), QString(canonicalName + version));
- }
- if (sysrootAbs.endsWith(QStringLiteral("/%1.sdk").arg(canonicalName),
- Qt::CaseInsensitive)) {
- data.insert(QLatin1String(XCODE_SDK), canonicalName);
+ QStringList linkerFlags = gcc->platformLinkerFlags();
+ filterCompilerLinkerFlags(targetAbi, linkerFlags);
+ data.insert(QLatin1String(CPP_PLATFORMLINKERFLAGS), linkerFlags);
+ }
+ if (targetAbi.os() == ProjectExplorer::Abi::DarwinOS) {
+ // Reverse engineer the Xcode developer path from the compiler path
+ const QRegularExpression compilerRe(
+ QStringLiteral("^(?<developerpath>.*)/Toolchains/(?:.+)\\.xctoolchain/usr/bin$"));
+ const QRegularExpressionMatch compilerReMatch = compilerRe.match(cxxFileInfo.absolutePath());
+ if (compilerReMatch.hasMatch()) {
+ const QString developerPath = compilerReMatch.captured(QStringLiteral("developerpath"));
+ data.insert(QLatin1String(XCODE_DEVELOPERPATH), developerPath);
+ toolchain.insert(0, QStringLiteral("xcode"));
+
+ // If the sysroot is part of this developer path, set the canonical SDK name
+ const QDir sysrootdir(QDir::cleanPath(sysroot));
+ const QString sysrootAbs = sysrootdir.absolutePath();
+ const QSettings sdkSettings(
+ sysrootdir.absoluteFilePath(QStringLiteral("SDKSettings.plist")),
+ QSettings::NativeFormat);
+ const QString version(
+ sdkSettings.value(QStringLiteral("Version")).toString());
+ QString canonicalName(
+ sdkSettings.value(QStringLiteral("CanonicalName")).toString());
+ canonicalName.chop(version.size());
+ if (!canonicalName.isEmpty() && !version.isEmpty()
+ && sysrootAbs.startsWith(developerPath)) {
+ if (sysrootAbs.endsWith(QStringLiteral("/%1.sdk").arg(canonicalName + version),
+ Qt::CaseInsensitive)) {
+ data.insert(QLatin1String(XCODE_SDK), QString(canonicalName + version));
+ }
+ if (sysrootAbs.endsWith(QStringLiteral("/%1.sdk").arg(canonicalName),
+ Qt::CaseInsensitive)) {
+ data.insert(QLatin1String(XCODE_SDK), canonicalName);
+ }
}
}
}
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
index 43ac1608f6..f3fd3d9f56 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
@@ -25,7 +25,6 @@
#include "qbsbuildconfiguration.h"
-#include "qbsbuildconfigurationwidget.h"
#include "qbsbuildstep.h"
#include "qbscleanstep.h"
#include "qbsinstallstep.h"
@@ -34,7 +33,6 @@
#include "qbsprojectmanagersettings.h"
#include <coreplugin/documentmanager.h>
-#include <coreplugin/icore.h>
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildsteplist.h>
@@ -54,7 +52,6 @@
#include <utils/qtcprocess.h>
#include <QCoreApplication>
-#include <QInputDialog>
using namespace ProjectExplorer;
using namespace Utils;
@@ -62,17 +59,15 @@ using namespace Utils;
namespace QbsProjectManager {
namespace Internal {
-static QString configNameKey() { return QStringLiteral("Qbs.configName"); }
-
-static FileName defaultBuildDirectory(const QString &projectFilePath, const Kit *k,
+static FilePath defaultBuildDirectory(const QString &projectFilePath, const Kit *k,
const QString &bcName,
BuildConfiguration::BuildType buildType)
{
const QString projectName = QFileInfo(projectFilePath).completeBaseName();
ProjectMacroExpander expander(projectFilePath, projectName, k, bcName, buildType);
- QString projectDir = Project::projectDirectory(FileName::fromString(projectFilePath)).toString();
+ QString projectDir = Project::projectDirectory(FilePath::fromString(projectFilePath)).toString();
QString buildPath = expander.expand(ProjectExplorerPlugin::buildDirectoryTemplate());
- return FileName::fromString(FileUtils::resolvePath(projectDir, buildPath));
+ return FilePath::fromString(FileUtils::resolvePath(projectDir, buildPath));
}
// ---------------------------------------------------------------------------
@@ -82,6 +77,15 @@ static FileName defaultBuildDirectory(const QString &projectFilePath, const Kit
QbsBuildConfiguration::QbsBuildConfiguration(Target *target, Core::Id id)
: BuildConfiguration(target, id)
{
+ setConfigWidgetHasFrame(true);
+
+ m_configurationName = addAspect<BaseStringAspect>();
+ m_configurationName->setLabelText(tr("Configuration name:"));
+ m_configurationName->setSettingsKey("Qbs.configName");
+ m_configurationName->setDisplayStyle(BaseStringAspect::LineEditDisplay);
+ connect(m_configurationName, &BaseStringAspect::changed,
+ this, &BuildConfiguration::buildDirectoryChanged);
+
connect(project(), &Project::parsingStarted, this, &BuildConfiguration::enabledChanged);
connect(project(), &Project::parsingFinished, this, &BuildConfiguration::enabledChanged);
}
@@ -96,7 +100,7 @@ void QbsBuildConfiguration::initialize(const BuildInfo &info)
? QLatin1String(Constants::QBS_VARIANT_DEBUG)
: QLatin1String(Constants::QBS_VARIANT_RELEASE));
- Utils::FileName buildDir = info.buildDirectory;
+ Utils::FilePath buildDir = info.buildDirectory;
if (buildDir.isEmpty())
buildDir = defaultBuildDirectory(target()->project()->projectFilePath().toString(),
target()->kit(), info.displayName, info.buildType);
@@ -109,7 +113,8 @@ void QbsBuildConfiguration::initialize(const BuildInfo &info)
configName = "qtc_" + target()->kit()->fileSystemFriendlyName() + '_'
+ Utils::FileUtils::fileSystemFriendlyName(info.displayName);
}
- setConfigurationName(configName);
+
+ m_configurationName->setValue(configName);
BuildStepList *buildSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
auto bs = new QbsBuildStep(buildSteps);
@@ -121,7 +126,6 @@ void QbsBuildConfiguration::initialize(const BuildInfo &info)
BuildStepList *cleanSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN);
cleanSteps->appendStep(new QbsCleanStep(cleanSteps));
- connect(bs, &QbsBuildStep::qbsConfigurationChanged, this, &QbsBuildConfiguration::qbsConfigurationChanged);
emit qbsConfigurationChanged();
}
@@ -130,36 +134,16 @@ bool QbsBuildConfiguration::fromMap(const QVariantMap &map)
if (!BuildConfiguration::fromMap(map))
return false;
- m_configurationName = map.value(configNameKey()).toString();
- if (m_configurationName.isEmpty()) { // pre-4.4 backwards compatibility
+ if (m_configurationName->value().isEmpty()) { // pre-4.4 backwards compatibility
const QString profileName = QbsManager::profileForKit(target()->kit());
const QString buildVariant = qbsConfiguration()
.value(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)).toString();
- m_configurationName = profileName + QLatin1Char('-') + buildVariant;
- }
- BuildStepList *bsl = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
- // Fix up the existing build steps:
- for (int i = 0; i < bsl->count(); ++i) {
- auto bs = qobject_cast<QbsBuildStep *>(bsl->at(i));
- if (bs)
- connect(bs, &QbsBuildStep::qbsConfigurationChanged, this, &QbsBuildConfiguration::qbsConfigurationChanged);
+ m_configurationName->setValue(profileName + '-' + buildVariant);
}
return true;
}
-QVariantMap QbsBuildConfiguration::toMap() const
-{
- QVariantMap map = BuildConfiguration::toMap();
- map.insert(configNameKey(), m_configurationName);
- return map;
-}
-
-NamedWidget *QbsBuildConfiguration::createConfigWidget()
-{
- return new QbsBuildConfigurationWidget(this);
-}
-
QbsBuildStep *QbsBuildConfiguration::qbsStep() const
{
return stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)->firstOfType<QbsBuildStep>();
@@ -236,22 +220,9 @@ QStringList QbsBuildConfiguration::products() const
return m_products;
}
-void QbsBuildConfiguration::emitBuildTypeChanged()
-{
- emit buildTypeChanged();
-}
-
-void QbsBuildConfiguration::setConfigurationName(const QString &configName)
-{
- if (m_configurationName == configName)
- return;
- m_configurationName = configName;
- emit buildDirectoryChanged();
-}
-
QString QbsBuildConfiguration::configurationName() const
{
- return m_configurationName;
+ return m_configurationName->value();
}
class StepProxy
@@ -312,7 +283,7 @@ public:
return m_qbsBuildStep ? m_qbsBuildStep->maxJobs() : 0;
}
- Utils::FileName installRoot() const {
+ Utils::FilePath installRoot() const {
const QbsBuildStep *bs = nullptr;
if (m_qbsBuildStep) {
bs = m_qbsBuildStep;
@@ -322,7 +293,7 @@ public:
}
if (bs && bs->hasCustomInstallRoot())
return bs->installRoot();
- return Utils::FileName();
+ return Utils::FilePath();
}
private:
@@ -333,60 +304,53 @@ private:
QString QbsBuildConfiguration::equivalentCommandLine(const BuildStep *buildStep) const
{
- QString commandLine;
+ CommandLine commandLine;
const QString qbsInstallDir = QString::fromLocal8Bit(qgetenv("QBS_INSTALL_DIR"));
- const QString qbsFilePath = Utils::HostOsInfo::withExecutableSuffix(!qbsInstallDir.isEmpty()
+ const QString qbsFilePath = HostOsInfo::withExecutableSuffix(!qbsInstallDir.isEmpty()
? qbsInstallDir + QLatin1String("/bin/qbs")
: QCoreApplication::applicationDirPath() + QLatin1String("/qbs"));
- Utils::QtcProcess::addArg(&commandLine, QDir::toNativeSeparators(qbsFilePath));
+ commandLine.addArg(QDir::toNativeSeparators(qbsFilePath));
const StepProxy stepProxy(buildStep);
- Utils::QtcProcess::addArg(&commandLine, stepProxy.command());
+ commandLine.addArg(stepProxy.command());
const QString buildDir = buildDirectory().toUserOutput();
- Utils::QtcProcess::addArgs(&commandLine, QStringList({"-d", buildDir}));
- Utils::QtcProcess::addArgs(&commandLine, QStringList("-f")
- << buildStep->project()->projectFilePath().toUserOutput());
+ commandLine.addArgs({"-d", buildDir});
+ commandLine.addArgs({"-f", buildStep->project()->projectFilePath().toUserOutput()});
if (QbsProjectManagerSettings::useCreatorSettingsDirForQbs()) {
- Utils::QtcProcess::addArgs(&commandLine, QStringList({"--settings-dir",
- QDir::toNativeSeparators(QbsProjectManagerSettings::qbsSettingsBaseDir())}));
+ commandLine.addArgs({"--settings-dir",
+ QDir::toNativeSeparators(QbsProjectManagerSettings::qbsSettingsBaseDir())});
}
if (stepProxy.dryRun())
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("--dry-run"));
+ commandLine.addArg("--dry-run");
if (stepProxy.keepGoing())
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("--keep-going"));
+ commandLine.addArg("--keep-going");
if (stepProxy.forceProbeExecution())
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("--force-probe-execution"));
+ commandLine.addArg("--force-probe-execution");
if (stepProxy.showCommandLines())
- Utils::QtcProcess::addArgs(&commandLine, QStringList({"--command-echo-mode",
- "command-line"}));
+ commandLine.addArgs({"--command-echo-mode", "command-line"});
if (stepProxy.noInstall())
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("--no-install"));
+ commandLine.addArg("--no-install");
if (stepProxy.noBuild())
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("--no-build"));
+ commandLine.addArg("--no-build");
if (stepProxy.cleanInstallRoot())
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("--clean-install-root"));
+ commandLine.addArg("--clean-install-root");
const int jobCount = stepProxy.jobCount();
- if (jobCount > 0) {
- Utils::QtcProcess::addArgs(&commandLine, QStringList({"--jobs",
- QString::number(jobCount)}));
- }
+ if (jobCount > 0)
+ commandLine.addArgs({"--jobs", QString::number(jobCount)});
+
const QString profileName = QbsManager::profileForKit(buildStep->target()->kit());
const QString buildVariant = qbsConfiguration()
.value(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)).toString();
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("config:") + configurationName());
- Utils::QtcProcess::addArg(&commandLine, QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)
- + QLatin1Char(':') + buildVariant);
- const Utils::FileName installRoot = stepProxy.installRoot();
+ commandLine.addArg("config:" + configurationName());
+ commandLine.addArg(QString(Constants::QBS_CONFIG_VARIANT_KEY) + ':' + buildVariant);
+ const FilePath installRoot = stepProxy.installRoot();
if (!installRoot.isEmpty()) {
- Utils::QtcProcess::addArg(&commandLine, QLatin1String(Constants::QBS_INSTALL_ROOT_KEY)
- + QLatin1Char(':') + installRoot.toUserOutput());
- if (qobject_cast<const QbsInstallStep *>(buildStep)) {
- Utils::QtcProcess::addArgs(&commandLine, QStringList({ QLatin1String("--installRoot"),
- installRoot.toUserOutput() } ));
- }
+ commandLine.addArg(QString(Constants::QBS_INSTALL_ROOT_KEY) + ':' + installRoot.toUserOutput());
+ if (qobject_cast<const QbsInstallStep *>(buildStep))
+ commandLine.addArgs({"--installRoot", installRoot.toUserOutput()});
}
- Utils::QtcProcess::addArg(&commandLine, QLatin1String("profile:") + profileName);
+ commandLine.addArg("profile:" + profileName);
- return commandLine;
+ return commandLine.arguments();
}
// ---------------------------------------------------------------------------
@@ -398,10 +362,10 @@ QbsBuildConfigurationFactory::QbsBuildConfigurationFactory()
registerBuildConfiguration<QbsBuildConfiguration>(Constants::QBS_BC_ID);
setSupportedProjectType(Constants::PROJECT_ID);
setSupportedProjectMimeTypeName(Constants::MIME_TYPE);
- setIssueReporter([](Kit *k, const QString &projectPath, const QString &buildDir) -> QList<Task> {
- const QtSupport::BaseQtVersion * const version = QtSupport::QtKitInformation::qtVersion(k);
+ setIssueReporter([](Kit *k, const QString &projectPath, const QString &buildDir) -> Tasks {
+ const QtSupport::BaseQtVersion * const version = QtSupport::QtKitAspect::qtVersion(k);
return version ? version->reportIssues(projectPath, buildDir)
- : QList<ProjectExplorer::Task>();
+ : Tasks();
});
}
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
index 1db6059252..f34e552a40 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
@@ -37,7 +37,6 @@ namespace ProjectExplorer { class BuildStep; }
namespace QbsProjectManager {
namespace Internal {
-class QbsBuildConfigurationWidget;
class QbsBuildStep;
class QbsProject;
@@ -50,7 +49,6 @@ class QbsBuildConfiguration : public ProjectExplorer::BuildConfiguration
public:
void initialize(const ProjectExplorer::BuildInfo &info) override;
- ProjectExplorer::NamedWidget *createConfigWidget() override;
QbsBuildStep *qbsStep() const;
QVariantMap qbsConfiguration() const;
@@ -71,9 +69,6 @@ public:
void setProducts(const QStringList &products);
QStringList products() const;
- void emitBuildTypeChanged();
-
- void setConfigurationName(const QString &configName);
QString configurationName() const;
QString equivalentCommandLine(const ProjectExplorer::BuildStep *buildStep) const;
@@ -83,16 +78,11 @@ signals:
private:
bool fromMap(const QVariantMap &map) override;
- QVariantMap toMap() const override;
- bool m_isParsing = true;
- bool m_parsingError = false;
QStringList m_changedFiles;
QStringList m_activeFileTags;
QStringList m_products;
- QString m_configurationName;
-
- friend class QbsBuildConfigurationWidget;
+ ProjectExplorer::BaseStringAspect *m_configurationName;
};
class QbsBuildConfigurationFactory : public ProjectExplorer::BuildConfigurationFactory
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.cpp
deleted file mode 100644
index 057280a21a..0000000000
--- a/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.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 "qbsbuildconfigurationwidget.h"
-
-#include "qbsbuildconfiguration.h"
-
-#include <projectexplorer/target.h>
-#include <projectexplorer/project.h>
-#include <utils/detailswidget.h>
-#include <utils/pathchooser.h>
-
-#include <QGridLayout>
-#include <QLabel>
-#include <QLineEdit>
-#include <QWidget>
-
-namespace QbsProjectManager {
-namespace Internal {
-
-QbsBuildConfigurationWidget::QbsBuildConfigurationWidget(QbsProjectManager::Internal::QbsBuildConfiguration *bc) :
- m_buildConfiguration(bc),
- m_ignoreChange(false)
-{
- connect(bc, &ProjectExplorer::BuildConfiguration::buildDirectoryChanged,
- this, &QbsBuildConfigurationWidget::buildDirectoryChanged);
- connect(bc, &ProjectExplorer::BuildConfiguration::environmentChanged,
- this, &QbsBuildConfigurationWidget::environmentHasChanged);
-
- auto vbox = new QVBoxLayout(this);
- vbox->setMargin(0);
- auto container = new Utils::DetailsWidget(this);
- container->setState(Utils::DetailsWidget::NoSummary);
- vbox->addWidget(container);
-
- QWidget *details = new QWidget(container);
- container->setWidget(details);
-
- auto layout = new QGridLayout(details);
- layout->setMargin(0);
- layout->addWidget(new QLabel(tr("Build directory:")), 0, 0);
-
- m_buildDirChooser = new Utils::PathChooser;
- m_buildDirChooser->setExpectedKind(Utils::PathChooser::Directory);
- m_buildDirChooser->setBaseFileName(bc->target()->project()->projectDirectory());
- m_buildDirChooser->setEnvironment(bc->environment());
- layout->addWidget(m_buildDirChooser, 0, 1);
- layout->addWidget(new QLabel(tr("Configuration name:")), 1, 0);
- m_configNameEdit = new QLineEdit;
- m_configNameEdit->setText(m_buildConfiguration->configurationName());
- layout->addWidget(m_configNameEdit, 1, 1);
-
- connect(m_buildDirChooser, &Utils::PathChooser::rawPathChanged,
- this, &QbsBuildConfigurationWidget::buildDirEdited);
- connect(m_configNameEdit, &QLineEdit::textEdited,
- this, &QbsBuildConfigurationWidget::configNameEdited);
-
- buildDirectoryChanged();
-}
-
-void QbsBuildConfigurationWidget::buildDirEdited()
-{
- m_ignoreChange = true;
- m_buildConfiguration->setBuildDirectory(m_buildDirChooser->fileName());
-}
-
-void QbsBuildConfigurationWidget::configNameEdited()
-{
- m_ignoreChange = true;
- m_buildConfiguration->setConfigurationName(m_configNameEdit->text());
-}
-
-void QbsBuildConfigurationWidget::buildDirectoryChanged()
-{
- if (m_ignoreChange)
- return;
-
- m_buildDirChooser->setPath(m_buildConfiguration->rawBuildDirectory().toString());
-}
-
-void QbsBuildConfigurationWidget::environmentHasChanged()
-{
- m_buildDirChooser->setEnvironment(m_buildConfiguration->environment());
-}
-
-} // namespace Internal
-} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.h b/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.h
deleted file mode 100644
index 48ffaa5fcc..0000000000
--- a/src/plugins/qbsprojectmanager/qbsbuildconfigurationwidget.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 <projectexplorer/namedwidget.h>
-
-namespace Utils {
-class DetailsWidget;
-class PathChooser;
-} // namespace Utils
-
-QT_BEGIN_NAMESPACE
-class QLineEdit;
-QT_END_NAMESPACE
-
-namespace QbsProjectManager {
-namespace Internal {
-class QbsBuildConfiguration;
-
-class QbsBuildConfigurationWidget : public ProjectExplorer::NamedWidget
-{
- Q_OBJECT
-
-public:
- QbsBuildConfigurationWidget(Internal::QbsBuildConfiguration *bc);
-
-private:
- void buildDirEdited();
- void configNameEdited();
-
- // Changes triggered from creator
- void buildDirectoryChanged();
- void environmentHasChanged();
-
-private:
- Internal::QbsBuildConfiguration *m_buildConfiguration;
- Utils::PathChooser *m_buildDirChooser;
- QLineEdit *m_configNameEdit;
- bool m_ignoreChange;
-};
-
-} // namespace Internal
-} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
index 45eb7535ce..da09f51c05 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
@@ -128,6 +128,11 @@ QbsBuildStep::QbsBuildStep(ProjectExplorer::BuildStepList *bsl) :
setDisplayName(tr("Qbs Build"));
setQbsConfiguration(QVariantMap());
+ auto qbsBuildConfig = qobject_cast<QbsBuildConfiguration *>(buildConfiguration());
+ QTC_CHECK(qbsBuildConfig);
+ connect(this, &QbsBuildStep::qbsConfigurationChanged,
+ qbsBuildConfig, &QbsBuildConfiguration::qbsConfigurationChanged);
+
// setQbsConfiguration(other->qbsConfiguration(PreserveVariables));
}
@@ -222,9 +227,8 @@ void QbsBuildStep::setQbsConfiguration(const QVariantMap &config)
if (tmp == m_qbsConfiguration)
return;
m_qbsConfiguration = tmp;
- auto bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
- if (bc)
- bc->emitBuildTypeChanged();
+ if (ProjectExplorer::BuildConfiguration *bc = buildConfiguration())
+ emit bc->buildTypeChanged();
emit qbsConfigurationChanged();
}
@@ -253,17 +257,17 @@ bool QbsBuildStep::hasCustomInstallRoot() const
return m_qbsConfiguration.contains(Constants::QBS_INSTALL_ROOT_KEY);
}
-Utils::FileName QbsBuildStep::installRoot(VariableHandling variableHandling) const
+Utils::FilePath QbsBuildStep::installRoot(VariableHandling variableHandling) const
{
- Utils::FileName root = Utils::FileName::fromString(qbsConfiguration(variableHandling)
- .value(Constants::QBS_INSTALL_ROOT_KEY).toString());
- if (root.isNull()) {
- const QbsBuildConfiguration * const bc
- = static_cast<QbsBuildConfiguration *>(buildConfiguration());
- root = bc->buildDirectory().appendPath(bc->configurationName())
- .appendPath(qbs::InstallOptions::defaultInstallRoot());
- }
- return root;
+ const QString root =
+ qbsConfiguration(variableHandling).value(Constants::QBS_INSTALL_ROOT_KEY).toString();
+ if (!root.isNull())
+ return Utils::FilePath::fromString(root);
+
+ const QbsBuildConfiguration * const bc
+ = static_cast<QbsBuildConfiguration *>(buildConfiguration());
+ return bc->buildDirectory().pathAppended(bc->configurationName())
+ .pathAppended(qbs::InstallOptions::defaultInstallRoot());
}
int QbsBuildStep::maxJobs() const
@@ -395,7 +399,7 @@ void QbsBuildStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, con
const QString &file, int line)
{
ProjectExplorer::Task task = ProjectExplorer::Task(type, message,
- Utils::FileName::fromString(file), line,
+ Utils::FilePath::fromString(file), line,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
emit addOutput(message, OutputFormat::Stdout);
@@ -412,9 +416,8 @@ void QbsBuildStep::setBuildVariant(const QString &variant)
return;
m_qbsConfiguration.insert(Constants::QBS_CONFIG_VARIANT_KEY, variant);
emit qbsConfigurationChanged();
- auto bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
- if (bc)
- bc->emitBuildTypeChanged();
+ if (ProjectExplorer::BuildConfiguration *bc = buildConfiguration())
+ emit bc->buildTypeChanged();
}
QString QbsBuildStep::profile() const
@@ -553,11 +556,11 @@ QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
m_ui->qmlDebuggingWarningIcon->setPixmap(Utils::Icons::WARNING.pixmap());
connect(m_ui->buildVariantComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &QbsBuildStepConfigWidget::changeBuildVariant);
connect(m_ui->keepGoingCheckBox, &QAbstractButton::toggled,
this, &QbsBuildStepConfigWidget::changeKeepGoing);
- connect(m_ui->jobSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_ui->jobSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &QbsBuildStepConfigWidget::changeJobCount);
connect(m_ui->showCommandLinesCheckBox, &QCheckBox::toggled, this,
&QbsBuildStepConfigWidget::changeShowCommandLines);
@@ -573,8 +576,6 @@ QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
&QbsBuildStepConfigWidget::changeForceProbes);
connect(m_ui->qmlDebuggingLibraryCheckBox, &QAbstractButton::toggled,
this, &QbsBuildStepConfigWidget::linkQmlDebuggingLibraryChecked);
- connect(QtSupport::QtVersionManager::instance(), &QtSupport::QtVersionManager::dumpUpdatedFor,
- this, &QbsBuildStepConfigWidget::updateQmlDebuggingOption);
updateState();
}
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.h b/src/plugins/qbsprojectmanager/qbsbuildstep.h
index 8c3622385d..913bf61268 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildstep.h
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.h
@@ -66,7 +66,7 @@ public:
bool install() const;
bool cleanInstallRoot() const;
bool hasCustomInstallRoot() const;
- Utils::FileName installRoot(VariableHandling variableHandling = ExpandVariables) const;
+ Utils::FilePath installRoot(VariableHandling variableHandling = ExpandVariables) const;
int maxJobs() const;
QString buildVariant() const;
diff --git a/src/plugins/qbsprojectmanager/qbscleanstep.cpp b/src/plugins/qbsprojectmanager/qbscleanstep.cpp
index f648e14aee..167299a0bb 100644
--- a/src/plugins/qbsprojectmanager/qbscleanstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbscleanstep.cpp
@@ -170,7 +170,7 @@ void QbsCleanStep::updateState()
void QbsCleanStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, const QString &message, const QString &file, int line)
{
ProjectExplorer::Task task = ProjectExplorer::Task(type, message,
- Utils::FileName::fromString(file), line,
+ Utils::FilePath::fromString(file), line,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
emit addOutput(message, OutputFormat::Stdout);
diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
index c375c87cac..ddfaadf8df 100644
--- a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
@@ -198,7 +198,7 @@ void QbsInstallStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type,
const QString &message, const QString &file, int line)
{
ProjectExplorer::Task task = ProjectExplorer::Task(type, message,
- Utils::FileName::fromString(file), line,
+ Utils::FilePath::fromString(file), line,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
emit addOutput(message, OutputFormat::Stdout);
diff --git a/src/plugins/qbsprojectmanager/qbskitinformation.cpp b/src/plugins/qbsprojectmanager/qbskitinformation.cpp
index 95242e5e37..53f3b9a142 100644
--- a/src/plugins/qbsprojectmanager/qbskitinformation.cpp
+++ b/src/plugins/qbsprojectmanager/qbskitinformation.cpp
@@ -27,7 +27,6 @@
#include "customqbspropertiesdialog.h"
-#include <projectexplorer/kitconfigwidget.h>
#include <projectexplorer/kitmanager.h>
#include <utils/elidinglabel.h>
@@ -42,49 +41,44 @@ using namespace ProjectExplorer;
namespace QbsProjectManager {
namespace Internal {
-class ConfigWidget final : public KitConfigWidget
+class AspectWidget final : public KitAspectWidget
{
- Q_OBJECT
+ Q_DECLARE_TR_FUNCTIONS(QbsProjectManager::Internal::AspectWidget)
public:
- ConfigWidget(Kit *kit, const KitInformation *kitInfo)
- : KitConfigWidget(kit, kitInfo),
+ AspectWidget(Kit *kit, const KitAspect *kitInfo)
+ : KitAspectWidget(kit, kitInfo),
m_contentLabel(new Utils::ElidingLabel),
m_changeButton(new QPushButton(tr("Change...")))
{
- connect(m_changeButton, &QPushButton::clicked, this, &ConfigWidget::changeProperties);
+ connect(m_changeButton, &QPushButton::clicked, this, &AspectWidget::changeProperties);
}
private:
- QString displayName() const override { return QbsKitInformation::displayName(); }
void makeReadOnly() override { m_changeButton->setEnabled(false); }
- void refresh() override { m_contentLabel->setText(QbsKitInformation::representation(kit())); }
+ void refresh() override { m_contentLabel->setText(QbsKitAspect::representation(kit())); }
QWidget *mainWidget() const override { return m_contentLabel; }
QWidget *buttonWidget() const override { return m_changeButton; }
void changeProperties()
{
- CustomQbsPropertiesDialog dlg(QbsKitInformation::properties(kit()));
+ CustomQbsPropertiesDialog dlg(QbsKitAspect::properties(kit()));
if (dlg.exec() == QDialog::Accepted)
- QbsKitInformation::setProperties(kit(), dlg.properties());
+ QbsKitAspect::setProperties(kit(), dlg.properties());
}
QLabel * const m_contentLabel;
QPushButton * const m_changeButton;
};
-QbsKitInformation::QbsKitInformation()
+QbsKitAspect::QbsKitAspect()
{
- setObjectName(QLatin1String("QbsKitInformation"));
- setId(QbsKitInformation::id());
+ setObjectName(QLatin1String("QbsKitAspect"));
+ setId(QbsKitAspect::id());
+ setDisplayName(tr("Additional Qbs Profile Settings"));
setPriority(22000);
}
-QString QbsKitInformation::displayName()
-{
- return tr("Additional Qbs Profile Settings");
-}
-
-QString QbsKitInformation::representation(const Kit *kit)
+QString QbsKitAspect::representation(const Kit *kit)
{
const QVariantMap props = properties(kit);
QString repr;
@@ -96,37 +90,34 @@ QString QbsKitInformation::representation(const Kit *kit)
return repr;
}
-QVariantMap QbsKitInformation::properties(const Kit *kit)
+QVariantMap QbsKitAspect::properties(const Kit *kit)
{
QTC_ASSERT(kit, return QVariantMap());
return kit->value(id()).toMap();
}
-void QbsKitInformation::setProperties(Kit *kit, const QVariantMap &properties)
+void QbsKitAspect::setProperties(Kit *kit, const QVariantMap &properties)
{
QTC_ASSERT(kit, return);
kit->setValue(id(), properties);
}
-Core::Id QbsKitInformation::id()
+Core::Id QbsKitAspect::id()
{
return "Qbs.KitInformation";
}
-QVariant QbsKitInformation::defaultValue(const Kit *) const { return QString(); }
-QList<Task> QbsKitInformation::validate(const Kit *) const { return QList<Task>(); }
+Tasks QbsKitAspect::validate(const Kit *) const { return {}; }
-KitInformation::ItemList QbsKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList QbsKitAspect::toUserOutput(const Kit *k) const
{
return ItemList({qMakePair(displayName(), representation(k))});
}
-KitConfigWidget *QbsKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *QbsKitAspect::createConfigWidget(Kit *k) const
{
- return new ConfigWidget(k, this);
+ return new AspectWidget(k, this);
}
} // namespace Internal
} // namespace QbsProjectManager
-
-#include <qbskitinformation.moc>
diff --git a/src/plugins/qbsprojectmanager/qbskitinformation.h b/src/plugins/qbsprojectmanager/qbskitinformation.h
index ef5a5b9351..1113f2ce01 100644
--- a/src/plugins/qbsprojectmanager/qbskitinformation.h
+++ b/src/plugins/qbsprojectmanager/qbskitinformation.h
@@ -30,14 +30,13 @@
namespace QbsProjectManager {
namespace Internal {
-class QbsKitInformation final : public ProjectExplorer::KitInformation
+class QbsKitAspect final : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- QbsKitInformation();
+ QbsKitAspect();
- static QString displayName();
static QString representation(const ProjectExplorer::Kit *kit);
static QVariantMap properties(const ProjectExplorer::Kit *kit);
static void setProperties(ProjectExplorer::Kit *kit, const QVariantMap &properties);
@@ -45,10 +44,9 @@ public:
private:
static Core::Id id();
- QVariant defaultValue(const ProjectExplorer::Kit *) const override;
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *) const override;
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *) const override;
ItemList toUserOutput(const ProjectExplorer::Kit *) const override;
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *) const override;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *) const override;
};
} // namespace Internal
diff --git a/src/plugins/qbsprojectmanager/qbslogsink.cpp b/src/plugins/qbsprojectmanager/qbslogsink.cpp
index c9a2f28d64..9e635c2958 100644
--- a/src/plugins/qbsprojectmanager/qbslogsink.cpp
+++ b/src/plugins/qbsprojectmanager/qbslogsink.cpp
@@ -70,7 +70,7 @@ void QbsLogSink::doPrintWarning(const qbs::ErrorInfo &warning)
foreach (const qbs::ErrorItem &item, warning.items())
emit newTask(Task(Task::Warning,
item.description(),
- Utils::FileName::fromString(item.codeLocation().filePath()),
+ Utils::FilePath::fromString(item.codeLocation().filePath()),
item.codeLocation().line(),
Constants::TASK_CATEGORY_BUILDSYSTEM));
}
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp
index 50b3957eca..cbc6e59740 100644
--- a/src/plugins/qbsprojectmanager/qbsnodes.cpp
+++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp
@@ -30,6 +30,7 @@
#include "qbsprojectmanagerconstants.h"
#include "qbsrunconfiguration.h"
+#include <android/androidconstants.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/idocument.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -223,63 +224,19 @@ static bool supportsNodeAction(ProjectAction action, const Node *node)
};
if (action == RemoveFile || action == Rename) {
- if (node->nodeType() == ProjectExplorer::NodeType::File)
+ if (node->asFileNode())
return !Utils::contains(project->qbsProject().buildSystemFiles(), equalsNodeFilePath);
}
return false;
}
-// ----------------------------------------------------------------------
-// QbsFileNode:
-// ----------------------------------------------------------------------
-
-QbsFileNode::QbsFileNode(const Utils::FileName &filePath,
- const ProjectExplorer::FileType fileType,
- bool generated,
- int line) :
- ProjectExplorer::FileNode(filePath, fileType, generated, line)
-{ }
-
-QString QbsFileNode::displayName() const
-{
- int l = line();
- if (l < 0)
- return ProjectExplorer::FileNode::displayName();
- return ProjectExplorer::FileNode::displayName() + QLatin1Char(':') + QString::number(l);
-}
-
-
-QbsFolderNode::QbsFolderNode(const Utils::FileName &folderPath, ProjectExplorer::NodeType nodeType,
- const QString &displayName)
- : ProjectExplorer::FolderNode(folderPath, nodeType, displayName)
-{
-}
-
-bool QbsFolderNode::supportsAction(ProjectAction action, const Node *node) const
-{
- return supportsNodeAction(action, node);
-}
-
-// ---------------------------------------------------------------------------
-// QbsBaseProjectNode:
-// ---------------------------------------------------------------------------
-
-QbsBaseProjectNode::QbsBaseProjectNode(const Utils::FileName &path) :
- ProjectExplorer::ProjectNode(path)
-{ }
-
-bool QbsBaseProjectNode::showInSimpleTree() const
-{
- return false;
-}
-
// --------------------------------------------------------------------
// QbsGroupNode:
// --------------------------------------------------------------------
QbsGroupNode::QbsGroupNode(const qbs::GroupData &grp, const QString &productPath) :
- QbsBaseProjectNode(Utils::FileName())
+ ProjectNode(Utils::FilePath())
{
static QIcon groupIcon = QIcon(QString(Constants::QBS_GROUP_ICON));
setIcon(groupIcon);
@@ -356,7 +313,7 @@ bool QbsGroupNode::renameFile(const QString &filePath, const QString &newFilePat
FolderNode::AddNewInformation QbsGroupNode::addNewInformation(const QStringList &files,
Node *context) const
{
- AddNewInformation info = QbsBaseProjectNode::addNewInformation(files, context);
+ AddNewInformation info = ProjectNode::addNewInformation(files, context);
if (context != this)
--info.priority;
return info;
@@ -367,16 +324,12 @@ FolderNode::AddNewInformation QbsGroupNode::addNewInformation(const QStringList
// --------------------------------------------------------------------
QbsProductNode::QbsProductNode(const qbs::ProductData &prd) :
- QbsBaseProjectNode(Utils::FileName::fromString(prd.location().filePath())),
+ ProjectNode(Utils::FilePath::fromString(prd.location().filePath())),
m_qbsProductData(prd)
{
static QIcon productIcon = Core::FileIconProvider::directoryIcon(Constants::QBS_PRODUCT_OVERLAY_ICON);
setIcon(productIcon);
-}
-
-bool QbsProductNode::showInSimpleTree() const
-{
- return true;
+ setIsProduct();
}
bool QbsProductNode::supportsAction(ProjectAction action, const Node *node) const
@@ -448,12 +401,47 @@ QString QbsProductNode::buildKey() const
return QbsProject::uniqueProductName(m_qbsProductData);
}
+QVariant QbsProductNode::data(Core::Id role) const
+{
+ if (role == Android::Constants::AndroidDeploySettingsFile) {
+ for (const auto &artifact : m_qbsProductData.generatedArtifacts()) {
+ if (artifact.fileTags().contains("qt_androiddeployqt_input"))
+ return artifact.filePath();
+ }
+ return {};
+ }
+
+ if (role == Android::Constants::AndroidSoLibPath) {
+ QStringList ret{m_qbsProductData.buildDirectory()};
+ for (const auto &artifact : m_qbsProductData.generatedArtifacts()) {
+ if (artifact.fileTags().contains("dynamiclibrary")) {
+ ret << QFileInfo(artifact.filePath()).path();
+ }
+ }
+ ret.removeDuplicates();
+ return ret;
+ }
+
+ if (role == Android::Constants::AndroidManifest) {
+ for (const auto &artifact : m_qbsProductData.generatedArtifacts()) {
+ if (artifact.fileTags().contains("android.manifest_final"))
+ return artifact.filePath();
+ }
+ return {};
+ }
+
+ if (role == Android::Constants::AndroidApk)
+ return m_qbsProductData.targetExecutable();
+
+ return {};
+}
+
// --------------------------------------------------------------------
// QbsProjectNode:
// --------------------------------------------------------------------
-QbsProjectNode::QbsProjectNode(const Utils::FileName &projectDirectory) :
- QbsBaseProjectNode(projectDirectory)
+QbsProjectNode::QbsProjectNode(const Utils::FilePath &projectDirectory) :
+ ProjectNode(projectDirectory)
{
static QIcon projectIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
setIcon(projectIcon);
@@ -469,11 +457,6 @@ const qbs::Project QbsProjectNode::qbsProject() const
return project()->qbsProject();
}
-bool QbsProjectNode::showInSimpleTree() const
-{
- return true;
-}
-
void QbsProjectNode::setProjectData(const qbs::ProjectData &data)
{
m_projectData = data;
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h
index cdf85b39ed..3d8f90c3df 100644
--- a/src/plugins/qbsprojectmanager/qbsnodes.h
+++ b/src/plugins/qbsprojectmanager/qbsnodes.h
@@ -35,59 +35,21 @@ namespace Internal {
class QbsNodeTreeBuilder;
class QbsProject;
-// ----------------------------------------------------------------------
-// QbsFileNode:
-// ----------------------------------------------------------------------
-
-class QbsFileNode : public ProjectExplorer::FileNode
-{
-public:
- QbsFileNode(const Utils::FileName &filePath, const ProjectExplorer::FileType fileType, bool generated,
- int line);
-
- QString displayName() const override;
-};
-
-class QbsFolderNode : public ProjectExplorer::FolderNode
-{
-public:
- QbsFolderNode(const Utils::FileName &folderPath, ProjectExplorer::NodeType nodeType,
- const QString &displayName);
-
-private:
- bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const final;
-};
-
-// ---------------------------------------------------------------------------
-// QbsBaseProjectNode:
-// ---------------------------------------------------------------------------
-
-class QbsGroupNode;
-
-class QbsBaseProjectNode : public ProjectExplorer::ProjectNode
-{
-public:
- explicit QbsBaseProjectNode(const Utils::FileName &absoluteFilePath);
-
- bool showInSimpleTree() const override;
-};
-
// --------------------------------------------------------------------
// QbsGroupNode:
// --------------------------------------------------------------------
-class QbsGroupNode : public QbsBaseProjectNode
+class QbsGroupNode : public ProjectExplorer::ProjectNode
{
public:
QbsGroupNode(const qbs::GroupData &grp, const QString &productPath);
+ bool showInSimpleTree() const final { return false; }
bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const final;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;
bool renameFile(const QString &filePath, const QString &newFilePath) override;
- qbs::GroupData qbsGroupData() const { return m_qbsGroupData; }
-
private:
AddNewInformation addNewInformation(const QStringList &files, Node *context) const override;
@@ -99,12 +61,11 @@ private:
// QbsProductNode:
// --------------------------------------------------------------------
-class QbsProductNode : public QbsBaseProjectNode
+class QbsProductNode : public ProjectExplorer::ProjectNode
{
public:
explicit QbsProductNode(const qbs::ProductData &prd);
- bool showInSimpleTree() const override;
bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const final;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;
@@ -114,6 +75,7 @@ public:
QString buildKey() const override;
const qbs::ProductData qbsProductData() const { return m_qbsProductData; }
+ QVariant data(Core::Id role) const override;
private:
const qbs::ProductData m_qbsProductData;
@@ -123,16 +85,15 @@ private:
// QbsProjectNode:
// ---------------------------------------------------------------------------
-class QbsProjectNode : public QbsBaseProjectNode
+class QbsProjectNode : public ProjectExplorer::ProjectNode
{
public:
- explicit QbsProjectNode(const Utils::FileName &projectDirectory);
+ explicit QbsProjectNode(const Utils::FilePath &projectDirectory);
virtual QbsProject *project() const;
const qbs::Project qbsProject() const;
const qbs::ProjectData qbsProjectData() const { return m_projectData; }
- bool showInSimpleTree() const override;
void setProjectData(const qbs::ProjectData &data); // FIXME: Needed?
private:
diff --git a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp
index 022d119190..f7f143b025 100644
--- a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp
+++ b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp
@@ -30,36 +30,43 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
-namespace {
+using namespace ProjectExplorer;
+using namespace Utils;
-ProjectExplorer::FileType fileType(const qbs::ArtifactData &artifact)
-{
- QTC_ASSERT(artifact.isValid(), return ProjectExplorer::FileType::Unknown);
+namespace QbsProjectManager {
+namespace Internal {
+
+namespace {
- if (artifact.fileTags().contains("c")
- || artifact.fileTags().contains("cpp")
- || artifact.fileTags().contains("objc")
- || artifact.fileTags().contains("objcpp")) {
- return ProjectExplorer::FileType::Source;
+FileType fileType(const qbs::ArtifactData &artifact)
+{
+ QTC_ASSERT(artifact.isValid(), return FileType::Unknown);
+
+ const QStringList fileTags = artifact.fileTags();
+ if (fileTags.contains("c")
+ || fileTags.contains("cpp")
+ || fileTags.contains("objc")
+ || fileTags.contains("objcpp")) {
+ return FileType::Source;
}
- if (artifact.fileTags().contains("hpp"))
- return ProjectExplorer::FileType::Header;
- if (artifact.fileTags().contains("qrc"))
- return ProjectExplorer::FileType::Resource;
- if (artifact.fileTags().contains("ui"))
- return ProjectExplorer::FileType::Form;
- if (artifact.fileTags().contains("scxml"))
- return ProjectExplorer::FileType::StateChart;
- if (artifact.fileTags().contains("qt.qml.qml"))
- return ProjectExplorer::FileType::QML;
- return ProjectExplorer::FileType::Unknown;
+ if (fileTags.contains("hpp"))
+ return FileType::Header;
+ if (fileTags.contains("qrc"))
+ return FileType::Resource;
+ if (fileTags.contains("ui"))
+ return FileType::Form;
+ if (fileTags.contains("scxml"))
+ return FileType::StateChart;
+ if (fileTags.contains("qt.qml.qml"))
+ return FileType::QML;
+ return FileType::Unknown;
}
-void setupArtifacts(ProjectExplorer::FolderNode *root, const QList<qbs::ArtifactData> &artifacts)
+void setupArtifacts(FolderNode *root, const QList<qbs::ArtifactData> &artifacts)
{
for (const qbs::ArtifactData &ad : artifacts) {
- const Utils::FileName path = Utils::FileName::fromString(ad.filePath());
- const ProjectExplorer::FileType type = fileType(ad);
+ const FilePath path = FilePath::fromString(ad.filePath());
+ const FileType type = fileType(ad);
const bool isGenerated = ad.isGenerated();
// A list of human-readable file types that we can reasonably expect
@@ -73,51 +80,48 @@ void setupArtifacts(ProjectExplorer::FolderNode *root, const QList<qbs::Artifact
QLatin1String("linkerscript"),
QLatin1String("qrc"), QLatin1String("java.java")
};
- auto node = std::make_unique<ProjectExplorer::FileNode>(path, type, isGenerated);
+ auto node = std::make_unique<FileNode>(path, type);
+ node->setIsGenerated(isGenerated);
node->setListInProject(!isGenerated || ad.fileTags().toSet().intersects(sourceTags));
root->addNestedNode(std::move(node));
}
root->compress();
}
-std::unique_ptr<QbsProjectManager::Internal::QbsGroupNode>
+std::unique_ptr<QbsGroupNode>
buildGroupNodeTree(const qbs::GroupData &grp, const QString &productPath, bool productIsEnabled)
{
QTC_ASSERT(grp.isValid(), return nullptr);
- auto result = std::make_unique<QbsProjectManager::Internal::QbsGroupNode>(grp, productPath);
+ auto fileNode = std::make_unique<FileNode>(FilePath::fromString(grp.location().filePath()),
+ FileType::Project);
+ fileNode->setLine(grp.location().line());
+
+ auto result = std::make_unique<QbsGroupNode>(grp, productPath);
result->setEnabled(productIsEnabled && grp.isEnabled());
result->setAbsoluteFilePathAndLine(
- Utils::FileName::fromString(grp.location().filePath()).parentDir(), -1);
+ FilePath::fromString(grp.location().filePath()).parentDir(), -1);
result->setDisplayName(grp.name());
- result->addNode(std::make_unique<QbsProjectManager::Internal::QbsFileNode>(
- Utils::FileName::fromString(grp.location().filePath()),
- ProjectExplorer::FileType::Project, false,
- grp.location().line()));
+ result->addNode(std::move(fileNode));
- ::setupArtifacts(result.get(), grp.allSourceArtifacts());
+ setupArtifacts(result.get(), grp.allSourceArtifacts());
return result;
}
-void setupQbsProductData(QbsProjectManager::Internal::QbsProductNode *node,
- const qbs::ProductData &prd)
+void setupQbsProductData(QbsProductNode *node, const qbs::ProductData &prd)
{
- using namespace QbsProjectManager::Internal;
+ auto fileNode = std::make_unique<FileNode>(FilePath::fromString(prd.location().filePath()),
+ FileType::Project);
+ fileNode->setLine(prd.location().line());
node->setEnabled(prd.isEnabled());
-
node->setDisplayName(prd.fullDisplayName());
- node->setAbsoluteFilePathAndLine(Utils::FileName::fromString(prd.location().filePath()).parentDir(), -1);
- const QString &productPath = QFileInfo(prd.location().filePath()).absolutePath();
-
- // Add QbsFileNode:
- node->addNode(std::make_unique<QbsFileNode>(Utils::FileName::fromString(prd.location().filePath()),
- ProjectExplorer::FileType::Project, false,
- prd.location().line()));
-
+ node->setAbsoluteFilePathAndLine(FilePath::fromString(prd.location().filePath()).parentDir(), -1);
+ node->addNode(std::move(fileNode));
+ const QString &productPath = QFileInfo(prd.location().filePath()).absolutePath();
foreach (const qbs::GroupData &grp, prd.groups()) {
if (grp.name() == prd.name() && grp.location() == prd.location()) {
// Set implicit product group right onto this node:
@@ -128,34 +132,31 @@ void setupQbsProductData(QbsProjectManager::Internal::QbsProductNode *node,
}
// Add "Generated Files" Node:
- auto genFiles
- = std::make_unique<ProjectExplorer::VirtualFolderNode>(node->filePath(),
- ProjectExplorer::Node::DefaultProjectFilePriority - 10);
+ auto genFiles = std::make_unique<VirtualFolderNode>(FilePath::fromString(prd.buildDirectory()));
genFiles->setDisplayName(QCoreApplication::translate("QbsProductNode", "Generated files"));
setupArtifacts(genFiles.get(), prd.generatedArtifacts());
node->addNode(std::move(genFiles));
}
-std::unique_ptr<QbsProjectManager::Internal::QbsProductNode>
-buildProductNodeTree(const qbs::ProductData &prd)
+std::unique_ptr<QbsProductNode> buildProductNodeTree(const qbs::ProductData &prd)
{
- auto result = std::make_unique<QbsProjectManager::Internal::QbsProductNode>(prd);
+ auto result = std::make_unique<QbsProductNode>(prd);
setupQbsProductData(result.get(), prd);
return result;
}
-void setupProjectNode(QbsProjectManager::Internal::QbsProjectNode *node, const qbs::ProjectData &prjData,
+void setupProjectNode(QbsProjectNode *node, const qbs::ProjectData &prjData,
const qbs::Project &qbsProject)
{
- using namespace QbsProjectManager::Internal;
- node->addNode(std::make_unique<QbsFileNode>(Utils::FileName::fromString(prjData.location().filePath()),
- ProjectExplorer::FileType::Project, false,
- prjData.location().line()));
+ auto fileNode = std::make_unique<FileNode>(FilePath::fromString(prjData.location().filePath()),
+ FileType::Project);
+ fileNode->setLine(prjData.location().line());
+
+ node->addNode(std::move(fileNode));
foreach (const qbs::ProjectData &subData, prjData.subProjects()) {
- auto subProject =
- std::make_unique<QbsProjectManager::Internal::QbsProjectNode>(
- Utils::FileName::fromString(subData.location().filePath()).parentDir());
+ auto subProject = std::make_unique<QbsProjectNode>(
+ FilePath::fromString(subData.location().filePath()).parentDir());
setupProjectNode(subProject.get(), subData, qbsProject);
node->addNode(std::move(subProject));
}
@@ -202,9 +203,6 @@ QStringList unreferencedBuildSystemFiles(const qbs::Project &p)
} // namespace
-namespace QbsProjectManager {
-namespace Internal {
-
std::unique_ptr<QbsRootProjectNode> QbsNodeTreeBuilder::buildTree(QbsProject *project)
{
if (!project->qbsProjectData().isValid())
@@ -212,17 +210,16 @@ std::unique_ptr<QbsRootProjectNode> QbsNodeTreeBuilder::buildTree(QbsProject *pr
auto root = std::make_unique<QbsRootProjectNode>(project);
setupProjectNode(root.get(), project->qbsProjectData(), project->qbsProject());
- auto buildSystemFiles
- = std::make_unique<ProjectExplorer::FolderNode>(project->projectDirectory(),
- ProjectExplorer::NodeType::Folder,
- QCoreApplication::translate("QbsRootProjectNode", "Qbs files"));
- Utils::FileName base = project->projectDirectory();
- const QStringList &files = unreferencedBuildSystemFiles(project->qbsProject());
+ auto buildSystemFiles = std::make_unique<FolderNode>(project->projectDirectory());
+ buildSystemFiles->setDisplayName(QCoreApplication::translate("QbsRootProjectNode", "Qbs files"));
+
+ const FilePath base = project->projectDirectory();
+ const QStringList files = unreferencedBuildSystemFiles(project->qbsProject());
for (const QString &f : files) {
- const Utils::FileName filePath = Utils::FileName::fromString(f);
+ const FilePath filePath = FilePath::fromString(f);
if (filePath.isChildOf(base))
- buildSystemFiles->addNestedNode(std::make_unique<ProjectExplorer::FileNode>(filePath, ProjectExplorer::FileType::Project, false));
+ buildSystemFiles->addNestedNode(std::make_unique<FileNode>(filePath, FileType::Project));
}
buildSystemFiles->compress();
root->addNode(std::move(buildSystemFiles));
diff --git a/src/plugins/qbsprojectmanager/qbsparser.cpp b/src/plugins/qbsprojectmanager/qbsparser.cpp
index 8aa0ed7e96..d6b2339dbb 100644
--- a/src/plugins/qbsprojectmanager/qbsparser.cpp
+++ b/src/plugins/qbsprojectmanager/qbsparser.cpp
@@ -52,7 +52,7 @@ void QbsParser::taskAdded(const ProjectExplorer::Task &task, int linkedLines, in
QString filePath = task.file.toString();
if (!filePath.isEmpty())
- editable.file = Utils::FileName::fromUserInput(m_workingDirectory.absoluteFilePath(filePath));
+ editable.file = Utils::FilePath::fromUserInput(m_workingDirectory.absoluteFilePath(filePath));
IOutputParser::taskAdded(editable, linkedLines, skipLines);
}
diff --git a/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp b/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp
index 418f30e211..5a79d42062 100644
--- a/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp
@@ -152,7 +152,7 @@ void QbsProfilesSettingsWidget::refreshKitsList()
m_ui.kitsComboBox->setCurrentIndex(0);
displayCurrentProfile();
connect(m_ui.kitsComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &QbsProfilesSettingsWidget::displayCurrentProfile);
}
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index 94bcb5a988..209e87b4bc 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -121,7 +121,7 @@ private:
// QbsProject:
// --------------------------------------------------------------------
-QbsProject::QbsProject(const FileName &fileName) :
+QbsProject::QbsProject(const FilePath &fileName) :
Project(Constants::MIME_TYPE, fileName, [this] { delayParsing(); }),
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
{
@@ -201,6 +201,11 @@ QVariant QbsProject::additionalData(Id id, const Target *target) const
return Project::additionalData(id, target);
}
+ProjectExplorer::DeploymentKnowledge QbsProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Perfect;
+}
+
QStringList QbsProject::filesGeneratedFrom(const QString &sourceFile) const
{
QStringList generated;
@@ -464,6 +469,7 @@ void QbsProject::updateAfterParse()
updateCppCodeModel();
updateQmlJsCodeModel();
emit fileListChanged();
+ m_envCache.clear();
emit dataChanged();
}
@@ -478,16 +484,16 @@ void QbsProject::updateProjectNodes()
rebuildProjectTree();
}
-FileName QbsProject::installRoot()
+FilePath QbsProject::installRoot()
{
if (!activeTarget())
- return FileName();
+ return FilePath();
const auto * const bc
= qobject_cast<QbsBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
if (!bc)
- return FileName();
+ return FilePath();
const QbsBuildStep * const buildStep = bc->qbsStep();
- return buildStep && buildStep->install() ? buildStep->installRoot() : FileName();
+ return buildStep && buildStep->install() ? buildStep->installRoot() : FilePath();
}
void QbsProject::handleQbsParsingDone(bool success)
@@ -647,6 +653,7 @@ void QbsProject::updateAfterBuild()
m_extraCompilersPending = false;
updateCppCodeModel();
}
+ m_envCache.clear();
emit dataChanged();
}
@@ -674,7 +681,7 @@ void QbsProject::generateErrors(const qbs::ErrorInfo &e)
foreach (const qbs::ErrorItem &item, e.items())
TaskHub::addTask(Task::Error, item.description(),
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
- FileName::fromString(item.codeLocation().filePath()),
+ FilePath::fromString(item.codeLocation().filePath()),
item.codeLocation().line());
}
@@ -693,7 +700,7 @@ void QbsProject::configureAsExampleProject(const QSet<Id> &platforms)
};
foreach (Kit *k, kits) {
const QtSupport::BaseQtVersion * const qtVersion
- = QtSupport::QtKitInformation::qtVersion(k);
+ = QtSupport::QtKitAspect::qtVersion(k);
if (!qtVersion || !qtVersionMatchesPlatform(qtVersion))
continue;
if (auto factory = BuildConfigurationFactory::find(k, projectFilePath().toString()))
@@ -756,11 +763,11 @@ void QbsProject::updateDocuments(const QSet<QString> &files)
}
}
QSet<IDocument *> toAdd;
- const FileName buildDir = FileName::fromString(m_projectData.buildDirectory());
+ const FilePath buildDir = FilePath::fromString(m_projectData.buildDirectory());
for (const QString &f : qAsConst(filesToAdd)) {
// A changed qbs file (project, module etc) should trigger a re-parse, but not if
// the file was generated by qbs itself, in which case that might cause an infinite loop.
- const FileName fp = FileName::fromString(f);
+ const FilePath fp = FilePath::fromString(f);
static const ProjectDocument::ProjectCallback noOpCallback = []{};
const ProjectDocument::ProjectCallback reparseCallback = [this]() { delayParsing(); };
toAdd.insert(new ProjectDocument(Constants::MIME_TYPE, fp, fp.isChildOf(buildDir)
@@ -964,7 +971,7 @@ void QbsProject::updateCppCodeModel()
list.removeDuplicates();
ProjectExplorer::HeaderPaths grpHeaderPaths;
foreach (const QString &p, list)
- grpHeaderPaths += {FileName::fromUserInput(p).toString(), HeaderPathType::User};
+ grpHeaderPaths += {FilePath::fromUserInput(p).toString(), HeaderPathType::User};
list = props.getModulePropertiesAsStringList(QLatin1String(CONFIG_CPP_MODULE),
QLatin1String(CONFIG_FRAMEWORKPATHS));
@@ -972,7 +979,7 @@ void QbsProject::updateCppCodeModel()
QLatin1String(CONFIG_SYSTEM_FRAMEWORKPATHS)));
list.removeDuplicates();
foreach (const QString &p, list)
- grpHeaderPaths += {FileName::fromUserInput(p).toString(), HeaderPathType::Framework};
+ grpHeaderPaths += {FilePath::fromUserInput(p).toString(), HeaderPathType::Framework};
rpp.setHeaderPaths(grpHeaderPaths);
@@ -1011,12 +1018,12 @@ void QbsProject::updateCppCodeModel()
continue;
}
- const FileNameList fileNames = Utils::transform(generated,
+ const FilePathList fileNames = Utils::transform(generated,
[](const QString &s) {
- return Utils::FileName::fromString(s);
+ return Utils::FilePath::fromString(s);
});
m_extraCompilers.append((*i)->create(
- this, FileName::fromString(source.filePath()), fileNames));
+ this, FilePath::fromString(source.filePath()), fileNames));
}
}
}
@@ -1072,7 +1079,7 @@ void QbsProject::updateQmlJsCodeModel()
foreach (const qbs::ProductData &product, m_projectData.allProducts()) {
static const QString propertyName = QLatin1String("qmlImportPaths");
foreach (const QString &path, product.properties().value(propertyName).toStringList()) {
- projectInfo.importPaths.maybeInsert(Utils::FileName::fromString(path),
+ projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(path),
QmlJS::Dialect::Qml);
}
}
@@ -1084,7 +1091,7 @@ void QbsProject::updateQmlJsCodeModel()
void QbsProject::updateApplicationTargets()
{
- BuildTargetInfoList applications;
+ QList<BuildTargetInfo> applications;
foreach (const qbs::ProductData &productData, m_projectData.allProducts()) {
if (!productData.isEnabled() || !productData.isRunnable())
continue;
@@ -1102,14 +1109,24 @@ void QbsProject::updateApplicationTargets()
BuildTargetInfo bti;
bti.buildKey = QbsProject::uniqueProductName(productData);
- bti.targetFilePath = FileName::fromString(targetFile);
- bti.projectFilePath = FileName::fromString(projectFile);
+ bti.targetFilePath = FilePath::fromString(targetFile);
+ bti.projectFilePath = FilePath::fromString(projectFile);
bti.isQtcRunnable = isQtcRunnable; // Fixed up below.
bti.usesTerminal = usesTerminal;
bti.displayName = productData.fullDisplayName();
bti.runEnvModifier = [targetFile, productData, this](Utils::Environment &env, bool usingLibraryPaths) {
if (!qbsProject().isValid())
return;
+
+ const QString key = env.toStringList().join(QChar())
+ + QbsProject::uniqueProductName(productData)
+ + QString::number(usingLibraryPaths);
+ const auto it = m_envCache.constFind(key);
+ if (it != m_envCache.constEnd()) {
+ env = it.value();
+ return;
+ }
+
QProcessEnvironment procEnv = env.toProcessEnvironment();
procEnv.insert(QLatin1String("QBS_RUN_FILE_PATH"), targetFile);
QStringList setupRunEnvConfig;
@@ -1128,9 +1145,11 @@ void QbsProject::updateApplicationTargets()
foreach (const QString &key, procEnv.keys())
env.set(key, procEnv.value(key));
}
+
+ m_envCache.insert(key, env);
};
- applications.list.append(bti);
+ applications.append(bti);
}
if (activeTarget())
activeTarget()->setApplicationTargets(applications);
diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h
index 5a2db0fa65..f186bb2c13 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.h
+++ b/src/plugins/qbsprojectmanager/qbsproject.h
@@ -54,7 +54,7 @@ class QbsProject : public ProjectExplorer::Project
Q_OBJECT
public:
- explicit QbsProject(const Utils::FileName &filename);
+ explicit QbsProject(const Utils::FilePath &filename);
~QbsProject() override;
QStringList filesGeneratedFrom(const QString &sourceFile) const override;
@@ -128,12 +128,14 @@ private:
void updateAfterParse();
void delayedUpdateAfterParse();
void updateProjectNodes();
- Utils::FileName installRoot();
+ Utils::FilePath installRoot();
void projectLoaded() override;
ProjectExplorer::ProjectImporter *projectImporter() const override;
QVariant additionalData(Core::Id id, const ProjectExplorer::Target *target) const final;
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+
static bool ensureWriteableQbsFile(const QString &file);
template<typename Options> qbs::AbstractJob *buildOrClean(const Options &opts,
@@ -162,6 +164,8 @@ private:
QTimer m_parsingDelay;
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
bool m_extraCompilersPending = false;
+
+ QHash<QString, Utils::Environment> m_envCache;
};
} // namespace Internal
diff --git a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
index b1d5adb849..69c4e5af1d 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
@@ -54,18 +54,18 @@ namespace Internal {
struct BuildGraphData
{
- FileName bgFilePath;
+ FilePath bgFilePath;
QVariantMap overriddenProperties;
- FileName cCompilerPath;
- FileName cxxCompilerPath;
- FileName qtBinPath;
- FileName sysroot;
+ FilePath cCompilerPath;
+ FilePath cxxCompilerPath;
+ FilePath qtBinPath;
+ FilePath sysroot;
QString buildVariant;
};
static BuildGraphData extractBgData(const qbs::Project::BuildGraphInfo &bgInfo)
{
BuildGraphData bgData;
- bgData.bgFilePath = FileName::fromString(bgInfo.bgFilePath);
+ bgData.bgFilePath = FilePath::fromString(bgInfo.bgFilePath);
bgData.overriddenProperties = bgInfo.overriddenProperties;
const QVariantMap &moduleProps = bgInfo.requestedProperties;
const QVariantMap prjCompilerPathByLanguage
@@ -73,17 +73,17 @@ static BuildGraphData extractBgData(const qbs::Project::BuildGraphInfo &bgInfo)
const QString prjCompilerPath = moduleProps.value("cpp.compilerPath").toString();
const QStringList prjToolchain = moduleProps.value("qbs.toolchain").toStringList();
const bool prjIsMsvc = prjToolchain.contains("msvc");
- bgData.cCompilerPath = FileName::fromString(
+ bgData.cCompilerPath = FilePath::fromString(
prjIsMsvc ? prjCompilerPath : prjCompilerPathByLanguage.value("c").toString());
- bgData.cxxCompilerPath = FileName::fromString(
+ bgData.cxxCompilerPath = FilePath::fromString(
prjIsMsvc ? prjCompilerPath : prjCompilerPathByLanguage.value("cpp").toString());
- bgData.qtBinPath = FileName::fromString(moduleProps.value("Qt.core.binPath").toString());
- bgData.sysroot = FileName::fromString(moduleProps.value("qbs.sysroot").toString());
+ bgData.qtBinPath = FilePath::fromString(moduleProps.value("Qt.core.binPath").toString());
+ bgData.sysroot = FilePath::fromString(moduleProps.value("qbs.sysroot").toString());
bgData.buildVariant = moduleProps.value("qbs.buildVariant").toString();
return bgData;
}
-QbsProjectImporter::QbsProjectImporter(const FileName &path) : QtProjectImporter(path)
+QbsProjectImporter::QbsProjectImporter(const FilePath &path) : QtProjectImporter(path)
{
}
@@ -93,7 +93,7 @@ static QString buildDir(const QString &projectFilePath, const Kit *k)
ProjectMacroExpander expander(projectFilePath, projectName, k, QString(),
BuildConfiguration::Unknown);
const QString projectDir
- = Project::projectDirectory(FileName::fromString(projectFilePath)).toString();
+ = Project::projectDirectory(FilePath::fromString(projectFilePath)).toString();
const QString buildPath = expander.expand(ProjectExplorerPlugin::buildDirectoryTemplate());
return FileUtils::resolvePath(projectDir, buildPath);
}
@@ -136,7 +136,7 @@ QStringList QbsProjectImporter::importCandidates()
return candidates;
}
-QList<void *> QbsProjectImporter::examineDirectory(const FileName &importPath) const
+QList<void *> QbsProjectImporter::examineDirectory(const FilePath &importPath) const
{
qCDebug(qbsPmLog) << "examining build directory" << importPath.toUserOutput();
QList<void *> data;
@@ -163,14 +163,14 @@ bool QbsProjectImporter::matchKit(void *directoryData, const Kit *k) const
const auto * const bgData = static_cast<BuildGraphData *>(directoryData);
qCDebug(qbsPmLog) << "matching kit" << k->displayName() << "against imported build"
<< bgData->bgFilePath.toUserOutput();
- if (ToolChainKitInformation::toolChains(k).isEmpty() && bgData->cCompilerPath.isEmpty()
+ if (ToolChainKitAspect::toolChains(k).isEmpty() && bgData->cCompilerPath.isEmpty()
&& bgData->cxxCompilerPath.isEmpty()) {
return true;
}
const ToolChain * const cToolchain
- = ToolChainKitInformation::toolChain(k, Constants::C_LANGUAGE_ID);
+ = ToolChainKitAspect::toolChain(k, Constants::C_LANGUAGE_ID);
const ToolChain * const cxxToolchain
- = ToolChainKitInformation::toolChain(k, Constants::CXX_LANGUAGE_ID);
+ = ToolChainKitAspect::toolChain(k, Constants::CXX_LANGUAGE_ID);
if (!bgData->cCompilerPath.isEmpty()) {
if (!cToolchain)
return false;
@@ -183,14 +183,14 @@ bool QbsProjectImporter::matchKit(void *directoryData, const Kit *k) const
if (bgData->cxxCompilerPath != cxxToolchain->compilerCommand())
return false;
}
- const QtSupport::BaseQtVersion * const qtVersion = QtSupport::QtKitInformation::qtVersion(k);
+ const QtSupport::BaseQtVersion * const qtVersion = QtSupport::QtKitAspect::qtVersion(k);
if (!bgData->qtBinPath.isEmpty()) {
if (!qtVersion)
return false;
if (bgData->qtBinPath != qtVersion->binPath())
return false;
}
- if (bgData->sysroot != SysRootKitInformation::sysRoot(k))
+ if (bgData->sysroot != SysRootKitAspect::sysRoot(k))
return false;
qCDebug(qbsPmLog) << "Kit matches";
@@ -203,8 +203,7 @@ Kit *QbsProjectImporter::createKit(void *directoryData) const
qCDebug(qbsPmLog) << "creating kit for imported build" << bgData->bgFilePath.toUserOutput();
QtVersionData qtVersionData;
if (!bgData->qtBinPath.isEmpty()) {
- FileName qmakeFilePath = bgData->qtBinPath;
- qmakeFilePath.appendPath(HostOsInfo::withExecutableSuffix("qmake"));
+ const FilePath qmakeFilePath = bgData->qtBinPath.pathAppended(HostOsInfo::withExecutableSuffix("qmake"));
qtVersionData = findOrCreateQtVersion(qmakeFilePath);
}
return createTemporaryKit(qtVersionData,[this, bgData](Kit *k) -> void {
@@ -215,9 +214,9 @@ Kit *QbsProjectImporter::createKit(void *directoryData) const
tcData << findOrCreateToolChains(bgData->cCompilerPath, Constants::C_LANGUAGE_ID);
foreach (const ToolChainData &tc, tcData) {
if (!tc.tcs.isEmpty())
- ToolChainKitInformation::setToolChain(k, tc.tcs.first());
+ ToolChainKitAspect::setToolChain(k, tc.tcs.first());
}
- SysRootKitInformation::setSysRoot(k, bgData->sysroot);
+ SysRootKitAspect::setSysRoot(k, bgData->sysroot);
});
}
diff --git a/src/plugins/qbsprojectmanager/qbsprojectimporter.h b/src/plugins/qbsprojectmanager/qbsprojectimporter.h
index 4aa3682a38..345e57522b 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectimporter.h
+++ b/src/plugins/qbsprojectmanager/qbsprojectimporter.h
@@ -35,11 +35,11 @@ class QbsProjectImporter final : public QtSupport::QtProjectImporter
Q_OBJECT
public:
- QbsProjectImporter(const Utils::FileName &path);
+ QbsProjectImporter(const Utils::FilePath &path);
private:
QStringList importCandidates() override;
- QList<void *> examineDirectory(const Utils::FileName &importPath) const override;
+ QList<void *> examineDirectory(const Utils::FilePath &importPath) const override;
bool matchKit(void *directoryData, const ProjectExplorer::Kit *k) const override;
ProjectExplorer::Kit *createKit(void *directoryData) const override;
const QList<ProjectExplorer::BuildInfo> buildInfoListForKit(const ProjectExplorer::Kit *k,
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
index b82a93987f..41cbe1763b 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
@@ -165,7 +165,7 @@ void QbsManager::addProfile(const QString &name, const QVariantMap &data)
void QbsManager::addQtProfileFromKit(const QString &profileName, const ProjectExplorer::Kit *k)
{
- if (const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitInformation::qtVersion(k)) {
+ if (const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitAspect::qtVersion(k)) {
qbs::Profile(profileName, settings()).setValue("moduleProviders.Qt.qmakeFilePaths",
qt->qmakeCommand().toString());
}
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
index bef7cd2a05..831422f262 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
@@ -20,7 +20,6 @@ HEADERS = \
defaultpropertyprovider.h \
propertyprovider.h \
qbsbuildconfiguration.h \
- qbsbuildconfigurationwidget.h \
qbsbuildstep.h \
qbscleanstep.h \
qbskitinformation.h \
@@ -45,7 +44,6 @@ SOURCES = \
customqbspropertiesdialog.cpp \
defaultpropertyprovider.cpp \
qbsbuildconfiguration.cpp \
- qbsbuildconfigurationwidget.cpp \
qbsbuildstep.cpp \
qbscleanstep.cpp \
qbsinstallstep.cpp \
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
index 45e5d1f3a4..1ef3f1b63b 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
@@ -66,8 +66,6 @@ QtcPlugin {
"propertyprovider.h",
"qbsbuildconfiguration.cpp",
"qbsbuildconfiguration.h",
- "qbsbuildconfigurationwidget.cpp",
- "qbsbuildconfigurationwidget.h",
"qbsbuildstep.cpp",
"qbsbuildstep.h",
"qbsbuildstepconfigwidget.ui",
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h b/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
index 8fe5f9170e..43cf1ce722 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
@@ -88,6 +88,7 @@ const char CPP_CCOMPILERNAME[] = "cpp.cCompilerName";
const char CPP_CXXCOMPILERNAME[] = "cpp.cxxCompilerName";
const char CPP_PLATFORMCOMMONCOMPILERFLAGS[] = "cpp.platformCommonCompilerFlags";
const char CPP_PLATFORMLINKERFLAGS[] = "cpp.platformLinkerFlags";
+const char CPP_VCVARSALLPATH[] = "cpp.vcvarsallPath";
const char XCODE_DEVELOPERPATH[] = "xcode.developerPath";
const char XCODE_SDK[] = "xcode.sdk";
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
index 3087dfc7a9..f8eb477e64 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
@@ -54,6 +54,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -91,7 +92,9 @@ public:
QbsCleanStepFactory cleanStepFactory;
QbsInstallStepFactory installStepFactory;
QbsRunConfigurationFactory runConfigFactory;
+ SimpleRunWorkerFactory<SimpleTargetRunner, QbsRunConfiguration> runWorkerFactory;
QbsProfilesSettingsPage profilesSetttingsPage;
+ QbsKitAspect qbsKitAspect;
};
QbsProjectManagerPlugin::~QbsProjectManagerPlugin()
@@ -112,7 +115,6 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
Core::HelpManager::registerDocumentation({Core::HelpManager::documentationPath() + "/qbs.qch"});
ProjectManager::registerProjectType<QbsProject>(QmlJSTools::Constants::QBS_MIMETYPE);
- KitManager::registerKitInformation<QbsKitInformation>();
//menus
// Build Menu:
@@ -219,16 +221,6 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
connect(m_buildSubprojectCtx, &QAction::triggered,
this, &QbsProjectManagerPlugin::buildSubprojectContextMenu);
- m_buildSubproject = new Utils::ParameterAction(tr("Build Subproject"), tr("Build Subproject \"%1\""),
- Utils::ParameterAction::AlwaysEnabled, this);
- command = Core::ActionManager::registerAction(m_buildSubproject, Constants::ACTION_BUILD_SUBPROJECT);
- command->setAttribute(Core::Command::CA_Hide);
- command->setAttribute(Core::Command::CA_UpdateText);
- command->setDescription(m_buildFile->text());
- command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+B")));
- mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
- connect(m_buildSubproject, &QAction::triggered, this, &QbsProjectManagerPlugin::buildSubproject);
-
m_cleanSubprojectCtx = new QAction(tr("Clean"), this);
command = Core::ActionManager::registerAction(
m_cleanSubprojectCtx, Constants::ACTION_CLEAN_SUBPROJECT_CONTEXT, projectContext);
@@ -237,17 +229,6 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
connect(m_cleanSubprojectCtx, &QAction::triggered,
this, &QbsProjectManagerPlugin::cleanSubprojectContextMenu);
- m_cleanSubproject = new Utils::ParameterAction(
- tr("Clean Subproject"), tr("Clean Subproject \"%1\""),
- Utils::ParameterAction::AlwaysEnabled, this);
- command = Core::ActionManager::registerAction(m_cleanSubproject,
- Constants::ACTION_CLEAN_SUBPROJECT);
- command->setAttribute(Core::Command::CA_Hide);
- command->setAttribute(Core::Command::CA_UpdateText);
- mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_CLEAN);
- connect(m_cleanSubproject, &QAction::triggered, this,
- &QbsProjectManagerPlugin::cleanSubproject);
-
m_rebuildSubprojectCtx = new QAction(tr("Rebuild"), this);
command = Core::ActionManager::registerAction(
m_rebuildSubprojectCtx, Constants::ACTION_REBUILD_SUBPROJECT_CONTEXT,
@@ -257,17 +238,6 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
connect(m_rebuildSubprojectCtx, &QAction::triggered,
this, &QbsProjectManagerPlugin::rebuildSubprojectContextMenu);
- m_rebuildSubproject = new Utils::ParameterAction(
- tr("Rebuild Subproject"), tr("Rebuild Subproject \"%1\""),
- Utils::ParameterAction::AlwaysEnabled, this);
- command = Core::ActionManager::registerAction(m_rebuildSubproject,
- Constants::ACTION_REBUILD_SUBPROJECT);
- command->setAttribute(Core::Command::CA_Hide);
- command->setAttribute(Core::Command::CA_UpdateText);
- mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_REBUILD);
- connect(m_rebuildSubproject, &QAction::triggered, this,
- &QbsProjectManagerPlugin::rebuildSubproject);
-
// Connect
connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged,
@@ -313,12 +283,12 @@ void QbsProjectManagerPlugin::projectWasAdded(Project *project)
void QbsProjectManagerPlugin::updateContextActions()
{
auto project = qobject_cast<Internal::QbsProject *>(ProjectTree::currentProject());
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
bool isEnabled = !BuildManager::isBuilding(project)
&& project && !project->isParsing()
&& node && node->isEnabled();
- bool isFile = project && node && (node->nodeType() == NodeType::File);
+ const bool isFile = project && node && node->asFileNode();
const bool isProduct = project && node && dynamic_cast<const QbsProductNode *>(node);
const auto subproject = dynamic_cast<const QbsProjectNode *>(node);
bool isSubproject = project && subproject && subproject != project->rootProjectNode();
@@ -346,32 +316,31 @@ void QbsProjectManagerPlugin::updateBuildActions()
bool enabled = false;
bool fileVisible = false;
bool productVisible = false;
- bool subprojectVisible = false;
QString fileName;
QString productName;
- QString subprojectName;
if (Node *editorNode = currentEditorNode()) {
- QbsProject *editorProject = currentEditorProject();
- enabled = editorProject
- && !BuildManager::isBuilding(editorProject)
- && !editorProject->isParsing();
-
fileName = editorNode->filePath().fileName();
- fileVisible = editorProject && editorNode && dynamic_cast<QbsBaseProjectNode *>(editorNode->parentProjectNode());
- auto productNode =
- dynamic_cast<QbsProductNode *>(editorNode ? editorNode->parentProjectNode() : nullptr);
+ ProjectNode *parentProjectNode = editorNode->parentProjectNode();
+ const QbsProductNode *productNode = nullptr;
+ for (const ProjectNode *potentialProductNode = parentProjectNode;
+ potentialProductNode && !productNode;
+ potentialProductNode = potentialProductNode->parentProjectNode()) {
+ productNode = dynamic_cast<const QbsProductNode *>(potentialProductNode);
+ }
+
if (productNode) {
productVisible = true;
productName = productNode->displayName();
}
- auto subprojectNode =
- dynamic_cast<QbsProjectNode *>(productNode ? productNode->parentFolderNode() : nullptr);
- if (subprojectNode && editorProject && subprojectNode != editorProject->rootProjectNode()) {
- subprojectVisible = true;
- subprojectName = subprojectNode->displayName();
+
+ if (QbsProject *editorProject = currentEditorProject()) {
+ enabled = !BuildManager::isBuilding(editorProject) && !editorProject->isParsing();
+ fileVisible = productNode
+ || dynamic_cast<QbsProjectNode *>(parentProjectNode)
+ || dynamic_cast<QbsGroupNode *>(parentProjectNode);
}
}
@@ -388,16 +357,6 @@ void QbsProjectManagerPlugin::updateBuildActions()
m_rebuildProduct->setEnabled(enabled);
m_rebuildProduct->setVisible(productVisible);
m_rebuildProduct->setParameter(productName);
-
- m_buildSubproject->setEnabled(enabled);
- m_buildSubproject->setVisible(subprojectVisible);
- m_buildSubproject->setParameter(subprojectName);
- m_cleanSubproject->setEnabled(enabled);
- m_cleanSubproject->setVisible(subprojectVisible);
- m_cleanSubproject->setParameter(subprojectName);
- m_rebuildSubproject->setEnabled(enabled);
- m_rebuildSubproject->setVisible(subprojectVisible);
- m_rebuildSubproject->setParameter(subprojectName);
}
void QbsProjectManagerPlugin::projectChanged()
@@ -416,7 +375,7 @@ void QbsProjectManagerPlugin::projectChanged()
void QbsProjectManagerPlugin::buildFileContextMenu()
{
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
QTC_ASSERT(node, return);
auto project = dynamic_cast<QbsProject *>(ProjectTree::currentProject());
QTC_ASSERT(project, return);
@@ -453,7 +412,7 @@ void QbsProjectManagerPlugin::rebuildProductContextMenu()
void QbsProjectManagerPlugin::runStepsForProductContextMenu(const QList<Core::Id> &stepTypes)
{
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
QTC_ASSERT(node, return);
auto project = dynamic_cast<QbsProject *>(ProjectTree::currentProject());
QTC_ASSERT(project, return);
@@ -518,7 +477,7 @@ void QbsProjectManagerPlugin::rebuildSubprojectContextMenu()
void QbsProjectManagerPlugin::runStepsForSubprojectContextMenu(const QList<Core::Id> &stepTypes)
{
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
QTC_ASSERT(node, return);
auto project = dynamic_cast<QbsProject *>(ProjectTree::currentProject());
QTC_ASSERT(project, return);
@@ -533,52 +492,6 @@ void QbsProjectManagerPlugin::runStepsForSubprojectContextMenu(const QList<Core:
runStepsForProducts(project, toBuild, {stepTypes});
}
-void QbsProjectManagerPlugin::buildSubproject()
-{
- runStepsForSubproject({Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)});
-}
-
-void QbsProjectManagerPlugin::cleanSubproject()
-{
- runStepsForSubproject({Core::Id(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)});
-}
-
-void QbsProjectManagerPlugin::rebuildSubproject()
-{
- runStepsForSubproject({
- Core::Id(ProjectExplorer::Constants::BUILDSTEPS_CLEAN),
- Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
- });
-}
-
-void QbsProjectManagerPlugin::runStepsForSubproject(const QList<Core::Id> &stepTypes)
-{
- Node *editorNode = currentEditorNode();
- QbsProject *editorProject = currentEditorProject();
- if (!editorNode || !editorProject)
- return;
-
- QbsProjectNode *subproject = nullptr;
- auto start = dynamic_cast<QbsBaseProjectNode *>(editorNode->parentProjectNode());
- while (start && start != editorProject->rootProjectNode()) {
- auto tmp = dynamic_cast<QbsProjectNode *>(start);
- if (tmp) {
- subproject = tmp;
- break;
- }
- start = dynamic_cast<QbsProjectNode *>(start->parentFolderNode());
- }
-
- if (!subproject)
- return;
-
- QStringList toBuild;
- foreach (const qbs::ProductData &data, subproject->qbsProjectData().allProducts())
- toBuild << QbsProject::uniqueProductName(data);
-
- runStepsForProducts(editorProject, toBuild, {stepTypes});
-}
-
void QbsProjectManagerPlugin::buildFiles(QbsProject *project, const QStringList &files,
const QStringList &activeFileTags)
{
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h
index 99aa566eff..f7b37e8d80 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.h
@@ -64,10 +64,6 @@ class QbsProjectManagerPlugin : public ExtensionSystem::IPlugin
void cleanSubprojectContextMenu();
void rebuildSubprojectContextMenu();
void runStepsForSubprojectContextMenu(const QList<Core::Id> &stepTypes);
- void buildSubproject();
- void cleanSubproject();
- void rebuildSubproject();
- void runStepsForSubproject(const QList<Core::Id> &stepTypes);
void reparseSelectedProject();
void reparseCurrentProject();
@@ -98,9 +94,6 @@ class QbsProjectManagerPlugin : public ExtensionSystem::IPlugin
Utils::ParameterAction *m_buildProduct = nullptr;
Utils::ParameterAction *m_cleanProduct = nullptr;
Utils::ParameterAction *m_rebuildProduct = nullptr;
- Utils::ParameterAction *m_buildSubproject = nullptr;
- Utils::ParameterAction *m_cleanSubproject = nullptr;
- Utils::ParameterAction *m_rebuildSubproject = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
index 03cff5f4eb..d4960b3524 100644
--- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
+++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
@@ -34,6 +34,7 @@
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h>
@@ -54,12 +55,18 @@ namespace Internal {
QbsRunConfiguration::QbsRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- auto envAspect = addAspect<LocalEnvironmentAspect>(target,
- [this](Environment &env) { addToBaseEnvironment(env); });
+ auto envAspect = addAspect<LocalEnvironmentAspect>(target);
+ envAspect->addModifier([this](Environment &env) {
+ bool usingLibraryPaths = aspect<UseLibraryPathsAspect>()->value();
+
+ BuildTargetInfo bti = buildTargetInfo();
+ if (bti.runEnvModifier)
+ bti.runEnvModifier(env, usingLibraryPaths);
+ });
addAspect<ExecutableAspect>();
addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>(envAspect);
+ addAspect<WorkingDirectoryAspect>();
addAspect<TerminalAspect>();
setOutputFormatter<QtSupport::QtOutputFormatter>();
@@ -71,6 +78,10 @@ QbsRunConfiguration::QbsRunConfiguration(Target *target, Core::Id id)
auto dyldAspect = addAspect<UseDyldSuffixAspect>();
connect(dyldAspect, &UseDyldSuffixAspect::changed,
envAspect, &EnvironmentAspect::environmentChanged);
+ envAspect->addModifier([dyldAspect](Environment &env) {
+ if (dyldAspect->value())
+ env.set("DYLD_IMAGE_SUFFIX", "_debug");
+ });
}
connect(project(), &Project::parsingFinished, this,
@@ -85,7 +96,6 @@ QbsRunConfiguration::QbsRunConfiguration(Target *target, Core::Id id)
this, &QbsRunConfiguration::updateTargetInformation);
auto qbsProject = static_cast<QbsProject *>(target->project());
- connect(qbsProject, &QbsProject::dataChanged, this, [this] { m_envCache.clear(); });
connect(qbsProject, &Project::parsingFinished,
this, &QbsRunConfiguration::updateTargetInformation);
}
@@ -110,41 +120,16 @@ void QbsRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo &
updateTargetInformation();
}
-void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const
+Utils::FilePath QbsRunConfiguration::executableToRun(const BuildTargetInfo &targetInfo) const
{
- if (auto dyldAspect = aspect<UseDyldSuffixAspect>()) {
- if (dyldAspect->value())
- env.set("DYLD_IMAGE_SUFFIX", "_debug");
- }
- bool usingLibraryPaths = aspect<UseLibraryPathsAspect>()->value();
-
- const auto key = qMakePair(env.toStringList(), usingLibraryPaths);
- const auto it = m_envCache.constFind(key);
- if (it != m_envCache.constEnd()) {
- env = it.value();
- return;
- }
- BuildTargetInfo bti = buildTargetInfo();
- if (bti.runEnvModifier) {
- if (project()->isParsing() || BuildManager::isBuilding(target())) {
- qCDebug(qbsPmLog) << "qbs project in flux, cannot modify environment";
- return; // Intentionally skips the cache update below.
- }
- bti.runEnvModifier(env, usingLibraryPaths);
- }
- m_envCache.insert(key, env);
-}
-
-Utils::FileName QbsRunConfiguration::executableToRun(const BuildTargetInfo &targetInfo) const
-{
- const FileName appInBuildDir = targetInfo.targetFilePath;
+ const FilePath appInBuildDir = targetInfo.targetFilePath;
if (target()->deploymentData().localInstallRoot().isEmpty())
return appInBuildDir;
const QString deployedAppFilePath = target()->deploymentData()
.deployableForLocalFile(appInBuildDir.toString()).remoteFilePath();
if (deployedAppFilePath.isEmpty())
return appInBuildDir;
- const FileName appInLocalInstallDir = target()->deploymentData().localInstallRoot()
+ const FilePath appInLocalInstallDir = target()->deploymentData().localInstallRoot()
+ deployedAppFilePath;
return appInLocalInstallDir.exists() ? appInLocalInstallDir : appInBuildDir;
}
@@ -152,10 +137,9 @@ Utils::FileName QbsRunConfiguration::executableToRun(const BuildTargetInfo &targ
void QbsRunConfiguration::updateTargetInformation()
{
BuildTargetInfo bti = buildTargetInfo();
- const FileName executable = executableToRun(bti);
+ const FilePath executable = executableToRun(bti);
auto terminalAspect = aspect<TerminalAspect>();
- if (!terminalAspect->isUserSet())
- terminalAspect->setUseTerminal(bti.usesTerminal);
+ terminalAspect->setUseTerminalHint(bti.usesTerminal);
aspect<ExecutableAspect>()->setExecutable(executable);
@@ -163,21 +147,13 @@ void QbsRunConfiguration::updateTargetInformation()
QString defaultWorkingDir = QFileInfo(executable.toString()).absolutePath();
if (!defaultWorkingDir.isEmpty()) {
auto wdAspect = aspect<WorkingDirectoryAspect>();
- wdAspect->setDefaultWorkingDirectory(FileName::fromString(defaultWorkingDir));
+ wdAspect->setDefaultWorkingDirectory(FilePath::fromString(defaultWorkingDir));
}
}
emit enabledChanged();
}
-bool QbsRunConfiguration::canRunForNode(const Node *node) const
-{
- if (auto pn = dynamic_cast<const QbsProductNode *>(node))
- return buildKey() == pn->buildKey();
-
- return false;
-}
-
// --------------------------------------------------------------------
// QbsRunConfigurationFactory:
// --------------------------------------------------------------------
@@ -187,8 +163,6 @@ QbsRunConfigurationFactory::QbsRunConfigurationFactory()
registerRunConfiguration<QbsRunConfiguration>("Qbs.RunConfiguration:");
addSupportedProjectType(Constants::PROJECT_ID);
addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
-
- addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
}
} // namespace Internal
diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
index 94b3ae6535..934f676624 100644
--- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
+++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
@@ -41,19 +41,13 @@ class QbsRunConfiguration : public ProjectExplorer::RunConfiguration
public:
QbsRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
- void addToBaseEnvironment(Utils::Environment &env) const;
-
private:
- Utils::FileName executableToRun(const ProjectExplorer::BuildTargetInfo &targetInfo) const;
+ Utils::FilePath executableToRun(const ProjectExplorer::BuildTargetInfo &targetInfo) const;
QVariantMap toMap() const final;
bool fromMap(const QVariantMap &map) final;
void doAdditionalSetup(const ProjectExplorer::RunConfigurationCreationInfo &rci) final;
- bool canRunForNode(const ProjectExplorer::Node *node) const final;
void updateTargetInformation();
-
- using EnvCache = QHash<QPair<QStringList, bool>, Utils::Environment>;
- mutable EnvCache m_envCache;
};
class QbsRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
diff --git a/src/plugins/qmakeprojectmanager/CMakeLists.txt b/src/plugins/qmakeprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..5cd7b6cc19
--- /dev/null
+++ b/src/plugins/qmakeprojectmanager/CMakeLists.txt
@@ -0,0 +1,53 @@
+add_qtc_plugin(QmakeProjectManager
+ DEPENDS qmljs
+ PLUGIN_DEPENDS Core CppTools QtSupport ResourceEditor TextEditor
+ PLUGIN_RECOMMENDS Designer
+ SOURCES
+ addlibrarywizard.cpp addlibrarywizard.h
+ applicationlauncher.h
+ customwidgetwizard/classdefinition.cpp customwidgetwizard/classdefinition.h customwidgetwizard/classdefinition.ui
+ customwidgetwizard/classlist.cpp customwidgetwizard/classlist.h
+ customwidgetwizard/customwidgetpluginwizardpage.cpp customwidgetwizard/customwidgetpluginwizardpage.h customwidgetwizard/customwidgetpluginwizardpage.ui
+ customwidgetwizard/customwidgetwidgetswizardpage.cpp customwidgetwizard/customwidgetwidgetswizardpage.h customwidgetwizard/customwidgetwidgetswizardpage.ui
+ customwidgetwizard/customwidgetwizard.cpp customwidgetwizard/customwidgetwizard.h
+ customwidgetwizard/customwidgetwizarddialog.cpp customwidgetwizard/customwidgetwizarddialog.h
+ customwidgetwizard/filenamingparameters.h
+ customwidgetwizard/plugingenerator.cpp customwidgetwizard/plugingenerator.h
+ customwidgetwizard/pluginoptions.h
+ desktopqmakerunconfiguration.cpp desktopqmakerunconfiguration.h
+ externaleditors.cpp externaleditors.h
+ librarydetailscontroller.cpp librarydetailscontroller.h
+ librarydetailswidget.ui
+ makefileparse.cpp makefileparse.h
+ profilecompletionassist.cpp profilecompletionassist.h
+ profileeditor.cpp profileeditor.h
+ profilehighlighter.cpp profilehighlighter.h
+ profilehoverhandler.cpp profilehoverhandler.h
+ qmakebuildconfiguration.cpp qmakebuildconfiguration.h
+ qmakebuildinfo.h
+ qmakekitinformation.cpp qmakekitinformation.h
+ qmakemakestep.cpp qmakemakestep.h
+ qmakenodes.cpp qmakenodes.h
+ qmakenodetreebuilder.cpp qmakenodetreebuilder.h
+ qmakeparser.cpp qmakeparser.h
+ qmakeparsernodes.cpp qmakeparsernodes.h
+ qmakeproject.cpp qmakeproject.h
+ qmakeprojectconfigwidget.cpp qmakeprojectconfigwidget.h
+ qmakeprojectimporter.cpp qmakeprojectimporter.h
+ qmakeprojectmanager.cpp qmakeprojectmanager.h
+ qmakeprojectmanager.qrc
+ qmakeprojectmanager_global.h
+ qmakeprojectmanagerconstants.h
+ qmakeprojectmanagerplugin.cpp qmakeprojectmanagerplugin.h
+ qmakesettings.cpp qmakesettings.h
+ qmakestep.cpp qmakestep.h qmakestep.ui
+ qtmodulesinfo.cpp qtmodulesinfo.h
+ wizards/filespage.cpp wizards/filespage.h
+ wizards/modulespage.cpp wizards/modulespage.h
+ wizards/qtprojectparameters.cpp wizards/qtprojectparameters.h
+ wizards/qtwizard.cpp wizards/qtwizard.h
+ wizards/simpleprojectwizard.cpp wizards/simpleprojectwizard.h
+ wizards/subdirsprojectwizard.cpp wizards/subdirsprojectwizard.h
+ wizards/subdirsprojectwizarddialog.cpp wizards/subdirsprojectwizarddialog.h
+ wizards/wizards.qrc
+)
diff --git a/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp b/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp
index 94f7d7b70d..bfef5875e3 100644
--- a/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp
+++ b/src/plugins/qmakeprojectmanager/addlibrarywizard.cpp
@@ -54,7 +54,7 @@ QStringList qt_clean_filter_list(const QString &filter)
return f.split(QLatin1Char(' '), QString::SkipEmptyParts);
}
-static bool validateLibraryPath(const Utils::FileName &filePath,
+static bool validateLibraryPath(const Utils::FilePath &filePath,
const Utils::PathChooser *pathChooser,
QString *errorMessage)
{
diff --git a/src/plugins/qmakeprojectmanager/addlibrarywizard.h b/src/plugins/qmakeprojectmanager/addlibrarywizard.h
index 196d31885c..ad2372f007 100644
--- a/src/plugins/qmakeprojectmanager/addlibrarywizard.h
+++ b/src/plugins/qmakeprojectmanager/addlibrarywizard.h
@@ -92,8 +92,6 @@ private:
QString m_proFile;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(AddLibraryWizard::Platforms)
-
class LibraryTypePage : public QWizardPage
{
Q_OBJECT
@@ -139,3 +137,5 @@ private:
} // namespace Internal
} // namespace QmakeProjectManager
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmakeProjectManager::Internal::AddLibraryWizard::Platforms)
diff --git a/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp b/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp
index be08ea5ff2..b93595bba1 100644
--- a/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp
+++ b/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp
@@ -130,7 +130,7 @@ QList<Core::GeneratedFile> PluginGenerator::generatePlugin(const GenerationPara
QString iconResource;
if (!wo.iconFile.isEmpty()) {
iconResource = QLatin1String("QLatin1String(\":/");
- iconResource += Utils::FileName::fromString(wo.iconFile).fileName();
+ iconResource += Utils::FilePath::fromString(wo.iconFile).fileName();
iconResource += QLatin1String("\")");
}
sm.insert(QLatin1String("WIDGET_ICON"),iconResource);
diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
index 8ac2a1cd0b..8cf53db49b 100644
--- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
+++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
@@ -31,6 +31,7 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
@@ -61,13 +62,16 @@ namespace Internal {
DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
- auto envAspect = addAspect<LocalEnvironmentAspect>(target, [this](Environment &env) {
- addToBaseEnvironment(env);
- });
+ auto envAspect = addAspect<LocalEnvironmentAspect>(target);
+ envAspect->addModifier([this](Environment &env) {
+ BuildTargetInfo bti = buildTargetInfo();
+ if (bti.runEnvModifier)
+ bti.runEnvModifier(env, aspect<UseLibraryPathsAspect>()->value());
+ });
addAspect<ExecutableAspect>();
addAspect<ArgumentsAspect>();
- addAspect<WorkingDirectoryAspect>(envAspect);
+ addAspect<WorkingDirectoryAspect>();
addAspect<TerminalAspect>();
setOutputFormatter<QtSupport::QtOutputFormatter>();
@@ -80,6 +84,10 @@ DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *target, Core:
auto dyldAspect = addAspect<UseDyldSuffixAspect>();
connect(dyldAspect, &UseLibraryPathsAspect::changed,
envAspect, &EnvironmentAspect::environmentChanged);
+ envAspect->addModifier([dyldAspect](Environment &env) {
+ if (dyldAspect->value())
+ env.set(QLatin1String("DYLD_IMAGE_SUFFIX"), QLatin1String("_debug"));
+ });
}
connect(target->project(), &Project::parsingFinished,
@@ -99,8 +107,7 @@ void DesktopQmakeRunConfiguration::updateTargetInformation()
wda->pathChooser()->setBaseFileName(target()->project()->projectDirectory());
auto terminalAspect = aspect<TerminalAspect>();
- if (!terminalAspect->isUserSet())
- terminalAspect->setUseTerminal(bti.usesTerminal);
+ terminalAspect->setUseTerminalHint(bti.usesTerminal);
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
}
@@ -118,31 +125,14 @@ void DesktopQmakeRunConfiguration::doAdditionalSetup(const RunConfigurationCreat
updateTargetInformation();
}
-void DesktopQmakeRunConfiguration::addToBaseEnvironment(Environment &env) const
+FilePath DesktopQmakeRunConfiguration::proFilePath() const
{
- BuildTargetInfo bti = buildTargetInfo();
- if (bti.runEnvModifier)
- bti.runEnvModifier(env, aspect<UseLibraryPathsAspect>()->value());
-
- if (auto dyldAspect = aspect<UseDyldSuffixAspect>()) {
- if (dyldAspect->value())
- env.set(QLatin1String("DYLD_IMAGE_SUFFIX"), QLatin1String("_debug"));
- }
-}
-
-bool DesktopQmakeRunConfiguration::canRunForNode(const Node *node) const
-{
- return node->filePath() == proFilePath();
-}
-
-FileName DesktopQmakeRunConfiguration::proFilePath() const
-{
- return FileName::fromString(buildKey());
+ return FilePath::fromString(buildKey());
}
QString DesktopQmakeRunConfiguration::defaultDisplayName()
{
- FileName profile = proFilePath();
+ FilePath profile = proFilePath();
if (!profile.isEmpty())
return profile.toFileInfo().completeBaseName();
return tr("Qt Run Configuration");
@@ -157,8 +147,6 @@ DesktopQmakeRunConfigurationFactory::DesktopQmakeRunConfigurationFactory()
registerRunConfiguration<DesktopQmakeRunConfiguration>("Qt4ProjectManager.Qt4RunConfiguration:");
addSupportedProjectType(QmakeProjectManager::Constants::QMAKEPROJECT_ID);
addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
-
- addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
}
} // namespace Internal
diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
index 2a4ccd564b..27bfb430b1 100644
--- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
+++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
@@ -39,17 +39,13 @@ class DesktopQmakeRunConfiguration : public ProjectExplorer::RunConfiguration
public:
DesktopQmakeRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
- void addToBaseEnvironment(Utils::Environment &env) const;
-
private:
void updateTargetInformation();
bool fromMap(const QVariantMap &map) final;
void doAdditionalSetup(const ProjectExplorer::RunConfigurationCreationInfo &info) final;
QString defaultDisplayName();
- bool canRunForNode(const ProjectExplorer::Node *node) const final;
-
- Utils::FileName proFilePath() const;
+ Utils::FilePath proFilePath() const;
};
class DesktopQmakeRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
diff --git a/src/plugins/qmakeprojectmanager/externaleditors.cpp b/src/plugins/qmakeprojectmanager/externaleditors.cpp
index 39de1e8ac7..50983370c3 100644
--- a/src/plugins/qmakeprojectmanager/externaleditors.cpp
+++ b/src/plugins/qmakeprojectmanager/externaleditors.cpp
@@ -168,21 +168,21 @@ bool ExternalQtEditor::getEditorLaunchData(const QString &fileName,
// As fallback check PATH
data->workingDirectory.clear();
QVector<QtSupport::BaseQtVersion *> qtVersionsToCheck; // deduplicated after being filled
- if (const Project *project = SessionManager::projectForFile(Utils::FileName::fromString(fileName))) {
+ if (const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(fileName))) {
data->workingDirectory = project->projectDirectory().toString();
// active kit
if (const Target *target = project->activeTarget()) {
- qtVersionsToCheck << QtSupport::QtKitInformation::qtVersion(target->kit());
+ qtVersionsToCheck << QtSupport::QtKitAspect::qtVersion(target->kit());
}
// all kits of project
qtVersionsToCheck += Utils::transform<QVector>(project->targets(), [](Target *t) {
- return QTC_GUARD(t) ? QtSupport::QtKitInformation::qtVersion(t->kit()) : nullptr;
+ return QTC_GUARD(t) ? QtSupport::QtKitAspect::qtVersion(t->kit()) : nullptr;
});
}
// default kit
- qtVersionsToCheck << QtSupport::QtKitInformation::qtVersion(KitManager::defaultKit());
+ qtVersionsToCheck << QtSupport::QtKitAspect::qtVersion(KitManager::defaultKit());
// all kits
- qtVersionsToCheck += Utils::transform<QVector>(KitManager::kits(), QtSupport::QtKitInformation::qtVersion);
+ qtVersionsToCheck += Utils::transform<QVector>(KitManager::kits(), QtSupport::QtKitAspect::qtVersion);
qtVersionsToCheck = Utils::filteredUnique(qtVersionsToCheck); // can still contain nullptr
data->binary = findFirstCommand(qtVersionsToCheck, m_commandForQtVersion);
// fallback
@@ -288,8 +288,7 @@ bool DesignerExternalEditor::startEditor(const QString &fileName, QString *error
m_processCache.insert(binary, socket);
auto mapSlot = [this, binary] { processTerminated(binary); };
connect(socket, &QAbstractSocket::disconnected, this, mapSlot);
- connect(socket,
- static_cast<void (QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
+ connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
this, mapSlot);
}
return true;
diff --git a/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp b/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp
index 1d3509f813..1f7a96eee5 100644
--- a/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp
+++ b/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp
@@ -860,7 +860,7 @@ QString PackageLibraryDetailsController::snippet() const
bool PackageLibraryDetailsController::isLinkPackageGenerated() const
{
- const Project *project = SessionManager::projectForFile(Utils::FileName::fromString(proFile()));
+ const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(proFile()));
if (!project)
return false;
@@ -947,7 +947,7 @@ InternalLibraryDetailsController::InternalLibraryDetailsController(
libraryDetailsWidget()->useSubfoldersCheckBox->setEnabled(true);
connect(libraryDetailsWidget()->libraryComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &InternalLibraryDetailsController::slotCurrentLibraryChanged);
updateProFile();
@@ -1010,7 +1010,7 @@ void InternalLibraryDetailsController::updateProFile()
libraryDetailsWidget()->libraryComboBox->clear();
const QmakeProject *project
- = dynamic_cast<QmakeProject *>(SessionManager::projectForFile(Utils::FileName::fromString(proFile())));
+ = dynamic_cast<QmakeProject *>(SessionManager::projectForFile(Utils::FilePath::fromString(proFile())));
if (!project)
return;
@@ -1092,7 +1092,7 @@ QString InternalLibraryDetailsController::snippet() const
const QString proRelavitePath = rootDir.relativeFilePath(proFile());
// project for which we insert the snippet
- const Project *project = SessionManager::projectForFile(Utils::FileName::fromString(proFile()));
+ const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(proFile()));
// the build directory of the active build configuration
QDir rootBuildDir = rootDir; // If the project is unconfigured use the project dir
diff --git a/src/plugins/qmakeprojectmanager/makefileparse.cpp b/src/plugins/qmakeprojectmanager/makefileparse.cpp
index b73c75244e..5fd6d5b0be 100644
--- a/src/plugins/qmakeprojectmanager/makefileparse.cpp
+++ b/src/plugins/qmakeprojectmanager/makefileparse.cpp
@@ -39,7 +39,7 @@
using namespace QmakeProjectManager;
using namespace Internal;
-using Utils::FileName;
+using Utils::FilePath;
using Utils::QtcProcess;
using QtSupport::QtVersionManager;
using QtSupport::BaseQtVersion;
@@ -242,7 +242,7 @@ void MakeFileParse::parseAssignments(QList<QMakeAssignment> *assignments)
}
}
-static FileName findQMakeBinaryFromMakefile(const QString &makefile)
+static FilePath findQMakeBinaryFromMakefile(const QString &makefile)
{
QFile fi(makefile);
if (fi.exists() && fi.open(QFile::ReadOnly)) {
@@ -260,11 +260,11 @@ static FileName findQMakeBinaryFromMakefile(const QString &makefile)
// Is qmake still installed?
QFileInfo fi(qmakePath);
if (fi.exists())
- return FileName(fi);
+ return FilePath::fromFileInfo(fi);
}
}
}
- return FileName();
+ return FilePath();
}
MakeFileParse::MakeFileParse(const QString &makefile)
@@ -312,7 +312,7 @@ MakeFileParse::MakefileState MakeFileParse::makeFileState() const
return m_state;
}
-Utils::FileName MakeFileParse::qmakePath() const
+Utils::FilePath MakeFileParse::qmakePath() const
{
return m_qmakePath;
}
diff --git a/src/plugins/qmakeprojectmanager/makefileparse.h b/src/plugins/qmakeprojectmanager/makefileparse.h
index 9a2abeb00e..90d3415662 100644
--- a/src/plugins/qmakeprojectmanager/makefileparse.h
+++ b/src/plugins/qmakeprojectmanager/makefileparse.h
@@ -47,7 +47,7 @@ public:
enum MakefileState { MakefileMissing, CouldNotParse, Okay };
MakefileState makeFileState() const;
- Utils::FileName qmakePath() const;
+ Utils::FilePath qmakePath() const;
QString srcProFile() const;
QMakeStepConfig config() const;
@@ -75,7 +75,7 @@ private:
};
MakefileState m_state;
- Utils::FileName m_qmakePath;
+ Utils::FilePath m_qmakePath;
QString m_srcProFile;
QmakeBuildConfig m_qmakeBuildConfig;
diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp
index cb26142767..346f119782 100644
--- a/src/plugins/qmakeprojectmanager/profileeditor.cpp
+++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp
@@ -28,6 +28,8 @@
#include "profilecompletionassist.h"
#include "profilehighlighter.h"
#include "profilehoverhandler.h"
+#include "qmakenodes.h"
+#include "qmakeproject.h"
#include "qmakeprojectmanager.h"
#include "qmakeprojectmanagerconstants.h"
#include "qmakeprojectmanagerconstants.h"
@@ -36,6 +38,7 @@
#include <extensionsystem/pluginmanager.h>
#include <qtsupport/qtsupportconstants.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/session.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/textdocument.h>
#include <utils/qtcassert.h>
@@ -48,6 +51,7 @@
#include <algorithm>
+using namespace ProjectExplorer;
using namespace TextEditor;
using namespace Utils;
@@ -56,12 +60,14 @@ namespace Internal {
class ProFileEditorWidget : public TextEditorWidget
{
-protected:
+private:
void findLinkAt(const QTextCursor &,
Utils::ProcessLinkCallback &&processLinkCallback,
bool resolveTarget = true,
bool inNextSplit = false) override;
void contextMenuEvent(QContextMenuEvent *) override;
+
+ QString checkForPrfFile(const QString &baseName) const;
};
static bool isValidFileNameChar(const QChar &c)
@@ -74,6 +80,36 @@ static bool isValidFileNameChar(const QChar &c)
|| c == QLatin1Char('\\');
}
+QString ProFileEditorWidget::checkForPrfFile(const QString &baseName) const
+{
+ const FilePath projectFile = textDocument()->filePath();
+ const QmakePriFileNode *projectNode = nullptr;
+ for (const Project * const project : SessionManager::projects()) {
+ if (project->isParsing())
+ continue;
+ projectNode = dynamic_cast<const QmakePriFileNode *>(project->rootProjectNode()
+ ->findProjectNode([&projectFile](const ProjectNode *pn) {
+ return pn->filePath() == projectFile;
+ }));
+ if (projectNode)
+ break;
+ }
+ if (!projectNode)
+ return QString();
+ const QmakeProFileNode * const proFileNode = projectNode->proFileNode();
+ if (!proFileNode)
+ return QString();
+ const QmakeProFile * const proFile = proFileNode->proFile();
+ if (!proFile)
+ return QString();
+ for (const QString &featureRoot : proFile->featureRoots()) {
+ const QFileInfo candidate(featureRoot + '/' + baseName + ".prf");
+ if (candidate.exists())
+ return candidate.filePath();
+ }
+ return QString();
+}
+
void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor,
Utils::ProcessLinkCallback &&processLinkCallback,
bool /*resolveTarget*/,
@@ -189,6 +225,10 @@ void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor,
return processLinkCallback(link);
}
link.targetFileName = QDir::cleanPath(fileName);
+ } else {
+ link.targetFileName = checkForPrfFile(buffer);
+ }
+ if (!link.targetFileName.isEmpty()) {
link.linkTextStart = cursor.position() - positionInBlock + beginPos + 1;
link.linkTextEnd = cursor.position() - positionInBlock + endPos;
}
@@ -229,7 +269,9 @@ ProFileEditorFactory::ProFileEditorFactory()
setDocumentCreator(createProFileDocument);
setEditorWidgetCreator([]() { return new ProFileEditorWidget; });
- setCompletionAssistProvider(new KeywordsCompletionAssistProvider(qmakeKeywords()));
+ const auto completionAssistProvider = new KeywordsCompletionAssistProvider(qmakeKeywords());
+ completionAssistProvider->setDynamicCompletionFunction(&TextEditor::pathComplete);
+ setCompletionAssistProvider(completionAssistProvider);
setCommentDefinition(Utils::CommentDefinition::HashStyle);
setEditorActionHandlers(TextEditorActionHandler::UnCommentSelection
diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
index 9435155b44..0bb6eed49f 100644
--- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp
@@ -31,6 +31,7 @@
#include "qmakeprojectconfigwidget.h"
#include "qmakeprojectmanagerconstants.h"
#include "qmakenodes.h"
+#include "qmakesettings.h"
#include "qmakestep.h"
#include "qmakemakestep.h"
#include "makefileparse.h"
@@ -86,17 +87,17 @@ QString QmakeBuildConfiguration::shadowBuildDirectory(const QString &proFilePath
const QString projectName = QFileInfo(proFilePath).completeBaseName();
ProjectMacroExpander expander(proFilePath, projectName, k, suffix, buildType);
- QString projectDir = Project::projectDirectory(FileName::fromString(proFilePath)).toString();
+ QString projectDir = Project::projectDirectory(FilePath::fromString(proFilePath)).toString();
QString buildPath = expander.expand(ProjectExplorerPlugin::buildDirectoryTemplate());
return FileUtils::resolvePath(projectDir, buildPath);
}
-static FileName defaultBuildDirectory(const QString &projectPath,
+static FilePath defaultBuildDirectory(const QString &projectPath,
const Kit *k,
const QString &suffix,
BuildConfiguration::BuildType type)
{
- return FileName::fromString(QmakeBuildConfiguration::shadowBuildDirectory(projectPath, k,
+ return FilePath::fromString(QmakeBuildConfiguration::shadowBuildDirectory(projectPath, k,
suffix, type));
}
@@ -140,7 +141,7 @@ void QmakeBuildConfiguration::initialize(const BuildInfo &info)
cleanSteps->appendStep(new QmakeMakeStep(cleanSteps));
const QmakeExtraBuildInfo qmakeExtra = info.extraInfo.value<QmakeExtraBuildInfo>();
- BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
+ BaseQtVersion *version = QtKitAspect::qtVersion(target()->kit());
BaseQtVersion::QmakeBuildConfigs config = version->defaultBuildConfig();
if (info.buildType == BuildConfiguration::Debug)
@@ -157,7 +158,7 @@ void QmakeBuildConfiguration::initialize(const BuildInfo &info)
setQMakeBuildConfiguration(config);
- FileName directory = info.buildDirectory;
+ FilePath directory = info.buildDirectory;
if (directory.isEmpty()) {
directory = defaultBuildDirectory(target()->project()->projectFilePath().toString(),
target()->kit(), info.displayName, buildType());
@@ -165,7 +166,7 @@ void QmakeBuildConfiguration::initialize(const BuildInfo &info)
setBuildDirectory(directory);
- if (DeviceTypeKitInformation::deviceTypeId(target()->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(target()->kit())
== Android::Constants::ANDROID_DEVICE_TYPE) {
buildSteps->appendStep(Android::Constants::ANDROID_PACKAGE_INSTALLATION_STEP_ID);
buildSteps->appendStep(Android::Constants::ANDROID_BUILD_APK_ID);
@@ -210,13 +211,13 @@ void QmakeBuildConfiguration::kitChanged()
void QmakeBuildConfiguration::toolChainUpdated(ToolChain *tc)
{
- if (ToolChainKitInformation::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID) == tc)
+ if (ToolChainKitAspect::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID) == tc)
emitProFileEvaluateNeeded();
}
void QmakeBuildConfiguration::qtVersionsChanged(const QList<int> &,const QList<int> &, const QList<int> &changed)
{
- if (changed.contains(QtKitInformation::qtVersionId(target()->kit())))
+ if (changed.contains(QtKitAspect::qtVersionId(target()->kit())))
emitProFileEvaluateNeeded();
}
@@ -293,6 +294,23 @@ void QmakeBuildConfiguration::emitProFileEvaluateNeeded()
static_cast<QmakeProject *>(p)->scheduleAsyncUpdate();
}
+QString QmakeBuildConfiguration::unalignedBuildDirWarning()
+{
+ return tr("The build directory should be at the same level as the source directory.");
+}
+
+bool QmakeBuildConfiguration::isBuildDirAtSafeLocation(const QString &sourceDir,
+ const QString &buildDir)
+{
+ return buildDir.count('/') == sourceDir.count('/');
+}
+
+bool QmakeBuildConfiguration::isBuildDirAtSafeLocation() const
+{
+ return isBuildDirAtSafeLocation(project()->projectDirectory().toString(),
+ buildDirectory().toString());
+}
+
void QmakeBuildConfiguration::emitQMakeBuildConfigurationChanged()
{
emit qmakeBuildConfigurationChanged();
@@ -301,7 +319,7 @@ void QmakeBuildConfiguration::emitQMakeBuildConfigurationChanged()
QStringList QmakeBuildConfiguration::configCommandLineArguments() const
{
QStringList result;
- BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
+ BaseQtVersion *version = QtKitAspect::qtVersion(target()->kit());
BaseQtVersion::QmakeBuildConfigs defaultBuildConfiguration =
version ? version->defaultBuildConfig() : BaseQtVersion::QmakeBuildConfigs(BaseQtVersion::DebugBuild | BaseQtVersion::BuildAll);
BaseQtVersion::QmakeBuildConfigs userBuildConfiguration = m_qmakeBuildConfiguration;
@@ -364,13 +382,13 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
return MakefileMissing;
}
- BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
+ BaseQtVersion *version = QtKitAspect::qtVersion(target()->kit());
if (!version) {
qCDebug(logs) << "**No qt version in kit";
return MakefileForWrongProject;
}
- const Utils::FileName projectPath =
+ const Utils::FilePath projectPath =
m_subNodeBuild ? m_subNodeBuild->filePath() : qs->project()->projectFilePath();
if (parse.srcProFile() != projectPath.toString()) {
qCDebug(logs) << "**Different profile used to generate the Makefile:"
@@ -406,16 +424,17 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
// This copies the settings from userArgs to actualArgs (minus some we
// are not interested in), splitting them up into individual strings:
extractSpecFromArguments(&userArgs, workingDirectory, version, &actualArgs);
- FileName actualSpec = qs->mkspec();
+ const QString actualSpec = qs->mkspec();
QString qmakeArgs = parse.unparsedArguments();
QStringList parsedArgs;
- FileName parsedSpec = extractSpecFromArguments(&qmakeArgs, workingDirectory, version, &parsedArgs);
+ QString parsedSpec =
+ extractSpecFromArguments(&qmakeArgs, workingDirectory, version, &parsedArgs);
qCDebug(logs) << " Actual args:" << actualArgs;
qCDebug(logs) << " Parsed args:" << parsedArgs;
- qCDebug(logs) << " Actual spec:" << actualSpec.toString();
- qCDebug(logs) << " Parsed spec:" << parsedSpec.toString();
+ qCDebug(logs) << " Actual spec:" << actualSpec;
+ qCDebug(logs) << " Parsed spec:" << parsedSpec;
qCDebug(logs) << " Actual config:" << qs->deducedArguments();
qCDebug(logs) << " Parsed config:" << parse.config();
@@ -456,8 +475,8 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
}
// Actual spec is the default one
// qDebug() << "AS vs VS" << actualSpec << version->mkspec();
- if ((actualSpec == version->mkspec() || actualSpec == FileName::fromLatin1("default"))
- && (parsedSpec == version->mkspec() || parsedSpec == FileName::fromLatin1("default") || parsedSpec.isEmpty())) {
+ if ((actualSpec == version->mkspec() || actualSpec == "default")
+ && (parsedSpec == version->mkspec() || parsedSpec == "default" || parsedSpec.isEmpty())) {
qCDebug(logs) << "**Matched specs (2)";
return MakefileMatches;
}
@@ -468,11 +487,11 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
return MakefileIncompatible;
}
-FileName QmakeBuildConfiguration::extractSpecFromArguments(QString *args,
+QString QmakeBuildConfiguration::extractSpecFromArguments(QString *args,
const QString &directory, const BaseQtVersion *version,
QStringList *outArgs)
{
- FileName parsedSpec;
+ FilePath parsedSpec;
bool ignoreNext = false;
bool nextIsSpec = false;
@@ -482,7 +501,7 @@ FileName QmakeBuildConfiguration::extractSpecFromArguments(QString *args,
ait.deleteArg();
} else if (nextIsSpec) {
nextIsSpec = false;
- parsedSpec = FileName::fromUserInput(ait.value());
+ parsedSpec = FilePath::fromUserInput(ait.value());
ait.deleteArg();
} else if (ait.value() == QLatin1String("-spec") || ait.value() == QLatin1String("-platform")) {
nextIsSpec = true;
@@ -502,11 +521,11 @@ FileName QmakeBuildConfiguration::extractSpecFromArguments(QString *args,
}
if (parsedSpec.isEmpty())
- return FileName();
+ return {};
- FileName baseMkspecDir = FileName::fromUserInput(
+ FilePath baseMkspecDir = FilePath::fromUserInput(
version->qmakeProperty("QT_HOST_DATA") + QLatin1String("/mkspecs"));
- baseMkspecDir = FileName::fromString(baseMkspecDir.toFileInfo().canonicalFilePath());
+ baseMkspecDir = FilePath::fromString(baseMkspecDir.toFileInfo().canonicalFilePath());
// if the path is relative it can be
// relative to the working directory (as found in the Makefiles)
@@ -515,26 +534,26 @@ FileName QmakeBuildConfiguration::extractSpecFromArguments(QString *args,
// for the other one we don't need to do anything
if (parsedSpec.toFileInfo().isRelative()) {
if (QFileInfo::exists(directory + QLatin1Char('/') + parsedSpec.toString()))
- parsedSpec = FileName::fromUserInput(directory + QLatin1Char('/') + parsedSpec.toString());
+ parsedSpec = FilePath::fromUserInput(directory + QLatin1Char('/') + parsedSpec.toString());
else
- parsedSpec = FileName::fromUserInput(baseMkspecDir.toString() + QLatin1Char('/') + parsedSpec.toString());
+ parsedSpec = FilePath::fromUserInput(baseMkspecDir.toString() + QLatin1Char('/') + parsedSpec.toString());
}
QFileInfo f2 = parsedSpec.toFileInfo();
while (f2.isSymLink()) {
- parsedSpec = FileName::fromString(f2.symLinkTarget());
+ parsedSpec = FilePath::fromString(f2.symLinkTarget());
f2.setFile(parsedSpec.toString());
}
if (parsedSpec.isChildOf(baseMkspecDir)) {
parsedSpec = parsedSpec.relativeChildPath(baseMkspecDir);
} else {
- FileName sourceMkSpecPath = FileName::fromString(version->sourcePath().toString()
+ FilePath sourceMkSpecPath = FilePath::fromString(version->sourcePath().toString()
+ QLatin1String("/mkspecs"));
if (parsedSpec.isChildOf(sourceMkSpecPath))
parsedSpec = parsedSpec.relativeChildPath(sourceMkSpecPath);
}
- return parsedSpec;
+ return parsedSpec.toString();
}
bool QmakeBuildConfiguration::isEnabled() const
@@ -567,23 +586,15 @@ QmakeBuildConfigurationFactory::QmakeBuildConfigurationFactory()
setSupportedProjectType(Constants::QMAKEPROJECT_ID);
setSupportedProjectMimeTypeName(Constants::PROFILE_MIMETYPE);
setIssueReporter([](Kit *k, const QString &projectPath, const QString &buildDir) {
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
- QList<Task> issues;
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
+ Tasks issues;
if (version)
issues << version->reportIssues(projectPath, buildDir);
-
- QString tmpBuildDir = QDir(buildDir).absolutePath();
- const QChar slash = QLatin1Char('/');
- if (!tmpBuildDir.endsWith(slash))
- tmpBuildDir.append(slash);
- QString sourcePath = QFileInfo(projectPath).absolutePath();
- if (!sourcePath.endsWith(slash))
- sourcePath.append(slash);
- if (tmpBuildDir.count(slash) != sourcePath.count(slash)) {
- const QString msg = QCoreApplication::translate("QmakeProjectManager::QtVersion",
- "The build directory needs to be at the same level as the source directory.");
-
- issues.append(Task(Task::Warning, msg, Utils::FileName(), -1,
+ if (QmakeSettings::warnAgainstUnalignedBuildDir()
+ && !QmakeBuildConfiguration::isBuildDirAtSafeLocation(
+ QFileInfo(projectPath).absoluteDir().path(), QDir(buildDir).absolutePath())) {
+ issues.append(Task(Task::Warning, QmakeBuildConfiguration::unalignedBuildDirWarning(),
+ Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
return issues;
@@ -594,7 +605,7 @@ BuildInfo QmakeBuildConfigurationFactory::createBuildInfo(const Kit *k,
const QString &projectPath,
BuildConfiguration::BuildType type) const
{
- BaseQtVersion *version = QtKitInformation::qtVersion(k);
+ BaseQtVersion *version = QtKitAspect::qtVersion(k);
QmakeExtraBuildInfo extraInfo;
BuildInfo info(this);
QString suffix;
@@ -628,7 +639,7 @@ BuildInfo QmakeBuildConfigurationFactory::createBuildInfo(const Kit *k,
info.kitId = k->id();
// check if this project is in the source directory:
- FileName projectFilePath = FileName::fromString(projectPath);
+ FilePath projectFilePath = FilePath::fromString(projectPath);
if (version && version->isInSourceDirectory(projectFilePath)) {
// assemble build directory
QString projectDirectory = projectFilePath.toFileInfo().absolutePath();
@@ -637,7 +648,7 @@ BuildInfo QmakeBuildConfigurationFactory::createBuildInfo(const Kit *k,
QString qtBuildDir = version->qmakeProperty("QT_INSTALL_PREFIX");
QString absoluteBuildPath = QDir::cleanPath(qtBuildDir + QLatin1Char('/') + relativeProjectPath);
- info.buildDirectory = FileName::fromString(absoluteBuildPath);
+ info.buildDirectory = FilePath::fromString(absoluteBuildPath);
} else {
info.buildDirectory = defaultBuildDirectory(projectPath, k, suffix, type);
}
@@ -662,7 +673,7 @@ QList<BuildInfo> QmakeBuildConfigurationFactory::availableBuilds(const Target *p
const QString projectFilePath = parent->project()->projectFilePath().toString();
foreach (BuildConfiguration::BuildType buildType,
- availableBuildTypes(QtKitInformation::qtVersion(parent->kit()))) {
+ availableBuildTypes(QtKitAspect::qtVersion(parent->kit()))) {
BuildInfo info = createBuildInfo(parent->kit(), projectFilePath, buildType);
info.displayName.clear(); // ask for a name
info.buildDirectory.clear(); // This depends on the displayName
@@ -675,7 +686,7 @@ QList<BuildInfo> QmakeBuildConfigurationFactory::availableBuilds(const Target *p
QList<BuildInfo> QmakeBuildConfigurationFactory::availableSetups(const Kit *k, const QString &projectPath) const
{
QList<BuildInfo> result;
- BaseQtVersion *qtVersion = QtKitInformation::qtVersion(k);
+ BaseQtVersion *qtVersion = QtKitAspect::qtVersion(k);
if (!qtVersion || !qtVersion->isValid())
return result;
@@ -704,7 +715,7 @@ void QmakeBuildConfiguration::addToEnvironment(Environment &env) const
void QmakeBuildConfiguration::setupBuildEnvironment(Kit *k, Environment &env)
{
prependCompilerPathToEnvironment(k, env);
- const BaseQtVersion *qt = QtKitInformation::qtVersion(k);
+ const BaseQtVersion *qt = QtKitAspect::qtVersion(k);
if (qt && !qt->binPath().isEmpty())
env.prependOrSetPath(qt->binPath().toString());
}
@@ -712,11 +723,11 @@ void QmakeBuildConfiguration::setupBuildEnvironment(Kit *k, Environment &env)
QmakeBuildConfiguration::LastKitState::LastKitState() = default;
QmakeBuildConfiguration::LastKitState::LastKitState(Kit *k)
- : m_qtVersion(QtKitInformation::qtVersionId(k)),
- m_sysroot(SysRootKitInformation::sysRoot(k).toString()),
- m_mkspec(QmakeKitInformation::mkspec(k).toString())
+ : m_qtVersion(QtKitAspect::qtVersionId(k)),
+ m_sysroot(SysRootKitAspect::sysRoot(k).toString()),
+ m_mkspec(QmakeKitAspect::mkspec(k))
{
- ToolChain *tc = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
m_toolchain = tc ? tc->id() : QByteArray();
}
diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h
index 480226e119..20b98103e8 100644
--- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h
+++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h
@@ -83,7 +83,7 @@ public:
enum MakefileState { MakefileMatches, MakefileForWrongProject, MakefileIncompatible, MakefileMissing };
MakefileState compareToImportFrom(const QString &makefile, QString *errorString = nullptr);
- static Utils::FileName extractSpecFromArguments(
+ static QString extractSpecFromArguments(
QString *arguments, const QString &directory, const QtSupport::BaseQtVersion *version,
QStringList *outArgs = nullptr);
@@ -101,6 +101,10 @@ public:
void emitProFileEvaluateNeeded();
+ static QString unalignedBuildDirWarning();
+ static bool isBuildDirAtSafeLocation(const QString &sourceDir, const QString &buildDir);
+ bool isBuildDirAtSafeLocation() const;
+
signals:
/// emitted for setQMakeBuildConfig, not emitted for Qt version changes, even
/// if those change the qmakebuildconfig
diff --git a/src/plugins/qmakeprojectmanager/qmakekitconfigwidget.cpp b/src/plugins/qmakeprojectmanager/qmakekitconfigwidget.cpp
deleted file mode 100644
index ba90baf6f1..0000000000
--- a/src/plugins/qmakeprojectmanager/qmakekitconfigwidget.cpp
+++ /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.
-**
-****************************************************************************/
-
-#include "qmakekitconfigwidget.h"
-
-#include "qmakekitinformation.h"
-
-#include <utils/fileutils.h>
-
-#include <QLineEdit>
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-QmakeKitConfigWidget::QmakeKitConfigWidget(ProjectExplorer::Kit *k, const ProjectExplorer::KitInformation *ki) :
- ProjectExplorer::KitConfigWidget(k, ki),
- m_lineEdit(new QLineEdit)
-{
- refresh(); // set up everything according to kit
- m_lineEdit->setToolTip(toolTip());
- connect(m_lineEdit, &QLineEdit::textEdited, this, &QmakeKitConfigWidget::mkspecWasChanged);
-}
-
-QmakeKitConfigWidget::~QmakeKitConfigWidget()
-{
- delete m_lineEdit;
-}
-
-QWidget *QmakeKitConfigWidget::mainWidget() const
-{
- return m_lineEdit;
-}
-
-QString QmakeKitConfigWidget::displayName() const
-{
- return tr("Qt mkspec");
-}
-
-QString QmakeKitConfigWidget::toolTip() const
-{
- return tr("The mkspec to use when building the project with qmake.<br>"
- "This setting is ignored when using other build systems.");
-}
-
-void QmakeKitConfigWidget::makeReadOnly()
-{
- m_lineEdit->setEnabled(false);
-}
-
-void QmakeKitConfigWidget::refresh()
-{
- if (!m_ignoreChange)
- m_lineEdit->setText(QmakeKitInformation::mkspec(m_kit).toUserOutput());
-}
-
-void QmakeKitConfigWidget::mkspecWasChanged(const QString &text)
-{
- m_ignoreChange = true;
- QmakeKitInformation::setMkspec(m_kit, Utils::FileName::fromString(text));
- m_ignoreChange = false;
-}
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/qmakekitconfigwidget.h b/src/plugins/qmakeprojectmanager/qmakekitconfigwidget.h
deleted file mode 100644
index f1faa861f1..0000000000
--- a/src/plugins/qmakeprojectmanager/qmakekitconfigwidget.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 <projectexplorer/kitconfigwidget.h>
-
-QT_BEGIN_NAMESPACE
-class QLineEdit;
-QT_END_NAMESPACE
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-class QmakeKitConfigWidget : public ProjectExplorer::KitConfigWidget
-{
- Q_OBJECT
-
-public:
- QmakeKitConfigWidget(ProjectExplorer::Kit *k, const ProjectExplorer::KitInformation *ki);
- ~QmakeKitConfigWidget() override;
-
- QWidget *mainWidget() const override;
- QString displayName() const override;
- QString toolTip() const override;
-
- void makeReadOnly() override;
- void refresh() override;
-
-private:
- void mkspecWasChanged(const QString &text);
- int findQtVersion(const int id) const;
-
- QLineEdit *m_lineEdit = nullptr;
- bool m_ignoreChange = false;
-};
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp
index 94f3efcbe7..95b7c8eb5b 100644
--- a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp
@@ -25,7 +25,6 @@
#include "qmakekitinformation.h"
-#include "qmakekitconfigwidget.h"
#include "qmakeprojectmanagerconstants.h"
#include <projectexplorer/projectexplorerconstants.h>
@@ -37,42 +36,80 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <QDir>
+#include <QLineEdit>
+
using namespace ProjectExplorer;
using namespace Utils;
namespace QmakeProjectManager {
+namespace Internal {
-QmakeKitInformation::QmakeKitInformation()
+class QmakeKitAspectWidget : public KitAspectWidget
{
- setObjectName(QLatin1String("QmakeKitInformation"));
- setId(QmakeKitInformation::id());
- setPriority(24000);
-}
+ Q_DECLARE_TR_FUNCTIONS(QmakeProjectManager::Internal::QmakeKitAspect)
+
+public:
+ QmakeKitAspectWidget(Kit *k, const KitAspect *ki)
+ : KitAspectWidget(k, ki), m_lineEdit(new QLineEdit)
+ {
+ refresh(); // set up everything according to kit
+ m_lineEdit->setToolTip(ki->description());
+ connect(m_lineEdit, &QLineEdit::textEdited, this, &QmakeKitAspectWidget::mkspecWasChanged);
+ }
-QVariant QmakeKitInformation::defaultValue(const Kit *k) const
+ ~QmakeKitAspectWidget() override { delete m_lineEdit; }
+
+private:
+ QWidget *mainWidget() const override { return m_lineEdit; }
+ void makeReadOnly() override { m_lineEdit->setEnabled(false); }
+
+ void refresh() override
+ {
+ if (!m_ignoreChange)
+ m_lineEdit->setText(QDir::toNativeSeparators(QmakeKitAspect::mkspec(m_kit)));
+ }
+
+ void mkspecWasChanged(const QString &text)
+ {
+ m_ignoreChange = true;
+ QmakeKitAspect::setMkspec(m_kit, text, QmakeKitAspect::MkspecSource::User);
+ m_ignoreChange = false;
+ }
+
+ QLineEdit *m_lineEdit = nullptr;
+ bool m_ignoreChange = false;
+};
+
+
+QmakeKitAspect::QmakeKitAspect()
{
- Q_UNUSED(k);
- return QString();
+ setObjectName(QLatin1String("QmakeKitAspect"));
+ setId(QmakeKitAspect::id());
+ setDisplayName(tr("Qt mkspec"));
+ setDescription(tr("The mkspec to use when building the project with qmake.<br>"
+ "This setting is ignored when using other build systems."));
+ setPriority(24000);
}
-QList<Task> QmakeKitInformation::validate(const Kit *k) const
+Tasks QmakeKitAspect::validate(const Kit *k) const
{
- QList<Task> result;
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
+ Tasks result;
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
- FileName mkspec = QmakeKitInformation::mkspec(k);
+ const QString mkspec = QmakeKitAspect::mkspec(k);
if (!version && !mkspec.isEmpty())
result << Task(Task::Warning, tr("No Qt version set, so mkspec is ignored."),
- FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
+ FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
if (version && !version->hasMkspec(mkspec))
result << Task(Task::Error, tr("Mkspec not found for Qt version."),
- FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
+ FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
return result;
}
-void QmakeKitInformation::setup(Kit *k)
+void QmakeKitAspect::setup(Kit *k)
{
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
if (!version)
return;
@@ -80,11 +117,11 @@ void QmakeKitInformation::setup(Kit *k)
if (version->type() == "Boot2Qt.QtVersionType" || version->type() == "Qdb.EmbeddedLinuxQt")
return;
- FileName spec = QmakeKitInformation::mkspec(k);
+ QString spec = QmakeKitAspect::mkspec(k);
if (spec.isEmpty())
spec = version->mkspec();
- ToolChain *tc = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!tc || (!tc->suggestedMkspecList().empty() && !tc->suggestedMkspecList().contains(spec))) {
const QList<ToolChain *> possibleTcs = ToolChainManager::toolChains(
@@ -110,65 +147,67 @@ void QmakeKitInformation::setup(Kit *k)
bestTc = goodTcs.isEmpty() ? possibleTcs.last() : goodTcs.last();
}
if (bestTc)
- ToolChainKitInformation::setAllToolChainsToMatch(k, bestTc);
+ ToolChainKitAspect::setAllToolChainsToMatch(k, bestTc);
}
}
}
-KitConfigWidget *QmakeKitInformation::createConfigWidget(Kit *k) const
+KitAspectWidget *QmakeKitAspect::createConfigWidget(Kit *k) const
{
- return new Internal::QmakeKitConfigWidget(k, this);
+ return new Internal::QmakeKitAspectWidget(k, this);
}
-KitInformation::ItemList QmakeKitInformation::toUserOutput(const Kit *k) const
+KitAspect::ItemList QmakeKitAspect::toUserOutput(const Kit *k) const
{
- return ItemList() << qMakePair(tr("mkspec"), mkspec(k).toUserOutput());
+ return {qMakePair(tr("mkspec"), QDir::toNativeSeparators(mkspec(k)))};
}
-void QmakeKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expander) const
+void QmakeKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
- expander->registerVariable("Qmake:mkspec", tr("Mkspec configured for qmake by the Kit."),
+ expander->registerVariable("Qmake:mkspec", tr("Mkspec configured for qmake by the kit."),
[kit]() -> QString {
- return QmakeKitInformation::mkspec(kit).toUserOutput();
+ return QDir::toNativeSeparators(mkspec(kit));
});
}
-Core::Id QmakeKitInformation::id()
+Core::Id QmakeKitAspect::id()
{
return Constants::KIT_INFORMATION_ID;
}
-FileName QmakeKitInformation::mkspec(const Kit *k)
+QString QmakeKitAspect::mkspec(const Kit *k)
{
if (!k)
- return FileName();
- return FileName::fromString(k->value(QmakeKitInformation::id()).toString());
+ return {};
+ return k->value(QmakeKitAspect::id()).toString();
}
-FileName QmakeKitInformation::effectiveMkspec(const Kit *k)
+QString QmakeKitAspect::effectiveMkspec(const Kit *k)
{
if (!k)
- return FileName();
- FileName spec = mkspec(k);
+ return {};
+ const QString spec = mkspec(k);
if (spec.isEmpty())
return defaultMkspec(k);
return spec;
}
-void QmakeKitInformation::setMkspec(Kit *k, const FileName &fn)
+void QmakeKitAspect::setMkspec(Kit *k, const QString &mkspec, MkspecSource source)
{
QTC_ASSERT(k, return);
- k->setValue(QmakeKitInformation::id(), fn == defaultMkspec(k) ? QString() : fn.toString());
+ k->setValue(QmakeKitAspect::id(), source == MkspecSource::Code && mkspec == defaultMkspec(k)
+ ? QString() : mkspec);
}
-FileName QmakeKitInformation::defaultMkspec(const Kit *k)
+QString QmakeKitAspect::defaultMkspec(const Kit *k)
{
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
if (!version) // No version, so no qmake
- return FileName();
+ return {};
- return version->mkspecFor(ToolChainKitInformation::toolChain(k,
+ return version->mkspecFor(ToolChainKitAspect::toolChain(k,
ProjectExplorer::Constants::CXX_LANGUAGE_ID));
}
+} // namespace Internal
} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/qmakekitinformation.h b/src/plugins/qmakeprojectmanager/qmakekitinformation.h
index 686ece1246..1de908396f 100644
--- a/src/plugins/qmakeprojectmanager/qmakekitinformation.h
+++ b/src/plugins/qmakeprojectmanager/qmakekitinformation.h
@@ -25,35 +25,34 @@
#pragma once
-#include "qmakeprojectmanager_global.h"
-
#include <projectexplorer/kitmanager.h>
namespace QmakeProjectManager {
+namespace Internal {
-class QMAKEPROJECTMANAGER_EXPORT QmakeKitInformation : public ProjectExplorer::KitInformation
+class QmakeKitAspect : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- QmakeKitInformation();
-
- QVariant defaultValue(const ProjectExplorer::Kit *k) const override;
+ QmakeKitAspect();
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const override;
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const override;
void setup(ProjectExplorer::Kit *k) override;
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const override;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const override;
ItemList toUserOutput(const ProjectExplorer::Kit *k) const override;
void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override;
static Core::Id id();
- static void setMkspec(ProjectExplorer::Kit *k, const Utils::FileName &fn);
- static Utils::FileName mkspec(const ProjectExplorer::Kit *k);
- static Utils::FileName effectiveMkspec(const ProjectExplorer::Kit *k);
- static Utils::FileName defaultMkspec(const ProjectExplorer::Kit *k);
+ enum class MkspecSource { User, Code };
+ static void setMkspec(ProjectExplorer::Kit *k, const QString &mkspec, MkspecSource source);
+ static QString mkspec(const ProjectExplorer::Kit *k);
+ static QString effectiveMkspec(const ProjectExplorer::Kit *k);
+ static QString defaultMkspec(const ProjectExplorer::Kit *k);
};
+} // namespace Internal
} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp
index be03c1affc..3b4642a6df 100644
--- a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp
@@ -30,6 +30,8 @@
#include "qmakenodes.h"
#include "qmakebuildconfiguration.h"
#include "qmakeprojectmanagerconstants.h"
+#include "qmakesettings.h"
+#include "qmakestep.h"
#include <coreplugin/variablechooser.h>
#include <projectexplorer/target.h>
@@ -38,6 +40,7 @@
#include <projectexplorer/gnumakeparser.h>
#include <projectexplorer/processparameters.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/xcodebuildparser.h>
#include <utils/qtcprocess.h>
@@ -61,18 +64,13 @@ QmakeMakeStep::QmakeMakeStep(BuildStepList *bsl)
}
}
-QmakeBuildConfiguration *QmakeMakeStep::qmakeBuildConfiguration() const
-{
- return static_cast<QmakeBuildConfiguration *>(buildConfiguration());
-}
-
bool QmakeMakeStep::init()
{
- QmakeBuildConfiguration *bc = qmakeBuildConfiguration();
+ const auto bc = static_cast<QmakeBuildConfiguration *>(buildConfiguration());
if (!bc)
emit addTask(Task::buildConfigurationMissingTask());
- const QString make = effectiveMakeCommand();
+ Utils::FilePath make = effectiveMakeCommand();
if (make.isEmpty())
emit addTask(makeCommandMissingTask());
@@ -81,6 +79,10 @@ bool QmakeMakeStep::init()
return false;
}
+ // Ignore all but the first make step for a non-top-level build. See QTCREATORBUG-15794.
+ m_ignoredNonTopLevelBuild = (bc->fileNodeBuild() || bc->subNodeBuild())
+ && static_cast<BuildStepList *>(parent())->firstOfType<QmakeMakeStep>() != this;
+
ProcessParameters *pp = processParameters();
pp->setMacroExpander(bc->macroExpander());
@@ -89,7 +91,7 @@ bool QmakeMakeStep::init()
workingDirectory = bc->subNodeBuild()->buildDir();
else
workingDirectory = bc->buildDirectory().toString();
- pp->setWorkingDirectory(workingDirectory);
+ pp->setWorkingDirectory(Utils::FilePath::fromString(workingDirectory));
pp->setCommand(make);
@@ -141,7 +143,8 @@ bool QmakeMakeStep::init()
objectsDir += "/release";
}
}
- QString relObjectsDir = QDir(pp->workingDirectory()).relativeFilePath(objectsDir);
+ QString relObjectsDir = QDir(pp->workingDirectory().toString())
+ .relativeFilePath(objectsDir);
if (relObjectsDir == ".")
relObjectsDir.clear();
if (!relObjectsDir.isEmpty())
@@ -156,7 +159,7 @@ bool QmakeMakeStep::init()
pp->resolveAll();
setOutputParser(new ProjectExplorer::GnuMakeParser());
- ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit(),
+ ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(),
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (tc && tc->targetAbi().os() == Abi::DarwinOS)
appendOutputParser(new XcodebuildParser);
@@ -168,13 +171,23 @@ bool QmakeMakeStep::init()
// it has a low priority.
m_scriptTarget = (static_cast<QmakeProject *>(bc->target()->project())->rootProjectNode()->projectType() == ProjectType::ScriptTemplate);
+ m_unalignedBuildDir = !bc->isBuildDirAtSafeLocation();
+
+ // A user doing "make clean" indicates they want a proper rebuild, so make sure to really
+ // execute qmake on the next build.
+ if (static_cast<BuildStepList *>(parent())->id()
+ == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
+ const auto qmakeStep = bc->qmakeStep();
+ if (qmakeStep)
+ qmakeStep->setForced(true);
+ }
return AbstractProcessStep::init();
}
void QmakeMakeStep::doRun()
{
- if (m_scriptTarget) {
+ if (m_scriptTarget || m_ignoredNonTopLevelBuild) {
emit finished(true);
return;
}
@@ -190,6 +203,18 @@ void QmakeMakeStep::doRun()
AbstractProcessStep::doRun();
}
+void QmakeMakeStep::finish(bool success)
+{
+ if (!success && !isCanceled() && m_unalignedBuildDir
+ && QmakeSettings::warnAgainstUnalignedBuildDir()) {
+ const QString msg = tr("The build directory is not at the same level as the source "
+ "directory, which could be the reason for the build failure.");
+ emit addTask(Task(Task::Warning, msg, Utils::FilePath(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ }
+ MakeStep::finish(success);
+}
+
///
// QmakeMakeStepFactory
///
diff --git a/src/plugins/qmakeprojectmanager/qmakemakestep.h b/src/plugins/qmakeprojectmanager/qmakemakestep.h
index 0a1cbe9198..a1bd2b1649 100644
--- a/src/plugins/qmakeprojectmanager/qmakemakestep.h
+++ b/src/plugins/qmakeprojectmanager/qmakemakestep.h
@@ -30,9 +30,6 @@
#include <projectexplorer/makestep.h>
namespace QmakeProjectManager {
-
-class QmakeBuildConfiguration;
-
namespace Internal {
class QmakeMakeStepFactory : public ProjectExplorer::BuildStepFactory
@@ -52,14 +49,15 @@ class QMAKEPROJECTMANAGER_EXPORT QmakeMakeStep : public ProjectExplorer::MakeSte
public:
explicit QmakeMakeStep(ProjectExplorer::BuildStepList *bsl);
- QmakeBuildConfiguration *qmakeBuildConfiguration() const;
-
+private:
+ void finish(bool success) override;
bool init() override;
void doRun() override;
-private:
bool m_scriptTarget = false;
QString m_makeFileToCheck;
+ bool m_unalignedBuildDir;
+ bool m_ignoredNonTopLevelBuild = false;
};
} // QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
index 1fc048e3ce..a71ab8c3d6 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
@@ -36,6 +36,7 @@
#include <utils/stringutils.h>
#include <android/androidconstants.h>
+#include <ios/iosconstants.h>
#include <QJsonDocument>
#include <QJsonObject>
@@ -52,7 +53,7 @@ namespace QmakeProjectManager {
*/
QmakePriFileNode::QmakePriFileNode(QmakeProject *project, QmakeProFileNode *qmakeProFileNode,
- const FileName &filePath, QmakePriFile *pf) :
+ const FilePath &filePath, QmakePriFile *pf) :
ProjectNode(filePath),
m_project(project),
m_qmakeProFileNode(qmakeProFileNode),
@@ -112,7 +113,7 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, const Node *node) co
return !(pro && pro->knowsFile(node->filePath()));
bool addExistingFiles = true;
- if (node->nodeType() == NodeType::VirtualFolder) {
+ if (node->isVirtualFolderType()) {
// A virtual folder, we do what the projectexplorer does
const FolderNode *folder = node->asFolderNode();
if (folder) {
@@ -132,21 +133,13 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, const Node *node) co
break;
}
case ProjectType::SubDirsTemplate:
- if (action == AddSubProject)
+ if (action == AddSubProject || action == AddExistingProject)
return true;
break;
default:
break;
}
- if (action == HasSubProjectRunConfigurations) {
- if (Target *t = m_project->activeTarget()) {
- auto canRunForNode = [node](RunConfiguration *rc) { return rc->canRunForNode(node); };
- if (Utils::anyOf(t->runConfigurations(), canRunForNode))
- return true;
- }
- }
-
return false;
}
@@ -168,13 +161,18 @@ bool QmakePriFileNode::removeSubProject(const QString &proFilePath)
return pri ? pri->removeSubProjects(proFilePath) : false;
}
+QStringList QmakePriFileNode::subProjectFileNamePatterns() const
+{
+ return QStringList("*.pro");
+}
+
bool QmakePriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
{
QmakePriFile *pri = priFile();
if (!pri)
return false;
QList<Node *> matchingNodes = findNodes([filePaths](const Node *n) {
- return n->nodeType() == NodeType::File && filePaths.contains(n->filePath().toString());
+ return n->asFileNode() && filePaths.contains(n->filePath().toString());
});
matchingNodes = filtered(matchingNodes, [](const Node *n) {
for (const Node *parent = n->parentFolderNode(); parent;
@@ -229,9 +227,11 @@ FolderNode::AddNewInformation QmakePriFileNode::addNewInformation(const QStringL
\class QmakeProFileNode
Implements abstract ProjectNode class
*/
-QmakeProFileNode::QmakeProFileNode(QmakeProject *project, const FileName &filePath, QmakeProFile *pf) :
+QmakeProFileNode::QmakeProFileNode(QmakeProject *project, const FilePath &filePath, QmakeProFile *pf) :
QmakePriFileNode(project, this, filePath, pf)
-{ }
+{
+ setIsProduct();
+}
bool QmakeProFileNode::showInSimpleTree() const
{
@@ -281,16 +281,32 @@ QVariant QmakeProFileNode::data(Core::Id role) const
if (role == Android::Constants::AndroidSoLibPath) {
TargetInformation info = targetInformation();
QStringList res = {info.buildDir.toString()};
- Utils::FileName destDir = info.destDir;
+ Utils::FilePath destDir = info.destDir;
if (!destDir.isEmpty()) {
if (destDir.toFileInfo().isRelative())
- destDir = Utils::FileName::fromString(QDir::cleanPath(info.buildDir.toString()
+ destDir = Utils::FilePath::fromString(QDir::cleanPath(info.buildDir.toString()
+ '/' + destDir.toString()));
res.append(destDir.toString());
}
res.removeDuplicates();
return res;
}
+
+ if (role == Android::Constants::AndroidTargets)
+ return {};
+
+ if (role == Ios::Constants::IosTarget) {
+ const TargetInformation info = targetInformation();
+ if (info.valid)
+ return info.target;
+ }
+
+ if (role == Ios::Constants::IosBuildDir) {
+ const TargetInformation info = targetInformation();
+ if (info.valid)
+ return info.buildDir.toString();
+ }
+
QTC_CHECK(false);
return {};
}
@@ -397,10 +413,10 @@ QString QmakeProFileNode::buildDir() const
return QString();
}
-FileName QmakeProFileNode::buildDir(QmakeBuildConfiguration *bc) const
+FilePath QmakeProFileNode::buildDir(QmakeBuildConfiguration *bc) const
{
const QmakeProFile *pro = proFile();
- return pro ? pro->buildDir(bc) : FileName();
+ return pro ? pro->buildDir(bc) : FilePath();
}
QString QmakeProFileNode::objectExtension() const
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.h b/src/plugins/qmakeprojectmanager/qmakenodes.h
index 2f29eac5e4..92b84fbcb0 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.h
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.h
@@ -30,7 +30,7 @@
#include <projectexplorer/projectnodes.h>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace QmakeProjectManager {
class QmakeProFileNode;
@@ -41,7 +41,7 @@ class QMAKEPROJECTMANAGER_EXPORT QmakePriFileNode : public ProjectExplorer::Proj
{
public:
QmakePriFileNode(QmakeProject *project, QmakeProFileNode *qmakeProFileNode,
- const Utils::FileName &filePath, QmakePriFile *pf);
+ const Utils::FilePath &filePath, QmakePriFile *pf);
QmakePriFile *priFile() const;
@@ -51,9 +51,9 @@ public:
bool showInSimpleTree() const override { return false; }
bool canAddSubProject(const QString &proFilePath) const override;
-
bool addSubProject(const QString &proFilePath) override;
bool removeSubProject(const QString &proFilePath) override;
+ QStringList subProjectFileNamePatterns() const override;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;
@@ -78,7 +78,7 @@ private:
class QMAKEPROJECTMANAGER_EXPORT QmakeProFileNode : public QmakePriFileNode
{
public:
- QmakeProFileNode(QmakeProject *project, const Utils::FileName &filePath, QmakeProFile *pf);
+ QmakeProFileNode(QmakeProject *project, const Utils::FilePath &filePath, QmakeProFile *pf);
QmakeProFile *proFile() const;
@@ -104,7 +104,7 @@ public:
QmakeProjectManager::ProjectType projectType() const;
QString buildDir() const;
- Utils::FileName buildDir(QmakeBuildConfiguration *bc) const;
+ Utils::FilePath buildDir(QmakeBuildConfiguration *bc) const;
QStringList variableValue(const Variable var) const;
QString singleVariableValue(const Variable var) const;
diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
index 253f9939d2..d2fc8051de 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
@@ -128,7 +128,7 @@ void clearQmakeStaticData()
namespace QmakeProjectManager {
-static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const FileNameList &toExclude)
+static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const FilePathList &toExclude)
{
QTC_ASSERT(pri, return);
QTC_ASSERT(node, return);
@@ -137,24 +137,35 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const Fi
node->setIcon(qmakeStaticData()->projectIcon);
// .pro/.pri-file itself:
- node->addNode(std::make_unique<FileNode>(pri->filePath(), FileType::Project, false));
+ node->addNode(std::make_unique<FileNode>(pri->filePath(), FileType::Project));
// other normal files:
const QVector<QmakeStaticData::FileTypeData> &fileTypes = qmakeStaticData()->fileTypeData;
+ FilePathList generatedFiles;
+ const auto proFile = dynamic_cast<const QmakeProFile *>(pri);
for (int i = 0; i < fileTypes.size(); ++i) {
FileType type = fileTypes.at(i).type;
- const QSet<FileName> &newFilePaths = Utils::filtered(pri->files(type), [&toExclude](const Utils::FileName &fn) {
- return !Utils::contains(toExclude, [&fn](const Utils::FileName &ex) { return fn.isChildOf(ex); });
+ const QSet<FilePath> &newFilePaths = Utils::filtered(pri->files(type), [&toExclude](const Utils::FilePath &fn) {
+ return !Utils::contains(toExclude, [&fn](const Utils::FilePath &ex) { return fn.isChildOf(ex); });
});
+ if (proFile) {
+ for (const FilePath &fp : newFilePaths) {
+ for (const ExtraCompiler *ec : proFile->extraCompilers()) {
+ if (ec->source() == fp)
+ generatedFiles << ec->targets();
+ }
+ }
+ }
if (!newFilePaths.isEmpty()) {
- auto vfolder = std::make_unique<VirtualFolderNode>(pri->filePath().parentDir(), Node::DefaultVirtualFolderPriority - i);
+ auto vfolder = std::make_unique<VirtualFolderNode>(pri->filePath().parentDir());
+ vfolder->setPriority(Node::DefaultVirtualFolderPriority - i);
vfolder->setIcon(fileTypes.at(i).icon);
vfolder->setDisplayName(fileTypes.at(i).typeName);
vfolder->setAddFileFilter(fileTypes.at(i).addFileFilter);
if (type == FileType::Resource) {
- for (const FileName &file : newFilePaths) {
+ for (const FilePath &file : newFilePaths) {
auto vfs = pri->project()->qmakeVfs();
QString contents;
QString errorMessage;
@@ -167,18 +178,20 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const Fi
int eid = vfs->idForFileName(file.toString(), QMakeVfs::VfsExact);
vfs->readFile(eid, &contents, &errorMessage);
}
+ auto topLevel = std::make_unique<ResourceEditor::ResourceTopLevelNode>
+ (file, vfolder->filePath(), contents);
const QString baseName = file.toFileInfo().completeBaseName();
- const bool generated = baseName.startsWith("qmake_")
- || baseName.endsWith("_qmlcache");
- vfolder->addNode(std::make_unique<ResourceEditor::ResourceTopLevelNode>(file, generated, contents, vfolder.get()));
+ topLevel->setIsGenerated(baseName.startsWith("qmake_")
+ || baseName.endsWith("_qmlcache"));
+ vfolder->addNode(std::move(topLevel));
}
} else {
- for (const FileName &fn : newFilePaths) {
+ for (const FilePath &fn : newFilePaths) {
// Qmake will flag everything in SOURCES as source, even when the
// qt quick compiler moves qrc files into it:-/ Get better data based on
// the filename.
type = FileNode::fileTypeForFileName(fn);
- vfolder->addNestedNode(std::make_unique<FileNode>(fn, type, false));
+ vfolder->addNestedNode(std::make_unique<FileNode>(fn, type));
}
for (FolderNode *fn : vfolder->folderNodes())
fn->compress();
@@ -187,6 +200,22 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const Fi
}
}
+ if (!generatedFiles.empty()) {
+ QTC_CHECK(proFile);
+ const FilePath baseDir = generatedFiles.size() == 1 ? generatedFiles.first().parentDir()
+ : proFile->buildDir();
+ auto genFolder = std::make_unique<VirtualFolderNode>(baseDir);
+ genFolder->setDisplayName(QCoreApplication::translate("QmakeProjectManager::QmakePriFile",
+ "Generated Files"));
+ genFolder->setIsGenerated(true);
+ for (const FilePath &fp : generatedFiles) {
+ auto fileNode = std::make_unique<FileNode>(fp, FileNode::fileTypeForFileName(fp));
+ fileNode->setIsGenerated(true);
+ genFolder->addNestedNode(std::move(fileNode));
+ }
+ node->addNode(std::move(genFolder));
+ }
+
// Virtual folders:
for (QmakePriFile *c : pri->children()) {
std::unique_ptr<QmakePriFileNode> newNode;
@@ -204,9 +233,9 @@ std::unique_ptr<QmakeProFileNode> QmakeNodeTreeBuilder::buildTree(QmakeProject *
// Remove qmake implementation details that litter up the project data:
Target *t = project->activeTarget();
Kit *k = t ? t->kit() : KitManager::defaultKit();
- BaseQtVersion *qt = k ? QtKitInformation::qtVersion(k) : nullptr;
+ BaseQtVersion *qt = k ? QtKitAspect::qtVersion(k) : nullptr;
- const FileNameList toExclude = qt ? qt->directoriesToIgnoreInProjectTree() : FileNameList();
+ const FilePathList toExclude = qt ? qt->directoriesToIgnoreInProjectTree() : FilePathList();
auto root = std::make_unique<QmakeProFileNode>(project, project->projectFilePath(),
project->rootProFile());
diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.h b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.h
index 2206ac904e..be3240da3c 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.h
+++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.h
@@ -29,7 +29,7 @@
#include "qmakeparsernodes.h"
#include "qmakenodes.h"
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace ProjectExplorer { class RunConfiguration; }
namespace QmakeProjectManager {
diff --git a/src/plugins/qmakeprojectmanager/qmakeparser.cpp b/src/plugins/qmakeprojectmanager/qmakeparser.cpp
index 4af888cc2c..ed6abf5ca7 100644
--- a/src/plugins/qmakeprojectmanager/qmakeparser.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeparser.cpp
@@ -59,7 +59,7 @@ void QMakeParser::stdError(const QString &line)
type = Task::Error;
Task task = Task(type,
description,
- Utils::FileName::fromUserInput(fileName),
+ Utils::FilePath::fromUserInput(fileName),
m_error.cap(2).toInt() /* line */,
Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
emit addTask(task, 1);
@@ -70,7 +70,7 @@ void QMakeParser::stdError(const QString &line)
const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2);
Task task = Task(Task::Error,
description,
- Utils::FileName() /* filename */,
+ Utils::FilePath() /* filename */,
-1 /* linenumber */,
Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
emit addTask(task, 1);
@@ -81,7 +81,7 @@ void QMakeParser::stdError(const QString &line)
const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2);
Task task = Task(Task::Warning,
description,
- Utils::FileName() /* filename */,
+ Utils::FilePath() /* filename */,
-1 /* linenumber */,
Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
emit addTask(task, 1);
@@ -110,29 +110,29 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
QTest::newRow("pass-through stdout")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<ProjectExplorer::Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<ProjectExplorer::Task>()
+ << Tasks()
<< QString();
QTest::newRow("qMake error")
<< QString::fromLatin1("Project ERROR: undefined file")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("undefined file"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryBuildSystem))
<< QString();
@@ -140,10 +140,10 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers_data()
<< QString::fromLatin1("e:\\project.pro:14: Parse Error ('sth odd')")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Error,
QLatin1String("Parse Error ('sth odd')"),
- Utils::FileName::fromUserInput(QLatin1String("e:\\project.pro")),
+ Utils::FilePath::fromUserInput(QLatin1String("e:\\project.pro")),
14,
categoryBuildSystem))
<< QString();
@@ -152,10 +152,10 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers_data()
<< QString::fromLatin1("Project WARNING: bearer module might require ReadUserData capability")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("bearer module might require ReadUserData capability"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryBuildSystem))
<< QString();
@@ -163,10 +163,10 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers_data()
<< QString::fromLatin1("WARNING: Failure to find: blackberrycreatepackagestepconfigwidget.cpp")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("Failure to find: blackberrycreatepackagestepconfigwidget.cpp"),
- Utils::FileName(), -1,
+ Utils::FilePath(), -1,
categoryBuildSystem))
<< QString();
@@ -174,20 +174,20 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers_data()
<< QString::fromLatin1("WARNING: e:\\QtSDK\\Simulator\\Qt\\msvc2008\\lib\\qtmaind.prl:1: Unescaped backslashes are deprecated.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Warning,
QLatin1String("Unescaped backslashes are deprecated."),
- Utils::FileName::fromUserInput(QLatin1String("e:\\QtSDK\\Simulator\\Qt\\msvc2008\\lib\\qtmaind.prl")), 1,
+ Utils::FilePath::fromUserInput(QLatin1String("e:\\QtSDK\\Simulator\\Qt\\msvc2008\\lib\\qtmaind.prl")), 1,
categoryBuildSystem))
<< QString();
QTest::newRow("moc note")
<< QString::fromLatin1("/home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>()
+ << (Tasks()
<< Task(Task::Unknown,
QLatin1String("Note: No relevant classes found. No output generated."),
- Utils::FileName::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
categoryBuildSystem)
)
<< QString();}
@@ -198,7 +198,7 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers()
testbench.appendOutputParser(new QMakeParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
index dad44e2f6b..c9fce5bb9a 100644
--- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
@@ -29,7 +29,6 @@
#include "qmakeprojectmanagerconstants.h"
#include "qmakebuildconfiguration.h"
-#include <coreplugin/dialogs/readonlyfilesdialog.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
@@ -69,7 +68,7 @@ namespace {
class QmakePriFileDocument : public Core::IDocument
{
public:
- QmakePriFileDocument(QmakePriFile *qmakePriFile, const Utils::FileName &filePath) :
+ QmakePriFileDocument(QmakePriFile *qmakePriFile, const Utils::FilePath &filePath) :
IDocument(nullptr), m_priFile(qmakePriFile)
{
setId("Qmake.PriFile");
@@ -111,9 +110,9 @@ class QmakeEvalInput
{
public:
QString projectDir;
- FileName projectFilePath;
- FileName buildDirectory;
- FileName sysroot;
+ FilePath projectFilePath;
+ FilePath buildDirectory;
+ FilePath sysroot;
QtSupport::ProFileReader *readerExact;
QtSupport::ProFileReader *readerCumulative;
QMakeGlobals *qmakeGlobals;
@@ -123,18 +122,18 @@ public:
class QmakePriFileEvalResult
{
public:
- QSet<FileName> folders;
- QSet<FileName> recursiveEnumerateFiles;
- QMap<FileType, QSet<FileName>> foundFiles;
+ QSet<FilePath> folders;
+ QSet<FilePath> recursiveEnumerateFiles;
+ QMap<FileType, QSet<FilePath>> foundFiles;
};
class QmakeIncludedPriFile
{
public:
ProFile *proFile;
- Utils::FileName name;
+ Utils::FilePath name;
QmakePriFileEvalResult result;
- QMap<Utils::FileName, QmakeIncludedPriFile *> children;
+ QMap<Utils::FilePath, QmakeIncludedPriFile *> children;
~QmakeIncludedPriFile()
{
@@ -150,7 +149,7 @@ public:
ProjectType projectType;
QStringList subProjectsNotToDeploy;
- QSet<FileName> exactSubdirs;
+ QSet<FilePath> exactSubdirs;
QmakeIncludedPriFile includedFiles;
TargetInformation targetInformation;
InstallsList installsList;
@@ -162,7 +161,7 @@ public:
} // namespace Internal
QmakePriFile::QmakePriFile(QmakeProject *project, QmakeProFile *qmakeProFile,
- const FileName &filePath) :
+ const FilePath &filePath) :
m_project(project),
m_qmakeProFile(qmakeProFile)
{
@@ -171,12 +170,12 @@ QmakePriFile::QmakePriFile(QmakeProject *project, QmakeProFile *qmakeProFile,
Core::DocumentManager::addDocument(m_priFileDocument.get());
}
-FileName QmakePriFile::filePath() const
+FilePath QmakePriFile::filePath() const
{
return m_priFileDocument->filePath();
}
-FileName QmakePriFile::directoryPath() const
+FilePath QmakePriFile::directoryPath() const
{
return filePath().parentDir();
}
@@ -201,7 +200,7 @@ QVector<QmakePriFile *> QmakePriFile::children() const
return m_children;
}
-QmakePriFile *QmakePriFile::findPriFile(const FileName &fileName)
+QmakePriFile *QmakePriFile::findPriFile(const FilePath &fileName)
{
if (fileName == filePath())
return this;
@@ -212,7 +211,7 @@ QmakePriFile *QmakePriFile::findPriFile(const FileName &fileName)
return nullptr;
}
-const QmakePriFile *QmakePriFile::findPriFile(const FileName &fileName) const
+const QmakePriFile *QmakePriFile::findPriFile(const FilePath &fileName) const
{
if (fileName == filePath())
return this;
@@ -229,14 +228,14 @@ void QmakePriFile::makeEmpty()
m_children.clear();
}
-QSet<FileName> QmakePriFile::files(const FileType &type) const
+QSet<FilePath> QmakePriFile::files(const FileType &type) const
{
return m_files.value(type);
}
-const QSet<FileName> QmakePriFile::collectFiles(const FileType &type) const
+const QSet<FilePath> QmakePriFile::collectFiles(const FileType &type) const
{
- QSet<FileName> allFiles = files(type);
+ QSet<FilePath> allFiles = files(type);
for (const QmakePriFile * const priFile : qAsConst(m_children)) {
if (!dynamic_cast<const QmakeProFile *>(priFile))
allFiles.unite(priFile->collectFiles(type));
@@ -281,16 +280,16 @@ QStringList QmakePriFile::fullVPaths(const QStringList &baseVPaths, QtSupport::P
return vPaths;
}
-QSet<FileName> QmakePriFile::recursiveEnumerate(const QString &folder)
+QSet<FilePath> QmakePriFile::recursiveEnumerate(const QString &folder)
{
- QSet<FileName> result;
+ QSet<FilePath> result;
QDir dir(folder);
dir.setFilter(dir.filter() | QDir::NoDotAndDotDot);
foreach (const QFileInfo &file, dir.entryInfoList()) {
if (file.isDir() && !file.isSymLink())
result += recursiveEnumerate(file.absoluteFilePath());
else if (!Core::EditorManager::isAutoSaveFile(file.fileName()))
- result += FileName(file);
+ result += FilePath::fromFileInfo(file);
}
return result;
}
@@ -315,7 +314,7 @@ void QmakePriFile::extractSources(
auto *result = proToResult.value(source.proFileId);
if (!result)
result = fallback;
- result->foundFiles[type].insert(FileName::fromString(source.fileName));
+ result->foundFiles[type].insert(FilePath::fromString(source.fileName));
}
}
@@ -328,7 +327,7 @@ void QmakePriFile::extractInstalls(
auto *result = proToResult.value(source.proFileId);
if (!result)
result = fallback;
- result->folders.insert(FileName::fromString(source.fileName));
+ result->folders.insert(FilePath::fromString(source.fileName));
}
}
}
@@ -357,9 +356,9 @@ void QmakePriFile::processValues(QmakePriFileEvalResult &result)
for (int i = 0; i < static_cast<int>(FileType::FileTypeSize); ++i) {
auto type = static_cast<FileType>(i);
- QSet<FileName> &foundFiles = result.foundFiles[type];
+ QSet<FilePath> &foundFiles = result.foundFiles[type];
result.recursiveEnumerateFiles.subtract(foundFiles);
- QSet<FileName> newFilePaths = filterFilesProVariables(type, foundFiles);
+ QSet<FilePath> newFilePaths = filterFilesProVariables(type, foundFiles);
newFilePaths += filterFilesRecursiveEnumerata(type, result.recursiveEnumerateFiles);
foundFiles = newFilePaths;
}
@@ -376,10 +375,10 @@ void QmakePriFile::update(const Internal::QmakePriFileEvalResult &result)
}
}
-void QmakePriFile::watchFolders(const QSet<FileName> &folders)
+void QmakePriFile::watchFolders(const QSet<FilePath> &folders)
{
const QSet<QString> folderStrings =
- Utils::transform(folders, &FileName::toString);
+ Utils::transform(folders, &FilePath::toString);
QSet<QString> toUnwatch = m_watchedFolders;
toUnwatch.subtract(folderStrings);
@@ -405,23 +404,23 @@ QString QmakePriFile::continuationIndent() const
return QString(tabSettings.m_indentSize, ' ');
}
-bool QmakePriFile::knowsFile(const FileName &filePath) const
+bool QmakePriFile::knowsFile(const FilePath &filePath) const
{
return m_recursiveEnumerateFiles.contains(filePath);
}
-bool QmakePriFile::folderChanged(const QString &changedFolder, const QSet<FileName> &newFiles)
+bool QmakePriFile::folderChanged(const QString &changedFolder, const QSet<FilePath> &newFiles)
{
qCDebug(qmakeParse()) << "QmakePriFile::folderChanged";
- QSet<FileName> addedFiles = newFiles;
+ QSet<FilePath> addedFiles = newFiles;
addedFiles.subtract(m_recursiveEnumerateFiles);
- QSet<FileName> removedFiles = m_recursiveEnumerateFiles;
+ QSet<FilePath> removedFiles = m_recursiveEnumerateFiles;
removedFiles.subtract(newFiles);
- foreach (const FileName &file, removedFiles) {
- if (!file.isChildOf(FileName::fromString(changedFolder)))
+ foreach (const FilePath &file, removedFiles) {
+ if (!file.isChildOf(FilePath::fromString(changedFolder)))
removedFiles.remove(file);
}
@@ -433,8 +432,8 @@ bool QmakePriFile::folderChanged(const QString &changedFolder, const QSet<FileNa
// Apply the differences per file type
for (int i = 0; i < static_cast<int>(FileType::FileTypeSize); ++i) {
auto type = static_cast<FileType>(i);
- QSet<FileName> add = filterFilesRecursiveEnumerata(type, addedFiles);
- QSet<FileName> remove = filterFilesRecursiveEnumerata(type, removedFiles);
+ QSet<FilePath> add = filterFilesRecursiveEnumerata(type, addedFiles);
+ QSet<FilePath> remove = filterFilesRecursiveEnumerata(type, removedFiles);
if (!add.isEmpty() || !remove.isEmpty()) {
qCDebug(qmakeParse()) << "For type" << static_cast<int>(type) <<"\n"
@@ -508,7 +507,7 @@ static QString simplifyProFilePath(const QString &proFilePath)
bool QmakePriFile::addSubProject(const QString &proFile)
{
QStringList uniqueProFilePaths;
- if (!m_recursiveEnumerateFiles.contains(FileName::fromString(proFile)))
+ if (!m_recursiveEnumerateFiles.contains(FilePath::fromString(proFile)))
uniqueProFilePaths.append(simplifyProFilePath(proFile));
QStringList failedFiles;
@@ -560,13 +559,13 @@ bool QmakePriFile::addFiles(const QStringList &filePaths, QStringList *notAdded)
QStringList uniqueQrcFiles;
foreach (const QString &file, qrcFiles) {
- if (!m_recursiveEnumerateFiles.contains(FileName::fromString(file)))
+ if (!m_recursiveEnumerateFiles.contains(FilePath::fromString(file)))
uniqueQrcFiles.append(file);
}
QStringList uniqueFilePaths;
foreach (const QString &file, typeFiles) {
- if (!m_recursiveEnumerateFiles.contains(FileName::fromString(file)))
+ if (!m_recursiveEnumerateFiles.contains(FilePath::fromString(file)))
uniqueFilePaths.append(file);
}
uniqueFilePaths.sort();
@@ -633,13 +632,6 @@ bool QmakePriFile::renameFile(const QString &filePath, const QString &newFilePat
return changeProFileOptional;
}
-bool QmakePriFile::priFileWritable(const QString &path)
-{
- ReadOnlyFilesDialog roDialog(path, ICore::mainWindow());
- roDialog.setShowFailWarning(true);
- return roDialog.exec() != ReadOnlyFilesDialog::RO_Cancel;
-}
-
bool QmakePriFile::saveModifiedEditors()
{
Core::IDocument *document
@@ -886,8 +878,7 @@ QStringList QmakePriFile::varNames(FileType type, QtSupport::ProFileReader *read
QStringList vars;
switch (type) {
case FileType::Header:
- vars << QLatin1String("HEADERS");
- vars << QLatin1String("PRECOMPILED_HEADER");
+ vars << "HEADERS" << "OBJECTIVE_HEADERS" << "PRECOMPILED_HEADER";
break;
case FileType::Source: {
vars << QLatin1String("SOURCES");
@@ -896,12 +887,15 @@ QStringList QmakePriFile::varNames(FileType type, QtSupport::ProFileReader *read
QStringList inputs = readerExact->values(var + QLatin1String(".input"));
foreach (const QString &input, inputs)
// FORMS, RESOURCES, and STATECHARTS are handled below, HEADERS and SOURCES above
- if (input != QLatin1String("FORMS")
- && input != QLatin1String("STATECHARTS")
- && input != QLatin1String("RESOURCES")
- && input != QLatin1String("SOURCES")
- && input != QLatin1String("HEADERS"))
+ if (input != "FORMS"
+ && input != "STATECHARTS"
+ && input != "RESOURCES"
+ && input != "SOURCES"
+ && input != "HEADERS"
+ && input != "OBJECTIVE_HEADERS"
+ && input != "PRECOMPILED_HEADER") {
vars << input;
+ }
}
break;
}
@@ -994,34 +988,34 @@ QStringList QmakePriFile::varNamesForRemoving()
return vars;
}
-QSet<FileName> QmakePriFile::filterFilesProVariables(FileType fileType, const QSet<FileName> &files)
+QSet<FilePath> QmakePriFile::filterFilesProVariables(FileType fileType, const QSet<FilePath> &files)
{
if (fileType != FileType::QML && fileType != FileType::Unknown)
return files;
- QSet<FileName> result;
+ QSet<FilePath> result;
if (fileType == FileType::QML) {
- foreach (const FileName &file, files)
+ foreach (const FilePath &file, files)
if (file.toString().endsWith(QLatin1String(".qml")))
result << file;
} else {
- foreach (const FileName &file, files)
+ foreach (const FilePath &file, files)
if (!file.toString().endsWith(QLatin1String(".qml")))
result << file;
}
return result;
}
-QSet<FileName> QmakePriFile::filterFilesRecursiveEnumerata(FileType fileType, const QSet<FileName> &files)
+QSet<FilePath> QmakePriFile::filterFilesRecursiveEnumerata(FileType fileType, const QSet<FilePath> &files)
{
- QSet<FileName> result;
+ QSet<FilePath> result;
if (fileType != FileType::QML && fileType != FileType::Unknown)
return result;
if (fileType == FileType::QML) {
- foreach (const FileName &file, files)
+ foreach (const FilePath &file, files)
if (file.toString().endsWith(QLatin1String(".qml")))
result << file;
} else {
- foreach (const FileName &file, files)
+ foreach (const FilePath &file, files)
if (!file.toString().endsWith(QLatin1String(".qml")))
result << file;
}
@@ -1051,12 +1045,12 @@ static ProjectType proFileTemplateTypeToProjectType(ProFileEvaluator::TemplateTy
}
}
-QmakeProFile *QmakeProFile::findProFile(const FileName &fileName)
+QmakeProFile *QmakeProFile::findProFile(const FilePath &fileName)
{
return static_cast<QmakeProFile *>(findPriFile(fileName));
}
-const QmakeProFile *QmakeProFile::findProFile(const FileName &fileName) const
+const QmakeProFile *QmakeProFile::findProFile(const FilePath &fileName) const
{
return static_cast<const QmakeProFile *>(findPriFile(fileName));
}
@@ -1093,7 +1087,7 @@ QByteArray QmakeProFile::cxxDefines() const
\class QmakeProFile
Implements abstract ProjectNode class
*/
-QmakeProFile::QmakeProFile(QmakeProject *project, const FileName &filePath) :
+QmakeProFile::QmakeProFile(QmakeProject *project, const FilePath &filePath) :
QmakePriFile(project, this, filePath)
{
// The lifetime of the m_parserFutureWatcher is shorter
@@ -1221,7 +1215,7 @@ QmakeEvalInput QmakeProFile::evalInput() const
input.projectDir = directoryPath().toString();
input.projectFilePath = filePath();
input.buildDirectory = buildDir();
- input.sysroot = FileName::fromString(m_project->qmakeSysroot());
+ input.sysroot = FilePath::fromString(m_project->qmakeSysroot());
input.readerExact = m_readerExact;
input.readerCumulative = m_readerCumulative;
input.qmakeGlobals = m_project->qmakeGlobals();
@@ -1308,10 +1302,10 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
if (result->state == QmakeEvalResult::EvalOk) {
if (result->projectType == ProjectType::SubDirsTemplate) {
QStringList errors;
- FileNameList subDirs = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors);
+ FilePathList subDirs = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors);
result->errors.append(errors);
- foreach (const Utils::FileName &subDirName, subDirs) {
+ foreach (const Utils::FilePath &subDirName, subDirs) {
auto subDir = new QmakeIncludedPriFile;
subDir->proFile = nullptr;
subDir->name = subDirName;
@@ -1330,7 +1324,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
continue; // Don't attempt to map subdirs here
QVector<ProFile *> children = includeFiles.value(current->proFile);
foreach (ProFile *child, children) {
- const Utils::FileName childName = Utils::FileName::fromString(child->fileName());
+ const Utils::FilePath childName = Utils::FilePath::fromString(child->fileName());
auto it = current->children.find(childName);
if (it == current->children.end()) {
auto childTree = new QmakeIncludedPriFile;
@@ -1345,8 +1339,8 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
}
if (result->projectType == ProjectType::SubDirsTemplate) {
- FileNameList subDirs = subDirsPaths(input.readerCumulative, input.projectDir, nullptr, nullptr);
- foreach (const Utils::FileName &subDirName, subDirs) {
+ FilePathList subDirs = subDirsPaths(input.readerCumulative, input.projectDir, nullptr, nullptr);
+ foreach (const Utils::FilePath &subDirName, subDirs) {
auto it = result->includedFiles.children.find(subDirName);
if (it == result->includedFiles.children.end()) {
auto subDir = new QmakeIncludedPriFile;
@@ -1366,7 +1360,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
continue; // Don't attempt to map subdirs here
QVector<ProFile *> children = includeFiles.value(current->proFile);
foreach (ProFile *child, children) {
- const Utils::FileName childName = Utils::FileName::fromString(child->fileName());
+ const Utils::FilePath childName = Utils::FilePath::fromString(child->fileName());
auto it = current->children.find(childName);
if (it == current->children.end()) {
auto childTree = new QmakeIncludedPriFile;
@@ -1564,7 +1558,7 @@ void QmakeProFile::applyEvaluate(QmakeEvalResult *evalResult)
// Add/Remove pri files, sub projects
//
- FileName buildDirectory = buildDir();
+ FilePath buildDirectory = buildDir();
QList<QPair<QmakePriFile *, QmakeIncludedPriFile *>> toCompare;
@@ -1619,13 +1613,14 @@ void QmakeProFile::applyEvaluate(QmakeEvalResult *evalResult)
m_subProjectsNotToDeploy
= Utils::transform(result->subProjectsNotToDeploy,
- [](const QString &s) { return FileName::fromString(s); });
+ [](const QString &s) { return FilePath::fromString(s); });
m_installsList = result->installsList;
if (m_varValues != result->newVarValues)
m_varValues = result->newVarValues;
m_displayName = singleVariableValue(Variable::QmakeProjectName);
+ m_featureRoots = m_readerExact->featureRoots();
} // result == EvalOk
if (!result->directoriesWithWildcards.isEmpty()) {
@@ -1686,7 +1681,7 @@ void QmakeProFile::cleanupProFileReaders()
m_readerCumulative = nullptr;
}
-QString QmakeProFile::uiDirPath(QtSupport::ProFileReader *reader, const FileName &buildDir)
+QString QmakeProFile::uiDirPath(QtSupport::ProFileReader *reader, const FilePath &buildDir)
{
QString path = reader->value(QLatin1String("UI_DIR"));
if (QFileInfo(path).isRelative())
@@ -1694,7 +1689,7 @@ QString QmakeProFile::uiDirPath(QtSupport::ProFileReader *reader, const FileName
return path;
}
-QString QmakeProFile::mocDirPath(QtSupport::ProFileReader *reader, const FileName &buildDir)
+QString QmakeProFile::mocDirPath(QtSupport::ProFileReader *reader, const FilePath &buildDir)
{
QString path = reader->value(QLatin1String("MOC_DIR"));
if (QFileInfo(path).isRelative())
@@ -1718,8 +1713,8 @@ QString QmakeProFile::sysrootify(const QString &path, const QString &sysroot,
return !IoUtils::exists(sysrooted) ? path : sysrooted;
}
-QStringList QmakeProFile::includePaths(QtSupport::ProFileReader *reader, const FileName &sysroot,
- const FileName &buildDir, const QString &projectDir)
+QStringList QmakeProFile::includePaths(QtSupport::ProFileReader *reader, const FilePath &sysroot,
+ const FilePath &buildDir, const QString &projectDir)
{
QStringList paths;
bool nextIsAnIncludePath = false;
@@ -1757,12 +1752,12 @@ QStringList QmakeProFile::libDirectories(QtSupport::ProFileReader *reader)
return result;
}
-FileNameList QmakeProFile::subDirsPaths(QtSupport::ProFileReader *reader,
+FilePathList QmakeProFile::subDirsPaths(QtSupport::ProFileReader *reader,
const QString &projectDir,
QStringList *subProjectsNotToDeploy,
QStringList *errors)
{
- FileNameList subProjectPaths;
+ FilePathList subProjectPaths;
const QStringList subDirVars = reader->values(QLatin1String("SUBDIRS"));
@@ -1796,7 +1791,7 @@ FileNameList QmakeProFile::subDirsPaths(QtSupport::ProFileReader *reader,
if (QFile::exists(realFile)) {
realFile = QDir::cleanPath(realFile);
- subProjectPaths << FileName::fromString(realFile);
+ subProjectPaths << FilePath::fromString(realFile);
if (subProjectsNotToDeploy && !subProjectsNotToDeploy->contains(realFile)
&& reader->values(subDirVar + QLatin1String(".CONFIG"))
.contains(QLatin1String("no_default_target"))) {
@@ -1814,8 +1809,8 @@ FileNameList QmakeProFile::subDirsPaths(QtSupport::ProFileReader *reader,
TargetInformation QmakeProFile::targetInformation(QtSupport::ProFileReader *reader,
QtSupport::ProFileReader *readerBuildPass,
- const FileName &buildDir,
- const FileName &projectFilePath)
+ const FilePath &buildDir,
+ const FilePath &projectFilePath)
{
TargetInformation result;
if (!reader || !readerBuildPass)
@@ -1831,7 +1826,7 @@ TargetInformation QmakeProFile::targetInformation(QtSupport::ProFileReader *read
result.buildDir = buildDir;
if (readerBuildPass->contains(QLatin1String("DESTDIR")))
- result.destDir = FileName::fromString(readerBuildPass->value(QLatin1String("DESTDIR")));
+ result.destDir = FilePath::fromString(readerBuildPass->value(QLatin1String("DESTDIR")));
// Target
result.target = readerBuildPass->value(QLatin1String("TARGET"));
@@ -1905,12 +1900,12 @@ InstallsList QmakeProFile::installsList() const
return m_installsList;
}
-FileName QmakeProFile::sourceDir() const
+FilePath QmakeProFile::sourceDir() const
{
return directoryPath();
}
-FileName QmakeProFile::buildDir(QmakeBuildConfiguration *bc) const
+FilePath QmakeProFile::buildDir(QmakeBuildConfiguration *bc) const
{
const QDir srcDirRoot = QDir(m_project->projectDirectory().toString());
const QString relativeDir = srcDirRoot.relativeFilePath(directoryPath().toString());
@@ -1920,11 +1915,11 @@ FileName QmakeProFile::buildDir(QmakeBuildConfiguration *bc) const
const QString buildDir = buildConfigBuildDir.isEmpty()
? m_project->projectDirectory().toString()
: buildConfigBuildDir;
- return FileName::fromString(QDir::cleanPath(QDir(buildDir).absoluteFilePath(relativeDir)));
+ return FilePath::fromString(QDir::cleanPath(QDir(buildDir).absoluteFilePath(relativeDir)));
}
-FileNameList QmakeProFile::generatedFiles(const FileName &buildDir,
- const FileName &sourceFile,
+FilePathList QmakeProFile::generatedFiles(const FilePath &buildDir,
+ const FilePath &sourceFile,
const FileType &sourceFileType) const
{
// The mechanism for finding the file names is rather crude, but as we
@@ -1933,29 +1928,26 @@ FileNameList QmakeProFile::generatedFiles(const FileName &buildDir,
// cannot help doing this here.
if (sourceFileType == FileType::Form) {
- FileName location;
+ FilePath location;
auto it = m_varValues.constFind(Variable::UiDir);
if (it != m_varValues.constEnd() && !it.value().isEmpty())
- location = FileName::fromString(it.value().front());
+ location = FilePath::fromString(it.value().front());
else
location = buildDir;
if (location.isEmpty())
return { };
- location.appendPath(QLatin1String("ui_")
- + sourceFile.toFileInfo().completeBaseName()
- + singleVariableValue(Variable::HeaderExtension));
- return { Utils::FileName::fromString(QDir::cleanPath(location.toString())) };
+ location = location.pathAppended("ui_"
+ + sourceFile.toFileInfo().completeBaseName()
+ + singleVariableValue(Variable::HeaderExtension));
+ return { Utils::FilePath::fromString(QDir::cleanPath(location.toString())) };
} else if (sourceFileType == FileType::StateChart) {
if (buildDir.isEmpty())
return { };
- FileName location = buildDir;
- location.appendPath(sourceFile.toFileInfo().completeBaseName());
- FileName header = location;
- header.appendString(singleVariableValue(Variable::HeaderExtension));
- FileName cpp = location;
- cpp.appendString(singleVariableValue(Variable::CppExtension));
-
- return { header, cpp };
+ const FilePath location = buildDir.pathAppended(sourceFile.toFileInfo().completeBaseName());
+ return {
+ location.stringAppended(singleVariableValue(Variable::HeaderExtension)),
+ location.stringAppended(singleVariableValue(Variable::CppExtension))
+ };
}
return { };
}
@@ -1965,17 +1957,17 @@ QList<ExtraCompiler *> QmakeProFile::extraCompilers() const
return m_extraCompilers;
}
-void QmakeProFile::setupExtraCompiler(const FileName &buildDir,
+void QmakeProFile::setupExtraCompiler(const FilePath &buildDir,
const FileType &fileType, ExtraCompilerFactory *factory)
{
- for (const FileName &fn : collectFiles(fileType)) {
- const FileNameList generated = generatedFiles(buildDir, fn, fileType);
+ for (const FilePath &fn : collectFiles(fileType)) {
+ const FilePathList generated = generatedFiles(buildDir, fn, fileType);
if (!generated.isEmpty())
m_extraCompilers.append(factory->create(m_project, fn, generated));
}
}
-void QmakeProFile::updateGeneratedFiles(const FileName &buildDir)
+void QmakeProFile::updateGeneratedFiles(const FilePath &buildDir)
{
// We can do this because other plugins are not supposed to keep the compilers around.
qDeleteAll(m_extraCompilers);
diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h
index 4c5b7048eb..3827957d57 100644
--- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h
+++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h
@@ -40,7 +40,7 @@
#include <memory>
namespace Utils {
-class FileName;
+class FilePath;
class FileSystemWatcher;
} // namespace Utils;
@@ -115,29 +115,29 @@ class InstallsList;
class QMAKEPROJECTMANAGER_EXPORT QmakePriFile
{
public:
- QmakePriFile(QmakeProject *project, QmakeProFile *qmakeProFile, const Utils::FileName &filePath);
+ QmakePriFile(QmakeProject *project, QmakeProFile *qmakeProFile, const Utils::FilePath &filePath);
virtual ~QmakePriFile();
- Utils::FileName filePath() const;
- Utils::FileName directoryPath() const;
+ Utils::FilePath filePath() const;
+ Utils::FilePath directoryPath() const;
virtual QString displayName() const;
QmakePriFile *parent() const;
QmakeProject *project() const;
QVector<QmakePriFile *> children() const;
- QmakePriFile *findPriFile(const Utils::FileName &fileName);
- const QmakePriFile *findPriFile(const Utils::FileName &fileName) const;
+ QmakePriFile *findPriFile(const Utils::FilePath &fileName);
+ const QmakePriFile *findPriFile(const Utils::FilePath &fileName) const;
- bool knowsFile(const Utils::FileName &filePath) const;
+ bool knowsFile(const Utils::FilePath &filePath) const;
void makeEmpty();
// Files of the specified type declared in this file.
- QSet<Utils::FileName> files(const ProjectExplorer::FileType &type) const;
+ QSet<Utils::FilePath> files(const ProjectExplorer::FileType &type) const;
// Files of the specified type declared in this file and in included .pri files.
- const QSet<Utils::FileName> collectFiles(const ProjectExplorer::FileType &type) const;
+ const QSet<Utils::FilePath> collectFiles(const ProjectExplorer::FileType &type) const;
void update(const Internal::QmakePriFileEvalResult &result);
@@ -156,7 +156,7 @@ public:
const QString &scope = QString(),
int flags = QmakeProjectManager::Internal::ProWriter::ReplaceValues);
- bool folderChanged(const QString &changedFolder, const QSet<Utils::FileName> &newFiles);
+ bool folderChanged(const QString &changedFolder, const QSet<Utils::FilePath> &newFiles);
bool deploysFolder(const QString &folder) const;
@@ -166,7 +166,7 @@ public:
// Set by parent
bool includedInExactParse() const;
- static QSet<Utils::FileName> recursiveEnumerate(const QString &folder);
+ static QSet<Utils::FilePath> recursiveEnumerate(const QString &folder);
void scheduleUpdate();
@@ -175,8 +175,8 @@ protected:
static QStringList varNames(ProjectExplorer::FileType type, QtSupport::ProFileReader *readerExact);
static QStringList varNamesForRemoving();
static QString varNameForAdding(const QString &mimeType);
- static QSet<Utils::FileName> filterFilesProVariables(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files);
- static QSet<Utils::FileName> filterFilesRecursiveEnumerata(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files);
+ static QSet<Utils::FilePath> filterFilesProVariables(ProjectExplorer::FileType fileType, const QSet<Utils::FilePath> &files);
+ static QSet<Utils::FilePath> filterFilesRecursiveEnumerata(ProjectExplorer::FileType fileType, const QSet<Utils::FilePath> &files);
enum ChangeType {
AddToProFile,
@@ -204,7 +204,6 @@ private:
static QPair<ProFile *, QStringList> readProFile(const QString &file);
static QPair<ProFile *, QStringList> readProFileFromContents(const QString &contents);
void save(const QStringList &lines);
- bool priFileWritable(const QString &absoluteFilePath);
bool saveModifiedEditors();
QStringList formResources(const QString &formFile) const;
static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir);
@@ -218,7 +217,7 @@ private:
Internal::QmakePriFileEvalResult *fallback,
const InstallsList &installList);
static void processValues(Internal::QmakePriFileEvalResult &result);
- void watchFolders(const QSet<Utils::FileName> &folders);
+ void watchFolders(const QSet<Utils::FilePath> &folders);
QString continuationIndent() const;
@@ -230,8 +229,8 @@ private:
std::unique_ptr<Core::IDocument> m_priFileDocument;
// Memory is cheap...
- QMap<ProjectExplorer::FileType, QSet<Utils::FileName>> m_files;
- QSet<Utils::FileName> m_recursiveEnumerateFiles; // FIXME: Remove this?!
+ QMap<ProjectExplorer::FileType, QSet<Utils::FilePath>> m_files;
+ QSet<Utils::FilePath> m_recursiveEnumerateFiles; // FIXME: Remove this?!
QSet<QString> m_watchedFolders;
bool m_includedInExactParse = true;
@@ -243,8 +242,8 @@ class QMAKEPROJECTMANAGER_EXPORT TargetInformation
public:
bool valid = false;
QString target;
- Utils::FileName destDir;
- Utils::FileName buildDir;
+ Utils::FilePath destDir;
+ Utils::FilePath buildDir;
QString buildTarget;
bool operator==(const TargetInformation &other) const
{
@@ -284,35 +283,36 @@ public:
class QMAKEPROJECTMANAGER_EXPORT QmakeProFile : public QmakePriFile
{
public:
- QmakeProFile(QmakeProject *project, const Utils::FileName &filePath);
+ QmakeProFile(QmakeProject *project, const Utils::FilePath &filePath);
~QmakeProFile() override;
bool isParent(QmakeProFile *node);
QString displayName() const final;
QList<QmakeProFile *> allProFiles();
- QmakeProFile *findProFile(const Utils::FileName &fileName);
- const QmakeProFile *findProFile(const Utils::FileName &fileName) const;
+ QmakeProFile *findProFile(const Utils::FilePath &fileName);
+ const QmakeProFile *findProFile(const Utils::FilePath &fileName) const;
ProjectType projectType() const;
QStringList variableValue(const Variable var) const;
QString singleVariableValue(const Variable var) const;
- bool isSubProjectDeployable(const Utils::FileName &filePath) const {
+ bool isSubProjectDeployable(const Utils::FilePath &filePath) const {
return !m_subProjectsNotToDeploy.contains(filePath);
}
- Utils::FileName sourceDir() const;
- Utils::FileName buildDir(QmakeBuildConfiguration *bc = nullptr) const;
+ Utils::FilePath sourceDir() const;
+ Utils::FilePath buildDir(QmakeBuildConfiguration *bc = nullptr) const;
- Utils::FileNameList generatedFiles(const Utils::FileName &buildDirectory,
- const Utils::FileName &sourceFile,
+ Utils::FilePathList generatedFiles(const Utils::FilePath &buildDirectory,
+ const Utils::FilePath &sourceFile,
const ProjectExplorer::FileType &sourceFileType) const;
QList<ProjectExplorer::ExtraCompiler *> extraCompilers() const;
TargetInformation targetInformation() const;
InstallsList installsList() const;
+ const QStringList featureRoots() const { return m_featureRoots; }
QByteArray cxxDefines() const;
@@ -342,19 +342,19 @@ private:
void asyncEvaluate(QFutureInterface<Internal::QmakeEvalResult *> &fi, Internal::QmakeEvalInput input);
void cleanupProFileReaders();
- void updateGeneratedFiles(const Utils::FileName &buildDir);
+ void updateGeneratedFiles(const Utils::FilePath &buildDir);
- static QString uiDirPath(QtSupport::ProFileReader *reader, const Utils::FileName &buildDir);
- static QString mocDirPath(QtSupport::ProFileReader *reader, const Utils::FileName &buildDir);
+ static QString uiDirPath(QtSupport::ProFileReader *reader, const Utils::FilePath &buildDir);
+ static QString mocDirPath(QtSupport::ProFileReader *reader, const Utils::FilePath &buildDir);
static QString sysrootify(const QString &path, const QString &sysroot, const QString &baseDir, const QString &outputDir);
- static QStringList includePaths(QtSupport::ProFileReader *reader, const Utils::FileName &sysroot, const Utils::FileName &buildDir, const QString &projectDir);
+ static QStringList includePaths(QtSupport::ProFileReader *reader, const Utils::FilePath &sysroot, const Utils::FilePath &buildDir, const QString &projectDir);
static QStringList libDirectories(QtSupport::ProFileReader *reader);
- static Utils::FileNameList subDirsPaths(QtSupport::ProFileReader *reader, const QString &projectDir, QStringList *subProjectsNotToDeploy, QStringList *errors);
+ static Utils::FilePathList subDirsPaths(QtSupport::ProFileReader *reader, const QString &projectDir, QStringList *subProjectsNotToDeploy, QStringList *errors);
- static TargetInformation targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const Utils::FileName &buildDir, const Utils::FileName &projectFilePath);
+ static TargetInformation targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const Utils::FilePath &buildDir, const Utils::FilePath &projectFilePath);
static InstallsList installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, const QString &projectDir, const QString &buildDir);
- void setupExtraCompiler(const Utils::FileName &buildDir,
+ void setupExtraCompiler(const Utils::FilePath &buildDir,
const ProjectExplorer::FileType &fileType,
ProjectExplorer::ExtraCompilerFactory *factory);
@@ -370,8 +370,9 @@ private:
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
TargetInformation m_qmakeTargetInformation;
- Utils::FileNameList m_subProjectsNotToDeploy;
+ Utils::FilePathList m_subProjectsNotToDeploy;
InstallsList m_installsList;
+ QStringList m_featureRoots;
std::unique_ptr<Utils::FileSystemWatcher> m_wildcardWatcher;
QMap<QString, QStringList> m_wildcardDirectoryContents;
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index a1bf62007a..dee31c56af 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -58,6 +58,7 @@
#include <projectexplorer/taskhub.h>
#include <projectexplorer/toolchain.h>
#include <proparser/qmakevfs.h>
+#include <proparser/qmakeglobals.h>
#include <qtsupport/profilereader.h>
#include <qtsupport/qtcppkitinfo.h>
#include <qtsupport/qtkitinformation.h>
@@ -109,51 +110,6 @@ private:
QSet<QString> m_changedFolders;
};
-// QmakeProjectFiles: Struct for (Cached) lists of files in a project
-class QmakeProjectFiles {
-public:
- void clear();
- bool equals(const QmakeProjectFiles &f) const;
-
- QStringList files[static_cast<int>(FileType::FileTypeSize)];
- QStringList generatedFiles[static_cast<int>(FileType::FileTypeSize)];
- QStringList proFiles;
-};
-
-void QmakeProjectFiles::clear()
-{
- for (int i = 0; i < static_cast<int>(FileType::FileTypeSize); ++i) {
- files[i].clear();
- generatedFiles[i].clear();
- }
- proFiles.clear();
-}
-
-bool QmakeProjectFiles::equals(const QmakeProjectFiles &f) const
-{
- for (int i = 0; i < static_cast<int>(FileType::FileTypeSize); ++i)
- if (files[i] != f.files[i] || generatedFiles[i] != f.generatedFiles[i])
- return false;
- if (proFiles != f.proFiles)
- return false;
- return true;
-}
-
-inline bool operator==(const QmakeProjectFiles &f1, const QmakeProjectFiles &f2)
-{ return f1.equals(f2); }
-
-inline bool operator!=(const QmakeProjectFiles &f1, const QmakeProjectFiles &f2)
-{ return !f1.equals(f2); }
-
-QDebug operator<<(QDebug d, const QmakeProjectFiles &f)
-{
- QDebug nsp = d.nospace();
- nsp << "QmakeProjectFiles: proFiles=" << f.proFiles << '\n';
- for (int i = 0; i < static_cast<int>(FileType::FileTypeSize); ++i)
- nsp << "Type " << i << " files=" << f.files[i] << " generated=" << f.generatedFiles[i] << '\n';
- return d;
-}
-
static QList<QmakeProject *> s_projects;
} // namespace Internal
@@ -164,7 +120,7 @@ static QList<QmakeProject *> s_projects;
QmakeProject manages information about an individual Qt 4 (.pro) project file.
*/
-QmakeProject::QmakeProject(const FileName &fileName) :
+QmakeProject::QmakeProject(const FilePath &fileName) :
Project(QmakeProjectManager::Constants::PROFILE_MIMETYPE, fileName),
m_qmakeVfs(new QMakeVfs),
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
@@ -248,6 +204,11 @@ Project::RestoreResult QmakeProject::fromMap(const QVariantMap &map, QString *er
return RestoreResult::Ok;
}
+DeploymentKnowledge QmakeProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Approximative; // E.g. QTCREATORBUG-21855
+}
+
void QmakeProject::updateCodeModels()
{
if (activeTarget() && !activeTarget()->activeBuildConfiguration())
@@ -308,7 +269,7 @@ void QmakeProject::updateCppCodeModel()
QStringList fileList = pro->variableValue(Variable::ExactSource) + cumulativeSourceFiles;
QList<ProjectExplorer::ExtraCompiler *> proGenerators = pro->extraCompilers();
foreach (ProjectExplorer::ExtraCompiler *ec, proGenerators) {
- ec->forEachTarget([&](const Utils::FileName &generatedFile) {
+ ec->forEachTarget([&](const Utils::FilePath &generatedFile) {
fileList += generatedFile.toString();
});
}
@@ -344,7 +305,7 @@ void QmakeProject::updateQmlJSCodeModel()
bool hasQmlLib = false;
for (QmakeProFile *file : proFiles) {
for (const QString &path : file->variableValue(Variable::QmlImportPath)) {
- projectInfo.importPaths.maybeInsert(FileName::fromString(path),
+ projectInfo.importPaths.maybeInsert(FilePath::fromString(path),
QmlJS::Dialect::Qml);
}
const QStringList &exactResources = file->variableValue(Variable::ExactResource);
@@ -562,6 +523,21 @@ void QmakeProject::asyncUpdate()
m_asyncUpdateFutureInterface->reportStarted();
+ const Kit * const kit = activeTarget() ? activeTarget()->kit() : nullptr;
+ QtSupport::BaseQtVersion * const qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
+ if (!qtVersion || !qtVersion->isValid()) {
+ const QString errorMessage = kit
+ ? tr("Cannot parse project \"%1\": The currently selected kit \"%2\" does not "
+ "have a valid Qt.").arg(displayName(), kit->displayName())
+ : tr("Cannot parse project \"%1\": No kit selected.").arg(displayName());
+ proFileParseError(errorMessage);
+ m_asyncUpdateFutureInterface->reportCanceled();
+ m_asyncUpdateFutureInterface->reportFinished();
+ delete m_asyncUpdateFutureInterface;
+ m_asyncUpdateFutureInterface = nullptr;
+ return;
+ }
+
if (m_asyncUpdateState == AsyncFullUpdatePending) {
rootProFile()->asyncUpdate();
} else {
@@ -579,20 +555,20 @@ void QmakeProject::buildFinished(bool success)
m_invalidateQmakeVfsContents = true;
}
-QList<Task> QmakeProject::projectIssues(const Kit *k) const
+Tasks QmakeProject::projectIssues(const Kit *k) const
{
- QList<Task> result = Project::projectIssues(k);
- if (!QtSupport::QtKitInformation::qtVersion(k))
+ Tasks result = Project::projectIssues(k);
+ if (!QtSupport::QtKitAspect::qtVersion(k))
result.append(createProjectTask(Task::TaskType::Error, tr("No Qt version set in kit.")));
- else if (!QtSupport::QtKitInformation::qtVersion(k)->isValid())
+ else if (!QtSupport::QtKitAspect::qtVersion(k)->isValid())
result.append(createProjectTask(Task::TaskType::Error, tr("Qt version is invalid.")));
- if (!ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID))
+ if (!ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID))
result.append(createProjectTask(Task::TaskType::Error, tr("No C++ compiler set in kit.")));
return result;
}
// Find the folder that contains a file with a certain name (recurse down)
-static FolderNode *folderOf(FolderNode *in, const FileName &fileName)
+static FolderNode *folderOf(FolderNode *in, const FilePath &fileName)
{
foreach (FileNode *fn, in->fileNodes())
if (fn->filePath() == fileName)
@@ -605,7 +581,7 @@ static FolderNode *folderOf(FolderNode *in, const FileName &fileName)
// Find the QmakeProFileNode that contains a certain file.
// First recurse down to folder, then find the pro-file.
-static FileNode *fileNodeOf(FolderNode *in, const FileName &fileName)
+static FileNode *fileNodeOf(FolderNode *in, const FilePath &fileName)
{
for (FolderNode *folder = folderOf(in, fileName); folder; folder = folder->parentFolderNode()) {
if (auto *proFile = dynamic_cast<QmakeProFileNode *>(folder)) {
@@ -623,13 +599,13 @@ QStringList QmakeProject::filesGeneratedFrom(const QString &input) const
if (!rootProjectNode())
return { };
- if (const FileNode *file = fileNodeOf(rootProjectNode(), FileName::fromString(input))) {
+ if (const FileNode *file = fileNodeOf(rootProjectNode(), FilePath::fromString(input))) {
const QmakeProFileNode *pro = static_cast<QmakeProFileNode *>(file->parentFolderNode());
QTC_ASSERT(pro, return {});
if (const QmakeProFile *proFile = pro->proFile())
- return Utils::transform(proFile->generatedFiles(FileName::fromString(pro->buildDir()),
+ return Utils::transform(proFile->generatedFiles(FilePath::fromString(pro->buildDir()),
file->filePath(), file->fileType()),
- &FileName::toString);
+ &FilePath::toString);
}
return { };
}
@@ -665,8 +641,8 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile *
k->addToEnvironment(env);
}
- QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
- m_qmakeSysroot = SysRootKitInformation::sysRoot(k).toString();
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(k);
+ m_qmakeSysroot = SysRootKitAspect::sysRoot(k).toString();
if (qtVersion && qtVersion->isValid()) {
m_qmakeGlobals->qmake_abslocation = QDir::cleanPath(qtVersion->qmakeCommand().toString());
@@ -770,7 +746,7 @@ void QmakeProject::setAllBuildConfigurationsEnabled(bool enabled)
}
}
-static void notifyChangedHelper(const FileName &fileName, QmakeProFile *file)
+static void notifyChangedHelper(const FilePath &fileName, QmakeProFile *file)
{
if (file->filePath() == fileName) {
QtSupport::ProFileCacheManager::instance()->discardFile(
@@ -784,7 +760,7 @@ static void notifyChangedHelper(const FileName &fileName, QmakeProFile *file)
}
}
-void QmakeProject::notifyChanged(const FileName &name)
+void QmakeProject::notifyChanged(const FilePath &name)
{
for (QmakeProject *project : s_projects) {
if (project->files(QmakeProject::SourceFiles).contains(name))
@@ -921,7 +897,7 @@ void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder)
QList<QmakePriFile *> files = m_map.values(dir);
if (!files.isEmpty()) {
// Collect all the files
- QSet<FileName> newFiles;
+ QSet<FilePath> newFiles;
newFiles += QmakePriFile::recursiveEnumerate(folder);
foreach (QmakePriFile *file, files)
newOrRemovedFiles = newOrRemovedFiles || file->folderChanged(folder, newFiles);
@@ -962,7 +938,7 @@ void QmakeProject::configureAsExampleProject(const QSet<Core::Id> &platforms)
QList<BuildInfo> infoList;
QList<Kit *> kits = KitManager::kits();
foreach (Kit *k, kits) {
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
if (!version
|| (!platforms.isEmpty()
&& !Utils::contains(version->targetDeviceTypes(), [platforms](Core::Id i) { return platforms.contains(i); })))
@@ -987,7 +963,7 @@ void QmakeProject::updateBuildSystemData()
collectData(file, deploymentData);
target->setDeploymentData(deploymentData);
- BuildTargetInfoList appTargetList;
+ QList<BuildTargetInfo> appTargetList;
rootProjectNode()->forEachProjectNode([this, target, &appTargetList](const ProjectNode *pn) {
auto node = dynamic_cast<const QmakeProFileNode *>(pn);
@@ -1025,11 +1001,11 @@ void QmakeProject::updateBuildSystemData()
workingDir += '/' + ti.target + ".app/Contents/MacOS";
BuildTargetInfo bti;
- bti.targetFilePath = FileName::fromString(executableFor(node->proFile()));
+ bti.targetFilePath = FilePath::fromString(executableFor(node->proFile()));
bti.projectFilePath = node->filePath();
- bti.workingDirectory = FileName::fromString(workingDir);
+ bti.workingDirectory = FilePath::fromString(workingDir);
bti.displayName = bti.projectFilePath.toFileInfo().completeBaseName();
- const FileName relativePathInProject
+ const FilePath relativePathInProject
= bti.projectFilePath.relativeChildPath(projectDirectory());
if (!relativePathInProject.isEmpty()) {
bti.displayNameUniquifier = QString::fromLatin1(" (%1)")
@@ -1061,7 +1037,7 @@ void QmakeProject::updateBuildSystemData()
libraryPaths.append(dir);
}
}
- QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(target->kit());
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target->kit());
if (qtVersion)
libraryPaths.append(qtVersion->librarySearchPath().toString());
@@ -1071,7 +1047,7 @@ void QmakeProject::updateBuildSystemData()
env.prependOrSetLibrarySearchPaths(libraryPaths);
};
- appTargetList.list.append(bti);
+ appTargetList.append(bti);
});
target->setApplicationTargets(appTargetList);
@@ -1119,12 +1095,12 @@ void QmakeProject::collectApplicationData(const QmakeProFile *file, DeploymentDa
DeployableFile::TypeExecutable);
}
-static FileName destDirFor(const TargetInformation &ti)
+static FilePath destDirFor(const TargetInformation &ti)
{
if (ti.destDir.isEmpty())
return ti.buildDir;
if (QDir::isRelativePath(ti.destDir.toString()))
- return FileName::fromString(QDir::cleanPath(ti.buildDir.toString() + '/' + ti.destDir.toString()));
+ return FilePath::fromString(QDir::cleanPath(ti.buildDir.toString() + '/' + ti.destDir.toString()));
return ti.destDir;
}
@@ -1134,7 +1110,7 @@ void QmakeProject::collectLibraryData(const QmakeProFile *file, DeploymentData &
if (targetPath.isEmpty())
return;
const Kit * const kit = activeTarget()->kit();
- const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ const ToolChain * const toolchain = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!toolchain)
return;
@@ -1161,9 +1137,9 @@ void QmakeProject::collectLibraryData(const QmakeProFile *file, DeploymentData &
break;
}
case Abi::DarwinOS: {
- FileName destDir = destDirFor(ti);
+ FilePath destDir = destDirFor(ti);
if (config.contains(QLatin1String("lib_bundle"))) {
- destDir.appendPath(ti.target + ".framework");
+ destDir = destDir.pathAppended(ti.target + ".framework");
} else {
if (!(isPlugin && config.contains(QLatin1String("no_plugin_name_prefix"))))
targetFileName.prepend(QLatin1String("lib"));
@@ -1220,15 +1196,15 @@ void QmakeProject::collectLibraryData(const QmakeProFile *file, DeploymentData &
bool QmakeProject::matchesKit(const Kit *kit)
{
- FileName filePath = projectFilePath();
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
+ FilePath filePath = projectFilePath();
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit);
return QtSupport::QtVersionManager::version([&filePath, version](const QtSupport::BaseQtVersion *v) {
return v->isValid() && v->isSubProject(filePath) && v == version;
});
}
-static Utils::FileName getFullPathOf(const QmakeProFile *pro, Variable variable,
+static Utils::FilePath getFullPathOf(const QmakeProFile *pro, Variable variable,
const BuildConfiguration *bc)
{
// Take last non-flag value, to cover e.g. '@echo $< && $$QMAKE_CC' or 'ccache gcc'
@@ -1237,22 +1213,22 @@ static Utils::FileName getFullPathOf(const QmakeProFile *pro, Variable variable,
return !value.startsWith('-');
});
if (values.isEmpty())
- return Utils::FileName();
+ return Utils::FilePath();
const QString exe = values.last();
- QTC_ASSERT(bc, return Utils::FileName::fromString(exe));
+ QTC_ASSERT(bc, return Utils::FilePath::fromString(exe));
QFileInfo fi(exe);
if (fi.isAbsolute())
- return Utils::FileName::fromString(exe);
+ return Utils::FilePath::fromString(exe);
return bc->environment().searchInPath(exe);
}
-void QmakeProject::testToolChain(ToolChain *tc, const Utils::FileName &path) const
+void QmakeProject::testToolChain(ToolChain *tc, const Utils::FilePath &path) const
{
if (!tc || path.isEmpty())
return;
- const Utils::FileName expected = tc->compilerCommand();
+ const Utils::FilePath expected = tc->compilerCommand();
Environment env = Environment::systemEnvironment();
Kit *k = nullptr;
@@ -1267,7 +1243,7 @@ void QmakeProject::testToolChain(ToolChain *tc, const Utils::FileName &path) con
if (env.isSameExecutable(path.toString(), expected.toString()))
return;
- const QPair<Utils::FileName, Utils::FileName> pair = qMakePair(expected, path);
+ const QPair<Utils::FilePath, Utils::FilePath> pair = qMakePair(expected, path);
if (m_toolChainWarnings.contains(pair))
return;
// Suppress warnings on Apple machines where compilers in /usr/bin point into Xcode.
@@ -1285,7 +1261,7 @@ void QmakeProject::testToolChain(ToolChain *tc, const Utils::FileName &path) con
"Please update your kit (%3) or choose a mkspec for qmake that matches "
"your target environment better.")
.arg(path.toUserOutput()).arg(expected.toUserOutput()).arg(k->displayName()),
- Utils::FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+ Utils::FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
m_toolChainWarnings.insert(pair);
}
@@ -1296,16 +1272,16 @@ void QmakeProject::warnOnToolChainMismatch(const QmakeProFile *pro) const
if (!bc)
return;
- testToolChain(ToolChainKitInformation::toolChain(t->kit(), ProjectExplorer::Constants::C_LANGUAGE_ID),
+ testToolChain(ToolChainKitAspect::toolChain(t->kit(), ProjectExplorer::Constants::C_LANGUAGE_ID),
getFullPathOf(pro, Variable::QmakeCc, bc));
- testToolChain(ToolChainKitInformation::toolChain(t->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID),
+ testToolChain(ToolChainKitAspect::toolChain(t->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID),
getFullPathOf(pro, Variable::QmakeCxx, bc));
}
QString QmakeProject::executableFor(const QmakeProFile *file)
{
const Kit *const kit = activeTarget() ? activeTarget()->kit() : nullptr;
- const ToolChain *const tc = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ const ToolChain *const tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!tc)
return QString();
@@ -1344,7 +1320,7 @@ QmakeProject::AsyncUpdateState QmakeProject::asyncUpdateState() const
return m_asyncUpdateState;
}
-QString QmakeProject::mapProFilePathToTarget(const FileName &proFilePath)
+QString QmakeProject::mapProFilePathToTarget(const FilePath &proFilePath)
{
const QmakeProFile *pro = rootProFile()->findProFile(proFilePath);
return pro ? pro->targetInformation().target : QString();
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h
index bdcb1c477a..42e8e57ec0 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.h
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.h
@@ -30,6 +30,7 @@
#include "qmakenodes.h"
#include "qmakeparsernodes.h"
+#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/project.h>
#include <QStringList>
@@ -55,18 +56,18 @@ class QMAKEPROJECTMANAGER_EXPORT QmakeProject : public ProjectExplorer::Project
Q_OBJECT
public:
- explicit QmakeProject(const Utils::FileName &proFile);
+ explicit QmakeProject(const Utils::FilePath &proFile);
~QmakeProject() final;
QmakeProFile *rootProFile() const;
- QList<ProjectExplorer::Task> projectIssues(const ProjectExplorer::Kit *k) const final;
+ ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
QmakeProFileNode *rootProjectNode() const final;
QStringList filesGeneratedFrom(const QString &file) const final;
- static void notifyChanged(const Utils::FileName &name);
+ static void notifyChanged(const Utils::FilePath &name);
/// \internal
QtSupport::ProFileReader *createProFileReader(const QmakeProFile *qmakeProFile);
@@ -104,7 +105,7 @@ public:
enum AsyncUpdateState { Base, AsyncFullUpdatePending, AsyncPartialUpdatePending, AsyncUpdateInProgress, ShuttingDown };
AsyncUpdateState asyncUpdateState() const;
- QString mapProFilePathToTarget(const Utils::FileName &proFilePath);
+ QString mapProFilePathToTarget(const Utils::FilePath &proFilePath);
QVariant additionalData(Core::Id id, const ProjectExplorer::Target *target) const final;
@@ -120,6 +121,9 @@ protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final;
private:
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+ bool hasMakeInstallEquivalent() const override { return true; }
+
void asyncUpdate();
void buildFinished(bool success);
void activeTargetWasChanged();
@@ -144,9 +148,9 @@ private:
bool matchesKit(const ProjectExplorer::Kit *kit);
void warnOnToolChainMismatch(const QmakeProFile *pro) const;
- void testToolChain(ProjectExplorer::ToolChain *tc, const Utils::FileName &path) const;
+ void testToolChain(ProjectExplorer::ToolChain *tc, const Utils::FilePath &path) const;
- mutable QSet<const QPair<Utils::FileName, Utils::FileName>> m_toolChainWarnings;
+ mutable QSet<const QPair<Utils::FilePath, Utils::FilePath>> m_toolChainWarnings;
// Current configuration
QString m_oldQtIncludePath;
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp
index 241bd5a4f5..a5a2d673a1 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp
@@ -28,8 +28,9 @@
#include "qmakeproject.h"
#include "qmakebuildconfiguration.h"
#include "qmakenodes.h"
-#include "ui_qmakeprojectconfigwidget.h"
+#include "qmakesettings.h"
+#include <QBoxLayout>
#include <coreplugin/coreicons.h>
#include <coreplugin/variablechooser.h>
#include <projectexplorer/target.h>
@@ -47,57 +48,96 @@ QmakeProjectConfigWidget::QmakeProjectConfigWidget(QmakeBuildConfiguration *bc)
: NamedWidget(),
m_buildConfiguration(bc)
{
+ const bool isShadowBuild = bc->isShadowBuild();
+ Project *project = bc->target()->project();
+
m_defaultShadowBuildDir
- = QmakeBuildConfiguration::shadowBuildDirectory(bc->target()->project()->projectFilePath().toString(),
+ = QmakeBuildConfiguration::shadowBuildDirectory(project->projectFilePath().toString(),
bc->target()->kit(),
Utils::FileUtils::qmakeFriendlyName(bc->displayName()),
bc->buildType());
- auto *vbox = new QVBoxLayout(this);
- vbox->setMargin(0);
m_detailsContainer = new Utils::DetailsWidget(this);
m_detailsContainer->setState(Utils::DetailsWidget::NoSummary);
+
+ auto vbox = new QVBoxLayout(this);
+ vbox->setMargin(0);
vbox->addWidget(m_detailsContainer);
- QWidget *details = new QWidget(m_detailsContainer);
+
+ auto details = new QWidget(m_detailsContainer);
m_detailsContainer->setWidget(details);
- m_ui = new Ui::QmakeProjectConfigWidget();
- m_ui->setupUi(details);
-
- m_browseButton = m_ui->shadowBuildDirEdit->buttonAtIndex(0);
-
- m_ui->warningLabel->setPixmap(Utils::Icons::WARNING.pixmap());
- m_ui->shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory"));
- m_ui->shadowBuildDirEdit->setExpectedKind(Utils::PathChooser::ExistingDirectory);
- m_ui->shadowBuildDirEdit->setHistoryCompleter(QLatin1String("Qmake.BuildDir.History"));
- m_ui->shadowBuildDirEdit->setEnvironment(bc->environment());
- m_ui->shadowBuildDirEdit->setBaseFileName(bc->target()->project()->projectDirectory());
- bool isShadowBuild = bc->isShadowBuild();
+
+ shadowBuildLabel = new QLabel(details);
+ shadowBuildLabel->setText(tr("Shadow build:"));
+
+ shadowBuildCheckBox = new QCheckBox(details);
+ shadowBuildCheckBox->setChecked(isShadowBuild);
+
+ buildDirLabel = new QLabel(details);
+ buildDirLabel->setText(tr("Build directory:"));
+
+ shadowBuildDirEdit = new Utils::PathChooser(details);
+
+ inSourceBuildDirEdit = new Utils::PathChooser(details);
+
+ warningLabel = new QLabel(details);
+ warningLabel->setPixmap(Utils::Icons::WARNING.pixmap());
+
+ problemLabel = new QLabel(details);
+ QSizePolicy sizePolicy2(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sizePolicy2.setHorizontalStretch(10);
+ sizePolicy2.setVerticalStretch(0);
+ problemLabel->setSizePolicy(sizePolicy2);
+ problemLabel->setWordWrap(true);
+
+ auto horizontalLayout_2 = new QHBoxLayout();
+ horizontalLayout_2->addWidget(warningLabel);
+ horizontalLayout_2->addWidget(problemLabel);
+
+ auto horizontalLayout = new QHBoxLayout();
+ horizontalLayout->addWidget(shadowBuildDirEdit);
+ horizontalLayout->addWidget(inSourceBuildDirEdit);
+
+ auto layout = new QGridLayout(details);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(shadowBuildLabel, 0, 0, 1, 1);
+ layout->addWidget(shadowBuildCheckBox, 0, 1, 1, 1);
+ layout->addWidget(buildDirLabel, 1, 0, 1, 1);
+ layout->addLayout(horizontalLayout, 1, 1, 1, 1);
+ layout->addLayout(horizontalLayout_2, 2, 1, 1, 1);
+
+ problemLabel->setText(tr("problemLabel"));
+
+ m_browseButton = shadowBuildDirEdit->buttonAtIndex(0);
+
+ shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory"));
+ shadowBuildDirEdit->setExpectedKind(Utils::PathChooser::ExistingDirectory);
+ shadowBuildDirEdit->setHistoryCompleter(QLatin1String("Qmake.BuildDir.History"));
+ shadowBuildDirEdit->setEnvironment(bc->environment());
+ shadowBuildDirEdit->setBaseFileName(project->projectDirectory());
if (isShadowBuild) {
- m_ui->shadowBuildDirEdit->setPath(bc->rawBuildDirectory().toString());
- m_ui->inSourceBuildDirEdit->setVisible(false);
+ shadowBuildDirEdit->setPath(bc->rawBuildDirectory().toString());
+ inSourceBuildDirEdit->setVisible(false);
} else {
- m_ui->shadowBuildDirEdit->setPath(m_defaultShadowBuildDir);
- m_ui->shadowBuildDirEdit->setVisible(false);
+ shadowBuildDirEdit->setPath(m_defaultShadowBuildDir);
+ shadowBuildDirEdit->setVisible(false);
}
- m_ui->inSourceBuildDirEdit->setFileName(bc->target()->project()->projectDirectory());
- m_ui->inSourceBuildDirEdit->setReadOnly(true);
- m_ui->inSourceBuildDirEdit->setEnabled(false);
+ inSourceBuildDirEdit->setFileName(project->projectDirectory());
+ inSourceBuildDirEdit->setReadOnly(true);
+ inSourceBuildDirEdit->setEnabled(false);
auto chooser = new Core::VariableChooser(this);
- chooser->addSupportedWidget(m_ui->shadowBuildDirEdit->lineEdit());
-
- m_ui->shadowBuildCheckBox->setChecked(isShadowBuild);
+ chooser->addSupportedWidget(shadowBuildDirEdit->lineEdit());
- connect(m_ui->shadowBuildCheckBox, &QAbstractButton::clicked,
+ connect(shadowBuildCheckBox, &QAbstractButton::clicked,
this, &QmakeProjectConfigWidget::shadowBuildClicked);
- connect(m_ui->shadowBuildDirEdit, &Utils::PathChooser::beforeBrowsing,
+ connect(shadowBuildDirEdit, &Utils::PathChooser::beforeBrowsing,
this, &QmakeProjectConfigWidget::onBeforeBeforeShadowBuildDirBrowsed);
- connect(m_ui->shadowBuildDirEdit, &Utils::PathChooser::rawPathChanged,
+ connect(shadowBuildDirEdit, &Utils::PathChooser::rawPathChanged,
this, &QmakeProjectConfigWidget::shadowBuildEdited);
- auto *project = static_cast<QmakeProject *>(bc->target()->project());
project->subscribeSignal(&BuildConfiguration::environmentChanged, this, [this]() {
if (static_cast<BuildConfiguration *>(sender())->isActive())
environmentChanged();
@@ -107,9 +147,13 @@ QmakeProjectConfigWidget::QmakeProjectConfigWidget(QmakeBuildConfiguration *bc)
if (pc && pc->isActive())
environmentChanged();
});
- connect(project, &QmakeProject::buildDirectoryInitialized,
+
+ auto qmakeProject = static_cast<QmakeProject *>(bc->target()->project());
+ connect(qmakeProject, &QmakeProject::buildDirectoryInitialized,
this, &QmakeProjectConfigWidget::updateProblemLabel);
- connect(project, &Project::parsingFinished,
+ connect(qmakeProject, &Project::parsingFinished,
+ this, &QmakeProjectConfigWidget::updateProblemLabel);
+ connect(&QmakeSettings::instance(), &QmakeSettings::settingsChanged,
this, &QmakeProjectConfigWidget::updateProblemLabel);
connect(bc->target(), &Target::kitChanged, this, &QmakeProjectConfigWidget::updateProblemLabel);
@@ -125,11 +169,6 @@ QmakeProjectConfigWidget::QmakeProjectConfigWidget(QmakeBuildConfiguration *bc)
updateProblemLabel();
}
-QmakeProjectConfigWidget::~QmakeProjectConfigWidget()
-{
- delete m_ui;
-}
-
void QmakeProjectConfigWidget::updateDetails()
{
m_detailsContainer->setSummaryText(
@@ -139,14 +178,14 @@ void QmakeProjectConfigWidget::updateDetails()
void QmakeProjectConfigWidget::setProblemLabel(const QString &text)
{
- m_ui->warningLabel->setVisible(!text.isEmpty());
- m_ui->problemLabel->setVisible(!text.isEmpty());
- m_ui->problemLabel->setText(text);
+ warningLabel->setVisible(!text.isEmpty());
+ problemLabel->setVisible(!text.isEmpty());
+ problemLabel->setText(text);
}
void QmakeProjectConfigWidget::environmentChanged()
{
- m_ui->shadowBuildDirEdit->setEnvironment(m_buildConfiguration->environment());
+ shadowBuildDirEdit->setEnvironment(m_buildConfiguration->environment());
}
void QmakeProjectConfigWidget::buildDirectoryChanged()
@@ -154,14 +193,14 @@ void QmakeProjectConfigWidget::buildDirectoryChanged()
if (m_ignoreChange)
return;
- bool shadowBuild = m_ui->shadowBuildCheckBox->isChecked();
- m_ui->inSourceBuildDirEdit->setVisible(!shadowBuild);
+ bool shadowBuild = shadowBuildCheckBox->isChecked();
+ inSourceBuildDirEdit->setVisible(!shadowBuild);
- m_ui->shadowBuildDirEdit->setVisible(shadowBuild);
- m_ui->shadowBuildDirEdit->setEnabled(shadowBuild);
+ shadowBuildDirEdit->setVisible(shadowBuild);
+ shadowBuildDirEdit->setEnabled(shadowBuild);
m_browseButton->setEnabled(shadowBuild);
- m_ui->shadowBuildDirEdit->setPath(m_buildConfiguration->rawBuildDirectory().toString());
+ shadowBuildDirEdit->setPath(m_buildConfiguration->rawBuildDirectory().toString());
updateDetails();
updateProblemLabel();
@@ -169,24 +208,24 @@ void QmakeProjectConfigWidget::buildDirectoryChanged()
void QmakeProjectConfigWidget::onBeforeBeforeShadowBuildDirBrowsed()
{
- Utils::FileName initialDirectory = m_buildConfiguration->target()->project()->projectDirectory();
+ Utils::FilePath initialDirectory = m_buildConfiguration->target()->project()->projectDirectory();
if (!initialDirectory.isEmpty())
- m_ui->shadowBuildDirEdit->setInitialBrowsePathBackup(initialDirectory.toString());
+ shadowBuildDirEdit->setInitialBrowsePathBackup(initialDirectory.toString());
}
void QmakeProjectConfigWidget::shadowBuildClicked(bool checked)
{
- m_ui->shadowBuildDirEdit->setEnabled(checked);
+ shadowBuildDirEdit->setEnabled(checked);
m_browseButton->setEnabled(checked);
- m_ui->shadowBuildDirEdit->setVisible(checked);
- m_ui->inSourceBuildDirEdit->setVisible(!checked);
+ shadowBuildDirEdit->setVisible(checked);
+ inSourceBuildDirEdit->setVisible(!checked);
m_ignoreChange = true;
if (checked)
- m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_ui->shadowBuildDirEdit->rawPath()));
+ m_buildConfiguration->setBuildDirectory(Utils::FilePath::fromString(shadowBuildDirEdit->rawPath()));
else
- m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_ui->inSourceBuildDirEdit->rawPath()));
+ m_buildConfiguration->setBuildDirectory(Utils::FilePath::fromString(inSourceBuildDirEdit->rawPath()));
m_ignoreChange = false;
updateDetails();
@@ -195,22 +234,22 @@ void QmakeProjectConfigWidget::shadowBuildClicked(bool checked)
void QmakeProjectConfigWidget::shadowBuildEdited()
{
- if (m_buildConfiguration->rawBuildDirectory().toString() == m_ui->shadowBuildDirEdit->rawPath())
+ if (m_buildConfiguration->rawBuildDirectory().toString() == shadowBuildDirEdit->rawPath())
return;
m_ignoreChange = true;
- m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(m_ui->shadowBuildDirEdit->rawPath()));
+ m_buildConfiguration->setBuildDirectory(Utils::FilePath::fromString(shadowBuildDirEdit->rawPath()));
m_ignoreChange = false;
}
void QmakeProjectConfigWidget::updateProblemLabel()
{
- m_ui->shadowBuildDirEdit->triggerChanged();
+ shadowBuildDirEdit->triggerChanged();
ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit();
const QString proFileName = m_buildConfiguration->target()->project()->projectFilePath().toString();
// Check for Qt version:
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
if (!version) {
setProblemLabel(tr("This kit cannot build this project since it does not define a Qt version."));
return;
@@ -250,11 +289,16 @@ void QmakeProjectConfigWidget::updateProblemLabel()
}
}
+ const bool unalignedBuildDir = QmakeSettings::warnAgainstUnalignedBuildDir()
+ && !m_buildConfiguration->isBuildDirAtSafeLocation();
+ if (unalignedBuildDir)
+ allGood = false;
+
if (allGood) {
QString buildDirectory = m_buildConfiguration->target()->project()->projectDirectory().toString();
if (m_buildConfiguration->isShadowBuild())
buildDirectory = m_buildConfiguration->buildDirectory().toString();
- QList<ProjectExplorer::Task> issues;
+ Tasks issues;
issues = version->reportIssues(proFileName, buildDirectory);
Utils::sort(issues);
@@ -293,6 +337,9 @@ void QmakeProjectConfigWidget::updateProblemLabel()
.arg(errorString)
.arg(m_buildConfiguration->buildDirectory().toUserOutput()));
return;
+ } else if (unalignedBuildDir) {
+ setProblemLabel(m_buildConfiguration->unalignedBuildDirWarning());
+ return;
}
setProblemLabel(QString());
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h
index 0c5c0ef6fd..c0dc7653b6 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h
@@ -27,6 +27,11 @@
#include <projectexplorer/namedwidget.h>
+#include <utils/pathchooser.h>
+
+#include <QCheckBox>
+#include <QLabel>
+
QT_BEGIN_NAMESPACE
class QAbstractButton;
QT_END_NAMESPACE
@@ -37,14 +42,12 @@ namespace QmakeProjectManager {
class QmakeBuildConfiguration;
namespace Internal {
-namespace Ui { class QmakeProjectConfigWidget; }
class QmakeProjectConfigWidget : public ProjectExplorer::NamedWidget
{
Q_OBJECT
public:
QmakeProjectConfigWidget(QmakeBuildConfiguration *bc);
- ~QmakeProjectConfigWidget() override;
private:
// User changes in our widgets
@@ -60,12 +63,19 @@ private:
void updateDetails();
void setProblemLabel(const QString &text);
- Ui::QmakeProjectConfigWidget *m_ui;
QAbstractButton *m_browseButton;
QmakeBuildConfiguration *m_buildConfiguration;
Utils::DetailsWidget *m_detailsContainer;
QString m_defaultShadowBuildDir;
bool m_ignoreChange = false;
+
+ QLabel *shadowBuildLabel;
+ QCheckBox *shadowBuildCheckBox;
+ QLabel *buildDirLabel;
+ Utils::PathChooser *shadowBuildDirEdit;
+ Utils::PathChooser *inSourceBuildDirEdit;
+ QLabel *warningLabel;
+ QLabel *problemLabel;
};
} // namespace Internal
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.ui b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.ui
deleted file mode 100644
index db15315897..0000000000
--- a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.ui
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmakeProjectManager::Internal::QmakeProjectConfigWidget</class>
- <widget class="QWidget" name="QmakeProjectManager::Internal::QmakeProjectConfigWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>408</width>
- <height>62</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <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 row="0" column="0">
- <widget class="QLabel" name="shadowBuildLabel">
- <property name="text">
- <string>Shadow build:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QCheckBox" name="shadowBuildCheckBox">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="buildDirLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Build directory:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="Utils::PathChooser" name="shadowBuildDirEdit" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Utils::PathChooser" name="inSourceBuildDirEdit" native="true"/>
- </item>
- </layout>
- </item>
- <item row="2" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLabel" name="warningLabel"/>
- </item>
- <item>
- <widget class="QLabel" name="problemLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>10</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>problemLabel</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>Utils::PathChooser</class>
- <extends>QWidget</extends>
- <header location="global">utils/pathchooser.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp
index a04657aa40..fe3d1bf67d 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp
@@ -64,10 +64,10 @@ namespace {
struct DirectoryData
{
QString makefile;
- Utils::FileName buildDirectory;
- Utils::FileName canonicalQmakeBinary;
+ Utils::FilePath buildDirectory;
+ Utils::FilePath canonicalQmakeBinary;
QtProjectImporter::QtVersionData qtVersionData;
- FileName parsedSpec;
+ QString parsedSpec;
BaseQtVersion::QmakeBuildConfigs buildConfig;
QString additionalArguments;
QMakeStepConfig config;
@@ -83,7 +83,7 @@ namespace Internal {
const Core::Id QT_IS_TEMPORARY("Qmake.TempQt");
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios"; // ugly
-QmakeProjectImporter::QmakeProjectImporter(const FileName &path) :
+QmakeProjectImporter::QmakeProjectImporter(const FilePath &path) :
QtProjectImporter(path)
{ }
@@ -109,7 +109,7 @@ QStringList QmakeProjectImporter::importCandidates()
return candidates;
}
-QList<void *> QmakeProjectImporter::examineDirectory(const FileName &importPath) const
+QList<void *> QmakeProjectImporter::examineDirectory(const FilePath &importPath) const
{
QList<void *> result;
const QLoggingCategory &logs = MakeFileParse::logging();
@@ -136,7 +136,7 @@ QList<void *> QmakeProjectImporter::examineDirectory(const FileName &importPath)
}
QFileInfo qmakeFi = parse.qmakePath().toFileInfo();
- data->canonicalQmakeBinary = FileName::fromString(qmakeFi.canonicalFilePath());
+ data->canonicalQmakeBinary = FilePath::fromString(qmakeFi.canonicalFilePath());
if (data->canonicalQmakeBinary.isEmpty()) {
qCDebug(logs) << " " << parse.qmakePath() << "doesn't exist anymore";
continue;
@@ -164,7 +164,7 @@ QList<void *> QmakeProjectImporter::examineDirectory(const FileName &importPath)
}
if (version->type() == QtSupport::Constants::DESKTOPQT) {
- const QList<ProjectExplorer::Abi> abis = version->qtAbis();
+ const ProjectExplorer::Abis abis = version->qtAbis();
if (!abis.isEmpty()) {
ProjectExplorer::Abi abi = abis.first();
if (abi.os() == ProjectExplorer::Abi::DarwinOS) {
@@ -185,8 +185,8 @@ QList<void *> QmakeProjectImporter::examineDirectory(const FileName &importPath)
qCDebug(logs) << " Extracted spec:" << data->parsedSpec;
qCDebug(logs) << " Arguments now:" << data->additionalArguments;
- FileName versionSpec = version->mkspec();
- if (data->parsedSpec.isEmpty() || data->parsedSpec == FileName::fromLatin1("default")) {
+ const QString versionSpec = version->mkspec();
+ if (data->parsedSpec.isEmpty() || data->parsedSpec == "default") {
data->parsedSpec = versionSpec;
qCDebug(logs) << " No parsed spec or default spec => parsed spec now:" << data->parsedSpec;
}
@@ -203,9 +203,9 @@ bool QmakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
auto *data = static_cast<DirectoryData *>(directoryData);
const QLoggingCategory &logs = MakeFileParse::logging();
- BaseQtVersion *kitVersion = QtKitInformation::qtVersion(k);
- FileName kitSpec = QmakeKitInformation::mkspec(k);
- ToolChain *tc = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ BaseQtVersion *kitVersion = QtKitAspect::qtVersion(k);
+ QString kitSpec = QmakeKitAspect::mkspec(k);
+ ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (kitSpec.isEmpty() && kitVersion)
kitSpec = kitVersion->mkspecFor(tc);
QMakeStepConfig::TargetArchConfig kitTargetArch = QMakeStepConfig::NoArch;
@@ -265,13 +265,13 @@ void QmakeProjectImporter::deleteDirectoryData(void *directoryData) const
delete static_cast<DirectoryData *>(directoryData);
}
-static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, const FileName &ms,
+static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, const QString &ms,
const QMakeStepConfig::TargetArchConfig &archConfig)
{
- const FileName spec = ms.isEmpty() ? qtVersion->mkspec() : ms;
+ const QString spec = ms.isEmpty() ? qtVersion->mkspec() : ms;
const QList<ToolChain *> toolchains = ToolChainManager::toolChains();
- QList<Abi> qtAbis = qtVersion->qtAbis();
+ const Abis qtAbis = qtVersion->qtAbis();
const auto matcher = [&](const ToolChain *tc) {
return qtAbis.contains(tc->targetAbi())
&& tc->suggestedMkspecList().contains(spec)
@@ -292,7 +292,7 @@ static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, co
}
Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersionData &data,
- const FileName &parsedSpec,
+ const QString &parsedSpec,
const QMakeStepConfig::TargetArchConfig &archConfig,
const QMakeStepConfig::OsType &osType) const
{
@@ -300,9 +300,9 @@ Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersion
return QtProjectImporter::createTemporaryKit(data,
[&data, parsedSpec, archConfig](Kit *k) -> void {
for (ToolChain * const tc : preferredToolChains(data.qt, parsedSpec, archConfig))
- ToolChainKitInformation::setToolChain(k, tc);
+ ToolChainKitAspect::setToolChain(k, tc);
if (parsedSpec != data.qt->mkspec())
- QmakeKitInformation::setMkspec(k, parsedSpec);
+ QmakeKitAspect::setMkspec(k, parsedSpec, QmakeKitAspect::MkspecSource::Code);
});
}
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.h b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.h
index 13dad12de5..c6f364210a 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.h
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.h
@@ -36,12 +36,12 @@ namespace Internal {
class QmakeProjectImporter : public QtSupport::QtProjectImporter
{
public:
- QmakeProjectImporter(const Utils::FileName &path);
+ QmakeProjectImporter(const Utils::FilePath &path);
QStringList importCandidates() final;
private:
- QList<void *> examineDirectory(const Utils::FileName &importPath) const final;
+ QList<void *> examineDirectory(const Utils::FilePath &importPath) const final;
bool matchKit(void *directoryData, const ProjectExplorer::Kit *k) const final;
ProjectExplorer::Kit *createKit(void *directoryData) const final;
const QList<ProjectExplorer::BuildInfo> buildInfoListForKit(const ProjectExplorer::Kit *k,
@@ -50,7 +50,7 @@ private:
void deleteDirectoryData(void *directoryData) const final;
ProjectExplorer::Kit *createTemporaryKit(const QtProjectImporter::QtVersionData &data,
- const Utils::FileName &parsedSpec,
+ const QString &parsedSpec,
const QmakeProjectManager::QMakeStepConfig::TargetArchConfig &archConfig,
const QMakeStepConfig::OsType &osType) const;
};
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
index 3af228874a..adbc1709fb 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
@@ -53,16 +53,6 @@ using namespace TextEditor;
namespace QmakeProjectManager {
-Node *QmakeManager::contextNode()
-{
- return ProjectTree::findCurrentNode();
-}
-
-Project *QmakeManager::contextProject()
-{
- return ProjectTree::currentProject();
-}
-
static QmakeProFileNode *buildableFileProFile(Node *node)
{
if (node) {
@@ -77,7 +67,7 @@ static QmakeProFileNode *buildableFileProFile(Node *node)
FileNode *QmakeManager::contextBuildableFileNode()
{
- Node *node = contextNode();
+ Node *node = ProjectTree::currentNode();
QmakeProFileNode *subProjectNode = buildableFileProFile(node);
FileNode *fileNode = node ? node->asFileNode() : nullptr;
@@ -97,7 +87,7 @@ void QmakeManager::addLibraryContextMenu()
{
QString projectPath;
- Node *node = contextNode();
+ Node *node = ProjectTree::currentNode();
if (ContainerNode *cn = node->asContainerNode())
projectPath = cn->project()->projectFilePath().toString();
else if (dynamic_cast<QmakeProFileNode *>(node))
@@ -142,7 +132,7 @@ void QmakeManager::runQMake()
void QmakeManager::runQMakeContextMenu()
{
- runQMakeImpl(contextProject(), contextNode());
+ runQMakeImpl(ProjectTree::currentProject(), ProjectTree::currentNode());
}
void QmakeManager::runQMakeImpl(ProjectExplorer::Project *p, ProjectExplorer::Node *node)
@@ -194,7 +184,7 @@ void QmakeManager::buildFileContextMenu()
void QmakeManager::buildFile()
{
if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
- const Utils::FileName file = currentDocument->filePath();
+ const Utils::FilePath file = currentDocument->filePath();
Node *n = ProjectTree::nodeForFile(file);
FileNode *node = n ? n->asFileNode() : nullptr;
Project *project = SessionManager::projectForFile(file);
@@ -206,8 +196,11 @@ void QmakeManager::buildFile()
void QmakeManager::handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild)
{
- handleSubDirContextMenu(action, isFileBuild, contextProject(),
- buildableFileProFile(contextNode()), contextBuildableFileNode());
+ handleSubDirContextMenu(action,
+ isFileBuild,
+ ProjectTree::currentProject(),
+ buildableFileProFile(ProjectTree::currentNode()),
+ contextBuildableFileNode());
}
void QmakeManager::handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild,
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.h b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.h
index b7869f9374..ab163f1a76 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.h
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.h
@@ -45,11 +45,9 @@ class QMAKEPROJECTMANAGER_EXPORT QmakeManager : public QObject
Q_OBJECT
public:
- void notifyChanged(const Utils::FileName &name);
+ void notifyChanged(const Utils::FilePath &name);
// Context information used in the slot implementations
- static ProjectExplorer::Node *contextNode();
- static ProjectExplorer::Project *contextProject();
static ProjectExplorer::FileNode *contextBuildableFileNode();
enum Action { BUILD, REBUILD, CLEAN };
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro
index b831a594d0..ccc64eda00 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro
@@ -7,23 +7,18 @@ DEFINES += \
HEADERS += \
qmakebuildinfo.h \
qmakekitinformation.h \
- qmakekitconfigwidget.h \
qmakeparsernodes.h \
qmakeprojectimporter.h \
qmakeprojectmanagerplugin.h \
qmakeprojectmanager.h \
qmakeproject.h \
+ qmakesettings.h \
qmakenodes.h \
qmakenodetreebuilder.h \
profileeditor.h \
profilehighlighter.h \
profilehoverhandler.h \
wizards/qtprojectparameters.h \
- wizards/guiappwizard.h \
- wizards/libraryparameters.h \
- wizards/librarywizard.h \
- wizards/librarywizarddialog.h \
- wizards/guiappwizarddialog.h \
wizards/modulespage.h \
wizards/filespage.h \
wizards/qtwizard.h \
@@ -46,7 +41,6 @@ HEADERS += \
qmakemakestep.h
SOURCES += \
- qmakekitconfigwidget.cpp \
qmakekitinformation.cpp \
qmakeparsernodes.cpp \
qmakeprojectimporter.cpp \
@@ -54,16 +48,12 @@ SOURCES += \
qmakeprojectmanager.cpp \
qmakeproject.cpp \
qmakenodes.cpp \
+ qmakesettings.cpp \
qmakenodetreebuilder.cpp \
profileeditor.cpp \
profilehighlighter.cpp \
profilehoverhandler.cpp \
wizards/qtprojectparameters.cpp \
- wizards/guiappwizard.cpp \
- wizards/libraryparameters.cpp \
- wizards/librarywizard.cpp \
- wizards/librarywizarddialog.cpp \
- wizards/guiappwizarddialog.cpp \
wizards/modulespage.cpp \
wizards/filespage.cpp \
wizards/qtwizard.cpp \
@@ -85,7 +75,6 @@ SOURCES += \
FORMS += \
qmakestep.ui \
- qmakeprojectconfigwidget.ui \
librarydetailswidget.ui
RESOURCES += qmakeprojectmanager.qrc \
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs
index 2b0e99f353..e045f60663 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs
@@ -36,18 +36,18 @@ Project {
"profilehighlighter.cpp", "profilehighlighter.h",
"profilehoverhandler.cpp", "profilehoverhandler.h",
"qmakebuildinfo.h",
- "qmakekitconfigwidget.cpp", "qmakekitconfigwidget.h",
"qmakekitinformation.cpp", "qmakekitinformation.h",
"qmakemakestep.cpp", "qmakemakestep.h",
"qmakeparser.cpp", "qmakeparser.h",
"qmakeparsernodes.cpp", "qmakeparsernodes.h",
"qmakeprojectimporter.cpp", "qmakeprojectimporter.h",
+ "qmakesettings.cpp", "qmakesettings.h",
"qmakestep.cpp", "qmakestep.h", "qmakestep.ui",
"qmakebuildconfiguration.cpp", "qmakebuildconfiguration.h",
"qmakenodes.cpp", "qmakenodes.h",
"qmakenodetreebuilder.cpp", "qmakenodetreebuilder.h",
"qmakeproject.cpp", "qmakeproject.h",
- "qmakeprojectconfigwidget.cpp", "qmakeprojectconfigwidget.h", "qmakeprojectconfigwidget.ui",
+ "qmakeprojectconfigwidget.cpp", "qmakeprojectconfigwidget.h",
"qmakeprojectmanager.cpp", "qmakeprojectmanager.h",
"qmakeprojectmanager.qrc",
"qmakeprojectmanager_global.h",
@@ -78,11 +78,6 @@ Project {
prefix: "wizards/"
files: [
"filespage.cpp", "filespage.h",
- "guiappwizard.cpp", "guiappwizard.h",
- "guiappwizarddialog.cpp", "guiappwizarddialog.h",
- "libraryparameters.cpp", "libraryparameters.h",
- "librarywizard.cpp", "librarywizard.h",
- "librarywizarddialog.cpp", "librarywizarddialog.h",
"modulespage.cpp", "modulespage.h",
"qtprojectparameters.cpp", "qtprojectparameters.h",
"qtwizard.cpp", "qtwizard.h",
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
index 46ffcec047..bf21949215 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
@@ -28,12 +28,11 @@
#include "profileeditor.h"
#include "qmakeprojectmanager.h"
#include "qmakenodes.h"
+#include "qmakesettings.h"
#include "qmakestep.h"
#include "qmakemakestep.h"
#include "qmakebuildconfiguration.h"
#include "desktopqmakerunconfiguration.h"
-#include "wizards/guiappwizard.h"
-#include "wizards/librarywizard.h"
#include "wizards/simpleprojectwizard.h"
#include "wizards/subdirsprojectwizard.h"
#include "customwidgetwizard/customwidgetwizard.h"
@@ -54,6 +53,7 @@
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -86,7 +86,7 @@ public:
void buildStateChanged(Project *pro);
void updateBuildFileAction();
void disableBuildFileMenus();
- void enableBuildFileMenus(const Utils::FileName &file);
+ void enableBuildFileMenus(const Utils::FilePath &file);
QmakeManager qmakeProjectManager;
Core::Context projectContext;
@@ -99,9 +99,13 @@ public:
QmakeBuildConfigurationFactory buildConfigFactory;
DesktopQmakeRunConfigurationFactory runConfigFactory;
+ SimpleRunWorkerFactory<SimpleTargetRunner, DesktopQmakeRunConfiguration>
+ runWorkerFactory;
ProFileEditorFactory profileEditorFactory;
+ QmakeSettingsPage settingsPage;
+
ExternalQtEditor *m_designerEditor{ExternalQtEditor::createDesignerEditor()};
ExternalQtEditor *m_linguistEditor{ExternalQtEditor::createLinguistEditor()};
@@ -121,6 +125,8 @@ public:
Utils::ParameterAction *m_buildFileAction = nullptr;
QAction *m_addLibraryAction = nullptr;
QAction *m_addLibraryActionContextMenu = nullptr;
+
+ QmakeKitAspect qmakeKitAspect;
};
QmakeProjectManagerPlugin::~QmakeProjectManagerPlugin()
@@ -140,13 +146,9 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString
//create and register objects
ProjectManager::registerProjectType<QmakeProject>(QmakeProjectManager::Constants::PROFILE_MIMETYPE);
- ProjectExplorer::KitManager::registerKitInformation<QmakeKitInformation>();
-
IWizardFactory::registerFactoryCreator([] {
return QList<IWizardFactory *> {
new SubdirsProjectWizard,
- new GuiAppWizard,
- new LibraryWizard,
new CustomWidgetWizard,
new SimpleProjectWizard
};
@@ -367,14 +369,14 @@ void QmakeProjectManagerPluginPrivate::updateRunQMakeAction()
void QmakeProjectManagerPluginPrivate::updateContextActions()
{
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
Project *project = ProjectTree::currentProject();
const ContainerNode *containerNode = node ? node->asContainerNode() : nullptr;
const auto *proFileNode = dynamic_cast<const QmakeProFileNode *>(containerNode ? containerNode->rootProjectNode() : node);
m_addLibraryActionContextMenu->setEnabled(proFileNode);
- auto *qmakeProject = qobject_cast<QmakeProject *>(QmakeManager::contextProject());
+ auto *qmakeProject = qobject_cast<QmakeProject *>(project);
QmakeProFileNode *subProjectNode = nullptr;
disableBuildFileMenus();
if (node) {
@@ -450,7 +452,7 @@ void QmakeProjectManagerPluginPrivate::disableBuildFileMenus()
m_buildFileContextMenu->setEnabled(false);
}
-void QmakeProjectManagerPluginPrivate::enableBuildFileMenus(const Utils::FileName &file)
+void QmakeProjectManagerPluginPrivate::enableBuildFileMenus(const Utils::FilePath &file)
{
bool visible = false;
bool enabled = false;
diff --git a/src/plugins/qmakeprojectmanager/qmakesettings.cpp b/src/plugins/qmakeprojectmanager/qmakesettings.cpp
new file mode 100644
index 0000000000..37c0a4ce39
--- /dev/null
+++ b/src/plugins/qmakeprojectmanager/qmakesettings.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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 "qmakesettings.h"
+
+#include <coreplugin/icore.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <utils/hostosinfo.h>
+
+#include <QCheckBox>
+#include <QCoreApplication>
+#include <QVBoxLayout>
+
+namespace QmakeProjectManager {
+namespace Internal {
+
+const char BUILD_DIR_WARNING_KEY[] = "QmakeProjectManager/WarnAgainstUnalignedBuildDir";
+const char ALWAYS_RUN_QMAKE_KEY[] = "QmakeProjectManager/AlwaysRunQmake";
+
+static bool operator==(const QmakeSettingsData &s1, const QmakeSettingsData &s2)
+{
+ return s1.warnAgainstUnalignedBuildDir == s2.warnAgainstUnalignedBuildDir
+ && s1.alwaysRunQmake == s2.alwaysRunQmake;
+}
+static bool operator!=(const QmakeSettingsData &s1, const QmakeSettingsData &s2)
+{
+ return !(s1 == s2);
+}
+
+bool QmakeSettings::warnAgainstUnalignedBuildDir()
+{
+ return instance().m_settings.warnAgainstUnalignedBuildDir;
+}
+
+bool QmakeSettings::alwaysRunQmake()
+{
+ return instance().m_settings.alwaysRunQmake;
+}
+
+QmakeSettings &QmakeSettings::instance()
+{
+ static QmakeSettings theSettings;
+ return theSettings;
+}
+
+void QmakeSettings::setSettingsData(const QmakeSettingsData &settings)
+{
+ if (instance().m_settings != settings) {
+ instance().m_settings = settings;
+ instance().storeSettings();
+ emit instance().settingsChanged();
+ }
+}
+
+QmakeSettings::QmakeSettings()
+{
+ loadSettings();
+}
+
+void QmakeSettings::loadSettings()
+{
+ QSettings * const s = Core::ICore::settings();
+ m_settings.warnAgainstUnalignedBuildDir = s->value(
+ BUILD_DIR_WARNING_KEY, Utils::HostOsInfo::isWindowsHost()).toBool();
+ m_settings.alwaysRunQmake = s->value(ALWAYS_RUN_QMAKE_KEY, false).toBool();
+}
+
+void QmakeSettings::storeSettings() const
+{
+ QSettings * const s = Core::ICore::settings();
+ s->setValue(BUILD_DIR_WARNING_KEY, warnAgainstUnalignedBuildDir());
+ s->setValue(ALWAYS_RUN_QMAKE_KEY, alwaysRunQmake());
+}
+
+class QmakeSettingsPage::SettingsWidget : public QWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(QmakeProjectManager::Internal::QmakeSettingsPage)
+public:
+ SettingsWidget()
+ {
+ m_warnAgainstUnalignedBuildDirCheckbox.setText(tr("Warn if a project's source and "
+ "build directories are not at the same level"));
+ m_warnAgainstUnalignedBuildDirCheckbox.setToolTip(tr("Qmake has subtle bugs that "
+ "can be triggered if source and build directory are not at the same level."));
+ m_warnAgainstUnalignedBuildDirCheckbox.setChecked(
+ QmakeSettings::warnAgainstUnalignedBuildDir());
+ m_alwaysRunQmakeCheckbox.setText(tr("Run qmake on every build"));
+ m_alwaysRunQmakeCheckbox.setToolTip(tr("This option can help to prevent failures on "
+ "incremental builds, but might slow them down unnecessarily in the general case."));
+ m_alwaysRunQmakeCheckbox.setChecked(QmakeSettings::alwaysRunQmake());
+ const auto layout = new QVBoxLayout(this);
+ layout->addWidget(&m_warnAgainstUnalignedBuildDirCheckbox);
+ layout->addWidget(&m_alwaysRunQmakeCheckbox);
+ layout->addStretch(1);
+ }
+
+ void apply()
+ {
+ QmakeSettingsData settings;
+ settings.warnAgainstUnalignedBuildDir = m_warnAgainstUnalignedBuildDirCheckbox.isChecked();
+ settings.alwaysRunQmake = m_alwaysRunQmakeCheckbox.isChecked();
+ QmakeSettings::setSettingsData(settings);
+ }
+
+private:
+ QCheckBox m_warnAgainstUnalignedBuildDirCheckbox;
+ QCheckBox m_alwaysRunQmakeCheckbox;
+};
+
+QmakeSettingsPage::QmakeSettingsPage()
+{
+ setId("K.QmakeProjectManager.QmakeSettings");
+ setDisplayName(tr("Qmake"));
+ setCategory(ProjectExplorer::Constants::BUILD_AND_RUN_SETTINGS_CATEGORY);
+}
+
+QWidget *QmakeSettingsPage::widget()
+{
+ if (!m_widget)
+ m_widget = new SettingsWidget;
+ return m_widget;
+
+}
+
+void QmakeSettingsPage::apply()
+{
+ if (m_widget)
+ m_widget->apply();
+}
+
+void QmakeSettingsPage::finish()
+{
+ delete m_widget;
+}
+
+} // namespace Internal
+} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/qmakesettings.h b/src/plugins/qmakeprojectmanager/qmakesettings.h
new file mode 100644
index 0000000000..6918483595
--- /dev/null
+++ b/src/plugins/qmakeprojectmanager/qmakesettings.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 <coreplugin/dialogs/ioptionspage.h>
+
+#include <QObject>
+#include <QPointer>
+
+namespace QmakeProjectManager {
+namespace Internal {
+
+class QmakeSettingsData {
+public:
+ bool warnAgainstUnalignedBuildDir = false;
+ bool alwaysRunQmake = false;
+};
+
+class QmakeSettings : public QObject
+{
+ Q_OBJECT
+public:
+ static QmakeSettings &instance();
+ static bool warnAgainstUnalignedBuildDir();
+ static bool alwaysRunQmake();
+ static void setSettingsData(const QmakeSettingsData &settings);
+
+signals:
+ void settingsChanged();
+
+private:
+ QmakeSettings();
+ void loadSettings();
+ void storeSettings() const;
+
+ QmakeSettingsData m_settings;
+};
+
+class QmakeSettingsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+public:
+ QmakeSettingsPage();
+
+private:
+ QWidget *widget() override;
+ void apply() override;
+ void finish() override;
+
+ class SettingsWidget;
+ QPointer<SettingsWidget> m_widget;
+};
+
+} // namespace Internal
+} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp
index 42f8a8fc00..104a093e4d 100644
--- a/src/plugins/qmakeprojectmanager/qmakestep.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp
@@ -33,6 +33,7 @@
#include "qmakeparser.h"
#include "qmakeproject.h"
#include "qmakeprojectmanagerconstants.h"
+#include "qmakesettings.h"
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildsteplist.h>
@@ -114,9 +115,9 @@ QString QMakeStep::allArguments(const BaseQtVersion *v, ArgumentFlags flags) con
}
}
}
- FileName specArg = mkspec();
+ const QString specArg = mkspec();
if (!userProvidedMkspec && !specArg.isEmpty())
- arguments << "-spec" << specArg.toUserOutput();
+ arguments << "-spec" << QDir::toNativeSeparators(specArg);
// Find out what flags we pass on to qmake
arguments << bc->configCommandLineArguments();
@@ -136,18 +137,18 @@ QMakeStepConfig QMakeStep::deducedArguments() const
ProjectExplorer::Kit *kit = target()->kit();
QMakeStepConfig config;
ProjectExplorer::ToolChain *tc
- = ProjectExplorer::ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ = ProjectExplorer::ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
ProjectExplorer::Abi targetAbi;
if (tc) {
targetAbi = tc->targetAbi();
if (HostOsInfo::isWindowsHost()
&& tc->typeId() == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
- config.sysRoot = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString();
+ config.sysRoot = ProjectExplorer::SysRootKitAspect::sysRoot(kit).toString();
config.targetTriple = tc->originalTargetTriple();
}
}
- BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
+ BaseQtVersion *version = QtKitAspect::qtVersion(target()->kit());
config.archConfig = QMakeStepConfig::targetArchFor(targetAbi, version);
config.osType = QMakeStepConfig::osTypeFor(targetAbi, version);
@@ -167,7 +168,7 @@ bool QMakeStep::init()
{
m_wasSuccess = true;
QmakeBuildConfiguration *qmakeBc = qmakeBuildConfiguration();
- const BaseQtVersion *qtVersion = QtKitInformation::qtVersion(target()->kit());
+ const BaseQtVersion *qtVersion = QtKitAspect::qtVersion(target()->kit());
if (!qtVersion) {
emit addOutput(tr("No Qt version configured."), BuildStep::OutputFormat::ErrorMessage);
@@ -181,7 +182,7 @@ bool QMakeStep::init()
else
workingDirectory = qmakeBc->buildDirectory().toString();
- m_qmakeExecutable = qtVersion->qmakeCommand().toString();
+ m_qmakeExecutable = qtVersion->qmakeCommand();
m_qmakeArguments = allArguments(qtVersion);
m_runMakeQmake = (qtVersion->qtVersion() >= QtVersionNumber(5, 0 ,0));
@@ -214,14 +215,15 @@ bool QMakeStep::init()
}
// Check whether we need to run qmake
- bool makefileOutDated = (qmakeBc->compareToImportFrom(makefile) != QmakeBuildConfiguration::MakefileMatches);
- if (m_forced || makefileOutDated)
+ if (m_forced || QmakeSettings::alwaysRunQmake()
+ || qmakeBc->compareToImportFrom(makefile) != QmakeBuildConfiguration::MakefileMatches) {
m_needToRunQMake = true;
+ }
m_forced = false;
ProcessParameters *pp = processParameters();
pp->setMacroExpander(qmakeBc->macroExpander());
- pp->setWorkingDirectory(workingDirectory);
+ pp->setWorkingDirectory(Utils::FilePath::fromString(workingDirectory));
pp->setEnvironment(qmakeBc->environment());
setOutputParser(new QMakeParser);
@@ -232,7 +234,7 @@ bool QMakeStep::init()
QTC_ASSERT(node, return false);
QString proFile = node->filePath().toString();
- QList<ProjectExplorer::Task> tasks = qtVersion->reportIssues(proFile, workingDirectory);
+ Tasks tasks = qtVersion->reportIssues(proFile, workingDirectory);
Utils::sort(tasks);
if (!tasks.isEmpty()) {
@@ -309,7 +311,7 @@ void QMakeStep::finish(bool success)
runNextCommand();
}
-void QMakeStep::startOneCommand(const QString &command, const QString &args)
+void QMakeStep::startOneCommand(const FilePath &command, const QString &args)
{
ProcessParameters *pp = processParameters();
pp->setCommand(command);
@@ -341,7 +343,7 @@ void QMakeStep::runNextCommand()
case State::RUN_MAKE_QMAKE_ALL:
{
auto *parser = new GnuMakeParser;
- parser->setWorkingDirectory(processParameters()->workingDirectory());
+ parser->setWorkingDirectory(processParameters()->workingDirectory().toString());
setOutputParser(parser);
m_nextState = State::POST_PROCESS;
startOneCommand(m_makeExecutable, m_makeArguments);
@@ -434,10 +436,10 @@ void QMakeStep::setSeparateDebugInfo(bool enable)
qmakeBuildConfiguration()->emitProFileEvaluateNeeded();
}
-QString QMakeStep::makeCommand() const
+FilePath QMakeStep::makeCommand() const
{
- auto *ms = qobject_cast<BuildStepList *>(parent())->firstOfType<MakeStep>();
- return ms ? ms->effectiveMakeCommand() : QString();
+ auto ms = qobject_cast<BuildStepList *>(parent())->firstOfType<MakeStep>();
+ return ms ? ms->effectiveMakeCommand() : FilePath();
}
QString QMakeStep::makeArguments(const QString &makefile) const
@@ -453,11 +455,11 @@ QString QMakeStep::makeArguments(const QString &makefile) const
QString QMakeStep::effectiveQMakeCall() const
{
- BaseQtVersion *qtVersion = QtKitInformation::qtVersion(target()->kit());
+ BaseQtVersion *qtVersion = QtKitAspect::qtVersion(target()->kit());
QString qmake = qtVersion ? qtVersion->qmakeCommand().toUserOutput() : QString();
if (qmake.isEmpty())
qmake = tr("<no Qt version>");
- QString make = makeCommand();
+ QString make = makeCommand().toString();
if (make.isEmpty())
make = tr("<no Make step found>");
@@ -475,7 +477,7 @@ QString QMakeStep::effectiveQMakeCall() const
QStringList QMakeStep::parserArguments()
{
QStringList result;
- BaseQtVersion *qt = QtKitInformation::qtVersion(target()->kit());
+ BaseQtVersion *qt = QtKitAspect::qtVersion(target()->kit());
QTC_ASSERT(qt, return QStringList());
for (QtcProcess::ConstArgIterator ait(allArguments(qt, ArgumentFlag::Expand)); ait.next(); ) {
if (ait.isSimple())
@@ -489,18 +491,18 @@ QString QMakeStep::userArguments()
return m_userArgs;
}
-FileName QMakeStep::mkspec() const
+QString QMakeStep::mkspec() const
{
QString additionalArguments = m_userArgs;
QtcProcess::addArgs(&additionalArguments, m_extraArgs);
for (QtcProcess::ArgIterator ait(&additionalArguments); ait.next(); ) {
if (ait.value() == "-spec") {
if (ait.next())
- return FileName::fromUserInput(ait.value());
+ return FilePath::fromUserInput(ait.value()).toString();
}
}
- return QmakeProjectManager::QmakeKitInformation::effectiveMkspec(target()->kit());
+ return QmakeKitAspect::effectiveMkspec(target()->kit());
}
QVariantMap QMakeStep::toMap() const
@@ -562,7 +564,7 @@ QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step)
connect(m_ui->qmakeAdditonalArgumentsLineEdit, &QLineEdit::textEdited,
this, &QMakeStepConfigWidget::qmakeArgumentsLineEdited);
connect(m_ui->buildConfigurationComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &QMakeStepConfigWidget::buildConfigurationSelected);
connect(m_ui->qmlDebuggingLibraryCheckBox, &QCheckBox::toggled,
this, &QMakeStepConfigWidget::linkQmlDebuggingLibraryChecked);
@@ -589,8 +591,6 @@ QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step)
connect(step->qmakeBuildConfiguration(), &QmakeBuildConfiguration::qmakeBuildConfigurationChanged,
this, &QMakeStepConfigWidget::qmakeBuildConfigChanged);
connect(step->target(), &Target::kitChanged, this, &QMakeStepConfigWidget::qtVersionChanged);
- connect(QtVersionManager::instance(), &QtVersionManager::dumpUpdatedFor,
- this, &QMakeStepConfigWidget::qtVersionChanged);
auto chooser = new Core::VariableChooser(m_ui->qmakeAdditonalArgumentsLineEdit);
chooser->addMacroExpanderProvider([step] { return step->macroExpander(); });
chooser->addSupportedWidget(m_ui->qmakeAdditonalArgumentsLineEdit);
@@ -744,7 +744,7 @@ void QMakeStepConfigWidget::separateDebugInfoChecked(bool checked)
void QMakeStepConfigWidget::updateSummaryLabel()
{
- BaseQtVersion *qtVersion = QtKitInformation::qtVersion(m_step->target()->kit());
+ BaseQtVersion *qtVersion = QtKitAspect::qtVersion(m_step->target()->kit());
if (!qtVersion) {
setSummaryText(tr("<b>qmake:</b> No Qt version set. Cannot run qmake."));
return;
diff --git a/src/plugins/qmakeprojectmanager/qmakestep.h b/src/plugins/qmakeprojectmanager/qmakestep.h
index a0124dc9bb..90fef01d35 100644
--- a/src/plugins/qmakeprojectmanager/qmakestep.h
+++ b/src/plugins/qmakeprojectmanager/qmakestep.h
@@ -26,14 +26,13 @@
#pragma once
#include "qmakeprojectmanager_global.h"
+
#include <projectexplorer/abstractprocessstep.h>
-#include <QStringList>
+#include <utils/fileutils.h>
#include <memory>
-namespace Utils { class FileName; }
-
namespace ProjectExplorer {
class Abi;
class BuildStep;
@@ -137,7 +136,7 @@ public:
// QMake extra arguments. Not user editable.
QStringList extraArguments() const;
void setExtraArguments(const QStringList &args);
- Utils::FileName mkspec() const;
+ QString mkspec() const;
bool linkQmlDebuggingLibrary() const;
void setLinkQmlDebuggingLibrary(bool enable);
bool useQtQuickCompiler() const;
@@ -145,7 +144,7 @@ public:
bool separateDebugInfo() const;
void setSeparateDebugInfo(bool enable);
- QString makeCommand() const;
+ Utils::FilePath makeCommand() const;
QString makeArguments(const QString &makefile) const;
QString effectiveQMakeCall() const;
@@ -167,12 +166,12 @@ private:
void doCancel() override;
void finish(bool success) override;
- void startOneCommand(const QString &command, const QString &args);
+ void startOneCommand(const Utils::FilePath &command, const QString &args);
void runNextCommand();
- QString m_qmakeExecutable;
+ Utils::FilePath m_qmakeExecutable;
QString m_qmakeArguments;
- QString m_makeExecutable;
+ Utils::FilePath m_makeExecutable;
QString m_makeArguments;
QString m_userArgs;
// Extra arguments for qmake.
diff --git a/src/plugins/qmakeprojectmanager/wizards/guiappwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/guiappwizard.cpp
deleted file mode 100644
index 08b7514a8e..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/guiappwizard.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "guiappwizard.h"
-
-#include "guiappwizarddialog.h"
-
-#include <projectexplorer/projectexplorerconstants.h>
-#include <cpptools/abstracteditorsupport.h>
-#include <designer/cpp/formclasswizardparameters.h>
-#include <extensionsystem/pluginmanager.h>
-#include <extensionsystem/invoker.h>
-#include <qtsupport/qtsupportconstants.h>
-
-#include <utils/fileutils.h>
-
-#include <QCoreApplication>
-#include <QDir>
-#include <QTextStream>
-#include <QSharedPointer>
-
-static const char mainSourceFileC[] = "main";
-static const char mainSourceShowC[] = " w.show();\n";
-static const char mainSourceMobilityShowC[] = " w.show();\n";
-
-static const char mainWindowUiContentsC[] =
-"\n <widget class=\"QMenuBar\" name=\"menuBar\" />"
-"\n <widget class=\"QToolBar\" name=\"mainToolBar\" />"
-"\n <widget class=\"QWidget\" name=\"centralWidget\" />"
-"\n <widget class=\"QStatusBar\" name=\"statusBar\" />";
-static const char mainWindowMobileUiContentsC[] =
-"\n <widget class=\"QWidget\" name=\"centralWidget\" />";
-
-static const char *baseClassesC[] = {"QMainWindow", "QWidget", "QDialog"};
-
-static inline QStringList baseClasses()
-{
- QStringList rc;
- for (auto baseClass : baseClassesC)
- rc.push_back(QLatin1String(baseClass));
- return rc;
-}
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-GuiAppWizard::GuiAppWizard()
-{
- setId("C.Qt4Gui");
- setCategory(QLatin1String(ProjectExplorer::Constants::QT_APPLICATION_WIZARD_CATEGORY));
- setDisplayCategory(QCoreApplication::translate("ProjectExplorer",
- ProjectExplorer::Constants::QT_APPLICATION_WIZARD_CATEGORY_DISPLAY));
- setDisplayName(tr("Qt Widgets Application"));
- setDescription(tr("Creates a Qt application for the desktop. "
- "Includes a Qt Designer-based main window.\n\n"
- "Preselects a desktop Qt for building the application if available."));
- setIcon(QIcon(QLatin1String(":/wizards/images/gui.png")));
- setRequiredFeatures({QtSupport::Constants::FEATURE_QWIDGETS});
-}
-
-Core::BaseFileWizard *GuiAppWizard::create(QWidget *parent, const Core::WizardDialogParameters &parameters) const
-{
- GuiAppWizardDialog *dialog = new GuiAppWizardDialog(this, displayName(), icon(), parent, parameters);
- dialog->setProjectName(GuiAppWizardDialog::uniqueProjectName(parameters.defaultPath()));
- // Order! suffixes first to generate files correctly
- dialog->setLowerCaseFiles(QtWizard::lowerCaseFiles());
- dialog->setSuffixes(headerSuffix(), sourceSuffix(), formSuffix());
- dialog->setBaseClasses(baseClasses());
- return dialog;
-}
-
-// Use the class generation utils provided by the designer plugin
-static inline bool generateFormClass(const GuiAppParameters &params,
- const Core::GeneratedFile &uiFile,
- Core::GeneratedFile *formSource,
- Core::GeneratedFile *formHeader,
- QString *errorMessage)
-{
- // Retrieve parameters from settings
- Designer::FormClassWizardParameters fp;
- fp.uiTemplate = uiFile.contents();
- fp.uiFile = uiFile.path();
- fp.className = params.className;
- fp.sourceFile = params.sourceFileName;
- fp.headerFile = params.headerFileName;
- fp.usePragmaOnce = CppTools::AbstractEditorSupport::usePragmaOnce();
- QString headerContents;
- QString sourceContents;
- // Invoke code generation service of Qt Designer plugin.
- if (QObject *codeGenerator = ExtensionSystem::PluginManager::getObjectByName("QtDesignerFormClassCodeGenerator")) {
- const QVariant code = ExtensionSystem::invoke<QVariant>(codeGenerator, "generateFormClassCode", fp);
- if (code.type() == QVariant::List) {
- const QVariantList vl = code.toList();
- if (vl.size() == 2) {
- headerContents = vl.front().toString();
- sourceContents = vl.back().toString();
- }
- }
- }
- if (headerContents.isEmpty() || sourceContents.isEmpty()) {
- *errorMessage = QString::fromLatin1("Failed to obtain Designer plugin code generation service.");
- return false;
- }
-
- formHeader->setContents(headerContents);
- formSource->setContents(sourceContents);
- return true;
-}
-
-Core::GeneratedFiles GuiAppWizard::generateFiles(const QWizard *w,
- QString *errorMessage) const
-{
- const auto *dialog = qobject_cast<const GuiAppWizardDialog *>(w);
- const QtProjectParameters projectParams = dialog->projectParameters();
- const QString projectPath = projectParams.projectPath();
- const GuiAppParameters params = dialog->parameters();
-
- // Generate file names. Note that the path for the project files is the
- // newly generated project directory.
- const QString templatePath = templateDir();
- // Create files: main source
- QString contents;
- const QString mainSourceFileName = buildFileName(projectPath, QLatin1String(mainSourceFileC), sourceSuffix());
- Core::GeneratedFile mainSource(mainSourceFileName);
- if (!parametrizeTemplate(templatePath, QLatin1String("main.cpp"), params, &contents, errorMessage))
- return Core::GeneratedFiles();
- mainSource.setContents(CppTools::AbstractEditorSupport::licenseTemplate(mainSourceFileName)
- + contents);
- // Create files: form source with or without form
- const QString formSourceFileName = buildFileName(projectPath, params.sourceFileName, sourceSuffix());
- const QString formHeaderName = buildFileName(projectPath, params.headerFileName, headerSuffix());
- Core::GeneratedFile formSource(formSourceFileName);
- Core::GeneratedFile formHeader(formHeaderName);
- formSource.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
-
- QSharedPointer<Core::GeneratedFile> form;
- if (params.designerForm) {
- // Create files: form
- const QString formName = buildFileName(projectPath, params.formFileName, formSuffix());
- form = QSharedPointer<Core::GeneratedFile>(new Core::GeneratedFile(formName));
- if (!parametrizeTemplate(templatePath, QLatin1String("widget.ui"), params, &contents, errorMessage))
- return Core::GeneratedFiles();
- form->setContents(contents);
- if (!generateFormClass(params, *form, &formSource, &formHeader, errorMessage))
- return Core::GeneratedFiles();
- } else {
- const QString formSourceTemplate = QLatin1String("mywidget.cpp");
- if (!parametrizeTemplate(templatePath, formSourceTemplate, params, &contents, errorMessage))
- return Core::GeneratedFiles();
- formSource.setContents(CppTools::AbstractEditorSupport::licenseTemplate(formSourceFileName)
- + contents);
- // Create files: form header
- const QString formHeaderTemplate = QLatin1String("mywidget.h");
- if (!parametrizeTemplate(templatePath, formHeaderTemplate, params, &contents, errorMessage))
- return Core::GeneratedFiles();
- formHeader.setContents(CppTools::AbstractEditorSupport::licenseTemplate(formHeaderName)
- + contents);
- }
- // Create files: profile
- const QString profileName = buildFileName(projectPath, projectParams.fileName, profileSuffix());
- Core::GeneratedFile profile(profileName);
- profile.setAttributes(Core::GeneratedFile::OpenProjectAttribute);
- contents.clear();
- {
- QTextStream proStr(&contents);
- QtProjectParameters::writeProFileHeader(proStr);
- projectParams.writeProFile(proStr);
- proStr << "\nCONFIG += c++11"; // ensure all Qt5 versions can handle the source
- proStr << "\n\nSOURCES +="
- << " \\\n " << Utils::FileName::fromString(mainSourceFileName).fileName()
- << " \\\n " << Utils::FileName::fromString(formSource.path()).fileName()
- << "\n\nHEADERS +="
- << " \\\n " << Utils::FileName::fromString(formHeader.path()).fileName();
- if (params.designerForm)
- proStr << "\n\nFORMS +="
- << " \\\n " << Utils::FileName::fromString(form->path()).fileName();
- if (params.isMobileApplication) {
- proStr << "\n\nCONFIG += mobility"
- << "\nMOBILITY = "
- << "\n";
- }
- proStr << "\n\n# Default rules for deployment.\n"
- "qnx: target.path = /tmp/$${TARGET}/bin\n"
- "else: unix:!android: target.path = /opt/$${TARGET}/bin\n"
- "!isEmpty(target.path): INSTALLS += target\n";
- }
- profile.setContents(contents);
- // List
- Core::GeneratedFiles rc;
- rc << mainSource << formSource << formHeader;
- if (params.designerForm)
- rc << *form;
- rc << profile;
- return rc;
-}
-
-bool GuiAppWizard::parametrizeTemplate(const QString &templatePath, const QString &templateName,
- const GuiAppParameters &params,
- QString *target, QString *errorMessage)
-{
- const QString fileName = templatePath + QLatin1Char('/') + templateName;
- Utils::FileReader reader;
- if (!reader.fetch(fileName, QIODevice::Text, errorMessage))
- return false;
- QString contents = QString::fromUtf8(reader.data());
- contents.replace(QLatin1String("%QAPP_INCLUDE%"), QLatin1String("QApplication"));
- contents.replace(QLatin1String("%INCLUDE%"), params.headerFileName);
- contents.replace(QLatin1String("%CLASS%"), params.className);
- contents.replace(QLatin1String("%BASECLASS%"), params.baseClassName);
- contents.replace(QLatin1String("%WIDGET_HEIGHT%"), QString::number(params.widgetHeight));
- contents.replace(QLatin1String("%WIDGET_WIDTH%"), QString::number(params.widgetWidth));
- if (params.isMobileApplication)
- contents.replace(QLatin1String("%SHOWMETHOD%"), QString::fromLatin1(mainSourceMobilityShowC));
- else
- contents.replace(QLatin1String("%SHOWMETHOD%"), QString::fromLatin1(mainSourceShowC));
-
- // Replace include guards with pragma once
- if (CppTools::AbstractEditorSupport::usePragmaOnce()) {
- contents.replace(QLatin1String("#ifndef %PRE_DEF%\n#define %PRE_DEF%"), "#pragma once");
- contents.replace(QLatin1String("#endif // %PRE_DEF%\n"), QString());
- }
-
- const QChar dot = QLatin1Char('.');
-
- QString preDef = params.headerFileName.toUpper();
- preDef.replace(dot, QLatin1Char('_'));
- contents.replace(QLatin1String("%PRE_DEF%"), preDef);
-
- const QString uiFileName = params.formFileName;
- QString uiHdr = QLatin1String("ui_");
- uiHdr += uiFileName.left(uiFileName.indexOf(dot));
- uiHdr += QLatin1String(".h");
-
- contents.replace(QLatin1String("%UI_HDR%"), uiHdr);
- if (params.baseClassName == QLatin1String("QMainWindow")) {
- if (params.isMobileApplication)
- contents.replace(QLatin1String("%CENTRAL_WIDGET%"), QLatin1String(mainWindowMobileUiContentsC));
- else
- contents.replace(QLatin1String("%CENTRAL_WIDGET%"), QLatin1String(mainWindowUiContentsC));
- } else {
- contents.remove(QLatin1String("%CENTRAL_WIDGET%"));
- }
- *target = contents;
- return true;
-}
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/guiappwizard.h b/src/plugins/qmakeprojectmanager/wizards/guiappwizard.h
deleted file mode 100644
index 31eb5b7ce9..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/guiappwizard.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 "qtwizard.h"
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-struct GuiAppParameters;
-
-class GuiAppWizard : public QtWizard
-{
- Q_OBJECT
-
-public:
- GuiAppWizard();
-
-private:
- Core::BaseFileWizard *create(QWidget *parent, const Core::WizardDialogParameters &parameters) const override;
-
- Core::GeneratedFiles generateFiles(const QWizard *w, QString *errorMessage) const override;
-
-private:
- static bool parametrizeTemplate(const QString &templatePath, const QString &templateName,
- const GuiAppParameters &params,
- QString *target, QString *errorMessage);
-};
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.cpp b/src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.cpp
deleted file mode 100644
index 5f12fdc41a..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.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 "guiappwizarddialog.h"
-
-#include "filespage.h"
-
-#include <projectexplorer/projectexplorerconstants.h>
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-GuiAppWizardDialog::GuiAppWizardDialog(const Core::BaseFileWizardFactory *factory,
- const QString &templateName,
- const QIcon &icon, QWidget *parent,
- const Core::WizardDialogParameters &parameters) :
- BaseQmakeProjectWizardDialog(factory, false, parent, parameters),
- m_filesPage(new FilesPage)
-{
- setWindowIcon(icon);
- setWindowTitle(templateName);
- setSelectedModules(QLatin1String("core gui"), true);
-
- setIntroDescription(tr("This wizard generates a Qt Widgets Application "
- "project. The application derives by default from QApplication "
- "and includes an empty widget."));
-
- addModulesPage();
- if (!parameters.extraValues().contains(QLatin1String(ProjectExplorer::Constants::PROJECT_KIT_IDS)))
- addTargetSetupPage();
-
- m_filesPage->setFormInputCheckable(true);
- m_filesPage->setClassTypeComboVisible(false);
- addPage(m_filesPage);
-
- addExtensionPages(extensionPages());
-}
-
-void GuiAppWizardDialog::setBaseClasses(const QStringList &baseClasses)
-{
- m_filesPage->setBaseClassChoices(baseClasses);
- if (!baseClasses.empty())
- m_filesPage->setBaseClassName(baseClasses.front());
-}
-
-void GuiAppWizardDialog::setSuffixes(const QString &header, const QString &source, const QString &form)
-{
- m_filesPage->setSuffixes(header, source, form);
-}
-
-void GuiAppWizardDialog::setLowerCaseFiles(bool l)
-{
- m_filesPage->setLowerCaseFiles(l);
-}
-
-QtProjectParameters GuiAppWizardDialog::projectParameters() const
-{
- QtProjectParameters rc;
- rc.type = QtProjectParameters::GuiApp;
- rc.flags |= QtProjectParameters::WidgetsRequiredFlag;
- rc.fileName = projectName();
- rc.path = path();
- rc.selectedModules = selectedModulesList();
- rc.deselectedModules = deselectedModulesList();
- return rc;
-}
-
-GuiAppParameters GuiAppWizardDialog::parameters() const
-{
- GuiAppParameters rc;
- rc.className = m_filesPage->className();
- rc.baseClassName = m_filesPage->baseClassName();
- rc.sourceFileName = m_filesPage->sourceFileName();
- rc.headerFileName = m_filesPage->headerFileName();
- rc.formFileName = m_filesPage->formFileName();
- rc.designerForm = m_filesPage->formInputChecked();
- if (isQtPlatformSelected("Android.Device.Type")) { // FIXME: Is this really necessary?
- rc.isMobileApplication = true;
- rc.widgetWidth = 800;
- rc.widgetHeight = 480;
- }
- return rc;
-}
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.h b/src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.h
deleted file mode 100644
index b12644e123..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/guiappwizarddialog.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 "qtwizard.h"
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-struct QtProjectParameters;
-class FilesPage;
-
-// Additional parameters required besides QtProjectParameters
-struct GuiAppParameters
-{
- QString className;
- QString baseClassName;
- QString sourceFileName;
- QString headerFileName;
- QString formFileName;
- int widgetWidth = 400;
- int widgetHeight = 300;
- bool designerForm = true;
- bool isMobileApplication = false;
-};
-
-class GuiAppWizardDialog : public BaseQmakeProjectWizardDialog
-{
- Q_OBJECT
-
-public:
- explicit GuiAppWizardDialog(const Core::BaseFileWizardFactory *factory, const QString &templateName,
- const QIcon &icon,
- QWidget *parent,
- const Core::WizardDialogParameters &parameters);
-
- void setBaseClasses(const QStringList &baseClasses);
- void setSuffixes(const QString &header, const QString &source, const QString &form);
- void setLowerCaseFiles(bool l);
-
- QtProjectParameters projectParameters() const;
- GuiAppParameters parameters() const;
-
-private:
- FilesPage *m_filesPage;
-};
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp b/src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp
deleted file mode 100644
index 83217ce2bf..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "libraryparameters.h"
-#include "librarywizarddialog.h"
-
-#include <utils/codegeneration.h>
-#include <utils/qtcassert.h>
-
-#include <QTextStream>
-#include <QStringList>
-
-#include <cstring>
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-void LibraryParameters::generateCode(QtProjectParameters:: Type t,
- const QString &headerName,
- const QString &sharedHeader,
- const QString &exportMacro,
- const QString &pluginJsonFileName,
- int indentation,
- bool usePragmaOnce,
- QString *header,
- QString *source) const
-{
- QTextStream headerStr(header);
-
- const QString indent = QString(indentation, QLatin1Char(' '));
-
- // Do we have namespaces?
- QStringList namespaceList = className.split(QLatin1String("::"));
- if (namespaceList.empty()) // Paranoia!
- return;
-
- const QString unqualifiedClassName = namespaceList.takeLast();
-
- // 1) Header
- const QString guard = Utils::headerGuard(headerFileName, namespaceList);
- if (usePragmaOnce)
- headerStr << "#pragma once\n\n";
- else
- headerStr << "#ifndef " << guard << "\n#define " << guard << "\n\n";
-
- if (!sharedHeader.isEmpty())
- Utils::writeIncludeFileDirective(sharedHeader, false, headerStr);
-
- // include base class header
- if (!baseClassName.isEmpty()) {
- Utils::writeIncludeFileDirective(baseClassName, true, headerStr);
- headerStr << '\n';
- }
-
- const QString namespaceIndent = Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr);
-
- // Class declaraction
- if (!namespaceIndent.isEmpty())
- headerStr << '\n';
- headerStr << namespaceIndent << "class ";
- if (t == QtProjectParameters::SharedLibrary && !exportMacro.isEmpty())
- headerStr << exportMacro << ' ';
-
- headerStr << unqualifiedClassName;
- if (!baseClassName.isEmpty())
- headerStr << " : public " << baseClassName;
- headerStr << "\n{\n";
-
- // Is this a QObject (plugin)
- const bool inheritsQObject = t == QtProjectParameters::QtPlugin;
- if (inheritsQObject)
- headerStr << namespaceIndent << indent << "Q_OBJECT\n";
- if (t == QtProjectParameters::QtPlugin) { // Write Qt plugin meta data.
- const QString qt5InterfaceName = LibraryWizardDialog::pluginInterface(baseClassName);
- QTC_CHECK(!qt5InterfaceName.isEmpty());
- headerStr << namespaceIndent << indent << "Q_PLUGIN_METADATA(IID \""
- << qt5InterfaceName << '"';
- QTC_CHECK(!pluginJsonFileName.isEmpty());
- headerStr << " FILE \"" << pluginJsonFileName << '"';
- headerStr << ")\n";
- }
-
- headerStr << namespaceIndent << "\npublic:\n";
- if (inheritsQObject) {
- headerStr << namespaceIndent << indent << "explicit " << unqualifiedClassName
- << "(QObject *parent = nullptr);\n";
- } else {
- headerStr << namespaceIndent << indent << unqualifiedClassName << "();\n";
- }
- if (!pureVirtualSignatures.empty()) {
- headerStr << "\nprivate:\n";
- for (const QString &signature : pureVirtualSignatures)
- headerStr << namespaceIndent << indent << signature << " override;\n";
- }
- headerStr << namespaceIndent << "};\n";
- if (!namespaceIndent.isEmpty())
- headerStr << '\n';
- Utils::writeClosingNameSpaces(namespaceList, indent, headerStr);
- if (!usePragmaOnce)
- headerStr << "\n#endif // " << guard << '\n';
-
- /// 2) Source
- QTextStream sourceStr(source);
-
- Utils::writeIncludeFileDirective(headerName, false, sourceStr);
- sourceStr << '\n';
-
- Utils::writeOpeningNameSpaces(namespaceList, indent, sourceStr);
- if (!namespaceIndent.isEmpty())
- sourceStr << '\n';
-
- // Constructor
- sourceStr << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName;
- if (inheritsQObject) {
- sourceStr << "(QObject *parent) :\n"
- << namespaceIndent << indent << baseClassName << "(parent)\n";
- } else {
- sourceStr << "()\n";
- }
- sourceStr << namespaceIndent << "{\n" << namespaceIndent << "}\n";
- for (const QString &signature : pureVirtualSignatures) {
- const int parenIndex = signature.indexOf('(');
- QTC_ASSERT(parenIndex != -1, continue);
- int nameIndex = -1;
- for (int i = parenIndex - 1; i > 0; --i) {
- if (!signature.at(i).isLetterOrNumber()) {
- nameIndex = i + 1;
- break;
- }
- }
- QTC_ASSERT(nameIndex != -1, continue);
- sourceStr << '\n' << namespaceIndent << signature.left(nameIndex);
- if (!std::strchr("&* ", signature.at(nameIndex - 1).toLatin1()))
- sourceStr << ' ';
- sourceStr << unqualifiedClassName << "::" << signature.mid(nameIndex) << '\n';
- sourceStr << namespaceIndent << "{\n" << indent
- << "static_assert(false, \"You need to implement this function\");\n}\n";
- }
-
- Utils::writeClosingNameSpaces(namespaceList, indent, sourceStr);
-}
-
-QString LibraryParameters::generateSharedHeader(const QString &globalHeaderFileName,
- const QString &projectTarget,
- const QString &exportMacro,
- bool usePragmaOnce)
-{
- QString contents;
- if (usePragmaOnce) {
- contents += "#pragma once\n";
- } else {
- contents += "#ifndef " + Utils::headerGuard(globalHeaderFileName) + "\n";
- contents += "#define " + Utils::headerGuard(globalHeaderFileName) + "\n";
- }
- contents += "\n";
- contents += "#include <QtCore/qglobal.h>\n";
- contents += "\n";
- contents += "#if defined(" + QtProjectParameters::libraryMacro(projectTarget) + ")\n";
- contents += "# define " + exportMacro + " Q_DECL_EXPORT\n";
- contents += "#else\n";
- contents += "# define " + exportMacro + " Q_DECL_IMPORT\n";
- contents += "#endif\n";
- contents += "\n";
- if (!usePragmaOnce)
- contents += "#endif // " + Utils::headerGuard(globalHeaderFileName) + '\n';
-
- return contents;
-}
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/libraryparameters.h b/src/plugins/qmakeprojectmanager/wizards/libraryparameters.h
deleted file mode 100644
index 4fe7d00dc1..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/libraryparameters.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 "qtprojectparameters.h"
-
-#include <QStringList>
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-// Additional parameters required besides QtProjectParameters for creating
-// libraries
-struct LibraryParameters {
-
- // generate class
- void generateCode(QtProjectParameters:: Type t,
- const QString &headerName,
- const QString &sharedHeader,
- const QString &exportMacro,
- const QString &pluginJsonFileName,
- int indentation,
- bool usePragmaOnce,
- QString *header,
- QString *source) const;
-
- // Generate the code of the shared header containing the export macro
- static QString generateSharedHeader(const QString &globalHeaderFileName,
- const QString &projectTarget,
- const QString &exportMacro,
- bool usePragmaOnce);
-
- QString className;
- QString baseClassName;
- QString sourceFileName;
- QString headerFileName;
- QStringList pureVirtualSignatures;
-};
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/librarywizard.cpp b/src/plugins/qmakeprojectmanager/wizards/librarywizard.cpp
deleted file mode 100644
index 239fec9c3f..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/librarywizard.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "librarywizard.h"
-#include "librarywizarddialog.h"
-
-#include <cpptools/abstracteditorsupport.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <qtsupport/qtsupportconstants.h>
-
-#include <utils/fileutils.h>
-
-#include <QTextStream>
-#include <QCoreApplication>
-
-static const char sharedHeaderPostfixC[] = "_global";
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-LibraryWizard::LibraryWizard()
-{
- setId("H.Qt4Library");
- setCategory(QLatin1String(ProjectExplorer::Constants::LIBRARIES_WIZARD_CATEGORY));
- setDisplayCategory(QCoreApplication::translate("ProjectExplorer",
- ProjectExplorer::Constants::LIBRARIES_WIZARD_CATEGORY_DISPLAY));
- setDisplayName(tr("C++ Library"));
- setDescription(tr("Creates a C++ library based on qmake. This can be used to create:<ul>"
- "<li>a shared C++ library for use with <tt>QPluginLoader</tt> and runtime (Plugins)</li>"
- "<li>a shared or static C++ library for use with another project at linktime</li></ul>"));
- setIcon(QIcon(QLatin1String(":/wizards/images/lib.png")));
- setRequiredFeatures({QtSupport::Constants::FEATURE_QT_PREFIX});
-}
-
-Core::BaseFileWizard *LibraryWizard::create(QWidget *parent, const Core::WizardDialogParameters &parameters) const
-{
- LibraryWizardDialog *dialog = new LibraryWizardDialog(this, displayName(), icon(), parent, parameters);
- dialog->setLowerCaseFiles(QtWizard::lowerCaseFiles());
- dialog->setProjectName(LibraryWizardDialog::uniqueProjectName(parameters.defaultPath()));
- dialog->setSuffixes(headerSuffix(), sourceSuffix(), formSuffix());
- return dialog;
-}
-
-static void writeLinuxProFile(QTextStream &str, const QtProjectParameters &params)
-{
- str << "\n"
- "unix {\n";
- if (!params.targetDirectory.isEmpty())
- str << " target.path = " << params.targetDirectory << '\n';
- else
- str << " target.path = /usr/lib\n";
- str << " INSTALLS += target\n"
- "}\n";
-}
-
-Core::GeneratedFiles LibraryWizard::generateFiles(const QWizard *w,
- QString *errorMessage) const
-{
- Q_UNUSED(errorMessage)
- const auto *dialog = qobject_cast<const LibraryWizardDialog *>(w);
- const QtProjectParameters projectParams = dialog->parameters();
- const QString projectPath = projectParams.projectPath();
- const LibraryParameters params = dialog->libraryParameters();
- const bool usePragmaOnce = CppTools::AbstractEditorSupport::usePragmaOnce();
-
- const QString sharedLibExportMacro = QtProjectParameters::exportMacro(projectParams.fileName);
-
- Core::GeneratedFiles rc;
- // Class header + source
- const QString sourceFileName = buildFileName(projectPath, params.sourceFileName, sourceSuffix());
- Core::GeneratedFile source(sourceFileName);
- source.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
-
- const QString headerFileFullName = buildFileName(projectPath, params.headerFileName, headerSuffix());
- const QString headerFileName = Utils::FileName::fromString(headerFileFullName).fileName();
- QString pluginJsonFileFullName;
- QString pluginJsonFileName;
- if (projectParams.type == QtProjectParameters::QtPlugin) {
- pluginJsonFileFullName = buildFileName(projectPath, projectParams.fileName, QLatin1String("json"));
- pluginJsonFileName = Utils::FileName::fromString(pluginJsonFileFullName).fileName();
- }
-
- Core::GeneratedFile header(headerFileFullName);
-
- // Create files: global header for shared libs
- QString globalHeaderFileName;
- if (projectParams.type == QtProjectParameters::SharedLibrary) {
- const QString globalHeaderName = buildFileName(projectPath, projectParams.fileName.toLower() + QLatin1String(sharedHeaderPostfixC), headerSuffix());
- Core::GeneratedFile globalHeader(globalHeaderName);
- globalHeaderFileName = Utils::FileName::fromString(globalHeader.path()).fileName();
- globalHeader.setContents(CppTools::AbstractEditorSupport::licenseTemplate(globalHeaderFileName)
- + LibraryParameters::generateSharedHeader(globalHeaderFileName, projectParams.fileName, sharedLibExportMacro, usePragmaOnce));
- rc.push_back(globalHeader);
- }
-
- // Generate code
- QString headerContents, sourceContents;
- params.generateCode(projectParams.type, headerFileName,
- globalHeaderFileName, sharedLibExportMacro, pluginJsonFileName,
- /* indentation*/ 4, usePragmaOnce, &headerContents, &sourceContents);
-
- source.setContents(CppTools::AbstractEditorSupport::licenseTemplate(sourceFileName, params.className)
- + sourceContents);
- header.setContents(CppTools::AbstractEditorSupport::licenseTemplate(headerFileFullName, params.className)
- + headerContents);
- rc.push_back(source);
- rc.push_back(header);
- // Create files: profile
- const QString profileName = buildFileName(projectPath, projectParams.fileName, profileSuffix());
- Core::GeneratedFile profile(profileName);
- profile.setAttributes(Core::GeneratedFile::OpenProjectAttribute);
- QString profileContents;
- {
- QTextStream proStr(&profileContents);
- QtProjectParameters::writeProFileHeader(proStr);
- projectParams.writeProFile(proStr);
- proStr << "\nSOURCES +="
- << " \\\n " << Utils::FileName::fromString(source.path()).fileName()
- << "\n\nHEADERS +="
- << " \\\n " << headerFileName;
- if (!globalHeaderFileName.isEmpty())
- proStr << " \\\n " << globalHeaderFileName << " \n";
- if (!pluginJsonFileName.isEmpty())
- proStr << "\nDISTFILES += " << pluginJsonFileName << " \n";
- writeLinuxProFile(proStr, projectParams);
- }
- profile.setContents(profileContents);
- rc.push_back(profile);
-
- if (!pluginJsonFileName.isEmpty()) {
- Core::GeneratedFile jsonFile(pluginJsonFileFullName);
- jsonFile.setContents(QLatin1String("{\n \"Keys\" : [ ]\n}\n"));
- rc.push_back(jsonFile);
- }
- return rc;
-}
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/librarywizard.h b/src/plugins/qmakeprojectmanager/wizards/librarywizard.h
deleted file mode 100644
index f7edeb5330..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/librarywizard.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 "qtwizard.h"
-#include "libraryparameters.h"
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-class LibraryWizard : public QtWizard
-{
- Q_OBJECT
-
-public:
- LibraryWizard();
-
-protected:
- Core::BaseFileWizard *create(QWidget *parent, const Core::WizardDialogParameters &parameters) const override;
-
- Core::GeneratedFiles generateFiles(const QWizard *w, QString *errorMessage) const override;
-};
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp b/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp
deleted file mode 100644
index 2aed6d43cd..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "librarywizarddialog.h"
-#include "filespage.h"
-#include "libraryparameters.h"
-#include "modulespage.h"
-
-#include <utils/projectintropage.h>
-#include <projectexplorer/projectexplorerconstants.h>
-
-#include <QDebug>
-
-#include <QComboBox>
-#include <QLabel>
-
-enum { debugLibWizard = 0 };
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-struct PluginBaseClasses {
- const char *name;
- const char *module;
- QStringList pureVirtuals;
-
- // blank separated list or 0
- const char *dependentModules;
- const char *targetDirectory;
- const char *pluginInterface;
-};
-using QSL = QStringList;
-
-static const PluginBaseClasses pluginBaseClasses[] =
-{
- {"QAccessiblePlugin", "QtGui",
- QSL{"QAccessibleInterface *create(const QString &key, QObject *object)"},
- "QtCore", "accessible", "QAccessibleFactoryInterface"},
- {"QGenericPlugin", "QtGui", QSL{"QObject *create(const QString &name, const QString &spec)"},
- "QtCore", "generic", "QGenericPluginFactoryInterface"},
- {"QIconEnginePlugin", "QtGui", QSL{"QIconEngine *create(const QString &filename)"},
- "QtCore", "imageformats", "QIconEngineFactoryInterface"},
- {"QImageIOPlugin", "QtGui",
- QSL{"QImageIOPlugin::Capabilities capabilities(QIODevice *device, const QByteArray &format) const",
- "QImageIOHandler *create(QIODevice *device, const QByteArray &format) const"},
- "QtCore", "imageformats", "QImageIOHandlerFactoryInterface"},
- {"QScriptExtensionPlugin", "QtScript",
- QSL{"void initialize(const QString &key, QScriptEngine *engine)", "QStringList keys() const"},
- "QtCore", nullptr, "QScriptExtensionInterface"},
- {"QSqlDriverPlugin", "QtSql", QSL{"QSqlDriver *create(const QString &key)"},
- "QtCore", "sqldrivers", "QSqlDriverFactoryInterface"},
- {"QStylePlugin", "QtWidgets", QSL{"QStyle *create(const QString &key)"},
- "QtCore", "styles", "QStyleFactoryInterface"},
-};
-
-enum { defaultPluginBaseClass = 1 };
-
-static const PluginBaseClasses *findPluginBaseClass(const QString &name)
-{
- const int pluginBaseClassCount = sizeof(pluginBaseClasses)/sizeof(PluginBaseClasses);
- for (int i = 0; i < pluginBaseClassCount; i++)
- if (name == QLatin1String(pluginBaseClasses[i].name))
- return pluginBaseClasses + i;
- return nullptr;
-}
-
-// return dependencies of a plugin as a line ready for the 'QT=' line in a pro
-// file
-static QStringList pluginDependencies(const PluginBaseClasses *plb)
-{
- QStringList dependencies;
- const QChar blank = QLatin1Char(' ');
- // Find the module names and convert to ids
- QStringList pluginModules= plb->dependentModules ?
- QString::fromLatin1(plb->dependentModules).split(blank) :
- QStringList();
- pluginModules.push_back(QLatin1String(plb->module));
- foreach (const QString &module, pluginModules) {
- dependencies.append(ModulesPage::idOfModule(module));
- }
- return dependencies;
-}
-
-// A Project intro page with an additional type chooser.
-class LibraryIntroPage : public Utils::ProjectIntroPage
-{
-public:
- explicit LibraryIntroPage(QWidget *parent = nullptr);
-
- QtProjectParameters::Type type() const;
-
-private:
- QComboBox *m_typeCombo;
-};
-
-LibraryIntroPage::LibraryIntroPage(QWidget *parent) :
- Utils::ProjectIntroPage(parent),
- m_typeCombo(new QComboBox)
-{
- m_typeCombo->setEditable(false);
- m_typeCombo->addItem(LibraryWizardDialog::tr("Shared Library"),
- QVariant(QtProjectParameters::SharedLibrary));
- m_typeCombo->addItem(LibraryWizardDialog::tr("Statically Linked Library"),
- QVariant(QtProjectParameters::StaticLibrary));
- m_typeCombo->addItem(LibraryWizardDialog::tr("Qt Plugin"),
- QVariant(QtProjectParameters::QtPlugin));
- insertControl(0, new QLabel(LibraryWizardDialog::tr("Type")), m_typeCombo);
-}
-
-QtProjectParameters::Type LibraryIntroPage::type() const
-{
- return static_cast<QtProjectParameters::Type>(m_typeCombo->itemData(m_typeCombo->currentIndex()).toInt());
-}
-
-// ------------------- LibraryWizardDialog
-LibraryWizardDialog::LibraryWizardDialog(const Core::BaseFileWizardFactory *factory,
- const QString &templateName,
- const QIcon &icon,
- QWidget *parent,
- const Core::WizardDialogParameters &parameters) :
- BaseQmakeProjectWizardDialog(factory, true, new LibraryIntroPage, -1, parent, parameters),
- m_filesPage(new FilesPage),
- m_pluginBaseClassesInitialized(false),
- m_filesPageId(-1), m_modulesPageId(-1), m_targetPageId(-1)
-{
- setWindowIcon(icon);
- setWindowTitle(templateName);
- setSelectedModules(QLatin1String("core"));
-
- // Note that QWizard::currentIdChanged() is emitted at strange times.
- // Use the intro page instead, set up initially
- setIntroDescription(tr("This wizard generates a C++ Library project."));
-
- if (!parameters.extraValues().contains(QLatin1String(ProjectExplorer::Constants::PROJECT_KIT_IDS)))
- m_targetPageId = addTargetSetupPage();
-
- m_modulesPageId = addModulesPage();
-
- m_filesPage->setNamespacesEnabled(true);
- m_filesPage->setFormFileInputVisible(false);
- m_filesPage->setClassTypeComboVisible(false);
-
- m_filesPageId = addPage(m_filesPage);
-
- Utils::WizardProgressItem *introItem = wizardProgress()->item(startId());
- Utils::WizardProgressItem *targetItem = nullptr;
- if (m_targetPageId != -1)
- targetItem = wizardProgress()->item(m_targetPageId);
- Utils::WizardProgressItem *modulesItem = wizardProgress()->item(m_modulesPageId);
- Utils::WizardProgressItem *filesItem = wizardProgress()->item(m_filesPageId);
- filesItem->setTitle(tr("Details"));
-
- if (targetItem) {
- if (m_targetPageId != -1) {
- targetItem->setNextItems(QList<Utils::WizardProgressItem *>()
- << modulesItem << filesItem);
- targetItem->setNextShownItem(nullptr);
- } else {
- introItem->setNextItems(QList<Utils::WizardProgressItem *>()
- << modulesItem << filesItem);
- introItem->setNextShownItem(nullptr);
- }
- }
-
- connect(this, &QWizard::currentIdChanged, this, &LibraryWizardDialog::slotCurrentIdChanged);
-
- addExtensionPages(extensionPages());
-}
-
-void LibraryWizardDialog::setSuffixes(const QString &header, const QString &source, const QString &form)
-{
- m_filesPage->setSuffixes(header, source, form);
-}
-
-void LibraryWizardDialog::setLowerCaseFiles(bool l)
-{
- m_filesPage->setLowerCaseFiles(l);
-}
-
-QtProjectParameters::Type LibraryWizardDialog::type() const
-{
- return static_cast<const LibraryIntroPage*>(introPage())->type();
-}
-
-bool LibraryWizardDialog::isModulesPageSkipped() const
-{
- // When leaving the intro or target page, the modules page is skipped
- // in the case of a plugin since it knows its dependencies by itself.
- return type() == QtProjectParameters::QtPlugin;
-}
-
-int LibraryWizardDialog::skipModulesPageIfNeeded() const
-{
- if (isModulesPageSkipped())
- return m_filesPageId;
- return m_modulesPageId;
-}
-
-int LibraryWizardDialog::nextId() const
-{
- if (m_targetPageId != -1) {
- if (currentId() == m_targetPageId)
- return skipModulesPageIfNeeded();
- } else if (currentId() == startId()) {
- return skipModulesPageIfNeeded();
- }
-
- return BaseQmakeProjectWizardDialog::nextId();
-}
-
-void LibraryWizardDialog::initializePage(int id)
-{
- if (m_targetPageId != -1 && id == m_targetPageId) {
- Utils::WizardProgressItem *targetsItem = wizardProgress()->item(m_targetPageId);
- Utils::WizardProgressItem *modulesItem = wizardProgress()->item(m_modulesPageId);
- Utils::WizardProgressItem *filesItem = wizardProgress()->item(m_filesPageId);
- if (isModulesPageSkipped())
- targetsItem->setNextShownItem(filesItem);
- else
- targetsItem->setNextShownItem(modulesItem);
-
- }
- BaseQmakeProjectWizardDialog::initializePage(id);
-}
-
-void LibraryWizardDialog::cleanupPage(int id)
-{
- if (m_targetPageId != -1 && id == m_targetPageId) {
- Utils::WizardProgressItem *targetsItem = wizardProgress()->item(m_targetPageId);
- targetsItem->setNextShownItem(nullptr);
- }
- BaseQmakeProjectWizardDialog::cleanupPage(id);
-}
-
-QtProjectParameters LibraryWizardDialog::parameters() const
-{
- QtProjectParameters rc;
- rc.type = type();
- rc.fileName = projectName();
- rc.path = path();
- if (rc.type == QtProjectParameters::QtPlugin) {
- // Plugin: Dependencies & Target directory
- if (const PluginBaseClasses *plb = findPluginBaseClass(m_filesPage->baseClassName())) {
- rc.selectedModules = pluginDependencies(plb);
- if (plb->targetDirectory) {
- rc.targetDirectory = QLatin1String("$$[QT_INSTALL_PLUGINS]/");
- rc.targetDirectory += QLatin1String(plb->targetDirectory);
- }
- }
- } else {
- // Modules from modules page
- rc.selectedModules = selectedModulesList();
- rc.deselectedModules = deselectedModulesList();
- }
- return rc;
-}
-
-void LibraryWizardDialog::slotCurrentIdChanged(int id)
-{
- if (debugLibWizard)
- qDebug() << Q_FUNC_INFO << id;
- if (id == m_filesPageId)
- setupFilesPage();// Switching to files page: Set up base class accordingly (plugin)
-}
-
-void LibraryWizardDialog::setupFilesPage()
-{
- switch (type()) {
- case QtProjectParameters::QtPlugin:
- if (!m_pluginBaseClassesInitialized) {
- if (debugLibWizard)
- qDebug("initializing for plugins");
- QStringList baseClasses;
- const int pluginBaseClassCount = sizeof(pluginBaseClasses)/sizeof(PluginBaseClasses);
- Q_ASSERT(defaultPluginBaseClass < pluginBaseClassCount);
- for (const PluginBaseClasses &pluginBaseClasse : pluginBaseClasses)
- baseClasses.push_back(QLatin1String(pluginBaseClasse.name));
- m_filesPage->setBaseClassChoices(baseClasses);
- m_filesPage->setBaseClassName(baseClasses.at(defaultPluginBaseClass));
- m_pluginBaseClassesInitialized = true;
- }
- m_filesPage->setBaseClassInputVisible(true);
- break;
- default:
- if (!m_filesPage->isComplete()) {
- // Urrm, figure out a good class name. Use project name this time
- QString className = projectName();
- if (!className.isEmpty())
- className[0] = className.at(0).toUpper();
- m_filesPage->setClassName(className);
- m_filesPage->setBaseClassInputVisible(false);
- }
- break;
- }
-}
-
-LibraryParameters LibraryWizardDialog::libraryParameters() const
-{
- LibraryParameters rc;
- rc.className = m_filesPage->className();
- if (type() == QtProjectParameters::QtPlugin) {
- rc.baseClassName = m_filesPage->baseClassName();
- for (const PluginBaseClasses &c : pluginBaseClasses) {
- if (QLatin1String(c.name) == rc.baseClassName) {
- rc.pureVirtualSignatures = c.pureVirtuals;
- break;
- }
- }
- }
- rc.sourceFileName = m_filesPage->sourceFileName();
- rc.headerFileName = m_filesPage->headerFileName();
- return rc;
-}
-
-QString LibraryWizardDialog::pluginInterface(const QString &baseClass)
-{
- if (const PluginBaseClasses *plb = findPluginBaseClass(baseClass))
- if (plb->pluginInterface)
- return QLatin1String("org.qt-project.Qt.") + QLatin1String(plb->pluginInterface);
- return QString();
-}
-
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.h b/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.h
deleted file mode 100644
index 620ffe7cca..0000000000
--- a/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.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 "qtwizard.h"
-
-namespace QmakeProjectManager {
-namespace Internal {
-
-struct QtProjectParameters;
-class FilesPage;
-struct LibraryParameters;
-
-// Library wizard dialog.
-class LibraryWizardDialog : public BaseQmakeProjectWizardDialog
-{
- Q_OBJECT
-
-public:
- LibraryWizardDialog(const Core::BaseFileWizardFactory *factory, const QString &templateName,
- const QIcon &icon,
- QWidget *parent,
- const Core::WizardDialogParameters &parameters);
-
- void setSuffixes(const QString &header, const QString &source, const QString &form= QString());
- void setLowerCaseFiles(bool);
-
- QtProjectParameters parameters() const;
- LibraryParameters libraryParameters() const;
-
- static QString pluginInterface(const QString &baseClass);
-
- int nextId() const override;
-
-protected:
- void initializePage(int id) override;
- void cleanupPage(int id) override;
-
-private:
- void slotCurrentIdChanged(int);
-
- QtProjectParameters::Type type() const;
- void setupFilesPage();
- bool isModulesPageSkipped() const;
- int skipModulesPageIfNeeded() const;
-
- FilesPage *m_filesPage;
- bool m_pluginBaseClassesInitialized;
- int m_filesPageId;
- int m_modulesPageId;
- int m_targetPageId;
-};
-
-} // namespace Internal
-} // namespace QmakeProjectManager
diff --git a/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp
index 9a4b97a0b7..0e9cd877a5 100644
--- a/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp
+++ b/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp
@@ -205,11 +205,11 @@ int BaseQmakeProjectWizardDialog::addTargetSetupPage(int id)
const Core::Id platform = selectedPlatform();
QSet<Core::Id> features = {QtSupport::Constants::FEATURE_DESKTOP};
if (!platform.isValid())
- m_targetSetupPage->setPreferredKitPredicate(QtKitInformation::qtVersionPredicate(features));
+ m_targetSetupPage->setPreferredKitPredicate(QtKitAspect::qtVersionPredicate(features));
else
- m_targetSetupPage->setPreferredKitPredicate(QtKitInformation::platformPredicate(platform));
+ m_targetSetupPage->setPreferredKitPredicate(QtKitAspect::platformPredicate(platform));
- m_targetSetupPage->setRequiredKitPredicate(QtKitInformation::qtVersionPredicate(requiredFeatures()));
+ m_targetSetupPage->setRequiredKitPredicate(QtKitAspect::qtVersionPredicate(requiredFeatures()));
resize(900, 450);
if (id >= 0)
@@ -259,7 +259,7 @@ bool BaseQmakeProjectWizardDialog::writeUserFile(const QString &proFileName) con
if (!m_targetSetupPage)
return false;
- QmakeProject *pro = new QmakeProject(Utils::FileName::fromString(proFileName));
+ QmakeProject *pro = new QmakeProject(Utils::FilePath::fromString(proFileName));
bool success = m_targetSetupPage->setupProject(pro);
if (success)
pro->saveSettings();
@@ -271,7 +271,7 @@ bool BaseQmakeProjectWizardDialog::isQtPlatformSelected(Core::Id platform) const
{
QList<Core::Id> selectedKitList = selectedKits();
- return Utils::contains(KitManager::kits(QtKitInformation::platformPredicate(platform)),
+ return Utils::contains(KitManager::kits(QtKitAspect::platformPredicate(platform)),
[selectedKitList](const Kit *k) { return selectedKitList.contains(k->id()); });
}
diff --git a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp
index 2c1621fcb0..77c6fdd10f 100644
--- a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp
+++ b/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp
@@ -70,8 +70,8 @@ public:
bool isComplete() const override { return m_filesWidget->hasFilesSelected(); }
void initializePage() override;
void cleanupPage() override { m_filesWidget->cancelParsing(); }
- FileNameList selectedFiles() const { return m_filesWidget->selectedFiles(); }
- FileNameList selectedPaths() const { return m_filesWidget->selectedPaths(); }
+ FilePathList selectedFiles() const { return m_filesWidget->selectedFiles(); }
+ FilePathList selectedPaths() const { return m_filesWidget->selectedPaths(); }
private:
SimpleProjectWizardDialog *m_simpleProjectWizardDialog;
@@ -117,8 +117,8 @@ public:
QString path() const { return m_firstPage->path(); }
void setPath(const QString &path) { m_firstPage->setPath(path); }
- FileNameList selectedFiles() const { return m_secondPage->selectedFiles(); }
- FileNameList selectedPaths() const { return m_secondPage->selectedPaths(); }
+ FilePathList selectedFiles() const { return m_secondPage->selectedFiles(); }
+ FilePathList selectedPaths() const { return m_secondPage->selectedPaths(); }
QString projectName() const { return m_firstPage->fileName(); }
FileWizardPage *m_firstPage;
@@ -127,8 +127,8 @@ public:
void FilesSelectionWizardPage::initializePage()
{
- m_filesWidget->resetModel(FileName::fromString(m_simpleProjectWizardDialog->path()),
- FileNameList());
+ m_filesWidget->resetModel(FilePath::fromString(m_simpleProjectWizardDialog->path()),
+ FilePathList());
}
SimpleProjectWizard::SimpleProjectWizard()
@@ -169,7 +169,7 @@ GeneratedFiles SimpleProjectWizard::generateFiles(const QWizard *w,
const QDir dir(projectPath);
const QString projectName = wizard->projectName();
const QString proFileName = QFileInfo(dir, projectName + ".pro").absoluteFilePath();
- const QStringList paths = Utils::transform(wizard->selectedPaths(), &FileName::toString);
+ const QStringList paths = Utils::transform(wizard->selectedPaths(), &FilePath::toString);
MimeType headerType = Utils::mimeTypeForName("text/x-chdr");
@@ -189,7 +189,7 @@ GeneratedFiles SimpleProjectWizard::generateFiles(const QWizard *w,
QString proSources = "SOURCES = \\\n";
QString proHeaders = "HEADERS = \\\n";
- for (const FileName &fileName : wizard->selectedFiles()) {
+ for (const FilePath &fileName : wizard->selectedFiles()) {
QString source = dir.relativeFilePath(fileName.toString());
MimeType mimeType = Utils::mimeTypeForFile(fileName.toFileInfo());
if (mimeType.matchesName("text/x-chdr") || mimeType.matchesName("text/x-c++hdr"))
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
new file mode 100644
index 0000000000..2a26bb8e7b
--- /dev/null
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -0,0 +1,611 @@
+add_qtc_plugin(QmlDesigner
+ DEPENDS
+ qmljs LanguageUtils QmlEditorWidgets
+ Qt5::QuickWidgets Qt5::CorePrivate
+ DEFINES
+ DESIGNER_CORE_LIBRARY
+ IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
+ INCLUDES
+ ${CMAKE_CURRENT_LIST_DIR}/designercore/include
+ PLUGIN_DEPENDS
+ Core ProjectExplorer QmlJSEditor QmakeProjectManager QmlProjectManager
+ QtSupport TextEditor
+ SOURCES
+ designersettings.cpp designersettings.h
+ designmodecontext.cpp designmodecontext.h
+ designmodewidget.cpp designmodewidget.h
+ documentmanager.cpp documentmanager.h
+ documentwarningwidget.cpp documentwarningwidget.h
+ openuiqmlfiledialog.cpp openuiqmlfiledialog.h openuiqmlfiledialog.ui
+ qmldesignerconstants.h
+ qmldesignericons.h
+ qmldesignerplugin.cpp qmldesignerplugin.h
+ settingspage.cpp settingspage.h settingspage.ui
+ shortcutmanager.cpp shortcutmanager.h
+ switchsplittabwidget.cpp switchsplittabwidget.h
+ EXPLICIT_MOC
+ components/propertyeditor/propertyeditorvalue.h
+ components/connectioneditor/connectionviewwidget.h
+ SKIP_DEBUG_CMAKE_FILE_CHECK
+)
+
+set(QmlDesignerPluginInstallPrefix "${IDE_PLUGIN_PATH}/qmldesigner")
+if (APPLE)
+ set(QmlDesignerPluginInstallPrefix "${IDE_PLUGIN_PATH}/QmlDesigner")
+endif()
+
+add_qtc_plugin(componentsplugin
+ CONDITION TARGET QmlDesigner
+ DEPENDS Core QmlDesigner Utils Qt5::Qml
+ DEFINES COMPONENTS_LIBRARY
+ INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/include
+ SOURCES
+ componentsplugin/addtabdesigneraction.cpp componentsplugin/addtabdesigneraction.h
+ componentsplugin/addtabtotabviewdialog.cpp componentsplugin/addtabtotabviewdialog.h
+ componentsplugin/addtabtotabviewdialog.ui
+ componentsplugin/componentsplugin.cpp componentsplugin/componentsplugin.h
+ componentsplugin/componentsplugin.qrc
+ componentsplugin/entertabdesigneraction.cpp componentsplugin/entertabdesigneraction.h
+ componentsplugin/tabviewindexmodel.cpp componentsplugin/tabviewindexmodel.h
+ PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
+ SKIP_DEBUG_CMAKE_FILE_CHECK
+)
+
+add_qtc_plugin(qmlpreviewplugin
+ CONDITION TARGET QmlDesigner
+ DEPENDS Core ProjectExplorer QmlDesigner Utils Qt5::Qml
+ INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/include
+ SOURCES
+ qmlpreviewplugin/qmlpreviewactions.cpp qmlpreviewplugin/qmlpreviewactions.h
+ qmlpreviewplugin/qmlpreviewplugin.cpp qmlpreviewplugin/qmlpreviewplugin.h
+ qmlpreviewplugin/qmlpreviewplugin.qrc
+ PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
+ SKIP_DEBUG_CMAKE_FILE_CHECK
+)
+
+add_qtc_plugin(qtquickplugin
+ CONDITION TARGET QmlDesigner
+ DEPENDS Core QmlDesigner Utils Qt5::Qml
+ DEFINES QTQUICK_LIBRARY
+ INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/include
+ SOURCES
+ qtquickplugin/qtquickplugin.cpp qtquickplugin/qtquickplugin.h
+ qtquickplugin/qtquickplugin.qrc
+ PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
+ SKIP_DEBUG_CMAKE_FILE_CHECK
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX ../../../share/qtcreator/qml/qmlpuppet/container
+ SOURCES
+ addimportcontainer.cpp addimportcontainer.h
+ idcontainer.cpp idcontainer.h
+ imagecontainer.cpp imagecontainer.h
+ informationcontainer.cpp informationcontainer.h
+ instancecontainer.cpp instancecontainer.h
+ mockuptypecontainer.cpp mockuptypecontainer.h
+ propertyabstractcontainer.cpp propertyabstractcontainer.h
+ propertybindingcontainer.cpp propertybindingcontainer.h
+ propertyvaluecontainer.cpp propertyvaluecontainer.h
+ reparentcontainer.cpp reparentcontainer.h
+ sharedmemory.h
+)
+
+if (UNIX)
+ extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX ../../../share/qtcreator/qml/qmlpuppet/container
+ SOURCES sharedmemory_unix.cpp
+ )
+ if (NOT APPLE)
+ extend_qtc_plugin(QmlDesigner DEPENDS rt)
+ endif()
+else()
+ extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX ../../../share/qtcreator/qml/qmlpuppet/container
+ SOURCES sharedmemory_qt.cpp
+ )
+endif()
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX ../../../share/qtcreator/qml/qmlpuppet/commands
+ SOURCES
+ changeauxiliarycommand.cpp changeauxiliarycommand.h
+ changebindingscommand.cpp changebindingscommand.h
+ changefileurlcommand.cpp changefileurlcommand.h
+ changeidscommand.cpp changeidscommand.h
+ changenodesourcecommand.cpp changenodesourcecommand.h
+ changestatecommand.cpp changestatecommand.h
+ changevaluescommand.cpp changevaluescommand.h
+ childrenchangedcommand.cpp childrenchangedcommand.h
+ clearscenecommand.cpp clearscenecommand.h
+ completecomponentcommand.cpp completecomponentcommand.h
+ componentcompletedcommand.cpp componentcompletedcommand.h
+ createinstancescommand.cpp createinstancescommand.h
+ createscenecommand.cpp createscenecommand.h
+ debugoutputcommand.cpp debugoutputcommand.h
+ endpuppetcommand.cpp endpuppetcommand.h
+ informationchangedcommand.cpp informationchangedcommand.h
+ pixmapchangedcommand.cpp pixmapchangedcommand.h
+ puppetalivecommand.cpp puppetalivecommand.h
+ removeinstancescommand.cpp removeinstancescommand.h
+ removepropertiescommand.cpp removepropertiescommand.h
+ removesharedmemorycommand.cpp removesharedmemorycommand.h
+ reparentinstancescommand.cpp reparentinstancescommand.h
+ statepreviewimagechangedcommand.cpp statepreviewimagechangedcommand.h
+ synchronizecommand.cpp synchronizecommand.h
+ tokencommand.cpp tokencommand.h
+ valueschangedcommand.cpp valueschangedcommand.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX ../../../share/qtcreator/qml/qmlpuppet/interfaces
+ SOURCES
+ nodeinstanceserverinterface.cpp
+ commondefines.h
+ nodeinstanceclientinterface.h
+ nodeinstanceglobal.h
+ nodeinstanceserverinterface.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX ../../../share/qtcreator/qml/qmlpuppet/types
+ SOURCES enumeration.cpp enumeration.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/componentcore
+ PUBLIC_INCLUDES components/componentcore
+ SOURCES
+ abstractaction.cpp abstractaction.h
+ abstractactiongroup.cpp abstractactiongroup.h
+ actioninterface.h
+ addimagesdialog.cpp addimagesdialog.h
+ addsignalhandlerdialog.cpp addsignalhandlerdialog.h addsignalhandlerdialog.ui
+ changestyleaction.cpp changestyleaction.h
+ componentcore.qrc
+ componentcore_constants.h
+ crumblebar.cpp crumblebar.h
+ designeractionmanager.cpp designeractionmanager.h
+ designeractionmanagerview.cpp designeractionmanagerview.h
+ findimplementation.cpp findimplementation.h
+ layoutingridlayout.cpp layoutingridlayout.h
+ modelnodecontextmenu.cpp modelnodecontextmenu.h
+ modelnodecontextmenu_helper.cpp modelnodecontextmenu_helper.h
+ modelnodeoperations.cpp modelnodeoperations.h
+ qmldesignericonprovider.cpp qmldesignericonprovider.h
+ selectioncontext.cpp selectioncontext.h
+ theme.cpp theme.h
+ zoomaction.cpp zoomaction.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/debugview
+ SOURCES
+ debugview.cpp debugview.h
+ debugviewwidget.cpp debugviewwidget.h debugviewwidget.ui
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/formeditor
+ SOURCES
+ abstractcustomtool.cpp abstractcustomtool.h
+ abstractformeditortool.cpp abstractformeditortool.h
+ anchorindicator.cpp anchorindicator.h
+ anchorindicatorgraphicsitem.cpp anchorindicatorgraphicsitem.h
+ backgroundaction.cpp backgroundaction.h
+ bindingindicator.cpp bindingindicator.h
+ bindingindicatorgraphicsitem.cpp bindingindicatorgraphicsitem.h
+ contentnoteditableindicator.cpp contentnoteditableindicator.h
+ controlelement.cpp controlelement.h
+ dragtool.cpp dragtool.h
+ formeditor.qrc
+ formeditorgraphicsview.cpp formeditorgraphicsview.h
+ formeditoritem.cpp formeditoritem.h
+ formeditorscene.cpp formeditorscene.h
+ formeditorsubwindow.h
+ formeditortoolbutton.cpp formeditortoolbutton.h
+ formeditorview.cpp formeditorview.h
+ formeditorwidget.cpp formeditorwidget.h
+ itemutilfunctions.cpp itemutilfunctions.h
+ layeritem.cpp layeritem.h
+ lineeditaction.cpp lineeditaction.h
+ movemanipulator.cpp movemanipulator.h
+ movetool.cpp movetool.h
+ numberseriesaction.cpp numberseriesaction.h
+ onedimensionalcluster.cpp onedimensionalcluster.h
+ resizecontroller.cpp resizecontroller.h
+ resizehandleitem.cpp resizehandleitem.h
+ resizeindicator.cpp resizeindicator.h
+ resizemanipulator.cpp resizemanipulator.h
+ resizetool.cpp resizetool.h
+ rubberbandselectionmanipulator.cpp rubberbandselectionmanipulator.h
+ scaleitem.cpp scaleitem.h
+ scalemanipulator.cpp scalemanipulator.h
+ selectionindicator.cpp selectionindicator.h
+ selectionrectangle.cpp selectionrectangle.h
+ selectiontool.cpp selectiontool.h
+ singleselectionmanipulator.cpp singleselectionmanipulator.h
+ snapper.cpp snapper.h
+ snappinglinecreator.cpp snappinglinecreator.h
+ toolbox.cpp toolbox.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/importmanager
+ SOURCES
+ importlabel.cpp importlabel.h
+ importmanager.qrc
+ importmanagercombobox.cpp importmanagercombobox.h
+ importmanagerview.cpp importmanagerview.h
+ importswidget.cpp importswidget.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/integration
+ SOURCES
+ componentaction.cpp componentaction.h
+ componentview.cpp componentview.h
+ designdocument.cpp designdocument.h
+ designdocumentview.cpp designdocumentview.h
+ stackedutilitypanelcontroller.cpp stackedutilitypanelcontroller.h
+ utilitypanelcontroller.cpp utilitypanelcontroller.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/itemlibrary
+ SOURCES
+ customfilesystemmodel.cpp customfilesystemmodel.h
+ itemlibrary.qrc
+ itemlibraryimageprovider.cpp itemlibraryimageprovider.h
+ itemlibraryitem.cpp itemlibraryitem.h
+ itemlibrarymodel.cpp itemlibrarymodel.h
+ itemlibraryresourceview.cpp itemlibraryresourceview.h
+ itemlibrarysection.cpp itemlibrarysection.h
+ itemlibrarysectionmodel.cpp itemlibrarysectionmodel.h
+ itemlibraryview.cpp itemlibraryview.h
+ itemlibrarywidget.cpp itemlibrarywidget.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/navigator
+ SOURCES
+ iconcheckboxitemdelegate.cpp iconcheckboxitemdelegate.h
+ nameitemdelegate.cpp nameitemdelegate.h
+ navigator.qrc
+ navigatormodelinterface.h
+ navigatortreemodel.cpp navigatortreemodel.h
+ navigatortreeview.cpp navigatortreeview.h
+ navigatorview.cpp navigatorview.h
+ navigatorwidget.cpp navigatorwidget.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/propertyeditor
+ SOURCES
+ designerpropertymap.cpp designerpropertymap.h
+ fileresourcesmodel.cpp fileresourcesmodel.h
+ gradientmodel.cpp gradientmodel.h
+ gradientpresetcustomlistmodel.cpp gradientpresetcustomlistmodel.h
+ gradientpresetdefaultlistmodel.cpp gradientpresetdefaultlistmodel.h
+ gradientpresetitem.cpp gradientpresetitem.h
+ gradientpresetlistmodel.cpp gradientpresetlistmodel.h
+ propertyeditorcontextobject.cpp propertyeditorcontextobject.h
+ propertyeditorqmlbackend.cpp propertyeditorqmlbackend.h
+ propertyeditortransaction.cpp propertyeditortransaction.h
+ propertyeditorvalue.cpp propertyeditorvalue.h
+ propertyeditorview.cpp propertyeditorview.h
+ propertyeditorwidget.cpp propertyeditorwidget.h
+ simplecolorpalette.cpp simplecolorpalette.h
+ simplecolorpalettemodel.cpp simplecolorpalettemodel.h
+ simplecolorpalettesingleton.cpp simplecolorpalettesingleton.h
+ qmlanchorbindingproxy.cpp qmlanchorbindingproxy.h
+ qmlmodelnodeproxy.cpp qmlmodelnodeproxy.h
+ quick2propertyeditorview.cpp quick2propertyeditorview.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components
+ SOURCES resources/resources.qrc
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/stateseditor
+ SOURCES
+ stateseditorimageprovider.cpp stateseditorimageprovider.h
+ stateseditormodel.cpp stateseditormodel.h
+ stateseditorview.cpp stateseditorview.h
+ stateseditorwidget.cpp stateseditorwidget.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/texteditor
+ SOURCES
+ texteditor.qrc
+ texteditorstatusbar.cpp texteditorstatusbar.h
+ texteditorview.cpp texteditorview.h
+ texteditorwidget.cpp texteditorwidget.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX designercore
+ SOURCES
+ exceptions/exception.cpp
+ exceptions/invalidargumentexception.cpp
+ exceptions/invalididexception.cpp
+ exceptions/invalidmetainfoexception.cpp
+ exceptions/invalidmodelnodeexception.cpp
+ exceptions/invalidmodelstateexception.cpp
+ exceptions/invalidpropertyexception.cpp
+ exceptions/invalidqmlsourceexception.cpp
+ exceptions/invalidreparentingexception.cpp
+ exceptions/invalidslideindexexception.cpp
+ exceptions/notimplementedexception.cpp
+ exceptions/removebasestateexception.cpp
+ exceptions/rewritingexception.cpp
+
+ filemanager/addarraymembervisitor.cpp filemanager/addarraymembervisitor.h
+ filemanager/addobjectvisitor.cpp filemanager/addobjectvisitor.h
+ filemanager/addpropertyvisitor.cpp filemanager/addpropertyvisitor.h
+ filemanager/astobjecttextextractor.cpp filemanager/astobjecttextextractor.h
+ filemanager/changeimportsvisitor.cpp filemanager/changeimportsvisitor.h
+ filemanager/changeobjecttypevisitor.cpp filemanager/changeobjecttypevisitor.h
+ filemanager/changepropertyvisitor.cpp filemanager/changepropertyvisitor.h
+ filemanager/firstdefinitionfinder.cpp filemanager/firstdefinitionfinder.h
+ filemanager/moveobjectbeforeobjectvisitor.cpp filemanager/moveobjectbeforeobjectvisitor.h
+ filemanager/moveobjectvisitor.cpp filemanager/moveobjectvisitor.h
+ filemanager/objectlengthcalculator.cpp filemanager/objectlengthcalculator.h
+ filemanager/qmlrefactoring.cpp filemanager/qmlrefactoring.h
+ filemanager/qmlrewriter.cpp filemanager/qmlrewriter.h
+ filemanager/removepropertyvisitor.cpp filemanager/removepropertyvisitor.h
+ filemanager/removeuiobjectmembervisitor.cpp filemanager/removeuiobjectmembervisitor.h
+
+ include/abstractproperty.h
+ include/abstractview.h
+ include/anchorline.h
+ include/basetexteditmodifier.h
+ include/bindingproperty.h
+ include/bytearraymodifier.h
+ include/componenttextmodifier.h
+ include/customnotifications.h
+ include/documentmessage.h
+ include/exception.h
+ include/forwardview.h
+ include/import.h
+ include/invalidargumentexception.h
+ include/invalididexception.h
+ include/invalidmetainfoexception.h
+ include/invalidmodelnodeexception.h
+ include/invalidmodelstateexception.h
+ include/invalidpropertyexception.h
+ include/invalidqmlsourceexception.h
+ include/invalidreparentingexception.h
+ include/invalidslideindexexception.h
+ include/itemlibraryinfo.h
+ include/iwidgetplugin.h
+ include/mathutils.h
+ include/metainfo.h
+ include/metainforeader.h
+ include/model.h
+ include/modelmerger.h
+ include/modelnode.h
+ include/modelnodepositionstorage.h
+ include/modificationgroupexception.h
+ include/modificationgrouptoken.h
+ include/nodeabstractproperty.h
+ include/nodeanchors.h
+ include/nodehints.h
+ include/nodeinstance.h
+ include/nodeinstanceview.h
+ include/nodelistproperty.h
+ include/nodemetainfo.h
+ include/nodeproperty.h
+ include/notimplementedexception.h
+ include/objectpropertybinding.h
+ include/plaintexteditmodifier.h
+ include/propertybinding.h
+ include/propertycontainer.h
+ include/propertynode.h
+ include/propertyparser.h
+ include/qmlanchors.h
+ include/qmlchangeset.h
+ include/qmldesignercorelib_global.h
+ include/qmlitemnode.h
+ include/qmlmodelnodefacade.h
+ include/qmlobjectnode.h
+ include/qmlstate.h
+ include/qmltimeline.h
+ include/qmltimelinekeyframegroup.h
+ include/removebasestateexception.h
+ include/rewriterview.h
+ include/rewritingexception.h
+ include/signalhandlerproperty.h
+ include/subcomponentmanager.h
+ include/textmodifier.h
+ include/variantproperty.h
+ include/viewmanager.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX designercore/instances
+ SOURCES
+ nodeinstance.cpp
+ nodeinstanceserverproxy.cpp nodeinstanceserverproxy.h
+ nodeinstanceview.cpp
+ puppetbuildprogressdialog.cpp puppetbuildprogressdialog.h puppetbuildprogressdialog.ui
+ puppetcreator.cpp puppetcreator.h
+ puppetdialog.cpp puppetdialog.h puppetdialog.ui
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX designercore
+ SOURCES
+ metainfo/itemlibraryinfo.cpp
+ metainfo/metainfo.cpp
+ metainfo/metainforeader.cpp
+ metainfo/nodehints.cpp
+ metainfo/nodemetainfo.cpp
+ metainfo/subcomponentmanager.cpp
+
+ model/abstractproperty.cpp
+ model/abstractview.cpp
+ model/anchorline.cpp
+ model/basetexteditmodifier.cpp
+ model/bindingproperty.cpp
+ model/componenttextmodifier.cpp
+ model/documentmessage.cpp
+ model/import.cpp
+ model/internalbindingproperty.cpp model/internalbindingproperty.h
+ model/internalnode.cpp model/internalnode_p.h
+ model/internalnodeabstractproperty.cpp model/internalnodeabstractproperty.h
+ model/internalnodelistproperty.cpp model/internalnodelistproperty.h
+ model/internalnodeproperty.cpp model/internalnodeproperty.h
+ model/internalproperty.cpp model/internalproperty.h
+ model/internalsignalhandlerproperty.cpp model/internalsignalhandlerproperty.h
+ model/internalvariantproperty.cpp model/internalvariantproperty.h
+ model/model.cpp model/model_p.h
+ model/modelmerger.cpp
+ model/modelnode.cpp
+ model/modelnodepositionrecalculator.cpp model/modelnodepositionrecalculator.h
+ model/modelnodepositionstorage.cpp
+ model/modeltotextmerger.cpp model/modeltotextmerger.h
+ model/nodeabstractproperty.cpp
+ model/nodelistproperty.cpp
+ model/nodeproperty.cpp
+ model/plaintexteditmodifier.cpp
+ model/propertycontainer.cpp
+ model/propertynode.cpp
+ model/propertyparser.cpp
+ model/qmlanchors.cpp
+ model/qmlchangeset.cpp
+ model/qmlitemnode.cpp
+ model/qmlmodelnodefacade.cpp
+ model/qmlobjectnode.cpp
+ model/qmlstate.cpp
+ model/qmltextgenerator.cpp model/qmltextgenerator.h
+ model/qmltimeline.cpp
+ model/qmltimelinekeyframegroup.cpp
+ model/rewriteaction.cpp model/rewriteaction.h
+ model/rewriteactioncompressor.cpp model/rewriteactioncompressor.h
+ model/rewriterview.cpp
+ model/signalhandlerproperty.cpp
+ model/textmodifier.cpp
+ model/texttomodelmerger.cpp model/texttomodelmerger.h
+ model/variantproperty.cpp
+ model/viewmanager.cpp
+
+ pluginmanager/widgetpluginmanager.cpp pluginmanager/widgetpluginmanager.h
+ pluginmanager/widgetpluginpath.cpp pluginmanager/widgetpluginpath.h
+ rewritertransaction.cpp rewritertransaction.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/colortool
+ SOURCES colortool.cpp colortool.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/connectioneditor
+ SOURCES
+ addnewbackenddialog.cpp addnewbackenddialog.h addnewbackenddialog.ui
+ backendmodel.cpp backendmodel.h
+ bindingmodel.cpp bindingmodel.h
+ connectioneditor.qrc
+ connectionmodel.cpp connectionmodel.h
+ connectionview.cpp connectionview.h
+ connectionviewwidget.cpp connectionviewwidget.h connectionviewwidget.ui
+ delegates.cpp delegates.h
+ dynamicpropertiesmodel.cpp dynamicpropertiesmodel.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components
+ SOURCES
+ pathtool/controlpoint.cpp pathtool/controlpoint.h
+ pathtool/cubicsegment.cpp pathtool/cubicsegment.h
+ pathtool/pathitem.cpp pathtool/pathitem.h
+ pathtool/pathselectionmanipulator.cpp pathtool/pathselectionmanipulator.h
+ pathtool/pathtool.cpp pathtool/pathtool.h
+ pathtool/pathtoolview.cpp pathtool/pathtoolview.h
+
+ sourcetool/sourcetool.cpp sourcetool/sourcetool.h
+
+ texttool/textedititem.cpp texttool/textedititem.h
+ texttool/textedititemwidget.cpp texttool/textedititemwidget.h
+ texttool/texttool.cpp texttool/texttool.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/timelineeditor
+ SOURCES
+ canvas.cpp canvas.h
+ canvasstyledialog.cpp canvasstyledialog.h
+ easingcurve.cpp easingcurve.h
+ easingcurvedialog.cpp easingcurvedialog.h
+ preseteditor.cpp preseteditor.h
+ setframevaluedialog.cpp setframevaluedialog.h setframevaluedialog.ui
+ splineeditor.cpp splineeditor.h
+ timeline.qrc
+ timelineabstracttool.cpp timelineabstracttool.h
+ timelineactions.cpp timelineactions.h
+ timelineanimationform.cpp timelineanimationform.h timelineanimationform.ui
+ timelineconstants.h
+ timelinecontext.cpp timelinecontext.h
+ timelinecontrols.cpp timelinecontrols.h
+ timelineform.cpp timelineform.h timelineform.ui
+ timelinegraphicslayout.cpp timelinegraphicslayout.h
+ timelinegraphicsscene.cpp timelinegraphicsscene.h
+ timelineicons.h
+ timelineitem.cpp timelineitem.h
+ timelinemovableabstractitem.cpp timelinemovableabstractitem.h
+ timelinemovetool.cpp timelinemovetool.h
+ timelineplaceholder.cpp timelineplaceholder.h
+ timelinepropertyitem.cpp timelinepropertyitem.h
+ timelinesectionitem.cpp timelinesectionitem.h
+ timelineselectiontool.cpp timelineselectiontool.h
+ timelinesettingsdialog.cpp
+ timelinesettingsdialog.h timelinesettingsdialog.ui
+ timelinesettingsmodel.cpp timelinesettingsmodel.h
+ timelinetoolbar.cpp timelinetoolbar.h
+ timelinetoolbutton.cpp timelinetoolbutton.h
+ timelinetooldelegate.cpp timelinetooldelegate.h
+ timelineutils.cpp timelineutils.h
+ timelineview.cpp timelineview.h
+ timelinewidget.cpp timelinewidget.h
+)
+
+extend_qtc_plugin(QmlDesigner
+ SOURCES_PREFIX components/curveeditor
+ SOURCES
+ animationcurve.cpp animationcurve.h
+ curveeditor.cpp curveeditor.h
+ curveeditormodel.cpp curveeditormodel.h
+ curveeditorstyle.h
+ keyframe.cpp keyframe.h
+ treeitem.cpp treeitem.h
+ detail/colorcontrol.cpp detail/colorcontrol.h
+ detail/curveeditorstyledialog.cpp detail/curveeditorstyledialog.h
+ detail/curveitem.cpp detail/curveitem.h
+ detail/curvesegment.cpp detail/curvesegment.h
+ detail/graphicsscene.cpp detail/graphicsscene.h
+ detail/graphicsview.cpp detail/graphicsview.h
+ detail/handleitem.cpp detail/handleitem.h
+ detail/keyframeitem.cpp detail/keyframeitem.h
+ detail/playhead.cpp detail/playhead.h
+ detail/selectableitem.cpp detail/selectableitem.h
+ detail/selector.cpp detail/selector.h
+ detail/shortcut.cpp detail/shortcut.h
+ detail/treeitemdelegate.cpp detail/treeitemdelegate.h
+ detail/treemodel.cpp detail/treemodel.h
+ detail/treeview.cpp detail/treeview.h
+ detail/utils.cpp detail/utils.h
+)
+
+# Do the file comparison at the end, due to all the extend_qtc_plugin calls
+if (WITH_DEBUG_CMAKE)
+ foreach(plugin QmlDesigner componentsplugin qtquickplugin)
+ unset(plugin_sources)
+ get_target_property(plugin_sources ${plugin} SOURCES)
+ list(APPEND QmlDesignerSources ${plugin_sources})
+ endforeach()
+ compare_sources_with_existing_disk_files(QmlDesigner "${QmlDesignerSources}")
+endif()
diff --git a/src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.cpp b/src/plugins/qmldesigner/components/colortool/colortool.cpp
index 32a5742f9f..32a5742f9f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.cpp
+++ b/src/plugins/qmldesigner/components/colortool/colortool.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.h b/src/plugins/qmldesigner/components/colortool/colortool.h
index 5e9e54c633..5e9e54c633 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.h
+++ b/src/plugins/qmldesigner/components/colortool/colortool.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.pri b/src/plugins/qmldesigner/components/colortool/colortool.pri
index 602af91da5..602af91da5 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/colortool/colortool.pri
+++ b/src/plugins/qmldesigner/components/colortool/colortool.pri
diff --git a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
index fa77acccb9..c2a17cd7b1 100644
--- a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
@@ -35,10 +35,10 @@ namespace QmlDesigner {
static QString styleConfigFileName(const QString &qmlFileName)
{
- ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(Utils::FileName::fromString(qmlFileName));
+ ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(Utils::FilePath::fromString(qmlFileName));
if (currentProject)
- foreach (const Utils::FileName &fileName, currentProject->files(ProjectExplorer::Project::SourceFiles))
+ foreach (const Utils::FilePath &fileName, currentProject->files(ProjectExplorer::Project::SourceFiles))
if (fileName.endsWith("qtquickcontrols2.conf"))
return fileName.toString();
@@ -90,14 +90,14 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
});
connect(comboBox,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ QOverload<const QString &>::of(&QComboBox::activated),
this,
[this](const QString &style) {
if (style.isEmpty())
return;
- const Utils::FileName configFileName = Utils::FileName::fromString(styleConfigFileName(qmlFileName));
+ const Utils::FilePath configFileName = Utils::FilePath::fromString(styleConfigFileName(qmlFileName));
if (configFileName.exists()) {
QSettings infiFile(configFileName.toString(), QSettings::IniFormat);
@@ -125,7 +125,7 @@ void ChangeStyleAction::currentContextChanged(const SelectionContext &selectionC
const QString confFileName = styleConfigFileName(fileName);
- if (Utils::FileName::fromString(confFileName).exists()) {
+ if (Utils::FilePath::fromString(confFileName).exists()) {
QSettings infiFile(confFileName, QSettings::IniFormat);
m_action->handleModelUpdate(infiFile.value("Controls/Style", "Default").toString());
} else {
diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
index 028d3a21b4..0535a8f52e 100644
--- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
+++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
@@ -165,6 +165,7 @@ const int priorityGenericToolBar = 50;
const int priorityLast = 60;
const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files");
+const char addFontsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Font Files");
} //ComponentCoreConstants
diff --git a/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp b/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp
index 112923c5f7..733b29ef5a 100644
--- a/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp
@@ -78,7 +78,7 @@ CrumbleBar::~CrumbleBar()
delete m_crumblePath;
}
-void CrumbleBar::pushFile(const Utils::FileName &fileName)
+void CrumbleBar::pushFile(const Utils::FilePath &fileName)
{
if (!m_isInternalCalled) {
crumblePath()->clear();
diff --git a/src/plugins/qmldesigner/components/componentcore/crumblebar.h b/src/plugins/qmldesigner/components/componentcore/crumblebar.h
index d29d8f594e..cd19e1faa2 100644
--- a/src/plugins/qmldesigner/components/componentcore/crumblebar.h
+++ b/src/plugins/qmldesigner/components/componentcore/crumblebar.h
@@ -39,7 +39,7 @@ public:
explicit CrumbleBar(QObject *parent = nullptr);
~CrumbleBar() override;
- void pushFile(const Utils::FileName &fileName);
+ void pushFile(const Utils::FilePath &fileName);
void pushInFileComponent(const ModelNode &modelNode);
void nextFileIsCalledInternally();
@@ -58,7 +58,7 @@ private:
class CrumbleBarInfo {
public:
- Utils::FileName fileName;
+ Utils::FilePath fileName;
QString displayName;
ModelNode modelNode;
};
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index 6edbacec36..37e1fdfd53 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -1026,6 +1026,13 @@ void DesignerActionManager::createDefaultAddResourceHandler()
registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addImagesDisplayString,
"*.svg",
ModelNodeOperations::addImageToProject));
+
+ registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addFontsDisplayString,
+ "*.ttf",
+ ModelNodeOperations::addFontToProject));
+ registerAddResourceHandler(AddResourceHandler(ComponentCoreConstants::addFontsDisplayString,
+ "*.otf",
+ ModelNodeOperations::addFontToProject));
}
void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
diff --git a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
index 5ec3ea557b..ba520a1ca3 100644
--- a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
@@ -185,17 +185,16 @@ void LayoutInGridLayout::doIt()
if (qmlItemNode.hasInstanceParentItem()) {
ModelNode layoutNode;
- {
- RewriterTransaction transaction(m_selectionContext.view(), QByteArrayLiteral("LayoutInGridLayout1"));
+
+ m_selectionContext.view()->executeInTransaction("LayoutInGridLayout1",[this, &layoutNode, layoutType](){
QTC_ASSERT(m_selectionContext.view()->model()->hasNodeMetaInfo(layoutType), return);
NodeMetaInfo metaInfo = m_selectionContext.view()->model()->metaInfo(layoutType);
layoutNode = m_selectionContext.view()->createModelNode(layoutType, metaInfo.majorVersion(), metaInfo.minorVersion());
reparentTo(layoutNode, m_parentNode);
- }
+ });
- {
- RewriterTransaction transaction(m_selectionContext.view(), QByteArrayLiteral("LayoutInGridLayout2"));
+ m_selectionContext.view()->executeInTransaction("LayoutInGridLayout2", [this, layoutNode](){
fillEmptyCells();
@@ -208,7 +207,7 @@ void LayoutInGridLayout::doIt()
reparentToNodeAndRemovePositionForModelNodes(layoutNode, sortedSelectedNodes);
setSizeAsPreferredSize(sortedSelectedNodes);
setSpanning(layoutNode);
- }
+ });
}
}
}
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index f5b701e44d..9f880c453b 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -240,9 +240,7 @@ void changeOrder(const SelectionContext &selectionState, OderAction orderAction)
if (!modelNode.parentProperty().isNodeListProperty())
return;
- try {
- RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|raise"));
-
+ selectionState.view()->executeInTransaction("DesignerActionManager|raise",[orderAction, selectionState, modelNode](){
ModelNode modelNode = selectionState.currentSingleSelectedNode();
NodeListProperty parentProperty = modelNode.parentProperty().toNodeListProperty();
const int index = parentProperty.indexOf(modelNode);
@@ -255,11 +253,7 @@ void changeOrder(const SelectionContext &selectionState, OderAction orderAction)
if (index > 0)
parentProperty.slide(index, index - 1);
}
-
- transaction.commit();
- } catch (const RewritingException &e) { //better save then sorry
- e.showException();
- }
+ });
}
void raise(const SelectionContext &selectionState)
@@ -328,16 +322,13 @@ void resetSize(const SelectionContext &selectionState)
if (!selectionState.view())
return;
- try {
- RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetSize"));
+ selectionState.view()->executeInTransaction("DesignerActionManager|resetSize",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
itemNode.removeProperty("width");
itemNode.removeProperty("height");
}
- } catch (const RewritingException &e) { //better save then sorry
- e.showException();
- }
+ });
}
void resetPosition(const SelectionContext &selectionState)
@@ -345,17 +336,13 @@ void resetPosition(const SelectionContext &selectionState)
if (!selectionState.view())
return;
- try {
- RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetPosition"));
+ selectionState.view()->executeInTransaction("DesignerActionManager|resetPosition",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
itemNode.removeProperty("x");
itemNode.removeProperty("y");
}
- transaction.commit();
- } catch (const RewritingException &e) { //better save then sorry
- e.showException();
- }
+ });
}
void goIntoComponentOperation(const SelectionContext &selectionState)
@@ -372,11 +359,12 @@ void resetZ(const SelectionContext &selectionState)
if (!selectionState.view())
return;
- RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetZ"));
- foreach (ModelNode node, selectionState.selectedModelNodes()) {
- QmlItemNode itemNode(node);
- itemNode.removeProperty("z");
- }
+ selectionState.view()->executeInTransaction("DesignerActionManager|resetZ",[selectionState](){
+ foreach (ModelNode node, selectionState.selectedModelNodes()) {
+ QmlItemNode itemNode(node);
+ itemNode.removeProperty("z");
+ }
+ });
}
static inline void backupPropertyAndRemove(const ModelNode &node, const PropertyName &propertyName)
@@ -404,9 +392,7 @@ void anchorsFill(const SelectionContext &selectionState)
if (!selectionState.view())
return;
- try {
- RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|anchorsFill"));
-
+ selectionState.view()->executeInTransaction("DesignerActionManager|anchorsFill",[selectionState](){
ModelNode modelNode = selectionState.currentSingleSelectedNode();
QmlItemNode node = modelNode;
@@ -417,11 +403,7 @@ void anchorsFill(const SelectionContext &selectionState)
backupPropertyAndRemove(modelNode, "width");
backupPropertyAndRemove(modelNode, "height");
}
-
- transaction.commit();
- } catch (const RewritingException &e) { //better save then sorry
- e.showException();
- }
+ });
}
void anchorsReset(const SelectionContext &selectionState)
@@ -429,19 +411,19 @@ void anchorsReset(const SelectionContext &selectionState)
if (!selectionState.view())
return;
- RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|anchorsReset"));
-
- ModelNode modelNode = selectionState.currentSingleSelectedNode();
+ selectionState.view()->executeInTransaction("DesignerActionManager|anchorsReset",[selectionState](){
+ ModelNode modelNode = selectionState.currentSingleSelectedNode();
- QmlItemNode node = modelNode;
- if (node.isValid()) {
- node.anchors().removeAnchors();
- node.anchors().removeMargins();
- restoreProperty(node, "x");
- restoreProperty(node, "y");
- restoreProperty(node, "width");
- restoreProperty(node, "height");
- }
+ QmlItemNode node = modelNode;
+ if (node.isValid()) {
+ node.anchors().removeAnchors();
+ node.anchors().removeMargins();
+ restoreProperty(node, "x");
+ restoreProperty(node, "y");
+ restoreProperty(node, "width");
+ restoreProperty(node, "height");
+ }
+ });
}
using LessThan = std::function<bool (const ModelNode &, const ModelNode&)>;
@@ -481,7 +463,7 @@ bool compareByGrid(const ModelNode &node1, const ModelNode &node2)
static void layoutHelperFunction(const SelectionContext &selectionContext,
const TypeName &layoutType,
- LessThan lessThan)
+ const LessThan &lessThan)
{
if (!selectionContext.view()
|| !selectionContext.hasSingleSelectedModelNode()
@@ -492,10 +474,8 @@ static void layoutHelperFunction(const SelectionContext &selectionContext,
const QmlItemNode qmlItemNode = QmlItemNode(selectionContext.firstSelectedModelNode());
if (qmlItemNode.hasInstanceParentItem()) {
-
ModelNode layoutNode;
- {
- RewriterTransaction transaction(selectionContext.view(), QByteArrayLiteral("DesignerActionManager|layoutHelperFunction1"));
+ selectionContext.view()->executeInTransaction("DesignerActionManager|layoutHelperFunction1",[=, &layoutNode](){
QmlItemNode parentNode = qmlItemNode.instanceParentItem();
@@ -504,10 +484,9 @@ static void layoutHelperFunction(const SelectionContext &selectionContext,
layoutNode = selectionContext.view()->createModelNode(layoutType, metaInfo.majorVersion(), metaInfo.minorVersion());
reparentTo(layoutNode, parentNode);
- }
+ });
- {
- RewriterTransaction transaction(selectionContext.view(), QByteArrayLiteral("DesignerActionManager|layoutHelperFunction2"));
+ selectionContext.view()->executeInTransaction("DesignerActionManager|layoutHelperFunction2",[=](){
QList<ModelNode> sortedSelectedNodes = selectionContext.selectedModelNodes();
Utils::sort(sortedSelectedNodes, lessThan);
@@ -516,7 +495,7 @@ static void layoutHelperFunction(const SelectionContext &selectionContext,
LayoutInGridLayout::reparentToNodeAndRemovePositionForModelNodes(layoutNode, sortedSelectedNodes);
if (layoutType.contains("Layout"))
LayoutInGridLayout::setSizeAsPreferredSize(sortedSelectedNodes);
- }
+ });
}
}
}
@@ -662,21 +641,14 @@ void addSignalHandlerOrGotoImplementation(const SelectionContext &selectionState
if (!qmlObjectNode.isRootModelNode()) {
isModelNodeRoot = false;
- try {
- RewriterTransaction transaction =
- qmlObjectNode.view()->beginRewriterTransaction(QByteArrayLiteral("NavigatorTreeModel:exportItem"));
-
- QmlObjectNode qmlObjectNode(modelNode);
+ qmlObjectNode.view()->executeInTransaction("NavigatorTreeModel:exportItem", [&qmlObjectNode](){
qmlObjectNode.ensureAliasExport();
- transaction.commit();
- } catch (RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
- }
+ });
}
QString itemId = modelNode.id();
- const Utils::FileName currentDesignDocument = QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->fileName();
+ const Utils::FilePath currentDesignDocument = QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->fileName();
const QString fileName = currentDesignDocument.toString();
const QString typeName = currentDesignDocument.toFileInfo().baseName();
@@ -708,14 +680,10 @@ void addSignalHandlerOrGotoImplementation(const SelectionContext &selectionState
if (dialog->signal().isEmpty())
return;
- try {
- RewriterTransaction transaction =
- qmlObjectNode.view()->beginRewriterTransaction(QByteArrayLiteral("NavigatorTreeModel:exportItem"));
+ qmlObjectNode.view()->executeInTransaction("NavigatorTreeModel:exportItem", [=](){
addSignal(typeName, itemId, dialog->signal(), isModelNodeRoot);
- } catch (RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
- }
+ });
addSignal(typeName, itemId, dialog->signal(), isModelNodeRoot);
@@ -751,9 +719,7 @@ void removeLayout(const SelectionContext &selectionContext)
if (!parent.isValid())
return;
- {
- RewriterTransaction transaction(selectionContext.view(), QByteArrayLiteral("DesignerActionManager|removeLayout"));
-
+ selectionContext.view()->executeInTransaction("DesignerActionManager|removeLayout", [selectionContext, &layoutItem, parent](){
foreach (const ModelNode &modelNode, selectionContext.currentSingleSelectedNode().directSubModelNodes()) {
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
@@ -772,7 +738,7 @@ void removeLayout(const SelectionContext &selectionContext)
parent.modelNode().defaultNodeListProperty().reparentHere(modelNode);
}
layoutItem.destroy();
- }
+ });
}
void removePositioner(const SelectionContext &selectionContext)
@@ -826,9 +792,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext)
}
}
- try {
- RewriterTransaction transaction =
- view->beginRewriterTransaction(QByteArrayLiteral("DesignerActionManager:addItemToStackedContainer"));
+ view->executeInTransaction("DesignerActionManager:addItemToStackedContainer", [=](){
NodeMetaInfo itemMetaInfo = view->model()->metaInfo("QtQuick.Item", -1, -1);
QTC_ASSERT(itemMetaInfo.isValid(), return);
@@ -853,11 +817,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext)
}
}
-
- transaction.commit();
- } catch (RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
- }
+ });
}
PropertyName getIndexPropertyName(const ModelNode &modelNode)
@@ -969,9 +929,8 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext)
const PropertyName indexPropertyName = getIndexPropertyName(container);
QTC_ASSERT(container.metaInfo().hasProperty(indexPropertyName), return);
- try {
- RewriterTransaction transaction =
- view->beginRewriterTransaction(QByteArrayLiteral("DesignerActionManager:addItemToStackedContainer"));
+ view->executeInTransaction("DesignerActionManager:addItemToStackedContainer",
+ [view, container, containerItemNode, tabBarMetaInfo, tabButtonMetaInfo, indexPropertyName](){
ModelNode tabBarNode =
view->createModelNode("QtQuick.Controls.TabBar",
@@ -1003,13 +962,42 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext)
container.removeProperty(indexPropertyName);
const QString expression = id + "." + QString::fromLatin1(indexPropertyName);
container.bindingProperty(indexPropertyName).setExpression(expression);
+ });
+
+}
+
+bool addFontToProject(const QStringList &fileNames, const QString &defaultDirectory)
+{
+ QString directory = AddImagesDialog::getDirectory(fileNames, defaultDirectory);
+
+ if (directory.isEmpty())
+ return true;
+
+ bool allSuccessful = true;
+ for (const QString &fileName : fileNames) {
+ const QString targetFile = directory + "/" + QFileInfo(fileName).fileName();
+ const bool success = QFile::copy(fileName, targetFile);
+
+ auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
+
+ QTC_ASSERT(document, return false);
- transaction.commit();
- } catch (RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
+ if (success) {
+ ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(document->fileName());
+ if (node) {
+ ProjectExplorer::FolderNode *containingFolder = node->parentFolderNode();
+ if (containingFolder)
+ containingFolder->addFiles(QStringList(targetFile));
+ }
+ } else {
+ allSuccessful = false;
+ }
}
+
+ return allSuccessful;
}
+
bool addImageToProject(const QStringList &fileNames, const QString &defaultDirectory)
{
QString directory = AddImagesDialog::getDirectory(fileNames, defaultDirectory);
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
index e3396a303e..52dfaf6f1d 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
@@ -73,6 +73,7 @@ void increaseIndexOfStackedContainer(const SelectionContext &selectionContext);
void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext);
void addTabBarToStackedContainer(const SelectionContext &selectionContext);
bool addImageToProject(const QStringList &fileNames, const QString &directory);
+bool addFontToProject(const QStringList &fileNames, const QString &directory);
} // namespace ModelNodeOperationso
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp b/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
index e82b2a22dd..434f73c0f3 100644
--- a/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
@@ -29,7 +29,6 @@
namespace QmlDesigner {
-
SelectionContext::SelectionContext() = default;
SelectionContext::SelectionContext(AbstractView *view) :
diff --git a/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp b/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp
index 9a1529414a..40ad483785 100644
--- a/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/zoomaction.cpp
@@ -30,7 +30,6 @@
namespace QmlDesigner {
-
ZoomAction::ZoomAction(QObject *parent)
: QWidgetAction(parent),
m_zoomLevel(1.0),
@@ -105,7 +104,7 @@ QWidget *ZoomAction::createWidget(QWidget *parent)
comboBox->setCurrentIndex(m_currentComboBoxIndex);
blockSignals(false);
});
- connect(comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
[this, comboBox](int index) {
m_currentComboBoxIndex = index;
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.cpp b/src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.cpp
index 9de928ae90..9de928ae90 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.h b/src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.h
index 4cfa46d66e..4cfa46d66e 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.ui b/src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.ui
index 1da43f7526..1da43f7526 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/addnewbackenddialog.ui
+++ b/src/plugins/qmldesigner/components/connectioneditor/addnewbackenddialog.ui
diff --git a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
new file mode 100644
index 0000000000..4a004ca575
--- /dev/null
+++ b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review 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/algorithm.h>
+
+#include "backendmodel.h"
+
+#include "bindingproperty.h"
+#include "connectionview.h"
+#include "exception.h"
+#include "nodemetainfo.h"
+#include "nodeproperty.h"
+#include "rewriterview.h"
+#include "rewritertransaction.h"
+
+#include "addnewbackenddialog.h"
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+BackendModel::BackendModel(ConnectionView *parent) :
+ QStandardItemModel(parent)
+ ,m_connectionView(parent)
+{
+ connect(this, &QStandardItemModel::dataChanged, this, &BackendModel::handleDataChanged);
+}
+
+ConnectionView *QmlDesigner::Internal::BackendModel::connectionView() const
+{
+ return m_connectionView;
+}
+
+void BackendModel::resetModel()
+{
+ if (!m_connectionView->model())
+ return;
+
+ RewriterView *rewriterView = m_connectionView->model()->rewriterView();
+
+ m_lock = true;
+
+ beginResetModel();
+ clear();
+
+ setHorizontalHeaderLabels(QStringList({ tr("Type"), tr("Name"), tr("Singleton"), tr("Local") }));
+
+ ModelNode rootNode = connectionView()->rootModelNode();
+
+ static const PropertyTypeList simpleTypes = {"int", "real", "color", "string"};
+
+ if (rewriterView)
+ for (const CppTypeData &cppTypeData : rewriterView->getCppTypes())
+ if (cppTypeData.isSingleton) {
+ NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(cppTypeData.typeName.toUtf8());
+ if (metaInfo.isValid() && !metaInfo.isSubclassOf("QtQuick.Item")) {
+ auto type = new QStandardItem(cppTypeData.typeName);
+ type->setData(cppTypeData.typeName, Qt::UserRole + 1);
+ type->setData(true, Qt::UserRole + 2);
+ type->setEditable(false);
+
+ auto name = new QStandardItem(cppTypeData.typeName);
+ name->setEditable(false);
+
+ QStandardItem *singletonItem = new QStandardItem("");
+ singletonItem->setCheckState(Qt::Checked);
+
+ singletonItem->setCheckable(true);
+ singletonItem->setEnabled(false);
+
+ QStandardItem *inlineItem = new QStandardItem("");
+
+ inlineItem->setCheckState(Qt::Unchecked);
+
+ inlineItem->setCheckable(true);
+ inlineItem->setEnabled(false);
+
+ appendRow({ type, name, singletonItem, inlineItem });
+ }
+ }
+
+ if (rootNode.isValid())
+ foreach (const AbstractProperty &property ,rootNode.properties())
+ if (property.isDynamic() && !simpleTypes.contains(property.dynamicTypeName())) {
+
+ NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(property.dynamicTypeName());
+ if (metaInfo.isValid() && !metaInfo.isSubclassOf("QtQuick.Item")) {
+ QStandardItem *type = new QStandardItem(QString::fromUtf8(property.dynamicTypeName()));
+ type->setEditable(false);
+
+ type->setData(QString::fromUtf8(property.name()), Qt::UserRole + 1);
+ type->setData(false, Qt::UserRole + 2);
+ QStandardItem *name = new QStandardItem(QString::fromUtf8(property.name()));
+
+ QStandardItem *singletonItem = new QStandardItem("");
+ singletonItem->setCheckState(Qt::Unchecked);
+
+ singletonItem->setCheckable(true);
+ singletonItem->setEnabled(false);
+
+ QStandardItem *inlineItem = new QStandardItem("");
+
+ inlineItem->setCheckState(property.isNodeProperty() ? Qt::Checked : Qt::Unchecked);
+
+ inlineItem->setCheckable(true);
+ inlineItem->setEnabled(false);
+
+ appendRow({ type, name, singletonItem, inlineItem });
+ }
+ }
+
+ m_lock = false;
+
+ endResetModel();
+}
+
+QStringList BackendModel::possibleCppTypes() const
+{
+ RewriterView *rewriterView = m_connectionView->model()->rewriterView();
+
+ QStringList list;
+
+ if (rewriterView)
+ foreach (const CppTypeData &cppTypeData, rewriterView->getCppTypes())
+ list.append(cppTypeData.typeName);
+
+ return list;
+}
+
+CppTypeData BackendModel::cppTypeDataForType(const QString &typeName) const
+{
+ RewriterView *rewriterView = m_connectionView->model()->rewriterView();
+
+ if (!rewriterView)
+ return CppTypeData();
+
+ return Utils::findOr(rewriterView->getCppTypes(), CppTypeData(), [&typeName](const CppTypeData &data) {
+ return typeName == data.typeName;
+ });
+}
+
+void BackendModel::deletePropertyByRow(int rowNumber)
+{
+ Model *model = m_connectionView->model();
+ if (!model)
+ return;
+
+ /* singleton case remove the import */
+ if (data(index(rowNumber, 0), Qt::UserRole + 1).toBool()) {
+ const QString typeName = data(index(rowNumber, 0), Qt::UserRole + 1).toString();
+ CppTypeData cppTypeData = cppTypeDataForType(typeName);
+
+ if (cppTypeData.isSingleton) {
+
+ Import import = Import::createLibraryImport(cppTypeData.importUrl, cppTypeData.versionString);
+
+ try {
+ if (model->hasImport(import))
+ model->changeImports({}, {import});
+ } catch (const Exception &e) {
+ e.showException();
+ }
+ }
+ } else {
+ const QString propertyName = data(index(rowNumber, 0), Qt::UserRole + 1).toString();
+
+ ModelNode modelNode = connectionView()->rootModelNode();
+
+ try {
+ modelNode.removeProperty(propertyName.toUtf8());
+ } catch (const Exception &e) {
+ e.showException();
+ }
+ }
+
+ resetModel();
+}
+
+void BackendModel::addNewBackend()
+{
+ Model *model = m_connectionView->model();
+ if (!model)
+ return;
+
+ AddNewBackendDialog dialog(Core::ICore::mainWindow());
+
+ RewriterView *rewriterView = model->rewriterView();
+
+ QStringList availableTypes;
+
+ if (rewriterView)
+ dialog.setupPossibleTypes(Utils::filtered(rewriterView->getCppTypes(), [model](const CppTypeData &cppTypeData) {
+ return !cppTypeData.isSingleton || !model->metaInfo(cppTypeData.typeName.toUtf8()).isValid();
+ /* Only show singletons if the import is missing */
+ }));
+
+ dialog.exec();
+
+ if (dialog.applied()) {
+ QStringList importSplit = dialog.importString().split(" ");
+ if (importSplit.count() != 2) {
+ qWarning() << Q_FUNC_INFO << "invalid import" << importSplit;
+ QTC_ASSERT(false, return);
+ }
+
+ QString typeName = dialog.type();
+
+ Import import = Import::createLibraryImport(importSplit.constFirst(), importSplit.constLast());
+
+ /* We cannot add an import and add a node from that import in a single transaction.
+ * We need the import to have the meta info available.
+ */
+
+ if (!model->hasImport(import))
+ model->changeImports({import}, {});
+
+ QString propertyName = m_connectionView->generateNewId(typeName);
+
+ NodeMetaInfo metaInfo = model->metaInfo(typeName.toUtf8());
+
+ QTC_ASSERT(metaInfo.isValid(), return);
+
+ /* Add a property for non singleton types. For singletons just adding the import is enough. */
+ if (!dialog.isSingleton()) {
+ m_connectionView->executeInTransaction("BackendModel::addNewBackend", [=, &dialog](){
+ int minorVersion = metaInfo.minorVersion();
+ int majorVersion = metaInfo.majorVersion();
+
+ if (dialog.localDefinition()) {
+ ModelNode newNode = m_connectionView->createModelNode(metaInfo.typeName(), majorVersion, minorVersion);
+
+ m_connectionView->rootModelNode().nodeProperty(propertyName.toUtf8()).setDynamicTypeNameAndsetModelNode(
+ typeName.toUtf8(), newNode);
+ } else {
+ m_connectionView->rootModelNode().bindingProperty(
+ propertyName.toUtf8()).setDynamicTypeNameAndExpression(typeName.toUtf8(), "null");
+ }
+ });
+ }
+ }
+ resetModel();
+}
+
+void BackendModel::updatePropertyName(int rowNumber)
+{
+ const PropertyName newName = data(index(rowNumber, 1)).toString().toUtf8();
+ const PropertyName oldName = data(index(rowNumber, 0), Qt::UserRole + 1).toString().toUtf8();
+
+ m_connectionView->executeInTransaction("BackendModel::updatePropertyName", [this, newName, oldName](){
+
+ ModelNode rootModelNode = m_connectionView->rootModelNode();
+ if (rootModelNode.property(oldName).isNodeProperty()) {
+
+ const TypeName typeName = rootModelNode.nodeProperty(oldName).dynamicTypeName();
+ const ModelNode targetModelNode = rootModelNode.nodeProperty(oldName).modelNode();
+ const TypeName fullTypeName = targetModelNode.type();
+ const int majorVersion = targetModelNode.majorVersion();
+ const int minorVersion = targetModelNode.minorVersion();
+
+ rootModelNode.removeProperty(oldName);
+ ModelNode newNode = m_connectionView->createModelNode(fullTypeName, majorVersion, minorVersion);
+ m_connectionView->rootModelNode().nodeProperty(newName).setDynamicTypeNameAndsetModelNode(typeName, newNode);
+
+ } else if (rootModelNode.property(oldName).isBindingProperty()) {
+ const QString expression = rootModelNode.bindingProperty(oldName).expression();
+ const TypeName typeName = rootModelNode.bindingProperty(oldName).dynamicTypeName();
+
+ rootModelNode.removeProperty(oldName);
+ rootModelNode.bindingProperty(newName).setDynamicTypeNameAndExpression(typeName, expression);
+ } else {
+ qWarning() << Q_FUNC_INFO << oldName << newName << "failed...";
+ QTC_ASSERT(false, return);
+ }
+ });
+}
+
+void BackendModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+ if (m_lock)
+ return;
+
+ if (topLeft != bottomRight) {
+ qWarning() << "BackendModel::handleDataChanged multi edit?";
+ return;
+ }
+
+ m_lock = true;
+
+ int currentColumn = topLeft.column();
+ int currentRow = topLeft.row();
+
+ switch (currentColumn) {
+ case 0: {
+ //updating user data
+ } break;
+ case 1: {
+ updatePropertyName(currentRow);
+ } break;
+
+ default: qWarning() << "BindingModel::handleDataChanged column" << currentColumn;
+ }
+
+ m_lock = false;
+}
+
+} // namespace Internal
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/backendmodel.h b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.h
index 8abbbe77fa..8abbbe77fa 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/backendmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.h
diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
new file mode 100644
index 0000000000..2cff12b044
--- /dev/null
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "bindingmodel.h"
+
+#include "connectionview.h"
+
+#include <nodemetainfo.h>
+#include <nodeproperty.h>
+#include <bindingproperty.h>
+#include <variantproperty.h>
+#include <rewritingexception.h>
+#include <rewritertransaction.h>
+
+#include <QMessageBox>
+#include <QTimer>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+BindingModel::BindingModel(ConnectionView *parent)
+ : QStandardItemModel(parent)
+ , m_connectionView(parent)
+{
+ connect(this, &QStandardItemModel::dataChanged, this, &BindingModel::handleDataChanged);
+}
+
+void BindingModel::resetModel()
+{
+ beginResetModel();
+ clear();
+ setHorizontalHeaderLabels(QStringList({ tr("Item"), tr("Property"), tr("Source Item"),
+ tr("Source Property") }));
+
+ foreach (const ModelNode modelNode, m_selectedModelNodes)
+ addModelNode(modelNode);
+
+ endResetModel();
+}
+
+void BindingModel::bindingChanged(const BindingProperty &bindingProperty)
+{
+ m_handleDataChanged = false;
+
+ QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
+ if (!selectedNodes.contains(bindingProperty.parentModelNode()))
+ return;
+ if (!m_lock) {
+ int rowNumber = findRowForBinding(bindingProperty);
+
+ if (rowNumber == -1) {
+ addBindingProperty(bindingProperty);
+ } else {
+ updateBindingProperty(rowNumber);
+ }
+ }
+
+ m_handleDataChanged = true;
+}
+
+void BindingModel::bindingRemoved(const BindingProperty &bindingProperty)
+{
+ m_handleDataChanged = false;
+
+ QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
+ if (!selectedNodes.contains(bindingProperty.parentModelNode()))
+ return;
+ if (!m_lock) {
+ int rowNumber = findRowForBinding(bindingProperty);
+ removeRow(rowNumber);
+ }
+
+ m_handleDataChanged = true;
+}
+
+void BindingModel::selectionChanged(const QList<ModelNode> &selectedNodes)
+{
+ m_handleDataChanged = false;
+ m_selectedModelNodes = selectedNodes;
+ resetModel();
+ m_handleDataChanged = true;
+}
+
+ConnectionView *BindingModel::connectionView() const
+{
+ return m_connectionView;
+}
+
+BindingProperty BindingModel::bindingPropertyForRow(int rowNumber) const
+{
+
+ const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
+ const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
+
+ ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
+
+ if (modelNode.isValid())
+ return modelNode.bindingProperty(targetPropertyName.toLatin1());
+
+ return BindingProperty();
+}
+
+QStringList BindingModel::possibleTargetProperties(const BindingProperty &bindingProperty) const
+{
+ const ModelNode modelNode = bindingProperty.parentModelNode();
+
+ if (!modelNode.isValid()) {
+ qWarning() << " BindingModel::possibleTargetPropertiesForRow invalid model node";
+ return QStringList();
+ }
+
+ NodeMetaInfo metaInfo = modelNode.metaInfo();
+
+ if (metaInfo.isValid()) {
+ QStringList possibleProperties;
+ foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
+ if (metaInfo.propertyIsWritable(propertyName))
+ possibleProperties << QString::fromUtf8(propertyName);
+ }
+
+ return possibleProperties;
+ }
+
+ return QStringList();
+}
+
+QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindingProperty) const
+{
+ const QString expression = bindingProperty.expression();
+ const QStringList stringlist = expression.split(QLatin1String("."));
+
+ TypeName typeName;
+
+ if (bindingProperty.parentModelNode().metaInfo().isValid()) {
+ typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name());
+ } else {
+ qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
+ }
+
+ const QString &id = stringlist.constFirst();
+
+ ModelNode modelNode = getNodeByIdOrParent(id, bindingProperty.parentModelNode());
+
+ if (!modelNode.isValid()) {
+ qWarning() << " BindingModel::possibleSourcePropertiesForRow invalid model node";
+ return QStringList();
+ }
+
+ NodeMetaInfo metaInfo = modelNode.metaInfo();
+
+ QStringList possibleProperties;
+
+ foreach (VariantProperty variantProperty, modelNode.variantProperties()) {
+ if (variantProperty.isDynamic())
+ possibleProperties << QString::fromUtf8(variantProperty.name());
+ }
+
+ foreach (BindingProperty bindingProperty, modelNode.bindingProperties()) {
+ if (bindingProperty.isDynamic())
+ possibleProperties << QString::fromUtf8((bindingProperty.name()));
+ }
+
+ if (metaInfo.isValid()) {
+ foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
+ if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
+ possibleProperties << QString::fromUtf8(propertyName);
+ }
+ } else {
+ qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node";
+ }
+
+ return possibleProperties;
+}
+
+void BindingModel::deleteBindindByRow(int rowNumber)
+{
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+
+ if (bindingProperty.isValid()) {
+ bindingProperty.parentModelNode().removeProperty(bindingProperty.name());
+ }
+
+ resetModel();
+}
+
+static PropertyName unusedProperty(const ModelNode &modelNode)
+{
+ PropertyName propertyName = "none";
+ if (modelNode.metaInfo().isValid()) {
+ foreach (const PropertyName &propertyName, modelNode.metaInfo().propertyNames()) {
+ if (modelNode.metaInfo().propertyIsWritable(propertyName) && !modelNode.hasProperty(propertyName))
+ return propertyName;
+ }
+ }
+
+ return propertyName;
+}
+
+void BindingModel::addBindingForCurrentNode()
+{
+ if (connectionView()->selectedModelNodes().count() == 1) {
+ const ModelNode modelNode = connectionView()->selectedModelNodes().constFirst();
+ if (modelNode.isValid()) {
+ try {
+ modelNode.bindingProperty(unusedProperty(modelNode)).setExpression(QLatin1String("none.none"));
+ } catch (RewritingException &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &BindingModel::handleException);
+ }
+ }
+ } else {
+ qWarning() << " BindingModel::addBindingForCurrentNode not one node selected";
+ }
+}
+
+void BindingModel::addBindingProperty(const BindingProperty &property)
+{
+ QStandardItem *idItem;
+ QStandardItem *targetPropertyNameItem;
+ QStandardItem *sourceIdItem;
+ QStandardItem *sourcePropertyNameItem;
+
+ QString idLabel = property.parentModelNode().id();
+ if (idLabel.isEmpty())
+ idLabel = property.parentModelNode().simplifiedTypeName();
+ idItem = new QStandardItem(idLabel);
+ updateCustomData(idItem, property);
+ targetPropertyNameItem = new QStandardItem(QString::fromUtf8(property.name()));
+ QList<QStandardItem*> items;
+
+ items.append(idItem);
+ items.append(targetPropertyNameItem);
+
+ QString sourceNodeName;
+ QString sourcePropertyName;
+ getExpressionStrings(property, &sourceNodeName, &sourcePropertyName);
+
+ sourceIdItem = new QStandardItem(sourceNodeName);
+ sourcePropertyNameItem = new QStandardItem(sourcePropertyName);
+
+ items.append(sourceIdItem);
+ items.append(sourcePropertyNameItem);
+ appendRow(items);
+}
+
+void BindingModel::updateBindingProperty(int rowNumber)
+{
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+
+ if (bindingProperty.isValid()) {
+ QString targetPropertyName = QString::fromUtf8(bindingProperty.name());
+ updateDisplayRole(rowNumber, TargetPropertyNameRow, targetPropertyName);
+ QString sourceNodeName;
+ QString sourcePropertyName;
+ getExpressionStrings(bindingProperty, &sourceNodeName, &sourcePropertyName);
+ updateDisplayRole(rowNumber, SourceModelNodeRow, sourceNodeName);
+ updateDisplayRole(rowNumber, SourcePropertyNameRow, sourcePropertyName);
+ }
+}
+
+void BindingModel::addModelNode(const ModelNode &modelNode)
+{
+ foreach (const BindingProperty &bindingProperty, modelNode.bindingProperties()) {
+ addBindingProperty(bindingProperty);
+ }
+}
+
+void BindingModel::updateExpression(int row)
+{
+ const QString sourceNode = data(index(row, SourceModelNodeRow)).toString().trimmed();
+ const QString sourceProperty = data(index(row, SourcePropertyNameRow)).toString().trimmed();
+
+ QString expression;
+ if (sourceProperty.isEmpty()) {
+ expression = sourceNode;
+ } else {
+ expression = sourceNode + QLatin1String(".") + sourceProperty;
+ }
+
+ connectionView()->executeInTransaction("BindingModel::updateExpression", [this, row, expression](){
+ BindingProperty bindingProperty = bindingPropertyForRow(row);
+ bindingProperty.setExpression(expression.trimmed());
+ });
+}
+
+void BindingModel::updatePropertyName(int rowNumber)
+{
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+
+ const PropertyName newName = data(index(rowNumber, TargetPropertyNameRow)).toString().toUtf8();
+ const QString expression = bindingProperty.expression();
+ const PropertyName dynamicPropertyType = bindingProperty.dynamicTypeName();
+ ModelNode targetNode = bindingProperty.parentModelNode();
+
+ if (!newName.isEmpty()) {
+ RewriterTransaction transaction =
+ connectionView()->beginRewriterTransaction(QByteArrayLiteral("BindingModel::updatePropertyName"));
+ try {
+ if (bindingProperty.isDynamic()) {
+ targetNode.bindingProperty(newName).setDynamicTypeNameAndExpression(dynamicPropertyType, expression);
+ } else {
+ targetNode.bindingProperty(newName).setExpression(expression);
+ }
+ targetNode.removeProperty(bindingProperty.name());
+ transaction.commit(); //committing in the try block
+ } catch (Exception &e) { //better save then sorry
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &BindingModel::handleException);
+ }
+
+ QStandardItem* idItem = item(rowNumber, 0);
+ BindingProperty newBindingProperty = targetNode.bindingProperty(newName);
+ updateCustomData(idItem, newBindingProperty);
+
+ } else {
+ qWarning() << "BindingModel::updatePropertyName invalid property name";
+ }
+}
+
+ModelNode BindingModel::getNodeByIdOrParent(const QString &id, const ModelNode &targetNode) const
+{
+ ModelNode modelNode;
+
+ if (id != QLatin1String("parent")) {
+ modelNode = connectionView()->modelNodeForId(id);
+ } else {
+ if (targetNode.hasParentProperty()) {
+ modelNode = targetNode.parentProperty().parentModelNode();
+ }
+ }
+ return modelNode;
+}
+
+void BindingModel::updateCustomData(QStandardItem *item, const BindingProperty &bindingProperty)
+{
+ item->setData(bindingProperty.parentModelNode().internalId(), Qt::UserRole + 1);
+ item->setData(bindingProperty.name(), Qt::UserRole + 2);
+}
+
+int BindingModel::findRowForBinding(const BindingProperty &bindingProperty)
+{
+ for (int i=0; i < rowCount(); i++) {
+ if (compareBindingProperties(bindingPropertyForRow(i), bindingProperty))
+ return i;
+ }
+ //not found
+ return -1;
+}
+
+bool BindingModel::getExpressionStrings(const BindingProperty &bindingProperty, QString *sourceNode, QString *sourceProperty)
+{
+ //### todo we assume no expressions yet
+
+ const QString expression = bindingProperty.expression();
+
+ if (true) {
+ const QStringList stringList = expression.split(QLatin1String("."));
+
+ *sourceNode = stringList.constFirst();
+
+ QString propertyName;
+
+ for (int i=1; i < stringList.count(); i++) {
+ propertyName += stringList.at(i);
+ if (i != stringList.count() - 1)
+ propertyName += QLatin1String(".");
+ }
+ *sourceProperty = propertyName;
+ }
+ return true;
+}
+
+void BindingModel::updateDisplayRole(int row, int columns, const QString &string)
+{
+ QModelIndex modelIndex = index(row, columns);
+ if (data(modelIndex).toString() != string)
+ setData(modelIndex, string);
+}
+
+void BindingModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+ if (!m_handleDataChanged)
+ return;
+
+ if (topLeft != bottomRight) {
+ qWarning() << "BindingModel::handleDataChanged multi edit?";
+ return;
+ }
+
+ m_lock = true;
+
+ int currentColumn = topLeft.column();
+ int currentRow = topLeft.row();
+
+ switch (currentColumn) {
+ case TargetModelNodeRow: {
+ //updating user data
+ } break;
+ case TargetPropertyNameRow: {
+ updatePropertyName(currentRow);
+ } break;
+ case SourceModelNodeRow: {
+ updateExpression(currentRow);
+ } break;
+ case SourcePropertyNameRow: {
+ updateExpression(currentRow);
+ } break;
+
+ default: qWarning() << "BindingModel::handleDataChanged column" << currentColumn;
+ }
+
+ m_lock = false;
+}
+
+void BindingModel::handleException()
+{
+ QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
+ resetModel();
+}
+
+} // namespace Internal
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.h b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h
index 480ba254ad..480ba254ad 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectioneditor.pri b/src/plugins/qmldesigner/components/connectioneditor/connectioneditor.pri
index 5dfa3160ab..5dfa3160ab 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectioneditor.pri
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectioneditor.pri
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectioneditor.qrc b/src/plugins/qmldesigner/components/connectioneditor/connectioneditor.qrc
index a313b6648d..a313b6648d 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectioneditor.qrc
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectioneditor.qrc
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
new file mode 100644
index 0000000000..80caf51ce0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "connectionmodel.h"
+#include "connectionview.h"
+
+#include <bindingproperty.h>
+#include <variantproperty.h>
+#include <signalhandlerproperty.h>
+#include <rewritertransaction.h>
+#include <nodeabstractproperty.h>
+#include <exception.h>
+#include <nodemetainfo.h>
+
+#include <QStandardItemModel>
+#include <QMessageBox>
+#include <QTableView>
+#include <QTimer>
+
+namespace {
+
+QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &propertyNameList)
+{
+ QStringList stringList;
+ foreach (QmlDesigner::PropertyName propertyName, propertyNameList) {
+ stringList << QString::fromUtf8(propertyName);
+ }
+ return stringList;
+}
+
+bool isConnection(const QmlDesigner::ModelNode &modelNode)
+{
+ return (modelNode.type() == "Connections"
+ || modelNode.type() == "QtQuick.Connections"
+ || modelNode.type() == "Qt.Connections");
+
+}
+
+} //namespace
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+ConnectionModel::ConnectionModel(ConnectionView *parent)
+ : QStandardItemModel(parent)
+ , m_connectionView(parent)
+{
+ connect(this, &QStandardItemModel::dataChanged, this, &ConnectionModel::handleDataChanged);
+}
+
+void ConnectionModel::resetModel()
+{
+ beginResetModel();
+ clear();
+ setHorizontalHeaderLabels(QStringList({ tr("Target"), tr("Signal Handler"), tr("Action") }));
+
+ if (connectionView()->isAttached()) {
+ foreach (const ModelNode modelNode, connectionView()->allModelNodes())
+ addModelNode(modelNode);
+ }
+
+ const int columnWidthTarget = connectionView()->connectionTableView()->columnWidth(0);
+ connectionView()->connectionTableView()->setColumnWidth(0, columnWidthTarget - 80);
+
+ endResetModel();
+}
+
+SignalHandlerProperty ConnectionModel::signalHandlerPropertyForRow(int rowNumber) const
+{
+ const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
+ const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
+
+ ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
+
+ if (modelNode.isValid())
+ return modelNode.signalHandlerProperty(targetPropertyName.toUtf8());
+
+ return SignalHandlerProperty();
+}
+
+void ConnectionModel::addModelNode(const ModelNode &modelNode)
+{
+ if (isConnection(modelNode))
+ addConnection(modelNode);
+}
+
+void ConnectionModel::addConnection(const ModelNode &modelNode)
+{
+ foreach (const AbstractProperty &property, modelNode.properties()) {
+ if (property.isSignalHandlerProperty() && property.name() != "target") {
+ addSignalHandler(property.toSignalHandlerProperty());
+ }
+ }
+}
+
+void ConnectionModel::addSignalHandler(const SignalHandlerProperty &signalHandlerProperty)
+{
+ QStandardItem *targetItem;
+ QStandardItem *signalItem;
+ QStandardItem *actionItem;
+
+ QString idLabel;
+
+ ModelNode connectionsModelNode = signalHandlerProperty.parentModelNode();
+
+ if (connectionsModelNode.bindingProperty("target").isValid()) {
+ idLabel =connectionsModelNode.bindingProperty("target").expression();
+ }
+
+ targetItem = new QStandardItem(idLabel);
+ updateCustomData(targetItem, signalHandlerProperty);
+ const QString propertyName = QString::fromUtf8(signalHandlerProperty.name());
+ const QString source = signalHandlerProperty.source();
+
+ signalItem = new QStandardItem(propertyName);
+ QList<QStandardItem*> items;
+
+ items.append(targetItem);
+ items.append(signalItem);
+
+ actionItem = new QStandardItem(source);
+
+ items.append(actionItem);
+
+ appendRow(items);
+}
+
+void ConnectionModel::removeModelNode(const ModelNode &modelNode)
+{
+ if (isConnection(modelNode))
+ removeConnection(modelNode);
+}
+
+void ConnectionModel::removeConnection(const ModelNode & /*modelNode*/)
+{
+ Q_ASSERT_X(false, "not implemented", Q_FUNC_INFO);
+}
+
+void ConnectionModel::updateSource(int row)
+{
+ SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(row);
+
+ const QString sourceString = data(index(row, SourceRow)).toString();
+
+ RewriterTransaction transaction =
+ connectionView()->beginRewriterTransaction(QByteArrayLiteral("ConnectionModel::updateSource"));
+
+ try {
+ signalHandlerProperty.setSource(sourceString);
+ transaction.commit();
+ }
+ catch (Exception &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &ConnectionModel::handleException);
+ }
+
+}
+
+void ConnectionModel::updateSignalName(int rowNumber)
+{
+ SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(rowNumber);
+ ModelNode connectionNode = signalHandlerProperty.parentModelNode();
+
+ const PropertyName newName = data(index(rowNumber, TargetPropertyNameRow)).toString().toUtf8();
+ if (!newName.isEmpty()) {
+ connectionView()->executeInTransaction("ConnectionModel::updateSignalName", [=, &connectionNode](){
+
+ const QString source = signalHandlerProperty.source();
+
+ connectionNode.signalHandlerProperty(newName).setSource(source);
+ connectionNode.removeProperty(signalHandlerProperty.name());
+ });
+
+ QStandardItem* idItem = item(rowNumber, 0);
+ SignalHandlerProperty newSignalHandlerProperty = connectionNode.signalHandlerProperty(newName);
+ updateCustomData(idItem, newSignalHandlerProperty);
+ } else {
+ qWarning() << "BindingModel::updatePropertyName invalid property name";
+ }
+}
+
+void ConnectionModel::updateTargetNode(int rowNumber)
+{
+ SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(rowNumber);
+ const QString newTarget = data(index(rowNumber, TargetModelNodeRow)).toString();
+ ModelNode connectionNode = signalHandlerProperty.parentModelNode();
+
+ if (!newTarget.isEmpty()) {
+ connectionView()->executeInTransaction("ConnectionModel::updateTargetNode", [= ,&connectionNode](){
+ connectionNode.bindingProperty("target").setExpression(newTarget);
+ });
+
+ QStandardItem* idItem = item(rowNumber, 0);
+ updateCustomData(idItem, signalHandlerProperty);
+
+ } else {
+ qWarning() << "BindingModel::updatePropertyName invalid target id";
+ }
+}
+
+void ConnectionModel::updateCustomData(QStandardItem *item, const SignalHandlerProperty &signalHandlerProperty)
+{
+ item->setData(signalHandlerProperty.parentModelNode().internalId(), Qt::UserRole + 1);
+ item->setData(signalHandlerProperty.name(), Qt::UserRole + 2);
+}
+
+ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connection) const
+{
+ BindingProperty bindingProperty = connection.bindingProperty("target");
+
+ if (bindingProperty.isValid()) {
+ if (bindingProperty.expression() == QLatin1String("parent"))
+ return connection.parentProperty().parentModelNode();
+ return connectionView()->modelNodeForId(bindingProperty.expression());
+ }
+
+ return ModelNode();
+}
+
+void ConnectionModel::addConnection()
+{
+ ModelNode rootModelNode = connectionView()->rootModelNode();
+
+ if (rootModelNode.isValid() && rootModelNode.metaInfo().isValid()) {
+
+ NodeMetaInfo nodeMetaInfo = connectionView()->model()->metaInfo("QtQuick.Connections");
+
+ if (nodeMetaInfo.isValid()) {
+ connectionView()->executeInTransaction("ConnectionModel::addConnection", [=](){
+ ModelNode newNode = connectionView()->createModelNode("QtQuick.Connections",
+ nodeMetaInfo.majorVersion(),
+ nodeMetaInfo.minorVersion());
+
+ rootModelNode.nodeAbstractProperty(rootModelNode.metaInfo().defaultPropertyName()).reparentHere(newNode);
+ newNode.signalHandlerProperty("onClicked").setSource(QLatin1String("print(\"clicked\")"));
+
+ if (connectionView()->selectedModelNodes().count() == 1
+ && !connectionView()->selectedModelNodes().constFirst().id().isEmpty()) {
+ const ModelNode selectedNode = connectionView()->selectedModelNodes().constFirst();
+ newNode.bindingProperty("target").setExpression(selectedNode.id());
+ } else {
+ newNode.bindingProperty("target").setExpression(QLatin1String("parent"));
+ }
+ });
+ }
+ }
+}
+
+void ConnectionModel::bindingPropertyChanged(const BindingProperty &bindingProperty)
+{
+ if (isConnection(bindingProperty.parentModelNode()))
+ resetModel();
+}
+
+void ConnectionModel::variantPropertyChanged(const VariantProperty &variantProperty)
+{
+ if (isConnection(variantProperty.parentModelNode()))
+ resetModel();
+}
+
+void ConnectionModel::deleteConnectionByRow(int currentRow)
+{
+ signalHandlerPropertyForRow(currentRow).parentModelNode().destroy();
+}
+
+void ConnectionModel::handleException()
+{
+ QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
+ resetModel();
+}
+
+void ConnectionModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+ if (topLeft != bottomRight) {
+ qWarning() << "ConnectionModel::handleDataChanged multi edit?";
+ return;
+ }
+
+ m_lock = true;
+
+ int currentColumn = topLeft.column();
+ int currentRow = topLeft.row();
+
+ switch (currentColumn) {
+ case TargetModelNodeRow: {
+ updateTargetNode(currentRow);
+ } break;
+ case TargetPropertyNameRow: {
+ updateSignalName(currentRow);
+ } break;
+ case SourceRow: {
+ updateSource(currentRow);
+ } break;
+
+ default: qWarning() << "ConnectionModel::handleDataChanged column" << currentColumn;
+ }
+
+ m_lock = false;
+}
+
+ConnectionView *ConnectionModel::connectionView() const
+{
+ return m_connectionView;
+}
+
+QStringList ConnectionModel::getSignalsForRow(int row) const
+{
+ QStringList stringList;
+ SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(row);
+
+ if (signalHandlerProperty.isValid()) {
+ stringList.append(getPossibleSignalsForConnection(signalHandlerProperty.parentModelNode()));
+ }
+
+ return stringList;
+}
+
+QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &connection) const
+{
+ QStringList stringList;
+
+ if (connection.isValid()) {
+ ModelNode targetNode = getTargetNodeForConnection(connection);
+ if (targetNode.isValid() && targetNode.metaInfo().isValid()) {
+ stringList.append(propertyNameListToStringList(targetNode.metaInfo().signalNames()));
+ }
+ }
+
+ return stringList;
+}
+
+} // namespace Internal
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.h b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
index 2c66b2ef25..2c66b2ef25 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionview.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
index 9aef01259e..9aef01259e 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionview.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionview.h b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
index da7623375a..da7623375a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionview.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
index c9b1277ce4..c9b1277ce4 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.h b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.h
index 2bcc3932c1..2bcc3932c1 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.ui b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.ui
index 18df078ec6..18df078ec6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.ui
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.ui
diff --git a/src/plugins/qmldesigner/components/connectioneditor/delegates.cpp b/src/plugins/qmldesigner/components/connectioneditor/delegates.cpp
new file mode 100644
index 0000000000..555f448858
--- /dev/null
+++ b/src/plugins/qmldesigner/components/connectioneditor/delegates.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "delegates.h"
+
+#include "backendmodel.h"
+#include "connectionmodel.h"
+#include "bindingmodel.h"
+#include "dynamicpropertiesmodel.h"
+#include "connectionview.h"
+
+#include <bindingproperty.h>
+
+#include <utils/qtcassert.h>
+
+#include <QStyleFactory>
+#include <QItemEditorFactory>
+#include <QDebug>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+QStringList prependOnForSignalHandler(const QStringList &signalNames)
+{
+ QStringList signalHandlerNames;
+ foreach (const QString &signalName, signalNames) {
+ QString signalHandlerName = signalName;
+ if (!signalHandlerName.isEmpty()) {
+ QChar firstChar = signalHandlerName.at(0).toUpper();
+ signalHandlerName[0] = firstChar;
+ signalHandlerName.prepend(QLatin1String("on"));
+ signalHandlerNames.append(signalHandlerName);
+ }
+ }
+ return signalHandlerNames;
+}
+
+PropertiesComboBox::PropertiesComboBox(QWidget *parent) : QComboBox(parent)
+{
+ setEditable(true);
+ setValidator(new QRegularExpressionValidator(QRegularExpression(QLatin1String("[a-z|A-Z|0-9|._-]*")), this));
+}
+
+QString PropertiesComboBox::text() const
+{
+ return currentText();
+}
+
+void PropertiesComboBox::setText(const QString &text)
+{
+ setEditText(text);
+}
+
+void PropertiesComboBox::disableValidator()
+{
+ setValidator(nullptr);
+}
+
+ConnectionComboBox::ConnectionComboBox(QWidget *parent) : PropertiesComboBox(parent)
+{
+}
+
+QString ConnectionComboBox::text() const
+{
+ int index = findText(currentText());
+ if (index > -1) {
+ QVariant variantData = itemData(index);
+ if (variantData.isValid())
+ return variantData.toString();
+ }
+
+ return currentText();
+}
+
+ConnectionEditorDelegate::ConnectionEditorDelegate(QWidget *parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+void ConnectionEditorDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QStyleOptionViewItem opt = option;
+ opt.state &= ~QStyle::State_HasFocus;
+ QStyledItemDelegate::paint(painter, opt, index);
+}
+
+BindingDelegate::BindingDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
+{
+ static QItemEditorFactory *factory = nullptr;
+ if (factory == nullptr) {
+ factory = new QItemEditorFactory;
+ QItemEditorCreatorBase *creator
+ = new QItemEditorCreator<PropertiesComboBox>("text");
+ factory->registerEditor(QVariant::String, creator);
+ }
+
+ setItemEditorFactory(factory);
+}
+
+QWidget *BindingDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
+
+ const auto model = qobject_cast<const BindingModel*>(index.model());
+ if (!model) {
+ qWarning() << "BindingDelegate::createEditor no model";
+ return widget;
+ }
+ if (!model->connectionView()) {
+ qWarning() << "BindingDelegate::createEditor no connection view";
+ return widget;
+ }
+
+ model->connectionView()->allModelNodes();
+
+ auto bindingComboBox = qobject_cast<PropertiesComboBox*>(widget);
+ if (!bindingComboBox) {
+ qWarning() << "BindingDelegate::createEditor no bindingComboBox";
+ return widget;
+ }
+
+ BindingProperty bindingProperty = model->bindingPropertyForRow(index.row());
+
+ switch (index.column()) {
+ case BindingModel::TargetModelNodeRow:
+ return nullptr; //no editor
+ case BindingModel::TargetPropertyNameRow: {
+ bindingComboBox->addItems(model->possibleTargetProperties(bindingProperty));
+ } break;
+ case BindingModel::SourceModelNodeRow: {
+ foreach (const ModelNode &modelNode, model->connectionView()->allModelNodes()) {
+ if (!modelNode.id().isEmpty()) {
+ bindingComboBox->addItem(modelNode.id());
+ }
+ }
+ if (!bindingProperty.parentModelNode().isRootNode())
+ bindingComboBox->addItem(QLatin1String("parent"));
+ } break;
+ case BindingModel::SourcePropertyNameRow: {
+ bindingComboBox->addItems(model->possibleSourceProperties(bindingProperty));
+ bindingComboBox->disableValidator();
+ } break;
+ default: qWarning() << "BindingDelegate::createEditor column" << index.column();
+ }
+
+ connect(bindingComboBox, QOverload<int>::of(&QComboBox::activated), this, [=]() {
+ auto delegate = const_cast<BindingDelegate*>(this);
+ emit delegate->commitData(bindingComboBox);
+ });
+
+ return widget;
+}
+
+DynamicPropertiesDelegate::DynamicPropertiesDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
+{
+// static QItemEditorFactory *factory = 0;
+// if (factory == 0) {
+// factory = new QItemEditorFactory;
+// QItemEditorCreatorBase *creator
+// = new QItemEditorCreator<DynamicPropertiesComboBox>("text");
+// factory->registerEditor(QVariant::String, creator);
+// }
+
+// setItemEditorFactory(factory);
+}
+
+QWidget *DynamicPropertiesDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
+
+ const auto model = qobject_cast<const DynamicPropertiesModel*>(index.model());
+ if (!model) {
+ qWarning() << "BindingDelegate::createEditor no model";
+ return widget;
+ }
+
+ if (!model->connectionView()) {
+ qWarning() << "BindingDelegate::createEditor no connection view";
+ return widget;
+ }
+ model->connectionView()->allModelNodes();
+
+ switch (index.column()) {
+ case DynamicPropertiesModel::TargetModelNodeRow: {
+ return nullptr; //no editor
+ };
+ case DynamicPropertiesModel::PropertyNameRow: {
+ return QStyledItemDelegate::createEditor(parent, option, index);
+ };
+ case DynamicPropertiesModel::PropertyTypeRow: {
+
+ auto dynamicPropertiesComboBox = new PropertiesComboBox(parent);
+ connect(dynamicPropertiesComboBox, QOverload<int>::of(&QComboBox::activated), this, [=]() {
+ auto delegate = const_cast<DynamicPropertiesDelegate*>(this);
+ emit delegate->commitData(dynamicPropertiesComboBox);
+ });
+
+ dynamicPropertiesComboBox->addItem(QLatin1String("alias"));
+ //dynamicPropertiesComboBox->addItem(QLatin1String("Item"));
+ dynamicPropertiesComboBox->addItem(QLatin1String("real"));
+ dynamicPropertiesComboBox->addItem(QLatin1String("int"));
+ dynamicPropertiesComboBox->addItem(QLatin1String("string"));
+ dynamicPropertiesComboBox->addItem(QLatin1String("bool"));
+ dynamicPropertiesComboBox->addItem(QLatin1String("url"));
+ dynamicPropertiesComboBox->addItem(QLatin1String("color"));
+ dynamicPropertiesComboBox->addItem(QLatin1String("variant"));
+ return dynamicPropertiesComboBox;
+ };
+ case DynamicPropertiesModel::PropertyValueRow: {
+ return QStyledItemDelegate::createEditor(parent, option, index);
+ };
+ default: qWarning() << "BindingDelegate::createEditor column" << index.column();
+ }
+
+ return nullptr;
+}
+
+ConnectionDelegate::ConnectionDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
+{
+ static QItemEditorFactory *factory = nullptr;
+ if (factory == nullptr) {
+ factory = new QItemEditorFactory;
+ QItemEditorCreatorBase *creator
+ = new QItemEditorCreator<ConnectionComboBox>("text");
+ factory->registerEditor(QVariant::String, creator);
+ }
+
+ setItemEditorFactory(factory);
+}
+
+QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+
+ QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
+
+ const auto connectionModel = qobject_cast<const ConnectionModel*>(index.model());
+
+ auto connectionComboBox = qobject_cast<ConnectionComboBox*>(widget);
+
+ if (!connectionModel) {
+ qWarning() << "ConnectionDelegate::createEditor no model";
+ return widget;
+ }
+
+ if (!connectionModel->connectionView()) {
+ qWarning() << "ConnectionDelegate::createEditor no connection view";
+ return widget;
+ }
+
+ if (!connectionComboBox) {
+ qWarning() << "ConnectionDelegate::createEditor no bindingComboBox";
+ return widget;
+ }
+
+ switch (index.column()) {
+ case ConnectionModel::TargetModelNodeRow: {
+ foreach (const ModelNode &modelNode, connectionModel->connectionView()->allModelNodes()) {
+ if (!modelNode.id().isEmpty()) {
+ connectionComboBox->addItem(modelNode.id());
+ }
+ }
+ } break;
+ case ConnectionModel::TargetPropertyNameRow: {
+ connectionComboBox->addItems(prependOnForSignalHandler(connectionModel->getSignalsForRow(index.row())));
+ } break;
+ case ConnectionModel::SourceRow: {
+ ModelNode rootModelNode = connectionModel->connectionView()->rootModelNode();
+ if (QmlItemNode::isValidQmlItemNode(rootModelNode) && !rootModelNode.id().isEmpty()) {
+
+ QString itemText = tr("Change to default state");
+ QString source = QString::fromLatin1("{ %1.state = \"\" }").arg(rootModelNode.id());
+ connectionComboBox->addItem(itemText, source);
+ connectionComboBox->disableValidator();
+
+ foreach (const QmlModelState &state, QmlItemNode(rootModelNode).states().allStates()) {
+ QString itemText = tr("Change state to %1").arg(state.name());
+ QString source = QString::fromLatin1("{ %1.state = \"%2\" }").arg(rootModelNode.id()).arg(state.name());
+ connectionComboBox->addItem(itemText, source);
+ }
+ }
+ connectionComboBox->disableValidator();
+ } break;
+
+ default: qWarning() << "ConnectionDelegate::createEditor column" << index.column();
+ }
+
+ connect(connectionComboBox, QOverload<int>::of(&QComboBox::activated), this, [=]() {
+ auto delegate = const_cast<ConnectionDelegate*>(this);
+ emit delegate->commitData(connectionComboBox);
+ });
+
+ return widget;
+}
+
+BackendDelegate::BackendDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
+{
+}
+
+QWidget *BackendDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ const auto model = qobject_cast<const BackendModel*>(index.model());
+
+ model->connectionView()->allModelNodes();
+
+ QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
+
+ QTC_ASSERT(model, return widget);
+ QTC_ASSERT(model->connectionView(), return widget);
+
+ switch (index.column()) {
+ case BackendModel::TypeNameColumn: {
+ auto backendComboBox = new PropertiesComboBox(parent);
+ backendComboBox->addItems(model->possibleCppTypes());
+ connect(backendComboBox, QOverload<int>::of(&QComboBox::activated), this, [=]() {
+ auto delegate = const_cast<BackendDelegate*>(this);
+ emit delegate->commitData(backendComboBox);
+ });
+ return backendComboBox;
+ };
+ case BackendModel::PropertyNameColumn: {
+ return widget;
+ };
+ case BackendModel::IsSingletonColumn: {
+ return nullptr; //no editor
+ };
+ case BackendModel::IsLocalColumn: {
+ return nullptr; //no editor
+ };
+ default: qWarning() << "BackendDelegate::createEditor column" << index.column();
+ }
+
+ return widget;
+}
+
+} // namesapce Internal
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/delegates.h b/src/plugins/qmldesigner/components/connectioneditor/delegates.h
index b9792293ac..b9792293ac 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/delegates.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/delegates.h
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
new file mode 100644
index 0000000000..0a08e5c883
--- /dev/null
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
@@ -0,0 +1,677 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "dynamicpropertiesmodel.h"
+
+#include "connectionview.h"
+
+#include <nodemetainfo.h>
+#include <nodeproperty.h>
+#include <variantproperty.h>
+#include <bindingproperty.h>
+#include <rewritingexception.h>
+#include <rewritertransaction.h>
+
+#include <utils/fileutils.h>
+
+#include <QMessageBox>
+#include <QTimer>
+#include <QUrl>
+
+namespace {
+
+bool compareVariantProperties(const QmlDesigner::VariantProperty &variantProperty01, const QmlDesigner::VariantProperty &variantProperty02)
+{
+ if (variantProperty01.parentModelNode() != variantProperty02.parentModelNode())
+ return false;
+ if (variantProperty01.name() != variantProperty02.name())
+ return false;
+ return true;
+}
+
+QString idOrTypeNameForNode(const QmlDesigner::ModelNode &modelNode)
+{
+ QString idLabel = modelNode.id();
+ if (idLabel.isEmpty())
+ idLabel = modelNode.simplifiedTypeName();
+
+ 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;
+
+ if (typeName == "int") {
+ bool ok;
+ returnValue = variant.toInt(&ok);
+ if (!ok)
+ returnValue = 0;
+ } else if (typeName == "real") {
+ bool ok;
+ returnValue = variant.toReal(&ok);
+ if (!ok)
+ returnValue = 0.0;
+
+ } else if (typeName == "string") {
+ returnValue = variant.toString();
+
+ } else if (typeName == "bool") {
+ returnValue = variant.toBool();
+ } else if (typeName == "url") {
+ returnValue = variant.toUrl();
+ } else if (typeName == "color") {
+ if (QColor::isValidColor(variant.toString())) {
+ returnValue = variant.toString();
+ } else {
+ returnValue = QColor(Qt::black);
+ }
+ } else if (typeName == "Item") {
+ returnValue = 0;
+ }
+
+ return returnValue;
+}
+
+} //internal namespace
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+DynamicPropertiesModel::DynamicPropertiesModel(ConnectionView *parent)
+ : QStandardItemModel(parent)
+ , m_connectionView(parent)
+{
+ connect(this, &QStandardItemModel::dataChanged, this, &DynamicPropertiesModel::handleDataChanged);
+}
+
+void DynamicPropertiesModel::resetModel()
+{
+ beginResetModel();
+ clear();
+ setHorizontalHeaderLabels(QStringList({ tr("Item"), tr("Property"), tr("Property Type"),
+ tr("Property Value") }));
+
+ foreach (const ModelNode modelNode, m_selectedModelNodes)
+ addModelNode(modelNode);
+
+ endResetModel();
+}
+
+void DynamicPropertiesModel::bindingPropertyChanged(const BindingProperty &bindingProperty)
+{
+ if (!bindingProperty.isDynamic())
+ return;
+
+ m_handleDataChanged = false;
+
+ QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
+ if (!selectedNodes.contains(bindingProperty.parentModelNode()))
+ return;
+ if (!m_lock) {
+ int rowNumber = findRowForBindingProperty(bindingProperty);
+
+ if (rowNumber == -1) {
+ addBindingProperty(bindingProperty);
+ } else {
+ updateBindingProperty(rowNumber);
+ }
+ }
+
+ m_handleDataChanged = true;
+}
+
+void DynamicPropertiesModel::variantPropertyChanged(const VariantProperty &variantProperty)
+{
+ if (!variantProperty.isDynamic())
+ return;
+
+ m_handleDataChanged = false;
+
+ QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
+ if (!selectedNodes.contains(variantProperty.parentModelNode()))
+ return;
+ if (!m_lock) {
+ int rowNumber = findRowForVariantProperty(variantProperty);
+
+ if (rowNumber == -1) {
+ addVariantProperty(variantProperty);
+ } else {
+ updateVariantProperty(rowNumber);
+ }
+ }
+
+ m_handleDataChanged = true;
+}
+
+void DynamicPropertiesModel::bindingRemoved(const BindingProperty &bindingProperty)
+{
+ m_handleDataChanged = false;
+
+ QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
+ if (!selectedNodes.contains(bindingProperty.parentModelNode()))
+ return;
+ if (!m_lock) {
+ int rowNumber = findRowForBindingProperty(bindingProperty);
+ removeRow(rowNumber);
+ }
+
+ m_handleDataChanged = true;
+}
+
+void DynamicPropertiesModel::selectionChanged(const QList<ModelNode> &selectedNodes)
+{
+ m_handleDataChanged = false;
+ m_selectedModelNodes = selectedNodes;
+ resetModel();
+ m_handleDataChanged = true;
+}
+
+ConnectionView *DynamicPropertiesModel::connectionView() const
+{
+ return m_connectionView;
+}
+
+BindingProperty DynamicPropertiesModel::bindingPropertyForRow(int rowNumber) const
+{
+
+ const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
+ const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
+
+ ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
+
+ if (modelNode.isValid())
+ return modelNode.bindingProperty(targetPropertyName.toUtf8());
+
+ return BindingProperty();
+}
+
+VariantProperty DynamicPropertiesModel::variantPropertyForRow(int rowNumber) const
+{
+ const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
+ const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
+
+ ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
+
+ if (modelNode.isValid())
+ return modelNode.variantProperty(targetPropertyName.toUtf8());
+
+ return VariantProperty();
+}
+
+QStringList DynamicPropertiesModel::possibleTargetProperties(const BindingProperty &bindingProperty) const
+{
+ const ModelNode modelNode = bindingProperty.parentModelNode();
+
+ if (!modelNode.isValid()) {
+ qWarning() << " BindingModel::possibleTargetPropertiesForRow invalid model node";
+ return QStringList();
+ }
+
+ NodeMetaInfo metaInfo = modelNode.metaInfo();
+
+ if (metaInfo.isValid()) {
+ QStringList possibleProperties;
+ foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
+ if (metaInfo.propertyIsWritable(propertyName))
+ possibleProperties << QString::fromUtf8(propertyName);
+ }
+
+ return possibleProperties;
+ }
+
+ return QStringList();
+}
+
+void DynamicPropertiesModel::addDynamicPropertyForCurrentNode()
+{
+ if (connectionView()->selectedModelNodes().count() == 1) {
+ const ModelNode modelNode = connectionView()->selectedModelNodes().constFirst();
+ if (modelNode.isValid()) {
+ try {
+ modelNode.variantProperty(unusedProperty(modelNode)).setDynamicTypeNameAndValue("string", QLatin1String("none.none"));
+ } catch (RewritingException &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &DynamicPropertiesModel::handleException);
+ }
+ }
+ } else {
+ qWarning() << " BindingModel::addBindingForCurrentNode not one node selected";
+ }
+}
+
+QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProperty &bindingProperty) const
+{
+ const QString expression = bindingProperty.expression();
+ const QStringList stringlist = expression.split(QLatin1String("."));
+
+ PropertyName typeName;
+
+ if (bindingProperty.parentModelNode().metaInfo().isValid()) {
+ typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name());
+ } else {
+ qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
+ }
+
+ const QString &id = stringlist.constFirst();
+
+ ModelNode modelNode = getNodeByIdOrParent(id, bindingProperty.parentModelNode());
+
+ if (!modelNode.isValid()) {
+ qWarning() << " BindingModel::possibleSourcePropertiesForRow invalid model node";
+ return QStringList();
+ }
+
+ NodeMetaInfo metaInfo = modelNode.metaInfo();
+
+ if (metaInfo.isValid()) {
+ QStringList possibleProperties;
+ foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
+ if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
+ possibleProperties << QString::fromUtf8(propertyName);
+ }
+
+ return possibleProperties;
+ } else {
+ qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node";
+ }
+
+ return QStringList();
+}
+
+void DynamicPropertiesModel::deleteDynamicPropertyByRow(int rowNumber)
+{
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+ if (bindingProperty.isValid()) {
+ bindingProperty.parentModelNode().removeProperty(bindingProperty.name());
+ }
+
+ VariantProperty variantProperty = variantPropertyForRow(rowNumber);
+
+ if (variantProperty.isValid()) {
+ variantProperty.parentModelNode().removeProperty(variantProperty.name());
+ }
+
+ resetModel();
+}
+
+void DynamicPropertiesModel::addProperty(const QVariant &propertyValue,
+ const QString &propertyType,
+ const AbstractProperty &abstractProperty)
+{
+ QList<QStandardItem*> items;
+
+ QStandardItem *idItem;
+ QStandardItem *propertyNameItem;
+ QStandardItem *propertyTypeItem;
+ QStandardItem *propertyValueItem;
+
+ idItem = new QStandardItem(idOrTypeNameForNode(abstractProperty.parentModelNode()));
+ updateCustomData(idItem, abstractProperty);
+
+ propertyNameItem = new QStandardItem(QString::fromUtf8(abstractProperty.name()));
+
+ items.append(idItem);
+ items.append(propertyNameItem);
+
+
+ propertyTypeItem = new QStandardItem(propertyType);
+ items.append(propertyTypeItem);
+
+ propertyValueItem = new QStandardItem();
+ propertyValueItem->setData(propertyValue, Qt::DisplayRole);
+ items.append(propertyValueItem);
+
+ appendRow(items);
+}
+
+void DynamicPropertiesModel::addBindingProperty(const BindingProperty &property)
+{
+ QVariant value = property.expression();
+ QString type = QString::fromLatin1(property.dynamicTypeName());
+ addProperty(value, type, property);
+}
+
+void DynamicPropertiesModel::addVariantProperty(const VariantProperty &property)
+{
+ QVariant value = property.value();
+ QString type = QString::fromLatin1(property.dynamicTypeName());
+ addProperty(value, type, property);
+}
+
+void DynamicPropertiesModel::updateBindingProperty(int rowNumber)
+{
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+
+ if (bindingProperty.isValid()) {
+ QString propertyName = QString::fromUtf8(bindingProperty.name());
+ updateDisplayRole(rowNumber, PropertyNameRow, propertyName);
+ QString value = bindingProperty.expression();
+ QString type = QString::fromUtf8(bindingProperty.dynamicTypeName());
+ updateDisplayRole(rowNumber, PropertyTypeRow, type);
+ updateDisplayRole(rowNumber, PropertyValueRow, value);
+ }
+}
+
+void DynamicPropertiesModel::updateVariantProperty(int rowNumber)
+{
+ VariantProperty variantProperty = variantPropertyForRow(rowNumber);
+
+ if (variantProperty.isValid()) {
+ QString propertyName = QString::fromUtf8(variantProperty.name());
+ updateDisplayRole(rowNumber, PropertyNameRow, propertyName);
+ QVariant value = variantProperty.value();
+ QString type = QString::fromUtf8(variantProperty.dynamicTypeName());
+ updateDisplayRole(rowNumber, PropertyTypeRow, type);
+
+ updateDisplayRoleFromVariant(rowNumber, PropertyValueRow, value);
+ }
+}
+
+void DynamicPropertiesModel::addModelNode(const ModelNode &modelNode)
+{
+ foreach (const BindingProperty &bindingProperty, modelNode.bindingProperties()) {
+ if (bindingProperty.isDynamic())
+ addBindingProperty(bindingProperty);
+ }
+
+ foreach (const VariantProperty &variantProperty, modelNode.variantProperties()) {
+ if (variantProperty.isDynamic())
+ addVariantProperty(variantProperty);
+ }
+}
+
+void DynamicPropertiesModel::updateValue(int row)
+{
+ BindingProperty bindingProperty = bindingPropertyForRow(row);
+
+ if (bindingProperty.isBindingProperty()) {
+ const QString expression = data(index(row, PropertyValueRow)).toString();
+
+ RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updateValue"));
+ try {
+ bindingProperty.setDynamicTypeNameAndExpression(bindingProperty.dynamicTypeName(), expression);
+ transaction.commit(); //committing in the try block
+ } catch (Exception &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &DynamicPropertiesModel::handleException);
+ }
+ return;
+ }
+
+ VariantProperty variantProperty = variantPropertyForRow(row);
+
+ if (variantProperty.isVariantProperty()) {
+ const QVariant value = data(index(row, PropertyValueRow));
+
+ RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updateValue"));
+ try {
+ variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(), value);
+ transaction.commit(); //committing in the try block
+ } catch (Exception &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &DynamicPropertiesModel::handleException);
+ }
+ }
+}
+
+void DynamicPropertiesModel::updatePropertyName(int rowNumber)
+{
+ const PropertyName newName = data(index(rowNumber, PropertyNameRow)).toString().toUtf8();
+ if (newName.isEmpty()) {
+ qWarning() << "DynamicPropertiesModel::updatePropertyName invalid property name";
+ return;
+ }
+
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+
+ ModelNode targetNode = bindingProperty.parentModelNode();
+
+ if (bindingProperty.isBindingProperty()) {
+ connectionView()->executeInTransaction("DynamicPropertiesModel::updatePropertyName", [bindingProperty, newName, &targetNode](){
+ const QString expression = bindingProperty.expression();
+ const PropertyName dynamicPropertyType = bindingProperty.dynamicTypeName();
+
+ targetNode.bindingProperty(newName).setDynamicTypeNameAndExpression(dynamicPropertyType, expression);
+ targetNode.removeProperty(bindingProperty.name());
+ });
+
+ updateCustomData(rowNumber, targetNode.bindingProperty(newName));
+ return;
+ }
+
+ VariantProperty variantProperty = variantPropertyForRow(rowNumber);
+
+ if (variantProperty.isVariantProperty()) {
+ const QVariant value = variantProperty.value();
+ const PropertyName dynamicPropertyType = variantProperty.dynamicTypeName();
+ ModelNode targetNode = variantProperty.parentModelNode();
+
+ connectionView()->executeInTransaction("DynamicPropertiesModel::updatePropertyName", [=](){
+ targetNode.variantProperty(newName).setDynamicTypeNameAndValue(dynamicPropertyType, value);
+ targetNode.removeProperty(variantProperty.name());
+ });
+
+ updateCustomData(rowNumber, targetNode.variantProperty(newName));
+ }
+}
+
+void DynamicPropertiesModel::updatePropertyType(int rowNumber)
+{
+
+ const TypeName newType = data(index(rowNumber, PropertyTypeRow)).toString().toLatin1();
+
+ if (newType.isEmpty()) {
+ qWarning() << "DynamicPropertiesModel::updatePropertyName invalid property type";
+ return;
+ }
+
+ BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
+
+ if (bindingProperty.isBindingProperty()) {
+ const QString expression = bindingProperty.expression();
+ const PropertyName propertyName = bindingProperty.name();
+ ModelNode targetNode = bindingProperty.parentModelNode();
+
+ connectionView()->executeInTransaction("DynamicPropertiesModel::updatePropertyType", [=](){
+ targetNode.removeProperty(bindingProperty.name());
+ targetNode.bindingProperty(propertyName).setDynamicTypeNameAndExpression(newType, expression);
+ });
+
+ updateCustomData(rowNumber, targetNode.bindingProperty(propertyName));
+ return;
+ }
+
+ VariantProperty variantProperty = variantPropertyForRow(rowNumber);
+
+ if (variantProperty.isVariantProperty()) {
+ const QVariant value = variantProperty.value();
+ ModelNode targetNode = variantProperty.parentModelNode();
+ const PropertyName propertyName = variantProperty.name();
+
+ connectionView()->executeInTransaction("DynamicPropertiesModel::updatePropertyType", [=](){
+ targetNode.removeProperty(variantProperty.name());
+ if (newType == "alias") { //alias properties have to be bindings
+ targetNode.bindingProperty(propertyName).setDynamicTypeNameAndExpression(newType, QLatin1String("none.none"));
+ } else {
+ targetNode.variantProperty(propertyName).setDynamicTypeNameAndValue(newType, convertVariantForTypeName(value, newType));
+ }
+ });
+
+ updateCustomData(rowNumber, targetNode.variantProperty(propertyName));
+
+ if (variantProperty.isVariantProperty()) {
+ updateVariantProperty(rowNumber);
+ } else if (bindingProperty.isBindingProperty()) {
+ updateBindingProperty(rowNumber);
+ }
+ }
+}
+
+ModelNode DynamicPropertiesModel::getNodeByIdOrParent(const QString &id, const ModelNode &targetNode) const
+{
+ ModelNode modelNode;
+
+ if (id != QLatin1String("parent")) {
+ modelNode = connectionView()->modelNodeForId(id);
+ } else {
+ if (targetNode.hasParentProperty()) {
+ modelNode = targetNode.parentProperty().parentModelNode();
+ }
+ }
+ return modelNode;
+}
+
+void DynamicPropertiesModel::updateCustomData(QStandardItem *item, const AbstractProperty &property)
+{
+ item->setData(property.parentModelNode().internalId(), Qt::UserRole + 1);
+ item->setData(property.name(), Qt::UserRole + 2);
+}
+
+void DynamicPropertiesModel::updateCustomData(int row, const AbstractProperty &property)
+{
+ QStandardItem* idItem = item(row, 0);
+ updateCustomData(idItem, property);
+}
+
+int DynamicPropertiesModel::findRowForBindingProperty(const BindingProperty &bindingProperty) const
+{
+ for (int i=0; i < rowCount(); i++) {
+ if (compareBindingProperties(bindingPropertyForRow(i), bindingProperty))
+ return i;
+ }
+ //not found
+ return -1;
+}
+
+int DynamicPropertiesModel::findRowForVariantProperty(const VariantProperty &variantProperty) const
+{
+ for (int i=0; i < rowCount(); i++) {
+ if (compareVariantProperties(variantPropertyForRow(i), variantProperty))
+ return i;
+ }
+ //not found
+ return -1;
+}
+
+bool DynamicPropertiesModel::getExpressionStrings(const BindingProperty &bindingProperty, QString *sourceNode, QString *sourceProperty)
+{
+ //### todo we assume no expressions yet
+
+ const QString expression = bindingProperty.expression();
+
+ if (true) {
+ const QStringList stringList = expression.split(QLatin1String("."));
+
+ *sourceNode = stringList.constFirst();
+
+ QString propertyName;
+
+ for (int i=1; i < stringList.count(); i++) {
+ propertyName += stringList.at(i);
+ if (i != stringList.count() - 1)
+ propertyName += QLatin1String(".");
+ }
+ *sourceProperty = propertyName;
+ }
+ return true;
+}
+
+void DynamicPropertiesModel::updateDisplayRole(int row, int columns, const QString &string)
+{
+ QModelIndex modelIndex = index(row, columns);
+ if (data(modelIndex).toString() != string)
+ setData(modelIndex, string);
+}
+
+void DynamicPropertiesModel::updateDisplayRoleFromVariant(int row, int columns, const QVariant &variant)
+{
+ QModelIndex modelIndex = index(row, columns);
+ if (data(modelIndex) != variant)
+ setData(modelIndex, variant);
+}
+
+
+void DynamicPropertiesModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+ if (!m_handleDataChanged)
+ return;
+
+ if (topLeft != bottomRight) {
+ qWarning() << "BindingModel::handleDataChanged multi edit?";
+ return;
+ }
+
+ m_lock = true;
+
+ int currentColumn = topLeft.column();
+ int currentRow = topLeft.row();
+
+ switch (currentColumn) {
+ case TargetModelNodeRow: {
+ //updating user data
+ } break;
+ case PropertyNameRow: {
+ updatePropertyName(currentRow);
+ } break;
+ case PropertyTypeRow: {
+ updatePropertyType(currentRow);
+ } break;
+ case PropertyValueRow: {
+ updateValue(currentRow);
+ } break;
+
+ default: qWarning() << "BindingModel::handleDataChanged column" << currentColumn;
+ }
+
+ m_lock = false;
+}
+
+void DynamicPropertiesModel::handleException()
+{
+ QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
+ resetModel();
+}
+
+} // namespace Internal
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.h b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
index e0c9617fed..e0c9617fed 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/stylesheet.css b/src/plugins/qmldesigner/components/connectioneditor/stylesheet.css
index aeacc63733..aeacc63733 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/stylesheet.css
+++ b/src/plugins/qmldesigner/components/connectioneditor/stylesheet.css
diff --git a/src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp b/src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp
new file mode 100644
index 0000000000..8e2d5224e1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/animationcurve.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "animationcurve.h"
+#include "detail/curvesegment.h"
+
+#include <QLineF>
+
+namespace DesignTools {
+
+AnimationCurve::AnimationCurve()
+ : m_frames()
+{}
+
+AnimationCurve::AnimationCurve(const std::vector<Keyframe> &frames)
+ : m_frames(frames)
+ , m_minY(std::numeric_limits<double>::max())
+ , m_maxY(std::numeric_limits<double>::lowest())
+{
+ if (isValid()) {
+
+ for (auto e : extrema()) {
+
+ if (m_minY > e.y())
+ m_minY = e.y();
+
+ if (m_maxY < e.y())
+ m_maxY = e.y();
+ }
+
+ for (auto &frame : qAsConst(m_frames)) {
+ if (frame.position().y() < m_minY)
+ m_minY = frame.position().y();
+
+ if (frame.position().y() > m_maxY)
+ m_maxY = frame.position().y();
+ }
+ }
+}
+
+bool AnimationCurve::isValid() const
+{
+ return m_frames.size() >= 2;
+}
+
+double AnimationCurve::minimumTime() const
+{
+ if (!m_frames.empty())
+ return m_frames.front().position().x();
+
+ return std::numeric_limits<double>::max();
+}
+
+double AnimationCurve::maximumTime() const
+{
+ if (!m_frames.empty())
+ return m_frames.back().position().x();
+
+ return std::numeric_limits<double>::lowest();
+}
+
+double AnimationCurve::minimumValue() const
+{
+ return m_minY;
+}
+
+double AnimationCurve::maximumValue() const
+{
+ return m_maxY;
+}
+
+std::vector<Keyframe> AnimationCurve::keyframes() const
+{
+ return m_frames;
+}
+
+std::vector<QPointF> AnimationCurve::extrema() const
+{
+ std::vector<QPointF> out;
+
+ CurveSegment segment;
+ segment.setLeft(m_frames.at(0));
+
+ for (size_t i = 1; i < m_frames.size(); ++i) {
+
+ segment.setRight(m_frames[i]);
+
+ const auto es = segment.extrema();
+ out.insert(std::end(out), std::begin(es), std::end(es));
+
+ segment.setLeft(m_frames[i]);
+ }
+
+ return out;
+}
+
+std::vector<double> AnimationCurve::yForX(double x) const
+{
+ if (m_frames.front().position().x() > x)
+ return std::vector<double>();
+
+ CurveSegment segment;
+ for (auto &frame : m_frames) {
+ if (frame.position().x() > x) {
+ segment.setRight(frame);
+ return segment.yForX(x);
+ }
+ segment.setLeft(frame);
+ }
+ return std::vector<double>();
+}
+
+std::vector<double> AnimationCurve::xForY(double y, uint segment) const
+{
+ if (m_frames.size() > segment + 1) {
+ CurveSegment seg(m_frames[segment], m_frames[segment + 1]);
+ return seg.xForY(y);
+ }
+ return std::vector<double>();
+}
+
+bool AnimationCurve::intersects(const QPointF &coord, double radius)
+{
+ if (m_frames.size() < 2)
+ return false;
+
+ std::vector<CurveSegment> influencer;
+
+ CurveSegment current;
+ current.setLeft(m_frames.at(0));
+
+ for (size_t i = 1; i < m_frames.size(); ++i) {
+ Keyframe &frame = m_frames.at(i);
+
+ current.setRight(frame);
+
+ if (current.containsX(coord.x() - radius) ||
+ current.containsX(coord.x()) ||
+ current.containsX(coord.x() + radius)) {
+ influencer.push_back(current);
+ }
+
+ if (frame.position().x() > coord.x() + radius)
+ break;
+
+ current.setLeft(frame);
+ }
+
+ for (auto &segment : influencer) {
+ for (auto &y : segment.yForX(coord.x())) {
+ QLineF line(coord.x(), y, coord.x(), coord.y());
+ if (line.length() < radius)
+ return true;
+ }
+
+ for (auto &x : segment.xForY(coord.y())) {
+ QLineF line(x, coord.y(), coord.x(), coord.y());
+ if (line.length() < radius)
+ return true;
+ }
+ }
+ return false;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/animationcurve.h b/src/plugins/qmldesigner/components/curveeditor/animationcurve.h
new file mode 100644
index 0000000000..0533e479a1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/animationcurve.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "keyframe.h"
+
+#include <vector>
+
+namespace DesignTools {
+
+class AnimationCurve
+{
+public:
+ AnimationCurve();
+
+ AnimationCurve(const std::vector<Keyframe> &frames);
+
+ bool isValid() const;
+
+ double minimumTime() const;
+
+ double maximumTime() const;
+
+ double minimumValue() const;
+
+ double maximumValue() const;
+
+ std::vector<Keyframe> keyframes() const;
+
+ std::vector<QPointF> extrema() const;
+
+ std::vector<double> yForX(double x) const;
+
+ std::vector<double> xForY(double y, uint segment) const;
+
+ bool intersects(const QPointF &coord, double radius);
+
+private:
+ std::vector<Keyframe> m_frames;
+
+ double m_minY;
+
+ double m_maxY;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
new file mode 100644
index 0000000000..4eba31c6bd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditor.h"
+#include "curveeditormodel.h"
+#include "detail/curveitem.h"
+#include "detail/graphicsview.h"
+#include "detail/treeview.h"
+
+#include <QHBoxLayout>
+#include <QSplitter>
+
+namespace DesignTools {
+
+CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
+ : QWidget(parent)
+ , m_tree(new TreeView(model, this))
+ , m_view(new GraphicsView(model))
+{
+ QSplitter *splitter = new QSplitter;
+ splitter->addWidget(m_tree);
+ splitter->addWidget(m_view);
+ splitter->setStretchFactor(1, 2);
+
+ QHBoxLayout *box = new QHBoxLayout;
+ box->addWidget(splitter);
+ setLayout(box);
+
+ connect(m_tree, &TreeView::curvesSelected, m_view, &GraphicsView::reset);
+}
+
+void CurveEditor::zoomX(double zoom)
+{
+ m_view->setZoomX(zoom);
+}
+
+void CurveEditor::zoomY(double zoom)
+{
+ m_view->setZoomY(zoom);
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.h b/src/plugins/qmldesigner/components/curveeditor/curveeditor.h
new file mode 100644
index 0000000000..a2c5873be0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QWidget>
+
+namespace DesignTools {
+
+class CurveEditorModel;
+class GraphicsView;
+class TreeView;
+
+class CurveEditor : public QWidget
+{
+ Q_OBJECT
+
+public:
+ CurveEditor(CurveEditorModel *model, QWidget *parent = nullptr);
+
+ void zoomX(double zoom);
+
+ void zoomY(double zoom);
+
+private:
+ TreeView *m_tree;
+
+ GraphicsView *m_view;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.pri b/src/plugins/qmldesigner/components/curveeditor/curveeditor.pri
new file mode 100644
index 0000000000..31ffe5d818
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.pri
@@ -0,0 +1,46 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/animationcurve.h \
+ $$PWD/curveeditor.h \
+ $$PWD/curveeditormodel.h \
+ $$PWD/detail/colorcontrol.h \
+ $$PWD/detail/curveeditorstyledialog.h \
+ $$PWD/detail/curveitem.h \
+ $$PWD/detail/curvesegment.h \
+ $$PWD/detail/graphicsscene.h \
+ $$PWD/detail/graphicsview.h \
+ $$PWD/detail/handleitem.h \
+ $$PWD/detail/keyframeitem.h \
+ $$PWD/detail/playhead.h \
+ $$PWD/detail/selectableitem.h \
+ $$PWD/detail/selector.h \
+ $$PWD/detail/shortcut.h \
+ $$PWD/detail/treeitemdelegate.h \
+ $$PWD/detail/treemodel.h \
+ $$PWD/detail/treeview.h \
+ $$PWD/keyframe.h \
+ $$PWD/treeitem.h
+
+SOURCES += \
+ $$PWD/animationcurve.cpp \
+ $$PWD/curveeditor.cpp \
+ $$PWD/curveeditormodel.cpp \
+ $$PWD/detail/colorcontrol.cpp \
+ $$PWD/detail/curveeditorstyledialog.cpp \
+ $$PWD/detail/curveitem.cpp \
+ $$PWD/detail/curvesegment.cpp \
+ $$PWD/detail/graphicsscene.cpp \
+ $$PWD/detail/graphicsview.cpp \
+ $$PWD/detail/handleitem.cpp \
+ $$PWD/detail/keyframeitem.cpp \
+ $$PWD/detail/playhead.cpp \
+ $$PWD/detail/selectableitem.cpp \
+ $$PWD/detail/selector.cpp \
+ $$PWD/detail/shortcut.cpp \
+ $$PWD/detail/treeitemdelegate.cpp \
+ $$PWD/detail/treemodel.cpp \
+ $$PWD/detail/treeview.cpp \
+ $$PWD/detail/utils.cpp \
+ $$PWD/keyframe.cpp \
+ $$PWD/treeitem.cpp
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
new file mode 100644
index 0000000000..3b8b26b763
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditormodel.h"
+#include "treeitem.h"
+#include "detail/graphicsview.h"
+
+namespace DesignTools {
+
+CurveEditorModel::CurveEditorModel(QObject *parent)
+ : TreeModel(parent)
+{}
+
+CurveEditorModel::~CurveEditorModel() {}
+
+
+void CurveEditorModel::setCurrentFrame(int frame)
+{
+ if (graphicsView())
+ graphicsView()->setCurrentFrame(frame);
+}
+
+void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve)
+{
+ if (TreeItem *item = find(id)) {
+ if (PropertyTreeItem *propertyItem = item->asPropertyItem()) {
+ propertyItem->setCurve(curve);
+ emit curveChanged(propertyItem);
+ }
+ }
+}
+
+void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
+{
+ beginResetModel();
+
+ initialize();
+
+ unsigned int counter = 0;
+ for (auto *item : items) {
+ item->setId(++counter);
+ root()->addChild(item);
+ }
+
+ endResetModel();
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h
new file mode 100644
index 0000000000..6e212d4c6a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "detail/treemodel.h"
+
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+class QPointF;
+QT_END_NAMESPACE
+
+namespace DesignTools {
+
+struct CurveEditorStyle;
+
+class AnimationCurve;
+class PropertyTreeItem;
+class TreeItem;
+
+class CurveEditorModel : public TreeModel
+{
+ Q_OBJECT
+
+signals:
+ void currentFrameChanged(int frame);
+
+ void curveChanged(PropertyTreeItem *item);
+
+public:
+ virtual double minimumTime() const = 0;
+
+ virtual double maximumTime() const = 0;
+
+ virtual CurveEditorStyle style() const = 0;
+
+public:
+ CurveEditorModel(QObject *parent = nullptr);
+
+ ~CurveEditorModel() override;
+
+ void setCurrentFrame(int frame);
+
+ void setCurve(unsigned int id, const AnimationCurve &curve);
+
+ void reset(const std::vector<TreeItem *> &items);
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h b/src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h
new file mode 100644
index 0000000000..03ea11c8c1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "detail/shortcut.h"
+
+#include <QBitmap>
+#include <QBrush>
+#include <QColor>
+#include <QDialog>
+#include <QIcon>
+#include <QKeySequence>
+
+namespace DesignTools {
+
+struct TreeItemStyleOption
+{
+ double margins;
+ QIcon pinnedIcon = QIcon(":/ICON_PINNED");
+ QIcon unpinnedIcon = QIcon(":/ICON_UNPINNED");
+ QIcon lockedIcon = QIcon(":/ICON_LOCKED");
+ QIcon unlockedIcon = QIcon(":/ICON_UNLOCKED");
+};
+
+struct HandleItemStyleOption
+{
+ double size = 10.0;
+ double lineWidth = 1.0;
+ QColor color = QColor(200, 0, 0);
+ QColor selectionColor = QColor(200, 200, 200);
+};
+
+struct KeyframeItemStyleOption
+{
+ double size = 10.0;
+ QColor color = QColor(200, 200, 0);
+ QColor selectionColor = QColor(200, 200, 200);
+};
+
+struct CurveItemStyleOption
+{
+ double width = 1.0;
+ QColor color = QColor(0, 200, 0);
+ QColor selectionColor = QColor(200, 200, 200);
+};
+
+struct PlayheadStyleOption
+{
+ double width = 20.0;
+ double radius = 4.0;
+ QColor color = QColor(200, 200, 0);
+};
+
+struct Shortcuts
+{
+ Shortcut newSelection = Shortcut(Qt::LeftButton);
+ Shortcut addToSelection = Shortcut(Qt::LeftButton, Qt::ControlModifier | Qt::ShiftModifier);
+ Shortcut removeFromSelection = Shortcut(Qt::LeftButton, Qt::ShiftModifier);
+ Shortcut toggleSelection = Shortcut(Qt::LeftButton, Qt::ControlModifier);
+
+ Shortcut zoom = Shortcut(Qt::RightButton, Qt::AltModifier);
+ Shortcut pan = Shortcut(Qt::MiddleButton, Qt::AltModifier);
+ Shortcut frameAll = Shortcut(Qt::NoModifier, Qt::Key_A);
+};
+
+struct CurveEditorStyle
+{
+ Shortcuts shortcuts;
+
+ QBrush backgroundBrush = QBrush(QColor(5, 0, 100));
+ QBrush backgroundAlternateBrush = QBrush(QColor(0, 0, 50));
+ QColor fontColor = QColor(200, 200, 200);
+ QColor gridColor = QColor(128, 128, 128);
+ double canvasMargin = 5.0;
+ int zoomInWidth = 100;
+ int zoomInHeight = 100;
+ double timeAxisHeight = 40.0;
+ double timeOffsetLeft = 10.0;
+ double timeOffsetRight = 10.0;
+ QColor rangeBarColor = QColor(128, 128, 128);
+ QColor rangeBarCapsColor = QColor(50, 50, 255);
+ double valueAxisWidth = 60.0;
+ double valueOffsetTop = 10.0;
+ double valueOffsetBottom = 10.0;
+
+ HandleItemStyleOption handleStyle;
+ KeyframeItemStyleOption keyframeStyle;
+ CurveItemStyleOption curveStyle;
+ TreeItemStyleOption treeItemStyle;
+ PlayheadStyleOption playhead;
+};
+
+inline QPixmap pixmapFromIcon(const QIcon &icon, const QSize &size, const QColor &color)
+{
+ QPixmap pixmap = icon.pixmap(size);
+ QPixmap mask(pixmap.size());
+ mask.fill(color);
+ mask.setMask(pixmap.createMaskFromColor(Qt::transparent));
+ return mask;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp
new file mode 100644
index 0000000000..a833a4c6ff
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "colorcontrol.h"
+
+#include <QColorDialog>
+#include <QEvent>
+#include <QHelpEvent>
+#include <QPainter>
+#include <QToolTip>
+
+namespace DesignTools {
+
+ColorControl::ColorControl()
+ : QWidget(nullptr)
+ , m_color(Qt::black)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ setFixedHeight(20);
+}
+
+ColorControl::ColorControl(const QColor &color, QWidget *parent)
+ : QWidget(parent)
+ , m_color(color)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ setFixedHeight(20);
+}
+
+ColorControl::~ColorControl() = default;
+
+QColor ColorControl::value() const
+{
+ return m_color;
+}
+
+void ColorControl::setValue(const QColor &val)
+{
+ m_color = val;
+}
+
+bool ColorControl::event(QEvent *event)
+{
+ if (event->type() == QEvent::ToolTip) {
+ if (auto helpEvent = static_cast<const QHelpEvent *>(event)) {
+ QToolTip::showText(helpEvent->globalPos(), m_color.name());
+ return true;
+ }
+ }
+ return QWidget::event(event);
+}
+
+void ColorControl::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(this);
+ painter.fillRect(event->rect(), m_color);
+}
+
+void ColorControl::mouseReleaseEvent(QMouseEvent *event)
+{
+ QColor color = QColorDialog::getColor(m_color, this);
+
+ event->accept();
+
+ if (color != m_color) {
+ m_color = color;
+ update();
+ emit valueChanged();
+ }
+}
+
+void ColorControl::mousePressEvent(QMouseEvent *event)
+{
+ // Required if embedded in a QGraphicsProxywidget
+ // in order to call mouseRelease properly.
+ QWidget::mousePressEvent(event);
+ event->accept();
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.h b/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.h
new file mode 100644
index 0000000000..54dfe194f8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/colorcontrol.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QWidget>
+
+namespace DesignTools {
+
+class ColorControl : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ColorControl();
+
+ ColorControl(const QColor &color, QWidget *parent = nullptr);
+
+ ~ColorControl() override;
+
+ QColor value() const;
+
+ void setValue(const QColor &val);
+
+protected:
+ bool event(QEvent *event) override;
+
+ void paintEvent(QPaintEvent *event) override;
+
+ void mouseReleaseEvent(QMouseEvent *event) override;
+
+ void mousePressEvent(QMouseEvent *event) override;
+
+signals:
+ void valueChanged();
+
+private:
+ QColor m_color;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp
new file mode 100644
index 0000000000..a8b653a74d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditorstyledialog.h"
+#include "colorcontrol.h"
+#include "curveeditorstyle.h"
+
+#include <QDebug>
+#include <QDoubleSpinBox>
+#include <QLabel>
+#include <QPushButton>
+#include <QSpinBox>
+#include <QVBoxLayout>
+
+namespace DesignTools {
+
+QHBoxLayout *createRow(const QString &title, QWidget *widget)
+{
+ auto *label = new QLabel(title);
+ label->setFixedWidth(200);
+ label->setAlignment(Qt::AlignRight);
+
+ auto *box = new QHBoxLayout;
+ box->addWidget(label);
+ box->addWidget(widget);
+ return box;
+}
+
+CurveEditorStyleDialog::CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent)
+ : QDialog(parent)
+ , m_printButton(new QPushButton("Print"))
+ , m_background(new ColorControl(style.backgroundBrush.color()))
+ , m_backgroundAlternate(new ColorControl(style.backgroundAlternateBrush.color()))
+ , m_fontColor(new ColorControl(style.fontColor))
+ , m_gridColor(new ColorControl(style.gridColor))
+ , m_canvasMargin(new QDoubleSpinBox())
+ , m_zoomInWidth(new QSpinBox())
+ , m_zoomInHeight(new QSpinBox())
+ , m_timeAxisHeight(new QDoubleSpinBox())
+ , m_timeOffsetLeft(new QDoubleSpinBox())
+ , m_timeOffsetRight(new QDoubleSpinBox())
+ , m_rangeBarColor(new ColorControl(style.rangeBarCapsColor))
+ , m_rangeBarCapsColor(new ColorControl(style.rangeBarCapsColor))
+ , m_valueAxisWidth(new QDoubleSpinBox())
+ , m_valueOffsetTop(new QDoubleSpinBox())
+ , m_valueOffsetBottom(new QDoubleSpinBox())
+ , m_handleSize(new QDoubleSpinBox())
+ , m_handleLineWidth(new QDoubleSpinBox())
+ , m_handleColor(new ColorControl(style.handleStyle.color))
+ , m_handleSelectionColor(new ColorControl(style.handleStyle.selectionColor))
+ , m_keyframeSize(new QDoubleSpinBox())
+ , m_keyframeColor(new ColorControl(style.keyframeStyle.color))
+ , m_keyframeSelectionColor(new ColorControl(style.keyframeStyle.selectionColor))
+ , m_curveWidth(new QDoubleSpinBox())
+ , m_curveColor(new ColorControl(style.curveStyle.color))
+ , m_curveSelectionColor(new ColorControl(style.curveStyle.selectionColor))
+ , m_treeMargins(new QDoubleSpinBox())
+ , m_playheadWidth(new QDoubleSpinBox())
+ , m_playheadRadius(new QDoubleSpinBox())
+ , m_playheadColor(new ColorControl(style.playhead.color))
+
+{
+ m_canvasMargin->setValue(style.canvasMargin);
+ m_zoomInWidth->setValue(style.zoomInWidth);
+ m_zoomInHeight->setValue(style.zoomInHeight);
+ m_zoomInHeight->setMaximum(9000);
+
+ m_timeAxisHeight->setValue(style.timeAxisHeight);
+ m_timeOffsetLeft->setValue(style.timeOffsetLeft);
+ m_timeOffsetRight->setValue(style.timeOffsetRight);
+ m_valueAxisWidth->setValue(style.valueAxisWidth);
+ m_valueOffsetTop->setValue(style.valueOffsetTop);
+ m_valueOffsetBottom->setValue(style.valueOffsetBottom);
+ m_handleSize->setValue(style.handleStyle.size);
+ m_handleLineWidth->setValue(style.handleStyle.lineWidth);
+ m_keyframeSize->setValue(style.keyframeStyle.size);
+ m_curveWidth->setValue(style.curveStyle.width);
+ m_treeMargins->setValue(style.treeItemStyle.margins);
+ m_playheadWidth->setValue(style.playhead.width);
+ m_playheadRadius->setValue(style.playhead.radius);
+
+ connect(m_printButton, &QPushButton::released, this, &CurveEditorStyleDialog::printStyle);
+
+ auto intChanged = [this](int) { emitStyleChanged(); };
+ auto doubleChanged = [this](double) { emitStyleChanged(); };
+ auto colorChanged = [this]() { emitStyleChanged(); };
+
+ auto intSignal = static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
+ auto doubleSignal = static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged);
+
+ connect(m_background, &ColorControl::valueChanged, colorChanged);
+ connect(m_backgroundAlternate, &ColorControl::valueChanged, colorChanged);
+ connect(m_fontColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_gridColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_canvasMargin, doubleSignal, doubleChanged);
+ connect(m_zoomInWidth, intSignal, intChanged);
+ connect(m_zoomInHeight, intSignal, intChanged);
+ connect(m_timeAxisHeight, doubleSignal, doubleChanged);
+ connect(m_timeOffsetLeft, doubleSignal, doubleChanged);
+ connect(m_timeOffsetRight, doubleSignal, doubleChanged);
+ connect(m_rangeBarColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_rangeBarCapsColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_valueAxisWidth, doubleSignal, doubleChanged);
+ connect(m_valueOffsetTop, doubleSignal, doubleChanged);
+ connect(m_valueOffsetBottom, doubleSignal, doubleChanged);
+ connect(m_handleSize, doubleSignal, doubleChanged);
+ connect(m_handleLineWidth, doubleSignal, doubleChanged);
+ connect(m_handleColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_handleSelectionColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_keyframeSize, doubleSignal, doubleChanged);
+ connect(m_keyframeColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_keyframeSelectionColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_curveWidth, doubleSignal, doubleChanged);
+ connect(m_curveColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_curveSelectionColor, &ColorControl::valueChanged, colorChanged);
+ connect(m_treeMargins, doubleSignal, doubleChanged);
+ connect(m_playheadWidth, doubleSignal, doubleChanged);
+ connect(m_playheadRadius, doubleSignal, doubleChanged);
+ connect(m_playheadColor, &ColorControl::valueChanged, colorChanged);
+
+ auto *box = new QVBoxLayout;
+ box->addLayout(createRow("Background Color", m_background));
+ box->addLayout(createRow("Alternate Background Color", m_backgroundAlternate));
+ box->addLayout(createRow("Font Color", m_fontColor));
+ box->addLayout(createRow("Grid Color", m_gridColor));
+ box->addLayout(createRow("Canvas Margin", m_canvasMargin));
+ box->addLayout(createRow("Zoom In Width", m_zoomInWidth));
+ box->addLayout(createRow("Zoom In Height", m_zoomInHeight));
+ box->addLayout(createRow("Time Axis Height", m_timeAxisHeight));
+ box->addLayout(createRow("Time Axis Left Offset", m_timeOffsetLeft));
+ box->addLayout(createRow("Time Axis Right Offset", m_timeOffsetRight));
+ box->addLayout(createRow("Range Bar Color", m_rangeBarColor));
+ box->addLayout(createRow("Range Bar Caps Color", m_rangeBarCapsColor));
+ box->addLayout(createRow("Value Axis Width", m_valueAxisWidth));
+ box->addLayout(createRow("Value Axis Top Offset", m_valueOffsetTop));
+ box->addLayout(createRow("Value Axis Bottom Offset", m_valueOffsetBottom));
+ box->addLayout(createRow("Handle Size", m_handleSize));
+ box->addLayout(createRow("Handle Line Width", m_handleLineWidth));
+ box->addLayout(createRow("Handle Color", m_handleColor));
+ box->addLayout(createRow("Handle Selection Color", m_handleSelectionColor));
+ box->addLayout(createRow("Keyframe Size", m_keyframeSize));
+ box->addLayout(createRow("Keyframe Color", m_keyframeColor));
+ box->addLayout(createRow("Keyframe Selection Color", m_keyframeSelectionColor));
+ box->addLayout(createRow("Curve Width", m_curveWidth));
+ box->addLayout(createRow("Curve Color", m_curveColor));
+ box->addLayout(createRow("Curve Selection Color", m_curveSelectionColor));
+ box->addLayout(createRow("Treeview margins", m_treeMargins));
+ box->addLayout(createRow("Playhead width", m_playheadWidth));
+ box->addLayout(createRow("Playhead radius", m_playheadRadius));
+ box->addLayout(createRow("Playhead color", m_playheadColor));
+
+ box->addWidget(m_printButton);
+ setLayout(box);
+}
+
+CurveEditorStyle CurveEditorStyleDialog::style() const
+{
+ CurveEditorStyle style;
+ style.backgroundBrush = QBrush(m_background->value());
+ style.backgroundAlternateBrush = QBrush(m_backgroundAlternate->value());
+ style.fontColor = m_fontColor->value();
+ style.gridColor = m_gridColor->value();
+ style.canvasMargin = m_canvasMargin->value();
+ style.zoomInWidth = m_zoomInWidth->value();
+ style.zoomInHeight = m_zoomInHeight->value();
+ style.timeAxisHeight = m_timeAxisHeight->value();
+ style.timeOffsetLeft = m_timeOffsetLeft->value();
+ style.timeOffsetRight = m_timeOffsetRight->value();
+ style.rangeBarColor = m_rangeBarColor->value();
+ style.rangeBarCapsColor = m_rangeBarCapsColor->value();
+ style.valueAxisWidth = m_valueAxisWidth->value();
+ style.valueOffsetTop = m_valueOffsetTop->value();
+ style.valueOffsetBottom = m_valueOffsetBottom->value();
+ style.handleStyle.size = m_handleSize->value();
+ style.handleStyle.lineWidth = m_handleLineWidth->value();
+ style.handleStyle.color = m_handleColor->value();
+ style.handleStyle.selectionColor = m_handleSelectionColor->value();
+ style.keyframeStyle.size = m_keyframeSize->value();
+ style.keyframeStyle.color = m_keyframeColor->value();
+ style.keyframeStyle.selectionColor = m_keyframeSelectionColor->value();
+ style.curveStyle.width = m_curveWidth->value();
+ style.curveStyle.color = m_curveColor->value();
+ style.curveStyle.selectionColor = m_curveSelectionColor->value();
+ style.treeItemStyle.margins = m_treeMargins->value();
+ style.playhead.width = m_playheadWidth->value();
+ style.playhead.radius = m_playheadRadius->value();
+ style.playhead.color = m_playheadColor->value();
+
+ return style;
+}
+
+void CurveEditorStyleDialog::emitStyleChanged()
+{
+ emit styleChanged(style());
+}
+
+void CurveEditorStyleDialog::printStyle()
+{
+ auto toString = [](const QColor &color) {
+ QString tmp
+ = QString("QColor(%1, %2, %3)").arg(color.red()).arg(color.green()).arg(color.blue());
+ return qPrintable(tmp);
+ };
+
+ CurveEditorStyle s = style();
+ qDebug() << "";
+ qDebug().nospace() << "CurveEditorStyle out;";
+ qDebug().nospace() << "out.backgroundBrush = QBrush(" << toString(s.backgroundBrush.color())
+ << ");";
+ qDebug().nospace() << "out.backgroundAlternateBrush = QBrush("
+ << toString(s.backgroundAlternateBrush.color()) << ");";
+ qDebug().nospace() << "out.fontColor = " << toString(s.fontColor) << ";";
+ qDebug().nospace() << "out.gridColor = " << toString(s.gridColor) << ";";
+ qDebug().nospace() << "out.canvasMargin = " << s.canvasMargin << ";";
+ qDebug().nospace() << "out.zoomInWidth = " << s.zoomInWidth << ";";
+ qDebug().nospace() << "out.zoomInHeight = " << s.zoomInHeight << ";";
+ qDebug().nospace() << "out.timeAxisHeight = " << s.timeAxisHeight << ";";
+ qDebug().nospace() << "out.timeOffsetLeft = " << s.timeOffsetLeft << ";";
+ qDebug().nospace() << "out.timeOffsetRight = " << s.timeOffsetRight << ";";
+ qDebug().nospace() << "out.rangeBarColor = " << toString(s.rangeBarColor) << ";";
+ qDebug().nospace() << "out.rangeBarCapsColor = " << toString(s.rangeBarCapsColor) << ";";
+ qDebug().nospace() << "out.valueAxisWidth = " << s.valueAxisWidth << ";";
+ qDebug().nospace() << "out.valueOffsetTop = " << s.valueOffsetTop << ";";
+ qDebug().nospace() << "out.valueOffsetBottom = " << s.valueOffsetBottom << ";";
+ qDebug().nospace() << "out.handleStyle.size = " << s.handleStyle.size << ";";
+ qDebug().nospace() << "out.handleStyle.lineWidth = " << s.handleStyle.lineWidth << ";";
+ qDebug().nospace() << "out.handleStyle.color = " << toString(s.handleStyle.color) << ";";
+ qDebug().nospace() << "out.handleStyle.selectionColor = "
+ << toString(s.handleStyle.selectionColor) << ";";
+ qDebug().nospace() << "out.keyframeStyle.size = " << s.keyframeStyle.size << ";";
+ qDebug().nospace() << "out.keyframeStyle.color = " << toString(s.keyframeStyle.color) << ";";
+ qDebug().nospace() << "out.keyframeStyle.selectionColor = "
+ << toString(s.keyframeStyle.selectionColor) << ";";
+ qDebug().nospace() << "out.curveStyle.width = " << s.curveStyle.width << ";";
+ qDebug().nospace() << "out.curveStyle.color = " << toString(s.curveStyle.color) << ";";
+ qDebug().nospace() << "out.curveStyle.selectionColor = "
+ << toString(s.curveStyle.selectionColor) << ";";
+ qDebug().nospace() << "out.treeItemStyle.margins = " << s.treeItemStyle.margins << ";";
+ qDebug().nospace() << "out.playheadStyle.width = " << s.playhead.width << ";";
+ qDebug().nospace() << "out.playheadStyle.radius = " << s.playhead.radius << ";";
+ qDebug().nospace() << "out.playheadStyle.color = " << toString(s.playhead.color) << ";";
+ qDebug().nospace() << "return out;";
+ qDebug() << "";
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.h b/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.h
new file mode 100644
index 0000000000..f1dc3bc372
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.h
@@ -0,0 +1,127 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QDialog>
+
+QT_BEGIN_NAMESPACE
+class QPushButton;
+class QSpinBox;
+class QDoubleSpinBox;
+QT_END_NAMESPACE
+
+namespace DesignTools {
+
+class ColorControl;
+
+struct CurveEditorStyle;
+
+class CurveEditorStyleDialog : public QDialog
+{
+ Q_OBJECT
+
+signals:
+ void styleChanged(const CurveEditorStyle &style);
+
+public:
+ CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent = nullptr);
+
+ CurveEditorStyle style() const;
+
+private:
+ void emitStyleChanged();
+
+ void printStyle();
+
+private:
+ QPushButton *m_printButton;
+
+ ColorControl *m_background;
+
+ ColorControl *m_backgroundAlternate;
+
+ ColorControl *m_fontColor;
+
+ ColorControl *m_gridColor;
+
+ QDoubleSpinBox *m_canvasMargin;
+
+ QSpinBox *m_zoomInWidth;
+
+ QSpinBox *m_zoomInHeight;
+
+ QDoubleSpinBox *m_timeAxisHeight;
+
+ QDoubleSpinBox *m_timeOffsetLeft;
+
+ QDoubleSpinBox *m_timeOffsetRight;
+
+ ColorControl *m_rangeBarColor;
+
+ ColorControl *m_rangeBarCapsColor;
+
+ QDoubleSpinBox *m_valueAxisWidth;
+
+ QDoubleSpinBox *m_valueOffsetTop;
+
+ QDoubleSpinBox *m_valueOffsetBottom;
+
+ // HandleItem
+ QDoubleSpinBox *m_handleSize;
+
+ QDoubleSpinBox *m_handleLineWidth;
+
+ ColorControl *m_handleColor;
+
+ ColorControl *m_handleSelectionColor;
+
+ // KeyframeItem
+ QDoubleSpinBox *m_keyframeSize;
+
+ ColorControl *m_keyframeColor;
+
+ ColorControl *m_keyframeSelectionColor;
+
+ // CurveItem
+ QDoubleSpinBox *m_curveWidth;
+
+ ColorControl *m_curveColor;
+
+ ColorControl *m_curveSelectionColor;
+
+ // TreeItem
+ QDoubleSpinBox *m_treeMargins;
+
+ // Playhead
+ QDoubleSpinBox *m_playheadWidth;
+
+ QDoubleSpinBox *m_playheadRadius;
+
+ ColorControl *m_playheadColor;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp
new file mode 100644
index 0000000000..38efd29571
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveitem.h"
+#include "animationcurve.h"
+#include "graphicsscene.h"
+#include "keyframeitem.h"
+#include "utils.h"
+
+#include <QPainter>
+#include <QPainterPath>
+
+#include <cmath>
+
+namespace DesignTools {
+
+CurveItem::CurveItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , m_id(0)
+ , m_style()
+ , m_transform()
+ , m_keyframes()
+ , m_underMouse(false)
+ , m_itemDirty(false)
+ , m_pathDirty(true)
+{}
+
+CurveItem::CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , m_id(id)
+ , m_style()
+ , m_transform()
+ , m_keyframes()
+ , m_underMouse(false)
+ , m_itemDirty(false)
+ , m_pathDirty(true)
+{
+ setAcceptHoverEvents(true);
+
+ setFlag(QGraphicsItem::ItemIsMovable, false);
+
+ auto emitCurveChanged = [this]() {
+ m_itemDirty = true;
+ m_pathDirty = true;
+ update();
+ };
+
+ for (auto frame : curve.keyframes()) {
+ auto *item = new KeyframeItem(frame, this);
+ QObject::connect(item, &KeyframeItem::redrawCurve, emitCurveChanged);
+ m_keyframes.push_back(item);
+ }
+}
+
+CurveItem::~CurveItem() {}
+
+int CurveItem::type() const
+{
+ return Type;
+}
+
+QRectF CurveItem::boundingRect() const
+{
+ auto bbox = [](QRectF &bounds, const Keyframe &frame) {
+ grow(bounds, frame.position());
+ grow(bounds, frame.leftHandle());
+ grow(bounds, frame.rightHandle());
+ };
+
+ QRectF bounds;
+ for (auto *item : m_keyframes)
+ bbox(bounds, item->keyframe());
+
+ return m_transform.mapRect(bounds);
+}
+
+bool CurveItem::contains(const QPointF &point) const
+{
+ bool valid = false;
+ QPointF transformed(m_transform.inverted(&valid).map(point));
+
+ double width = std::abs(20.0 / scaleY(m_transform));
+
+ if (valid)
+ return curve().intersects(transformed, width);
+
+ return false;
+}
+
+void CurveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (m_keyframes.size() > 1) {
+ QPen pen = painter->pen();
+ QColor col = m_underMouse ? Qt::red : m_style.color;
+
+ pen.setWidthF(m_style.width);
+ pen.setColor(hasSelection() ? m_style.selectionColor : col);
+
+ painter->save();
+ painter->setPen(pen);
+ painter->drawPath(path());
+
+ painter->restore();
+ }
+}
+
+bool CurveItem::isDirty() const
+{
+ return m_itemDirty;
+}
+
+bool CurveItem::hasSelection() const
+{
+ for (auto *frame : m_keyframes) {
+ if (frame->selected())
+ return true;
+ }
+
+ return false;
+}
+
+unsigned int CurveItem::id() const
+{
+ return m_id;
+}
+
+QPainterPath CurveItem::path() const
+{
+ if (m_pathDirty) {
+ Keyframe previous = m_keyframes.front()->keyframe();
+ Keyframe current;
+
+ m_path = QPainterPath(m_transform.map(previous.position()));
+ for (size_t i = 1; i < m_keyframes.size(); ++i) {
+ current = m_keyframes[i]->keyframe();
+
+ if (previous.rightHandle().isNull() || current.leftHandle().isNull()) {
+ m_path.lineTo(m_transform.map(current.position()));
+ } else {
+ m_path.cubicTo(
+ m_transform.map(previous.rightHandle()),
+ m_transform.map(current.leftHandle()),
+ m_transform.map(current.position()));
+ }
+
+ previous = current;
+ }
+ m_pathDirty = false;
+ }
+
+ return m_path;
+}
+
+AnimationCurve CurveItem::curve() const
+{
+ std::vector<Keyframe> out;
+ out.reserve(m_keyframes.size());
+ for (auto item : m_keyframes)
+ out.push_back(item->keyframe());
+
+ return out;
+}
+
+void CurveItem::setDirty(bool dirty)
+{
+ m_itemDirty = dirty;
+}
+
+QRectF CurveItem::setComponentTransform(const QTransform &transform)
+{
+ m_pathDirty = true;
+
+ prepareGeometryChange();
+ m_transform = transform;
+ for (auto frame : m_keyframes)
+ frame->setComponentTransform(transform);
+
+ return boundingRect();
+}
+
+void CurveItem::setStyle(const CurveEditorStyle &style)
+{
+ m_style = style.curveStyle;
+
+ for (auto *frame : m_keyframes)
+ frame->setStyle(style);
+}
+
+void CurveItem::connect(GraphicsScene *scene)
+{
+ for (auto *frame : m_keyframes) {
+ QObject::connect(frame, &KeyframeItem::keyframeMoved, scene, &GraphicsScene::keyframeMoved);
+ QObject::connect(frame, &KeyframeItem::handleMoved, scene, &GraphicsScene::handleMoved);
+ }
+}
+
+void CurveItem::setIsUnderMouse(bool under)
+{
+ if (under != m_underMouse) {
+ m_underMouse = under;
+ update();
+ }
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h
new file mode 100644
index 0000000000..90e68e20f1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curveitem.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditorstyle.h"
+#include "selectableitem.h"
+
+#include <QGraphicsObject>
+
+namespace DesignTools {
+
+class AnimationCurve;
+class KeyframeItem;
+class GraphicsScene;
+
+class CurveItem : public QGraphicsObject
+{
+ Q_OBJECT
+
+public:
+ CurveItem(QGraphicsItem *parent = nullptr);
+
+ CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent = nullptr);
+
+ ~CurveItem() override;
+
+ enum { Type = ItemTypeCurve };
+
+ int type() const override;
+
+ QRectF boundingRect() const override;
+
+ bool contains(const QPointF &point) const override;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
+
+ bool isDirty() const;
+
+ bool hasSelection() const;
+
+ unsigned int id() const;
+
+ AnimationCurve curve() const;
+
+ void setDirty(bool dirty);
+
+ QRectF setComponentTransform(const QTransform &transform);
+
+ void setStyle(const CurveEditorStyle &style);
+
+ void connect(GraphicsScene *scene);
+
+ void setIsUnderMouse(bool under);
+
+private:
+ QPainterPath path() const;
+
+ unsigned int m_id;
+
+ CurveItemStyleOption m_style;
+
+ QTransform m_transform;
+
+ std::vector<KeyframeItem *> m_keyframes;
+
+ bool m_underMouse;
+
+ bool m_itemDirty;
+
+ mutable bool m_pathDirty;
+
+ mutable QPainterPath m_path;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.cpp
new file mode 100644
index 0000000000..40f675f3ec
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curvesegment.h"
+#include "utils.h"
+
+#include <qmath.h>
+
+#include <assert.h>
+
+namespace DesignTools {
+
+class CubicPolynomial
+{
+public:
+ CubicPolynomial(double p0, double p1, double p2, double p3);
+
+ std::vector<double> extrema() const;
+
+ std::vector<double> roots() const;
+
+private:
+ double m_a;
+ double m_b;
+ double m_c;
+ double m_d;
+};
+
+CubicPolynomial::CubicPolynomial(double p0, double p1, double p2, double p3)
+ : m_a(p3 - 3.0 * p2 + 3.0 * p1 - p0)
+ , m_b(3.0 * p2 - 6.0 * p1 + 3.0 * p0)
+ , m_c(3.0 * p1 - 3.0 * p0)
+ , m_d(p0)
+{}
+
+std::vector<double> CubicPolynomial::extrema() const
+{
+ std::vector<double> out;
+
+ auto addValidValue = [&out](double value) {
+ if (!std::isnan(value) && !std::isinf(value))
+ out.push_back(clamp(value, 0.0, 1.0));
+ };
+
+ // Find the roots of the first derivative of y.
+ auto pd2 = (2.0 * m_b) / (3.0 * m_a) / 2.0;
+ auto q = m_c / (3.0 * m_a);
+
+ auto radi = std::pow(pd2, 2.0) - q;
+
+ auto x1 = -pd2 + std::sqrt(radi);
+ auto x2 = -pd2 - std::sqrt(radi);
+
+ addValidValue(x1);
+ addValidValue(x2);
+
+ return out;
+}
+
+std::vector<double> CubicPolynomial::roots() const
+{
+ std::vector<double> out;
+
+ auto addValidValue = [&out](double value) {
+ if (!(std::isnan(value) || std::isinf(value)))
+ out.push_back(value);
+ };
+
+ if (m_a == 0.0) {
+ // Linear
+ if (m_b == 0.0) {
+ if (m_c != 0.0)
+ out.push_back(-m_d / m_c);
+ // Quadratic
+ } else {
+ const double p = m_c / m_b / 2.0;
+ const double q = m_d / m_b;
+ addValidValue(-p + std::sqrt(std::pow(p, 2.0) - q));
+ addValidValue(-p - std::sqrt(std::pow(p, 2.0) - q));
+ }
+ // Cubic
+ } else {
+ const double p = 3.0 * m_a * m_c - std::pow(m_b, 2.0);
+ const double q = 2.0 * std::pow(m_b, 3.0) - 9.0 * m_a * m_b * m_c
+ + 27.0 * std::pow(m_a, 2.0) * m_d;
+
+ auto disc = std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0);
+
+ auto toX = [&](double y) { return (y - m_b) / (3.0 * m_a); };
+
+ // One real solution.
+ if (disc >= 0) {
+ auto u = (1.0 / 2.0)
+ * std::cbrt(-4.0 * q
+ + 4.0 * std::sqrt(std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0)));
+ auto v = (1.0 / 2.0)
+ * std::cbrt(-4.0 * q
+ - 4.0 * std::sqrt(std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0)));
+
+ addValidValue(toX(u + v));
+ // Three real solutions.
+ } else {
+ auto phi = acos(-q / (2 * std::sqrt(-std::pow(p, 3.0))));
+ auto y1 = std::sqrt(-p) * 2.0 * cos(phi / 3.0);
+ auto y2 = std::sqrt(-p) * 2.0 * cos((phi / 3.0) + (2.0 * M_PI / 3.0));
+ auto y3 = std::sqrt(-p) * 2.0 * cos((phi / 3.0) + (4.0 * M_PI / 3.0));
+
+ addValidValue(toX(y1));
+ addValidValue(toX(y2));
+ addValidValue(toX(y3));
+ }
+ }
+ return out;
+}
+
+CurveSegment::CurveSegment()
+ : m_left()
+ , m_right()
+{}
+
+CurveSegment::CurveSegment(const Keyframe &left, const Keyframe &right)
+ : m_left(left)
+ , m_right(right)
+{}
+
+bool CurveSegment::containsX(double x) const
+{
+ return m_left.position().x() <= x && m_right.position().x() >= x;
+}
+
+double evaluateForT(double t, double p0, double p1, double p2, double p3)
+{
+ assert(t >= 0. && t <= 1.);
+
+ const double it = 1.0 - t;
+
+ return p0 * std::pow(it, 3.0) + p1 * 3.0 * std::pow(it, 2.0) * t
+ + p2 * 3.0 * it * std::pow(t, 2.0) + p3 * std::pow(t, 3.0);
+}
+
+QPointF CurveSegment::evaluate(double t) const
+{
+ const double x = evaluateForT(
+ t,
+ m_left.position().x(),
+ m_left.rightHandle().x(),
+ m_right.leftHandle().x(),
+ m_right.position().x());
+
+ const double y = evaluateForT(
+ t,
+ m_left.position().y(),
+ m_left.rightHandle().y(),
+ m_right.leftHandle().y(),
+ m_right.position().y());
+
+ return QPointF(x, y);
+}
+
+std::vector<QPointF> CurveSegment::extrema() const
+{
+ std::vector<QPointF> out;
+
+ auto polynomial = CubicPolynomial(
+ m_left.position().y(),
+ m_left.rightHandle().y(),
+ m_right.leftHandle().y(),
+ m_right.position().y());
+
+ for (double t : polynomial.extrema()) {
+
+ const double x = evaluateForT(
+ t,
+ m_left.position().x(),
+ m_left.rightHandle().x(),
+ m_right.leftHandle().x(),
+ m_right.position().x());
+
+ const double y = evaluateForT(
+ t,
+ m_left.position().y(),
+ m_left.rightHandle().y(),
+ m_right.leftHandle().y(),
+ m_right.position().y());
+
+ out.push_back(QPointF(x, y));
+ }
+ return out;
+}
+
+std::vector<double> CurveSegment::yForX(double x) const
+{
+ std::vector<double> out;
+
+ auto polynomial = CubicPolynomial(
+ m_left.position().x() - x,
+ m_left.rightHandle().x() - x,
+ m_right.leftHandle().x() - x,
+ m_right.position().x() - x);
+
+ for (double t : polynomial.roots()) {
+ if (t < 0.0 || t > 1.0)
+ continue;
+
+ const double y = evaluateForT(
+ t,
+ m_left.position().y(),
+ m_left.rightHandle().y(),
+ m_right.leftHandle().y(),
+ m_right.position().y());
+
+ out.push_back(y);
+ }
+
+ return out;
+}
+
+std::vector<double> CurveSegment::xForY(double y) const
+{
+ std::vector<double> out;
+
+ auto polynomial = CubicPolynomial(
+ m_left.position().y() - y,
+ m_left.rightHandle().y() - y,
+ m_right.leftHandle().y() - y,
+ m_right.position().y() - y);
+
+ for (double t : polynomial.roots()) {
+ if (t < 0.0 || t > 1.0)
+ continue;
+
+ const double x = evaluateForT(
+ t,
+ m_left.position().x(),
+ m_left.rightHandle().x(),
+ m_right.leftHandle().x(),
+ m_right.position().x());
+
+ out.push_back(x);
+ }
+
+ return out;
+}
+
+void CurveSegment::setLeft(const Keyframe &frame)
+{
+ m_left = frame;
+}
+
+void CurveSegment::setRight(const Keyframe &frame)
+{
+ m_right = frame;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.h b/src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.h
new file mode 100644
index 0000000000..5dbce58bcc
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/curvesegment.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "keyframe.h"
+
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+class QPointF;
+QT_END_NAMESPACE
+
+namespace DesignTools {
+
+class CurveSegment
+{
+public:
+ CurveSegment();
+
+ CurveSegment(const Keyframe &first, const Keyframe &last);
+
+ bool containsX(double x) const;
+
+ QPointF evaluate(double t) const;
+
+ std::vector<QPointF> extrema() const;
+
+ std::vector<double> yForX(double x) const;
+
+ std::vector<double> xForY(double y) const;
+
+ void setLeft(const Keyframe &frame);
+
+ void setRight(const Keyframe &frame);
+
+private:
+ Keyframe m_left;
+
+ Keyframe m_right;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp
new file mode 100644
index 0000000000..096e57aafa
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "graphicsscene.h"
+#include "animationcurve.h"
+#include "curveitem.h"
+#include "graphicsview.h"
+#include "handleitem.h"
+
+#include <QGraphicsSceneMouseEvent>
+
+namespace DesignTools {
+
+GraphicsScene::GraphicsScene(QObject *parent)
+ : QGraphicsScene(parent)
+ , m_dirty(true)
+ , m_limits()
+{}
+
+bool GraphicsScene::empty() const
+{
+ return items().empty();
+}
+
+double GraphicsScene::minimumTime() const
+{
+ return limits().left();
+}
+
+double GraphicsScene::maximumTime() const
+{
+ return limits().right();
+}
+
+double GraphicsScene::minimumValue() const
+{
+ return limits().bottom();
+}
+
+double GraphicsScene::maximumValue() const
+{
+ return limits().top();
+}
+
+void GraphicsScene::addCurveItem(CurveItem *item)
+{
+ m_dirty = true;
+ addItem(item);
+ item->connect(this);
+}
+
+void GraphicsScene::setComponentTransform(const QTransform &transform)
+{
+ QRectF bounds;
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
+ bounds = bounds.united(curveItem->setComponentTransform(transform));
+ }
+
+ if (bounds.isNull()) {
+ if (GraphicsView *gview = graphicsView())
+ bounds = gview->defaultRasterRect();
+ }
+
+ if (bounds.isValid())
+ setSceneRect(bounds);
+}
+
+void GraphicsScene::keyframeMoved(KeyframeItem *movedItem, const QPointF &direction)
+{
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (item == movedItem)
+ continue;
+
+ if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
+ if (frameItem->selected())
+ frameItem->moveKeyframe(direction);
+ }
+ }
+}
+
+void GraphicsScene::handleMoved(KeyframeItem *frame,
+ HandleSlot handle,
+ double angle,
+ double deltaLength)
+{
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (item == frame)
+ continue;
+
+ if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
+ if (frameItem->selected())
+ frameItem->moveHandle(handle, angle, deltaLength);
+ }
+ }
+}
+
+void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
+{
+ QGraphicsScene::mouseMoveEvent(mouseEvent);
+
+ if (hasActiveItem())
+ return;
+
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
+ curveItem->setIsUnderMouse(curveItem->contains(mouseEvent->scenePos()));
+ }
+}
+
+void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
+{
+ QGraphicsScene::mouseReleaseEvent(mouseEvent);
+
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
+ if (curveItem->contains(mouseEvent->scenePos()))
+ curveItem->setSelected(true);
+
+ if (curveItem->isDirty()) {
+ emit curveChanged(curveItem->id(), curveItem->curve());
+ curveItem->setDirty(false);
+ m_dirty = true;
+ }
+ }
+ }
+}
+
+bool GraphicsScene::hasActiveKeyframe() const
+{
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (auto *kitem = qgraphicsitem_cast<KeyframeItem *>(item)) {
+ if (kitem->activated())
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GraphicsScene::hasActiveHandle() const
+{
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (auto *hitem = qgraphicsitem_cast<HandleItem *>(item)) {
+ if (hitem->activated())
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GraphicsScene::hasActiveItem() const
+{
+ return hasActiveKeyframe() || hasActiveHandle();
+}
+
+GraphicsView *GraphicsScene::graphicsView() const
+{
+ const QList<QGraphicsView *> viewList = views();
+ for (auto &&view : viewList) {
+ if (GraphicsView *gview = qobject_cast<GraphicsView *>(view))
+ return gview;
+ }
+ return nullptr;
+}
+
+QRectF GraphicsScene::limits() const
+{
+ if (m_dirty) {
+ QPointF min(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
+ QPointF max(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
+
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
+ auto curve = curveItem->curve();
+ if (min.x() > curve.minimumTime())
+ min.rx() = curve.minimumTime();
+
+ if (min.y() > curve.minimumValue())
+ min.ry() = curve.minimumValue();
+
+ if (max.x() < curve.maximumTime())
+ max.rx() = curve.maximumTime();
+
+ if (max.y() < curve.maximumValue())
+ max.ry() = curve.maximumValue();
+ }
+ }
+
+ m_limits = QRectF(QPointF(min.x(), max.y()), QPointF(max.x(), min.y()));
+ m_dirty = false;
+ }
+ return m_limits;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h
new file mode 100644
index 0000000000..981c326b5a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsscene.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "keyframeitem.h"
+
+#include <QGraphicsScene>
+
+namespace DesignTools {
+
+class AnimationCurve;
+class CurveItem;
+class GraphicsView;
+
+class GraphicsScene : public QGraphicsScene
+{
+ Q_OBJECT
+
+signals:
+ void curveChanged(unsigned int id, const AnimationCurve &curve);
+
+public:
+ GraphicsScene(QObject *parent = nullptr);
+
+ bool empty() const;
+
+ bool hasActiveKeyframe() const;
+
+ bool hasActiveHandle() const;
+
+ bool hasActiveItem() const;
+
+ double minimumTime() const;
+
+ double maximumTime() const;
+
+ double minimumValue() const;
+
+ double maximumValue() const;
+
+ void addCurveItem(CurveItem *item);
+
+ void setComponentTransform(const QTransform &transform);
+
+ void keyframeMoved(KeyframeItem *item, const QPointF &direction);
+
+ void handleMoved(KeyframeItem *frame, HandleSlot handle, double angle, double deltaLength);
+
+protected:
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
+
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
+
+private:
+ using QGraphicsScene::addItem;
+
+ GraphicsView *graphicsView() const;
+
+ QRectF limits() const;
+
+ mutable bool m_dirty;
+
+ mutable QRectF m_limits;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
new file mode 100644
index 0000000000..ae60888d1f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
@@ -0,0 +1,523 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "graphicsview.h"
+#include "curveeditormodel.h"
+#include "curveitem.h"
+#include "utils.h"
+
+#include <QAction>
+#include <QMenu>
+#include <QResizeEvent>
+#include <QScrollBar>
+
+#include <cmath>
+
+namespace DesignTools {
+
+GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
+ : QGraphicsView(parent)
+ , m_zoomX(0.0)
+ , m_zoomY(0.0)
+ , m_transform()
+ , m_scene()
+ , m_model(model)
+ , m_playhead(this)
+ , m_selector()
+ , m_style(model->style())
+ , m_dialog(m_style)
+{
+ model->setGraphicsView(this);
+
+ setScene(&m_scene);
+ setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
+ setResizeAnchor(QGraphicsView::NoAnchor);
+ setTransformationAnchor(QGraphicsView::NoAnchor);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+
+ connect(&m_dialog, &CurveEditorStyleDialog::styleChanged, this, &GraphicsView::setStyle);
+
+ auto itemSlot = [this](unsigned int id, const AnimationCurve &curve) {
+ applyZoom(m_zoomX, m_zoomY);
+ m_model->setCurve(id, curve);
+ };
+
+ connect(&m_scene, &GraphicsScene::curveChanged, itemSlot);
+
+ applyZoom(m_zoomX, m_zoomY);
+ update();
+}
+
+CurveEditorModel *GraphicsView::model() const
+{
+ return m_model;
+}
+
+CurveEditorStyle GraphicsView::editorStyle() const
+{
+ return m_style;
+}
+
+bool GraphicsView::hasActiveItem() const
+{
+ return m_scene.hasActiveItem();
+}
+
+bool GraphicsView::hasActiveHandle() const
+{
+ return m_scene.hasActiveHandle();
+}
+
+double GraphicsView::minimumTime() const
+{
+ bool check = m_model->minimumTime() < m_scene.minimumTime();
+ return check ? m_model->minimumTime() : m_scene.minimumTime();
+}
+
+double GraphicsView::maximumTime() const
+{
+ bool check = m_model->maximumTime() > m_scene.maximumTime();
+ return check ? m_model->maximumTime() : m_scene.maximumTime();
+}
+
+double GraphicsView::minimumValue() const
+{
+ return m_scene.empty() ? -1.0 : m_scene.minimumValue();
+}
+
+double GraphicsView::maximumValue() const
+{
+ return m_scene.empty() ? 1.0 : m_scene.maximumValue();
+}
+
+double GraphicsView::zoomX() const
+{
+ return m_zoomX;
+}
+
+double GraphicsView::zoomY() const
+{
+ return m_zoomY;
+}
+
+QRectF GraphicsView::canvasRect() const
+{
+ QRect r = viewport()->rect().adjusted(
+ m_style.valueAxisWidth + m_style.canvasMargin,
+ m_style.timeAxisHeight + m_style.canvasMargin,
+ -m_style.canvasMargin,
+ -m_style.canvasMargin);
+
+ return mapToScene(r).boundingRect();
+}
+
+QRectF GraphicsView::timeScaleRect() const
+{
+ QRect vp(viewport()->rect());
+ QPoint tl = vp.topLeft() + QPoint(m_style.valueAxisWidth, 0);
+ QPoint br = vp.topRight() + QPoint(0, m_style.timeAxisHeight);
+ return mapToScene(QRect(tl, br)).boundingRect();
+}
+
+QRectF GraphicsView::valueScaleRect() const
+{
+ QRect vp(viewport()->rect());
+ QPoint tl = vp.topLeft() + QPoint(0, m_style.timeAxisHeight);
+ QPoint br = vp.bottomLeft() + QPoint(m_style.valueAxisWidth, 0);
+ return mapToScene(QRect(tl, br)).boundingRect();
+}
+
+QRectF GraphicsView::defaultRasterRect() const
+{
+ QPointF topLeft(mapTimeToX(minimumTime()), mapValueToY(maximumValue()));
+ QPointF bottomRight(mapTimeToX(maximumTime()), mapValueToY(minimumValue()));
+ return QRectF(topLeft, bottomRight);
+}
+
+void GraphicsView::setStyle(const CurveEditorStyle &style)
+{
+ m_style = style;
+
+ const auto itemList = items();
+ for (auto *item : itemList) {
+ if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
+ curveItem->setStyle(style);
+ }
+
+ applyZoom(m_zoomX, m_zoomY);
+ viewport()->update();
+}
+
+void GraphicsView::setZoomX(double zoom, const QPoint &pivot)
+{
+ applyZoom(zoom, m_zoomY, pivot);
+ viewport()->update();
+}
+
+void GraphicsView::setZoomY(double zoom, const QPoint &pivot)
+{
+ applyZoom(m_zoomX, zoom, pivot);
+ viewport()->update();
+}
+
+void GraphicsView::setCurrentFrame(int frame)
+{
+ int clampedFrame = clamp(frame, m_model->minimumTime(), m_model->maximumTime());
+ m_playhead.moveToFrame(clampedFrame, this);
+ viewport()->update();
+}
+
+void GraphicsView::scrollContent(double x, double y)
+{
+ QScrollBar *hs = horizontalScrollBar();
+ QScrollBar *vs = verticalScrollBar();
+ hs->setValue(hs->value() + x);
+ vs->setValue(vs->value() + y);
+}
+
+void GraphicsView::reset(const std::vector<CurveItem *> &items)
+{
+ m_scene.clear();
+ for (auto *item : items)
+ m_scene.addCurveItem(item);
+
+ applyZoom(m_zoomX, m_zoomY);
+ viewport()->update();
+}
+
+void GraphicsView::resizeEvent(QResizeEvent *event)
+{
+ QGraphicsView::resizeEvent(event);
+ applyZoom(m_zoomX, m_zoomY);
+}
+
+void GraphicsView::keyPressEvent(QKeyEvent *event)
+{
+ Shortcut shortcut(event->modifiers(), static_cast<Qt::Key>(event->key()));
+ if (shortcut == m_style.shortcuts.frameAll)
+ applyZoom(0.0, 0.0);
+}
+
+void GraphicsView::mousePressEvent(QMouseEvent *event)
+{
+ if (m_playhead.mousePress(globalToScene(event->globalPos())))
+ return;
+
+ Shortcut shortcut(event);
+ if (shortcut == Shortcut(Qt::LeftButton)) {
+ QPointF pos = mapToScene(event->pos());
+ if (timeScaleRect().contains(pos)) {
+ setCurrentFrame(std::round(mapXtoTime(pos.x())));
+ event->accept();
+ return;
+ }
+ }
+
+ QGraphicsView::mousePressEvent(event);
+
+ m_selector.mousePress(event, this);
+}
+
+void GraphicsView::mouseMoveEvent(QMouseEvent *event)
+{
+ if (m_playhead.mouseMove(globalToScene(event->globalPos()), this))
+ return;
+
+ QGraphicsView::mouseMoveEvent(event);
+
+ m_selector.mouseMove(event, this, m_playhead);
+}
+
+void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
+{
+ QGraphicsView::mouseReleaseEvent(event);
+
+ m_playhead.mouseRelease(this);
+ m_selector.mouseRelease(event, this);
+ this->viewport()->update();
+}
+
+void GraphicsView::wheelEvent(QWheelEvent *event)
+{
+ if (event->modifiers().testFlag(Qt::AltModifier))
+ return;
+
+ QGraphicsView::wheelEvent(event);
+}
+
+void GraphicsView::contextMenuEvent(QContextMenuEvent *event)
+{
+ if (event->modifiers() != Qt::NoModifier)
+ return;
+
+ auto openStyleEditor = [this]() { m_dialog.show(); };
+
+ QMenu menu;
+ QAction *openEditorAction = menu.addAction(tr("Open Style Editor"));
+ connect(openEditorAction, &QAction::triggered, openStyleEditor);
+
+ menu.exec(event->globalPos());
+}
+
+void GraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
+{
+ QRectF abscissa = timeScaleRect();
+ if (abscissa.isValid())
+ drawTimeScale(painter, abscissa);
+
+ auto ordinate = valueScaleRect();
+ if (ordinate.isValid())
+ drawValueScale(painter, ordinate);
+
+ m_playhead.paint(painter, this);
+
+ painter->fillRect(QRectF(rect.topLeft(), abscissa.bottomLeft()),
+ m_style.backgroundAlternateBrush);
+
+ m_selector.paint(painter);
+}
+
+void GraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
+{
+ painter->fillRect(rect, m_style.backgroundBrush);
+ painter->fillRect(scene()->sceneRect(), m_style.backgroundAlternateBrush);
+
+ drawGrid(painter, rect);
+ drawExtremaX(painter, rect);
+ drawExtremaY(painter, rect);
+}
+
+int GraphicsView::mapTimeToX(double time) const
+{
+ return std::round(time * scaleX(m_transform));
+}
+
+int GraphicsView::mapValueToY(double y) const
+{
+ return std::round(y * scaleY(m_transform));
+}
+
+double GraphicsView::mapXtoTime(int x) const
+{
+ return static_cast<double>(x) / scaleX(m_transform);
+}
+
+double GraphicsView::mapYtoValue(int y) const
+{
+ return static_cast<double>(y) / scaleY(m_transform);
+}
+
+QPointF GraphicsView::globalToScene(const QPoint &point) const
+{
+ return mapToScene(viewport()->mapFromGlobal(point));
+}
+
+QPointF GraphicsView::globalToRaster(const QPoint &point) const
+{
+ QPointF scene = globalToScene(point);
+ return QPointF(mapXtoTime(scene.x()), mapYtoValue(scene.y()));
+}
+
+void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
+{
+ QPointF pivotRaster(globalToRaster(pivot));
+
+ m_zoomX = clamp(x, 0.0, 1.0);
+ m_zoomY = clamp(y, 0.0, 1.0);
+
+ double minTime = minimumTime();
+ double maxTime = maximumTime();
+
+ double minValue = minimumValue();
+ double maxValue = maximumValue();
+
+ QRectF canvas = canvasRect();
+
+ double xZoomedOut = canvas.width() / (maxTime - minTime);
+ double xZoomedIn = m_style.zoomInWidth;
+ double scaleX = lerp(clamp(m_zoomX, 0.0, 1.0), xZoomedOut, xZoomedIn);
+
+ double yZoomedOut = canvas.height() / (maxValue - minValue);
+ double yZoomedIn = m_style.zoomInHeight;
+ double scaleY = lerp(clamp(m_zoomY, 0.0, 1.0), -yZoomedOut, -yZoomedIn);
+
+ m_transform = QTransform::fromScale(scaleX, scaleY);
+
+ m_scene.setComponentTransform(m_transform);
+
+ QRectF sr = m_scene.sceneRect().adjusted(
+ -m_style.valueAxisWidth - m_style.canvasMargin,
+ -m_style.timeAxisHeight - m_style.canvasMargin,
+ m_style.canvasMargin,
+ m_style.canvasMargin);
+
+ setSceneRect(sr);
+
+ m_playhead.resize(this);
+
+ if (!pivot.isNull()) {
+ QPointF deltaTransformed = pivotRaster - globalToRaster(pivot);
+ scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y()));
+ }
+}
+
+void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect)
+{
+ QRectF gridRect = rect.adjusted(
+ m_style.valueAxisWidth + m_style.canvasMargin,
+ m_style.timeAxisHeight + m_style.canvasMargin,
+ -m_style.canvasMargin,
+ -m_style.canvasMargin);
+
+ if (!gridRect.isValid())
+ return;
+
+ auto drawVerticalLine = [painter, gridRect](double position) {
+ painter->drawLine(position, gridRect.top(), position, gridRect.bottom());
+ };
+
+ painter->save();
+ painter->setPen(m_style.gridColor);
+
+ double timeIncrement = timeLabelInterval(painter, m_model->maximumTime());
+ for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement)
+ drawVerticalLine(mapTimeToX(i));
+
+ painter->restore();
+}
+
+void GraphicsView::drawExtremaX(QPainter *painter, const QRectF &rect)
+{
+ auto drawVerticalLine = [rect, painter](double position) {
+ painter->drawLine(position, rect.top(), position, rect.bottom());
+ };
+
+ painter->save();
+ painter->setPen(Qt::red);
+ drawVerticalLine(mapTimeToX(m_model->minimumTime()));
+ drawVerticalLine(mapTimeToX(m_model->maximumTime()));
+ painter->restore();
+}
+
+void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect)
+{
+ if (m_scene.empty())
+ return;
+
+ auto drawHorizontalLine = [rect, painter](double position) {
+ painter->drawLine(rect.left(), position, rect.right(), position);
+ };
+
+ painter->save();
+ painter->setPen(Qt::blue);
+ drawHorizontalLine(mapValueToY(m_scene.minimumValue()));
+ drawHorizontalLine(mapValueToY(m_scene.maximumValue()));
+
+ drawHorizontalLine(mapValueToY(0.0));
+
+ painter->restore();
+}
+
+void GraphicsView::drawTimeScale(QPainter *painter, const QRectF &rect)
+{
+ painter->save();
+ painter->setPen(m_style.fontColor);
+ painter->fillRect(rect, m_style.backgroundAlternateBrush);
+
+ QFontMetrics fm(painter->font());
+
+ auto paintLabeledTick = [this, painter, rect, fm](double time) {
+ QString timeText = QString("%1").arg(time);
+
+ int position = mapTimeToX(time);
+
+ QRect textRect = fm.boundingRect(timeText);
+ textRect.moveCenter(QPoint(position, rect.center().y()));
+
+ painter->drawText(textRect, Qt::AlignCenter, timeText);
+ painter->drawLine(position, rect.bottom() - 2, position, textRect.bottom() + 2);
+ };
+
+ double timeIncrement = timeLabelInterval(painter, maximumTime());
+ for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement)
+ paintLabeledTick(i);
+
+ painter->restore();
+}
+
+void GraphicsView::drawValueScale(QPainter *painter, const QRectF &rect)
+{
+ painter->save();
+ painter->setPen(m_style.fontColor);
+ painter->fillRect(rect, m_style.backgroundAlternateBrush);
+
+ QFontMetrics fm(painter->font());
+ auto paintLabeledTick = [this, painter, rect, fm](double value) {
+ QString valueText = QString("%1").arg(value);
+
+ int position = mapValueToY(value);
+
+ QRect textRect = fm.boundingRect(valueText);
+ textRect.moveCenter(QPoint(rect.center().x(), position));
+ painter->drawText(textRect, Qt::AlignCenter, valueText);
+ };
+
+ paintLabeledTick(minimumValue());
+ paintLabeledTick(maximumValue());
+ painter->restore();
+}
+
+double GraphicsView::timeLabelInterval(QPainter *painter, double maxTime)
+{
+ QFontMetrics fm(painter->font());
+ int minTextSpacing = fm.width(QString("X%1X").arg(maxTime));
+
+ int deltaTime = 1;
+ int nextFactor = 5;
+
+ double tickDistance = mapTimeToX(deltaTime);
+
+ while (true) {
+ if (tickDistance == 0 && deltaTime > maxTime)
+ return maxTime;
+
+ if (tickDistance > minTextSpacing)
+ break;
+
+ deltaTime *= nextFactor;
+ tickDistance = mapTimeToX(deltaTime);
+
+ if (nextFactor == 5)
+ nextFactor = 2;
+ else
+ nextFactor = 5;
+ }
+
+ return deltaTime;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h
new file mode 100644
index 0000000000..1975e3696d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditorstyle.h"
+#include "curveeditorstyledialog.h"
+#include "graphicsscene.h"
+#include "playhead.h"
+#include "selector.h"
+
+#include <QGraphicsView>
+
+namespace DesignTools {
+
+class CurveItem;
+class CurveEditorModel;
+class Playhead;
+
+class GraphicsView : public QGraphicsView
+{
+ Q_OBJECT
+
+ friend class Playhead;
+
+public:
+ GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr);
+
+ CurveEditorModel *model() const;
+
+ CurveEditorStyle editorStyle() const;
+
+ bool hasActiveItem() const;
+
+ bool hasActiveHandle() const;
+
+ int mapTimeToX(double time) const;
+
+ int mapValueToY(double value) const;
+
+ double mapXtoTime(int x) const;
+
+ double mapYtoValue(int y) const;
+
+ QPointF globalToScene(const QPoint &point) const;
+
+ QPointF globalToRaster(const QPoint &point) const;
+
+ double minimumTime() const;
+
+ double maximumTime() const;
+
+ double minimumValue() const;
+
+ double maximumValue() const;
+
+ double zoomX() const;
+
+ double zoomY() const;
+
+ QRectF canvasRect() const;
+
+ QRectF timeScaleRect() const;
+
+ QRectF valueScaleRect() const;
+
+ QRectF defaultRasterRect() const;
+
+ void setStyle(const CurveEditorStyle &style);
+
+ void setZoomX(double zoom, const QPoint &pivot = QPoint());
+
+ void setZoomY(double zoom, const QPoint &pivot = QPoint());
+
+ void setCurrentFrame(int frame);
+
+ void scrollContent(double x, double y);
+
+ void reset(const std::vector<CurveItem *> &items);
+
+protected:
+ void resizeEvent(QResizeEvent *event) override;
+
+ void keyPressEvent(QKeyEvent *event) override;
+
+ void mousePressEvent(QMouseEvent *event) override;
+
+ void mouseMoveEvent(QMouseEvent *event) override;
+
+ void mouseReleaseEvent(QMouseEvent *event) override;
+
+ void wheelEvent(QWheelEvent *event) override;
+
+ void contextMenuEvent(QContextMenuEvent *event) override;
+
+ void drawForeground(QPainter *painter, const QRectF &rect) override;
+
+ void drawBackground(QPainter *painter, const QRectF &rect) override;
+
+private:
+ void applyZoom(double x, double y, const QPoint &pivot = QPoint());
+
+ void drawGrid(QPainter *painter, const QRectF &rect);
+
+ void drawExtremaX(QPainter *painter, const QRectF &rect);
+
+ void drawExtremaY(QPainter *painter, const QRectF &rect);
+
+ void drawTimeScale(QPainter *painter, const QRectF &rect);
+
+ void drawValueScale(QPainter *painter, const QRectF &rect);
+
+ double timeLabelInterval(QPainter *painter, double maxTime);
+
+private:
+ double m_zoomX;
+
+ double m_zoomY;
+
+ QTransform m_transform;
+
+ GraphicsScene m_scene;
+
+ CurveEditorModel *m_model;
+
+ Playhead m_playhead;
+
+ Selector m_selector;
+
+ CurveEditorStyle m_style;
+
+ CurveEditorStyleDialog m_dialog;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/handleitem.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/handleitem.cpp
new file mode 100644
index 0000000000..c54b26e279
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/handleitem.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "handleitem.h"
+#include "utils.h"
+
+#include <QPainter>
+
+namespace DesignTools {
+
+struct HandleGeometry
+{
+ HandleGeometry(const QPointF &pos, const HandleItemStyleOption &style)
+ {
+ QPointF topLeft(-style.size / 2.0, -style.size / 2.0);
+ handle = QRectF(topLeft, -topLeft);
+ toKeyframe = QLineF(QPointF(0.0, 0.0), -pos);
+ angle = -toKeyframe.angle() + 45.0;
+ }
+
+ QRectF handle;
+
+ QLineF toKeyframe;
+
+ double angle;
+};
+
+HandleItem::HandleItem(QGraphicsItem *parent)
+ : SelectableItem(parent)
+ , m_style()
+{
+ setFlag(QGraphicsItem::ItemStacksBehindParent, true);
+}
+
+HandleItem::~HandleItem() {}
+
+int HandleItem::type() const
+{
+ return Type;
+}
+
+QRectF HandleItem::boundingRect() const
+{
+ HandleGeometry geom(pos(), m_style);
+
+ QTransform transform;
+ transform.rotate(geom.angle);
+
+ QRectF bounds = bbox(geom.handle, transform);
+ grow(bounds, -pos());
+ return bounds;
+}
+
+void HandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ QColor handleColor(isSelected() ? m_style.selectionColor : m_style.color);
+
+ HandleGeometry geom(pos(), m_style);
+
+ QPen pen = painter->pen();
+ pen.setWidthF(m_style.lineWidth);
+ pen.setColor(handleColor);
+
+ painter->save();
+ painter->setPen(pen);
+
+ painter->drawLine(geom.toKeyframe);
+ painter->rotate(geom.angle);
+ painter->fillRect(geom.handle, handleColor);
+
+ painter->restore();
+}
+
+void HandleItem::setStyle(const CurveEditorStyle &style)
+{
+ m_style = style.handleStyle;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/handleitem.h b/src/plugins/qmldesigner/components/curveeditor/detail/handleitem.h
new file mode 100644
index 0000000000..4c9126c629
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/handleitem.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditorstyle.h"
+#include "selectableitem.h"
+
+namespace DesignTools {
+
+class HandleItem : public SelectableItem
+{
+ Q_OBJECT
+
+public:
+ HandleItem(QGraphicsItem *parent);
+
+ ~HandleItem() override;
+
+ enum { Type = ItemTypeHandle };
+
+ int type() const override;
+
+ QRectF boundingRect() const override;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
+
+ void setStyle(const CurveEditorStyle &style);
+
+private:
+ HandleItemStyleOption m_style;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp
new file mode 100644
index 0000000000..94cdbbcbb1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "keyframeitem.h"
+#include "handleitem.h"
+
+#include <QPainter>
+
+#include <cmath>
+
+namespace DesignTools {
+
+KeyframeItem::KeyframeItem(QGraphicsItem *parent)
+ : SelectableItem(parent)
+ , m_frame()
+{}
+
+KeyframeItem::KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent)
+ : SelectableItem(parent)
+ , m_transform()
+ , m_frame(keyframe)
+ , m_left(keyframe.hasLeftHandle() ? new HandleItem(this) : nullptr)
+ , m_right(keyframe.hasRightHandle() ? new HandleItem(this) : nullptr)
+{
+ auto updatePosition = [this]() { this->updatePosition(true); };
+ connect(this, &QGraphicsObject::xChanged, updatePosition);
+ connect(this, &QGraphicsObject::yChanged, updatePosition);
+
+ if (m_left) {
+ m_left->setPos(m_frame.leftHandle() - m_frame.position());
+ auto updateLeftHandle = [this]() { updateHandle(m_left); };
+ connect(m_left, &QGraphicsObject::xChanged, updateLeftHandle);
+ connect(m_left, &QGraphicsObject::yChanged, updateLeftHandle);
+ m_left->hide();
+ }
+
+ if (m_right) {
+ m_right->setPos(m_frame.rightHandle() - m_frame.position());
+ auto updateRightHandle = [this]() { updateHandle(m_right); };
+ connect(m_right, &QGraphicsObject::xChanged, updateRightHandle);
+ connect(m_right, &QGraphicsObject::yChanged, updateRightHandle);
+ m_right->hide();
+ }
+
+ setPos(m_frame.position());
+}
+
+int KeyframeItem::type() const
+{
+ return Type;
+}
+
+QRectF KeyframeItem::boundingRect() const
+{
+ QPointF topLeft(-m_style.size / 2.0, -m_style.size / 2.0);
+ return QRectF(topLeft, -topLeft);
+}
+
+void KeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ QPen pen = painter->pen();
+ pen.setColor(Qt::black);
+
+ painter->save();
+ painter->setPen(pen);
+ painter->setBrush(selected() ? Qt::red : m_style.color);
+ painter->drawEllipse(boundingRect());
+
+ painter->restore();
+}
+
+KeyframeItem::~KeyframeItem() {}
+
+Keyframe KeyframeItem::keyframe() const
+{
+ return m_frame;
+}
+
+void KeyframeItem::setComponentTransform(const QTransform &transform)
+{
+ m_transform = transform;
+
+ if (m_left)
+ m_left->setPos(m_transform.map(m_frame.leftHandle() - m_frame.position()));
+
+ if (m_right)
+ m_right->setPos(m_transform.map(m_frame.rightHandle() - m_frame.position()));
+
+ setPos(m_transform.map(m_frame.position()));
+}
+
+void KeyframeItem::setStyle(const CurveEditorStyle &style)
+{
+ m_style = style.keyframeStyle;
+
+ if (m_left)
+ m_left->setStyle(style);
+
+ if (m_right)
+ m_right->setStyle(style);
+}
+
+void KeyframeItem::updatePosition(bool update)
+{
+ bool ok = false;
+ QPointF position = m_transform.inverted(&ok).map(pos());
+
+ if (!ok)
+ return;
+
+ QPointF oldPosition = m_frame.position();
+ m_frame.setPosition(position);
+
+ if (m_left)
+ updateHandle(m_left, false);
+
+ if (m_right)
+ updateHandle(m_right, false);
+
+ if (update) {
+ emit redrawCurve();
+ emit keyframeMoved(this, position - oldPosition);
+ }
+}
+
+void KeyframeItem::moveKeyframe(const QPointF &direction)
+{
+ this->blockSignals(true);
+ setPos(m_transform.map(m_frame.position() + direction));
+ updatePosition(false);
+ this->blockSignals(false);
+ emit redrawCurve();
+}
+
+void KeyframeItem::moveHandle(HandleSlot handle, double deltaAngle, double deltaLength)
+{
+ auto move = [this, deltaAngle, deltaLength](HandleItem *item) {
+ QLineF current(QPointF(0.0, 0.0), item->pos());
+ current.setAngle(current.angle() + deltaAngle);
+ current.setLength(current.length() + deltaLength);
+ item->setPos(current.p2());
+ updateHandle(item, false);
+ };
+
+ this->blockSignals(true);
+
+ if (handle == HandleSlot::Left)
+ move(m_left);
+ else if (handle == HandleSlot::Right)
+ move(m_right);
+
+ this->blockSignals(false);
+
+ emit redrawCurve();
+}
+
+void KeyframeItem::updateHandle(HandleItem *handle, bool emitChanged)
+{
+ bool ok = false;
+
+ QPointF handlePosition = m_transform.inverted(&ok).map(handle->pos());
+
+ if (!ok)
+ return;
+
+ QPointF oldPosition;
+ QPointF newPosition;
+ HandleSlot slot = HandleSlot::Undefined;
+ if (handle == m_left) {
+ slot = HandleSlot::Left;
+ oldPosition = m_frame.leftHandle();
+ m_frame.setLeftHandle(m_frame.position() + handlePosition);
+ newPosition = m_frame.leftHandle();
+ } else {
+ slot = HandleSlot::Right;
+ oldPosition = m_frame.rightHandle();
+ m_frame.setRightHandle(m_frame.position() + handlePosition);
+ newPosition = m_frame.rightHandle();
+ }
+
+ if (emitChanged) {
+ QLineF oldLine(m_frame.position(), oldPosition);
+ QLineF newLine(m_frame.position(), newPosition);
+
+ QLineF mappedOld = m_transform.map(oldLine);
+ QLineF mappedNew = m_transform.map(newLine);
+
+ auto angle = mappedOld.angleTo(mappedNew);
+ auto deltaLength = mappedNew.length() - mappedOld.length();
+
+ emit redrawCurve();
+ emit handleMoved(this, slot, angle, deltaLength);
+ }
+}
+
+QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+{
+ if (change == ItemPositionChange) {
+ bool ok;
+ QPointF position = m_transform.inverted(&ok).map(value.toPointF());
+ if (ok) {
+ position.setX(std::round(position.x()));
+ return QVariant(m_transform.map(position));
+ }
+ }
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void KeyframeItem::selectionCallback()
+{
+ auto setHandleVisibility = [](HandleItem *handle, bool visible) {
+ if (handle)
+ handle->setVisible(visible);
+ };
+
+ if (selected()) {
+ setHandleVisibility(m_left, true);
+ setHandleVisibility(m_right, true);
+ } else {
+ setHandleVisibility(m_left, false);
+ setHandleVisibility(m_right, false);
+ }
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h
new file mode 100644
index 0000000000..ae65be1e9b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/keyframeitem.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditorstyle.h"
+#include "keyframe.h"
+#include "selectableitem.h"
+
+#include <QGraphicsObject>
+
+namespace DesignTools {
+
+class HandleItem;
+
+enum class HandleSlot { Undefined, Left, Right };
+
+class KeyframeItem : public SelectableItem
+{
+ Q_OBJECT
+
+signals:
+ void redrawCurve();
+
+ void keyframeMoved(KeyframeItem *item, const QPointF &direction);
+
+ void handleMoved(KeyframeItem *frame, HandleSlot handle, double angle, double deltaLength);
+
+public:
+ KeyframeItem(QGraphicsItem *parent = nullptr);
+
+ KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent = nullptr);
+
+ ~KeyframeItem() override;
+
+ enum { Type = ItemTypeKeyframe };
+
+ int type() const override;
+
+ QRectF boundingRect() const override;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
+
+ Keyframe keyframe() const;
+
+ void setComponentTransform(const QTransform &transform);
+
+ void setStyle(const CurveEditorStyle &style);
+
+ void moveKeyframe(const QPointF &direction);
+
+ void moveHandle(HandleSlot handle, double deltaAngle, double deltaLength);
+
+protected:
+ QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
+
+ void selectionCallback() override;
+
+private:
+ void updatePosition(bool emit = true);
+
+ void updateHandle(HandleItem *handle, bool emit = true);
+
+private:
+ QTransform m_transform;
+
+ KeyframeItemStyleOption m_style;
+
+ Keyframe m_frame;
+
+ HandleItem *m_left;
+
+ HandleItem *m_right;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/playhead.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/playhead.cpp
new file mode 100644
index 0000000000..e2e6d21274
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/playhead.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "playhead.h"
+#include "curveeditormodel.h"
+#include "graphicsview.h"
+
+#include <QApplication>
+#include <QGraphicsScene>
+#include <QPainter>
+
+#include <cmath>
+
+namespace DesignTools {
+
+constexpr double g_playheadMargin = 5.0;
+
+Playhead::Playhead(GraphicsView *view)
+ : m_frame(0)
+ , m_moving(false)
+ , m_rect()
+ , m_timer()
+{
+ m_timer.setSingleShot(true);
+ m_timer.setInterval(30);
+ QObject::connect(&m_timer, &QTimer::timeout, view, [this, view]() {
+ if (QApplication::mouseButtons() == Qt::LeftButton)
+ mouseMoveOutOfBounds(view);
+ });
+}
+
+int Playhead::currentFrame() const
+{
+ return m_frame;
+}
+
+void Playhead::moveToFrame(int frame, GraphicsView *view)
+{
+ m_frame = frame;
+ m_rect.moveCenter(QPointF(view->mapTimeToX(m_frame), m_rect.center().y()));
+}
+
+void Playhead::resize(GraphicsView *view)
+{
+ QRectF viewRect = view->mapToScene(view->viewport()->rect()).boundingRect();
+
+ CurveEditorStyle style = view->editorStyle();
+
+ QPointF tlr(style.valueAxisWidth, style.timeAxisHeight - style.playhead.width);
+ QPointF brr(style.valueAxisWidth + style.playhead.width, -g_playheadMargin);
+
+ QPointF tl = viewRect.topLeft() + tlr;
+ QPointF br = viewRect.bottomLeft() + brr;
+
+ m_rect = QRectF(tl, br);
+
+ moveToFrame(m_frame, view);
+}
+
+bool Playhead::mousePress(const QPointF &pos)
+{
+ QRectF hitRect = m_rect;
+ hitRect.setBottom(hitRect.top() + hitRect.width());
+
+ m_moving = hitRect.contains(pos);
+
+ return m_moving;
+}
+
+bool Playhead::mouseMove(const QPointF &pos, GraphicsView *view)
+{
+ if (m_moving) {
+ CurveEditorStyle style = view->editorStyle();
+
+ QRectF canvas = view->canvasRect().adjusted(0.0, -style.timeAxisHeight, 0.0, 0.0);
+
+ if (canvas.contains(pos))
+ view->setCurrentFrame(std::round(view->mapXtoTime(pos.x())));
+ else if (!m_timer.isActive())
+ m_timer.start();
+ }
+
+ return m_moving;
+}
+
+void Playhead::mouseMoveOutOfBounds(GraphicsView *view)
+{
+ if (QApplication::mouseButtons() != Qt::LeftButton)
+ return;
+
+ CurveEditorStyle style = view->editorStyle();
+ QRectF canvas = view->canvasRect();
+ QPointF pos = view->globalToScene(QCursor::pos());
+
+ if (pos.x() > canvas.right()) {
+ double speed = (pos.x() - canvas.right());
+ double nextCenter = m_rect.center().x() + speed;
+ double frame = std::round(view->mapXtoTime(nextCenter));
+ view->setCurrentFrame(frame);
+
+ double framePosition = view->mapTimeToX(frame);
+ double rightSideOut = framePosition + style.playhead.width / 2.0 + style.canvasMargin;
+ double overshoot = rightSideOut - canvas.right();
+ view->scrollContent(overshoot, 0.0);
+
+ } else if (pos.x() < canvas.left()) {
+ double speed = (canvas.left() - pos.x());
+ double nextCenter = m_rect.center().x() - speed;
+ double frame = std::round(view->mapXtoTime(nextCenter));
+ view->setCurrentFrame(frame);
+
+ double framePosition = view->mapTimeToX(frame);
+ double leftSideOut = framePosition - style.playhead.width / 2.0 - style.canvasMargin;
+ double undershoot = canvas.left() - leftSideOut;
+ view->scrollContent(-undershoot, 0.0);
+ }
+
+ m_timer.start();
+}
+
+void Playhead::mouseRelease(GraphicsView *view)
+{
+ if (m_moving)
+ emit view->model()->currentFrameChanged(m_frame);
+
+ m_moving = false;
+}
+
+void Playhead::paint(QPainter *painter, GraphicsView *view) const
+{
+ CurveEditorStyle style = view->editorStyle();
+
+ painter->save();
+ painter->setPen(style.playhead.color);
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ QRectF rect = m_rect;
+ rect.setBottom(m_rect.top() + m_rect.width());
+
+ QPointF top(rect.center().x(), rect.top());
+ QPointF right(rect.right(), rect.top());
+ QPointF bottom(rect.center().x(), rect.bottom());
+ QPointF left(rect.left(), rect.top());
+
+ QLineF rightToBottom(right, bottom);
+ rightToBottom.setLength(style.playhead.radius);
+
+ QLineF leftToBottom(left, bottom);
+ leftToBottom.setLength(style.playhead.radius);
+
+ QPainterPath path(top);
+ path.lineTo(right - QPointF(style.playhead.radius, 0.));
+ path.quadTo(right, rightToBottom.p2());
+ path.lineTo(bottom);
+ path.lineTo(leftToBottom.p2());
+ path.quadTo(left, left + QPointF(style.playhead.radius, 0.));
+ path.closeSubpath();
+
+ painter->fillPath(path, style.playhead.color);
+ painter->drawLine(top + QPointF(0., 5.), QPointF(m_rect.center().x(), m_rect.bottom()));
+
+ painter->restore();
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/playhead.h b/src/plugins/qmldesigner/components/curveeditor/detail/playhead.h
new file mode 100644
index 0000000000..28d2a21a5c
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/playhead.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QRectF>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+class QPainter;
+QT_END_NAMESPACE
+
+namespace DesignTools {
+
+class GraphicsView;
+
+class Playhead
+{
+public:
+ Playhead(GraphicsView *view);
+
+ int currentFrame() const;
+
+ void paint(QPainter *painter, GraphicsView *view) const;
+
+ void moveToFrame(int frame, GraphicsView *view);
+
+ void resize(GraphicsView *view);
+
+ bool mousePress(const QPointF &pos);
+
+ bool mouseMove(const QPointF &pos, GraphicsView *view);
+
+ void mouseRelease(GraphicsView *view);
+
+private:
+ void mouseMoveOutOfBounds(GraphicsView *view);
+
+ int m_frame;
+
+ bool m_moving;
+
+ QRectF m_rect;
+
+ QTimer m_timer;
+
+ GraphicsView *m_view;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.cpp
new file mode 100644
index 0000000000..fb61682090
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "selectableitem.h"
+#include "keyframeitem.h"
+
+#include <QDebug>
+
+namespace DesignTools {
+
+SelectableItem::SelectableItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , m_active(false)
+ , m_selected(false)
+ , m_preSelected(SelectionMode::Undefined)
+{
+ setFlag(QGraphicsItem::ItemIsSelectable, false);
+
+ setFlag(QGraphicsItem::ItemIsMovable, true);
+ setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
+ setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+}
+
+SelectableItem::~SelectableItem() {}
+
+bool SelectableItem::activated() const
+{
+ return m_active;
+}
+
+bool SelectableItem::selected() const
+{
+ switch (m_preSelected) {
+ case SelectionMode::Clear:
+ return false;
+ case SelectionMode::New:
+ return true;
+ case SelectionMode::Add:
+ return true;
+ case SelectionMode::Remove:
+ return false;
+ case SelectionMode::Toggle:
+ return !m_selected;
+ default:
+ return m_selected;
+ }
+
+ return false;
+}
+
+void SelectableItem::setActivated(bool active)
+{
+ m_active = active;
+}
+
+void SelectableItem::setPreselected(SelectionMode mode)
+{
+ m_preSelected = mode;
+ selectionCallback();
+}
+
+void SelectableItem::applyPreselection()
+{
+ m_selected = selected();
+ m_preSelected = SelectionMode::Undefined;
+}
+
+void SelectableItem::selectionCallback() {}
+
+void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ m_active = true;
+ QGraphicsObject::mousePressEvent(event);
+}
+
+void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (type() == KeyframeItem::Type && !selected())
+ return;
+
+ QGraphicsObject::mouseMoveEvent(event);
+}
+
+void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ m_active = false;
+ QGraphicsObject::mouseReleaseEvent(event);
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.h b/src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.h
new file mode 100644
index 0000000000..0a2a4898a1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/selectableitem.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QGraphicsObject>
+
+namespace DesignTools {
+
+enum ItemType
+{
+ ItemTypeKeyframe = QGraphicsItem::UserType + 1,
+ ItemTypeHandle = QGraphicsItem::UserType + 2,
+ ItemTypeCurve = QGraphicsItem::UserType + 3
+};
+
+enum class SelectionMode : unsigned int
+{
+ Undefined,
+ Clear,
+ New,
+ Add,
+ Remove,
+ Toggle
+};
+
+class SelectableItem : public QGraphicsObject
+{
+ Q_OBJECT
+
+public:
+ SelectableItem(QGraphicsItem *parent = nullptr);
+
+ ~SelectableItem() override;
+
+ bool activated() const;
+
+ bool selected() const;
+
+ void setActivated(bool active);
+
+ void setPreselected(SelectionMode mode);
+
+ void applyPreselection();
+
+protected:
+ virtual void selectionCallback();
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
+
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
+
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
+
+private:
+ bool m_active;
+
+ bool m_selected;
+
+ SelectionMode m_preSelected;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp
new file mode 100644
index 0000000000..633c1ddd39
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/selector.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "selector.h"
+#include "graphicsview.h"
+#include "keyframeitem.h"
+#include "playhead.h"
+
+#include <QApplication>
+
+#include <cmath>
+
+namespace DesignTools {
+
+Selector::Selector() {}
+
+void Selector::paint(QPainter *painter)
+{
+ QPen pen(Qt::white);
+
+ painter->save();
+ painter->setPen(pen);
+
+ if (!m_lasso.isEmpty())
+ painter->drawPath(m_lasso);
+
+ if (!m_rect.isNull())
+ painter->drawRect(m_rect);
+
+ painter->restore();
+}
+
+void Selector::mousePress(QMouseEvent *event, GraphicsView *view)
+{
+ m_shortcut = Shortcut(event);
+
+ if (view->hasActiveHandle())
+ return;
+
+ if (select(SelectionTool::Undefined, view->globalToScene(event->globalPos()), view))
+ applyPreSelection(view);
+
+ m_mouseInit = event->globalPos();
+ m_mouseCurr = event->globalPos();
+
+ QPointF click = view->globalToScene(m_mouseInit);
+
+ m_lasso = QPainterPath(click);
+ m_lasso.closeSubpath();
+
+ m_rect = QRectF(click, click);
+}
+
+void Selector::mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playhead)
+{
+ if (m_mouseInit.isNull())
+ return;
+
+ QPointF delta = event->globalPos() - m_mouseInit;
+ if (delta.manhattanLength() < QApplication::startDragDistance())
+ return;
+
+ if (m_shortcut == m_shortcuts.newSelection || m_shortcut == m_shortcuts.addToSelection
+ || m_shortcut == m_shortcuts.removeFromSelection
+ || m_shortcut == m_shortcuts.toggleSelection) {
+ if (view->hasActiveItem())
+ return;
+
+ select(m_tool, view->globalToScene(event->globalPos()), view);
+
+ event->accept();
+ view->viewport()->update();
+
+ } else if (m_shortcut == m_shortcuts.zoom) {
+ double bigger = std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y();
+ double factor = bigger / view->width();
+ view->setZoomX(view->zoomX() + factor, m_mouseInit);
+ m_mouseCurr = event->globalPos();
+ event->accept();
+
+ } else if (m_shortcut == m_shortcuts.pan) {
+ view->scrollContent(-delta.x(), -delta.y());
+ playhead.resize(view);
+ m_mouseCurr = event->globalPos();
+ }
+}
+
+void Selector::mouseRelease(QMouseEvent *event, GraphicsView *view)
+{
+ Q_UNUSED(event);
+
+ applyPreSelection(view);
+
+ m_shortcut = Shortcut();
+ m_mouseInit = QPoint();
+ m_mouseCurr = QPoint();
+ m_lasso = QPainterPath();
+ m_rect = QRectF();
+}
+
+bool Selector::select(const SelectionTool &tool, const QPointF &pos, GraphicsView *view)
+{
+ auto selectWidthTool = [this, tool](SelectionMode mode, const QPointF &pos, GraphicsView *view) {
+ switch (tool) {
+ case SelectionTool::Lasso:
+ return lassoSelection(mode, pos, view);
+ case SelectionTool::Rectangle:
+ return rectangleSelection(mode, pos, view);
+ default:
+ return pressSelection(mode, pos, view);
+ }
+ };
+
+ if (m_shortcut == m_shortcuts.newSelection) {
+ clearSelection(view);
+ return selectWidthTool(SelectionMode::New, pos, view);
+ } else if (m_shortcut == m_shortcuts.addToSelection) {
+ return selectWidthTool(SelectionMode::Add, pos, view);
+ } else if (m_shortcut == m_shortcuts.removeFromSelection) {
+ return selectWidthTool(SelectionMode::Remove, pos, view);
+ } else if (m_shortcut == m_shortcuts.toggleSelection) {
+ return selectWidthTool(SelectionMode::Toggle, pos, view);
+ }
+
+ return false;
+}
+
+bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
+{
+ bool out = false;
+ const auto itemList = view->items();
+ for (auto *item : itemList) {
+ if (auto *frame = qgraphicsitem_cast<KeyframeItem *>(item)) {
+ QRectF itemRect = frame->mapRectToScene(frame->boundingRect());
+ if (itemRect.contains(pos)) {
+ frame->setPreselected(mode);
+ out = true;
+ }
+ }
+ }
+ return out;
+}
+
+bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
+{
+ bool out = false;
+ m_rect.setBottomRight(pos);
+ const auto itemList = view->items();
+ for (auto *item : itemList) {
+ if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
+ if (m_rect.contains(keyframeItem->pos())) {
+ keyframeItem->setPreselected(mode);
+ out = true;
+ } else {
+ keyframeItem->setPreselected(SelectionMode::Undefined);
+ }
+ }
+ }
+ return out;
+}
+
+bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
+{
+ bool out = false;
+ m_lasso.lineTo(pos);
+ const auto itemList = view->items();
+ for (auto *item : itemList) {
+ if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
+ if (m_lasso.contains(keyframeItem->pos())) {
+ keyframeItem->setPreselected(mode);
+ out = true;
+ } else {
+ keyframeItem->setPreselected(SelectionMode::Undefined);
+ }
+ }
+ }
+ return out;
+}
+
+void Selector::clearSelection(GraphicsView *view)
+{
+ const auto itemList = view->items();
+ for (auto *item : itemList) {
+ if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
+ frameItem->setPreselected(SelectionMode::Clear);
+ frameItem->applyPreselection();
+ }
+ }
+}
+
+void Selector::applyPreSelection(GraphicsView *view)
+{
+ const auto itemList = view->items();
+ for (auto *item : itemList) {
+ if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item))
+ keyframeItem->applyPreselection();
+ }
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/selector.h b/src/plugins/qmldesigner/components/curveeditor/detail/selector.h
new file mode 100644
index 0000000000..e8f53d9d59
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/selector.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditorstyle.h"
+#include "selectableitem.h"
+
+#include <QMouseEvent>
+#include <QPainterPath>
+#include <QPoint>
+#include <QRectF>
+
+namespace DesignTools {
+
+class GraphicsView;
+class Playhead;
+
+enum class SelectionTool { Undefined, Lasso, Rectangle };
+
+class Selector
+{
+public:
+ Selector();
+
+ void paint(QPainter *painter);
+
+ void mousePress(QMouseEvent *event, GraphicsView *view);
+
+ void mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playhead);
+
+ void mouseRelease(QMouseEvent *event, GraphicsView *view);
+
+private:
+ bool select(const SelectionTool &tool, const QPointF &pos, GraphicsView *view);
+
+ bool pressSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
+
+ bool rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
+
+ bool lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
+
+ void clearSelection(GraphicsView *view);
+
+ void applyPreSelection(GraphicsView *view);
+
+ Shortcuts m_shortcuts = Shortcuts();
+
+ Shortcut m_shortcut;
+
+ SelectionMode m_mode = SelectionMode::Undefined;
+
+ SelectionTool m_tool = SelectionTool::Rectangle;
+
+ QPoint m_mouseInit = QPoint();
+
+ QPoint m_mouseCurr = QPoint();
+
+ QPainterPath m_lasso = QPainterPath();
+
+ QRectF m_rect = QRectF();
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/shortcut.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/shortcut.cpp
new file mode 100644
index 0000000000..d6d04dbbae
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/shortcut.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "shortcut.h"
+
+namespace DesignTools {
+
+Shortcut::Shortcut()
+ : m_key()
+ , m_buttons()
+ , m_modifiers()
+{}
+
+Shortcut::Shortcut(QMouseEvent *event)
+ : m_key()
+ , m_buttons(event->buttons())
+ , m_modifiers(event->modifiers())
+{}
+
+Shortcut::Shortcut(const Qt::KeyboardModifiers &mods, const Qt::Key &key)
+ : m_key(key)
+ , m_buttons()
+ , m_modifiers(mods)
+{}
+
+Shortcut::Shortcut(const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &mods)
+ : m_key()
+ , m_buttons(buttons)
+ , m_modifiers(mods)
+{}
+
+Shortcut::Shortcut(const Qt::MouseButtons &buttons,
+ const Qt::KeyboardModifiers &mods,
+ const Qt::Key &key)
+ : m_key(key)
+ , m_buttons(buttons)
+ , m_modifiers(mods)
+{}
+
+bool Shortcut::exactMatch(const Qt::Key &key) const
+{
+ return m_key == key;
+}
+
+bool Shortcut::exactMatch(const Qt::MouseButton &button) const
+{
+ return static_cast<int>(m_buttons) == static_cast<int>(button);
+}
+
+bool Shortcut::exactMatch(const Qt::KeyboardModifier &modifier) const
+{
+ return static_cast<int>(m_modifiers) == static_cast<int>(modifier);
+}
+
+bool Shortcut::operator==(const Shortcut &other) const
+{
+ return m_key == other.m_key && m_buttons == other.m_buttons && m_modifiers == other.m_modifiers;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/shortcut.h b/src/plugins/qmldesigner/components/curveeditor/detail/shortcut.h
new file mode 100644
index 0000000000..a9e075bd8b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/shortcut.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QMouseEvent>
+
+namespace DesignTools {
+
+class Shortcut
+{
+public:
+ Shortcut();
+
+ Shortcut(QMouseEvent *event);
+
+ Shortcut(const Qt::KeyboardModifiers &mods, const Qt::Key &key);
+
+ Shortcut(const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &mods = Qt::NoModifier);
+
+ Shortcut(const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &mods, const Qt::Key &key);
+
+ bool exactMatch(const Qt::Key &key) const;
+
+ bool exactMatch(const Qt::MouseButton &button) const;
+
+ bool exactMatch(const Qt::KeyboardModifier &modifier) const;
+
+ bool operator==(const Shortcut &other) const;
+
+private:
+ Qt::Key m_key;
+
+ Qt::MouseButtons m_buttons;
+
+ Qt::KeyboardModifiers m_modifiers;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.cpp
new file mode 100644
index 0000000000..21633ddce1
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "treeitemdelegate.h"
+#include "treeitem.h"
+
+#include <QEvent>
+#include <QMouseEvent>
+#include <QPainter>
+
+namespace DesignTools {
+
+TreeItemDelegate::TreeItemDelegate(const CurveEditorStyle &style, QObject *parent)
+ : QStyledItemDelegate(parent)
+ , m_style(style)
+{}
+
+QSize TreeItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ return QStyledItemDelegate::sizeHint(option, index);
+}
+
+void TreeItemDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (index.column() == 1 || index.column() == 2) {
+
+ int height = option.rect.size().height();
+ QRect iconRect(QPoint(0, 0), QSize(height, height));
+ iconRect.moveCenter(option.rect.center());
+
+ auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
+ if (option.state & QStyle::State_MouseOver && iconRect.contains(m_mousePos)) {
+
+ painter->fillRect(option.rect, option.backgroundBrush);
+
+ if (index.column() == 1) {
+
+ if (treeItem->locked()) {
+
+ QPixmap pixmap = pixmapFromIcon(
+ m_style.treeItemStyle.unlockedIcon,
+ iconRect.size(),
+ m_style.fontColor);
+
+ painter->drawPixmap(iconRect, pixmap);
+
+ } else {
+
+ QPixmap pixmap = pixmapFromIcon(
+ m_style.treeItemStyle.lockedIcon,
+ iconRect.size(),
+ m_style.fontColor);
+
+ painter->drawPixmap(iconRect, pixmap);
+ }
+
+ } else if (index.column() == 2) {
+
+ if (treeItem->pinned()) {
+
+ QPixmap pixmap = pixmapFromIcon(
+ m_style.treeItemStyle.unpinnedIcon,
+ iconRect.size(),
+ m_style.fontColor);
+
+ painter->drawPixmap(iconRect, pixmap);
+
+ } else {
+
+ QPixmap pixmap = pixmapFromIcon(
+ m_style.treeItemStyle.pinnedIcon,
+ iconRect.size(),
+ m_style.fontColor);
+
+ painter->drawPixmap(iconRect, pixmap);
+
+ }
+ }
+
+ } else {
+
+ if (treeItem->locked() && index.column() == 1) {
+
+ QPixmap pixmap = pixmapFromIcon(
+ m_style.treeItemStyle.lockedIcon,
+ iconRect.size(),
+ m_style.fontColor);
+
+ painter->drawPixmap(iconRect, pixmap);
+
+ } else if (treeItem->pinned() && index.column() == 2) {
+
+ QPixmap pixmap = pixmapFromIcon(
+ m_style.treeItemStyle.pinnedIcon,
+ iconRect.size(),
+ m_style.fontColor);
+
+ painter->drawPixmap(iconRect, pixmap);
+
+ }
+ }
+ } else {
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+}
+
+void TreeItemDelegate::setStyle(const CurveEditorStyle &style)
+{
+ m_style = style;
+}
+
+bool TreeItemDelegate::editorEvent(QEvent *event,
+ QAbstractItemModel *model,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index)
+{
+ if (event->type() == QEvent::MouseMove)
+ m_mousePos = static_cast<QMouseEvent *>(event)->pos();
+
+ return QStyledItemDelegate::editorEvent(event, model, option, index);
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.h b/src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.h
new file mode 100644
index 0000000000..6479f48942
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treeitemdelegate.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "curveeditorstyle.h"
+
+#include <QStyledItemDelegate>
+
+namespace DesignTools {
+
+class TreeItemDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+
+public:
+ TreeItemDelegate(const CurveEditorStyle &style, QObject *parent = nullptr);
+
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+
+ void paint(
+ QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+
+ void setStyle(const CurveEditorStyle &style);
+
+protected:
+ bool editorEvent(
+ QEvent *event,
+ QAbstractItemModel *model,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) override;
+
+private:
+ CurveEditorStyle m_style;
+
+ QPoint m_mousePos;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp
new file mode 100644
index 0000000000..1ea037091d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "treemodel.h"
+#include "treeitem.h"
+#include "detail/graphicsview.h"
+
+#include <QIcon>
+
+namespace DesignTools {
+
+TreeModel::TreeModel(QObject *parent)
+ : QAbstractItemModel(parent)
+ , m_view(nullptr)
+ , m_root(new TreeItem("Root"))
+{}
+
+TreeModel::~TreeModel()
+{
+ if (m_root) {
+ delete m_root;
+ m_root = nullptr;
+ }
+
+ m_view = nullptr;
+}
+
+QVariant TreeModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
+
+ if (role == Qt::DecorationRole && index.column() == 0)
+ return item->icon();
+
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ return item->data(index.column());
+}
+
+QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Horizontal)
+ return m_root->headerData(section);
+
+ return QVariant();
+}
+
+QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ TreeItem *parentItem = m_root;
+
+ if (parent.isValid())
+ parentItem = static_cast<TreeItem *>(parent.internalPointer());
+
+ if (TreeItem *childItem = parentItem->child(row))
+ return createIndex(row, column, childItem);
+
+ return QModelIndex();
+}
+
+QModelIndex TreeModel::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ TreeItem *childItem = static_cast<TreeItem *>(index.internalPointer());
+
+ if (TreeItem *parentItem = childItem->parent()) {
+ if (parentItem == m_root)
+ return QModelIndex();
+
+ return createIndex(parentItem->row(), 0, parentItem);
+ }
+ return QModelIndex();
+}
+
+int TreeModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.column() > 0)
+ return 0;
+
+ TreeItem *parentItem = m_root;
+
+ if (parent.isValid())
+ parentItem = static_cast<TreeItem *>(parent.internalPointer());
+
+ return parentItem->rowCount();
+}
+
+int TreeModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return m_root->columnCount();
+}
+
+void TreeModel::setGraphicsView(GraphicsView *view)
+{
+ m_view = view;
+}
+
+GraphicsView *TreeModel::graphicsView() const
+{
+ return m_view;
+}
+
+void TreeModel::initialize()
+{
+ if (m_root)
+ delete m_root;
+
+ m_root = new TreeItem("Root");
+}
+
+TreeItem *TreeModel::root()
+{
+ return m_root;
+}
+
+TreeItem *TreeModel::find(unsigned int id)
+{
+ return m_root->find(id);
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.h b/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.h
new file mode 100644
index 0000000000..209b2ee506
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treemodel.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QAbstractItemModel>
+
+#include <vector>
+
+namespace DesignTools {
+
+class GraphicsView;
+class TreeItem;
+
+class TreeModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ TreeModel(QObject *parent = nullptr);
+
+ ~TreeModel() override;
+
+ QVariant data(const QModelIndex &index, int role) 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 &index) const override;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ void setGraphicsView(GraphicsView *view);
+
+protected:
+ GraphicsView *graphicsView() const;
+
+ void initialize();
+
+ TreeItem *root();
+
+ TreeItem *find(unsigned int id);
+
+private:
+ GraphicsView *m_view;
+
+ TreeItem *m_root;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp
new file mode 100644
index 0000000000..3b9a4ef7c5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "treeview.h"
+#include "curveeditormodel.h"
+#include "curveitem.h"
+#include "treeitem.h"
+#include "treeitemdelegate.h"
+
+#include <QHeaderView>
+#include <QMouseEvent>
+
+namespace DesignTools {
+
+TreeView::TreeView(CurveEditorModel *model, QWidget *parent)
+ : QTreeView(parent)
+{
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ setUniformRowHeights(true);
+ setRootIsDecorated(false);
+ setMouseTracking(true);
+ setHeaderHidden(true);
+
+ model->setParent(this);
+ setModel(model);
+
+ auto expandItems = [this]() { expandAll(); };
+ connect(model, &QAbstractItemModel::modelReset, expandItems);
+
+ auto *delegate = new TreeItemDelegate(model->style(), this);
+ setItemDelegate(delegate);
+
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+ connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &TreeView::changeSelection);
+ setStyle(model->style());
+
+ header()->setSectionResizeMode(0, QHeaderView::Stretch);
+ header()->setSectionResizeMode(1, QHeaderView::Fixed);
+ header()->setSectionResizeMode(2, QHeaderView::Fixed);
+
+ header()->setStretchLastSection(false);
+ header()->resizeSection(1, 20);
+ header()->resizeSection(2, 20);
+}
+
+void TreeView::setStyle(const CurveEditorStyle &style)
+{
+ QPalette pal = palette();
+ pal.setBrush(QPalette::Base, style.backgroundBrush);
+ pal.setBrush(QPalette::Button, style.backgroundAlternateBrush);
+ pal.setBrush(QPalette::Text, style.fontColor);
+
+ // Tmp to see what happens on windows/macOS.
+ pal.setBrush(backgroundRole(), Qt::white);
+ pal.setBrush(foregroundRole(), Qt::white);
+
+ setPalette(pal);
+
+ if (auto *delegate = qobject_cast<TreeItemDelegate *>(itemDelegate()))
+ delegate->setStyle(style);
+}
+
+void TreeView::changeCurve(unsigned int id, const AnimationCurve &curve)
+{
+ if (auto *curveModel = qobject_cast<CurveEditorModel *>(model()))
+ curveModel->setCurve(id, curve);
+}
+
+void TreeView::changeSelection(const QItemSelection &selected, const QItemSelection &deselected)
+{
+ Q_UNUSED(selected);
+ Q_UNUSED(deselected);
+
+ std::vector<CurveItem *> curves;
+ for (auto index : selectedIndexes()) {
+ if (index.isValid() && index.column() == 0) {
+ auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
+ if (auto *propertyItem = treeItem->asPropertyItem())
+ curves.push_back(new CurveItem(treeItem->id(), propertyItem->curve()));
+ }
+ }
+
+ emit curvesSelected(curves);
+}
+
+QSize TreeView::sizeHint() const
+{
+ return QSize(170, 300);
+}
+
+void TreeView::mousePressEvent(QMouseEvent *event)
+{
+ QModelIndex index = indexAt(event->pos());
+ if (index.isValid()) {
+ auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
+ if (index.column() == 1)
+ treeItem->setLocked(!treeItem->locked());
+ else if (index.column() == 2)
+ treeItem->setPinned(!treeItem->pinned());
+ }
+ QTreeView::mousePressEvent(event);
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treeview.h b/src/plugins/qmldesigner/components/curveeditor/detail/treeview.h
new file mode 100644
index 0000000000..9d3af647ad
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treeview.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QTreeView>
+
+namespace DesignTools {
+
+class AnimationCurve;
+class CurveEditorModel;
+class CurveItem;
+
+struct CurveEditorStyle;
+
+class TreeView : public QTreeView
+{
+ Q_OBJECT
+
+signals:
+ void curvesSelected(const std::vector<CurveItem *> &curves);
+
+public:
+ TreeView(CurveEditorModel *model, QWidget *parent = nullptr);
+
+ void changeCurve(unsigned int id, const AnimationCurve &curve);
+
+ void setStyle(const CurveEditorStyle &style);
+
+protected:
+ QSize sizeHint() const override;
+
+ void mousePressEvent(QMouseEvent *event) override;
+
+private:
+ void changeSelection(const QItemSelection &selected, const QItemSelection &deselected);
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/utils.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/utils.cpp
new file mode 100644
index 0000000000..4933bcbe88
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/utils.cpp
@@ -0,0 +1,107 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QPalette>
+#include <QPointF>
+#include <QRectF>
+#include <QTransform>
+
+namespace DesignTools {
+
+double clamp(double val, double lo, double hi)
+{
+ return val < lo ? lo : (val > hi ? hi : val);
+}
+
+double lerp(double blend, double a, double b)
+{
+ return (1.0 - blend) * a + blend * b;
+}
+
+double scaleX(const QTransform &transform)
+{
+ return transform.m11();
+}
+
+double scaleY(const QTransform &transform)
+{
+ return transform.m22();
+}
+
+void grow(QRectF &rect, const QPointF &point)
+{
+ if (rect.left() > point.x())
+ rect.setLeft(point.x());
+
+ if (rect.right() < point.x())
+ rect.setRight(point.x());
+
+ if (rect.top() > point.y())
+ rect.setTop(point.y());
+
+ if (rect.bottom() < point.y())
+ rect.setBottom(point.y());
+}
+
+QRectF bbox(const QRectF &rect, const QTransform &transform)
+{
+ QRectF out = rect;
+ grow(out, transform.map(rect.topLeft()));
+ grow(out, transform.map(rect.topRight()));
+ grow(out, transform.map(rect.bottomLeft()));
+ grow(out, transform.map(rect.bottomRight()));
+ return out;
+}
+
+QPalette singleColorPalette(const QColor &color)
+{
+ QPalette palette;
+ palette.setColor(QPalette::Window, color);
+ palette.setColor(QPalette::Background, color);
+ palette.setColor(QPalette::WindowText, color);
+ palette.setColor(QPalette::Foreground, color);
+ palette.setColor(QPalette::Base, color);
+ palette.setColor(QPalette::AlternateBase, color);
+ palette.setColor(QPalette::ToolTipBase, color);
+ palette.setColor(QPalette::ToolTipText, color);
+ palette.setColor(QPalette::Text, color);
+
+ palette.setColor(QPalette::Button, color);
+ palette.setColor(QPalette::ButtonText, color);
+ palette.setColor(QPalette::BrightText, color);
+ palette.setColor(QPalette::Light, color);
+ palette.setColor(QPalette::Midlight, color);
+ palette.setColor(QPalette::Dark, color);
+ palette.setColor(QPalette::Mid, color);
+ palette.setColor(QPalette::Shadow, color);
+ palette.setColor(QPalette::Highlight, color);
+ palette.setColor(QPalette::HighlightedText, color);
+ palette.setColor(QPalette::Link, color);
+ palette.setColor(QPalette::LinkVisited, color);
+ return palette;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/utils.h b/src/plugins/qmldesigner/components/curveeditor/detail/utils.h
new file mode 100644
index 0000000000..77cbd2c7bf
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/utils.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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
+
+QT_BEGIN_NAMESPACE
+class QColor;
+class QPalette;
+class QPointF;
+class QRectF;
+class QTransform;
+QT_END_NAMESPACE
+
+namespace DesignTools {
+
+double clamp(double val, double lo, double hi);
+
+double lerp(double blend, double a, double b);
+
+double scaleX(const QTransform &transform);
+
+double scaleY(const QTransform &transform);
+
+void grow(QRectF &rect, const QPointF &point);
+
+QRectF bbox(const QRectF &rect, const QTransform &transform);
+
+QPalette singleColorPalette(const QColor &color);
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/keyframe.cpp b/src/plugins/qmldesigner/components/curveeditor/keyframe.cpp
new file mode 100644
index 0000000000..8ff577c0a5
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/keyframe.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "keyframe.h"
+
+namespace DesignTools {
+
+Keyframe::Keyframe()
+ : m_position()
+ , m_leftHandle()
+ , m_rightHandle()
+{}
+
+Keyframe::Keyframe(const QPointF &position)
+ : m_position(position)
+ , m_leftHandle()
+ , m_rightHandle()
+{}
+
+Keyframe::Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle)
+ : m_position(position)
+ , m_leftHandle(leftHandle)
+ , m_rightHandle(rightHandle)
+{}
+
+bool Keyframe::hasLeftHandle() const
+{
+ return !m_leftHandle.isNull();
+}
+
+bool Keyframe::hasRightHandle() const
+{
+ return !m_rightHandle.isNull();
+}
+
+QPointF Keyframe::position() const
+{
+ return m_position;
+}
+
+QPointF Keyframe::leftHandle() const
+{
+ return m_leftHandle;
+}
+
+QPointF Keyframe::rightHandle() const
+{
+ return m_rightHandle;
+}
+
+void Keyframe::setPosition(const QPointF &pos)
+{
+ m_position = pos;
+}
+
+void Keyframe::setLeftHandle(const QPointF &pos)
+{
+ m_leftHandle = pos;
+}
+
+void Keyframe::setRightHandle(const QPointF &pos)
+{
+ m_rightHandle = pos;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/keyframe.h b/src/plugins/qmldesigner/components/curveeditor/keyframe.h
new file mode 100644
index 0000000000..5e6042531b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/keyframe.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QPointF>
+
+namespace DesignTools {
+
+class Keyframe
+{
+public:
+ Keyframe();
+
+ Keyframe(const QPointF &position);
+
+ Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle);
+
+ bool hasLeftHandle() const;
+
+ bool hasRightHandle() const;
+
+ QPointF position() const;
+
+ QPointF leftHandle() const;
+
+ QPointF rightHandle() const;
+
+ void setPosition(const QPointF &pos);
+
+ void setLeftHandle(const QPointF &pos);
+
+ void setRightHandle(const QPointF &pos);
+
+private:
+ QPointF m_position;
+
+ QPointF m_leftHandle;
+
+ QPointF m_rightHandle;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/treeitem.cpp b/src/plugins/qmldesigner/components/curveeditor/treeitem.cpp
new file mode 100644
index 0000000000..beed419e54
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/treeitem.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "treeitem.h"
+
+#include <QIcon>
+#include <QVariant>
+
+namespace DesignTools {
+
+TreeItem::TreeItem(const QString &name)
+ : m_name(name)
+ , m_id(0)
+ , m_locked(false)
+ , m_pinned(false)
+ , m_parent(nullptr)
+ , m_children()
+{}
+
+TreeItem::~TreeItem()
+{
+ m_parent = nullptr;
+
+ qDeleteAll(m_children);
+}
+
+QIcon TreeItem::icon() const
+{
+ return QIcon();
+}
+
+NodeTreeItem *TreeItem::asNodeItem()
+{
+ return nullptr;
+}
+
+PropertyTreeItem *TreeItem::asPropertyItem()
+{
+ return nullptr;
+}
+
+unsigned int TreeItem::id() const
+{
+ return m_id;
+}
+
+bool TreeItem::locked() const
+{
+ return m_locked;
+}
+
+bool TreeItem::pinned() const
+{
+ return m_pinned;
+}
+
+int TreeItem::row() const
+{
+ if (m_parent) {
+ for (size_t i = 0; i < m_parent->m_children.size(); ++i) {
+ if (m_parent->m_children[i] == this)
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+int TreeItem::column() const
+{
+ return 0;
+}
+
+int TreeItem::rowCount() const
+{
+ return m_children.size();
+}
+
+int TreeItem::columnCount() const
+{
+ return 3;
+}
+
+TreeItem *TreeItem::parent() const
+{
+ return m_parent;
+}
+
+TreeItem *TreeItem::child(int row) const
+{
+ if (row < 0 || row >= static_cast<int>(m_children.size()))
+ return nullptr;
+
+ return m_children.at(row);
+}
+
+TreeItem *TreeItem::find(unsigned int id) const
+{
+ for (auto *child : m_children) {
+ if (child->id() == id)
+ return child;
+
+ if (auto *childsChild = child->find(id))
+ return childsChild;
+ }
+
+ return nullptr;
+}
+
+QVariant TreeItem::data(int column) const
+{
+ switch (column) {
+ case 0:
+ return QVariant(m_name);
+ case 1:
+ return QVariant(m_locked);
+ case 2:
+ return QVariant(m_pinned);
+ case 3:
+ return QVariant(m_id);
+ default:
+ return QVariant();
+ }
+}
+
+QVariant TreeItem::headerData(int column) const
+{
+ switch (column) {
+ case 0:
+ return QString("Name");
+ case 1:
+ return QString("L");
+ case 2:
+ return QString("P");
+ case 3:
+ return QString("Id");
+ default:
+ return QVariant();
+ }
+}
+
+void TreeItem::setId(unsigned int &id)
+{
+ m_id = id;
+
+ for (auto *child : m_children)
+ child->setId(++id);
+}
+
+void TreeItem::addChild(TreeItem *child)
+{
+ child->m_parent = this;
+ m_children.push_back(child);
+}
+
+void TreeItem::setLocked(bool locked)
+{
+ m_locked = locked;
+}
+
+void TreeItem::setPinned(bool pinned)
+{
+ m_pinned = pinned;
+}
+
+
+NodeTreeItem::NodeTreeItem(const QString &name, const QIcon &icon)
+ : TreeItem(name)
+ , m_icon(icon)
+{
+ Q_UNUSED(icon);
+}
+
+NodeTreeItem *NodeTreeItem::asNodeItem()
+{
+ return this;
+}
+
+QIcon NodeTreeItem::icon() const
+{
+ return m_icon;
+}
+
+
+PropertyTreeItem::PropertyTreeItem(const QString &name, const AnimationCurve &curve)
+ : TreeItem(name)
+ , m_curve(curve)
+{}
+
+PropertyTreeItem *PropertyTreeItem::asPropertyItem()
+{
+ return this;
+}
+
+AnimationCurve PropertyTreeItem::curve() const
+{
+ return m_curve;
+}
+
+void PropertyTreeItem::setCurve(const AnimationCurve &curve)
+{
+ m_curve = curve;
+}
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/curveeditor/treeitem.h b/src/plugins/qmldesigner/components/curveeditor/treeitem.h
new file mode 100644
index 0000000000..5b31dc2fc8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/curveeditor/treeitem.h
@@ -0,0 +1,137 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "animationcurve.h"
+
+#include <QIcon>
+#include <QString>
+
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+class QIcon;
+class QVariant;
+QT_END_NAMESPACE
+
+namespace DesignTools {
+
+class NodeTreeItem;
+class PropertyTreeItem;
+
+class TreeItem
+{
+public:
+ TreeItem(const QString &name);
+
+ virtual ~TreeItem();
+
+ virtual QIcon icon() const;
+
+ virtual NodeTreeItem *asNodeItem();
+
+ virtual PropertyTreeItem *asPropertyItem();
+
+ unsigned int id() const;
+
+ bool locked() const;
+
+ bool pinned() const;
+
+ int row() const;
+
+ int column() const;
+
+ int rowCount() const;
+
+ int columnCount() const;
+
+ TreeItem *parent() const;
+
+ TreeItem *child(int row) const;
+
+ TreeItem *find(unsigned int row) const;
+
+ QVariant data(int column) const;
+
+ QVariant headerData(int column) const;
+
+ void setId(unsigned int &id);
+
+ void addChild(TreeItem *child);
+
+ void setLocked(bool locked);
+
+ void setPinned(bool pinned);
+
+protected:
+ QString m_name;
+
+ unsigned int m_id;
+
+ bool m_locked;
+
+ bool m_pinned;
+
+ TreeItem *m_parent;
+
+ std::vector<TreeItem *> m_children;
+};
+
+
+class NodeTreeItem : public TreeItem
+{
+public:
+ NodeTreeItem(const QString &name, const QIcon &icon);
+
+ NodeTreeItem *asNodeItem() override;
+
+ QIcon icon() const override;
+
+private:
+ QIcon m_icon;
+};
+
+
+class PropertyTreeItem : public TreeItem
+{
+public:
+ PropertyTreeItem(const QString &name, const AnimationCurve &curve);
+
+ PropertyTreeItem *asPropertyItem() override;
+
+ AnimationCurve curve() const;
+
+ void setCurve(const AnimationCurve &curve);
+
+private:
+ using TreeItem::addChild;
+
+ AnimationCurve m_curve;
+};
+
+} // End namespace DesignTools.
diff --git a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
index 356fbf4f32..6d3cef0fbd 100644
--- a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
@@ -64,7 +64,7 @@ QWidget *BackgroundAction::createWidget(QWidget *parent)
}
comboBox->setCurrentIndex(0);
- connect(comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &BackgroundAction::emitBackgroundChanged);
comboBox->setProperty("hideborder", true);
diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
index 0737e2ab45..6446e2422f 100644
--- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
@@ -42,7 +42,6 @@ static Q_LOGGING_CATEGORY(dragToolInfo, "qtc.qmldesigner.formeditor", QtWarningM
namespace QmlDesigner {
-
DragTool::DragTool(FormEditorView *editorView)
: AbstractFormEditorTool(editorView),
m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
index 2cc524c799..9f6d3e9cd8 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
@@ -41,7 +41,6 @@
namespace QmlDesigner {
-
FormEditorScene *FormEditorItem::scene() const {
return qobject_cast<FormEditorScene*>(QGraphicsItem::scene());
}
@@ -110,7 +109,7 @@ void FormEditorItem::updateGeometry()
m_boundingRect = m_paintedBoundingRect.united(m_selectionBoundingRect);
setTransform(qmlItemNode().instanceTransformWithContentTransform());
//the property for zValue is called z in QGraphicsObject
- if (qmlItemNode().instanceValue("z").isValid())
+ if (qmlItemNode().instanceValue("z").isValid() && !qmlItemNode().isRootModelNode())
setZValue(qmlItemNode().instanceValue("z").toDouble());
}
@@ -260,7 +259,7 @@ static void paintTextInPlaceHolderForInvisbleItem(QPainter *painter,
QFontMetrics fm(font);
painter->rotate(90);
- if (fm.width(displayText) > (boundingRect.height() - 32) && displayText.length() > 4) {
+ if (fm.horizontalAdvance(displayText) > (boundingRect.height() - 32) && displayText.length() > 4) {
displayText = fm.elidedText(displayText, Qt::ElideRight, boundingRect.height() - 32, Qt::TextShowMnemonic);
}
diff --git a/src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp b/src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp
index 0ce0a995ba..27bfbe4f83 100644
--- a/src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/numberseriesaction.cpp
@@ -59,7 +59,7 @@ QWidget *NumberSeriesAction::createWidget(QWidget *parent)
comboBox->setModel(m_comboBoxModel.data());
comboBox->setCurrentIndex(m_comboBoxModelIndex);
- connect(comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &NumberSeriesAction::emitValueChanged);
return comboBox;
diff --git a/src/plugins/qmldesigner/components/importmanager/importswidget.cpp b/src/plugins/qmldesigner/components/importmanager/importswidget.cpp
index 0d2218a42b..07ada7c858 100644
--- a/src/plugins/qmldesigner/components/importmanager/importswidget.cpp
+++ b/src/plugins/qmldesigner/components/importmanager/importswidget.cpp
@@ -39,7 +39,7 @@ ImportsWidget::ImportsWidget(QWidget *parent) :
{
setWindowTitle(tr("Import Manager"));
m_addImportComboBox = new ImportManagerComboBox(this);
- connect(m_addImportComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_addImportComboBox, QOverload<int>::of(&QComboBox::activated),
this, &ImportsWidget::addSelectedImport);
}
diff --git a/src/plugins/qmldesigner/components/integration/componentaction.cpp b/src/plugins/qmldesigner/components/integration/componentaction.cpp
index daedbe8d7d..c3c6875d63 100644
--- a/src/plugins/qmldesigner/components/integration/componentaction.cpp
+++ b/src/plugins/qmldesigner/components/integration/componentaction.cpp
@@ -53,7 +53,7 @@ QWidget *ComponentAction::createWidget(QWidget *parent)
comboBox->setToolTip(tr("Edit sub components defined in this file."));
comboBox->setModel(m_componentView->standardItemModel());
comboBox->setCurrentIndex(-1);
- connect(comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(comboBox, QOverload<int>::of(&QComboBox::activated),
this, &ComponentAction::emitCurrentComponentChanged);
connect(this, &ComponentAction::currentIndexChanged, comboBox, &QComboBox::setCurrentIndex);
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp
index 7a0f1f10b5..4f23154945 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp
@@ -64,7 +64,6 @@ enum {
namespace QmlDesigner {
-
/**
\class QmlDesigner::DesignDocument
@@ -197,7 +196,7 @@ QString DesignDocument::simplfiedDisplayName() const
return rootModelNode().simplifiedTypeName();
}
-void DesignDocument::updateFileName(const Utils::FileName & /*oldFileName*/, const Utils::FileName &newFileName)
+void DesignDocument::updateFileName(const Utils::FilePath & /*oldFileName*/, const Utils::FilePath &newFileName)
{
if (m_documentModel)
m_documentModel->setFileUrl(QUrl::fromLocalFile(newFileName.toString()));
@@ -210,11 +209,11 @@ void DesignDocument::updateFileName(const Utils::FileName & /*oldFileName*/, con
emit displayNameChanged(displayName());
}
-Utils::FileName DesignDocument::fileName() const
+Utils::FilePath DesignDocument::fileName() const
{
if (editor())
return editor()->document()->filePath();
- return Utils::FileName();
+ return Utils::FilePath();
}
Kit *DesignDocument::currentKit() const
@@ -251,7 +250,7 @@ void DesignDocument::loadDocument(QPlainTextEdit *edit)
m_inFileComponentTextModifier.reset();
- updateFileName(Utils::FileName(), fileName());
+ updateFileName(Utils::FilePath(), fileName());
updateQrcFiles();
@@ -288,7 +287,7 @@ void DesignDocument::updateQrcFiles()
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(fileName());
if (currentProject) {
- for (const Utils::FileName &fileName : currentProject->files(ProjectExplorer::Project::SourceFiles)) {
+ for (const Utils::FilePath &fileName : currentProject->files(ProjectExplorer::Project::SourceFiles)) {
if (fileName.endsWith(".qrc"))
QmlJS::ModelManagerInterface::instance()->updateQrcFile(fileName.toString());
}
@@ -366,18 +365,13 @@ void DesignDocument::deleteSelected()
if (!currentModel())
return;
- try {
- RewriterTransaction transaction(rewriterView(), QByteArrayLiteral("DesignDocument::deleteSelected"));
+ rewriterView()->executeInTransaction("DesignDocument::deleteSelected", [this](){
QList<ModelNode> toDelete = view()->selectedModelNodes();
foreach (ModelNode node, toDelete) {
if (node.isValid() && !node.isRootNode() && QmlObjectNode::isValidQmlObjectNode(node))
QmlObjectNode(node).destroy();
}
-
- transaction.commit();
- } catch (const RewritingException &e) {
- e.showException();
- }
+ });
}
void DesignDocument::copySelected()
@@ -466,10 +460,8 @@ void DesignDocument::paste()
}
}
- QList<ModelNode> pastedNodeList;
-
- try {
- RewriterTransaction transaction(rewriterView(), QByteArrayLiteral("DesignDocument::paste1"));
+ rewriterView()->executeInTransaction("DesignDocument::paste1", [this, &view, selectedNodes, targetNode](){
+ QList<ModelNode> pastedNodeList;
int offset = double(qrand()) / RAND_MAX * 20 - 10;
@@ -482,14 +474,10 @@ void DesignDocument::paste()
}
view.setSelectedModelNodes(pastedNodeList);
- transaction.commit();
- } catch (const RewritingException &e) {
- qWarning() << e.description(); //silent error
- }
- } else {
- try {
- RewriterTransaction transaction(rewriterView(), QByteArrayLiteral("DesignDocument::paste2"));
+ });
+ } else {
+ rewriterView()->executeInTransaction("DesignDocument::paste1", [this, &view, selectedNodes, rootNode](){
currentModel()->attachView(&view);
ModelNode pastedNode(view.insertModel(rootNode));
ModelNode targetNode;
@@ -501,9 +489,9 @@ void DesignDocument::paste()
targetNode = view.rootModelNode();
if (targetNode.hasParentProperty() &&
- (pastedNode.simplifiedTypeName() == targetNode.simplifiedTypeName()) &&
- (pastedNode.variantProperty("width").value() == targetNode.variantProperty("width").value()) &&
- (pastedNode.variantProperty("height").value() == targetNode.variantProperty("height").value()))
+ (pastedNode.simplifiedTypeName() == targetNode.simplifiedTypeName()) &&
+ (pastedNode.variantProperty("width").value() == targetNode.variantProperty("width").value()) &&
+ (pastedNode.variantProperty("height").value() == targetNode.variantProperty("height").value()))
targetNode = targetNode.parentProperty().parentModelNode();
@@ -515,15 +503,9 @@ void DesignDocument::paste()
} else {
qWarning() << "Cannot reparent to" << targetNode;
}
-
- transaction.commit();
- NodeMetaInfo::clearCache();
-
view.setSelectedModelNodes({pastedNode});
- transaction.commit();
- } catch (const RewritingException &e) {
- qWarning() << e.description(); //silent error
- }
+ });
+ NodeMetaInfo::clearCache();
}
}
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h
index 0bb5377c6d..eba0cf4060 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.h
+++ b/src/plugins/qmldesigner/components/integration/designdocument.h
@@ -90,7 +90,7 @@ public:
TextEditor::BaseTextEditor *textEditor() const;
QPlainTextEdit *plainTextEdit() const;
- Utils::FileName fileName() const;
+ Utils::FilePath fileName() const;
ProjectExplorer::Kit *currentKit() const;
bool isDocumentLoaded() const;
@@ -121,7 +121,7 @@ public:
void changeToMaster();
private: // functions
- void updateFileName(const Utils::FileName &oldFileName, const Utils::FileName &newFileName);
+ void updateFileName(const Utils::FilePath &oldFileName, const Utils::FilePath &newFileName);
void changeToInFileComponentModel(ComponentTextModifier *textModifer);
diff --git a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp
index 089a540b8f..8739ec64a8 100644
--- a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp
+++ b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp
@@ -137,7 +137,7 @@ static QRect drawText(QPainter *painter,
displayString = styleOption.fontMetrics.elidedText(displayString, Qt::ElideMiddle, styleOption.rect.width() - extraSpace);
displayStringOffset = QPoint(5 + iconOffset, -5);
- width = styleOption.fontMetrics.width(displayString);
+ width = styleOption.fontMetrics.horizontalAdvance(displayString);
QPoint textPosition = styleOption.rect.bottomLeft() + displayStringOffset;
painter->drawText(textPosition, displayString);
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 126fed8e68..8c89acb7c8 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -246,14 +246,29 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const
| Qt::ItemNeverHasChildren;
}
+void static appendForcedNodes(const NodeListProperty &property, QList<ModelNode> &list)
+{
+ const QStringList visibleProperties = NodeHints::fromModelNode(property.parentModelNode()).visibleNonDefaultProperties();
+ for (const ModelNode &node : property.parentModelNode().directSubModelNodes()) {
+ if (!list.contains(node) && visibleProperties.contains(QString::fromUtf8(node.parentProperty().name())))
+ list.append(node);
+ }
+}
+
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter)
{
if (!filter)
return property.toModelNodeList();
- return Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
+ QList<ModelNode> list;
+
+ list.append(Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
return QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator();
- });
+ }));
+
+ appendForcedNodes(property, list);
+
+ return list;
}
QModelIndex NavigatorTreeModel::index(int row, int column,
@@ -431,7 +446,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
static bool findTargetProperty(const QModelIndex &rowModelIndex,
NavigatorTreeModel *navigatorTreeModel,
NodeAbstractProperty *targetProperty,
- int *targetRowNumber)
+ int *targetRowNumber,
+ const PropertyName &propertyName = {})
{
QModelIndex targetItemIndex;
PropertyName targetPropertyName;
@@ -445,7 +461,10 @@ static bool findTargetProperty(const QModelIndex &rowModelIndex,
if (!targetNode.metaInfo().hasDefaultProperty())
return false;
- targetPropertyName = targetNode.metaInfo().defaultPropertyName();
+ if (propertyName.isEmpty() || !targetNode.metaInfo().hasProperty(propertyName))
+ targetPropertyName = targetNode.metaInfo().defaultPropertyName();
+ else
+ targetPropertyName = propertyName;
}
// Disallow dropping items between properties, which are listed first.
@@ -494,26 +513,30 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
int targetRowNumber = rowNumber;
NodeAbstractProperty targetProperty;
- bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber);
+ const ItemLibraryEntry itemLibraryEntry =
+ createItemLibraryEntryFromMimeData(mimeData->data("application/vnd.bauhaus.itemlibraryinfo"));
- if (foundTarget) {
- const ItemLibraryEntry itemLibraryEntry =
- createItemLibraryEntryFromMimeData(mimeData->data("application/vnd.bauhaus.itemlibraryinfo"));
+ const NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry);
+
+ const QString targetPropertyName = hints.forceNonDefaultProperty();
+ bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber, targetPropertyName.toUtf8());
+
+ if (foundTarget) {
if (!NodeHints::fromItemLibraryEntry(itemLibraryEntry).canBeDroppedInNavigator())
return;
- const QmlItemNode newQmlItemNode = QmlItemNode::createQmlItemNode(m_view, itemLibraryEntry, QPointF(), targetProperty);
+ const QmlObjectNode newQmlObjectNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, QPointF(), targetProperty);
- if (newQmlItemNode.isValid() && targetProperty.isNodeListProperty()) {
+ if (newQmlObjectNode.isValid() && targetProperty.isNodeListProperty()) {
QList<ModelNode> newModelNodeList;
- newModelNodeList.append(newQmlItemNode);
+ newModelNodeList.append(newQmlObjectNode);
moveNodesInteractive(targetProperty, newModelNodeList, targetRowNumber);
}
- if (newQmlItemNode.isValid())
- m_view->selectModelNode(newQmlItemNode.modelNode());
+ if (newQmlObjectNode.isValid())
+ m_view->selectModelNode(newQmlObjectNode.modelNode());
}
}
@@ -545,10 +568,9 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i
void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes, int targetIndex)
{
QTC_ASSERT(m_view, return);
- try {
- const TypeName propertyQmlType = parentProperty.parentModelNode().metaInfo().propertyTypeName(parentProperty.name());
- RewriterTransaction transaction = m_view->beginRewriterTransaction(QByteArrayLiteral("NavigatorTreeModel::moveNodesInteractive"));
+ m_view->executeInTransaction("NavigatorTreeModel::moveNodesInteractive",[this, &parentProperty, modelNodes, targetIndex](){
+ const TypeName propertyQmlType = parentProperty.parentModelNode().metaInfo().propertyTypeName(parentProperty.name());
foreach (const ModelNode &modelNode, modelNodes) {
if (modelNode.isValid()
&& modelNode != parentProperty.parentModelNode()
@@ -565,10 +587,7 @@ void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProper
}
}
}
- transaction.commit();
- } catch (const RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
- }
+ });
}
Qt::DropActions NavigatorTreeModel::supportedDropActions() const
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreeview.h b/src/plugins/qmldesigner/components/navigator/navigatortreeview.h
index cc5a0e344d..1001977b8f 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreeview.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreeview.h
@@ -29,7 +29,6 @@
namespace QmlDesigner {
-
class NavigatorTreeView : public QTreeView
{
Q_OBJECT
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index 07434102fc..57578d866f 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -198,16 +198,10 @@ void NavigatorView::handleChangedExport(const ModelNode &modelNode, bool exporte
if (rootNode.hasProperty(modelNodeId))
rootNode.removeProperty(modelNodeId);
if (exported) {
- try {
- RewriterTransaction transaction =
- beginRewriterTransaction(QByteArrayLiteral("NavigatorTreeModel:exportItem"));
-
+ executeInTransaction("NavigatorTreeModel:exportItem", [this, modelNode](){
QmlObjectNode qmlObjectNode(modelNode);
qmlObjectNode.ensureAliasExport();
- transaction.commit();
- } catch (RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
- }
+ });
}
}
@@ -400,7 +394,8 @@ void NavigatorView::upButtonClicked()
index--;
if (index < 0)
index = node.parentProperty().count() - 1; //wrap around
- node.parentProperty().toNodeListProperty().slide(oldIndex, index);
+ if (oldIndex != index)
+ node.parentProperty().toNodeListProperty().slide(oldIndex, index);
}
}
updateItemSelection();
@@ -417,7 +412,8 @@ void NavigatorView::downButtonClicked()
index++;
if (index >= node.parentProperty().count())
index = 0; //wrap around
- node.parentProperty().toNodeListProperty().slide(oldIndex, index);
+ if (oldIndex != index)
+ node.parentProperty().toNodeListProperty().slide(oldIndex, index);
}
}
updateItemSelection();
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/controlpoint.cpp b/src/plugins/qmldesigner/components/pathtool/controlpoint.cpp
index d2a8bf75c3..d2a8bf75c3 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/controlpoint.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/controlpoint.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/controlpoint.h b/src/plugins/qmldesigner/components/pathtool/controlpoint.h
index 39dc184978..39dc184978 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/controlpoint.h
+++ b/src/plugins/qmldesigner/components/pathtool/controlpoint.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/cubicsegment.cpp b/src/plugins/qmldesigner/components/pathtool/cubicsegment.cpp
index 0005514339..0005514339 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/cubicsegment.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/cubicsegment.cpp
diff --git a/src/plugins/qmldesigner/components/pathtool/cubicsegment.h b/src/plugins/qmldesigner/components/pathtool/cubicsegment.h
new file mode 100644
index 0000000000..e22b4e1aa3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pathtool/cubicsegment.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "controlpoint.h"
+
+#include <modelnode.h>
+
+#include <QMap>
+
+#include <QPointF>
+#include <QExplicitlySharedDataPointer>
+
+namespace QmlDesigner {
+
+class CubicSegmentData : public QSharedData
+{
+public:
+ CubicSegmentData();
+ ModelNode modelNode;
+ ControlPoint firstControllPoint;
+ ControlPoint secondControllPoint;
+ ControlPoint thirdControllPoint;
+ ControlPoint fourthControllPoint;
+ QMap<QString, QVariant> attributes;
+ double percent;
+};
+
+class CubicSegment
+{
+ friend bool operator ==(const CubicSegment& firstCubicSegment, const CubicSegment& secondCubicSegment);
+
+public:
+ CubicSegment();
+
+ static CubicSegment create();
+
+ void setModelNode(const ModelNode &modelNode);
+ ModelNode modelNode() const;
+
+ void setFirstControlPoint(const ControlPoint &firstControlPoint);
+ void setFirstControlPoint(double x, double y);
+ void setFirstControlPoint(const QPointF &coordiante);
+
+ void setSecondControlPoint(const ControlPoint &secondControlPoint);
+ void setSecondControlPoint(double x, double y);
+ void setSecondControlPoint(const QPointF &coordiante);
+
+ void setThirdControlPoint(const ControlPoint &thirdControlPoint);
+ void setThirdControlPoint(double x, double y);
+ void setThirdControlPoint(const QPointF &coordiante);
+
+ void setFourthControlPoint(const ControlPoint &fourthControlPoint);
+ void setFourthControlPoint(double x, double y);
+ void setFourthControlPoint(const QPointF &coordiante);
+
+ void setAttributes(const QMap<QString, QVariant> &attributes);
+
+ void setPercent(double percent);
+
+ ControlPoint firstControlPoint() const;
+ ControlPoint secondControlPoint() const;
+ ControlPoint thirdControlPoint() const;
+ ControlPoint fourthControlPoint() const;
+
+ const QMap<QString, QVariant> attributes() const;
+
+ double percent() const;
+
+ QList<ControlPoint> controlPoints() const;
+
+ double firstControlX() const;
+ double firstControlY() const;
+ double secondControlX() const;
+ double secondControlY() const;
+ double thirdControlX() const;
+ double thirdControlY() const;
+ double fourthControlX() const;
+ double fourthControlY() const;
+ double quadraticControlX() const;
+ double quadraticControlY() const;
+
+ bool isValid() const;
+ bool canBeConvertedToLine() const;
+ bool canBeConvertedToQuad() const;
+
+ QPointF sample(double t) const;
+ double minimumDistance(const QPointF &pickPoint, double &t) const;
+
+ QPair<CubicSegment, CubicSegment> split(double t);
+
+ void makeStraightLine();
+
+ void updateModelNode();
+
+private:
+ QExplicitlySharedDataPointer<CubicSegmentData> d;
+};
+
+bool operator ==(const CubicSegment& firstCubicSegment, const CubicSegment& secondCubicSegment);
+QDebug operator<<(QDebug debug, const CubicSegment &cubicSegment);
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/pathtool/pathitem.cpp b/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
new file mode 100644
index 0000000000..76fe6f0b90
--- /dev/null
+++ b/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
@@ -0,0 +1,971 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pathitem.h"
+
+#include <exception.h>
+#include <nodeproperty.h>
+#include <variantproperty.h>
+#include <nodelistproperty.h>
+#include <rewritingexception.h>
+#include <rewritertransaction.h>
+#include <formeditorscene.h>
+#include <formeditorview.h>
+#include <theme.h>
+
+#include <QPainter>
+#include <QMenu>
+#include <QtDebug>
+#include <QGraphicsSceneMouseEvent>
+
+namespace QmlDesigner {
+
+PathItem::PathItem(FormEditorScene* scene)
+ : m_selectionManipulator(this),
+ m_lastPercent(-1.),
+ m_formEditorItem(nullptr),
+ m_dontUpdatePath(false)
+{
+ scene->addItem(this);
+ setFlag(QGraphicsItem::ItemIsMovable, false);
+}
+
+PathItem::~PathItem()
+{
+ m_formEditorItem = nullptr;
+}
+
+static ModelNode pathModelNode(FormEditorItem *formEditorItem)
+{
+ ModelNode modelNode = formEditorItem->qmlItemNode().modelNode();
+
+ return modelNode.nodeProperty("path").modelNode();
+}
+
+using PropertyPair = QPair<PropertyName, QVariant>;
+
+void PathItem::writeLinePath(const ModelNode &pathNode, const CubicSegment &cubicSegment)
+{
+ QList<PropertyPair> propertyList;
+ propertyList.append(PropertyPair("x", cubicSegment.fourthControlX()));
+ propertyList.append(PropertyPair("y", cubicSegment.fourthControlY()));
+
+ ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathLine", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
+ pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
+}
+
+void PathItem::writeQuadPath(const ModelNode &pathNode, const CubicSegment &cubicSegment)
+{
+ QList<QPair<PropertyName, QVariant> > propertyList;
+ propertyList.append(PropertyPair("controlX", cubicSegment.quadraticControlX()));
+ propertyList.append(PropertyPair("controlY", cubicSegment.quadraticControlY()));
+ propertyList.append(PropertyPair("x", cubicSegment.fourthControlX()));
+ propertyList.append(PropertyPair("y", cubicSegment.fourthControlY()));
+
+ ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathQuad", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
+ pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
+}
+
+void PathItem::writeCubicPath(const ModelNode &pathNode, const CubicSegment &cubicSegment)
+{
+ QList<QPair<PropertyName, QVariant> > propertyList;
+ propertyList.append(PropertyPair("control1X", cubicSegment.secondControlX()));
+ propertyList.append(PropertyPair("control1Y", cubicSegment.secondControlY()));
+ propertyList.append(PropertyPair("control2X", cubicSegment.thirdControlX()));
+ propertyList.append(PropertyPair("control2Y", cubicSegment.thirdControlY()));
+ propertyList.append(PropertyPair("x", cubicSegment.fourthControlX()));
+ propertyList.append(PropertyPair("y", cubicSegment.fourthControlY()));
+
+ ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathCubic", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
+ pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
+}
+
+void PathItem::writePathAttributes(const ModelNode &pathNode, const QMap<QString, QVariant> &attributes)
+{
+ QMapIterator<QString, QVariant> attributesIterator(attributes);
+ while (attributesIterator.hasNext()) {
+ attributesIterator.next();
+ QList<QPair<PropertyName, QVariant> > propertyList;
+ propertyList.append(PropertyPair("name", attributesIterator.key()));
+ propertyList.append(PropertyPair("value", attributesIterator.value()));
+
+ ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathAttribute", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
+ pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
+ }
+}
+
+void PathItem::writePathPercent(const ModelNode& pathNode, double percent)
+{
+ if (percent >= 0.0) {
+ QList<QPair<PropertyName, QVariant> > propertyList;
+ propertyList.append(PropertyPair("value", percent));
+
+ ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathPercent", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
+ pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
+ }
+}
+
+void PathItem::writePathToProperty()
+{
+ PathUpdateDisabler pathUpdateDisable(this);
+
+ ModelNode pathNode = pathModelNode(formEditorItem());
+
+ pathNode.view()->executeInTransaction("PathItem::writePathToProperty", [this, &pathNode](){
+ QList<ModelNode> pathSegmentNodes = pathNode.nodeListProperty("pathElements").toModelNodeList();
+
+ foreach (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) {
+ writePathAttributes(pathNode, cubicSegment.attributes());
+ writePathPercent(pathNode, cubicSegment.percent());
+
+ if (cubicSegment.canBeConvertedToLine())
+ writeLinePath(pathNode, cubicSegment);
+ else if (cubicSegment.canBeConvertedToQuad())
+ writeQuadPath(pathNode, cubicSegment);
+ else
+ writeCubicPath(pathNode, cubicSegment);
+ }
+
+ writePathAttributes(pathNode, m_lastAttributes);
+ writePathPercent(pathNode, m_lastPercent);
+ }
+ });
+}
+
+void PathItem::writePathAsCubicSegmentsOnly()
+{
+ PathUpdateDisabler pathUpdateDisabler(this);
+
+ ModelNode pathNode = pathModelNode(formEditorItem());
+ pathNode.view()->executeInTransaction("PathItem::writePathAsCubicSegmentsOnly", [this, &pathNode](){
+
+ QList<ModelNode> pathSegmentNodes = pathNode.nodeListProperty("pathElements").toModelNodeList();
+
+ foreach (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) {
+ writePathAttributes(pathNode, cubicSegment.attributes());
+ writePathPercent(pathNode, cubicSegment.percent());
+ writeCubicPath(pathNode, cubicSegment);
+ }
+
+ writePathAttributes(pathNode, m_lastAttributes);
+ writePathPercent(pathNode, m_lastPercent);
+ }
+ });
+}
+
+void PathItem::setFormEditorItem(FormEditorItem *formEditorItem)
+{
+ m_formEditorItem = formEditorItem;
+ setTransform(formEditorItem->sceneTransform());
+ updatePath();
+
+// m_textEdit->setPlainText(m_formEditorItem->qmlItemNode().modelValue("path").toString());
+}
+
+static bool hasPath(FormEditorItem *formEditorItem)
+{
+ ModelNode modelNode = formEditorItem->qmlItemNode().modelNode();
+
+ return modelNode.hasProperty("path") && modelNode.property("path").isNodeProperty();
+}
+
+QPointF startPoint(const ModelNode &modelNode)
+{
+ QPointF point;
+
+ if (modelNode.hasProperty("startX"))
+ point.setX(modelNode.variantProperty("startX").value().toDouble());
+
+ if (modelNode.hasProperty("startY"))
+ point.setY(modelNode.variantProperty("startY").value().toDouble());
+
+ return point;
+}
+
+static void addCubicSegmentToPainterPath(const CubicSegment &cubicSegment, QPainterPath &painterPath)
+{
+ painterPath.cubicTo(cubicSegment.secondControlPoint().coordinate(),
+ cubicSegment.thirdControlPoint().coordinate(),
+ cubicSegment.fourthControlPoint().coordinate());
+
+}
+
+static void drawCubicSegments(const QList<CubicSegment> &cubicSegments, QPainter *painter)
+{
+ painter->save();
+
+ QPainterPath curvePainterPath(cubicSegments.constFirst().firstControlPoint().coordinate());
+
+ foreach (const CubicSegment &cubicSegment, cubicSegments)
+ addCubicSegmentToPainterPath(cubicSegment, curvePainterPath);
+
+ painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
+ painter->drawPath(curvePainterPath);
+
+ painter->restore();
+}
+
+static void drawControlLine(const CubicSegment &cubicSegment, QPainter *painter)
+{
+ static const QPen solidPen(QColor(104, 183, 214), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
+ painter->setPen(solidPen);
+ painter->drawLine(cubicSegment.firstControlPoint().coordinate(),
+ cubicSegment.secondControlPoint().coordinate());
+
+ QVector<double> dashVector;
+ dashVector.append(4);
+ dashVector.append(4);
+ QPen dashedPen(QColor(104, 183, 214), 1, Qt::CustomDashLine, Qt::FlatCap, Qt::MiterJoin);
+ dashedPen.setDashPattern(dashVector);
+ painter->setPen(dashedPen);
+ painter->drawLine(cubicSegment.secondControlPoint().coordinate(),
+ cubicSegment.thirdControlPoint().coordinate());
+
+ painter->setPen(QPen(QColor(104, 183, 214), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
+ painter->drawLine(cubicSegment.thirdControlPoint().coordinate(),
+ cubicSegment.fourthControlPoint().coordinate());
+}
+
+static void drawControlLines(const QList<CubicSegment> &cubicSegments, QPainter *painter)
+{
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, false);
+
+ foreach (const CubicSegment &cubicSegment, cubicSegments)
+ drawControlLine(cubicSegment, painter);
+
+ painter->restore();
+}
+
+static QRectF controlPointShape(-2, -2, 5, 5);
+
+static void drawControlPoint(const ControlPoint &controlPoint, const QList<ControlPoint> &selectionPoints, QPainter *painter)
+{
+ static const QColor editPointColor(0, 110, 255);
+ static const QColor controlVertexColor(0, 110, 255);
+ static const QColor selectionPointColor(0, 255, 0);
+
+ double originX = controlPoint.coordinate().x();
+ double originY = controlPoint.coordinate().y();
+
+ if (controlPoint.isEditPoint()) {
+ if (selectionPoints.contains(controlPoint)) {
+ painter->setBrush(selectionPointColor);
+ painter->setPen(selectionPointColor);
+ } else {
+ painter->setBrush(editPointColor);
+ painter->setPen(editPointColor);
+ }
+ painter->setRenderHint(QPainter::Antialiasing, false);
+ painter->drawRect(controlPointShape.adjusted(originX -1, originY - 1, originX - 1, originY - 1));
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ } else {
+ if (selectionPoints.contains(controlPoint)) {
+ painter->setBrush(selectionPointColor);
+ painter->setPen(selectionPointColor);
+ } else {
+ painter->setBrush(controlVertexColor);
+ painter->setPen(controlVertexColor);
+ }
+ painter->drawEllipse(controlPointShape.adjusted(originX, originY, originX, originY));
+ }
+}
+
+static void drawControlPoints(const QList<ControlPoint> &controlPoints, const QList<ControlPoint> &selectionPoints, QPainter *painter)
+{
+ painter->save();
+
+ foreach (const ControlPoint &controlPoint, controlPoints)
+ drawControlPoint(controlPoint, selectionPoints, painter);
+
+ painter->restore();
+}
+
+static void drawPositionOverlay(const ControlPoint &controlPoint, QPainter *painter)
+{
+ QPoint position = controlPoint.coordinate().toPoint();
+ position.rx() += 3;
+ position.ry() -= 3;
+
+ QString postionText(QString(QLatin1String("x: %1 y: %2")).arg(controlPoint.coordinate().x()).arg(controlPoint.coordinate().y()));
+ painter->drawText(position, postionText);
+}
+
+static void drawPostionOverlays(const QList<SelectionPoint> &selectedPoints, QPainter *painter)
+{
+ painter->save();
+ QFont font = painter->font();
+ font.setPixelSize(Theme::instance()->smallFontPixelSize());
+ painter->setFont(font);
+ painter->setPen(QColor(0, 0, 0));
+
+ foreach (const SelectionPoint &selectedPoint, selectedPoints)
+ drawPositionOverlay(selectedPoint.controlPoint, painter);
+
+ painter->restore();
+}
+
+static void drawMultiSelectionRectangle(const QRectF &selectionRectangle, QPainter *painter)
+{
+ painter->save();
+ static QColor selectionBrush(painter->pen().color());
+ selectionBrush.setAlpha(50);
+ painter->setRenderHint(QPainter::Antialiasing, false);
+ painter->setBrush(selectionBrush);
+ painter->drawRect(selectionRectangle);
+ painter->restore();
+}
+
+void PathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
+{
+ painter->save();
+
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ if (!m_cubicSegments.isEmpty()) {
+ drawCubicSegments(m_cubicSegments, painter);
+ drawControlLines(m_cubicSegments, painter);
+ drawControlPoints(controlPoints(), m_selectionManipulator.allControlPoints(), painter);
+ drawPostionOverlays(m_selectionManipulator.singleSelectedPoints(), painter);
+ if (m_selectionManipulator.isMultiSelecting())
+ drawMultiSelectionRectangle(m_selectionManipulator.multiSelectionRectangle(), painter);
+ }
+
+ painter->restore();
+}
+
+FormEditorItem *PathItem::formEditorItem() const
+{
+ return m_formEditorItem;
+}
+
+static CubicSegment createCubicSegmentForLine(const ModelNode &lineNode, const ControlPoint &startControlPoint)
+{
+ CubicSegment cubicSegment = CubicSegment::create();
+ cubicSegment.setModelNode(lineNode);
+
+ if (lineNode.hasProperty("x")
+ && lineNode.hasProperty("y")) {
+
+ QPointF controlPoint0Line = startControlPoint.coordinate();
+ QPointF controlPoint1Line(lineNode.variantProperty("x").value().toDouble(),
+ lineNode.variantProperty("y").value().toDouble());
+
+ QPointF controlPoint1Cubic = controlPoint0Line + (1./3.) * (controlPoint1Line - controlPoint0Line);
+ QPointF controlPoint2Cubic = controlPoint0Line + (2./3.) * (controlPoint1Line - controlPoint0Line);
+
+ cubicSegment.setFirstControlPoint(startControlPoint);
+ cubicSegment.setSecondControlPoint(controlPoint1Cubic);
+ cubicSegment.setThirdControlPoint(controlPoint2Cubic);
+ cubicSegment.setFourthControlPoint(controlPoint1Line);
+ } else {
+ qWarning() << "PathLine has not all entries!";
+ }
+
+ return cubicSegment;
+}
+
+static CubicSegment createCubicSegmentForQuad(const ModelNode &quadNode, const ControlPoint &startControlPoint)
+{
+ CubicSegment cubicSegment = CubicSegment::create();
+ cubicSegment.setModelNode(quadNode);
+
+ if (quadNode.hasProperty("controlX")
+ && quadNode.hasProperty("controlY")
+ && quadNode.hasProperty("x")
+ && quadNode.hasProperty("y")) {
+ QPointF controlPoint0Quad = startControlPoint.coordinate();
+ QPointF controlPoint1Quad(quadNode.variantProperty("controlX").value().toDouble(),
+ quadNode.variantProperty("controlY").value().toDouble());
+ QPointF controlPoint2Quad(quadNode.variantProperty("x").value().toDouble(),
+ quadNode.variantProperty("y").value().toDouble());
+
+ QPointF controlPoint1Cubic = controlPoint0Quad + (2./3.) * (controlPoint1Quad - controlPoint0Quad);
+ QPointF controlPoint2Cubic = controlPoint2Quad + (2./3.) * (controlPoint1Quad - controlPoint2Quad);
+
+ cubicSegment.setFirstControlPoint(startControlPoint);
+ cubicSegment.setSecondControlPoint(controlPoint1Cubic);
+ cubicSegment.setThirdControlPoint(controlPoint2Cubic);
+ cubicSegment.setFourthControlPoint(controlPoint2Quad);
+ } else {
+ qWarning() << "PathQuad has not all entries!";
+ }
+
+ return cubicSegment;
+}
+
+static CubicSegment createCubicSegmentForCubic(const ModelNode &cubicNode, const ControlPoint &startControlPoint)
+{
+ CubicSegment cubicSegment = CubicSegment::create();
+ cubicSegment.setModelNode(cubicNode);
+
+ if (cubicNode.hasProperty("control1X")
+ && cubicNode.hasProperty("control1Y")
+ && cubicNode.hasProperty("control2X")
+ && cubicNode.hasProperty("control2Y")
+ && cubicNode.hasProperty("x")
+ && cubicNode.hasProperty("y")) {
+
+ cubicSegment.setFirstControlPoint(startControlPoint);
+ cubicSegment.setSecondControlPoint(cubicNode.variantProperty("control1X").value().toDouble(),
+ cubicNode.variantProperty("control1Y").value().toDouble());
+ cubicSegment.setThirdControlPoint(cubicNode.variantProperty("control2X").value().toDouble(),
+ cubicNode.variantProperty("control2Y").value().toDouble());
+ cubicSegment.setFourthControlPoint(cubicNode.variantProperty("x").value().toDouble(),
+ cubicNode.variantProperty("y").value().toDouble());
+ } else {
+ qWarning() << "PathCubic has not all entries!";
+ }
+
+ return cubicSegment;
+}
+
+static QRectF boundingRectForPath(const QList<ControlPoint> &controlPoints)
+{
+ double xMinimum = 0.;
+ double xMaximum = 0.;
+ double yMinimum = 0.;
+ double yMaximum = 0.;
+
+ foreach (const ControlPoint & controlPoint, controlPoints) {
+ xMinimum = qMin(xMinimum, controlPoint.coordinate().x());
+ xMaximum = qMax(xMaximum, controlPoint.coordinate().x());
+ yMinimum = qMin(yMinimum, controlPoint.coordinate().y());
+ yMaximum = qMax(yMaximum, controlPoint.coordinate().y());
+ }
+
+ return QRect(xMinimum, yMinimum, xMaximum - xMinimum, yMaximum - yMinimum);
+}
+
+void PathItem::updateBoundingRect()
+{
+ QRectF controlBoundingRect = boundingRectForPath(controlPoints()).adjusted(-100, -100, 200, 100);
+
+ if (m_selectionManipulator.isMultiSelecting())
+ controlBoundingRect = controlBoundingRect.united(m_selectionManipulator.multiSelectionRectangle());
+
+ setBoundingRect(instanceBoundingRect().united(controlBoundingRect));
+}
+
+QRectF PathItem::instanceBoundingRect() const
+{
+ if (formEditorItem())
+ return formEditorItem()->qmlItemNode().instanceBoundingRect();
+
+ return {};
+}
+
+void PathItem::readControlPoints()
+{
+ ModelNode pathNode = pathModelNode(formEditorItem());
+
+ m_cubicSegments.clear();
+
+ if (pathNode.hasNodeListProperty("pathElements")) {
+ ControlPoint firstControlPoint(startPoint(pathNode));
+ firstControlPoint.setPathModelNode(pathNode);
+ firstControlPoint.setPointType(StartPoint);
+
+ QMap<QString, QVariant> actualAttributes;
+ double percent = -1.0;
+
+ foreach (const ModelNode &childNode, pathNode.nodeListProperty("pathElements").toModelNodeList()) {
+
+ if (childNode.type() == "QtQuick.PathAttribute") {
+ actualAttributes.insert(childNode.variantProperty("name").value().toString(), childNode.variantProperty("value").value());
+ } else if (childNode.type() == "QtQuick.PathPercent") {
+ percent = childNode.variantProperty("value").value().toDouble();
+ } else {
+ CubicSegment newCubicSegement;
+
+ if (childNode.type() == "QtQuick.PathLine")
+ newCubicSegement = createCubicSegmentForLine(childNode, firstControlPoint);
+ else if (childNode.type() == "QtQuick.PathQuad")
+ newCubicSegement = createCubicSegmentForQuad(childNode, firstControlPoint);
+ else if (childNode.type() == "QtQuick.PathCubic")
+ newCubicSegement = createCubicSegmentForCubic(childNode, firstControlPoint);
+ else
+ continue;
+
+ newCubicSegement.setPercent(percent);
+ newCubicSegement.setAttributes(actualAttributes);
+
+ firstControlPoint = newCubicSegement.fourthControlPoint();
+ qDebug() << "Can be converted to quad" << newCubicSegement.canBeConvertedToQuad();
+ qDebug() << "Can be converted to line" << newCubicSegement.canBeConvertedToLine();
+ m_cubicSegments.append(newCubicSegement);
+ actualAttributes.clear();
+ percent = -1.0;
+ }
+ }
+
+ m_lastAttributes = actualAttributes;
+ m_lastPercent = percent;
+
+ if (m_cubicSegments.constFirst().firstControlPoint().coordinate() == m_cubicSegments.constLast().fourthControlPoint().coordinate()) {
+ CubicSegment lastCubicSegment = m_cubicSegments.constLast();
+ lastCubicSegment.setFourthControlPoint(m_cubicSegments.constFirst().firstControlPoint());
+ lastCubicSegment.fourthControlPoint().setPathModelNode(pathNode);
+ lastCubicSegment.fourthControlPoint().setPointType(StartAndEndPoint);
+ }
+ }
+}
+
+static CubicSegment getMinimumDistanceSegment(const QPointF &pickPoint, const QList<CubicSegment> &cubicSegments, double maximumDistance, double *t = nullptr)
+{
+ CubicSegment minimumDistanceSegment;
+ double actualMinimumDistance = maximumDistance;
+
+ foreach (const CubicSegment &cubicSegment, cubicSegments) {
+ double tSegment = 0.;
+ double cubicSegmentMinimumDistance = cubicSegment.minimumDistance(pickPoint, tSegment);
+ if (cubicSegmentMinimumDistance < actualMinimumDistance) {
+ minimumDistanceSegment = cubicSegment;
+ actualMinimumDistance = cubicSegmentMinimumDistance;
+ if (t)
+ *t = tSegment;
+ }
+ }
+
+ return minimumDistanceSegment;
+}
+
+void PathItem::splitCubicSegment(CubicSegment &cubicSegment, double t)
+{
+ QPair<CubicSegment, CubicSegment> newCubicSegmentPair = cubicSegment.split(t);
+ int indexOfOldCubicSegment = m_cubicSegments.indexOf(cubicSegment);
+
+ m_cubicSegments.removeAt(indexOfOldCubicSegment);
+ m_cubicSegments.insert(indexOfOldCubicSegment, newCubicSegmentPair.first);
+ m_cubicSegments.insert(indexOfOldCubicSegment + 1, newCubicSegmentPair.second);
+}
+
+void PathItem::closePath()
+{
+ if (!m_cubicSegments.isEmpty()) {
+ const CubicSegment &firstCubicSegment = m_cubicSegments.constFirst();
+ CubicSegment lastCubicSegment = m_cubicSegments.constLast();
+ lastCubicSegment.setFourthControlPoint(firstCubicSegment.firstControlPoint());
+ writePathAsCubicSegmentsOnly();
+ }
+}
+
+void PathItem::openPath()
+{
+ if (!m_cubicSegments.isEmpty()) {
+ const CubicSegment &firstCubicSegment = m_cubicSegments.constFirst();
+ CubicSegment lastCubicSegment = m_cubicSegments.constLast();
+ QPointF newEndPoint = firstCubicSegment.firstControlPoint().coordinate();
+ newEndPoint.setX(newEndPoint.x() + 10.);
+ lastCubicSegment.setFourthControlPoint(ControlPoint(newEndPoint));
+ writePathAsCubicSegmentsOnly();
+ }
+}
+
+QAction *PathItem::createClosedPathAction(QMenu *contextMenu) const
+{
+ auto closedPathAction = new QAction(contextMenu);
+ closedPathAction->setCheckable(true);
+ closedPathAction->setChecked(isClosedPath());
+ closedPathAction->setText(tr("Closed Path"));
+ contextMenu->addAction(closedPathAction);
+
+ if (m_cubicSegments.count() == 1)
+ closedPathAction->setDisabled(true);
+
+ return closedPathAction;
+}
+
+void PathItem::createGlobalContextMenu(const QPoint &menuPosition)
+{
+ QMenu contextMenu;
+
+ QAction *closedPathAction = createClosedPathAction(&contextMenu);
+
+ QAction *activatedAction = contextMenu.exec(menuPosition);
+
+ if (activatedAction == closedPathAction)
+ makePathClosed(closedPathAction->isChecked());
+}
+
+void PathItem::createCubicSegmentContextMenu(CubicSegment &cubicSegment, const QPoint &menuPosition, double t)
+{
+ QMenu contextMenu;
+
+ auto splitSegmentAction = new QAction(&contextMenu);
+ splitSegmentAction->setText(tr("Split Segment"));
+ contextMenu.addAction(splitSegmentAction);
+
+ auto straightLinePointAction = new QAction(&contextMenu);
+ straightLinePointAction->setText(tr("Make Curve Segment Straight"));
+ contextMenu.addAction(straightLinePointAction);
+
+ if (m_cubicSegments.count() == 1 && isClosedPath())
+ straightLinePointAction->setDisabled(true);
+
+ QAction *closedPathAction = createClosedPathAction(&contextMenu);
+
+ QAction *activatedAction = contextMenu.exec(menuPosition);
+
+ if (activatedAction == straightLinePointAction) {
+ cubicSegment.makeStraightLine();
+ PathUpdateDisabler pathItemDisabler(this, PathUpdateDisabler::DontUpdatePath);
+ RewriterTransaction rewriterTransaction =
+ cubicSegment.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("PathItem::createCubicSegmentContextMenu"));
+ cubicSegment.updateModelNode();
+ rewriterTransaction.commit();
+ } else if (activatedAction == splitSegmentAction) {
+ splitCubicSegment(cubicSegment, t);
+ writePathAsCubicSegmentsOnly();
+ } else if (activatedAction == closedPathAction) {
+ makePathClosed(closedPathAction->isChecked());
+ }
+}
+
+
+void PathItem::createEditPointContextMenu(const ControlPoint &controlPoint, const QPoint &menuPosition)
+{
+ QMenu contextMenu;
+ auto removeEditPointAction = new QAction(&contextMenu);
+ removeEditPointAction->setText(tr("Remove Edit Point"));
+ contextMenu.addAction(removeEditPointAction);
+
+ QAction *closedPathAction = createClosedPathAction(&contextMenu);
+
+ if (m_cubicSegments.count() <= 1 || (m_cubicSegments.count() == 2 && isClosedPath()))
+ removeEditPointAction->setDisabled(true);
+
+ QAction *activatedAction = contextMenu.exec(menuPosition);
+
+ if (activatedAction == removeEditPointAction)
+ removeEditPoint(controlPoint);
+ else if (activatedAction == closedPathAction)
+ makePathClosed(closedPathAction->isChecked());
+}
+
+const QList<ControlPoint> PathItem::controlPoints() const
+{
+ QList<ControlPoint> controlPointList;
+ controlPointList.reserve((m_cubicSegments.count() * 4));
+
+ if (!m_cubicSegments.isEmpty())
+ controlPointList.append(m_cubicSegments.constFirst().firstControlPoint());
+
+ foreach (const CubicSegment &cubicSegment, m_cubicSegments) {
+ controlPointList.append(cubicSegment.secondControlPoint());
+ controlPointList.append(cubicSegment.thirdControlPoint());
+ controlPointList.append(cubicSegment.fourthControlPoint());
+ }
+
+ if (isClosedPath())
+ controlPointList.pop_back();
+
+ return controlPointList;
+}
+
+bool hasLineOrQuadPathElements(const QList<ModelNode> &modelNodes)
+{
+ foreach (const ModelNode &modelNode, modelNodes) {
+ if (modelNode.type() == "QtQuick.PathLine"
+ || modelNode.type() == "QtQuick.PathQuad")
+ return true;
+ }
+
+ return false;
+}
+
+void PathItem::updatePath()
+{
+ if (m_dontUpdatePath)
+ return;
+
+ if (hasPath(formEditorItem())) {
+ readControlPoints();
+
+ ModelNode pathNode = pathModelNode(formEditorItem());
+
+ if (hasLineOrQuadPathElements(pathNode.nodeListProperty("pathElements").toModelNodeList()))
+ writePathAsCubicSegmentsOnly();
+ }
+
+ updateBoundingRect();
+ update();
+}
+
+QRectF PathItem::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void PathItem::setBoundingRect(const QRectF &boundingRect)
+{
+ m_boundingRect = boundingRect;
+}
+
+static bool controlPointIsNearMousePosition(const ControlPoint &controlPoint, const QPointF &mousePosition)
+{
+ QPointF distanceVector = controlPoint.coordinate() - mousePosition;
+
+ if (distanceVector.manhattanLength() < 10)
+ return true;
+
+ return false;
+}
+
+static bool controlPointsAreNearMousePosition(const QList<ControlPoint> &controlPoints, const QPointF &mousePosition)
+{
+ foreach (const ControlPoint &controlPoint, controlPoints) {
+ if (controlPointIsNearMousePosition(controlPoint, mousePosition))
+ return true;
+ }
+
+ return false;
+}
+
+static ControlPoint pickControlPoint(const QList<ControlPoint> &controlPoints, const QPointF &mousePosition)
+{
+ foreach (const ControlPoint &controlPoint, controlPoints) {
+ if (controlPointIsNearMousePosition(controlPoint, mousePosition))
+ return controlPoint;
+ }
+
+ return ControlPoint();
+}
+
+void PathItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ if (m_selectionManipulator.hasMultiSelection()) {
+ m_selectionManipulator.setStartPoint(event->pos());
+ } else {
+ ControlPoint pickedControlPoint = pickControlPoint(controlPoints(), event->pos());
+
+ if (pickedControlPoint.isValid()) {
+ m_selectionManipulator.addSingleControlPointSmartly(pickedControlPoint);
+ m_selectionManipulator.startMoving(event->pos());
+ } else {
+ m_selectionManipulator.startMultiSelection(event->pos());
+ }
+ }
+ }
+}
+
+bool hasMoveStartDistance(const QPointF &startPoint, const QPointF &updatePoint)
+{
+ return (startPoint - updatePoint).manhattanLength() > 10;
+}
+
+void PathItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (controlPointsAreNearMousePosition(controlPoints(), event->pos()))
+ setCursor(Qt::SizeAllCursor);
+ else
+ setCursor(Qt::ArrowCursor);
+
+ PathUpdateDisabler pathUpdateDisabler(this, PathUpdateDisabler::DontUpdatePath);
+ if (event->buttons().testFlag(Qt::LeftButton)) {
+ if (m_selectionManipulator.isMultiSelecting()) {
+ m_selectionManipulator.updateMultiSelection(event->pos());
+ update();
+ } else if (m_selectionManipulator.hasSingleSelection()) {
+ setCursor(Qt::SizeAllCursor);
+ m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
+ updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
+ updateBoundingRect();
+ update();
+ } else if (m_selectionManipulator.hasMultiSelection()) {
+ setCursor(Qt::SizeAllCursor);
+ if (m_selectionManipulator.isMoving()) {
+ m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
+ updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
+ updateBoundingRect();
+ update();
+ } else if (hasMoveStartDistance(m_selectionManipulator.startPoint(), event->pos())) {
+ m_selectionManipulator.startMoving(m_selectionManipulator.startPoint());
+ m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
+ updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
+ updateBoundingRect();
+ update();
+ }
+ }
+ }
+}
+
+void PathItem::updatePathModelNodes(const QList<SelectionPoint> &changedPoints)
+{
+ PathUpdateDisabler pathUpdateDisabler(this, PathUpdateDisabler::DontUpdatePath);
+
+ try {
+ RewriterTransaction rewriterTransaction =
+ formEditorItem()->qmlItemNode().view()->beginRewriterTransaction(QByteArrayLiteral("PathItem::createCubicSegmentContextMenu"));
+
+ foreach (SelectionPoint changedPoint, changedPoints)
+ changedPoint.controlPoint.updateModelNode();
+
+ rewriterTransaction.commit();
+ } catch (const Exception &e) {
+ e.showException();
+ }
+}
+
+void PathItem::disablePathUpdates()
+{
+ m_dontUpdatePath = true;
+}
+
+void PathItem::enablePathUpdates()
+{
+ m_dontUpdatePath = false;
+}
+
+bool PathItem::pathUpdatesDisabled() const
+{
+ return m_dontUpdatePath;
+}
+
+void PathItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ if (m_selectionManipulator.isMultiSelecting()) {
+ m_selectionManipulator.updateMultiSelection(event->pos());
+ m_selectionManipulator.endMultiSelection();
+ } else if (m_selectionManipulator.hasSingleSelection()) {
+ m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
+ updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
+ updateBoundingRect();
+ m_selectionManipulator.clearSingleSelection();
+ } else if (m_selectionManipulator.hasMultiSelection()) {
+ if (m_selectionManipulator.isMoving()) {
+ m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
+ m_selectionManipulator.endMoving();
+ updatePathModelNodes(m_selectionManipulator.multiSelectedPoints());
+ updateBoundingRect();
+ } else {
+ m_selectionManipulator.clearMultiSelection();
+ }
+ }
+ } else if (event->button() == Qt::RightButton) {
+ ControlPoint pickedControlPoint = pickControlPoint(controlPoints(), event->pos());
+ if (pickedControlPoint.isEditPoint()) {
+ createEditPointContextMenu(pickedControlPoint, event->screenPos());
+ } else {
+ double t = 0.0;
+ CubicSegment minimumDistanceSegment = getMinimumDistanceSegment(event->pos(), m_cubicSegments, 20., &t);
+ if (minimumDistanceSegment.isValid())
+ createCubicSegmentContextMenu(minimumDistanceSegment, event->screenPos(), t);
+ else
+ createGlobalContextMenu(event->screenPos());
+ }
+ }
+
+ update();
+
+}
+
+bool PathItem::isClosedPath() const
+{
+ if (m_cubicSegments.isEmpty())
+ return false;
+
+ ControlPoint firstControlPoint = m_cubicSegments.constFirst().firstControlPoint();
+ ControlPoint lastControlPoint = m_cubicSegments.constLast().fourthControlPoint();
+
+ return firstControlPoint == lastControlPoint;
+}
+
+void PathItem::makePathClosed(bool pathShoudlBeClosed)
+{
+ if (pathShoudlBeClosed && !isClosedPath())
+ closePath();
+ else if (!pathShoudlBeClosed && isClosedPath())
+ openPath();
+}
+
+QList<CubicSegment> cubicSegmentsContainingControlPoint(const ControlPoint &controlPoint, const QList<CubicSegment> &allCubicSegments)
+{
+ QList<CubicSegment> cubicSegmentsHasControlPoint;
+
+ foreach (const CubicSegment &cubicSegment, allCubicSegments) {
+ if (cubicSegment.controlPoints().contains(controlPoint))
+ cubicSegmentsHasControlPoint.append(cubicSegment);
+ }
+
+ return cubicSegmentsHasControlPoint;
+}
+
+void PathItem::removeEditPoint(const ControlPoint &controlPoint)
+{
+ QList<CubicSegment> cubicSegments = cubicSegmentsContainingControlPoint(controlPoint, m_cubicSegments);
+
+ if (cubicSegments.count() == 1) {
+ m_cubicSegments.removeOne(cubicSegments.constFirst());
+ } else if (cubicSegments.count() == 2){
+ CubicSegment mergedCubicSegment = CubicSegment::create();
+ const CubicSegment &firstCubicSegment = cubicSegments.at(0);
+ const CubicSegment &secondCubicSegment = cubicSegments.at(1);
+ mergedCubicSegment.setFirstControlPoint(firstCubicSegment.firstControlPoint());
+ mergedCubicSegment.setSecondControlPoint(firstCubicSegment.secondControlPoint());
+ mergedCubicSegment.setThirdControlPoint(secondCubicSegment.thirdControlPoint());
+ mergedCubicSegment.setFourthControlPoint(secondCubicSegment.fourthControlPoint());
+
+ int indexOfFirstCubicSegment = m_cubicSegments.indexOf(firstCubicSegment);
+ m_cubicSegments.removeAt(indexOfFirstCubicSegment);
+ m_cubicSegments.removeAt(indexOfFirstCubicSegment);
+ m_cubicSegments.insert(indexOfFirstCubicSegment, mergedCubicSegment);
+ }
+
+ writePathAsCubicSegmentsOnly();
+}
+
+PathUpdateDisabler::PathUpdateDisabler(PathItem *pathItem, PathUpdate updatePath)
+ : m_pathItem(pathItem),
+ m_updatePath(updatePath)
+{
+ pathItem->disablePathUpdates();
+}
+
+PathUpdateDisabler::~PathUpdateDisabler()
+{
+ m_pathItem->enablePathUpdates();
+ if (m_updatePath == UpdatePath)
+ m_pathItem->updatePath();
+}
+
+}
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.h b/src/plugins/qmldesigner/components/pathtool/pathitem.h
index 17981283a6..17981283a6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.h
+++ b/src/plugins/qmldesigner/components/pathtool/pathitem.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathselectionmanipulator.cpp b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
index 6df6976233..6df6976233 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathselectionmanipulator.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathselectionmanipulator.h b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.h
index def0148367..def0148367 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathselectionmanipulator.h
+++ b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.cpp b/src/plugins/qmldesigner/components/pathtool/pathtool.cpp
index a01ae050ac..a01ae050ac 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathtool.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.h b/src/plugins/qmldesigner/components/pathtool/pathtool.h
index a2a65db27d..a2a65db27d 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.h
+++ b/src/plugins/qmldesigner/components/pathtool/pathtool.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.pri b/src/plugins/qmldesigner/components/pathtool/pathtool.pri
index eba35315fe..eba35315fe 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtool.pri
+++ b/src/plugins/qmldesigner/components/pathtool/pathtool.pri
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtoolview.cpp b/src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp
index ea1e28832a..ea1e28832a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtoolview.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathtoolview.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtoolview.h b/src/plugins/qmldesigner/components/pathtool/pathtoolview.h
index 46b688923e..46b688923e 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathtoolview.h
+++ b/src/plugins/qmldesigner/components/pathtool/pathtoolview.h
diff --git a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
index 5d7b1aeaaf..245d604707 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
@@ -85,6 +85,11 @@ QUrl FileResourcesModel::path() const
return m_path;
}
+QUrl FileResourcesModel::dirPath() const
+{
+ return QUrl::fromLocalFile(m_dirPath.path());
+}
+
void FileResourcesModel::setFilter(const QString &filter)
{
if (m_filter != filter) {
@@ -162,16 +167,14 @@ void FileResourcesModel::setupModel()
m_lock = true;
m_model.clear();
- QDir dir;
-
- dir = QFileInfo(m_path.toLocalFile()).dir();
+ m_dirPath = QFileInfo(m_path.toLocalFile()).dir();
QStringList filterList = m_filter.split(QLatin1Char(' '));
- QDirIterator it(dir.absolutePath(), filterList, QDir::Files, QDirIterator::Subdirectories);
+ QDirIterator it(m_dirPath.absolutePath(), filterList, QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) {
QString absolutePath = it.next();
- m_model.append(dir.relativeFilePath(absolutePath));
+ m_model.append(m_dirPath.relativeFilePath(absolutePath));
}
m_lock = false;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.h b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.h
index e0d6fc9725..f686631079 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.h
@@ -27,6 +27,7 @@
#include <qmlitemnode.h>
+#include <QDir>
#include <QObject>
#include <QStringList>
#include <QUrl>
@@ -40,6 +41,7 @@ class FileResourcesModel : public QObject
Q_PROPERTY(QString filter READ filter WRITE setFilter)
Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
Q_PROPERTY(QUrl path READ path WRITE setPath)
+ Q_PROPERTY(QUrl dirPath READ dirPath)
Q_PROPERTY(QStringList fileModel READ fileModel NOTIFY fileModelChanged)
public:
@@ -51,6 +53,7 @@ public:
void setFileNameStr(const QString &fileName);
void setPath(const QUrl &url);
QUrl path() const;
+ QUrl dirPath() const;
void setFilter(const QString &filter);
QString filter() const;
QStringList fileModel() const;
@@ -71,6 +74,7 @@ private:
private:
QUrl m_fileName;
QUrl m_path;
+ QDir m_dirPath;
QString m_filter;
bool m_lock;
QString m_currentPath;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
index 6bb3153bea..d4b1f47184 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
@@ -27,6 +27,8 @@
#include "qmlanchorbindingproxy.h"
#include "propertyeditorview.h"
+#include "gradientpresetitem.h"
+#include "gradientpresetcustomlistmodel.h"
#include <exception.h>
#include <nodeproperty.h>
@@ -34,14 +36,14 @@
#include <variantproperty.h>
#include <abstractview.h>
#include <nodemetainfo.h>
-#include <rewritertransaction.h>
+#include <exception.h>
#include <utils/qtcassert.h>
#include <QTimer>
GradientModel::GradientModel(QObject *parent) :
- QAbstractListModel(parent), m_gradientTypeName("Gradient"), m_locked(false)
+ QAbstractListModel(parent)
{
}
@@ -145,18 +147,16 @@ void GradientModel::addGradient()
return;
if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) {
- try {
+ if (m_gradientTypeName != "Gradient")
+ ensureShapesImport();
+
+ view()->executeInTransaction("GradientModel::addGradient", [this](){
QColor color = m_itemNode.instanceValue("color").value<QColor>();
if (!color.isValid())
color = QColor(Qt::white);
- if (m_gradientTypeName != "Gradient")
- ensureShapesImport();
-
- QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::addGradient"));
-
QmlDesigner::ModelNode gradientNode = createGradientNode();
m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).reparentHere(gradientNode);
@@ -170,16 +170,12 @@ void GradientModel::addGradient()
gradientStopNode.variantProperty("position").setValue(1.0);
gradientStopNode.variantProperty("color").setValue(QColor(Qt::black));
gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
-
- } catch (const QmlDesigner::Exception &e) {
- e.showException();
- }
-
+ });
}
setupModel();
if (m_gradientTypeName != "Gradient")
- QTimer::singleShot(100, [this](){ view()->resetPuppet(); }); /*Unfortunately required */
+ resetPuppet(); /*Unfortunately required */
emit hasGradientChanged();
emit gradientTypeChanged();
}
@@ -242,18 +238,18 @@ qreal GradientModel::getPosition(int index) const
void GradientModel::removeStop(int index)
{
if (index < rowCount() - 1 && index != 0) {
- QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::removeStop"));
- QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode();
- QmlDesigner::QmlObjectNode stop = gradientNode.nodeListProperty("stops").at(index);
- if (stop.isValid()) {
- stop.destroy();
- setupModel();
- }
+ view()->executeInTransaction("GradientModel::removeStop", [this, index](){
+ QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode();
+ QmlDesigner::QmlObjectNode stop = gradientNode.nodeListProperty("stops").at(index);
+ if (stop.isValid()) {
+ stop.destroy();
+ setupModel();
+ }
+ });
}
qWarning() << Q_FUNC_INFO << "invalid index";
}
-
void GradientModel::deleteGradient()
{
if (!m_itemNode.isValid())
@@ -262,16 +258,7 @@ void GradientModel::deleteGradient()
if (!m_itemNode.modelNode().metaInfo().hasProperty(gradientPropertyName().toUtf8()))
return;
- QmlDesigner::ModelNode modelNode = m_itemNode.modelNode();
-
- if (m_itemNode.isInBaseState()) {
- if (modelNode.hasProperty(gradientPropertyName().toUtf8())) {
- QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::deleteGradient"));
- QmlDesigner::ModelNode gradientNode = modelNode.nodeProperty(gradientPropertyName().toUtf8()).modelNode();
- if (QmlDesigner::QmlObjectNode(gradientNode).isValid())
- QmlDesigner::QmlObjectNode(gradientNode).destroy();
- }
- }
+ deleteGradientNode(true);
emit hasGradientChanged();
emit gradientTypeChanged();
@@ -392,7 +379,11 @@ void GradientModel::ensureShapesImport()
{
if (!hasShapesImport()) {
QmlDesigner::Import timelineImport = QmlDesigner::Import::createLibraryImport("QtQuick.Shapes", "1.0");
- model()->changeImports({timelineImport}, {});
+ try {
+ model()->changeImports({timelineImport}, {});
+ } catch (const QmlDesigner::Exception &) {
+ QTC_ASSERT(false, return);
+ }
}
}
@@ -444,6 +435,11 @@ QmlDesigner::AbstractView *GradientModel::view() const
return m_itemNode.view();
}
+void GradientModel::resetPuppet()
+{
+ QTimer::singleShot(1000, [this]() { view()->resetPuppet(); });
+}
+
QmlDesigner::ModelNode GradientModel::createGradientNode()
{
QByteArray fullTypeName = m_gradientTypeName.toUtf8();
@@ -477,6 +473,23 @@ QmlDesigner::ModelNode GradientModel::createGradientStopNode()
return view()->createModelNode(fullTypeName, majorVersion, minorVersion);
}
+void GradientModel::deleteGradientNode(bool saveTransaction)
+{
+ QmlDesigner::ModelNode modelNode = m_itemNode.modelNode();
+
+ if (m_itemNode.isInBaseState()) {
+ if (modelNode.hasProperty(gradientPropertyName().toUtf8())) {
+ if (saveTransaction)
+ QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(
+ QByteArrayLiteral("GradientModel::deleteGradient"));
+ QmlDesigner::ModelNode gradientNode
+ = modelNode.nodeProperty(gradientPropertyName().toUtf8()).modelNode();
+ if (QmlDesigner::QmlObjectNode(gradientNode).isValid())
+ QmlDesigner::QmlObjectNode(gradientNode).destroy();
+ }
+ }
+}
+
void GradientModel::setGradientProperty(const QString &propertyName, qreal value)
{
QTC_ASSERT(m_itemNode.isValid(), return);
@@ -494,3 +507,102 @@ void GradientModel::setGradientProperty(const QString &propertyName, qreal value
e.showException();
}
}
+
+void GradientModel::setPresetByID(int presetID)
+{
+ const QGradient gradient(GradientPresetItem::createGradientFromPreset(
+ static_cast<GradientPresetItem::Preset>(presetID)));
+ const QList<QGradientStop> gradientStops = gradient.stops().toList();
+
+ QList<qreal> stopsPositions;
+ QList<QString> stopsColors;
+ for (const QGradientStop &stop : gradientStops) {
+ stopsPositions.append(stop.first);
+ stopsColors.append(stop.second.name());
+ }
+
+ setPresetByStops(stopsPositions, stopsColors, gradientStops.size());
+}
+
+void GradientModel::setPresetByStops(const QList<qreal> &stopsPositions,
+ const QList<QString> &stopsColors,
+ int stopsCount)
+{
+ if (m_locked)
+ return;
+
+ if (!m_itemNode.isValid() || gradientPropertyName().isEmpty())
+ return;
+
+ QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(
+ QByteArrayLiteral("GradientModel::setCustomPreset"));
+
+ deleteGradientNode(false);
+
+ if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) {
+ try {
+
+ if (m_gradientTypeName != "Gradient")
+ ensureShapesImport();
+
+ QmlDesigner::ModelNode gradientNode = createGradientNode();
+
+ m_itemNode.modelNode()
+ .nodeProperty(gradientPropertyName().toUtf8())
+ .reparentHere(gradientNode);
+
+ for (int i = 0; i < stopsCount; i++) {
+ QmlDesigner::ModelNode gradientStopNode = createGradientStopNode();
+ gradientStopNode.variantProperty("position").setValue(stopsPositions.at(i));
+ gradientStopNode.variantProperty("color").setValue(stopsColors.at(i));
+ gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
+ }
+
+ } catch (const QmlDesigner::Exception &e) {
+ e.showException();
+ }
+ }
+ setupModel();
+
+ if (m_gradientTypeName != "Gradient")
+ resetPuppet(); /*Unfortunately required */
+
+ emit hasGradientChanged();
+ emit gradientTypeChanged();
+}
+
+void GradientModel::savePreset()
+{
+ //preparing qgradient:
+ QGradient currentGradient;
+ QGradientStops currentStops;
+ QGradientStop stop; //double, color
+
+ for (int i = 0; i < rowCount(); i++) {
+ stop.first = getPosition(i);
+ stop.second = getColor(i);
+ currentStops.append(stop);
+ }
+ currentGradient.setStops(currentStops);
+ const GradientPresetItem item(currentGradient, "Custom Gradient");
+
+ //reading the custom gradient file
+ //filling the file with old data + new data
+ const QString filename(GradientPresetCustomListModel::getFilename());
+ QList<GradientPresetItem> items = GradientPresetCustomListModel::storedPresets(filename);
+ items.append(item);
+ GradientPresetCustomListModel::storePresets(filename, items);
+}
+
+void GradientModel::updateGradient()
+{
+ QList<qreal> stops;
+ QList<QString> colors;
+ int stopsCount = rowCount();
+ for (int i = 0; i < stopsCount; i++) {
+ stops.append(getPosition(i));
+ colors.append(getColor(i).name(QColor::HexArgb));
+ }
+
+ setPresetByStops(stops, colors, stopsCount);
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h
index 48514ae688..c54526838e 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h
@@ -70,6 +70,15 @@ public:
Q_INVOKABLE void setGradientProperty(const QString &propertyName, qreal value);
+ Q_INVOKABLE void setPresetByID(int presetID);
+ Q_INVOKABLE void setPresetByStops(const QList<qreal> &stopsPositions,
+ const QList<QString> &stopsColors,
+ int stopsCount);
+
+ Q_INVOKABLE void savePreset();
+
+ Q_INVOKABLE void updateGradient();
+
signals:
void anchorBackendChanged();
void hasGradientChanged();
@@ -87,17 +96,19 @@ private:
bool locked() const;
QmlDesigner::ModelNode createGradientNode();
QmlDesigner::ModelNode createGradientStopNode();
+ void deleteGradientNode(bool saveTransaction);
private:
QmlDesigner::QmlItemNode m_itemNode;
QString m_gradientPropertyName;
- QString m_gradientTypeName;
- bool m_locked;
+ QString m_gradientTypeName = {"Gradient"};
+ bool m_locked = false;
bool hasShapesImport() const;
void ensureShapesImport();
void setupGradientProperties(const QmlDesigner::ModelNode &gradient);
QmlDesigner::Model *model() const;
QmlDesigner::AbstractView *view() const;
+ void resetPuppet();
};
QML_DECLARE_TYPE(GradientModel)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.cpp
new file mode 100644
index 0000000000..a1599a7099
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gradientpresetcustomlistmodel.h"
+#include "gradientpresetitem.h"
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+#include <utils/algorithm.h>
+
+#include <QHash>
+#include <QByteArray>
+#include <QDebug>
+#include <QSettings>
+#include <QFile>
+
+namespace Internal {
+
+static const char settingsKey[] = "GradientPresetCustomList";
+static const char settingsFileName[] = "/GradientPresets.ini";
+
+QString settingsFullFilePath(const QSettings::Scope &scope)
+{
+ if (scope == QSettings::SystemScope)
+ return Core::ICore::installerResourcePath() + settingsFileName;
+
+ return Core::ICore::userResourcePath() + settingsFileName;
+}
+
+} // namespace Internal
+
+GradientPresetCustomListModel::GradientPresetCustomListModel(QObject *parent)
+ : GradientPresetListModel(parent)
+ , m_filename(getFilename())
+{
+ qRegisterMetaTypeStreamOperators<GradientPresetItem>("GradientPresetItem");
+ readPresets();
+}
+
+GradientPresetCustomListModel::~GradientPresetCustomListModel() {}
+
+void GradientPresetCustomListModel::registerDeclarativeType()
+{
+ qmlRegisterType<GradientPresetCustomListModel>("HelperWidgets",
+ 2,
+ 0,
+ "GradientPresetCustomListModel");
+}
+
+QString GradientPresetCustomListModel::getFilename()
+{
+ return Internal::settingsFullFilePath(QSettings::UserScope);
+}
+
+void GradientPresetCustomListModel::storePresets(const QString &filename,
+ const QList<GradientPresetItem> &items)
+{
+ const QList<QVariant> presets
+ = Utils::transform<QList<QVariant>>(items, [](const GradientPresetItem &item) {
+ return QVariant::fromValue(item);
+ });
+
+ QSettings settings(filename, QSettings::IniFormat);
+ settings.clear();
+ settings.setValue(Internal::settingsKey, QVariant::fromValue(presets));
+}
+
+QList<GradientPresetItem> GradientPresetCustomListModel::storedPresets(const QString &filename)
+{
+ const QSettings settings(filename, QSettings::IniFormat);
+ const QVariant presetSettings = settings.value(Internal::settingsKey);
+
+ if (!presetSettings.isValid())
+ return {};
+
+ const QList<QVariant> presets = presetSettings.toList();
+
+ QList<GradientPresetItem> out;
+ for (const QVariant &preset : presets) {
+ if (preset.isValid()) {
+ out.append(preset.value<GradientPresetItem>());
+ }
+ }
+
+ return out;
+}
+
+void GradientPresetCustomListModel::addGradient(const QList<qreal> &stopsPositions,
+ const QList<QString> &stopsColors,
+ int stopsCount)
+{
+ QGradient tempGradient;
+ QGradientStops gradientStops;
+ QGradientStop gradientStop;
+ for (int i = 0; i < stopsCount; i++) {
+ gradientStop.first = stopsPositions.at(i);
+ gradientStop.second = stopsColors.at(i);
+ gradientStops.push_back(gradientStop);
+ }
+
+ tempGradient.setStops(gradientStops);
+
+ addItem(GradientPresetItem(tempGradient));
+}
+
+void GradientPresetCustomListModel::changePresetName(int id, const QString &newName)
+{
+ QTC_ASSERT(id >= 0, return);
+ QTC_ASSERT(id < m_items.size(), return);
+ m_items[id].setPresetName(newName);
+ writePresets();
+}
+
+void GradientPresetCustomListModel::deletePreset(int id)
+{
+ QTC_ASSERT(id >= 0, return);
+ QTC_ASSERT(id < m_items.size(), return);
+ beginResetModel();
+ m_items.removeAt(id);
+ writePresets();
+ endResetModel();
+}
+
+void GradientPresetCustomListModel::writePresets()
+{
+ storePresets(m_filename, m_items);
+}
+
+void GradientPresetCustomListModel::readPresets()
+{
+ const QList<GradientPresetItem> presets = storedPresets(m_filename);
+ beginResetModel();
+ m_items.clear();
+
+ for (const GradientPresetItem &preset : presets) {
+ addItem(preset);
+ }
+ endResetModel();
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.h
new file mode 100644
index 0000000000..382b651e3b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetcustomlistmodel.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "gradientpresetlistmodel.h"
+
+#include <QObject>
+#include <QAbstractListModel>
+#include <QtQml/qqml.h>
+
+class GradientPresetCustomListModel : public GradientPresetListModel
+{
+ Q_OBJECT
+
+public:
+ explicit GradientPresetCustomListModel(QObject *parent = nullptr);
+ ~GradientPresetCustomListModel() override;
+
+ static void registerDeclarativeType();
+
+ static QString getFilename();
+ static void storePresets(const QString &filename, const QList<GradientPresetItem> &items);
+ static QList<GradientPresetItem> storedPresets(const QString &filename);
+
+ Q_INVOKABLE void addGradient(const QList<qreal> &stopsPositions,
+ const QList<QString> &stopsColors,
+ int stopsCount);
+
+ Q_INVOKABLE void changePresetName(int id, const QString &newName);
+ Q_INVOKABLE void deletePreset(int id);
+
+ Q_INVOKABLE void writePresets();
+ Q_INVOKABLE void readPresets();
+
+private:
+ QString m_filename;
+};
+
+QML_DECLARE_TYPE(GradientPresetCustomListModel)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.cpp
new file mode 100644
index 0000000000..8237390de9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gradientpresetdefaultlistmodel.h"
+#include "gradientpresetitem.h"
+
+#include <QHash>
+#include <QByteArray>
+#include <QDebug>
+#include <QFile>
+
+GradientPresetDefaultListModel::GradientPresetDefaultListModel(QObject *parent)
+ : GradientPresetListModel(parent)
+{
+ addAllPresets();
+}
+
+GradientPresetDefaultListModel::~GradientPresetDefaultListModel() {}
+
+void GradientPresetDefaultListModel::registerDeclarativeType()
+{
+ qmlRegisterType<GradientPresetDefaultListModel>("HelperWidgets",
+ 2,
+ 0,
+ "GradientPresetDefaultListModel");
+}
+
+void GradientPresetDefaultListModel::addAllPresets()
+{
+ const QMetaObject &metaObj = QGradient::staticMetaObject;
+ const QMetaEnum metaEnum = metaObj.enumerator(metaObj.indexOfEnumerator("Preset"));
+
+ if (!metaEnum.isValid())
+ return;
+
+ for (int i = 0; i < metaEnum.keyCount(); i++) {
+ addItem(GradientPresetItem(GradientPresetItem::Preset(metaEnum.value(i))));
+ }
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.h
new file mode 100644
index 0000000000..831135e052
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetdefaultlistmodel.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "gradientpresetlistmodel.h"
+
+#include <QObject>
+#include <QAbstractListModel>
+#include <QtQml/qqml.h>
+
+class GradientPresetDefaultListModel : public GradientPresetListModel
+{
+ Q_OBJECT
+
+public:
+ explicit GradientPresetDefaultListModel(QObject *parent = nullptr);
+ ~GradientPresetDefaultListModel() override;
+
+ static void registerDeclarativeType();
+
+private:
+ void addAllPresets();
+};
+
+QML_DECLARE_TYPE(GradientPresetDefaultListModel)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.cpp
new file mode 100644
index 0000000000..9d2454c4e9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gradientpresetitem.h"
+
+#include <utils/qtcassert.h>
+#include <utils/algorithm.h>
+
+#include <QVariant>
+#include <QMetaObject>
+#include <QMetaEnum>
+#include <algorithm>
+#include <QDebug>
+
+
+GradientPresetItem::GradientPresetItem()
+ : m_gradientVal(QGradient())
+ , m_gradientID(Preset(0))
+ , m_presetName(QString())
+{}
+
+GradientPresetItem::GradientPresetItem(const QGradient &value, const QString &name)
+ : m_gradientVal(value)
+ , m_gradientID(Preset(0))
+ , m_presetName(name)
+{}
+
+GradientPresetItem::GradientPresetItem(const Preset value)
+ : m_gradientVal(createGradientFromPreset(value))
+ , m_gradientID(value)
+ , m_presetName(getNameByPreset(value))
+{}
+
+GradientPresetItem::~GradientPresetItem() = default;
+
+QVariant GradientPresetItem::getProperty(GradientPresetItem::Property id) const
+{
+ QVariant out;
+
+ switch (id) {
+ case objectNameRole:
+ out.setValue(QString());
+ break;
+ case stopsPosListRole:
+ out.setValue(stopsPosList());
+ break;
+ case stopsColorListRole:
+ out.setValue(stopsColorList());
+ break;
+ case stopListSizeRole:
+ out.setValue(stopListSize());
+ break;
+ case presetNameRole:
+ out.setValue(presetName());
+ break;
+ case presetIDRole:
+ out.setValue(presetID());
+ break;
+ default:
+ qWarning() << "GradientPresetItem Property switch default case";
+ break; //replace with assert before switch?
+ }
+
+ return out;
+}
+
+QGradient GradientPresetItem::gradientVal() const
+{
+ return m_gradientVal;
+}
+
+void GradientPresetItem::setGradient(const QGradient &value)
+{
+ m_gradientVal = value;
+ m_gradientID = Preset(0);
+ m_presetName = QString();
+}
+
+void GradientPresetItem::setGradient(const Preset value)
+{
+ m_gradientID = value;
+ m_gradientVal = createGradientFromPreset(value);
+ m_presetName = getNameByPreset(value);
+}
+
+QList<qreal> GradientPresetItem::stopsPosList() const
+{
+ const QList<QPair<qreal, QColor>> subres = m_gradientVal.stops().toList();
+ const QList<qreal> result = Utils::transform<QList<qreal>>(subres,
+ [](const QPair<qreal, QColor> &item) {
+ return item.first;
+ });
+ return result;
+}
+
+QList<QString> GradientPresetItem::stopsColorList() const
+{
+ const QList<QPair<qreal, QColor>> subres = m_gradientVal.stops().toList();
+ const QList<QString> result
+ = Utils::transform<QList<QString>>(subres, [](const QPair<qreal, QColor> &item) {
+ return item.second.name();
+ });
+ return result;
+}
+
+int GradientPresetItem::stopListSize() const
+{
+ return m_gradientVal.stops().size();
+}
+
+void GradientPresetItem::setPresetName(const QString &value)
+{
+ m_presetName = value;
+}
+
+QString GradientPresetItem::presetName() const
+{
+ return m_presetName;
+}
+
+int GradientPresetItem::presetID() const
+{
+ return static_cast<int>(m_gradientID);
+}
+
+QString GradientPresetItem::getNameByPreset(Preset value)
+{
+ const QMetaObject &metaObj = QGradient::staticMetaObject;
+ const QMetaEnum metaEnum = metaObj.enumerator(metaObj.indexOfEnumerator("Preset"));
+
+ if (!metaEnum.isValid())
+ return QString("Custom");
+
+ QString enumName = QString::fromUtf8(metaEnum.valueToKey(static_cast<int>(value)));
+
+ const QStringList sl = enumName.split(QRegExp("(?=[A-Z])"), QString::SkipEmptyParts);
+
+ enumName.clear();
+ std::for_each(sl.begin(), sl.end(), [&enumName](const QString &s) { enumName += (s + " "); });
+ enumName.chop(1); //let's remove the last empty space
+
+ return (enumName.isEmpty() ? QString("Custom") : enumName);
+}
+
+QGradient GradientPresetItem::createGradientFromPreset(Preset value)
+{
+#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
+ return QGradient(value);
+#else
+ Q_UNUSED(value);
+ return {};
+#endif
+}
+
+QDebug &operator<<(QDebug &stream, const GradientPresetItem &gradient)
+{
+ stream << "\"stops:" << gradient.m_gradientVal.stops() << "\"";
+ stream << "\"preset:" << gradient.m_gradientID << "\"";
+ stream << "\"name:" << gradient.m_presetName << "\"";
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const GradientPresetItem &gradient)
+{
+ stream << gradient.m_gradientVal.stops();
+
+ stream << static_cast<int>(gradient.m_gradientID);
+ stream << gradient.m_presetName;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, GradientPresetItem &gradient)
+{
+ QGradientStops stops;
+ stream >> stops;
+ gradient.m_gradientVal.setStops(stops);
+
+ int gradientID;
+ stream >> gradientID;
+ gradient.m_gradientID = static_cast<GradientPresetItem::Preset>(gradientID);
+
+ stream >> gradient.m_presetName;
+ return stream;
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.h b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.h
new file mode 100644
index 0000000000..cd0f0017e0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetitem.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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 <QGradient>
+
+class GradientPresetItem
+{
+ Q_GADGET
+
+ Q_PROPERTY(QList<qreal> stopsPosList READ stopsPosList FINAL)
+ Q_PROPERTY(QList<QString> stopsColorList READ stopsColorList FINAL)
+ Q_PROPERTY(int stopListSize READ stopListSize FINAL)
+ Q_PROPERTY(QString presetName READ presetName FINAL)
+ Q_PROPERTY(int presetID READ presetID FINAL)
+
+public:
+#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
+ using Preset = QGradient::Preset;
+#else
+ enum Preset {};
+#endif
+
+ explicit GradientPresetItem();
+ explicit GradientPresetItem(const QGradient &value, const QString &name = QString());
+ explicit GradientPresetItem(const Preset number);
+ ~GradientPresetItem();
+
+ enum Property {
+ objectNameRole = 0,
+ stopsPosListRole = 1,
+ stopsColorListRole = 2,
+ stopListSizeRole = 3,
+ presetNameRole = 4,
+ presetIDRole = 5
+ };
+
+ QVariant getProperty(Property id) const;
+
+ QGradient gradientVal() const;
+
+ void setGradient(const QGradient &value);
+ void setGradient(const Preset value);
+
+ QList<qreal> stopsPosList() const;
+ QList<QString> stopsColorList() const;
+ int stopListSize() const;
+
+ void setPresetName(const QString &value);
+ QString presetName() const;
+ int presetID() const;
+
+ static QString getNameByPreset(Preset value);
+
+ friend QDebug &operator<<(QDebug &stream, const GradientPresetItem &gradient);
+
+ friend QDataStream &operator<<(QDataStream &stream, const GradientPresetItem &gradient);
+ friend QDataStream &operator>>(QDataStream &stream, GradientPresetItem &gradient);
+
+ static QGradient createGradientFromPreset(Preset value);
+
+private:
+ QGradient m_gradientVal;
+ Preset m_gradientID;
+ QString m_presetName;
+};
+
+Q_DECLARE_METATYPE(GradientPresetItem)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp
new file mode 100644
index 0000000000..1ed95f8719
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "gradientpresetlistmodel.h"
+#include "gradientpresetitem.h"
+
+#include <QHash>
+#include <QByteArray>
+#include <QDebug>
+#include <QSettings>
+
+GradientPresetListModel::GradientPresetListModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+ m_roleNames
+ = {{static_cast<int>(GradientPresetItem::Property::objectNameRole), "objectName"},
+ {static_cast<int>(GradientPresetItem::Property::stopsPosListRole), "stopsPosList"},
+ {static_cast<int>(GradientPresetItem::Property::stopsColorListRole), "stopsColorList"},
+ {static_cast<int>(GradientPresetItem::Property::stopListSizeRole), "stopListSize"},
+ {static_cast<int>(GradientPresetItem::Property::presetNameRole), "presetName"},
+ {static_cast<int>(GradientPresetItem::Property::presetIDRole), "presetID"}};
+}
+
+GradientPresetListModel::~GradientPresetListModel()
+{
+ clearItems();
+}
+
+int GradientPresetListModel::rowCount(const QModelIndex & /*parent*/) const
+{
+ return m_items.count();
+}
+
+QVariant GradientPresetListModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && (index.row() >= 0) && (index.row() < m_items.count())) {
+ if (m_roleNames.contains(role)) {
+ QVariant value = m_items.at(index.row())
+ .getProperty(static_cast<GradientPresetItem::Property>(role));
+
+ if (auto model = qobject_cast<GradientPresetListModel *>(value.value<QObject *>()))
+ return QVariant::fromValue(model);
+
+ return value;
+ }
+
+ qWarning() << Q_FUNC_INFO << "invalid role requested";
+ return QVariant();
+ }
+
+ qWarning() << Q_FUNC_INFO << "invalid index requested";
+ return QVariant();
+}
+
+QHash<int, QByteArray> GradientPresetListModel::roleNames() const
+{
+ return m_roleNames;
+}
+
+void GradientPresetListModel::clearItems()
+{
+ beginResetModel();
+ m_items.clear();
+ endResetModel();
+}
+
+void GradientPresetListModel::addItem(const GradientPresetItem &element)
+{
+ beginResetModel();
+ m_items.append(element);
+ endResetModel();
+}
+
+const QList<GradientPresetItem> &GradientPresetListModel::items() const
+{
+ return m_items;
+}
+
+void GradientPresetListModel::sortItems()
+{
+ auto itemSort = [](const GradientPresetItem &first, const GradientPresetItem &second) {
+ return (static_cast<int>(first.presetID()) < static_cast<int>(second.presetID()));
+ };
+
+ std::sort(m_items.begin(), m_items.end(), itemSort);
+}
+
+void GradientPresetListModel::registerDeclarativeType()
+{
+ qmlRegisterType<GradientPresetListModel>("HelperWidgets", 2, 0, "GradientPresetListModel");
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.h
new file mode 100644
index 0000000000..7fce2243dd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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 <QAbstractListModel>
+#include <QtQml/qqml.h>
+
+class GradientPresetItem;
+
+class GradientPresetListModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit GradientPresetListModel(QObject *parent = nullptr);
+ ~GradientPresetListModel() override;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ void clearItems();
+ void addItem(const GradientPresetItem &element);
+
+ const QList<GradientPresetItem> &items() const;
+
+ void sortItems();
+
+ static void registerDeclarativeType();
+
+protected:
+ QList<GradientPresetItem> m_items;
+ QHash<int, QByteArray> m_roleNames;
+};
+
+//QML_DECLARE_TYPE(GradientPresetListModel)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
index d822fbb70d..b32a744016 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
@@ -11,7 +11,14 @@ SOURCES += propertyeditorview.cpp \
propertyeditorwidget.cpp \
fileresourcesmodel.cpp \
gradientmodel.cpp \
- qmlmodelnodeproxy.cpp
+ qmlmodelnodeproxy.cpp \
+ gradientpresetitem.cpp \
+ gradientpresetlistmodel.cpp \
+ gradientpresetdefaultlistmodel.cpp \
+ gradientpresetcustomlistmodel.cpp \
+ simplecolorpalette.cpp \
+ simplecolorpalettemodel.cpp \
+ simplecolorpalettesingleton.cpp
HEADERS += propertyeditorview.h \
qmlanchorbindingproxy.h \
@@ -24,6 +31,13 @@ HEADERS += propertyeditorview.h \
propertyeditorwidget.h \
fileresourcesmodel.h \
gradientmodel.h \
- qmlmodelnodeproxy.h
+ qmlmodelnodeproxy.h \
+ gradientpresetitem.h \
+ gradientpresetlistmodel.h \
+ gradientpresetdefaultlistmodel.h \
+ gradientpresetcustomlistmodel.h \
+ simplecolorpalette.h \
+ simplecolorpalettemodel.h \
+ simplecolorpalettesingleton.h
QT += qml quick
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
index dc8243e1c8..8fdab5a821 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
@@ -152,22 +152,14 @@ void PropertyEditorContextObject::toogleExportAlias()
PropertyName modelNodeId = selectedNode.id().toUtf8();
ModelNode rootModelNode = rewriterView->rootModelNode();
- try {
- RewriterTransaction transaction =
- rewriterView->beginRewriterTransaction(QByteArrayLiteral("PropertyEditorContextObject:toogleExportAlias"));
-
+ rewriterView->executeInTransaction("PropertyEditorContextObject:toogleExportAlias", [&objectNode, &rootModelNode, modelNodeId](){
if (!objectNode.isAliasExported())
objectNode.ensureAliasExport();
else
if (rootModelNode.hasProperty(modelNodeId))
rootModelNode.removeProperty(modelNodeId);
-
- transaction.commit();
- } catch (RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
- }
+ });
}
-
}
void PropertyEditorContextObject::changeTypeName(const QString &typeName)
@@ -181,11 +173,8 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
- ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
-
- try {
- RewriterTransaction transaction =
- rewriterView->beginRewriterTransaction(QByteArrayLiteral("PropertyEditorContextObject:changeTypeName"));
+ rewriterView->executeInTransaction("PropertyEditorContextObject:changeTypeName", [this, rewriterView, typeName](){
+ ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
NodeMetaInfo metaInfo = m_model->metaInfo(typeName.toLatin1());
if (!metaInfo.isValid()) {
@@ -193,16 +182,10 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
return;
}
if (selectedNode.isRootNode())
- rewriterView->changeRootNodeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
+ rewriterView->changeRootNodeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
else
selectedNode.changeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
-
- transaction.commit();
- } catch (RewritingException &exception) { //better safe than sorry! There always might be cases where we fail
- exception.showException();
- }
-
-
+ });
}
void PropertyEditorContextObject::insertKeyframe(const QString &propertyName)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index 284b6948ee..12f12ed2bc 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -40,6 +40,7 @@
#include <coreplugin/icore.h>
#include <qmljs/qmljssimplereader.h>
+#include <utils/qtcassert.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
@@ -281,13 +282,17 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
setupLayoutAttachedProperties(qmlObjectNode, propertyEditor);
+ // model node
+ m_backendModelNode.setup(qmlObjectNode.modelNode());
+ context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode);
+
// className
auto valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("className"))));
if (!valueObject)
valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
valueObject->setName("className");
valueObject->setModelNode(qmlObjectNode.modelNode());
- valueObject->setValue(qmlObjectNode.modelNode().simplifiedTypeName());
+ valueObject->setValue(m_backendModelNode.simplifiedTypeName());
QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged);
m_backendValuesPropertyMap.insert(QLatin1String("className"), QVariant::fromValue(valueObject));
@@ -296,7 +301,7 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
if (!valueObject)
valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
valueObject->setName("id");
- valueObject->setValue(qmlObjectNode.id());
+ valueObject->setValue(m_backendModelNode.nodeId());
QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged);
m_backendValuesPropertyMap.insert(QLatin1String("id"), QVariant::fromValue(valueObject));
@@ -310,10 +315,6 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed();
- // model node
- m_backendModelNode.setup(qmlObjectNode.modelNode());
- context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode);
-
qCInfo(propertyEditorBenchmark) << "context:" << time.elapsed();
contextObject()->setSpecificsUrl(qmlSpecificsFile);
@@ -402,23 +403,49 @@ QString PropertyEditorQmlBackend::propertyEditorResourcesPath() {
QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
const NodeMetaInfo &superType,
- const QmlObjectNode &objectNode)
+ const QmlObjectNode &node)
{
if (!templateConfiguration() || !templateConfiguration()->isValid())
return QString();
+ const auto nodes = templateConfiguration()->children();
+
+ QStringList sectorTypes;
+
+ for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) {
+ if (node->propertyNames().contains("separateSection"))
+ sectorTypes.append(variantToStringList(node->property("typeNames")));
+ }
+
QStringList imports = variantToStringList(templateConfiguration()->property(QStringLiteral("imports")));
QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n');
- qmlTemplate += QStringLiteral("Section {\n");
- qmlTemplate += QStringLiteral("caption: \"%1\"\n").arg(objectNode.modelNode().simplifiedTypeName());
- qmlTemplate += QStringLiteral("SectionLayout {\n");
+
+ qmlTemplate += "Column {\n";
+ qmlTemplate += "anchors.left: parent.left\n";
+ qmlTemplate += "anchors.right: parent.right\n";
QList<PropertyName> orderedList = type.propertyNames();
- Utils::sort(orderedList);
+ Utils::sort(orderedList, [type, &sectorTypes](const PropertyName &left, const PropertyName &right){
+ const QString typeNameLeft = QString::fromLatin1(type.propertyTypeName(left));
+ const QString typeNameRight = QString::fromLatin1(type.propertyTypeName(right));
+ if (typeNameLeft == typeNameRight)
+ return left > right;
+
+ if (sectorTypes.contains(typeNameLeft)) {
+ if (sectorTypes.contains(typeNameRight))
+ return left > right;
+ return true;
+ } else if (sectorTypes.contains(typeNameRight)) {
+ return false;
+ }
+ return left > right;
+ });
bool emptyTemplate = true;
+ bool sectionStarted = false;
+
foreach (const PropertyName &name, orderedList) {
if (name.startsWith("__"))
@@ -429,18 +456,38 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
TypeName typeName = type.propertyTypeName(name);
//alias resolution only possible with instance
- if (typeName == "alias" && objectNode.isValid())
- typeName = objectNode.instanceType(name);
+ if (typeName == "alias" && node.isValid())
+ typeName = node.instanceType(name);
+
+ auto nodes = templateConfiguration()->children();
if (!superType.hasProperty(name) && type.propertyIsWritable(name) && !name.contains(".")) {
- foreach (const QmlJS::SimpleReaderNode::Ptr &node, templateConfiguration()->children())
+
+ foreach (const QmlJS::SimpleReaderNode::Ptr &node, nodes)
if (variantToStringList(node->property(QStringLiteral("typeNames"))).contains(QString::fromLatin1(typeName))) {
const QString fileName = propertyTemplatesPath() + node->property(QStringLiteral("sourceFile")).toString();
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QString source = QString::fromUtf8(file.readAll());
file.close();
+ const bool section = node->propertyNames().contains("separateSection");
+ if (section) {
+ qmlTemplate += "Section {\n";
+ qmlTemplate += "anchors.left: parent.left\n";
+ qmlTemplate += "anchors.right: parent.right\n";
+ qmlTemplate += QString("caption: \"%1\"\n").arg(QString::fromUtf8(properName));
+ } else if (!sectionStarted) {
+ qmlTemplate += QStringLiteral("Section {\n");
+ qmlTemplate += QStringLiteral("caption: \"%1\"\n").arg(QString::fromUtf8(type.simplifiedTypeName()));
+ qmlTemplate += "anchors.left: parent.left\n";
+ qmlTemplate += "anchors.right: parent.right\n";
+ qmlTemplate += QStringLiteral("SectionLayout {\n");
+ sectionStarted = true;
+ }
+
qmlTemplate += source.arg(QString::fromUtf8(name)).arg(QString::fromUtf8(properName));
+ if (section)
+ qmlTemplate += "}\n";
emptyTemplate = false;
} else {
qWarning().nospace() << "template definition source file not found:" << fileName;
@@ -448,8 +495,12 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
}
}
}
- qmlTemplate += QStringLiteral("}\n"); //Section
- qmlTemplate += QStringLiteral("}\n"); //SectionLayout
+ if (sectionStarted) {
+ qmlTemplate += QStringLiteral("}\n"); //Section
+ qmlTemplate += QStringLiteral("}\n"); //SectionLayout
+ }
+
+ qmlTemplate += "}\n";
if (emptyTemplate)
return QString();
@@ -469,6 +520,36 @@ TypeName PropertyEditorQmlBackend::fixTypeNameForPanes(const TypeName &typeName)
return fixedTypeName;
}
+static NodeMetaInfo findCommonSuperClass(const NodeMetaInfo &first, const NodeMetaInfo &second)
+{
+ for (const NodeMetaInfo &info : first.superClasses()) {
+ if (second.isSubclassOf(info.typeName()))
+ return info;
+ }
+ return first;
+}
+
+NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node)
+{
+ if (!node.isValid())
+ return {};
+
+ QTC_ASSERT(node.metaInfo().isValid(), return {});
+
+ AbstractView *view = node.view();
+
+ if (view->selectedModelNodes().count() > 1) {
+ NodeMetaInfo commonClass = node.metaInfo();
+ for (const ModelNode &currentNode : view->selectedModelNodes()) {
+ if (currentNode.metaInfo().isValid() && !currentNode.isSubclassOf(commonClass.typeName(), -1, -1))
+ commonClass = findCommonSuperClass(currentNode.metaInfo(), commonClass);
+ }
+ return commonClass;
+ }
+
+ return node.metaInfo();
+}
+
TypeName PropertyEditorQmlBackend::qmlFileName(const NodeMetaInfo &nodeInfo)
{
const TypeName fixedTypeName = fixTypeNameForPanes(nodeInfo.typeName());
@@ -526,10 +607,10 @@ void PropertyEditorQmlBackend::setValueforLayoutAttachedProperties(const QmlObje
setValue(qmlObjectNode, name, properDefaultLayoutAttachedProperties(qmlObjectNode, propertyName));
}
-QUrl PropertyEditorQmlBackend::getQmlUrlForModelNode(const ModelNode &modelNode, TypeName &className)
+QUrl PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo, TypeName &className)
{
- if (modelNode.isValid()) {
- foreach (const NodeMetaInfo &info, modelNode.metaInfo().classHierarchy()) {
+ if (metaInfo.isValid()) {
+ foreach (const NodeMetaInfo &info, metaInfo.classHierarchy()) {
QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info))));
if (fileUrl.isValid()) {
className = info.typeName();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h
index a0012a1cc1..51279a1fc6 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h
@@ -68,11 +68,10 @@ public:
PropertyEditorValue *propertyValueForName(const QString &propertyName);
static QString propertyEditorResourcesPath();
- static QString templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType,
- const QmlObjectNode &objectNode);
+ static QString templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, const QmlObjectNode &node);
static QUrl getQmlFileUrl(const TypeName &relativeTypeName, const NodeMetaInfo &info = NodeMetaInfo());
- static QUrl getQmlUrlForModelNode(const ModelNode &modelNode, TypeName &className);
+ static QUrl getQmlUrlForMetaInfo(const NodeMetaInfo &modelNode, TypeName &className);
static bool checkIfUrlExists(const QUrl &url);
@@ -83,6 +82,8 @@ public:
void setupLayoutAttachedProperties(const QmlObjectNode &qmlObjectNode, PropertyEditorView *propertyEditor);
+ static NodeMetaInfo findCommonAncestor(const ModelNode &node);
+
private:
void createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
const PropertyName &name, const QVariant &value,
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
index 0467355bf4..9dd0a2da24 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
@@ -213,20 +213,13 @@ void PropertyEditorView::changeValue(const QString &name)
castedValue = QVariant(newColor);
}
- try {
- if (!value->value().isValid()) { //reset
- qmlObjectNode.removeProperty(propertyName);
- } else {
- if (castedValue.isValid() && !castedValue.isNull()) {
- m_locked = true;
- qmlObjectNode.setVariantProperty(propertyName, castedValue);
- m_locked = false;
- }
+ if (!value->value().isValid()) { //reset
+ removePropertyFromModel(propertyName);
+ } else {
+ if (castedValue.isValid() && !castedValue.isNull()) {
+ commitVariantValueToModel(propertyName, castedValue);
}
}
- catch (const RewritingException &e) {
- e.showException();
- }
}
void PropertyEditorView::changeExpression(const QString &propertyName)
@@ -242,9 +235,7 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
if (!m_selectedNode.isValid())
return;
- RewriterTransaction transaction = beginRewriterTransaction(QByteArrayLiteral("PropertyEditorView::changeExpression"));
-
- try {
+ executeInTransaction("PropertyEditorView::changeExpression", [this, name](){
PropertyName underscoreName(name);
underscoreName.replace('.', '_');
@@ -260,7 +251,6 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
if (qmlObjectNode.modelNode().metaInfo().propertyTypeName(name) == "QColor") {
if (QColor(value->expression().remove('"')).isValid()) {
qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"')));
- transaction.commit(); //committing in the try block
return;
}
} else if (qmlObjectNode.modelNode().metaInfo().propertyTypeName(name) == "bool") {
@@ -270,7 +260,6 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
qmlObjectNode.setVariantProperty(name, true);
else
qmlObjectNode.setVariantProperty(name, false);
- transaction.commit(); //committing in the try block
return;
}
} else if (qmlObjectNode.modelNode().metaInfo().propertyTypeName(name) == "int") {
@@ -278,7 +267,6 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
int intValue = value->expression().toInt(&ok);
if (ok) {
qmlObjectNode.setVariantProperty(name, intValue);
- transaction.commit(); //committing in the try block
return;
}
} else if (qmlObjectNode.modelNode().metaInfo().propertyTypeName(name) == "qreal") {
@@ -286,7 +274,6 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
qreal realValue = value->expression().toDouble(&ok);
if (ok) {
qmlObjectNode.setVariantProperty(name, realValue);
- transaction.commit(); //committing in the try block
return;
}
}
@@ -298,12 +285,7 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
if (qmlObjectNode.expression(name) != value->expression() || !qmlObjectNode.propertyAffectedByCurrentState(name))
qmlObjectNode.setBindingProperty(name, value->expression());
- transaction.commit(); //committing in the try block
- }
-
- catch (const RewritingException &e) {
- e.showException();
- }
+ }); /* end of transaction */
}
void PropertyEditorView::exportPopertyAsAlias(const QString &name)
@@ -317,9 +299,7 @@ void PropertyEditorView::exportPopertyAsAlias(const QString &name)
if (!m_selectedNode.isValid())
return;
- RewriterTransaction transaction = beginRewriterTransaction(QByteArrayLiteral("PropertyEditorView::exportPopertyAsAlias"));
-
- try {
+ executeInTransaction("PropertyEditorView::exportPopertyAsAlias", [this, name](){
const QString id = m_selectedNode.validId();
QString upperCasePropertyName = name;
upperCasePropertyName.replace(0, 1, upperCasePropertyName.at(0).toUpper());
@@ -333,11 +313,7 @@ void PropertyEditorView::exportPopertyAsAlias(const QString &name)
return;
}
rootModelNode().bindingProperty(propertyName).setDynamicTypeNameAndExpression("alias", id + "." + name);
-
- transaction.commit(); //committing in the try block
- } catch (const RewritingException &e) {
- e.showException();
- }
+ });
}
void PropertyEditorView::removeAliasExport(const QString &name)
@@ -351,9 +327,7 @@ void PropertyEditorView::removeAliasExport(const QString &name)
if (!m_selectedNode.isValid())
return;
- RewriterTransaction transaction = beginRewriterTransaction(QByteArrayLiteral("PropertyEditorView::exportPopertyAsAlias"));
-
- try {
+ executeInTransaction("PropertyEditorView::exportPopertyAsAlias", [this, name](){
const QString id = m_selectedNode.validId();
for (const BindingProperty &property : rootModelNode().bindingProperties())
@@ -361,10 +335,7 @@ void PropertyEditorView::removeAliasExport(const QString &name)
rootModelNode().removeProperty(property.name());
break;
}
- transaction.commit(); //committing in the try block
- } catch (const RewritingException &e) {
- e.showException();
- }
+ });
}
bool PropertyEditorView::locked() const
@@ -446,13 +417,16 @@ void PropertyEditorView::resetView()
void PropertyEditorView::setupQmlBackend()
{
TypeName specificsClassName;
- QUrl qmlFile(PropertyEditorQmlBackend::getQmlUrlForModelNode(m_selectedNode, specificsClassName));
+
+ const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode);
+
+ const QUrl qmlFile(PropertyEditorQmlBackend::getQmlUrlForMetaInfo(commonAncestor, specificsClassName));
QUrl qmlSpecificsFile;
TypeName diffClassName;
- if (m_selectedNode.isValid()) {
- diffClassName = m_selectedNode.metaInfo().typeName();
- foreach (const NodeMetaInfo &metaInfo, m_selectedNode.metaInfo().classHierarchy()) {
+ if (commonAncestor.isValid()) {
+ diffClassName = commonAncestor.typeName();
+ foreach (const NodeMetaInfo &metaInfo, commonAncestor.classHierarchy()) {
if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsFile))
break;
qmlSpecificsFile = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName() + "Specifics", metaInfo);
@@ -465,8 +439,8 @@ void PropertyEditorView::setupQmlBackend()
QString specificQmlData;
- if (m_selectedNode.isValid() && m_selectedNode.metaInfo().isValid() && diffClassName != m_selectedNode.type())
- specificQmlData = PropertyEditorQmlBackend::templateGeneration(m_selectedNode.metaInfo(), model()->metaInfo(diffClassName), m_selectedNode);
+ if (commonAncestor.isValid() && m_selectedNode.metaInfo().isValid() && diffClassName != m_selectedNode.type())
+ specificQmlData = PropertyEditorQmlBackend::templateGeneration(commonAncestor, model()->metaInfo(diffClassName), m_selectedNode);
PropertyEditorQmlBackend *currentQmlBackend = m_qmlBackendHash.value(qmlFile.toString());
@@ -515,14 +489,51 @@ void PropertyEditorView::setupQmlBackend()
}
+void PropertyEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value)
+{
+ m_locked = true;
+ try {
+ RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::commitVariantValueToMode");
+
+ for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) {
+ if (QmlObjectNode::isValidQmlObjectNode(node))
+ QmlObjectNode(node).setVariantProperty(propertyName, value);
+ }
+ transaction.commit();
+ }
+ catch (const RewritingException &e) {
+ e.showException();
+ }
+ m_locked = false;
+}
+
+void PropertyEditorView::removePropertyFromModel(const PropertyName &propertyName)
+{
+ m_locked = true;
+ try {
+ RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::removePropertyFromModel");
+
+ for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) {
+ if (QmlObjectNode::isValidQmlObjectNode(node))
+ QmlObjectNode(node).removeProperty(propertyName);
+ }
+
+ transaction.commit();
+ }
+ catch (const RewritingException &e) {
+ e.showException();
+ }
+ m_locked = false;
+}
+
void PropertyEditorView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList)
{
Q_UNUSED(lastSelectedNodeList);
- if (selectedNodeList.isEmpty() || selectedNodeList.count() > 1)
+ if (selectedNodeList.isEmpty())
select(ModelNode());
- else if (m_selectedNode != selectedNodeList.constFirst())
+ else
select(selectedNodeList.constFirst());
}
@@ -542,10 +553,11 @@ void PropertyEditorView::modelAttached(Model *model)
m_locked = true;
if (!m_setupCompleted) {
- m_singleShotTimer->setSingleShot(true);
- m_singleShotTimer->setInterval(100);
- connect(m_singleShotTimer, &QTimer::timeout, this, &PropertyEditorView::setupPanes);
- m_singleShotTimer->start();
+ QTimer::singleShot(50, this, [this]{
+ PropertyEditorView::setupPanes();
+ /* workaround for QTBUG-75847 */
+ reloadQml();
+ });
}
m_locked = false;
@@ -648,6 +660,9 @@ void PropertyEditorView::instanceInformationsChanged(const QMultiHash<ModelNode,
if (!m_selectedNode.isValid())
return;
+ if (!m_qmlBackEndForCurrentType)
+ return;
+
m_locked = true;
QList<InformationName> informationNameList = informationChangedHash.values(m_selectedNode);
if (informationNameList.contains(Anchor)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h
index 85bd8286f5..e7f57cf186 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h
@@ -110,6 +110,9 @@ private: //functions
void delayedResetView();
void setupQmlBackend();
+ void commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value);
+ void removePropertyFromModel(const PropertyName &propertyName);
+
private: //variables
ModelNode m_selectedNode;
QWidget *m_parent;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
index bc6b4376b6..7a38f74f34 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp
@@ -292,9 +292,9 @@ void QmlAnchorBindingProxy::setDefaultRelativeRightTarget()
}
}
-RewriterTransaction QmlAnchorBindingProxy::beginRewriterTransaction(const QByteArray &identifier)
+bool QmlAnchorBindingProxy::executeInTransaction(const QByteArray &identifier, const AbstractView::OperationBlock &lambda)
{
- return m_qmlItemNode.modelNode().view()->beginRewriterTransaction(identifier);
+ return m_qmlItemNode.modelNode().view()->executeInTransaction(identifier, lambda);
}
bool QmlAnchorBindingProxy::hasParent() const
@@ -361,20 +361,11 @@ void QmlAnchorBindingProxy::setTopTarget(const QString &target)
if (!newTarget.isValid())
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setTopTarget"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setTopTarget", [this, newTarget](){
m_topTarget = newTarget;
-
setDefaultRelativeTopTarget();
-
anchorTop();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit topTargetChanged();
}
@@ -393,18 +384,12 @@ void QmlAnchorBindingProxy::setBottomTarget(const QString &target)
if (!newTarget.isValid())
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setBottomTarget"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setBottomTarget", [this, newTarget](){
m_bottomTarget = newTarget;
setDefaultRelativeBottomTarget();
anchorBottom();
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit bottomTargetChanged();
}
@@ -422,18 +407,11 @@ void QmlAnchorBindingProxy::setLeftTarget(const QString &target)
if (!newTarget.isValid())
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setLeftTarget"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setLeftTarget", [this, newTarget](){
m_leftTarget = newTarget;
setDefaultRelativeLeftTarget();
anchorLeft();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit leftTargetChanged();
}
@@ -451,18 +429,11 @@ void QmlAnchorBindingProxy::setRightTarget(const QString &target)
if (!newTarget.isValid())
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRightTarget"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setRightTarget", [this, newTarget](){
m_rightTarget = newTarget;
setDefaultRelativeRightTarget();
anchorRight();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit rightTargetChanged();
}
@@ -480,17 +451,10 @@ void QmlAnchorBindingProxy::setVerticalTarget(const QString &target)
if (!newTarget.isValid())
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setVerticalTarget"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setVerticalTarget", [this, newTarget](){
m_verticalTarget = newTarget;
anchorVertical();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit verticalTargetChanged();
}
@@ -508,17 +472,10 @@ void QmlAnchorBindingProxy::setHorizontalTarget(const QString &target)
if (!newTarget.isValid())
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setHorizontalTarget"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setHorizontalTarget", [this, newTarget](){
m_horizontalTarget = newTarget;
- anchorHorizontal();\
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ anchorHorizontal();
+ });
emit horizontalTargetChanged();
}
@@ -531,18 +488,10 @@ void QmlAnchorBindingProxy::setRelativeAnchorTargetTop(QmlAnchorBindingProxy::Re
if (target == m_relativeTopTarget)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRelativeAnchorTargetTop"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setRelativeAnchorTargetTop", [this, target](){
m_relativeTopTarget = target;
-
anchorTop();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetTopChanged();
}
@@ -555,19 +504,10 @@ void QmlAnchorBindingProxy::setRelativeAnchorTargetBottom(QmlAnchorBindingProxy:
if (target == m_relativeBottomTarget)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRelativeAnchorTargetBottom"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setRelativeAnchorTargetBottom", [this, target](){
m_relativeBottomTarget = target;
-
-
anchorBottom();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetBottomChanged();
}
@@ -580,18 +520,11 @@ void QmlAnchorBindingProxy::setRelativeAnchorTargetLeft(QmlAnchorBindingProxy::R
if (target == m_relativeLeftTarget)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRelativeAnchorTargetLeft"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setRelativeAnchorTargetLeft", [this, target](){
m_relativeLeftTarget = target;
-
anchorLeft();
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetLeftChanged();
}
@@ -604,18 +537,10 @@ void QmlAnchorBindingProxy::setRelativeAnchorTargetRight(QmlAnchorBindingProxy::
if (target == m_relativeRightTarget)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRelativeAnchorTargetRight"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setRelativeAnchorTargetRight", [this, target](){
m_relativeRightTarget = target;
-
anchorRight();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetRightChanged();
@@ -629,18 +554,11 @@ void QmlAnchorBindingProxy::setRelativeAnchorTargetVertical(QmlAnchorBindingProx
if (target == m_relativeVerticalTarget)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRelativeAnchorTargetVertical"));
+ executeInTransaction("QmlAnchorBindingProxy::setRelativeAnchorTargetVertical", [this, target](){
m_relativeVerticalTarget = target;
-
anchorVertical();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetVerticalChanged();
}
@@ -653,18 +571,10 @@ void QmlAnchorBindingProxy::setRelativeAnchorTargetHorizontal(QmlAnchorBindingPr
if (target == m_relativeHorizontalTarget)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRelativeAnchorTargetHorizontal"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setRelativeAnchorTargetHorizontal", [this, target](){
m_relativeHorizontalTarget = target;
-
anchorHorizontal();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetHorizontalChanged();
}
@@ -709,12 +619,10 @@ int QmlAnchorBindingProxy::indexOfPossibleTargetItem(const QString &targetName)
return possibleTargetItems().indexOf(targetName);
}
-void QmlAnchorBindingProxy::resetLayout() {
-
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::resetLayout"));
+void QmlAnchorBindingProxy::resetLayout()
+{
+ executeInTransaction("QmlAnchorBindingProxy::resetLayout", [this](){
m_qmlItemNode.anchors().removeAnchors();
m_qmlItemNode.anchors().removeMargins();
@@ -722,11 +630,7 @@ void QmlAnchorBindingProxy::resetLayout() {
restoreProperty(modelNode(), "y");
restoreProperty(modelNode(), "width");
restoreProperty(modelNode(), "height");
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit topAnchorChanged();
emit bottomAnchorChanged();
@@ -743,10 +647,7 @@ void QmlAnchorBindingProxy::setBottomAnchor(bool anchor)
if (bottomAnchored() == anchor)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setBottomAnchor"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setBottomAnchor", [this, anchor](){
if (!anchor) {
removeBottomAnchor();
} else {
@@ -756,10 +657,7 @@ void QmlAnchorBindingProxy::setBottomAnchor(bool anchor)
backupPropertyAndRemove(modelNode(), "height");
}
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetBottomChanged();
emit bottomAnchorChanged();
@@ -776,10 +674,8 @@ void QmlAnchorBindingProxy::setLeftAnchor(bool anchor)
if (leftAnchored() == anchor)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setLeftAnchor"));
+ executeInTransaction("QmlAnchorBindingProxy::setLeftAnchor", [this, anchor](){
if (!anchor) {
removeLeftAnchor();
} else {
@@ -791,10 +687,7 @@ void QmlAnchorBindingProxy::setLeftAnchor(bool anchor)
backupPropertyAndRemove(modelNode(), "width");
}
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetLeftChanged();
emit leftAnchorChanged();
@@ -810,10 +703,7 @@ void QmlAnchorBindingProxy::setRightAnchor(bool anchor)
if (rightAnchored() == anchor)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setRightAnchor"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setRightAnchor", [this, anchor](){
if (!anchor) {
removeRightAnchor();
} else {
@@ -824,10 +714,7 @@ void QmlAnchorBindingProxy::setRightAnchor(bool anchor)
backupPropertyAndRemove(modelNode(), "width");
}
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetRightChanged();
emit rightAnchorChanged();
@@ -1026,10 +913,7 @@ void QmlAnchorBindingProxy::setTopAnchor(bool anchor)
if (topAnchored() == anchor)
return;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setTopAnchor"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setTopAnchor", [this, anchor](){
if (!anchor) {
removeTopAnchor();
} else {
@@ -1040,10 +924,7 @@ void QmlAnchorBindingProxy::setTopAnchor(bool anchor)
if (bottomAnchored())
backupPropertyAndRemove(modelNode(), "height");
}
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit relativeAnchorTargetTopChanged();
emit topAnchorChanged();
@@ -1052,70 +933,44 @@ void QmlAnchorBindingProxy::setTopAnchor(bool anchor)
}
void QmlAnchorBindingProxy::removeTopAnchor() {
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::removeTopAnchor"));
-
+ executeInTransaction("QmlAnchorBindingProxy::removeTopAnchor", [this](){
m_qmlItemNode.anchors().removeAnchor(AnchorLineTop);
m_qmlItemNode.anchors().removeMargin(AnchorLineTop);
restoreProperty(modelNode(), "y");
restoreProperty(modelNode(), "height");
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
}
-void QmlAnchorBindingProxy::removeBottomAnchor() {
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::removeBottomAnchor"));
-
+void QmlAnchorBindingProxy::removeBottomAnchor()
+{
+ executeInTransaction("QmlAnchorBindingProxy::removeBottomAnchor", [this](){
m_qmlItemNode.anchors().removeAnchor(AnchorLineBottom);
m_qmlItemNode.anchors().removeMargin(AnchorLineBottom);
-
restoreProperty(modelNode(), "height");
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
}
-void QmlAnchorBindingProxy::removeLeftAnchor() {
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::removeLeftAnchor"));
-
+void QmlAnchorBindingProxy::removeLeftAnchor()
+{
+ executeInTransaction("QmlAnchorBindingProxy::removeLeftAnchor", [this](){
m_qmlItemNode.anchors().removeAnchor(AnchorLineLeft);
m_qmlItemNode.anchors().removeMargin(AnchorLineLeft);
restoreProperty(modelNode(), "x");
restoreProperty(modelNode(), "width");
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
}
-void QmlAnchorBindingProxy::removeRightAnchor() {
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::removeRightAnchor"));
-
+void QmlAnchorBindingProxy::removeRightAnchor()
+{
+ executeInTransaction("QmlAnchorBindingProxy::removeRightAnchor", [this](){
m_qmlItemNode.anchors().removeAnchor(AnchorLineRight);
m_qmlItemNode.anchors().removeMargin(AnchorLineRight);
restoreProperty(modelNode(), "width");
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
}
void QmlAnchorBindingProxy::setVerticalCentered(bool centered)
@@ -1128,10 +983,7 @@ void QmlAnchorBindingProxy::setVerticalCentered(bool centered)
m_locked = true;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setVerticalCentered"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setVerticalCentered", [this, centered](){
if (!centered) {
m_qmlItemNode.anchors().removeAnchor(AnchorLineVerticalCenter);
m_qmlItemNode.anchors().removeMargin(AnchorLineVerticalCenter);
@@ -1141,10 +993,7 @@ void QmlAnchorBindingProxy::setVerticalCentered(bool centered)
anchorVertical();
}
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
m_locked = false;
emit relativeAnchorTargetVerticalChanged();
@@ -1161,10 +1010,7 @@ void QmlAnchorBindingProxy::setHorizontalCentered(bool centered)
m_locked = true;
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::setHorizontalCentered"));
-
+ executeInTransaction("QmlAnchorBindingProxy::setHorizontalCentered", [this, centered](){
if (!centered) {
m_qmlItemNode.anchors().removeAnchor(AnchorLineHorizontalCenter);
m_qmlItemNode.anchors().removeMargin(AnchorLineHorizontalCenter);
@@ -1173,11 +1019,7 @@ void QmlAnchorBindingProxy::setHorizontalCentered(bool centered)
anchorHorizontal();
}
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
m_locked = false;
emit relativeAnchorTargetHorizontalChanged();
@@ -1256,12 +1098,7 @@ bool QmlAnchorBindingProxy::horizontalCentered()
void QmlAnchorBindingProxy::fill()
{
-
- try {
- RewriterTransaction transaction = beginRewriterTransaction(
- QByteArrayLiteral("QmlAnchorBindingProxy::fill"));
-
-
+ executeInTransaction("QmlAnchorBindingProxy::fill", [this](){
backupPropertyAndRemove(modelNode(), "x");
backupPropertyAndRemove(modelNode(), "y");
backupPropertyAndRemove(modelNode(), "width");
@@ -1277,10 +1114,7 @@ void QmlAnchorBindingProxy::fill()
m_qmlItemNode.anchors().removeMargin(AnchorLineTop);
m_qmlItemNode.anchors().removeMargin(AnchorLineBottom);
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
+ });
emit topAnchorChanged();
emit bottomAnchorChanged();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
index cf42ea055a..0bd562add2 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h
@@ -210,7 +210,7 @@ private:
void setDefaultRelativeLeftTarget();
void setDefaultRelativeRightTarget();
- RewriterTransaction beginRewriterTransaction(const QByteArray &identifier);
+ bool executeInTransaction(const QByteArray &identifier, const AbstractView::OperationBlock &lambda);
QmlItemNode targetIdToNode(const QString &id) const;
QString idForNode(const QmlItemNode &qmlItemNode) const;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
index 6f56b055c8..934c284691 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
@@ -23,6 +23,7 @@
**
****************************************************************************/
+#include "abstractview.h"
#include "qmlmodelnodeproxy.h"
#include <QtQml>
@@ -66,4 +67,34 @@ ModelNode QmlModelNodeProxy::modelNode() const
return m_qmlItemNode.modelNode();
}
+bool QmlModelNodeProxy::multiSelection() const
+{
+ if (!m_qmlItemNode.isValid())
+ return false;
+
+ return m_qmlItemNode.view()->selectedModelNodes().count() > 1;
+}
+
+QString QmlModelNodeProxy::nodeId() const
+{
+ if (!m_qmlItemNode.isValid())
+ return {};
+
+ if (multiSelection())
+ return tr("multiselection");
+
+ return m_qmlItemNode.id();
+}
+
+QString QmlModelNodeProxy::simplifiedTypeName() const
+{
+ if (!m_qmlItemNode.isValid())
+ return {};
+
+ if (multiSelection())
+ return tr("multiselection");
+
+ return m_qmlItemNode.simplifiedTypeName();
+}
+
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h
index 0a73583355..6037f32752 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h
@@ -35,7 +35,8 @@ class QmlModelNodeProxy : public QObject
{
Q_OBJECT
- Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode NOTIFY modelNodeChanged)
+ Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode NOTIFY modelNodeChanged)
+ Q_PROPERTY(bool multiSelection READ multiSelection NOTIFY modelNodeChanged)
public:
explicit QmlModelNodeProxy(QObject *parent = nullptr);
@@ -51,6 +52,12 @@ public:
ModelNode modelNode() const;
+ bool multiSelection() const;
+
+ QString nodeId() const;
+
+ QString simplifiedTypeName() const;
+
signals:
void modelNodeChanged();
void selectionToBeChanged();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp
index 4e58374759..862d16ba22 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp
@@ -28,6 +28,9 @@
#include "propertyeditorvalue.h"
#include "fileresourcesmodel.h"
#include "gradientmodel.h"
+#include "gradientpresetdefaultlistmodel.h"
+#include "gradientpresetcustomlistmodel.h"
+#include "simplecolorpalettemodel.h"
#include "qmlanchorbindingproxy.h"
#include "theme.h"
@@ -48,6 +51,9 @@ void Quick2PropertyEditorView::registerQmlTypes()
PropertyEditorValue::registerDeclarativeTypes();
FileResourcesModel::registerDeclarativeType();
GradientModel::registerDeclarativeType();
+ GradientPresetDefaultListModel::registerDeclarativeType();
+ GradientPresetCustomListModel::registerDeclarativeType();
+ SimpleColorPaletteModel::registerDeclarativeType();
Internal::QmlAnchorBindingProxy::registerDeclarativeType();
}
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp
new file mode 100644
index 0000000000..c88d83aa0a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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 "simplecolorpalette.h"
+
+#include "designersettings.h"
+
+#include <QDebug>
+
+namespace QmlDesigner {
+
+PaletteColor::PaletteColor()
+ : m_color(QColor())
+ , m_colorCode(QColor().name())
+ , m_isFavorite(false)
+{}
+
+PaletteColor::PaletteColor(const QString &colorCode)
+ : m_color(colorCode)
+ , m_colorCode(colorCode)
+ , m_isFavorite(false)
+{}
+
+PaletteColor::PaletteColor(const QColor &color)
+ : m_color(color)
+ , m_colorCode(color.name(QColor::HexArgb))
+ , m_isFavorite(false)
+{}
+
+QVariant PaletteColor::getProperty(Property id) const
+{
+ QVariant out;
+
+ switch (id) {
+ case objectNameRole:
+ out.setValue(QString());
+ break;
+ case colorRole:
+ out.setValue(color());
+ break;
+ case colorCodeRole:
+ out.setValue(colorCode());
+ break;
+ case isFavoriteRole:
+ out.setValue(isFavorite());
+ break;
+ default:
+ qWarning() << "PaletteColor Property switch default case";
+ break; //replace with assert before switch?
+ }
+
+ return out;
+}
+
+QColor PaletteColor::color() const
+{
+ return m_color;
+}
+
+void PaletteColor::setColor(const QColor &value)
+{
+ m_color = value;
+ m_colorCode = m_color.name(QColor::HexArgb);
+}
+
+QString PaletteColor::colorCode() const
+{
+ return m_colorCode;
+}
+
+bool PaletteColor::isFavorite() const
+{
+ return m_isFavorite;
+}
+
+void PaletteColor::setFavorite(bool favorite)
+{
+ m_isFavorite = favorite;
+}
+
+bool PaletteColor::toggleFavorite()
+{
+ return m_isFavorite = !m_isFavorite;
+}
+
+bool PaletteColor::operator==(const PaletteColor &other) const
+{
+ return (m_color == other.m_color);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h
new file mode 100644
index 0000000000..342c9832e7
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalette.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 <QObject>
+#include <QtQml/qqml.h>
+#include <QColor>
+
+namespace QmlDesigner {
+
+class PaletteColor
+{
+ Q_GADGET
+
+ Q_PROPERTY(QColor color READ color FINAL)
+ Q_PROPERTY(QString colorCode READ colorCode FINAL)
+ Q_PROPERTY(bool isFavorite READ isFavorite FINAL)
+public:
+ PaletteColor();
+ PaletteColor(const QString &colorCode);
+ PaletteColor(const QColor &value);
+ ~PaletteColor() = default;
+
+ enum Property {
+ objectNameRole = 0,
+ colorRole = 1,
+ colorCodeRole = 2,
+ isFavoriteRole = 3
+ };
+
+ QVariant getProperty(Property id) const;
+
+ QColor color() const;
+ void setColor(const QColor &value);
+
+ QString colorCode() const;
+
+ bool isFavorite() const;
+ void setFavorite(bool favorite);
+ bool toggleFavorite();
+
+ bool operator==(const PaletteColor &other) const;
+
+private:
+ QColor m_color;
+ QString m_colorCode;
+ bool m_isFavorite;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::PaletteColor)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp
new file mode 100644
index 0000000000..b3207f0006
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** 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 "simplecolorpalettemodel.h"
+#include "simplecolorpalette.h"
+#include "simplecolorpalettesingleton.h"
+
+#include "designersettings.h"
+
+#include <QHash>
+#include <QByteArray>
+#include <QDebug>
+#include <QSettings>
+
+namespace QmlDesigner {
+
+SimpleColorPaletteModel::SimpleColorPaletteModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+ connect(&SimpleColorPaletteSingleton::getInstance(),
+ &SimpleColorPaletteSingleton::paletteChanged,
+ this,
+ &SimpleColorPaletteModel::setPalette);
+ m_roleNames = {{static_cast<int>(PaletteColor::Property::objectNameRole), "objectName"},
+ {static_cast<int>(PaletteColor::Property::colorRole), "color"},
+ {static_cast<int>(PaletteColor::Property::colorCodeRole), "colorCode"},
+ {static_cast<int>(PaletteColor::Property::isFavoriteRole), "isFavorite"}};
+
+ setPalette();
+}
+
+SimpleColorPaletteModel::~SimpleColorPaletteModel()
+{
+ clearItems();
+}
+
+int SimpleColorPaletteModel::rowCount(const QModelIndex & /*parent*/) const
+{
+ return m_items.count();
+}
+
+QVariant SimpleColorPaletteModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && (index.row() >= 0) && (index.row() < m_items.count())) {
+ if (m_roleNames.contains(role)) {
+ QVariant value = m_items.at(index.row())
+ .getProperty(static_cast<PaletteColor::Property>(role));
+ if (auto model = qobject_cast<SimpleColorPaletteModel *>(value.value<QObject *>()))
+ return QVariant::fromValue(model);
+
+ return value;
+ }
+
+ qWarning() << Q_FUNC_INFO << "invalid role requested";
+ return QVariant();
+ }
+
+ qWarning() << Q_FUNC_INFO << "invalid index requested";
+ return QVariant();
+}
+
+QHash<int, QByteArray> SimpleColorPaletteModel::roleNames() const
+{
+ return m_roleNames;
+}
+
+void SimpleColorPaletteModel::clearItems()
+{
+ beginResetModel();
+ m_items.clear();
+ endResetModel();
+}
+
+void SimpleColorPaletteModel::addItem(const QString &item)
+{
+ PaletteColor palette(item);
+ addItem(palette);
+}
+
+void SimpleColorPaletteModel::addItem(const PaletteColor &item)
+{
+ SimpleColorPaletteSingleton::getInstance().addItem(item);
+}
+
+const QList<PaletteColor> &SimpleColorPaletteModel::items() const
+{
+ return m_items;
+}
+
+void SimpleColorPaletteModel::sortItems()
+{
+ SimpleColorPaletteSingleton::getInstance().sortItems();
+}
+
+void SimpleColorPaletteModel::registerDeclarativeType()
+{
+ qmlRegisterType<SimpleColorPaletteModel>("HelperWidgets", 2, 0, "SimpleColorPaletteModel");
+}
+
+void SimpleColorPaletteModel::toggleFavorite(int id)
+{
+ SimpleColorPaletteSingleton::getInstance().toggleFavorite(id);
+}
+
+void SimpleColorPaletteModel::setPalette()
+{
+ beginResetModel();
+ m_items = SimpleColorPaletteSingleton::getInstance().getItems();
+ m_favoriteOffset = SimpleColorPaletteSingleton::getInstance().getFavoriteOffset();
+ m_paletteSize = SimpleColorPaletteSingleton::getInstance().getPaletteSize();
+ endResetModel();
+}
+
+bool SimpleColorPaletteModel::read()
+{
+ return SimpleColorPaletteSingleton::getInstance().readPalette();
+}
+
+void SimpleColorPaletteModel::write()
+{
+ SimpleColorPaletteSingleton::getInstance().writePalette();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h
new file mode 100644
index 0000000000..3ed2cc8a31
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettemodel.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 <QAbstractListModel>
+#include <QtQml/qqml.h>
+#include <QList>
+
+namespace QmlDesigner {
+
+class PaletteColor;
+
+class SimpleColorPaletteModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ explicit SimpleColorPaletteModel(QObject *parent = nullptr);
+ ~SimpleColorPaletteModel() override;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ void clearItems();
+ Q_INVOKABLE void addItem(const QString &item);
+ void addItem(const PaletteColor &item);
+
+ const QList<PaletteColor> &items() const;
+
+ void sortItems();
+
+ static void registerDeclarativeType();
+
+ Q_INVOKABLE void toggleFavorite(int id);
+
+ bool read();
+ void write();
+
+private slots:
+ void setPalette();
+
+private:
+ void enqueue(const PaletteColor &item);
+
+private:
+ int m_paletteSize;
+ int m_favoriteOffset;
+ QList<PaletteColor> m_items;
+ QHash<int, QByteArray> m_roleNames;
+};
+
+} // namespace QmlDesigner
+
+QML_DECLARE_TYPE(QmlDesigner::SimpleColorPaletteModel)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp
new file mode 100644
index 0000000000..ccea50bbf2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** 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 "simplecolorpalettesingleton.h"
+#include "simplecolorpalette.h"
+
+#include "designersettings.h"
+
+#include <QDebug>
+#include <QSettings>
+
+namespace QmlDesigner {
+
+SimpleColorPaletteSingleton::SimpleColorPaletteSingleton()
+ : m_items()
+ , m_favoriteOffset(0)
+{
+ if (!readPalette()) {
+ for (int i = 0; i < m_paletteSize; i++)
+ m_items.append(PaletteColor());
+ }
+}
+
+SimpleColorPaletteSingleton &SimpleColorPaletteSingleton::getInstance()
+{
+ static SimpleColorPaletteSingleton singleton;
+
+ return singleton;
+}
+
+void SimpleColorPaletteSingleton::addItem(const PaletteColor &item)
+{
+ if (m_favoriteOffset >= m_paletteSize)
+ return;
+
+ if (item.isFavorite()) {
+ int contains = m_items.indexOf(item);
+ if (contains != -1) {
+ if (m_items.at(contains).isFavorite())
+ return;
+ else
+ m_items.removeAt(contains);
+ }
+ m_items.insert(0, item);
+ m_favoriteOffset++;
+ } else if (m_items.contains(item))
+ return;
+ else
+ m_items.insert(m_favoriteOffset, item);
+
+ while (m_items.size() > m_paletteSize) {
+ m_items.removeLast();
+ }
+
+ writePalette();
+
+ emit paletteChanged();
+}
+
+QList<PaletteColor> SimpleColorPaletteSingleton::getItems() const
+{
+ return m_items;
+}
+
+int SimpleColorPaletteSingleton::getPaletteSize() const
+{
+ return m_paletteSize;
+}
+
+int SimpleColorPaletteSingleton::getFavoriteOffset() const
+{
+ return m_favoriteOffset;
+}
+
+void SimpleColorPaletteSingleton::sortItems()
+{
+ auto itemSort = [](const PaletteColor &first, const PaletteColor &second) {
+ return (static_cast<int>(first.isFavorite()) < static_cast<int>(second.isFavorite()));
+ };
+
+ std::sort(m_items.begin(), m_items.end(), itemSort);
+
+ emit paletteChanged();
+}
+
+void SimpleColorPaletteSingleton::toggleFavorite(int id)
+{
+ bool toggleResult = m_items[id].toggleFavorite();
+
+ if (toggleResult) {
+ m_favoriteOffset++;
+ m_items.move(id, 0);
+ } else {
+ m_favoriteOffset--;
+ m_items.move(id, m_favoriteOffset);
+ }
+
+ if (m_favoriteOffset < 0)
+ m_favoriteOffset = 0;
+ else if (m_favoriteOffset > m_paletteSize)
+ m_favoriteOffset = m_paletteSize;
+
+ emit paletteChanged();
+}
+
+bool SimpleColorPaletteSingleton::readPalette()
+{
+ QList<PaletteColor> proxy;
+ const QStringList stringData = QmlDesigner::DesignerSettings::getValue(
+ QmlDesigner::DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT)
+ .toStringList();
+
+ int favCounter = 0;
+
+ for (int i = 0; i < stringData.size(); i++) {
+ const QStringList strsep = stringData.at(i).split(";");
+ if (strsep.size() != 2) {
+ continue;
+ }
+ PaletteColor colorItem(strsep.at(0));
+ bool isFav = static_cast<bool>(strsep.at(1).toInt());
+ colorItem.setFavorite(isFav);
+ if (isFav)
+ favCounter++;
+ proxy.append(colorItem);
+ }
+
+ if (proxy.size() == 0) {
+ return false;
+ }
+
+ while (proxy.size() > m_paletteSize) {
+ proxy.removeLast();
+ }
+ while (proxy.size() < m_paletteSize) {
+ proxy.append(PaletteColor());
+ }
+
+ m_items.clear();
+ m_items = proxy;
+ m_favoriteOffset = favCounter;
+
+ return true;
+}
+
+void SimpleColorPaletteSingleton::writePalette()
+{
+ QStringList output;
+ QString subres;
+
+ for (int i = 0; i < m_items.size(); i++) {
+ subres = m_items.at(i).color().name(QColor::HexArgb);
+ subres += ";";
+ subres += QString::number(static_cast<int>(m_items.at(i).isFavorite()));
+ output.push_back(subres);
+ subres.clear();
+ }
+
+ QmlDesigner::DesignerSettings::setValue(
+ QmlDesigner::DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT, output);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h
new file mode 100644
index 0000000000..77ad2b0732
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/simplecolorpalettesingleton.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 <QObject>
+#include <QAbstractListModel>
+#include <QtQml/qqml.h>
+#include <QList>
+#include <QColor>
+#include <simplecolorpalette.h>
+
+namespace QmlDesigner {
+
+class SimpleColorPaletteSingleton : public QObject
+{
+ Q_OBJECT
+public:
+ static SimpleColorPaletteSingleton &getInstance();
+
+ bool readPalette();
+ void writePalette();
+
+ void addItem(const PaletteColor &item);
+ QList<PaletteColor> getItems() const;
+
+ int getPaletteSize() const;
+ int getFavoriteOffset() const;
+
+ void sortItems();
+
+ void toggleFavorite(int id);
+
+ SimpleColorPaletteSingleton(const SimpleColorPaletteSingleton &) = delete;
+ void operator=(const SimpleColorPaletteSingleton &) = delete;
+
+signals:
+ void paletteChanged();
+
+private:
+ SimpleColorPaletteSingleton();
+
+private:
+ QList<PaletteColor> m_items;
+ const int m_paletteSize = 6;
+ int m_favoriteOffset;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.cpp b/src/plugins/qmldesigner/components/sourcetool/sourcetool.cpp
index d121e60c73..d121e60c73 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.cpp
+++ b/src/plugins/qmldesigner/components/sourcetool/sourcetool.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.h b/src/plugins/qmldesigner/components/sourcetool/sourcetool.h
index 16797b3912..16797b3912 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.h
+++ b/src/plugins/qmldesigner/components/sourcetool/sourcetool.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.pri b/src/plugins/qmldesigner/components/sourcetool/sourcetool.pri
index 8117fd73e9..8117fd73e9 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/sourcetool/sourcetool.pri
+++ b/src/plugins/qmldesigner/components/sourcetool/sourcetool.pri
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
index 07e758b35a..ae7400e382 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
@@ -185,6 +185,7 @@ void StatesEditorModel::renameState(int internalNodeId, const QString &newName)
newName.isEmpty() ?
tr("The empty string as a name is reserved for the base state.") :
tr("Name already used in another state"));
+ reset();
} else {
m_statesEditorView->renameState(internalNodeId, newName);
}
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
index 2f8bc56650..572b454892 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
@@ -31,7 +31,6 @@
namespace QmlDesigner {
-
class StatesEditorModel;
class StatesEditorWidget;
diff --git a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititem.cpp b/src/plugins/qmldesigner/components/texttool/textedititem.cpp
index 1ce3244cbc..1ce3244cbc 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititem.cpp
+++ b/src/plugins/qmldesigner/components/texttool/textedititem.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititem.h b/src/plugins/qmldesigner/components/texttool/textedititem.h
index 5497dadbe1..5497dadbe1 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititem.h
+++ b/src/plugins/qmldesigner/components/texttool/textedititem.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititemwidget.cpp b/src/plugins/qmldesigner/components/texttool/textedititemwidget.cpp
index 40efb67e77..40efb67e77 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititemwidget.cpp
+++ b/src/plugins/qmldesigner/components/texttool/textedititemwidget.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititemwidget.h b/src/plugins/qmldesigner/components/texttool/textedititemwidget.h
index 7ff2909919..7ff2909919 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/texttool/textedititemwidget.h
+++ b/src/plugins/qmldesigner/components/texttool/textedititemwidget.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.cpp b/src/plugins/qmldesigner/components/texttool/texttool.cpp
index 76dc414c03..76dc414c03 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.cpp
+++ b/src/plugins/qmldesigner/components/texttool/texttool.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.h b/src/plugins/qmldesigner/components/texttool/texttool.h
index b7c352c917..b7c352c917 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.h
+++ b/src/plugins/qmldesigner/components/texttool/texttool.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.pri b/src/plugins/qmldesigner/components/texttool/texttool.pri
index 0cfdfb7629..0cfdfb7629 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/texttool/texttool.pri
+++ b/src/plugins/qmldesigner/components/texttool/texttool.pri
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvas.cpp b/src/plugins/qmldesigner/components/timelineeditor/canvas.cpp
index eab3d0bf56..eab3d0bf56 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvas.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/canvas.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvas.h b/src/plugins/qmldesigner/components/timelineeditor/canvas.h
index c4491e4b79..c4491e4b79 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvas.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/canvas.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.cpp b/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.cpp
new file mode 100644
index 0000000000..88d78615ca
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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 "canvasstyledialog.h"
+
+#include <QColorDialog>
+#include <QDoubleSpinBox>
+#include <QLabel>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QVBoxLayout>
+
+namespace QmlDesigner {
+
+CanvasStyleDialog::CanvasStyleDialog(const CanvasStyle &style, QWidget *parent)
+ : QDialog(parent)
+ , m_aspect(new QDoubleSpinBox(this))
+ , m_thinLineWidth(new QDoubleSpinBox(this))
+ , m_thickLineWidth(new QDoubleSpinBox(this))
+ , m_thinLineColor(new ColorControl(style.thinLineColor, this))
+ , m_thickLineColor(new ColorControl(style.thickLineColor, this))
+ , m_handleSize(new QDoubleSpinBox(this))
+ , m_handleLineWidth(new QDoubleSpinBox(this))
+ , m_endPointColor(new ColorControl(style.endPointColor, this))
+ , m_interPointColor(new ColorControl(style.interPointColor, this))
+ , m_curveWidth(new QDoubleSpinBox(this))
+{
+ m_aspect->setValue(style.aspect);
+ m_thinLineWidth->setValue(style.thinLineWidth);
+ m_thickLineWidth->setValue(style.thickLineWidth);
+ m_handleSize->setValue(style.handleSize);
+ m_handleLineWidth->setValue(style.handleLineWidth);
+ m_curveWidth->setValue(style.curveWidth);
+
+ int labelWidth = QFontMetrics(this->font()).horizontalAdvance("Inter Handle ColorXX");
+ auto addControl = [labelWidth](QVBoxLayout *layout, const QString &name, QWidget *control) {
+ auto *hbox = new QHBoxLayout;
+
+ QLabel *label = new QLabel(name);
+ label->setAlignment(Qt::AlignLeft);
+ label->setFixedWidth(labelWidth);
+
+ hbox->addWidget(label);
+ hbox->addWidget(control);
+ layout->addLayout(hbox);
+ };
+
+ auto layout = new QVBoxLayout;
+ addControl(layout, "Aspect Ratio", m_aspect);
+
+ addControl(layout, "Thin Line Width", m_thinLineWidth);
+ addControl(layout, "Thin Line Color", m_thinLineColor);
+
+ addControl(layout, "Thick Line Width", m_thickLineWidth);
+ addControl(layout, "Thick Line Color", m_thickLineColor);
+
+ addControl(layout, "Handle Size", m_handleSize);
+ addControl(layout, "Handle Line Width", m_handleLineWidth);
+ addControl(layout, "End Handle Color", m_endPointColor);
+ addControl(layout, "Inter Handle Color", m_interPointColor);
+
+ addControl(layout, "Curve Width", m_curveWidth);
+
+ setLayout(layout);
+
+ auto emitValueChanged = [this]() {
+ CanvasStyle out;
+ out.aspect = m_aspect->value();
+ out.thinLineWidth = m_thinLineWidth->value();
+ out.thickLineWidth = m_thickLineWidth->value();
+ out.thinLineColor = m_thinLineColor->value();
+ out.thickLineColor = m_thickLineColor->value();
+ out.handleSize = m_handleSize->value();
+ out.handleLineWidth = m_handleLineWidth->value();
+ out.endPointColor = m_endPointColor->value();
+ out.interPointColor = m_interPointColor->value();
+ out.curveWidth = m_curveWidth->value();
+ emit styleChanged(out);
+ };
+
+ auto doubleValueChanged = QOverload<double>::of(
+ &QDoubleSpinBox::valueChanged);
+ auto colorValueChanged = &ColorControl::valueChanged;
+
+ connect(m_aspect, doubleValueChanged, this, emitValueChanged);
+
+ connect(m_thinLineWidth, doubleValueChanged, this, emitValueChanged);
+ connect(m_thickLineWidth, doubleValueChanged, this, emitValueChanged);
+
+ connect(m_thinLineColor, colorValueChanged, this, emitValueChanged);
+ connect(m_thickLineColor, colorValueChanged, this, emitValueChanged);
+
+ connect(m_handleSize, doubleValueChanged, this, emitValueChanged);
+ connect(m_handleLineWidth, doubleValueChanged, this, emitValueChanged);
+
+ connect(m_endPointColor, colorValueChanged, this, emitValueChanged);
+ connect(m_interPointColor, colorValueChanged, this, emitValueChanged);
+
+ connect(m_curveWidth, doubleValueChanged, this, emitValueChanged);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvasstyledialog.h b/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.h
index b3b1a86c95..b3b1a86c95 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvasstyledialog.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/canvasstyledialog.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp b/src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp
new file mode 100644
index 0000000000..cae0bfab09
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** 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 "easingcurve.h"
+#include "timelineutils.h"
+
+#include <QDataStream>
+#include <QDebug>
+#include <QLineF>
+#include <QPainterPath>
+#include <QPointF>
+
+#include <utils/qtcassert.h>
+
+namespace QmlDesigner {
+
+EasingCurve::EasingCurve()
+ : QEasingCurve(QEasingCurve::BezierSpline)
+ , m_active(-1)
+ , m_start(0.0, 0.0)
+{}
+
+EasingCurve::EasingCurve(const QEasingCurve &curve)
+ : QEasingCurve(curve)
+ , m_active(-1)
+ , m_start(0.0, 0.0)
+{}
+
+EasingCurve::EasingCurve(const EasingCurve &curve) = default;
+
+EasingCurve::EasingCurve(const QPointF &start, const QVector<QPointF> &points)
+ : QEasingCurve(QEasingCurve::BezierSpline)
+ , m_active(-1)
+ , m_start(start)
+{
+ fromCubicSpline(points);
+}
+
+EasingCurve &EasingCurve::operator=(const EasingCurve &curve) = default;
+
+EasingCurve::~EasingCurve() = default;
+
+bool EasingCurve::IsValidIndex(int idx)
+{
+ return idx >= 0;
+}
+
+void EasingCurve::registerStreamOperators()
+{
+ qRegisterMetaType<QmlDesigner::EasingCurve>("QmlDesigner::EasingCurve");
+ qRegisterMetaType<QmlDesigner::NamedEasingCurve>("QmlDesigner::NamedEasingCurve");
+ qRegisterMetaTypeStreamOperators<QmlDesigner::EasingCurve>("QmlDesigner::EasingCurve");
+ qRegisterMetaTypeStreamOperators<QmlDesigner::NamedEasingCurve>("QmlDesigner::NamedEasingCurve");
+}
+
+int EasingCurve::count() const
+{
+ return toCubicSpline().count();
+}
+
+int EasingCurve::active() const
+{
+ return m_active;
+}
+
+int EasingCurve::segmentCount() const
+{
+ return toCubicSpline().count() / 3;
+}
+
+bool EasingCurve::isLegal() const
+{
+ QPainterPath painterPath(path());
+
+ double increment = 1.0 / 30.0;
+ QPointF max = painterPath.pointAtPercent(0.0);
+ for (double i = increment; i <= 1.0; i += increment) {
+ QPointF current = painterPath.pointAtPercent(i);
+ if (current.x() < max.x())
+ return false;
+ else
+ max = current;
+ }
+ return true;
+}
+
+bool EasingCurve::hasActive() const
+{
+ QTC_ASSERT(m_active < toCubicSpline().size(), return false);
+ return m_active >= 0;
+}
+
+bool EasingCurve::isValidIndex(int idx) const
+{
+ return idx >= 0 && idx < toCubicSpline().size();
+}
+
+bool EasingCurve::isSmooth(int idx) const
+{
+ auto iter = std::find(m_smoothIds.begin(), m_smoothIds.end(), idx);
+ return iter != m_smoothIds.end();
+}
+
+bool EasingCurve::isHandle(int idx) const
+{
+ return (idx + 1) % 3;
+}
+
+bool EasingCurve::isLeftHandle(int idx) const
+{
+ return ((idx + 2) % 3) == 0;
+}
+
+QString EasingCurve::toString() const
+{
+ QLatin1Char c(',');
+ QString s = QLatin1String("[");
+ for (const QPointF &point : toCubicSpline()) {
+ auto x = QString::number(point.x(), 'g', 3);
+ auto y = QString::number(point.y(), 'g', 3);
+ s += x + c + y + c;
+ }
+
+ // Replace last "," with "]"
+ s.chop(1);
+ s.append(QLatin1Char(']'));
+
+ return s;
+}
+
+bool EasingCurve::fromString(const QString &code)
+{
+ if (code.startsWith(QLatin1Char('[')) && code.endsWith(QLatin1Char(']'))) {
+ const QStringRef cleanCode(&code, 1, code.size() - 2);
+ const auto stringList = cleanCode.split(QLatin1Char(','), QString::SkipEmptyParts);
+
+ if (stringList.count() >= 6 && (stringList.count() % 6 == 0)) {
+ bool checkX, checkY;
+ QVector<QPointF> points;
+ for (int i = 0; i < stringList.count(); ++i) {
+ QPointF point;
+ point.rx() = stringList[i].toDouble(&checkX);
+ point.ry() = stringList[++i].toDouble(&checkY);
+
+ if (!checkX || !checkY)
+ return false;
+
+ points.push_back(point);
+ }
+
+ if (points.constLast() != QPointF(1.0, 1.0))
+ return false;
+
+ QEasingCurve easingCurve(QEasingCurve::BezierSpline);
+
+ for (int i = 0; i < points.count() / 3; ++i) {
+ easingCurve.addCubicBezierSegment(points.at(i * 3),
+ points.at(i * 3 + 1),
+ points.at(i * 3 + 2));
+ }
+
+ fromCubicSpline(easingCurve.toCubicSpline());
+ return true;
+ }
+ }
+ return false;
+}
+
+QPointF EasingCurve::start() const
+{
+ return m_start;
+}
+
+QPointF EasingCurve::end() const
+{
+ return toCubicSpline().last();
+}
+
+QPainterPath EasingCurve::path() const
+{
+ QPainterPath path;
+ path.moveTo(m_start);
+
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ int numSegments = controlPoints.count() / 3;
+ for (int i = 0; i < numSegments; i++) {
+ QPointF p1 = controlPoints.at(i * 3);
+ QPointF p2 = controlPoints.at(i * 3 + 1);
+ QPointF p3 = controlPoints.at(i * 3 + 2);
+ path.cubicTo(p1, p2, p3);
+ }
+
+ return path;
+}
+
+int EasingCurve::curvePoint(int idx) const
+{
+ if (isHandle(idx)) {
+ if (isLeftHandle(idx))
+ return idx + 1;
+ else
+ return idx - 1;
+ }
+ return idx;
+}
+
+QPointF EasingCurve::point(int idx) const
+{
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ QTC_ASSERT(controlPoints.count() > idx || idx < 0, return QPointF());
+
+ return controlPoints.at(idx);
+}
+
+int EasingCurve::hit(const QPointF &point, double threshold) const
+{
+ int id = -1;
+ qreal distance = std::numeric_limits<qreal>::max();
+
+ QVector<QPointF> controlPoints = toCubicSpline();
+ for (int i = 0; i < controlPoints.size() - 1; ++i) {
+ qreal d = QLineF(point, controlPoints.at(i)).length();
+ if (d < threshold && d < distance) {
+ distance = d;
+ id = i;
+ }
+ }
+ return id;
+}
+
+void EasingCurve::makeDefault()
+{
+ QVector<QPointF> controlPoints;
+ controlPoints.append(QPointF(0.0, 0.2));
+ controlPoints.append(QPointF(0.3, 0.5));
+ controlPoints.append(QPointF(0.5, 0.5));
+
+ controlPoints.append(QPointF(0.7, 0.5));
+ controlPoints.append(QPointF(1.0, 0.8));
+ controlPoints.append(QPointF(1.0, 1.0));
+
+ fromCubicSpline(controlPoints);
+
+ m_smoothIds.push_back(2);
+}
+
+void EasingCurve::clearActive()
+{
+ m_active = -1;
+}
+
+void EasingCurve::setActive(int idx)
+{
+ m_active = idx;
+}
+
+void EasingCurve::makeSmooth(int idx)
+{
+ if (!isSmooth(idx) && !isHandle(idx)) {
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ QPointF before = m_start;
+ if (idx > 3)
+ before = controlPoints.at(idx - 3);
+
+ QPointF after = end();
+ if ((idx + 3) < controlPoints.count())
+ after = controlPoints.at(idx + 3);
+
+ QPointF tangent = (after - before) / 6;
+
+ QPointF thisPoint = controlPoints.at(idx);
+
+ if (idx > 0)
+ controlPoints[idx - 1] = thisPoint - tangent;
+
+ if (idx + 1 < controlPoints.count())
+ controlPoints[idx + 1] = thisPoint + tangent;
+
+ fromCubicSpline(controlPoints);
+
+ m_smoothIds.push_back(idx);
+ }
+}
+
+void EasingCurve::breakTangent(int idx)
+{
+ if (isSmooth(idx) && !isHandle(idx)) {
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ QPointF before = m_start;
+ if (idx > 3)
+ before = controlPoints.at(idx - 3);
+
+ QPointF after = end();
+ if ((idx + 3) < controlPoints.count())
+ after = controlPoints.at(idx + 3);
+
+ QPointF thisPoint = controlPoints.at(idx);
+
+ if (idx > 0)
+ controlPoints[idx - 1] = (before - thisPoint) / 3 + thisPoint;
+
+ if (idx + 1 < controlPoints.count())
+ controlPoints[idx + 1] = (after - thisPoint) / 3 + thisPoint;
+
+ fromCubicSpline(controlPoints);
+
+ auto iter = std::find(m_smoothIds.begin(), m_smoothIds.end(), idx);
+ m_smoothIds.erase(iter);
+ }
+}
+
+void EasingCurve::addPoint(const QPointF &point)
+{
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ int splitIndex = 0;
+ for (int i = 0; i < controlPoints.size() - 1; ++i) {
+ if (!isHandle(i)) {
+ if (controlPoints.at(i).x() > point.x())
+ break;
+
+ splitIndex = i;
+ }
+ }
+
+ QPointF before = m_start;
+ if (splitIndex > 0) {
+ before = controlPoints.at(splitIndex);
+ }
+
+ QPointF after = end();
+ if ((splitIndex + 3) < controlPoints.count()) {
+ after = controlPoints.at(splitIndex + 3);
+ }
+
+ int newIdx;
+
+ if (splitIndex > 0) {
+ newIdx = splitIndex + 3;
+ controlPoints.insert(splitIndex + 2, (point + after) / 2);
+ controlPoints.insert(splitIndex + 2, point);
+ controlPoints.insert(splitIndex + 2, (point + before) / 2);
+ } else {
+ newIdx = splitIndex + 2;
+ controlPoints.insert(splitIndex + 1, (point + after) / 2);
+ controlPoints.insert(splitIndex + 1, point);
+ controlPoints.insert(splitIndex + 1, (point + before) / 2);
+ }
+
+ fromCubicSpline(controlPoints);
+
+ QTC_ASSERT(!isHandle(newIdx), return );
+
+ m_active = newIdx;
+
+ breakTangent(newIdx);
+ makeSmooth(newIdx);
+}
+
+void EasingCurve::setPoint(int idx, const QPointF &point)
+{
+ if (!isValidIndex(idx))
+ return;
+
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ controlPoints[idx] = point;
+
+ fromCubicSpline(controlPoints);
+}
+
+void EasingCurve::movePoint(int idx, const QPointF &vector)
+{
+ if (!isValidIndex(idx))
+ return;
+
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ controlPoints[idx] += vector;
+
+ fromCubicSpline(controlPoints);
+}
+
+void EasingCurve::deletePoint(int idx)
+{
+ if (!isValidIndex(idx))
+ return;
+
+ QVector<QPointF> controlPoints = toCubicSpline();
+
+ controlPoints.remove(idx - 1, 3);
+
+ fromCubicSpline(controlPoints);
+}
+
+void EasingCurve::fromCubicSpline(const QVector<QPointF> &points)
+{
+ QEasingCurve tmp(QEasingCurve::BezierSpline);
+
+ int numSegments = points.count() / 3;
+ for (int i = 0; i < numSegments; ++i) {
+ tmp.addCubicBezierSegment(points.at(i * 3), points.at(i * 3 + 1), points.at(i * 3 + 2));
+ }
+ swap(tmp);
+}
+
+QDebug &operator<<(QDebug &stream, const EasingCurve &curve)
+{
+ stream << static_cast<QEasingCurve>(curve);
+ stream << "\"active:" << curve.m_active << "\"";
+ stream << "\"smooth ids:" << curve.m_smoothIds << "\"";
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const EasingCurve &curve)
+{
+ // Ignore the active flag.
+ stream << static_cast<QEasingCurve>(curve);
+ stream << curve.toCubicSpline();
+ stream << curve.m_smoothIds;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, EasingCurve &curve)
+{
+ // This is to circumvent a bug in QEasingCurve serialization.
+ QVector<QPointF> points;
+
+ // Ignore the active flag.
+ stream >> static_cast<QEasingCurve &>(curve);
+ stream >> points;
+ curve.fromCubicSpline(points);
+ stream >> curve.m_smoothIds;
+
+ return stream;
+}
+
+NamedEasingCurve::NamedEasingCurve()
+ : m_name()
+ , m_curve()
+{}
+
+NamedEasingCurve::NamedEasingCurve(const QString &name, const EasingCurve &curve)
+ : m_name(name)
+ , m_curve(curve)
+{}
+
+NamedEasingCurve::NamedEasingCurve(const NamedEasingCurve &other) = default;
+
+NamedEasingCurve::~NamedEasingCurve() = default;
+
+QString NamedEasingCurve::name() const
+{
+ return m_name;
+}
+
+EasingCurve NamedEasingCurve::curve() const
+{
+ return m_curve;
+}
+
+QDataStream &operator<<(QDataStream &stream, const NamedEasingCurve &curve)
+{
+ stream << curve.m_name;
+ stream << curve.m_curve;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, NamedEasingCurve &curve)
+{
+ stream >> curve.m_name;
+ stream >> curve.m_curve;
+ return stream;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/timelineeditor/easingcurve.h b/src/plugins/qmldesigner/components/timelineeditor/easingcurve.h
new file mode 100644
index 0000000000..d46f5600aa
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/easingcurve.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** 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 <QEasingCurve>
+#include <QMetaType>
+#include <QPointF>
+
+QT_FORWARD_DECLARE_CLASS(QPainterPath);
+
+namespace QmlDesigner {
+
+class EasingCurve : public QEasingCurve
+{
+public:
+ EasingCurve();
+
+ EasingCurve(const QEasingCurve &curve);
+
+ EasingCurve(const EasingCurve &curve);
+
+ EasingCurve(const QPointF &start, const QVector<QPointF> &points);
+
+ virtual ~EasingCurve();
+
+ EasingCurve &operator=(const EasingCurve &curve);
+
+ static bool IsValidIndex(int idx);
+
+ static void registerStreamOperators();
+
+public:
+ int count() const;
+
+ int active() const;
+
+ int segmentCount() const;
+
+ bool hasActive() const;
+
+ bool isLegal() const;
+
+ bool isValidIndex(int idx) const;
+
+ bool isSmooth(int idx) const;
+
+ bool isHandle(int idx) const;
+
+ bool isLeftHandle(int idx) const;
+
+ QString toString() const;
+
+ QPointF start() const;
+
+ QPointF end() const;
+
+ QPainterPath path() const;
+
+ int curvePoint(int idx) const;
+
+ QPointF point(int idx) const;
+
+ int hit(const QPointF &point, double threshold) const;
+
+public:
+ void makeDefault();
+
+ void clearActive();
+
+ void setActive(int idx);
+
+ void makeSmooth(int idx);
+
+ void breakTangent(int idx);
+
+ void addPoint(const QPointF &point);
+
+ void setPoint(int idx, const QPointF &point);
+
+ void movePoint(int idx, const QPointF &vector);
+
+ void deletePoint(int idx);
+
+ bool fromString(const QString &string);
+
+ void fromCubicSpline(const QVector<QPointF> &points);
+
+ friend QDebug &operator<<(QDebug &stream, const EasingCurve &curve);
+
+ friend QDataStream &operator<<(QDataStream &stream, const EasingCurve &curve);
+
+ friend QDataStream &operator>>(QDataStream &stream, EasingCurve &curve);
+
+ friend std::ostream &operator<<(std::ostream &stream, const EasingCurve &curve);
+
+ friend std::istream &operator>>(std::istream &stream, EasingCurve &curve);
+
+private:
+ int m_active;
+
+ QPointF m_start;
+
+ std::vector<int> m_smoothIds;
+};
+
+class NamedEasingCurve
+{
+public:
+ NamedEasingCurve();
+
+ NamedEasingCurve(const QString &name, const EasingCurve &curve);
+
+ NamedEasingCurve(const NamedEasingCurve &other);
+
+ virtual ~NamedEasingCurve();
+
+ QString name() const;
+
+ EasingCurve curve() const;
+
+ friend QDataStream &operator<<(QDataStream &stream, const NamedEasingCurve &curve);
+
+ friend QDataStream &operator>>(QDataStream &stream, NamedEasingCurve &curve);
+
+private:
+ QString m_name;
+
+ EasingCurve m_curve;
+};
+
+} // namespace QmlDesigner
+
+Q_DECLARE_METATYPE(QmlDesigner::EasingCurve);
+Q_DECLARE_METATYPE(QmlDesigner::NamedEasingCurve);
diff --git a/src/plugins/qmldesigner/components/timelineeditor/easingcurvedialog.cpp b/src/plugins/qmldesigner/components/timelineeditor/easingcurvedialog.cpp
new file mode 100644
index 0000000000..a069dc187b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/easingcurvedialog.cpp
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** 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 "easingcurvedialog.h"
+
+#include "preseteditor.h"
+#include "splineeditor.h"
+
+#include <QApplication>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QMessageBox>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QSizePolicy>
+#include <QSpinBox>
+#include <QTabBar>
+#include <QTabWidget>
+#include <QVBoxLayout>
+
+#include <abstractview.h>
+#include <bindingproperty.h>
+#include <rewritingexception.h>
+#include <theme.h>
+#include <utils/qtcassert.h>
+
+namespace QmlDesigner {
+
+EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *parent)
+ : QDialog(parent)
+ , m_splineEditor(new SplineEditor(this))
+ , m_text(new QPlainTextEdit(this))
+ , m_presets(new PresetEditor(this))
+ , m_durationLayout(new QHBoxLayout)
+ , m_buttons(new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel
+ | QDialogButtonBox::Ok))
+ , m_label(new QLabel)
+ , m_frames(frames)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ auto tw = new QTabWidget;
+ tw->setTabPosition(QTabWidget::East);
+ tw->addTab(m_splineEditor, "Curve");
+ tw->addTab(m_text, "Text");
+
+ connect(tw, &QTabWidget::currentChanged, this, &EasingCurveDialog::tabClicked);
+ connect(m_text, &QPlainTextEdit::textChanged, this, &EasingCurveDialog::textChanged);
+
+ auto labelFont = m_label->font();
+ labelFont.setPointSize(labelFont.pointSize() + 2);
+ m_label->setFont(labelFont);
+
+ auto hSpacing = qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
+ auto vSpacing = qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ auto *vbox = new QVBoxLayout;
+ vbox->setContentsMargins(2, 0, 0, vSpacing);
+ vbox->addWidget(m_label);
+
+ auto *presetBar = new QTabBar;
+
+ auto smallFont = presetBar->font();
+ smallFont.setPixelSize(Theme::instance()->smallFontPixelSize());
+
+ presetBar->setFont(smallFont);
+ presetBar->setExpanding(false);
+ presetBar->setDrawBase(false);
+ presetBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+
+ auto *durationLabel = new QLabel("Duration (ms)");
+ auto *durationEdit = new QSpinBox;
+ durationEdit->setMaximum(std::numeric_limits<int>::max());
+ durationEdit->setValue(1000);
+ auto *animateButton = new QPushButton("Preview");
+
+ m_durationLayout->setContentsMargins(0, vSpacing, 0, 0);
+ m_durationLayout->addWidget(durationLabel);
+ m_durationLayout->addWidget(durationEdit);
+ m_durationLayout->addWidget(animateButton);
+
+ m_durationLayout->insertSpacing(1, hSpacing);
+ m_durationLayout->insertSpacing(2, hSpacing);
+ m_durationLayout->insertSpacing(4, hSpacing);
+ m_durationLayout->addStretch(hSpacing);
+
+ m_buttons->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ auto callButtonsClicked = [this](QAbstractButton *button) {
+ buttonsClicked(m_buttons->standardButton(button));
+ };
+
+ connect(m_buttons, &QDialogButtonBox::clicked, this, callButtonsClicked);
+
+ auto *buttonLayout = new QVBoxLayout;
+ buttonLayout->setContentsMargins(0, vSpacing, 0, 0);
+ buttonLayout->addWidget(m_buttons);
+
+ auto *grid = new QGridLayout;
+ grid->setVerticalSpacing(0);
+ grid->addLayout(vbox, 0, 0);
+ grid->addWidget(presetBar, 0, 1, Qt::AlignBottom);
+
+ grid->addWidget(tw);
+ grid->addWidget(m_presets, 1, 1);
+ grid->addLayout(m_durationLayout, 2, 0);
+ grid->addLayout(buttonLayout, 2, 1);
+
+ auto *groupBox = new QGroupBox;
+ groupBox->setLayout(grid);
+
+ auto *tabWidget = new QTabWidget(this);
+ tabWidget->addTab(groupBox, "Easing Curve Editor");
+
+ auto *mainBox = new QVBoxLayout;
+ mainBox->addWidget(tabWidget);
+ setLayout(mainBox);
+
+ connect(m_splineEditor,
+ &SplineEditor::easingCurveChanged,
+ this,
+ &EasingCurveDialog::updateEasingCurve);
+
+ connect(m_presets, &PresetEditor::presetChanged, m_splineEditor, &SplineEditor::setEasingCurve);
+
+ connect(durationEdit,
+ QOverload<int>::of(&QSpinBox::valueChanged),
+ m_splineEditor,
+ &SplineEditor::setDuration);
+
+ connect(animateButton, &QPushButton::clicked, m_splineEditor, &SplineEditor::animate);
+
+ m_presets->initialize(presetBar);
+
+ m_splineEditor->setDuration(durationEdit->value());
+
+ resize(QSize(1421, 918));
+}
+
+void EasingCurveDialog::initialize(const QString &curveString)
+{
+ EasingCurve curve;
+ if (curveString.isEmpty()) {
+ QEasingCurve qcurve;
+ qcurve.addCubicBezierSegment(QPointF(0.2, 0.2), QPointF(0.8, 0.8), QPointF(1.0, 1.0));
+ curve = EasingCurve(qcurve);
+ } else
+ curve.fromString(curveString);
+
+ m_splineEditor->setEasingCurve(curve);
+}
+
+void EasingCurveDialog::runDialog(const QList<ModelNode> &frames, QWidget *parent)
+{
+ if (frames.empty())
+ return;
+
+ EasingCurveDialog dialog(frames, parent);
+
+ ModelNode current = frames.last();
+
+ if (current.hasBindingProperty("easing.bezierCurve"))
+ dialog.initialize(current.bindingProperty("easing.bezierCurve").expression());
+ else
+ dialog.initialize("");
+
+ dialog.exec();
+}
+
+bool EasingCurveDialog::apply()
+{
+ QTC_ASSERT(!m_frames.empty(), return false);
+
+ EasingCurve curve = m_splineEditor->easingCurve();
+ if (!curve.isLegal()) {
+ QMessageBox msgBox;
+ msgBox.setText("Attempting to apply invalid curve to keyframe");
+ msgBox.setInformativeText("Please solve the issue before proceeding.");
+ msgBox.setStandardButtons(QMessageBox::Ok);
+ msgBox.exec();
+ return false;
+ }
+ AbstractView *view = m_frames.first().view();
+
+ return view->executeInTransaction("EasingCurveDialog::apply", [this, view](){
+ auto expression = m_splineEditor->easingCurve().toString();
+ for (const auto &frame : m_frames)
+ frame.bindingProperty("easing.bezierCurve").setExpression(expression);
+ });
+}
+
+void EasingCurveDialog::textChanged()
+{
+ auto curve = m_splineEditor->easingCurve();
+ curve.fromString(m_text->toPlainText());
+ m_splineEditor->setEasingCurve(curve);
+}
+
+void EasingCurveDialog::tabClicked(int id)
+{
+ if (auto tw = qobject_cast<const QTabWidget *>(sender())) {
+ int seid = tw->indexOf(m_splineEditor);
+ if (seid == id) {
+ for (int i = 0; i < m_durationLayout->count(); ++i) {
+ auto *item = m_durationLayout->itemAt(i);
+ if (auto *widget = item->widget())
+ widget->show();
+ }
+
+ auto curve = m_splineEditor->easingCurve();
+ curve.fromString(m_text->toPlainText());
+ m_splineEditor->setEasingCurve(curve);
+
+ } else {
+ for (int i = 0; i < m_durationLayout->count(); ++i) {
+ auto *item = m_durationLayout->itemAt(i);
+ if (auto *widget = item->widget())
+ widget->hide();
+ }
+
+ auto curve = m_splineEditor->easingCurve();
+ m_text->setPlainText(curve.toString());
+ }
+ }
+}
+
+void EasingCurveDialog::presetTabClicked(int id)
+{
+ m_presets->activate(id);
+}
+
+void EasingCurveDialog::updateEasingCurve(const EasingCurve &curve)
+{
+ if (!curve.isLegal()) {
+ auto *save = m_buttons->button(QDialogButtonBox::Save);
+ save->setEnabled(false);
+
+ auto *ok = m_buttons->button(QDialogButtonBox::Ok);
+ ok->setEnabled(false);
+
+ m_label->setText("Invalid Curve!");
+ } else {
+ auto *save = m_buttons->button(QDialogButtonBox::Save);
+ save->setEnabled(true);
+
+ auto *ok = m_buttons->button(QDialogButtonBox::Ok);
+ ok->setEnabled(true);
+
+ m_label->setText("");
+ }
+
+ m_presets->update(curve);
+}
+
+void EasingCurveDialog::buttonsClicked(QDialogButtonBox::StandardButton button)
+{
+ switch (button) {
+ case QDialogButtonBox::Ok:
+ if (apply())
+ close();
+ break;
+
+ case QDialogButtonBox::Cancel:
+ close();
+ break;
+
+ case QDialogButtonBox::Save:
+ m_presets->writePresets(m_splineEditor->easingCurve());
+ break;
+
+ default:
+ break;
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurvedialog.h b/src/plugins/qmldesigner/components/timelineeditor/easingcurvedialog.h
index a8c026989c..a8c026989c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurvedialog.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/easingcurvedialog.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/add_timeline.png b/src/plugins/qmldesigner/components/timelineeditor/images/add_timeline.png
index af651276ed..af651276ed 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/add_timeline.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/add_timeline.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/add_timeline@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/add_timeline@2x.png
index 58a7174288..58a7174288 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/add_timeline@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/add_timeline@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/animation.png b/src/plugins/qmldesigner/components/timelineeditor/images/animation.png
index 20ad0273b5..20ad0273b5 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/animation.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/animation.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/animation@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/animation@2x.png
index 1ecf1857c7..1ecf1857c7 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/animation@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/animation@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/back_one_frame.png b/src/plugins/qmldesigner/components/timelineeditor/images/back_one_frame.png
index 69c93ebe3e..69c93ebe3e 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/back_one_frame.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/back_one_frame.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/back_one_frame@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/back_one_frame@2x.png
index 9bd8a52e59..9bd8a52e59 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/back_one_frame@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/back_one_frame@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_editor.png b/src/plugins/qmldesigner/components/timelineeditor/images/curve_editor.png
index bda4dc0095..bda4dc0095 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_editor.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/curve_editor.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_editor@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/curve_editor@2x.png
index 3d5c3abe05..3d5c3abe05 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_editor@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/curve_editor@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_picker.png b/src/plugins/qmldesigner/components/timelineeditor/images/curve_picker.png
index 4842ac0738..4842ac0738 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_picker.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/curve_picker.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_picker@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/curve_picker@2x.png
index 0d99fc180c..0d99fc180c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/curve_picker@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/curve_picker@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/forward_one_frame.png b/src/plugins/qmldesigner/components/timelineeditor/images/forward_one_frame.png
index 0846f194e0..0846f194e0 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/forward_one_frame.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/forward_one_frame.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/forward_one_frame@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/forward_one_frame@2x.png
index 8e5ddc3930..8e5ddc3930 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/forward_one_frame@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/forward_one_frame@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/global_record_keyframes.png b/src/plugins/qmldesigner/components/timelineeditor/images/global_record_keyframes.png
index 64a28ca075..64a28ca075 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/global_record_keyframes.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/global_record_keyframes.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/global_record_keyframes@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/global_record_keyframes@2x.png
index 534737f385..534737f385 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/global_record_keyframes@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/global_record_keyframes@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/is_keyframe.png b/src/plugins/qmldesigner/components/timelineeditor/images/is_keyframe.png
index 5655e0b278..5655e0b278 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/is_keyframe.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/is_keyframe.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/is_keyframe@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/is_keyframe@2x.png
index 2f522c22b6..2f522c22b6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/is_keyframe@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/is_keyframe@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe-16px.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe-16px.png
index 6e1c9f912a..6e1c9f912a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe-16px.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe-16px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe.png
index 6bf7d1ad53..6bf7d1ad53 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe@2x.png
index 5102e279a1..5102e279a1 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_active.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_active.png
index 8a3eaa7888..8a3eaa7888 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_active.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_active.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_active@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_active@2x.png
index e0168a097a..e0168a097a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_active@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_active@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_inactive.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_inactive.png
index 2c12d98e01..2c12d98e01 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_inactive.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_inactive.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_inactive@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_inactive@2x.png
index 4bbbe6cd3f..4bbbe6cd3f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_inactive@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_inactive@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_selected.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_selected.png
index 58ccb7c765..58ccb7c765 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_selected.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_selected.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_selected@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_selected@2x.png
index 829dd99391..829dd99391 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_autobezier_selected@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_autobezier_selected@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_active.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_active.png
index a195ac5fca..a195ac5fca 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_active.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_active.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_active@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_active@2x.png
index fd879e5837..fd879e5837 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_active@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_active@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_inactive.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_inactive.png
index b84a800097..b84a800097 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_inactive.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_inactive.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_inactive@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_inactive@2x.png
index 0ad868dcd6..0ad868dcd6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_inactive@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_inactive@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_selected.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_selected.png
index e840819f2d..e840819f2d 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_selected.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_selected.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_selected@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_selected@2x.png
index e5f63f1fc9..e5f63f1fc9 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_linear_selected@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_linear_selected@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_active.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_active.png
index f85d3f78fd..f85d3f78fd 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_active.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_active.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_active@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_active@2x.png
index 2f65f7970c..2f65f7970c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_active@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_active@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_inactive.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_inactive.png
index 9798c76115..9798c76115 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_inactive.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_inactive.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_inactive@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_inactive@2x.png
index b4ee45a566..b4ee45a566 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_inactive@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_inactive@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_selected.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_selected.png
index 1e39f84502..1e39f84502 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_selected.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_selected.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_selected@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_selected@2x.png
index b99474718c..b99474718c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_lineartobezier_selected@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_lineartobezier_selected@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_active.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_active.png
index 4b6a7c8978..4b6a7c8978 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_active.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_active.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_active@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_active@2x.png
index fd85a10758..fd85a10758 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_active@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_active@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_inactive.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_inactive.png
index 9c0a1fd550..9c0a1fd550 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_inactive.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_inactive.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_inactive@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_inactive@2x.png
index 1299a370fc..1299a370fc 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_inactive@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_inactive@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_selected.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_selected.png
index 7b5faebae0..7b5faebae0 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_selected.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_selected.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_selected@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_selected@2x.png
index 726ead7a43..726ead7a43 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/keyframe_manualbezier_selected@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/keyframe_manualbezier_selected@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/local_record_keyframes.png b/src/plugins/qmldesigner/components/timelineeditor/images/local_record_keyframes.png
index d68aa73214..d68aa73214 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/local_record_keyframes.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/local_record_keyframes.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/local_record_keyframes@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/local_record_keyframes@2x.png
index f5265a2218..f5265a2218 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/local_record_keyframes@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/local_record_keyframes@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/loop_playback.png b/src/plugins/qmldesigner/components/timelineeditor/images/loop_playback.png
index f38fbef1d4..f38fbef1d4 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/loop_playback.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/loop_playback.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/loop_playback@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/loop_playback@2x.png
index b760a04133..b760a04133 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/loop_playback@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/loop_playback@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/next_keyframe.png b/src/plugins/qmldesigner/components/timelineeditor/images/next_keyframe.png
index 415ec0127f..415ec0127f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/next_keyframe.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/next_keyframe.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/next_keyframe@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/next_keyframe@2x.png
index 3f1e24e04a..3f1e24e04a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/next_keyframe@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/next_keyframe@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/pause_playback.png b/src/plugins/qmldesigner/components/timelineeditor/images/pause_playback.png
index 001ca37b1c..001ca37b1c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/pause_playback.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/pause_playback.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/pause_playback@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/pause_playback@2x.png
index 95e8567ccb..95e8567ccb 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/pause_playback@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/pause_playback@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/playhead.png b/src/plugins/qmldesigner/components/timelineeditor/images/playhead.png
index 518a77f404..518a77f404 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/playhead.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/playhead.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/playhead@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/playhead@2x.png
index 7f6778556b..7f6778556b 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/playhead@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/playhead@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/previous_keyframe.png b/src/plugins/qmldesigner/components/timelineeditor/images/previous_keyframe.png
index 52ba668973..52ba668973 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/previous_keyframe.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/previous_keyframe.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/previous_keyframe@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/previous_keyframe@2x.png
index df151051fc..df151051fc 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/previous_keyframe@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/previous_keyframe@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/remove_timeline.png b/src/plugins/qmldesigner/components/timelineeditor/images/remove_timeline.png
index 0589f982a7..0589f982a7 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/remove_timeline.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/remove_timeline.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/remove_timeline@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/remove_timeline@2x.png
index 9eed9ce3c3..9eed9ce3c3 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/remove_timeline@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/remove_timeline@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/start_playback.png b/src/plugins/qmldesigner/components/timelineeditor/images/start_playback.png
index 0cf0865c48..0cf0865c48 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/start_playback.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/start_playback.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/start_playback@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/start_playback@2x.png
index f05dfcd9ed..f05dfcd9ed 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/start_playback@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/start_playback@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/timeline-16px.png b/src/plugins/qmldesigner/components/timelineeditor/images/timeline-16px.png
index d4ecf00031..d4ecf00031 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/timeline-16px.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/timeline-16px.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_first_frame.png b/src/plugins/qmldesigner/components/timelineeditor/images/to_first_frame.png
index 910b856638..910b856638 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_first_frame.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/to_first_frame.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_first_frame@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/to_first_frame@2x.png
index abefa72fb3..abefa72fb3 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_first_frame@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/to_first_frame@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_last_frame.png b/src/plugins/qmldesigner/components/timelineeditor/images/to_last_frame.png
index d6bc429196..d6bc429196 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_last_frame.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/to_last_frame.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_last_frame@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/to_last_frame@2x.png
index affc3c9848..affc3c9848 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/to_last_frame@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/to_last_frame@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_left.png b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_left.png
index 83d441d64f..83d441d64f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_left.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_left.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_left@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_left@2x.png
index 0fec4b269e..0fec4b269e 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_left@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_left@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_right.png b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_right.png
index 611684a7f6..611684a7f6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_right.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_right.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_right@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_right@2x.png
index c1dbdbc56c..c1dbdbc56c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/work_area_handle_right@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/work_area_handle_right@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_big.png b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_big.png
index eec61eb86c..eec61eb86c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_big.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_big.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_big@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_big@2x.png
index 1706de0bb4..1706de0bb4 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_big@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_big@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_small.png b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_small.png
index 20433d99c4..20433d99c4 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_small.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_small.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_small@2x.png b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_small@2x.png
index 326ea32c25..326ea32c25 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/images/zoom_small@2x.png
+++ b/src/plugins/qmldesigner/components/timelineeditor/images/zoom_small@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/components/timelineeditor/preseteditor.cpp b/src/plugins/qmldesigner/components/timelineeditor/preseteditor.cpp
new file mode 100644
index 0000000000..8ea7692e3d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/preseteditor.cpp
@@ -0,0 +1,560 @@
+/****************************************************************************
+**
+** 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 "preseteditor.h"
+
+#include "canvas.h"
+#include "easingcurve.h"
+#include "timelineicons.h"
+
+#include <QAbstractButton>
+#include <QApplication>
+#include <QContextMenuEvent>
+#include <QMenu>
+#include <QMessageBox>
+#include <QPainter>
+#include <QPixmap>
+#include <QSettings>
+#include <QStandardItemModel>
+#include <QString>
+
+#include <coreplugin/icore.h>
+#include <theme.h>
+
+namespace QmlDesigner {
+
+constexpr int iconWidth = 86;
+constexpr int iconHeight = 86;
+constexpr int itemFrame = 3;
+constexpr int itemWidth = iconWidth + 2 * itemFrame;
+constexpr int unsavedMarkSize = 18;
+
+constexpr int spacingg = 5;
+
+const QColor background = Qt::white;
+
+const QColor labelBackground = qRgb(0x70, 0x70, 0x70);
+const QColor canvasBackground = qRgb(0x46, 0x46, 0x46);
+const QColor curveLine = qRgb(0xe6, 0xe7, 0xe8);
+
+PresetItemDelegate::PresetItemDelegate() = default;
+
+void PresetItemDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &opt,
+ const QModelIndex &index) const
+{
+ QStyleOptionViewItem option = opt;
+ initStyleOption(&option, index);
+
+ auto *w = option.widget;
+ auto *style = w == nullptr ? qApp->style() : w->style();
+
+ QSize textSize = QSize(option.rect.width(),
+ style->subElementRect(QStyle::SE_ItemViewItemText, &option, w).height());
+
+ auto textRect = QRect(option.rect.topLeft(), textSize);
+ textRect.moveBottom(option.rect.bottom());
+
+ option.font.setPixelSize(Theme::instance()->smallFontPixelSize());
+
+ painter->save();
+ painter->fillRect(option.rect, canvasBackground);
+
+ if (option.text.isEmpty())
+ painter->fillRect(textRect, canvasBackground);
+ else
+ painter->fillRect(textRect, Theme::instance()->qmlDesignerButtonColor());
+
+ style->drawControl(QStyle::CE_ItemViewItem, &option, painter, option.widget);
+
+ QVariant dirty = option.index.data(PresetList::ItemRole_Dirty);
+ if (dirty.isValid()) {
+ if (dirty.toBool()) {
+ QRect asteriskRect(option.rect.right() - unsavedMarkSize,
+ itemFrame,
+ unsavedMarkSize,
+ unsavedMarkSize);
+
+ QFont font = painter->font();
+ font.setPixelSize(unsavedMarkSize);
+ painter->setFont(font);
+
+ auto pen = painter->pen();
+ pen.setColor(Qt::white);
+ painter->setPen(pen);
+
+ painter->drawText(asteriskRect, Qt::AlignTop | Qt::AlignRight, "*");
+ }
+ }
+ painter->restore();
+}
+
+QSize PresetItemDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const
+{
+ QSize size = QStyledItemDelegate::sizeHint(opt, index);
+ size.rwidth() = itemWidth;
+ return size;
+}
+
+QIcon paintPreview()
+{
+ QPixmap pm(iconWidth, iconHeight);
+ pm.fill(canvasBackground);
+ return QIcon(pm);
+}
+
+QIcon paintPreview(const EasingCurve &curve)
+{
+ QPixmap pm(iconWidth, iconHeight);
+ pm.fill(canvasBackground);
+
+ QPainter painter(&pm);
+ painter.setRenderHint(QPainter::Antialiasing, true);
+
+ Canvas canvas(iconWidth, iconHeight, 2, 2, 9, 6, 0, 1);
+ canvas.paintCurve(&painter, curve, curveLine);
+
+ return QIcon(pm);
+}
+
+namespace Internal {
+
+static const char settingsKey[] = "EasingCurveList";
+static const char settingsFileName[] = "/EasingCurves.ini";
+
+QString settingsFullFilePath(const QSettings::Scope &scope)
+{
+ if (scope == QSettings::SystemScope)
+ return Core::ICore::installerResourcePath() + settingsFileName;
+
+ return Core::ICore::userResourcePath() + settingsFileName;
+}
+
+} // namespace Internal
+
+PresetList::PresetList(QSettings::Scope scope, QWidget *parent)
+ : QListView(parent)
+ , m_scope(scope)
+ , m_index(-1)
+ , m_filename(Internal::settingsFullFilePath(scope))
+{
+ int magic = 4;
+ int scrollBarWidth = this->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+ const int width = 3 * itemWidth + 4 * spacingg + scrollBarWidth + magic;
+
+ setFixedWidth(width);
+
+ setModel(new QStandardItemModel);
+
+ setItemDelegate(new PresetItemDelegate);
+
+ setSpacing(spacingg);
+
+ setUniformItemSizes(true);
+
+ setIconSize(QSize(iconWidth, iconHeight));
+
+ setSelectionMode(QAbstractItemView::SingleSelection);
+
+ setViewMode(QListView::IconMode);
+
+ setFlow(QListView::LeftToRight);
+
+ setMovement(QListView::Static);
+
+ setWrapping(true);
+
+ setTextElideMode(Qt::ElideMiddle);
+
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+}
+
+void PresetList::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+{
+ for (const QModelIndex &index : deselected.indexes()) {
+ if (dirty(index)) {
+ QMessageBox msgBox;
+ msgBox.setText("The preset has been modified.");
+ msgBox.setInformativeText("Do you want to save your changes?");
+ msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard
+ | QMessageBox::Cancel);
+ msgBox.setDefaultButton(QMessageBox::Save);
+
+ if (QAbstractButton *button = msgBox.button(QMessageBox::Discard))
+ button->setText("Discard Changes");
+
+ if (QAbstractButton *button = msgBox.button(QMessageBox::Cancel))
+ button->setText("Cancel Selection");
+
+ int ret = msgBox.exec();
+
+ switch (ret) {
+ case QMessageBox::Save:
+ // Save the preset and continue selection.
+ writePresets();
+ break;
+ case QMessageBox::Discard:
+ // Discard changes to the curve and continue selection.
+ revert(index);
+ break;
+
+ case QMessageBox::Cancel:
+ // Cancel selection operation and leave the curve untouched.
+ selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
+ return;
+
+ default:
+ // should never be reachedDiscard
+ break;
+ }
+ }
+ }
+
+ for (const auto &index : selected.indexes()) {
+ QVariant curveData = model()->data(index, ItemRole_Data);
+ if (curveData.isValid())
+ emit presetChanged(curveData.value<EasingCurve>());
+ }
+}
+
+bool PresetList::hasSelection() const
+{
+ return selectionModel()->hasSelection();
+}
+
+bool PresetList::dirty(const QModelIndex &index) const
+{
+ return model()->data(index, ItemRole_Dirty).toBool();
+}
+
+int PresetList::index() const
+{
+ return m_index;
+}
+
+bool PresetList::isEditable(const QModelIndex &index) const
+{
+ QFlags<Qt::ItemFlag> flags(model()->flags(index));
+ return flags.testFlag(Qt::ItemIsEditable);
+}
+
+void PresetList::initialize(int index)
+{
+ m_index = index;
+
+ readPresets();
+}
+
+void PresetList::readPresets()
+{
+ auto *simodel = qobject_cast<QStandardItemModel *>(model());
+
+ simodel->clear();
+
+ QList<NamedEasingCurve> curves = storedCurves();
+
+ for (int i = 0; i < curves.size(); ++i) {
+ QVariant curveData = QVariant::fromValue(curves[i].curve());
+
+ auto *item = new QStandardItem(paintPreview(curves[i].curve()), curves[i].name());
+ item->setData(curveData, ItemRole_Data);
+ item->setEditable(m_scope == QSettings::UserScope);
+ item->setToolTip(curves[i].name());
+
+ simodel->setItem(i, item);
+ }
+}
+
+void PresetList::writePresets()
+{
+ QList<QVariant> presets;
+ for (int i = 0; i < model()->rowCount(); ++i) {
+ QModelIndex index = model()->index(i, 0);
+
+ QVariant nameData = model()->data(index, Qt::DisplayRole);
+ QVariant curveData = model()->data(index, ItemRole_Data);
+
+ if (nameData.isValid() && curveData.isValid()) {
+ NamedEasingCurve curve(nameData.toString(), curveData.value<QmlDesigner::EasingCurve>());
+
+ presets << QVariant::fromValue(curve);
+ }
+
+ model()->setData(index, false, ItemRole_Dirty);
+ }
+
+ QSettings settings(m_filename, QSettings::IniFormat);
+ settings.clear();
+ settings.setValue(Internal::settingsKey, QVariant::fromValue(presets));
+}
+
+void PresetList::revert(const QModelIndex &index)
+{
+ auto *simodel = qobject_cast<QStandardItemModel *>(model());
+ if (auto *item = simodel->itemFromIndex(index)) {
+ QString name = item->data(Qt::DisplayRole).toString();
+ QList<NamedEasingCurve> curves = storedCurves();
+
+ for (const auto &curve : curves) {
+ if (curve.name() == name) {
+ item->setData(false, ItemRole_Dirty);
+ item->setData(paintPreview(curve.curve()), Qt::DecorationRole);
+ item->setData(QVariant::fromValue(curve.curve()), ItemRole_Data);
+ item->setToolTip(name);
+ return;
+ }
+ }
+ }
+}
+
+void PresetList::updateCurve(const EasingCurve &curve)
+{
+ if (!selectionModel()->hasSelection())
+ return;
+
+ QVariant icon = QVariant::fromValue(paintPreview(curve));
+ QVariant curveData = QVariant::fromValue(curve);
+
+ for (const auto &index : selectionModel()->selectedIndexes())
+ setItemData(index, curveData, icon);
+}
+
+void PresetList::contextMenuEvent(QContextMenuEvent *event)
+{
+ event->accept();
+
+ if (m_scope == QSettings::SystemScope)
+ return;
+
+ QMenu menu;
+
+ QAction *addAction = menu.addAction(tr("Add Preset"));
+
+ connect(addAction, &QAction::triggered, [&]() { createItem(); });
+
+ if (selectionModel()->hasSelection()) {
+ QAction *removeAction = menu.addAction(tr("Delete Selected Preset"));
+ connect(removeAction, &QAction::triggered, [&]() { removeSelectedItem(); });
+ }
+
+ menu.exec(event->globalPos());
+}
+
+void PresetList::dataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight,
+ const QVector<int> &roles)
+{
+ if (topLeft == bottomRight && roles.contains(0)) {
+ QVariant name = model()->data(topLeft, 0);
+ model()->setData(topLeft, name, Qt::ToolTipRole);
+ }
+}
+
+void PresetList::createItem()
+{
+ EasingCurve curve;
+ curve.makeDefault();
+ createItem(createUniqueName(), curve);
+}
+
+void PresetList::createItem(const QString &name, const EasingCurve &curve)
+{
+ auto *item = new QStandardItem(paintPreview(curve), name);
+ item->setData(QVariant::fromValue(curve), ItemRole_Data);
+ item->setToolTip(name);
+
+ int row = model()->rowCount();
+ qobject_cast<QStandardItemModel *>(model())->setItem(row, item);
+
+ QModelIndex index = model()->index(row, 0);
+
+ // Why is that needed? SingleSelection is specified.
+ selectionModel()->clear();
+ selectionModel()->select(index, QItemSelectionModel::Select);
+}
+
+void PresetList::removeSelectedItem()
+{
+ for (const auto &index : selectionModel()->selectedIndexes())
+ model()->removeRow(index.row());
+
+ writePresets();
+}
+
+void PresetList::setItemData(const QModelIndex &index, const QVariant &curve, const QVariant &icon)
+{
+ if (isEditable(index)) {
+ model()->setData(index, curve, PresetList::ItemRole_Data);
+ model()->setData(index, true, PresetList::ItemRole_Dirty);
+ model()->setData(index, icon, Qt::DecorationRole);
+ }
+}
+
+QString PresetList::createUniqueName() const
+{
+ QStringList names = allNames();
+ auto nameIsUnique = [&](const QString &name) {
+ auto iter = std::find(names.begin(), names.end(), name);
+ if (iter == names.end())
+ return true;
+ else
+ return false;
+ };
+
+ int counter = 0;
+ QString tmp("Default");
+ QString name = tmp;
+
+ while (!nameIsUnique(name))
+ name = tmp + QString(" %1").arg(counter++);
+
+ return name;
+}
+
+QStringList PresetList::allNames() const
+{
+ QStringList names;
+ for (int i = 0; i < model()->rowCount(); ++i) {
+ QModelIndex index = model()->index(i, 0);
+ QVariant nameData = model()->data(index, Qt::DisplayRole);
+ if (nameData.isValid())
+ names << nameData.toString();
+ }
+
+ return names;
+}
+
+QList<NamedEasingCurve> PresetList::storedCurves() const
+{
+ QSettings settings(m_filename, QSettings::IniFormat);
+ QVariant presetSettings = settings.value(Internal::settingsKey);
+
+ if (!presetSettings.isValid())
+ return QList<NamedEasingCurve>();
+
+ QList<QVariant> presets = presetSettings.toList();
+
+ QList<NamedEasingCurve> out;
+ for (const QVariant &preset : presets)
+ if (preset.isValid())
+ out << preset.value<NamedEasingCurve>();
+
+ return out;
+}
+
+PresetEditor::PresetEditor(QWidget *parent)
+ : QStackedWidget(parent)
+ , m_presets(new PresetList(QSettings::SystemScope))
+ , m_customs(new PresetList(QSettings::UserScope))
+{
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+
+ addWidget(m_presets);
+ addWidget(m_customs);
+
+ connect(m_presets, &PresetList::presetChanged, this, &PresetEditor::presetChanged);
+ connect(m_customs, &PresetList::presetChanged, this, &PresetEditor::presetChanged);
+}
+
+void PresetEditor::initialize(QTabBar *bar)
+{
+ m_presets->initialize(bar->addTab("Presets"));
+ m_customs->initialize(bar->addTab("Custom"));
+
+ connect(bar, &QTabBar::currentChanged, this, &PresetEditor::activate);
+ connect(this, &PresetEditor::currentChanged, bar, &QTabBar::setCurrentIndex);
+
+ m_presets->selectionModel()->clear();
+ m_customs->selectionModel()->clear();
+
+ activate(m_presets->index());
+}
+
+void PresetEditor::activate(int id)
+{
+ if (id == m_presets->index())
+ setCurrentWidget(m_presets);
+ else
+ setCurrentWidget(m_customs);
+}
+
+void PresetEditor::update(const EasingCurve &curve)
+{
+ if (isCurrent(m_presets))
+ m_presets->selectionModel()->clear();
+ else {
+ if (m_customs->selectionModel()->hasSelection()) {
+ QVariant icon = QVariant::fromValue(paintPreview(curve));
+ QVariant curveData = QVariant::fromValue(curve);
+ for (const QModelIndex &index : m_customs->selectionModel()->selectedIndexes())
+ m_customs->setItemData(index, curveData, icon);
+ }
+ }
+}
+
+bool PresetEditor::writePresets(const EasingCurve &curve)
+{
+ if (!curve.isLegal()) {
+ QMessageBox msgBox;
+ msgBox.setText("Attempting to save invalid curve");
+ msgBox.setInformativeText("Please solve the issue before proceeding.");
+ msgBox.setStandardButtons(QMessageBox::Ok);
+ msgBox.exec();
+ return false;
+ }
+
+ if (auto current = qobject_cast<const PresetList *>(currentWidget())) {
+ if (current->index() == m_presets->index()
+ || (current->index() == m_customs->index() && !m_customs->hasSelection())) {
+ bool ok;
+ QString name = QInputDialog::getText(this,
+ tr("Save Preset"),
+ tr("Name"),
+ QLineEdit::Normal,
+ QString(),
+ &ok);
+
+ if (ok && !name.isEmpty()) {
+ activate(m_customs->index());
+ m_customs->createItem(name, curve);
+ }
+ }
+
+ m_customs->writePresets();
+ return true;
+ }
+
+ return false;
+}
+
+bool PresetEditor::isCurrent(PresetList *list)
+{
+ if (auto current = qobject_cast<const PresetList *>(currentWidget()))
+ return list->index() == current->index();
+
+ return false;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/preseteditor.h b/src/plugins/qmldesigner/components/timelineeditor/preseteditor.h
index 6fab3e7adb..6fab3e7adb 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/preseteditor.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/preseteditor.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.cpp b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
index 4120aaee21..4120aaee21 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.h b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
index e7ed226b67..e7ed226b67 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.ui b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
index 2fa1241e4a..2fa1241e4a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/setframevaluedialog.ui
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/splineeditor.cpp b/src/plugins/qmldesigner/components/timelineeditor/splineeditor.cpp
index 44ef1f194c..44ef1f194c 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/splineeditor.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/splineeditor.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/splineeditor.h b/src/plugins/qmldesigner/components/timelineeditor/splineeditor.h
index 8b454943ad..8b454943ad 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/splineeditor.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/splineeditor.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timeline.metainfo b/src/plugins/qmldesigner/components/timelineeditor/timeline.metainfo
index c1d7e92bf5..c1d7e92bf5 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timeline.metainfo
+++ b/src/plugins/qmldesigner/components/timelineeditor/timeline.metainfo
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timeline.qrc b/src/plugins/qmldesigner/components/timelineeditor/timeline.qrc
index b793c1f8da..b793c1f8da 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timeline.qrc
+++ b/src/plugins/qmldesigner/components/timelineeditor/timeline.qrc
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineabstracttool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineabstracttool.cpp
index 485bb8dbb0..485bb8dbb0 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineabstracttool.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineabstracttool.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineabstracttool.h b/src/plugins/qmldesigner/components/timelineeditor/timelineabstracttool.h
index 0411a8d166..0411a8d166 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineabstracttool.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineabstracttool.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineactions.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineactions.cpp
new file mode 100644
index 0000000000..4751765874
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineactions.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** 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 "timelineactions.h"
+
+#include "timelineutils.h"
+#include "timelineview.h"
+
+#include <bindingproperty.h>
+#include <designdocument.h>
+#include <designdocumentview.h>
+#include <nodelistproperty.h>
+#include <nodemetainfo.h>
+#include <rewritertransaction.h>
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+#include <variantproperty.h>
+#include <qmldesignerplugin.h>
+#include <qmlobjectnode.h>
+#include <qmltimelinekeyframegroup.h>
+
+namespace QmlDesigner {
+
+TimelineActions::TimelineActions() = default;
+
+void TimelineActions::deleteAllKeyframesForTarget(const ModelNode &targetNode,
+ const QmlTimeline &timeline)
+{
+ targetNode.view()->executeInTransaction("TimelineActions::deleteAllKeyframesForTarget", [=](){
+ if (timeline.isValid()) {
+ for (auto frames : timeline.keyframeGroupsForTarget(targetNode))
+ frames.destroy();
+ }
+ });
+}
+
+void TimelineActions::insertAllKeyframesForTarget(const ModelNode &targetNode,
+ const QmlTimeline &timeline)
+{
+ targetNode.view()->executeInTransaction("TimelineActions::insertAllKeyframesForTarget", [=](){
+ auto object = QmlObjectNode(targetNode);
+ if (timeline.isValid() && object.isValid()) {
+ for (auto frames : timeline.keyframeGroupsForTarget(targetNode)) {
+ QVariant value = object.instanceValue(frames.propertyName());
+ frames.setValue(value, timeline.currentKeyframe());
+ }
+ }
+
+ });
+}
+
+void TimelineActions::copyAllKeyframesForTarget(const ModelNode &targetNode,
+ const QmlTimeline &timeline)
+{
+ DesignDocumentView::copyModelNodes(Utils::transform(timeline.keyframeGroupsForTarget(targetNode),
+ &QmlTimelineKeyframeGroup::modelNode));
+}
+
+void TimelineActions::pasteKeyframesToTarget(const ModelNode &targetNode,
+ const QmlTimeline &timeline)
+{
+ if (timeline.isValid()) {
+ QScopedPointer<Model> pasteModel(DesignDocumentView::pasteToModel());
+
+ if (!pasteModel)
+ return;
+
+ DesignDocumentView view;
+ pasteModel->attachView(&view);
+
+ if (!view.rootModelNode().isValid())
+ return;
+
+ ModelNode rootNode = view.rootModelNode();
+
+ //Sanity check
+ if (!QmlTimelineKeyframeGroup::checkKeyframesType(rootNode)) {
+ for (const ModelNode &node : rootNode.directSubModelNodes())
+ if (!QmlTimelineKeyframeGroup::checkKeyframesType(node))
+ return;
+ }
+
+ pasteModel->detachView(&view);
+
+ view.executeInTransaction("TimelineActions::pasteKeyframesToTarget", [=, &view](){
+
+
+ targetNode.view()->model()->attachView(&view);
+
+ ModelNode nonConstTargetNode = targetNode;
+ nonConstTargetNode.validId();
+
+ if (QmlTimelineKeyframeGroup::checkKeyframesType(rootNode)) {
+ /* Single selection */
+
+ ModelNode newNode = view.insertModel(rootNode);
+ QmlTimelineKeyframeGroup frames(newNode);
+ frames.setTarget(targetNode);
+
+ timeline.modelNode().defaultNodeListProperty().reparentHere(newNode);
+
+ } else {
+ /* Multi selection */
+ for (const ModelNode &node : rootNode.directSubModelNodes()) {
+ ModelNode newNode = view.insertModel(node);
+ QmlTimelineKeyframeGroup frames(newNode);
+ frames.setTarget(targetNode);
+ timeline.modelNode().defaultNodeListProperty().reparentHere(newNode);
+ }
+ }
+ });
+ }
+}
+
+void TimelineActions::copyKeyframes(const QList<ModelNode> &keyframes)
+{
+ QList<ModelNode> nodes;
+ for (const auto &node : keyframes) {
+ NodeAbstractProperty pp = node.parentProperty();
+ QTC_ASSERT(pp.isValid(), return );
+
+ ModelNode parentModelNode = pp.parentModelNode();
+ for (const auto &property : parentModelNode.properties()) {
+ auto name = property.name();
+ if (property.isBindingProperty()) {
+ BindingProperty bp = property.toBindingProperty();
+ ModelNode bpNode = bp.resolveToModelNode();
+ if (bpNode.isValid())
+ node.setAuxiliaryData(name, bpNode.id());
+ } else if (property.isVariantProperty()) {
+ VariantProperty vp = property.toVariantProperty();
+ node.setAuxiliaryData(name, vp.value());
+ }
+ }
+
+ nodes << node;
+ }
+
+ DesignDocumentView::copyModelNodes(nodes);
+}
+
+bool isKeyframe(const ModelNode &node)
+{
+ return node.isValid() && node.metaInfo().isValid()
+ && node.metaInfo().isSubclassOf("QtQuick.Timeline.Keyframe");
+}
+
+QVariant getValue(const ModelNode &node)
+{
+ if (node.isValid())
+ return node.variantProperty("value").value();
+
+ return QVariant();
+}
+
+qreal getTime(const ModelNode &node)
+{
+ Q_ASSERT(node.isValid());
+ Q_ASSERT(node.hasProperty("frame"));
+
+ return node.variantProperty("frame").value().toReal();
+}
+
+QmlTimelineKeyframeGroup getFrameGroup(const ModelNode &node,
+ AbstractView *timelineView,
+ const QmlTimeline &timeline)
+{
+ QVariant targetId = node.auxiliaryData("target");
+ QVariant property = node.auxiliaryData("property");
+
+ if (targetId.isValid() && property.isValid()) {
+ ModelNode targetNode = timelineView->modelNodeForId(targetId.toString());
+ if (targetNode.isValid()) {
+ for (QmlTimelineKeyframeGroup frameGrp : timeline.keyframeGroupsForTarget(targetNode)) {
+ if (frameGrp.propertyName() == property.toByteArray())
+ return frameGrp;
+ }
+ }
+ }
+ return QmlTimelineKeyframeGroup();
+}
+
+void pasteKeyframe(const qreal expectedTime,
+ const ModelNode &keyframe,
+ AbstractView *timelineView,
+ const QmlTimeline &timeline)
+{
+ QmlTimelineKeyframeGroup group = getFrameGroup(keyframe, timelineView, timeline);
+ if (group.isValid()) {
+ const qreal clampedTime = TimelineUtils::clamp(expectedTime,
+ timeline.startKeyframe(),
+ timeline.endKeyframe());
+
+ // Create a new frame ...
+ group.setValue(getValue(keyframe), clampedTime);
+
+ // ... look it up by time ...
+ for (const ModelNode &key : group.keyframePositions()) {
+ qreal time = key.variantProperty("frame").value().toReal();
+ if (qFuzzyCompare(clampedTime, time)) {
+ // ... and transfer the properties.
+ for (const auto &property : keyframe.properties()) {
+ if (property.name() == "frame" || property.name() == "value")
+ continue;
+
+ if (property.isVariantProperty()) {
+ auto vp = property.toVariantProperty();
+ key.variantProperty(vp.name()).setValue(vp.value());
+ } else if (property.isBindingProperty()) {
+ auto bp = property.toBindingProperty();
+ key.bindingProperty(bp.name()).setExpression(bp.expression());
+ }
+ }
+ }
+ }
+ }
+}
+
+std::vector<std::tuple<ModelNode, qreal>> getFramesRelative(const ModelNode &parent)
+{
+ auto byTime = [](const ModelNode &lhs, const ModelNode &rhs) {
+ return getTime(lhs) < getTime(rhs);
+ };
+
+ std::vector<std::tuple<ModelNode, qreal>> result;
+
+ QList<ModelNode> sortedByTime;
+ QList<ModelNode> subs(parent.directSubModelNodes());
+
+ std::copy_if(subs.begin(), subs.end(), std::back_inserter(sortedByTime), &isKeyframe);
+ std::sort(sortedByTime.begin(), sortedByTime.end(), byTime);
+
+ if (!sortedByTime.empty()) {
+ qreal firstTime = getTime(sortedByTime.first());
+ for (ModelNode keyframe : sortedByTime)
+ result.emplace_back(keyframe, getTime(keyframe) - firstTime);
+ }
+
+ return result;
+}
+
+void TimelineActions::pasteKeyframes(AbstractView *timelineView, const QmlTimeline &timeline)
+{
+ QScopedPointer<Model> pasteModel(DesignDocumentView::pasteToModel());
+
+ if (!pasteModel)
+ return;
+
+ DesignDocumentView view;
+ pasteModel->attachView(&view);
+
+ if (!view.rootModelNode().isValid())
+ return;
+
+ const qreal currentTime = timeline.currentKeyframe();
+
+ ModelNode rootNode = view.rootModelNode();
+
+ timelineView->executeInTransaction("TimelineActions::pasteKeyframes", [=](){
+ if (isKeyframe(rootNode))
+ pasteKeyframe(currentTime, rootNode, timelineView, timeline);
+ else
+ for (auto frame : getFramesRelative(rootNode))
+ pasteKeyframe(currentTime + std::get<1>(frame),
+ std::get<0>(frame),
+ timelineView,
+ timeline);
+
+ });
+}
+
+bool TimelineActions::clipboardContainsKeyframes()
+{
+ QScopedPointer<Model> pasteModel(DesignDocumentView::pasteToModel());
+
+ if (!pasteModel)
+ return false;
+
+ DesignDocumentView view;
+ pasteModel->attachView(&view);
+
+ if (!view.rootModelNode().isValid())
+ return false;
+
+ ModelNode rootNode = view.rootModelNode();
+
+ if (!rootNode.hasAnySubModelNodes())
+ return false;
+
+ //Sanity check
+ if (!QmlTimelineKeyframeGroup::checkKeyframesType(rootNode)) {
+ for (const ModelNode &node : rootNode.directSubModelNodes())
+ if (!QmlTimelineKeyframeGroup::checkKeyframesType(node))
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineactions.h b/src/plugins/qmldesigner/components/timelineeditor/timelineactions.h
index bae09b110f..bae09b110f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineactions.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineactions.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
new file mode 100644
index 0000000000..032a133f89
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** 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 "timelineanimationform.h"
+#include "ui_timelineanimationform.h"
+
+#include <abstractview.h>
+#include <bindingproperty.h>
+#include <exception>
+#include <nodelistproperty.h>
+#include <nodemetainfo.h>
+#include <rewritertransaction.h>
+#include <signalhandlerproperty.h>
+#include <variantproperty.h>
+#include <qmlitemnode.h>
+#include <qmlobjectnode.h>
+
+#include <coreplugin/messagebox.h>
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+namespace QmlDesigner {
+
+TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::TimelineAnimationForm)
+{
+ ui->setupUi(this);
+
+ connectSpinBox(ui->duration, "duration");
+ connectSpinBox(ui->loops, "loops");
+
+ connectSpinBox(ui->startFrame, "from");
+ connectSpinBox(ui->endFrame, "to");
+
+ connect(ui->loops, QOverload<int>::of(&QSpinBox::valueChanged), [this]() {
+ ui->continuous->setChecked(ui->loops->value() == -1);
+ });
+
+ connect(ui->continuous, &QCheckBox::toggled, [this](bool checked) {
+ if (checked) {
+ setProperty("loops", -1);
+ ui->loops->setValue(-1);
+ } else {
+ setProperty("loops", 1);
+ ui->loops->setValue(1);
+ }
+ });
+
+ connect(ui->idLineEdit, &QLineEdit::editingFinished, [this]() {
+ QTC_ASSERT(m_timeline.isValid(), return );
+
+ static QString lastString;
+
+ const QString newId = ui->idLineEdit->text();
+
+ if (lastString == newId)
+ return;
+
+ lastString = newId;
+
+ if (newId == animation().id())
+ return;
+
+ bool error = false;
+
+ if (!ModelNode::isValidId(newId)) {
+ Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
+ tr("%1 is an invalid id.").arg(newId));
+ error = true;
+ } else if (animation().view()->hasId(newId)) {
+ Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
+ tr("%1 already exists.").arg(newId));
+ } else {
+ animation().setIdWithRefactoring(newId);
+ error = true;
+ }
+
+ if (error) {
+ lastString.clear();
+ ui->idLineEdit->setText(animation().id());
+ }
+ });
+
+ connect(ui->running, &QCheckBox::clicked, [this](bool checked) {
+ if (checked) {
+ setProperty("running", true);
+ } else {
+ setProperty("running", false);
+ }
+ });
+
+ connect(ui->pingPong, &QCheckBox::clicked, [this](bool checked) {
+ if (checked) {
+ setProperty("pingPong", true);
+ } else {
+ setProperty("pingPong", false);
+ }
+ });
+
+ connect(ui->transitionToState,
+ QOverload<int>::of(&QComboBox::activated),
+ [this](int index) {
+ if (!m_animation.isValid())
+ return;
+ if (!m_animation.view()->rootModelNode().hasId())
+ return;
+
+ ModelNode rootNode = m_animation.view()->rootModelNode();
+
+ if (index == 0) {
+ if (m_animation.signalHandlerProperty("onFinished").isValid())
+ m_animation.removeProperty("onFinished");
+ } else if (index == 1) {
+ m_animation.signalHandlerProperty("onFinished")
+ .setSource(rootNode.id() + ".state = \"" + "\"");
+ } else {
+ m_animation.signalHandlerProperty("onFinished")
+ .setSource(rootNode.id() + ".state = \""
+ + ui->transitionToState->currentText() + "\"");
+ }
+ });
+}
+
+TimelineAnimationForm::~TimelineAnimationForm()
+{
+ delete ui;
+}
+
+void TimelineAnimationForm::setup(const ModelNode &animation)
+{
+ m_timeline = QmlTimeline(animation.parentProperty().parentModelNode());
+ setAnimation(animation);
+ setupAnimation();
+}
+
+ModelNode TimelineAnimationForm::animation() const
+{
+ return m_animation;
+}
+
+void TimelineAnimationForm::setAnimation(const ModelNode &animation)
+{
+ m_animation = animation;
+}
+
+void TimelineAnimationForm::setupAnimation()
+{
+ if (!m_animation.isValid())
+ setEnabled(false);
+
+ if (m_animation.isValid()) {
+ setEnabled(true);
+
+ ui->idLineEdit->setText(m_animation.id());
+
+ if (m_animation.hasVariantProperty("duration"))
+ ui->duration->setValue(m_animation.variantProperty("duration").value().toInt());
+ else
+ ui->duration->setValue(0);
+
+ ui->startFrame->setValue(m_animation.variantProperty("from").value().toInt());
+ ui->endFrame->setValue(m_animation.variantProperty("to").value().toInt());
+
+ if (m_animation.hasVariantProperty("loops"))
+ ui->loops->setValue(m_animation.variantProperty("loops").value().toInt());
+ else
+ ui->loops->setValue(0);
+
+ if (m_animation.hasVariantProperty("running"))
+ ui->running->setChecked(m_animation.variantProperty("running").value().toBool());
+ else
+ ui->running->setChecked(false);
+
+ if (m_animation.hasVariantProperty("pingPong"))
+ ui->pingPong->setChecked(m_animation.variantProperty("pingPong").value().toBool());
+ else
+ ui->pingPong->setChecked(false);
+
+ ui->continuous->setChecked(ui->loops->value() == -1);
+ }
+
+ populateStateComboBox();
+
+ ui->duration->setEnabled(m_animation.isValid());
+ ui->running->setEnabled(m_animation.isValid());
+ ui->continuous->setEnabled(m_animation.isValid());
+ ui->loops->setEnabled(m_animation.isValid());
+}
+
+void TimelineAnimationForm::setProperty(const PropertyName &propertyName, const QVariant &value)
+{
+ QTC_ASSERT(m_animation.isValid(), return );
+
+ try {
+ m_animation.variantProperty(propertyName).setValue(value);
+ } catch (const Exception &e) {
+ e.showException();
+ }
+}
+
+void TimelineAnimationForm::connectSpinBox(QSpinBox *spinBox, const PropertyName &propertyName)
+{
+ connect(spinBox, &QSpinBox::editingFinished, [this, propertyName, spinBox]() {
+ setProperty(propertyName, spinBox->value());
+ });
+}
+
+void TimelineAnimationForm::populateStateComboBox()
+{
+ ui->transitionToState->clear();
+ ui->transitionToState->addItem(tr("none"));
+ ui->transitionToState->addItem(tr("Base State"));
+ if (!m_animation.isValid())
+ return;
+ QmlObjectNode rootNode = QmlObjectNode(m_animation.view()->rootModelNode());
+ if (rootNode.isValid() && rootNode.modelNode().hasId()) {
+ for (const QmlModelState &state : QmlItemNode(rootNode).states().allStates()) {
+ ui->transitionToState
+ ->addItem(state.modelNode().variantProperty("name").value().toString(),
+ QVariant::fromValue<ModelNode>(state.modelNode()));
+ }
+ if (m_animation.signalHandlerProperty("onFinished").isValid()) {
+ const QString source = m_animation.signalHandlerProperty("onFinished").source();
+ const QStringList list = source.split("=");
+ if (list.count() == 2) {
+ QString name = list.last().trimmed();
+ name.chop(1);
+ name.remove(0, 1);
+ if (name.isEmpty())
+ ui->transitionToState->setCurrentIndex(1);
+ else
+ ui->transitionToState->setCurrentText(name);
+ }
+ }
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.h b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.h
index 1b5eaf6cab..1b5eaf6cab 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.ui b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.ui
index 5d13cfa726..5d13cfa726 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.ui
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.ui
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineconstants.h b/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h
index 6c012beec1..6c012beec1 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineconstants.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontext.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinecontext.cpp
index b3e2e12a3f..b3e2e12a3f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontext.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinecontext.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontext.h b/src/plugins/qmldesigner/components/timelineeditor/timelinecontext.h
index a8a6ca3b8f..a8a6ca3b8f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontext.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinecontext.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontrols.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
index 682a14f1c7..682a14f1c7 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontrols.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontrols.h b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.h
index 4c30357be9..4c30357be9 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinecontrols.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineeditor.pri b/src/plugins/qmldesigner/components/timelineeditor/timelineeditor.pri
index 8001748fb0..8001748fb0 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineeditor.pri
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineeditor.pri
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
index eb63ad4883..eb63ad4883 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.h b/src/plugins/qmldesigner/components/timelineeditor/timelineform.h
index 7745de3a0f..7745de3a0f 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineform.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.ui b/src/plugins/qmldesigner/components/timelineeditor/timelineform.ui
index b8b47e4c70..b8b47e4c70 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineform.ui
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineform.ui
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicslayout.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicslayout.cpp
new file mode 100644
index 0000000000..af0f26d249
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicslayout.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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 "timelinegraphicslayout.h"
+
+#include "timelinegraphicsscene.h"
+#include "timelineplaceholder.h"
+#include "timelinesectionitem.h"
+#include "timelineview.h"
+
+#include <QGraphicsLinearLayout>
+
+#include <cmath>
+
+namespace QmlDesigner {
+
+TimelineGraphicsLayout::TimelineGraphicsLayout(TimelineGraphicsScene *scene, TimelineItem *parent)
+ : TimelineItem(parent)
+ , m_layout(new QGraphicsLinearLayout)
+ , m_rulerItem(TimelineRulerSectionItem::create(scene, this))
+ , m_placeholder1(TimelinePlaceholder::create(scene, this))
+ , m_placeholder2(TimelinePlaceholder::create(scene, this))
+{
+ m_layout->setOrientation(Qt::Vertical);
+ m_layout->setSpacing(0);
+ m_layout->setContentsMargins(0, 0, 0, 0);
+
+ m_layout->addItem(m_rulerItem);
+ m_layout->addItem(m_placeholder1);
+ m_layout->addItem(m_placeholder2);
+
+ setLayout(m_layout);
+
+ setPos(QPointF(0, 0));
+
+ connect(m_rulerItem,
+ &TimelineRulerSectionItem::rulerClicked,
+ this,
+ &TimelineGraphicsLayout::rulerClicked);
+}
+
+TimelineGraphicsLayout::~TimelineGraphicsLayout() = default;
+
+double TimelineGraphicsLayout::rulerWidth() const
+{
+ return m_rulerItem->preferredWidth();
+}
+
+double TimelineGraphicsLayout::rulerScaling() const
+{
+ return m_rulerItem->rulerScaling();
+}
+
+double TimelineGraphicsLayout::rulerDuration() const
+{
+ return m_rulerItem->rulerDuration();
+}
+
+double TimelineGraphicsLayout::startFrame() const
+{
+ return m_rulerItem->startFrame();
+}
+
+double TimelineGraphicsLayout::endFrame() const
+{
+ return m_rulerItem->endFrame();
+}
+
+void TimelineGraphicsLayout::setWidth(int width)
+{
+ m_rulerItem->setSizeHints(width);
+ m_placeholder1->setMinimumWidth(width);
+ m_placeholder2->setMinimumWidth(width);
+ setPreferredWidth(width);
+ setMaximumWidth(width);
+}
+
+void TimelineGraphicsLayout::setTimeline(const QmlTimeline &timeline)
+{
+ m_layout->removeItem(m_rulerItem);
+ m_layout->removeItem(m_placeholder1);
+ m_layout->removeItem(m_placeholder2);
+
+ m_rulerItem->setParentItem(nullptr);
+ m_placeholder1->setParentItem(nullptr);
+ m_placeholder2->setParentItem(nullptr);
+
+ qDeleteAll(this->childItems());
+
+ m_rulerItem->setParentItem(this);
+ m_rulerItem->invalidateRulerSize(timeline);
+ m_layout->addItem(m_rulerItem);
+
+ m_placeholder1->setParentItem(this);
+ m_layout->addItem(m_placeholder1);
+
+ m_layout->invalidate();
+
+ if (timeline.isValid()) {
+ for (const ModelNode &target : timeline.allTargets()) {
+ if (target.isValid()) {
+ auto item = TimelineSectionItem::create(timeline, target, this);
+ m_layout->addItem(item);
+ }
+ }
+ }
+
+ m_placeholder2->setParentItem(this);
+ m_layout->addItem(m_placeholder2);
+
+ if (auto *scene = timelineScene())
+ if (auto *view = scene->timelineView())
+ if (!timeline.isValid() && view->isAttached())
+ emit scaleFactorChanged(0);
+}
+
+void TimelineGraphicsLayout::setRulerScaleFactor(int factor)
+{
+ m_rulerItem->setRulerScaleFactor(factor);
+}
+
+void TimelineGraphicsLayout::invalidate()
+{
+ m_layout->invalidate();
+}
+
+int TimelineGraphicsLayout::maximumScrollValue() const
+{
+ const qreal w = this->geometry().width() - qreal(TimelineConstants::sectionWidth);
+ const qreal duration = m_rulerItem->rulerDuration() + m_rulerItem->rulerDuration() * 0.1;
+ const qreal maxr = m_rulerItem->rulerScaling() * duration - w;
+ return std::round(qMax(maxr, 0.0));
+}
+
+void TimelineGraphicsLayout::activate()
+{
+ m_layout->activate();
+}
+
+} // End namespace QmlDesigner.
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicslayout.h b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicslayout.h
index d5b7c4debc..d5b7c4debc 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicslayout.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicslayout.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
new file mode 100644
index 0000000000..99cc486710
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
@@ -0,0 +1,720 @@
+/****************************************************************************
+**
+** 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 "timelinegraphicsscene.h"
+
+#include "timelineactions.h"
+#include "timelinegraphicslayout.h"
+#include "timelineitem.h"
+#include "timelinemovableabstractitem.h"
+#include "timelinemovetool.h"
+#include "timelineplaceholder.h"
+#include "timelinepropertyitem.h"
+#include "timelinesectionitem.h"
+#include "timelinetoolbar.h"
+#include "timelineview.h"
+#include "timelinewidget.h"
+
+#include <designdocumentview.h>
+#include <exception.h>
+#include <rewritertransaction.h>
+#include <rewriterview.h>
+#include <viewmanager.h>
+#include <qmldesignerplugin.h>
+#include <qmlobjectnode.h>
+#include <qmltimelinekeyframegroup.h>
+
+#include <bindingproperty.h>
+
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <variantproperty.h>
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+#include <QComboBox>
+#include <QGraphicsLinearLayout>
+#include <QGraphicsProxyWidget>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsView>
+#include <QKeyEvent>
+
+#include <cmath>
+
+namespace QmlDesigner {
+
+QList<QmlTimelineKeyframeGroup> allTimelineFrames(const QmlTimeline &timeline)
+{
+ QList<QmlTimelineKeyframeGroup> returnList;
+
+ for (const ModelNode &childNode :
+ timeline.modelNode().defaultNodeListProperty().toModelNodeList()) {
+ if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(childNode))
+ returnList.append(QmlTimelineKeyframeGroup(childNode));
+ }
+
+ return returnList;
+}
+
+TimelineGraphicsScene::TimelineGraphicsScene(TimelineWidget *parent)
+ : QGraphicsScene(parent)
+ , m_parent(parent)
+ , m_layout(new TimelineGraphicsLayout(this))
+ , m_currentFrameIndicator(new TimelineFrameHandle)
+ , m_tools(this)
+{
+ addItem(m_layout);
+ addItem(m_currentFrameIndicator);
+
+ setSceneRect(m_layout->geometry());
+
+ connect(m_layout, &QGraphicsWidget::geometryChanged, this, [this]() {
+ auto rect = m_layout->geometry();
+
+ setSceneRect(rect);
+
+ if (auto *gview = graphicsView())
+ gview->setSceneRect(rect.adjusted(0, TimelineConstants::rulerHeight, 0, 0));
+
+ if (auto *rview = rulerView())
+ rview->setSceneRect(rect);
+
+ m_currentFrameIndicator->setHeight(m_layout->geometry().height());
+ });
+
+ auto moveFrameIndicator = [this](const QPointF &pos) {
+ m_currentFrameIndicator->commitPosition(pos);
+ };
+ connect(m_layout, &TimelineGraphicsLayout::rulerClicked, moveFrameIndicator);
+
+ auto changeScale = [this](int factor) {
+ timelineWidget()->changeScaleFactor(factor);
+ setRulerScaling(qreal(factor));
+ };
+ connect(m_layout, &TimelineGraphicsLayout::scaleFactorChanged, changeScale);
+}
+
+TimelineGraphicsScene::~TimelineGraphicsScene()
+{
+ QSignalBlocker block(this);
+ clearSelection();
+ qDeleteAll(items());
+}
+
+void TimelineGraphicsScene::onShow()
+{
+ if (timelineView()->isAttached()) {
+ auto timeline = currentTimeline();
+ if (timeline.isValid()) {
+ int cf = std::round(timeline.currentKeyframe());
+ setCurrentFrame(cf);
+ }
+
+ emit m_layout->scaleFactorChanged(0);
+ }
+}
+
+void TimelineGraphicsScene::setTimeline(const QmlTimeline &timeline)
+{
+ if (qFuzzyCompare(timeline.duration(), 0.0))
+ return;
+
+ m_layout->setTimeline(timeline);
+}
+
+void TimelineGraphicsScene::clearTimeline()
+{
+ m_layout->setTimeline(QmlTimeline());
+}
+
+void TimelineGraphicsScene::setWidth(int width)
+{
+ m_layout->setWidth(width);
+ invalidateScrollbar();
+}
+
+void TimelineGraphicsScene::invalidateLayout()
+{
+ m_layout->invalidate();
+}
+
+void TimelineGraphicsScene::setCurrenFrame(const QmlTimeline &timeline, qreal frame)
+{
+ if (timeline.isValid())
+ m_currentFrameIndicator->setPosition(frame);
+ else
+ m_currentFrameIndicator->setPosition(0);
+
+ invalidateCurrentValues();
+}
+
+void TimelineGraphicsScene::setCurrentFrame(int frame)
+{
+ QmlTimeline timeline(timelineModelNode());
+
+ if (timeline.isValid()) {
+ timeline.modelNode().setAuxiliaryData("currentFrame@NodeInstance", frame);
+ m_currentFrameIndicator->setPosition(frame + timeline.startKeyframe());
+ } else {
+ m_currentFrameIndicator->setPosition(0);
+ }
+
+ invalidateCurrentValues();
+
+ emitStatusBarFrameMessageChanged(frame);
+}
+
+void TimelineGraphicsScene::setStartFrame(int frame)
+{
+ QmlTimeline timeline(timelineModelNode());
+
+ if (timeline.isValid())
+ timeline.modelNode().variantProperty("startFrame").setValue(frame);
+}
+
+void TimelineGraphicsScene::setEndFrame(int frame)
+{
+ QmlTimeline timeline(timelineModelNode());
+
+ if (timeline.isValid())
+ timeline.modelNode().variantProperty("endFrame").setValue(frame);
+}
+
+qreal TimelineGraphicsScene::rulerScaling() const
+{
+ return m_layout->rulerScaling();
+}
+
+int TimelineGraphicsScene::rulerWidth() const
+{
+ return m_layout->rulerWidth();
+}
+
+qreal TimelineGraphicsScene::rulerDuration() const
+{
+ return m_layout->rulerDuration();
+}
+
+qreal TimelineGraphicsScene::startFrame() const
+{
+ return m_layout->startFrame();
+}
+
+qreal TimelineGraphicsScene::endFrame() const
+{
+ return m_layout->endFrame();
+}
+
+qreal TimelineGraphicsScene::mapToScene(qreal x) const
+{
+ return TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
+ + (x - startFrame()) * rulerScaling() - scrollOffset();
+}
+
+qreal TimelineGraphicsScene::mapFromScene(qreal x) const
+{
+ auto xPosOffset = (x - TimelineConstants::sectionWidth - TimelineConstants::timelineLeftOffset)
+ + scrollOffset();
+
+ return xPosOffset / rulerScaling() + startFrame();
+}
+
+qreal TimelineGraphicsScene::currentFramePosition() const
+{
+ return currentTimeline().currentKeyframe();
+}
+
+QVector<qreal> TimelineGraphicsScene::keyframePositions() const
+{
+ QVector<qreal> positions;
+ for (const auto &frames : allTimelineFrames(currentTimeline()))
+ positions.append(keyframePositions(frames));
+ return positions;
+}
+
+QVector<qreal> TimelineGraphicsScene::keyframePositions(const QmlTimelineKeyframeGroup &frames) const
+{
+ const QList<ModelNode> keyframes = frames.keyframePositions();
+ QVector<qreal> positions;
+ for (const ModelNode &modelNode : keyframes)
+ positions.append(modelNode.variantProperty("frame").value().toReal());
+ return positions;
+}
+
+void TimelineGraphicsScene::setRulerScaling(int scaleFactor)
+{
+ const qreal oldOffset = scrollOffset();
+ const qreal oldScaling = m_layout->rulerScaling();
+ const qreal oldPosition = mapToScene(currentFramePosition());
+ m_layout->setRulerScaleFactor(scaleFactor);
+
+ const qreal newScaling = m_layout->rulerScaling();
+ const qreal newPosition = mapToScene(currentFramePosition());
+
+ const qreal newOffset = oldOffset + (newPosition - oldPosition);
+
+ if (std::isinf(oldScaling) || std::isinf(newScaling))
+ setScrollOffset(0);
+ else {
+ setScrollOffset(std::round(newOffset));
+
+ const qreal start = mapToScene(startFrame());
+ const qreal head = TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset;
+
+ if (start - head > 0)
+ setScrollOffset(0);
+ }
+
+ invalidateSections();
+ QmlTimeline timeline(timelineModelNode());
+
+ if (timeline.isValid())
+ setCurrenFrame(timeline,
+ timeline.modelNode().auxiliaryData("currentFrame@NodeInstance").toReal());
+
+ invalidateScrollbar();
+ update();
+}
+
+void TimelineGraphicsScene::commitCurrentFrame(qreal frame)
+{
+ QmlTimeline timeline(timelineModelNode());
+
+ if (timeline.isValid()) {
+ timeline.modelNode().setAuxiliaryData("currentFrame@NodeInstance", qRound(frame));
+ setCurrenFrame(timeline, qRound(frame));
+ invalidateCurrentValues();
+ }
+ emitStatusBarFrameMessageChanged(int(frame));
+}
+
+QList<TimelineKeyframeItem *> TimelineGraphicsScene::selectedKeyframes() const
+{
+ return m_selectedKeyframes;
+}
+
+bool TimelineGraphicsScene::hasSelection() const
+{
+ return !m_selectedKeyframes.empty();
+}
+
+bool TimelineGraphicsScene::isCurrent(TimelineKeyframeItem *keyframe) const
+{
+ if (m_selectedKeyframes.empty())
+ return false;
+
+ return m_selectedKeyframes.back() == keyframe;
+}
+
+bool TimelineGraphicsScene::isKeyframeSelected(TimelineKeyframeItem *keyframe) const
+{
+ return m_selectedKeyframes.contains(keyframe);
+}
+
+bool TimelineGraphicsScene::multipleKeyframesSelected() const
+{
+ return m_selectedKeyframes.count() > 1;
+}
+
+void TimelineGraphicsScene::invalidateSectionForTarget(const ModelNode &target)
+{
+ if (!target.isValid())
+ return;
+
+ bool found = false;
+ for (auto child : m_layout->childItems())
+ TimelineSectionItem::updateDataForTarget(child, target, &found);
+
+ if (!found)
+ invalidateScene();
+
+ clearSelection();
+ invalidateLayout();
+}
+
+void TimelineGraphicsScene::invalidateKeyframesForTarget(const ModelNode &target)
+{
+ for (auto child : m_layout->childItems())
+ TimelineSectionItem::updateFramesForTarget(child, target);
+}
+
+void TimelineGraphicsScene::invalidateScene()
+{
+ ModelNode node = timelineView()->modelNodeForId(
+ timelineWidget()->toolBar()->currentTimelineId());
+ setTimeline(QmlTimeline(node));
+ invalidateScrollbar();
+}
+
+void TimelineGraphicsScene::invalidateScrollbar()
+{
+ double max = m_layout->maximumScrollValue();
+ timelineWidget()->setupScrollbar(0, max, scrollOffset());
+ if (scrollOffset() > max)
+ setScrollOffset(max);
+}
+
+void TimelineGraphicsScene::invalidateCurrentValues()
+{
+ for (auto item : items())
+ TimelinePropertyItem::updateTextEdit(item);
+}
+
+void TimelineGraphicsScene::invalidateRecordButtonsStatus()
+{
+ for (auto item : items())
+ TimelinePropertyItem::updateRecordButtonStatus(item);
+}
+
+int TimelineGraphicsScene::scrollOffset() const
+{
+ return m_scrollOffset;
+}
+
+void TimelineGraphicsScene::setScrollOffset(int offset)
+{
+ m_scrollOffset = offset;
+ emitScrollOffsetChanged();
+ update();
+}
+
+QGraphicsView *TimelineGraphicsScene::graphicsView() const
+{
+ for (auto *v : views())
+ if (v->objectName() == "SceneView")
+ return v;
+
+ return nullptr;
+}
+
+QGraphicsView *TimelineGraphicsScene::rulerView() const
+{
+ for (auto *v : views())
+ if (v->objectName() == "RulerView")
+ return v;
+
+ return nullptr;
+}
+
+QmlTimeline TimelineGraphicsScene::currentTimeline() const
+{
+ return QmlTimeline(timelineModelNode());
+}
+
+QRectF TimelineGraphicsScene::selectionBounds() const
+{
+ QRectF bbox;
+
+ for (auto *frame : m_selectedKeyframes)
+ bbox = bbox.united(frame->rect());
+
+ return bbox;
+}
+
+void TimelineGraphicsScene::selectKeyframes(const SelectionMode &mode,
+ const QList<TimelineKeyframeItem *> &items)
+{
+ if (mode == SelectionMode::Remove || mode == SelectionMode::Toggle) {
+ for (auto *item : items) {
+ if (auto *keyframe = TimelineMovableAbstractItem::asTimelineKeyframeItem(item)) {
+ if (m_selectedKeyframes.contains(keyframe)) {
+ keyframe->setHighlighted(false);
+ m_selectedKeyframes.removeAll(keyframe);
+
+ } else if (mode == SelectionMode::Toggle) {
+ if (!m_selectedKeyframes.contains(keyframe)) {
+ keyframe->setHighlighted(true);
+ m_selectedKeyframes << keyframe;
+ }
+ }
+ }
+ }
+
+ } else {
+ if (mode == SelectionMode::New)
+ clearSelection();
+
+ for (auto item : items) {
+ if (auto *keyframe = TimelineMovableAbstractItem::asTimelineKeyframeItem(item)) {
+ if (!m_selectedKeyframes.contains(keyframe)) {
+ keyframe->setHighlighted(true);
+ m_selectedKeyframes.append(keyframe);
+ }
+ }
+ }
+ }
+ emit selectionChanged();
+}
+
+void TimelineGraphicsScene::clearSelection()
+{
+ for (auto *keyframe : m_selectedKeyframes)
+ if (keyframe)
+ keyframe->setHighlighted(false);
+
+ m_selectedKeyframes.clear();
+}
+
+QList<QGraphicsItem *> TimelineGraphicsScene::itemsAt(const QPointF &pos)
+{
+ QTransform transform;
+
+ if (auto *gview = graphicsView())
+ transform = gview->transform();
+
+ return items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder, transform);
+}
+
+void TimelineGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
+ m_tools.mousePressEvent(topItem, event);
+ QGraphicsScene::mousePressEvent(event);
+}
+
+void TimelineGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
+ m_tools.mouseMoveEvent(topItem, event);
+ QGraphicsScene::mouseMoveEvent(event);
+}
+
+void TimelineGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
+ /* The tool has handle the event last. */
+ QGraphicsScene::mouseReleaseEvent(event);
+ m_tools.mouseReleaseEvent(topItem, event);
+}
+
+void TimelineGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
+ m_tools.mouseDoubleClickEvent(topItem, event);
+ QGraphicsScene::mouseDoubleClickEvent(event);
+}
+
+void TimelineGraphicsScene::keyPressEvent(QKeyEvent *keyEvent)
+{
+ if (qgraphicsitem_cast<QGraphicsProxyWidget *>(focusItem())) {
+ keyEvent->ignore();
+ QGraphicsScene::keyPressEvent(keyEvent);
+ return;
+ }
+
+ if (keyEvent->modifiers().testFlag(Qt::ControlModifier)) {
+ switch (keyEvent->key()) {
+ case Qt::Key_C:
+ copySelectedKeyframes();
+ break;
+
+ case Qt::Key_V:
+ pasteSelectedKeyframes();
+ break;
+
+ default:
+ QGraphicsScene::keyPressEvent(keyEvent);
+ break;
+ }
+ } else {
+ switch (keyEvent->key()) {
+ case Qt::Key_Left:
+ emit scroll(TimelineUtils::Side::Left);
+ keyEvent->accept();
+ break;
+
+ case Qt::Key_Right:
+ emit scroll(TimelineUtils::Side::Right);
+ keyEvent->accept();
+ break;
+
+ default:
+ QGraphicsScene::keyPressEvent(keyEvent);
+ break;
+ }
+ }
+}
+
+void TimelineGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
+{
+ if (qgraphicsitem_cast<QGraphicsProxyWidget *>(focusItem())) {
+ keyEvent->ignore();
+ QGraphicsScene::keyReleaseEvent(keyEvent);
+ return;
+ }
+
+ switch (keyEvent->key()) {
+ case Qt::Key_Delete:
+ handleKeyframeDeletion();
+ break;
+
+ default:
+ break;
+ }
+
+ QGraphicsScene::keyReleaseEvent(keyEvent);
+}
+
+void TimelineGraphicsScene::invalidateSections()
+{
+ for (auto child : m_layout->childItems())
+ TimelineSectionItem::updateData(child);
+
+ clearSelection();
+ invalidateLayout();
+}
+
+TimelineView *TimelineGraphicsScene::timelineView() const
+{
+ return m_parent->timelineView();
+}
+
+TimelineWidget *TimelineGraphicsScene::timelineWidget() const
+{
+ return m_parent;
+}
+
+TimelineToolBar *TimelineGraphicsScene::toolBar() const
+{
+ return timelineWidget()->toolBar();
+}
+
+ModelNode TimelineGraphicsScene::timelineModelNode() const
+{
+ if (timelineView()->isAttached()) {
+ const QString timelineId = timelineWidget()->toolBar()->currentTimelineId();
+ return timelineView()->modelNodeForId(timelineId);
+ }
+
+ return ModelNode();
+}
+
+void TimelineGraphicsScene::handleKeyframeDeletion()
+{
+ QList<ModelNode> nodesToBeDeleted;
+ for (auto keyframe : m_selectedKeyframes) {
+ nodesToBeDeleted.append(keyframe->frameNode());
+ }
+ deleteKeyframes(nodesToBeDeleted);
+}
+
+void TimelineGraphicsScene::deleteAllKeyframesForTarget(const ModelNode &targetNode)
+{
+ TimelineActions::deleteAllKeyframesForTarget(targetNode, currentTimeline());
+}
+
+void TimelineGraphicsScene::insertAllKeyframesForTarget(const ModelNode &targetNode)
+{
+ TimelineActions::insertAllKeyframesForTarget(targetNode, currentTimeline());
+}
+
+void TimelineGraphicsScene::copyAllKeyframesForTarget(const ModelNode &targetNode)
+{
+ TimelineActions::copyAllKeyframesForTarget(targetNode, currentTimeline());
+}
+
+void TimelineGraphicsScene::pasteKeyframesToTarget(const ModelNode &targetNode)
+{
+ TimelineActions::pasteKeyframesToTarget(targetNode, currentTimeline());
+}
+
+void TimelineGraphicsScene::copySelectedKeyframes()
+{
+ TimelineActions::copyKeyframes(
+ Utils::transform(m_selectedKeyframes, &TimelineKeyframeItem::frameNode));
+}
+
+void TimelineGraphicsScene::pasteSelectedKeyframes()
+{
+ TimelineActions::pasteKeyframes(timelineView(), currentTimeline());
+}
+
+void TimelineGraphicsScene::handleKeyframeInsertion(const ModelNode &target,
+ const PropertyName &propertyName)
+{
+ timelineView()->insertKeyframe(target, propertyName);
+}
+
+void TimelineGraphicsScene::deleteKeyframeGroup(const ModelNode &group)
+{
+ if (!QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(group))
+ return;
+
+ timelineView()->executeInTransaction("TimelineGraphicsScene::handleKeyframeGroupDeletion", [group](){
+ ModelNode nonConst = group;
+ nonConst.destroy();
+ });
+
+}
+
+void TimelineGraphicsScene::deleteKeyframes(const QList<ModelNode> &frames)
+{
+ timelineView()->executeInTransaction("TimelineGraphicsScene::handleKeyframeDeletion", [frames](){
+ for (auto keyframe : frames) {
+ if (keyframe.isValid()) {
+ ModelNode frame = keyframe;
+ ModelNode parent = frame.parentProperty().parentModelNode();
+ keyframe.destroy();
+ if (parent.isValid() && parent.defaultNodeListProperty().isEmpty())
+ parent.destroy();
+ }
+ }
+ });
+}
+
+void TimelineGraphicsScene::activateLayout()
+{
+ m_layout->activate();
+}
+
+void TimelineGraphicsScene::emitScrollOffsetChanged()
+{
+ for (QGraphicsItem *item : items())
+ TimelineMovableAbstractItem::emitScrollOffsetChanged(item);
+}
+
+void TimelineGraphicsScene::emitStatusBarFrameMessageChanged(int frame)
+{
+ emit statusBarMessageChanged(
+ QString(TimelineConstants::timelineStatusBarFrameNumber).arg(frame));
+}
+
+bool TimelineGraphicsScene::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::ShortcutOverride:
+ if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Delete) {
+ QGraphicsScene::keyPressEvent(static_cast<QKeyEvent *>(event));
+ event->accept();
+ return true;
+ }
+ Q_FALLTHROUGH();
+ default:
+ return QGraphicsScene::event(event);
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicsscene.h b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h
index b8f93595c4..b8f93595c4 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicsscene.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineicons.h b/src/plugins/qmldesigner/components/timelineeditor/timelineicons.h
index 641d4e77b6..641d4e77b6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineicons.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineicons.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineitem.cpp
index ebe3644e4e..ebe3644e4e 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineitem.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineitem.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineitem.h b/src/plugins/qmldesigner/components/timelineeditor/timelineitem.h
index 87fb9e3ec8..87fb9e3ec8 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineitem.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineitem.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovableabstractitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp
index 4db4567fd6..4db4567fd6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovableabstractitem.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovableabstractitem.h b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h
index 4bc11675c2..4bc11675c2 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovableabstractitem.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp
new file mode 100644
index 0000000000..0384d7c0a3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "timelinemovetool.h"
+
+#include "timelinegraphicsscene.h"
+#include "timelinemovableabstractitem.h"
+#include "timelinepropertyitem.h"
+#include "timelineview.h"
+
+#include <exception.h>
+
+#include <QGraphicsScene>
+#include <QGraphicsSceneMouseEvent>
+
+#include <cmath>
+
+namespace QmlDesigner {
+
+static QPointF mapPointToItem(TimelineMovableAbstractItem *item, const QPointF &pos)
+{
+ if (auto parent = item->parentItem())
+ return parent->mapFromScene(pos);
+ return pos;
+}
+
+QPointF mapToItem(TimelineMovableAbstractItem *item, const QPointF &pos)
+{
+ if (auto parent = item->parentItem())
+ return parent->mapFromScene(pos);
+ return pos;
+}
+
+QPointF mapToItem(TimelineMovableAbstractItem *item, QGraphicsSceneMouseEvent *event)
+{
+ if (auto parent = item->parentItem())
+ return parent->mapFromScene(event->scenePos());
+ return event->scenePos();
+}
+
+TimelineMoveTool::TimelineMoveTool(TimelineGraphicsScene *scene, TimelineToolDelegate *delegate)
+ : TimelineAbstractTool(scene, delegate)
+{}
+
+void TimelineMoveTool::mousePressEvent(TimelineMovableAbstractItem *item,
+ QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(item);
+ Q_UNUSED(event);
+}
+
+void TimelineMoveTool::mouseMoveEvent(TimelineMovableAbstractItem *item,
+ QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(item);
+
+ if (!currentItem())
+ return;
+
+ if (auto *current = currentItem()->asTimelineKeyframeItem()) {
+ const qreal sourceFrame = qRound(current->mapFromSceneToFrame(current->rect().center().x()));
+ const qreal targetFrame = qRound(current->mapFromSceneToFrame(event->scenePos().x()));
+ qreal deltaFrame = targetFrame - sourceFrame;
+
+ const qreal minFrame = scene()->startFrame();
+ const qreal maxFrame = scene()->endFrame();
+
+ auto bbox = scene()->selectionBounds().united(current->rect());
+
+ double firstFrame = std::round(current->mapFromSceneToFrame(bbox.center().x()));
+ double lastFrame = std::round(current->mapFromSceneToFrame(bbox.center().x()));
+
+ if ((lastFrame + deltaFrame) > maxFrame)
+ deltaFrame = maxFrame - lastFrame;
+
+ if ((firstFrame + deltaFrame) <= minFrame)
+ deltaFrame = minFrame - firstFrame;
+
+ current->setPosition(sourceFrame + deltaFrame);
+
+ for (auto *keyframe : scene()->selectedKeyframes()) {
+ if (keyframe != current) {
+ qreal pos = std::round(current->mapFromSceneToFrame(keyframe->rect().center().x()));
+ keyframe->setPosition(pos + deltaFrame);
+ }
+ }
+
+ } else {
+ currentItem()->itemMoved(mapPointToItem(currentItem(), startPosition()),
+ mapToItem(currentItem(), event));
+ }
+}
+
+void TimelineMoveTool::mouseReleaseEvent(TimelineMovableAbstractItem *item,
+ QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(item);
+ Q_UNUSED(event);
+
+ if (auto *current = currentItem()) {
+ if (current->asTimelineFrameHandle()) {
+ double mousePos = event->pos().x();
+ double start = current->mapFromFrameToScene(scene()->startFrame());
+ double end = current->mapFromFrameToScene(scene()->endFrame());
+
+ if (mousePos < start) {
+ scene()->setCurrentFrame(scene()->startFrame());
+ scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(scene()->startFrame()));
+ return;
+ } else if (mousePos > end) {
+ scene()->setCurrentFrame(scene()->endFrame());
+ scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(scene()->endFrame()));
+ return;
+ }
+ }
+
+ scene()->timelineView()->executeInTransaction("TimelineMoveTool::mouseReleaseEvent", [this, current](){
+ current->commitPosition(mapToItem(current, current->rect().center()));
+
+ if (current->asTimelineKeyframeItem()) {
+ double frame = std::round(
+ current->mapFromSceneToFrame(current->rect().center().x()));
+
+ scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(frame));
+
+ for (auto keyframe : scene()->selectedKeyframes())
+ if (keyframe != current)
+ keyframe->commitPosition(mapToItem(current, keyframe->rect().center()));
+ }
+ });
+ }
+}
+
+void TimelineMoveTool::mouseDoubleClickEvent(TimelineMovableAbstractItem *item,
+ QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(item);
+ Q_UNUSED(event);
+}
+
+void TimelineMoveTool::keyPressEvent(QKeyEvent *keyEvent)
+{
+ Q_UNUSED(keyEvent);
+}
+
+void TimelineMoveTool::keyReleaseEvent(QKeyEvent *keyEvent)
+{
+ Q_UNUSED(keyEvent);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovetool.h b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h
index 55b9a39417..55b9a39417 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovetool.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineplaceholder.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.cpp
index 7e7cb69fc9..7e7cb69fc9 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineplaceholder.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineplaceholder.h b/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.h
index 14d6d8a2fc..14d6d8a2fc 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineplaceholder.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineplaceholder.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
new file mode 100644
index 0000000000..beeca23183
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
@@ -0,0 +1,641 @@
+/****************************************************************************
+**
+** 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 "timelinepropertyitem.h"
+
+#include "abstractview.h"
+#include "easingcurvedialog.h"
+#include "setframevaluedialog.h"
+#include "timelineconstants.h"
+#include "timelinegraphicsscene.h"
+#include "timelineicons.h"
+#include "timelinetoolbar.h"
+#include "timelinetoolbutton.h"
+
+#include <rewritertransaction.h>
+#include <rewritingexception.h>
+#include <theme.h>
+#include <variantproperty.h>
+#include <qmlobjectnode.h>
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
+
+#include <utils/algorithm.h>
+#include <utils/fileutils.h>
+
+#include <coreplugin/icore.h>
+
+#include <QCursor>
+#include <QGraphicsProxyWidget>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsView>
+#include <QLineEdit>
+#include <QMenu>
+#include <QPainter>
+
+#include <algorithm>
+
+namespace QmlDesigner {
+
+static bool s_blockUpdates = false;
+
+static qreal findNext(const QVector<qreal> &vector, qreal current)
+{
+ for (qreal n : vector)
+ if (n > current)
+ return n;
+ return current;
+}
+
+static qreal findPrev(const QVector<qreal> &vector, qreal current)
+{
+ for (qreal n : vector)
+ if (n < current)
+ return n;
+ return current;
+}
+
+static QVector<qreal> getPositions(const QmlTimelineKeyframeGroup &frames)
+{
+ const QList<ModelNode> keyframes = frames.keyframePositions();
+ QVector<qreal> positions;
+ for (const ModelNode &modelNode : keyframes)
+ positions.append(modelNode.variantProperty("frame").value().toReal());
+ return positions;
+}
+
+static ModelNode getModelNodeForFrame(const QmlTimelineKeyframeGroup &frames, qreal frame)
+{
+ if (frames.isValid()) {
+ const QList<ModelNode> keyframes = frames.keyframePositions();
+ for (const ModelNode &modelNode : keyframes)
+ if (qFuzzyCompare(modelNode.variantProperty("frame").value().toReal(), frame))
+ return modelNode;
+ }
+
+ return {};
+}
+
+static void setEasingCurve(TimelineGraphicsScene *scene, const QList<ModelNode> &keys)
+{
+ QTC_ASSERT(scene, return );
+ EasingCurveDialog::runDialog(keys);
+}
+
+static void editValue(const ModelNode &frame, const QString &propertyName)
+{
+ const QVariant value = frame.variantProperty("value").value();
+ auto dialog = new SetFrameValueDialog(Core::ICore::dialogParent());
+
+ dialog->lineEdit()->setText(value.toString());
+ dialog->setPropertName(propertyName);
+
+ QObject::connect(dialog, &SetFrameValueDialog::rejected, [dialog]() { dialog->deleteLater(); });
+
+ QObject::connect(dialog, &SetFrameValueDialog::accepted, [dialog, frame, value]() {
+ dialog->deleteLater();
+ int userType = value.userType();
+ const QVariant result = dialog->lineEdit()->text();
+
+ if (result.canConvert(userType)) {
+ QVariant newValue = result;
+ newValue.convert(userType);
+ // canConvert gives true in case if the result is a double but the usertype was interger
+ // try to fix that with a workaround to convert it to double if convertion resulted in isNull
+ if (newValue.isNull()) {
+ newValue = result;
+ newValue.convert(QMetaType::Double);
+ }
+ frame.variantProperty("value").setValue(result);
+ }
+ });
+
+ dialog->show();
+}
+
+TimelinePropertyItem *TimelinePropertyItem::create(const QmlTimelineKeyframeGroup &frames,
+ TimelineSectionItem *parent)
+{
+ ModelNode modelnode = frames.target();
+
+ bool isRecording = false;
+
+ if (frames.isValid())
+ isRecording = frames.isRecording();
+
+ auto item = new TimelinePropertyItem(parent);
+
+ auto sectionItem = new QGraphicsWidget(item);
+
+ sectionItem->setGeometry(0,
+ 0,
+ TimelineConstants::sectionWidth,
+ TimelineConstants::sectionHeight);
+
+ sectionItem->setZValue(10);
+ sectionItem->setCursor(Qt::ArrowCursor);
+
+ item->m_frames = frames;
+ item->setToolTip(item->propertyName());
+ item->resize(parent->size());
+ item->setupKeyframes();
+
+ TimelineToolButton *buttonPrev
+ = new TimelineToolButton(new QAction(TimelineIcons::PREVIOUS_KEYFRAME.icon(),
+ tr("Previous Frame")),
+ sectionItem);
+ buttonPrev->setToolTip("Jump to previous frame.");
+
+ TimelineToolButton *buttonNext
+ = new TimelineToolButton(new QAction(TimelineIcons::NEXT_KEYFRAME.icon(), tr("Next Frame")),
+ sectionItem);
+ buttonNext->setToolTip("Jump to next frame.");
+
+ connect(buttonPrev, &TimelineToolButton::clicked, item, [item]() {
+ if (item->m_frames.isValid()) {
+ QVector<qreal> positions = getPositions(item->m_frames);
+ std::sort(positions.begin(), positions.end(), std::greater<qreal>());
+ const qreal prev = findPrev(positions, item->currentFrame());
+ item->timelineScene()->commitCurrentFrame(prev);
+ }
+ });
+
+ connect(buttonNext, &TimelineToolButton::clicked, item, [item]() {
+ if (item->m_frames.isValid()) {
+ QVector<qreal> positions = getPositions(item->m_frames);
+ std::sort(positions.begin(), positions.end(), std::less<qreal>());
+ const qreal next = findNext(positions, item->currentFrame());
+ item->timelineScene()->commitCurrentFrame(next);
+ }
+ });
+
+ QIcon autoKeyIcon = TimelineUtils::mergeIcons(TimelineIcons::GLOBAL_RECORD_KEYFRAMES,
+ TimelineIcons::GLOBAL_RECORD_KEYFRAMES_OFF);
+ auto recact = new QAction(autoKeyIcon, tr("Auto Record"));
+ recact->setCheckable(true);
+ recact->setChecked(isRecording);
+
+ auto toggleRecord = [frames](bool check) { frames.toogleRecording(check); };
+ connect(recact, &QAction::toggled, toggleRecord);
+ item->m_recording = new TimelineToolButton(recact, sectionItem);
+ item->m_recording->setToolTip("Per property recording");
+
+ const int buttonsY = (TimelineConstants::sectionHeight - 1 - TimelineConstants::toolButtonSize)
+ / 2;
+ buttonPrev->setPos(2, buttonsY);
+ buttonNext->setPos(buttonPrev->size().width() + TimelineConstants::toolButtonSize + 4, buttonsY);
+ item->m_recording->setPos(buttonNext->geometry().right() + 2, buttonsY);
+
+ QRectF hideToolTipDummy(buttonPrev->geometry().topRight(), buttonNext->geometry().bottomLeft());
+
+ auto *dummy = new QGraphicsRectItem(sectionItem);
+ dummy->setPen(Qt::NoPen);
+ dummy->setRect(hideToolTipDummy);
+ dummy->setToolTip("Frame indicator");
+
+ if (!item->m_frames.isValid())
+ return item;
+
+ QmlObjectNode objectNode(modelnode);
+ if (!objectNode.isValid())
+ return item;
+
+ auto nameOfType = objectNode.modelNode().metaInfo().propertyTypeName(
+ item->m_frames.propertyName());
+ item->m_control = createTimelineControl(nameOfType);
+ if (item->m_control) {
+ item->m_control->setSize((TimelineConstants::sectionWidth / 2.6) - 10,
+ item->size().height() - 2 + 1);
+ item->m_control->connect(item);
+ QGraphicsProxyWidget *proxy = item->timelineScene()->addWidget(item->m_control->widget());
+ proxy->setParentItem(sectionItem);
+ proxy->setPos(qreal(TimelineConstants::sectionWidth) * 2.0 / 3, 0);
+ item->updateTextEdit();
+ }
+
+ updateRecordButtonStatus(item);
+
+ return item;
+}
+
+int TimelinePropertyItem::type() const
+{
+ return Type;
+}
+
+void TimelinePropertyItem::updateData()
+{
+ for (auto child : childItems())
+ delete qgraphicsitem_cast<TimelineMovableAbstractItem *>(child);
+
+ setupKeyframes();
+ updateTextEdit();
+}
+
+void TimelinePropertyItem::updateFrames()
+{
+ for (auto child : (childItems())) {
+ if (auto frameItem = qgraphicsitem_cast<TimelineMovableAbstractItem *>(child))
+ static_cast<TimelineKeyframeItem *>(frameItem)->updateFrame();
+ }
+}
+
+bool TimelinePropertyItem::isSelected() const
+{
+ if (m_frames.isValid() && m_frames.target().isValid())
+ return m_frames.target().isSelected();
+
+ return false;
+}
+
+QString convertVariant(const QVariant &variant)
+{
+ if (variant.userType() == QMetaType::QColor)
+ return variant.toString();
+
+ return QString::number(variant.toFloat(), 'f', 2);
+}
+
+void TimelinePropertyItem::updateTextEdit()
+{
+ if (!m_frames.isValid())
+ return;
+
+ QmlObjectNode objectNode(m_frames.target());
+ if (objectNode.isValid() && m_control)
+ m_control->setControlValue(objectNode.instanceValue(m_frames.propertyName()));
+}
+
+void TimelinePropertyItem::updateTextEdit(QGraphicsItem *item)
+{
+ if (auto timelinePropertyItem = qgraphicsitem_cast<TimelinePropertyItem *>(item))
+ timelinePropertyItem->updateTextEdit();
+}
+
+void TimelinePropertyItem::updateRecordButtonStatus(QGraphicsItem *item)
+{
+ if (auto timelinePropertyItem = qgraphicsitem_cast<TimelinePropertyItem *>(item)) {
+ auto frames = timelinePropertyItem->m_frames;
+ if (frames.isValid()) {
+ timelinePropertyItem->m_recording->setChecked(frames.isRecording());
+ if (frames.timeline().isValid())
+ timelinePropertyItem->m_recording->setDisabled(frames.timeline().isRecording());
+ }
+ }
+}
+
+QmlTimelineKeyframeGroup TimelinePropertyItem::frames() const
+{
+ return m_frames;
+}
+
+QString TimelinePropertyItem::propertyName() const
+{
+ if (m_frames.isValid())
+ return QString::fromUtf8(m_frames.propertyName());
+ return QString();
+}
+
+void TimelinePropertyItem::changePropertyValue(const QVariant &value)
+{
+ Q_ASSERT(m_frames.isValid());
+
+ auto timeline = timelineScene()->currentTimeline();
+
+ if (timelineScene()->toolBar()->recording() || m_recording->isChecked()) {
+ QmlTimelineKeyframeGroup frames = m_frames;
+ auto deferredFunc = [frames, value, timeline]() {
+ auto constFrames = frames;
+ qreal frame = timeline.modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
+ try {
+ constFrames.setValue(value, frame);
+ } catch (const RewritingException &e) {
+ e.showException();
+ }
+ };
+
+ // QmlTimelineKeyframeGroup::setValue might create a new keyframe.
+ // This might result in a temporal cleanup of the graphicsscene and
+ // therefore a deletion of this property item.
+ // Adding a keyframe to this already deleted item results in a crash.
+ QTimer::singleShot(0, deferredFunc);
+
+ } else {
+ QmlObjectNode objectNode(m_frames.target());
+ objectNode.setVariantProperty(m_frames.propertyName(), value);
+ }
+}
+
+static int devicePixelHeight(const QPixmap &pixmap)
+{
+ return pixmap.height() / pixmap.devicePixelRatioF();
+}
+
+void TimelinePropertyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ painter->save();
+
+ static const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker();
+ static const QColor textColor = Theme::getColor(Theme::PanelTextColorLight);
+ static const QColor backgroundColor = Theme::instance()
+ ->qmlDesignerBackgroundColorDarkAlternate();
+
+ static const QPixmap keyframe = TimelineIcons::KEYFRAME.pixmap();
+ static const QPixmap isKeyframe = TimelineIcons::IS_KEYFRAME.pixmap();
+
+ painter->fillRect(0, 0, TimelineConstants::sectionWidth, size().height(), backgroundColor);
+ painter->fillRect(TimelineConstants::textIndentationProperties - 4,
+ 0,
+ TimelineConstants::sectionWidth - TimelineConstants::textIndentationProperties
+ + 4,
+ size().height(),
+ backgroundColor.darker(110));
+
+ painter->setPen(penColor);
+
+ drawLine(painter,
+ TimelineConstants::sectionWidth - 1,
+ 0,
+ TimelineConstants::sectionWidth - 1,
+ size().height());
+
+ drawLine(painter,
+ TimelineConstants::textIndentationProperties - 4,
+ TimelineConstants::sectionHeight - 1,
+ size().width(),
+ TimelineConstants::sectionHeight - 1);
+
+ painter->setPen(textColor);
+
+ const QFontMetrics metrics(font());
+
+ const QString elidedText = metrics.elidedText(propertyName(),
+ Qt::ElideMiddle,
+ qreal(TimelineConstants::sectionWidth) * 2.0 / 3
+ - TimelineConstants::textIndentationProperties,
+ 0);
+
+ painter->drawText(TimelineConstants::textIndentationProperties, 12, elidedText);
+
+ const bool onKeyFrame = m_frames.isValid() && getPositions(m_frames).contains(currentFrame());
+ painter->drawPixmap(TimelineConstants::toolButtonSize + 3,
+ (TimelineConstants::sectionHeight - 1 - devicePixelHeight(isKeyframe)) / 2,
+ onKeyFrame ? isKeyframe : keyframe);
+ painter->restore();
+}
+
+void TimelinePropertyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+ if (event->pos().x() < TimelineConstants::toolButtonSize * 2 + 3
+ && event->pos().x() > TimelineConstants::toolButtonSize) {
+ QMenu mainMenu;
+
+ const ModelNode currentFrameNode = getModelNodeForFrame(m_frames, currentFrame());
+
+ QAction *insertAction = mainMenu.addAction(tr("Insert Keyframe"));
+ QObject::connect(insertAction, &QAction::triggered, [this]() {
+ timelineScene()->handleKeyframeInsertion(m_frames.target(), propertyName().toUtf8());
+ });
+
+ QAction *removeAction = mainMenu.addAction(tr("Delete Keyframe"));
+ QObject::connect(removeAction, &QAction::triggered, [this, currentFrameNode]() {
+ timelineScene()->deleteKeyframes({currentFrameNode});
+ });
+
+ QAction *editEasingAction = mainMenu.addAction(tr("Edit Easing Curve..."));
+ QObject::connect(editEasingAction, &QAction::triggered, [this, currentFrameNode]() {
+ setEasingCurve(timelineScene(), {currentFrameNode});
+ });
+
+ QAction *editValueAction = mainMenu.addAction(tr("Edit Value for Keyframe..."));
+ QObject::connect(editValueAction, &QAction::triggered, [this, currentFrameNode]() {
+ editValue(currentFrameNode, propertyName());
+ });
+
+ const bool hasKeyframe = currentFrameNode.isValid();
+
+ insertAction->setEnabled(!hasKeyframe);
+ removeAction->setEnabled(hasKeyframe);
+ editEasingAction->setEnabled(hasKeyframe);
+ editValueAction->setEnabled(hasKeyframe);
+
+ mainMenu.exec(event->screenPos());
+ event->accept();
+ } else if (event->pos().x() > TimelineConstants::toolButtonSize * 3 + 3
+ && event->pos().x() < TimelineConstants::sectionWidth) {
+ QMenu mainMenu;
+ QAction *deleteAction = mainMenu.addAction(tr("Remove Property"));
+
+ QObject::connect(deleteAction, &QAction::triggered, [this]() {
+ auto deleteKeyframeGroup = [this]() { timelineScene()->deleteKeyframeGroup(m_frames); };
+ QTimer::singleShot(0, deleteKeyframeGroup);
+ });
+
+ mainMenu.exec(event->screenPos());
+ event->accept();
+ }
+}
+
+TimelinePropertyItem::TimelinePropertyItem(TimelineSectionItem *parent)
+ : TimelineItem(parent)
+{
+ setPreferredHeight(TimelineConstants::sectionHeight);
+ setMinimumHeight(TimelineConstants::sectionHeight);
+ setMaximumHeight(TimelineConstants::sectionHeight);
+}
+
+void TimelinePropertyItem::setupKeyframes()
+{
+ for (const ModelNode &frame : m_frames.keyframePositions())
+ new TimelineKeyframeItem(this, frame);
+}
+
+qreal TimelinePropertyItem::currentFrame()
+{
+ QmlTimeline timeline = timelineScene()->currentTimeline();
+ if (timeline.isValid())
+ return timeline.currentKeyframe();
+ return 0;
+}
+
+TimelineKeyframeItem::TimelineKeyframeItem(TimelinePropertyItem *parent, const ModelNode &frame)
+ : TimelineMovableAbstractItem(parent)
+ , m_frame(frame)
+
+{
+ setPosition(frame.variantProperty("frame").value().toReal());
+ setCursor(Qt::ClosedHandCursor);
+}
+
+TimelineKeyframeItem::~TimelineKeyframeItem()
+{
+ timelineScene()->selectKeyframes(SelectionMode::Remove, {this});
+}
+
+void TimelineKeyframeItem::updateFrame()
+{
+ if (s_blockUpdates)
+ return;
+
+ QTC_ASSERT(m_frame.isValid(), return );
+ setPosition(m_frame.variantProperty("frame").value().toReal());
+}
+
+void TimelineKeyframeItem::setPosition(qreal position)
+{
+ int offset = (TimelineConstants::sectionHeight - TimelineConstants::keyFrameSize) / 2;
+ const qreal scenePostion = mapFromFrameToScene(position);
+
+ setRect(scenePostion - TimelineConstants::keyFrameSize / 2,
+ offset,
+ TimelineConstants::keyFrameSize,
+ TimelineConstants::keyFrameSize);
+}
+
+void TimelineKeyframeItem::setPositionInteractive(const QPointF &postion)
+{
+ qreal left = postion.x() - qreal(TimelineConstants::keyFrameSize) / qreal(2);
+ setRect(left, rect().y(), rect().width(), rect().height());
+}
+
+void TimelineKeyframeItem::commitPosition(const QPointF &point)
+{
+ setPositionInteractive(point);
+
+ const qreal frame = qRound(mapFromSceneToFrame(rect().center().x()));
+
+ setPosition(frame);
+
+ QTC_ASSERT(m_frame.isValid(), return );
+
+ blockUpdates();
+
+ m_frame.view()->executeInTransaction("TimelineKeyframeItem::commitPosition", [this, frame](){
+ m_frame.variantProperty("frame").setValue(frame);
+ });
+
+ enableUpdates();
+}
+
+TimelineKeyframeItem *TimelineKeyframeItem::asTimelineKeyframeItem()
+{
+ return this;
+}
+
+void TimelineKeyframeItem::blockUpdates()
+{
+ s_blockUpdates = true;
+}
+
+void TimelineKeyframeItem::enableUpdates()
+{
+ s_blockUpdates = false;
+}
+
+bool TimelineKeyframeItem::hasManualBezier() const
+{
+ return m_frame.isValid() && m_frame.hasProperty("easing.bezierCurve");
+}
+
+void TimelineKeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (rect().x() < TimelineConstants::sectionWidth - rect().width() / 2)
+ return;
+
+ painter->save();
+
+ Utils::Icon icon([this]() {
+ const bool itemIsSelected = propertyItem()->isSelected();
+ const bool manualBezier = hasManualBezier();
+
+ if (m_highlight && manualBezier) {
+ return TimelineIcons::KEYFRAME_MANUALBEZIER_SELECTED;
+ } else if (m_highlight) {
+ return TimelineIcons::KEYFRAME_LINEAR_SELECTED;
+ } else if (itemIsSelected && manualBezier) {
+ return TimelineIcons::KEYFRAME_MANUALBEZIER_ACTIVE;
+ } else if (itemIsSelected) {
+ return TimelineIcons::KEYFRAME_LINEAR_ACTIVE;
+ } else if (manualBezier) {
+ return TimelineIcons::KEYFRAME_MANUALBEZIER_INACTIVE;
+ }
+
+ return TimelineIcons::KEYFRAME_LINEAR_INACTIVE;
+ }());
+
+ painter->drawPixmap(rect().topLeft() - QPointF(0, 1), icon.pixmap());
+
+ painter->restore();
+}
+
+ModelNode TimelineKeyframeItem::frameNode() const
+{
+ return m_frame;
+}
+
+void TimelineKeyframeItem::setHighlighted(bool b)
+{
+ m_highlight = b;
+ update();
+}
+
+TimelinePropertyItem *TimelineKeyframeItem::propertyItem() const
+{
+ /* The parentItem is always a TimelinePropertyItem. See constructor */
+ return qgraphicsitem_cast<TimelinePropertyItem *>(parentItem());
+}
+
+void TimelineKeyframeItem::scrollOffsetChanged()
+{
+ updateFrame();
+}
+
+void TimelineKeyframeItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+ QMenu mainMenu;
+ QAction *removeAction = mainMenu.addAction(tr("Delete Keyframe"));
+ QObject::connect(removeAction, &QAction::triggered, [this]() {
+ timelineScene()->handleKeyframeDeletion();
+ });
+
+ QAction *editEasingAction = mainMenu.addAction(tr("Edit Easing Curve..."));
+ QObject::connect(editEasingAction, &QAction::triggered, [this]() {
+ const QList<ModelNode> keys = Utils::transform(timelineScene()->selectedKeyframes(),
+ &TimelineKeyframeItem::m_frame);
+
+ setEasingCurve(timelineScene(), keys);
+ });
+
+ QAction *editValueAction = mainMenu.addAction(tr("Edit Value for Keyframe..."));
+ QObject::connect(editValueAction, &QAction::triggered, [this]() {
+ editValue(m_frame, propertyItem()->propertyName());
+ });
+
+ mainMenu.exec(event->screenPos());
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinepropertyitem.h b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h
index 2b8c00c59b..2b8c00c59b 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinepropertyitem.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp
new file mode 100644
index 0000000000..7bd784a7dd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp
@@ -0,0 +1,1062 @@
+/****************************************************************************
+**
+** 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 "timelinesectionitem.h"
+
+#include "abstractview.h"
+#include "timelineactions.h"
+#include "timelineconstants.h"
+#include "timelinegraphicsscene.h"
+#include "timelineicons.h"
+#include "timelinepropertyitem.h"
+#include "timelinetoolbutton.h"
+#include "timelineutils.h"
+
+#include <qmltimeline.h>
+#include <qmltimelinekeyframegroup.h>
+
+#include <rewritingexception.h>
+
+#include <theme.h>
+
+#include <utils/qtcassert.h>
+
+#include <QAction>
+#include <QColorDialog>
+#include <QComboBox>
+#include <QGraphicsProxyWidget>
+#include <QGraphicsScene>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsView>
+#include <QHBoxLayout>
+#include <QMenu>
+#include <QPainter>
+#include <QToolBar>
+
+#include <QGraphicsView>
+
+#include <QDebug>
+
+#include <cmath>
+
+static int textOffset = 8;
+
+namespace QmlDesigner {
+
+class ClickDummy : public TimelineItem
+{
+public:
+ explicit ClickDummy(TimelineSectionItem *parent)
+ : TimelineItem(parent)
+ {
+ setGeometry(0, 0, TimelineConstants::sectionWidth, TimelineConstants::sectionHeight);
+
+ setZValue(10);
+ setCursor(Qt::ArrowCursor);
+ }
+
+protected:
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override
+ {
+ scene()->sendEvent(parentItem(), event);
+ }
+ void mousePressEvent(QGraphicsSceneMouseEvent *event) override
+ {
+ scene()->sendEvent(parentItem(), event);
+ }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
+ {
+ scene()->sendEvent(parentItem(), event);
+ }
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override
+ {
+ scene()->sendEvent(parentItem(), event);
+ }
+};
+
+TimelineSectionItem::TimelineSectionItem(TimelineItem *parent)
+ : TimelineItem(parent)
+{}
+
+TimelineSectionItem *TimelineSectionItem::create(const QmlTimeline &timeline,
+ const ModelNode &target,
+ TimelineItem *parent)
+{
+ auto item = new TimelineSectionItem(parent);
+
+ if (target.isValid())
+ item->setToolTip(target.id());
+
+ item->m_targetNode = target;
+ item->m_timeline = timeline;
+
+ item->createPropertyItems();
+
+ item->m_dummyItem = new ClickDummy(item);
+ item->m_dummyItem->update();
+
+ item->m_barItem = new TimelineBarItem(item);
+ item->invalidateBar();
+ item->invalidateHeight();
+
+ return item;
+}
+
+void TimelineSectionItem::invalidateBar()
+{
+ qreal min = m_timeline.minActualKeyframe(m_targetNode);
+ qreal max = m_timeline.maxActualKeyframe(m_targetNode);
+
+ const qreal sceneMin = m_barItem->mapFromFrameToScene(min);
+
+ QRectF barRect(sceneMin,
+ 0,
+ (max - min) * m_barItem->rulerScaling(),
+ TimelineConstants::sectionHeight - 1);
+
+ m_barItem->setRect(barRect);
+}
+
+int TimelineSectionItem::type() const
+{
+ return Type;
+}
+
+void TimelineSectionItem::updateData(QGraphicsItem *item)
+{
+ if (auto sectionItem = qgraphicsitem_cast<TimelineSectionItem *>(item))
+ sectionItem->updateData();
+}
+
+void TimelineSectionItem::updateDataForTarget(QGraphicsItem *item, const ModelNode &target, bool *b)
+{
+ if (!target.isValid())
+ return;
+
+ if (auto sectionItem = qgraphicsitem_cast<TimelineSectionItem *>(item)) {
+ if (sectionItem->m_targetNode == target) {
+ sectionItem->updateData();
+ if (b)
+ *b = true;
+ }
+ }
+}
+
+void TimelineSectionItem::updateFramesForTarget(QGraphicsItem *item, const ModelNode &target)
+{
+ if (auto sectionItem = qgraphicsitem_cast<TimelineSectionItem *>(item)) {
+ if (sectionItem->m_targetNode == target)
+ sectionItem->updateFrames();
+ }
+}
+
+void TimelineSectionItem::moveAllFrames(qreal offset)
+{
+ if (m_timeline.isValid())
+ m_timeline.moveAllKeyframes(m_targetNode, offset);
+}
+
+void TimelineSectionItem::scaleAllFrames(qreal scale)
+{
+ if (m_timeline.isValid())
+ m_timeline.scaleAllKeyframes(m_targetNode, scale);
+}
+
+qreal TimelineSectionItem::firstFrame()
+{
+ if (!m_timeline.isValid())
+ return 0;
+
+ return m_timeline.minActualKeyframe(m_targetNode);
+}
+
+AbstractView *TimelineSectionItem::view() const
+{
+ return m_timeline.view();
+}
+
+bool TimelineSectionItem::isSelected() const
+{
+ return m_targetNode.isValid() && m_targetNode.isSelected();
+}
+
+ModelNode TimelineSectionItem::targetNode() const
+{
+ return m_targetNode;
+}
+
+QVector<qreal> TimelineSectionItem::keyframePositions() const
+{
+ QVector<qreal> out;
+ for (auto frame : m_timeline.keyframeGroupsForTarget(m_targetNode))
+ out.append(timelineScene()->keyframePositions(frame));
+
+ return out;
+}
+
+QTransform rotatationTransform(qreal degrees)
+{
+ QTransform transform;
+ transform.rotate(degrees);
+
+ return transform;
+}
+
+QPixmap rotateby90(const QPixmap &pixmap)
+{
+ QImage sourceImage = pixmap.toImage();
+ QImage destImage(pixmap.height(), pixmap.width(), sourceImage.format());
+
+ for (int x = 0; x < pixmap.width(); x++)
+ for (int y = 0; y < pixmap.height(); y++)
+ destImage.setPixel(y, x, sourceImage.pixel(x, y));
+
+ QPixmap result = QPixmap::fromImage(destImage);
+
+ result.setDevicePixelRatio(pixmap.devicePixelRatio());
+
+ return result;
+}
+
+static int devicePixelHeight(const QPixmap &pixmap)
+{
+ return pixmap.height() / pixmap.devicePixelRatioF();
+}
+
+void TimelineSectionItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem * /*option*/,
+ QWidget *)
+{
+ if (m_targetNode.isValid()) {
+ painter->save();
+
+ const QColor textColor = Theme::getColor(Theme::PanelTextColorLight);
+ const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker();
+ QColor brushColor = Theme::getColor(Theme::BackgroundColorDark);
+
+ int fillOffset = 0;
+ if (isSelected()) {
+ brushColor = Theme::getColor(Theme::QmlDesigner_HighlightColor);
+ fillOffset = 1;
+ }
+
+ painter->fillRect(0,
+ 0,
+ TimelineConstants::sectionWidth,
+ TimelineConstants::sectionHeight - fillOffset,
+ brushColor);
+ painter->fillRect(TimelineConstants::sectionWidth,
+ 0,
+ size().width() - TimelineConstants::sectionWidth,
+ size().height(),
+ Theme::instance()->qmlDesignerBackgroundColorDarkAlternate());
+
+ painter->setPen(penColor);
+ drawLine(painter,
+ TimelineConstants::sectionWidth - 1,
+ 0,
+ TimelineConstants::sectionWidth - 1,
+ size().height() - 1);
+ drawLine(painter,
+ TimelineConstants::sectionWidth,
+ TimelineConstants::sectionHeight - 1,
+ size().width(),
+ TimelineConstants::sectionHeight - 1);
+
+ static const QPixmap arrow = Theme::getPixmap("down-arrow");
+
+ static const QPixmap arrow90 = rotateby90(arrow);
+
+ const QPixmap rotatedArrow = collapsed() ? arrow90 : arrow;
+
+ const int textOffset = QFontMetrics(font()).ascent()
+ + (TimelineConstants::sectionHeight - QFontMetrics(font()).height())
+ / 2;
+
+ painter->drawPixmap(collapsed() ? 6 : 4,
+ (TimelineConstants::sectionHeight - devicePixelHeight(rotatedArrow)) / 2,
+ rotatedArrow);
+
+ painter->setPen(textColor);
+
+ QFontMetrics fm(painter->font());
+ const QString elidedId = fm.elidedText(m_targetNode.id(),
+ Qt::ElideMiddle,
+ TimelineConstants::sectionWidth
+ - TimelineConstants::textIndentationSections);
+ painter->drawText(TimelineConstants::textIndentationSections, textOffset, elidedId);
+
+ painter->restore();
+ }
+}
+
+void TimelineSectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->pos().y() > TimelineConstants::sectionHeight
+ || event->pos().x() < TimelineConstants::textIndentationSections) {
+ TimelineItem::mouseDoubleClickEvent(event);
+ return;
+ }
+
+ if (event->button() == Qt::LeftButton) {
+ event->accept();
+ toggleCollapsed();
+ }
+}
+
+void TimelineSectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->pos().y() > TimelineConstants::sectionHeight) {
+ TimelineItem::mousePressEvent(event);
+ return;
+ }
+
+ if (event->button() == Qt::LeftButton)
+ event->accept();
+}
+
+void TimelineSectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->pos().y() > TimelineConstants::sectionHeight) {
+ TimelineItem::mouseReleaseEvent(event);
+ return;
+ }
+
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ event->accept();
+
+ if (event->pos().x() > TimelineConstants::textIndentationSections
+ && event->button() == Qt::LeftButton) {
+ if (m_targetNode.isValid())
+ m_targetNode.view()->setSelectedModelNode(m_targetNode);
+ } else {
+ toggleCollapsed();
+ }
+ update();
+}
+
+void TimelineSectionItem::resizeEvent(QGraphicsSceneResizeEvent *event)
+{
+ TimelineItem::resizeEvent(event);
+
+ for (auto child : propertyItems()) {
+ TimelinePropertyItem *item = static_cast<TimelinePropertyItem *>(child);
+ item->resize(size().width(), TimelineConstants::sectionHeight);
+ }
+}
+
+void TimelineSectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+ if (event->pos().x() < TimelineConstants::sectionWidth
+ && event->pos().y() < TimelineConstants::sectionHeight) {
+ QMenu mainMenu;
+
+ auto timeline = timelineScene()->currentTimeline();
+
+ QAction *removeAction = mainMenu.addAction(
+ TimelineConstants::timelineDeleteKeyframesDisplayName);
+ QObject::connect(removeAction, &QAction::triggered, [this]() {
+ timelineScene()->deleteAllKeyframesForTarget(m_targetNode);
+ });
+
+ QAction *addKeyframesAction = mainMenu.addAction(
+ TimelineConstants::timelineInsertKeyframesDisplayName);
+ QObject::connect(addKeyframesAction, &QAction::triggered, [this]() {
+ timelineScene()->insertAllKeyframesForTarget(m_targetNode);
+ });
+
+ QAction *copyAction = mainMenu.addAction(
+ TimelineConstants::timelineCopyKeyframesDisplayName);
+ QObject::connect(copyAction, &QAction::triggered, [this]() {
+ timelineScene()->copyAllKeyframesForTarget(m_targetNode);
+ });
+
+ QAction *pasteAction = mainMenu.addAction(
+ TimelineConstants::timelinePasteKeyframesDisplayName);
+ QObject::connect(pasteAction, &QAction::triggered, [this]() {
+ timelineScene()->pasteKeyframesToTarget(m_targetNode);
+ });
+
+ pasteAction->setEnabled(TimelineActions::clipboardContainsKeyframes());
+
+ mainMenu.exec(event->screenPos());
+ event->accept();
+ }
+}
+
+void TimelineSectionItem::updateData()
+{
+ invalidateBar();
+ resize(rulerWidth(), size().height());
+ invalidateProperties();
+ update();
+}
+
+void TimelineSectionItem::updateFrames()
+{
+ invalidateBar();
+ invalidateFrames();
+ update();
+}
+
+void TimelineSectionItem::invalidateHeight()
+{
+ int height = 0;
+ bool visible = true;
+
+ if (collapsed()) {
+ height = TimelineConstants::sectionHeight;
+ visible = false;
+ } else {
+ height = TimelineConstants::sectionHeight
+ + m_timeline.keyframeGroupsForTarget(m_targetNode).count()
+ * TimelineConstants::sectionHeight;
+ visible = true;
+ }
+
+ for (auto child : propertyItems())
+ child->setVisible(visible);
+
+ setPreferredHeight(height);
+ setMinimumHeight(height);
+ setMaximumHeight(height);
+ timelineScene()->activateLayout();
+}
+
+void TimelineSectionItem::invalidateProperties()
+{
+ for (auto child : propertyItems()) {
+ delete child;
+ }
+
+ createPropertyItems();
+
+ for (auto child : propertyItems()) {
+ TimelinePropertyItem *item = static_cast<TimelinePropertyItem *>(child);
+ item->updateData();
+ item->resize(size().width(), TimelineConstants::sectionHeight);
+ }
+ invalidateHeight();
+}
+
+void TimelineSectionItem::invalidateFrames()
+{
+ for (auto child : propertyItems()) {
+ TimelinePropertyItem *item = static_cast<TimelinePropertyItem *>(child);
+ item->updateFrames();
+ }
+}
+
+bool TimelineSectionItem::collapsed() const
+{
+ return m_targetNode.isValid() && !m_targetNode.hasAuxiliaryData("timeline_expanded");
+}
+
+void TimelineSectionItem::createPropertyItems()
+{
+ auto framesList = m_timeline.keyframeGroupsForTarget(m_targetNode);
+
+ int yPos = TimelineConstants::sectionHeight;
+ for (const auto &frames : framesList) {
+ auto item = TimelinePropertyItem::create(frames, this);
+ item->setY(yPos);
+ yPos = yPos + TimelineConstants::sectionHeight;
+ }
+}
+
+qreal TimelineSectionItem::rulerWidth() const
+{
+ return static_cast<TimelineGraphicsScene *>(scene())->rulerWidth();
+}
+
+void TimelineSectionItem::toggleCollapsed()
+{
+ QTC_ASSERT(m_targetNode.isValid(), return );
+
+ if (collapsed())
+ m_targetNode.setAuxiliaryData("timeline_expanded", true);
+ else
+ m_targetNode.removeAuxiliaryData("timeline_expanded");
+
+ invalidateHeight();
+}
+
+QList<QGraphicsItem *> TimelineSectionItem::propertyItems() const
+{
+ QList<QGraphicsItem *> list;
+
+ for (auto child : childItems()) {
+ if (m_barItem != child && m_dummyItem != child)
+ list.append(child);
+ }
+
+ return list;
+}
+
+TimelineRulerSectionItem::TimelineRulerSectionItem(TimelineItem *parent)
+ : TimelineItem(parent)
+{
+ setPreferredHeight(TimelineConstants::rulerHeight);
+ setMinimumHeight(TimelineConstants::rulerHeight);
+ setMaximumHeight(TimelineConstants::rulerHeight);
+ setZValue(10);
+}
+
+static void drawCenteredText(QPainter *p, int x, int y, const QString &text)
+{
+ QRect rect(x - 16, y - 4, 32, 8);
+ p->drawText(rect, Qt::AlignCenter, text);
+}
+
+TimelineRulerSectionItem *TimelineRulerSectionItem::create(QGraphicsScene *parentScene,
+ TimelineItem *parent)
+{
+ auto item = new TimelineRulerSectionItem(parent);
+ item->setMaximumHeight(TimelineConstants::rulerHeight);
+
+ auto widget = new QWidget;
+ widget->setFixedWidth(TimelineConstants::sectionWidth);
+
+ auto toolBar = new QToolBar;
+ toolBar->setFixedHeight(TimelineConstants::rulerHeight);
+
+ auto layout = new QHBoxLayout(widget);
+ layout->addWidget(toolBar);
+ layout->setMargin(0);
+
+ layout->addWidget(toolBar);
+ layout->setMargin(0);
+
+ QGraphicsProxyWidget *proxy = parentScene->addWidget(widget);
+ proxy->setParentItem(item);
+
+ return item;
+}
+
+void TimelineRulerSectionItem::invalidateRulerSize(const QmlTimeline &timeline)
+{
+ m_duration = timeline.duration();
+ m_start = timeline.startKeyframe();
+ m_end = timeline.endKeyframe();
+}
+
+void TimelineRulerSectionItem::setRulerScaleFactor(int scaling)
+{
+ qreal blend = qreal(scaling) / 100.0;
+
+ qreal width = size().width() - qreal(TimelineConstants::sectionWidth);
+ qreal duration = rulerDuration();
+
+ qreal offset = duration * 0.1;
+ qreal maxCount = duration + offset;
+ qreal minCount = width
+ / qreal(TimelineConstants::keyFrameSize
+ + 2 * TimelineConstants::keyFrameMargin);
+
+ qreal count = maxCount < minCount ? maxCount : TimelineUtils::lerp(blend, minCount, maxCount);
+
+ if (count > std::numeric_limits<qreal>::min() && count <= maxCount)
+ m_scaling = width / count;
+ else
+ m_scaling = 1.0;
+
+ update();
+}
+
+int TimelineRulerSectionItem::getRulerScaleFactor() const
+{
+ qreal width = size().width() - qreal(TimelineConstants::sectionWidth);
+ qreal duration = rulerDuration();
+
+ qreal offset = duration * 0.1;
+ qreal maxCount = duration + offset;
+ qreal minCount = width
+ / qreal(TimelineConstants::keyFrameSize
+ + 2 * TimelineConstants::keyFrameMargin);
+
+ if (maxCount < minCount)
+ return -1;
+
+ qreal rcount = width / m_scaling;
+ qreal rblend = TimelineUtils::reverseLerp(rcount, minCount, maxCount);
+
+ int rfactor = std::round(rblend * 100);
+ return TimelineUtils::clamp(rfactor, 0, 100);
+}
+
+qreal TimelineRulerSectionItem::rulerScaling() const
+{
+ return m_scaling;
+}
+
+qreal TimelineRulerSectionItem::rulerDuration() const
+{
+ return m_duration;
+}
+
+qreal TimelineRulerSectionItem::durationViewportLength() const
+{
+ return m_duration * m_scaling;
+}
+
+qreal TimelineRulerSectionItem::startFrame() const
+{
+ return m_start;
+}
+
+qreal TimelineRulerSectionItem::endFrame() const
+{
+ return m_end;
+}
+
+void TimelineRulerSectionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ static const QColor backgroundColor = Theme::instance()
+ ->qmlDesignerBackgroundColorDarkAlternate();
+ static const QColor penColor = Theme::getColor(Theme::PanelTextColorLight);
+ static const QColor highlightColor = Theme::instance()->Theme::qmlDesignerButtonColor();
+ static const QColor handleColor = Theme::getColor(Theme::QmlDesigner_HighlightColor);
+
+ painter->save();
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->translate(-timelineScene()->scrollOffset(), 0);
+ painter->fillRect(TimelineConstants::sectionWidth,
+ 0,
+ size().width() - TimelineConstants::sectionWidth,
+ size().height(),
+ backgroundColor);
+
+ painter->translate(TimelineConstants::timelineLeftOffset, 0);
+
+ const QRectF rangeRect(TimelineConstants::sectionWidth,
+ 0,
+ m_duration * m_scaling,
+ size().height());
+
+ const qreal radius = 5;
+ const qreal handleWidth = TimelineConstants::timelineBounds * 2;
+ QRectF boundsRect(0, rangeRect.y(), handleWidth, rangeRect.height());
+
+ boundsRect.moveRight(rangeRect.left() + TimelineConstants::timelineBounds);
+
+ QPainterPath leftBoundsPath;
+ leftBoundsPath.addRoundedRect(boundsRect, radius, radius);
+ painter->fillPath(leftBoundsPath, handleColor);
+
+ boundsRect.moveLeft(rangeRect.right() - TimelineConstants::timelineBounds);
+
+ QPainterPath rightBoundsPath;
+ rightBoundsPath.addRoundedRect(boundsRect, radius, radius);
+ painter->fillPath(rightBoundsPath, handleColor);
+
+ painter->fillRect(rangeRect, highlightColor);
+
+ painter->setPen(penColor);
+
+ const int height = size().height() - 1;
+
+ drawLine(painter,
+ TimelineConstants::sectionWidth + timelineScene()->scrollOffset()
+ - TimelineConstants::timelineLeftOffset,
+ height,
+ size().width() + timelineScene()->scrollOffset(),
+ height);
+
+ QFont font = painter->font();
+ font.setPixelSize(8);
+ painter->setFont(font);
+
+ paintTicks(painter);
+
+ painter->restore();
+
+ painter->fillRect(0, 0, TimelineConstants::sectionWidth, size().height(), backgroundColor);
+ painter->restore();
+}
+
+void TimelineRulerSectionItem::paintTicks(QPainter *painter)
+{
+ const int totalWidth = size().width() / m_scaling + timelineScene()->scrollOffset() / m_scaling;
+
+ QFontMetrics fm(painter->font());
+
+ int minSpacingText = fm.horizontalAdvance(QString("X%1X").arg(rulerDuration()));
+ int minSpacingLine = 5;
+
+ int deltaText = 0;
+ int deltaLine = 0;
+
+ // Marks possibly at [1, 5, 10, 50, 100, ...]
+ int spacing = 1;
+ bool toggle = true;
+ while (deltaText == 0) {
+ int distance = spacing * m_scaling;
+
+ if (distance > minSpacingLine && deltaLine == 0)
+ deltaLine = spacing;
+
+ if (distance > minSpacingText) {
+ deltaText = spacing;
+ break;
+ }
+
+ if (toggle) {
+ spacing *= 5;
+ toggle = false;
+ } else {
+ spacing *= 2;
+ toggle = true;
+ }
+ }
+
+ int height = size().height();
+
+ for (int i = timelineScene()->scrollOffset() / m_scaling; i < totalWidth; ++i) {
+ if ((i % deltaText) == 0) {
+ drawCenteredText(painter,
+ TimelineConstants::sectionWidth + i * m_scaling,
+ textOffset,
+ QString::number(m_start + i));
+
+ drawLine(painter,
+ TimelineConstants::sectionWidth + i * m_scaling,
+ height - 2,
+ TimelineConstants::sectionWidth + i * m_scaling,
+ height * 0.6);
+
+ } else if ((i % deltaLine) == 0) {
+ drawLine(painter,
+ TimelineConstants::sectionWidth + i * m_scaling,
+ height - 2,
+ TimelineConstants::sectionWidth + i * m_scaling,
+ height * 0.75);
+ }
+ }
+}
+
+void TimelineRulerSectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ TimelineItem::mousePressEvent(event);
+ emit rulerClicked(event->pos());
+}
+
+void TimelineRulerSectionItem::resizeEvent(QGraphicsSceneResizeEvent *event)
+{
+ QGraphicsWidget::resizeEvent(event);
+
+ auto factor = getRulerScaleFactor();
+
+ if (factor < 0) {
+ if (event->oldSize().width() < event->newSize().width())
+ factor = 0;
+ else
+ factor = 100;
+ }
+
+ emit scaleFactorChanged(factor);
+}
+
+void TimelineRulerSectionItem::setSizeHints(int width)
+{
+ const int rulerWidth = width;
+ setPreferredWidth(rulerWidth);
+ setMinimumWidth(rulerWidth);
+ setMaximumWidth(rulerWidth);
+}
+
+TimelineBarItem::TimelineBarItem(TimelineSectionItem *parent)
+ : TimelineMovableAbstractItem(parent)
+{
+ setAcceptHoverEvents(true);
+ setPen(Qt::NoPen);
+}
+
+void TimelineBarItem::itemMoved(const QPointF &start, const QPointF &end)
+{
+ if (isActiveHandle(Location::Undefined))
+ dragInit(rect(), start);
+
+ const qreal min = qreal(TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
+ - scrollOffset());
+ const qreal max = qreal(timelineScene()->rulerWidth() - TimelineConstants::sectionWidth
+ + rect().width());
+
+ if (isActiveHandle(Location::Center))
+ dragCenter(rect(), end, min, max);
+ else
+ dragHandle(rect(), end, min, max);
+
+ timelineScene()->statusBarMessageChanged(
+ tr("Range from %1 to %2")
+ .arg(qRound(mapFromSceneToFrame(rect().x())))
+ .arg(qRound(mapFromSceneToFrame(rect().width() + rect().x()))));
+}
+
+void TimelineBarItem::commitPosition(const QPointF & /*point*/)
+{
+ if (sectionItem()->view()) {
+ if (m_handle != Location::Undefined) {
+ sectionItem()->view()->executeInTransaction("TimelineBarItem::commitPosition", [this](){
+ qreal scaleFactor = rect().width() / m_oldRect.width();
+
+ qreal moved = (rect().topLeft().x() - m_oldRect.topLeft().x()) / rulerScaling();
+ qreal supposedFirstFrame = qRound(sectionItem()->firstFrame() + moved);
+
+ sectionItem()->scaleAllFrames(scaleFactor);
+ sectionItem()->moveAllFrames(supposedFirstFrame - sectionItem()->firstFrame());
+ });
+ }
+ }
+
+ m_handle = Location::Undefined;
+ m_bounds = Location::Undefined;
+ m_pivot = 0.0;
+ m_oldRect = QRectF();
+}
+
+void TimelineBarItem::scrollOffsetChanged()
+{
+ sectionItem()->invalidateBar();
+}
+
+void TimelineBarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ QColor brushColorSelected = Theme::getColor(Theme::QmlDesigner_HighlightColor);
+ QColor brushColor = Theme::getColor(Theme::QmlDesigner_HighlightColor).darker(120);
+ const QColor indicatorColor = Theme::getColor(Theme::PanelTextColorLight);
+
+ ModelNode target = sectionItem()->targetNode();
+ if (target.isValid()) {
+ QColor overrideColor = target.auxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE).value<QColor>();
+ if (overrideColor.isValid()) {
+ brushColorSelected = overrideColor;
+ brushColor = brushColorSelected.darker(120);
+ }
+ }
+
+ const QRectF itemRect = rect();
+
+ painter->save();
+ painter->setClipRect(TimelineConstants::sectionWidth,
+ 0,
+ itemRect.width() + itemRect.x(),
+ itemRect.height());
+
+ if (sectionItem()->isSelected())
+ painter->fillRect(itemRect, brushColorSelected);
+ else
+ painter->fillRect(itemRect, brushColor);
+
+ auto positions = sectionItem()->keyframePositions();
+ std::sort(positions.begin(), positions.end());
+
+ auto fcompare = [](auto v1, auto v2) { return qFuzzyCompare(v1, v2); };
+ auto unique = std::unique(positions.begin(), positions.end(), fcompare);
+ positions.erase(unique, positions.end());
+
+ painter->setPen(indicatorColor);
+ auto margin = itemRect.height() * 0.166;
+ auto p1y = itemRect.top() + margin;
+ auto p2y = itemRect.bottom() - margin;
+ for (auto pos : positions) {
+ auto px = mapFromFrameToScene(pos) + 0.5;
+ painter->drawLine(QLineF(px, p1y, px, p2y));
+ }
+ painter->restore();
+}
+
+void TimelineBarItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+ const auto p = event->pos();
+
+ QRectF left, right;
+ if (handleRects(rect(), left, right)) {
+ if (left.contains(p) || right.contains(p)) {
+ if (cursor().shape() != Qt::SizeHorCursor)
+ setCursor(QCursor(Qt::SizeHorCursor));
+ } else if (rect().contains(p)) {
+ if (cursor().shape() != Qt::ClosedHandCursor)
+ setCursor(QCursor(Qt::ClosedHandCursor));
+ }
+ } else {
+ if (rect().contains(p))
+ setCursor(QCursor(Qt::ClosedHandCursor));
+ }
+}
+
+void TimelineBarItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
+{
+ QMenu menu;
+ QAction* overrideColor = menu.addAction(tr("Override Color"));
+
+ auto setColor = [this] () {
+ ModelNode target = sectionItem()->targetNode();
+ if (target.isValid()) {
+ QColor current = target.auxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE).value<QColor>();
+ QColor color = QColorDialog::getColor(current, nullptr);
+ if (color.isValid())
+ target.setAuxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE, color);
+ }
+ };
+
+ QObject::connect(overrideColor, &QAction::triggered, setColor);
+
+ QAction* resetColor = menu.addAction(tr("Reset Color"));
+ auto reset = [this]() {
+ ModelNode target = sectionItem()->targetNode();
+ if (target.isValid())
+ target.removeAuxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE);
+ };
+ QObject::connect(resetColor, &QAction::triggered, reset);
+
+ menu.exec(event->screenPos());
+}
+
+TimelineSectionItem *TimelineBarItem::sectionItem() const
+{
+ /* The parentItem is always a TimelineSectionItem. See constructor */
+ return qgraphicsitem_cast<TimelineSectionItem *>(parentItem());
+}
+
+void TimelineBarItem::dragInit(const QRectF &rect, const QPointF &pos)
+{
+ QRectF left, right;
+ m_oldRect = rect;
+ if (handleRects(rect, left, right)) {
+ if (left.contains(pos)) {
+ m_handle = Location::Left;
+ m_pivot = pos.x() - left.topLeft().x();
+ } else if (right.contains(pos)) {
+ m_handle = Location::Right;
+ m_pivot = pos.x() - right.topRight().x();
+ } else if (rect.contains(pos)) {
+ m_handle = Location::Center;
+ m_pivot = pos.x() - rect.topLeft().x();
+ }
+
+ } else {
+ if (rect.contains(pos)) {
+ m_handle = Location::Center;
+ m_pivot = pos.x() - rect.topLeft().x();
+ }
+ }
+}
+
+void TimelineBarItem::dragCenter(QRectF rect, const QPointF &pos, qreal min, qreal max)
+{
+ if (validateBounds(pos.x() - rect.topLeft().x())) {
+ rect.moveLeft(pos.x() - m_pivot);
+ if (rect.topLeft().x() < min) {
+ rect.moveLeft(min);
+ setOutOfBounds(Location::Left);
+ } else if (rect.topRight().x() > max) {
+ rect.moveRight(max);
+ setOutOfBounds(Location::Right);
+ }
+ setRect(rect);
+ }
+}
+
+void TimelineBarItem::dragHandle(QRectF rect, const QPointF &pos, qreal min, qreal max)
+{
+ QRectF left, right;
+ handleRects(rect, left, right);
+
+ if (isActiveHandle(Location::Left)) {
+ if (validateBounds(pos.x() - left.topLeft().x())) {
+ rect.setLeft(pos.x() - m_pivot);
+ if (rect.left() < min) {
+ rect.setLeft(min);
+ setOutOfBounds(Location::Left);
+ } else if (rect.left() >= rect.right() - minimumBarWidth)
+ rect.setLeft(rect.right() - minimumBarWidth);
+
+ setRect(rect);
+ }
+ } else if (isActiveHandle(Location::Right)) {
+ if (validateBounds(pos.x() - right.topRight().x())) {
+ rect.setRight(pos.x() - m_pivot);
+ if (rect.right() > max) {
+ rect.setRight(max);
+ setOutOfBounds(Location::Right);
+ } else if (rect.right() <= rect.left() + minimumBarWidth)
+ rect.setRight(rect.left() + minimumBarWidth);
+
+ setRect(rect);
+ }
+ }
+}
+
+bool TimelineBarItem::handleRects(const QRectF &rect, QRectF &left, QRectF &right) const
+{
+ if (rect.width() < minimumBarWidth)
+ return false;
+
+ const qreal handleSize = rect.height();
+
+ auto handleRect = QRectF(0, 0, handleSize, handleSize);
+ handleRect.moveCenter(rect.center());
+
+ handleRect.moveLeft(rect.left());
+ left = handleRect;
+
+ handleRect.moveRight(rect.right());
+ right = handleRect;
+
+ return true;
+}
+
+bool TimelineBarItem::isActiveHandle(Location location) const
+{
+ return m_handle == location;
+}
+
+void TimelineBarItem::setOutOfBounds(Location location)
+{
+ m_bounds = location;
+}
+
+bool TimelineBarItem::validateBounds(qreal distance)
+{
+ if (m_bounds == Location::Left) {
+ if (distance > m_pivot)
+ m_bounds = Location::Center;
+ return false;
+
+ } else if (m_bounds == Location::Right) {
+ if (distance < m_pivot)
+ m_bounds = Location::Center;
+ return false;
+ }
+ return true;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesectionitem.h b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.h
index 26db04f757..26db04f757 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesectionitem.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineselectiontool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
index 53367c9b67..53367c9b67 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineselectiontool.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineselectiontool.h b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.h
index 3485e087ec..3485e087ec 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineselectiontool.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.cpp
index 960c409553..960c409553 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.h b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.h
index da4ddac4f6..da4ddac4f6 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.ui b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.ui
index f3dfa6f094..f3dfa6f094 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsdialog.ui
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsdialog.ui
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsmodel.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsmodel.cpp
new file mode 100644
index 0000000000..f75d129983
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsmodel.cpp
@@ -0,0 +1,484 @@
+/****************************************************************************
+**
+** 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 "timelinesettingsmodel.h"
+
+#include "timelineview.h"
+
+#include <modelnode.h>
+#include <variantproperty.h>
+#include <qmlitemnode.h>
+
+#include <utils/qtcassert.h>
+
+#include <QComboBox>
+#include <QItemEditorFactory>
+#include <QMessageBox>
+#include <QStyledItemDelegate>
+#include <QTimer>
+
+namespace QmlDesigner {
+
+class CustomDelegate : public QStyledItemDelegate
+{
+public:
+ explicit CustomDelegate(QWidget *parent = nullptr);
+ void paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+};
+
+CustomDelegate::CustomDelegate(QWidget *parent)
+ : QStyledItemDelegate(parent)
+{}
+
+void CustomDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QStyleOptionViewItem opt = option;
+ opt.state &= ~QStyle::State_HasFocus;
+ QStyledItemDelegate::paint(painter, opt, index);
+}
+
+class TimelineEditorDelegate : public CustomDelegate
+{
+public:
+ TimelineEditorDelegate(QWidget *parent = nullptr);
+ QWidget *createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+};
+
+TimelineEditorDelegate::TimelineEditorDelegate(QWidget *parent)
+ : CustomDelegate(parent)
+{
+ static QItemEditorFactory *factory = nullptr;
+ if (factory == nullptr) {
+ factory = new QItemEditorFactory;
+ QItemEditorCreatorBase *creator = new QItemEditorCreator<QComboBox>("currentText");
+ factory->registerEditor(QVariant::String, creator);
+ }
+
+ setItemEditorFactory(factory);
+}
+
+QWidget *TimelineEditorDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
+
+ const auto timelineSettingsModel = qobject_cast<const TimelineSettingsModel *>(index.model());
+
+ auto comboBox = qobject_cast<QComboBox *>(widget);
+
+ QTC_ASSERT(timelineSettingsModel, return widget);
+ QTC_ASSERT(timelineSettingsModel->timelineView(), return widget);
+
+ QmlTimeline qmlTimeline = timelineSettingsModel->timelineForRow(index.row());
+
+ switch (index.column()) {
+ case TimelineSettingsModel::TimelineRow: {
+ QTC_ASSERT(comboBox, return widget);
+ comboBox->addItem(TimelineSettingsModel::tr("None"));
+ for (const auto &timeline : timelineSettingsModel->timelineView()->getTimelines()) {
+ if (!timeline.modelNode().id().isEmpty())
+ comboBox->addItem(timeline.modelNode().id());
+ }
+ } break;
+ case TimelineSettingsModel::AnimationRow: {
+ QTC_ASSERT(comboBox, return widget);
+ comboBox->addItem(TimelineSettingsModel::tr("None"));
+ for (const auto &animation :
+ timelineSettingsModel->timelineView()->getAnimations(qmlTimeline)) {
+ if (!animation.id().isEmpty())
+ comboBox->addItem(animation.id());
+ }
+ } break;
+ case TimelineSettingsModel::FixedFrameRow: {
+ } break;
+
+ default:
+ qWarning() << "TimelineEditorDelegate::createEditor column" << index.column();
+ }
+
+ if (comboBox) {
+ connect(comboBox, QOverload<int>::of(&QComboBox::activated), this, [=]() {
+ auto delegate = const_cast<TimelineEditorDelegate *>(this);
+ emit delegate->commitData(comboBox);
+ });
+ }
+
+ return widget;
+}
+
+TimelineSettingsModel::TimelineSettingsModel(QObject *parent, TimelineView *view)
+ : QStandardItemModel(parent)
+ , m_timelineView(view)
+{
+ connect(this, &QStandardItemModel::dataChanged, this, &TimelineSettingsModel::handleDataChanged);
+}
+
+void TimelineSettingsModel::resetModel()
+{
+ beginResetModel();
+ clear();
+ setHorizontalHeaderLabels(
+ QStringList({tr("State"), tr("Timeline"), tr("Animation"), tr("Fixed Frame")}));
+
+ if (timelineView()->isAttached() && timelineView()->rootModelNode().hasId()) {
+ addState(ModelNode());
+ for (const QmlModelState &state :
+ QmlItemNode(timelineView()->rootModelNode()).states().allStates())
+ addState(state);
+ }
+
+ endResetModel();
+}
+
+TimelineView *TimelineSettingsModel::timelineView() const
+{
+ return m_timelineView;
+}
+
+void TimelineSettingsModel::setupDelegates(QAbstractItemView *view)
+{
+ view->setItemDelegate(new TimelineEditorDelegate);
+}
+
+static int propertyValueForState(const ModelNode &modelNode,
+ QmlModelState state,
+ const PropertyName &propertyName)
+{
+ if (!modelNode.isValid())
+ return -1;
+
+ if (state.isBaseState()) {
+ if (modelNode.hasVariantProperty(propertyName))
+ return modelNode.variantProperty(propertyName).value().toInt();
+ return -1;
+ }
+
+ if (state.hasPropertyChanges(modelNode)) {
+ QmlPropertyChanges propertyChanges(state.propertyChanges(modelNode));
+ if (propertyChanges.modelNode().hasVariantProperty(propertyName))
+ return propertyChanges.modelNode().variantProperty(propertyName).value().toInt();
+ }
+
+ return -1;
+}
+
+static QStandardItem *createStateItem(const ModelNode &state)
+{
+ if (state.isValid())
+ return new QStandardItem(state.variantProperty("name").value().toString());
+ else
+ return new QStandardItem(TimelineSettingsModel::tr("Base State"));
+}
+
+void TimelineSettingsModel::addState(const ModelNode &state)
+{
+ QList<QStandardItem *> items;
+
+ QmlTimeline timeline = timelineView()->timelineForState(state);
+ const QString timelineId = timeline.isValid() ? timeline.modelNode().id() : QString("");
+ ModelNode animation = animationForTimelineAndState(timeline, state);
+ const QString animationId = animation.isValid() ? animation.id() : QString("");
+
+ QStandardItem *stateItem = createStateItem(state);
+ auto *timelinelItem = new QStandardItem(timelineId);
+ auto *animationItem = new QStandardItem(animationId);
+ auto *fixedFrameItem = new QStandardItem("");
+
+ stateItem->setData(state.internalId());
+ stateItem->setFlags(Qt::ItemIsEnabled);
+
+ int fixedValue = propertyValueForState(timeline, state, "currentFrame");
+ fixedFrameItem->setData(fixedValue, Qt::EditRole);
+
+ items.append(stateItem);
+ items.append(timelinelItem);
+ items.append(animationItem);
+ items.append(fixedFrameItem);
+
+ appendRow(items);
+}
+
+void TimelineSettingsModel::handleException()
+{
+ QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
+ resetModel();
+}
+
+ModelNode TimelineSettingsModel::animationForTimelineAndState(const QmlTimeline &timeline,
+ const ModelNode &state)
+{
+ QmlModelState modelState(state);
+
+ if (!timeline.isValid())
+ return ModelNode();
+
+ const QList<ModelNode> &animations = timelineView()->getAnimations(timeline);
+
+ if (modelState.isBaseState()) {
+ for (const auto &animation : animations) {
+ if (animation.hasVariantProperty("running")
+ && animation.variantProperty("running").value().toBool())
+ return animation;
+ }
+ return ModelNode();
+ }
+
+ for (const auto &animation : animations) {
+ if (modelState.affectsModelNode(animation)) {
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(animation));
+
+ if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("running")
+ && propertyChanges.modelNode().variantProperty("running").value().toBool())
+ return animation;
+ }
+ }
+ return ModelNode();
+}
+
+void TimelineSettingsModel::updateTimeline(int row)
+{
+
+ timelineView()->executeInTransaction("TimelineSettingsModel::updateTimeline", [this, row](){
+ QmlModelState modelState(stateForRow(row));
+ QmlTimeline timeline(timelineForRow(row));
+ ModelNode animation(animationForRow(row));
+ QmlTimeline oldTimeline = timelineView()->timelineForState(modelState);
+
+ if (modelState.isBaseState()) {
+ if (oldTimeline.isValid())
+ oldTimeline.modelNode().variantProperty("enabled").setValue(false);
+ if (timeline.isValid())
+ timeline.modelNode().variantProperty("enabled").setValue(true);
+ } else {
+ if (oldTimeline.isValid() && modelState.affectsModelNode(oldTimeline)) {
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(oldTimeline));
+ if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("enabled"))
+ propertyChanges.modelNode().removeProperty("enabled");
+ }
+
+ QmlTimeline baseTimeline(timelineForRow(0));
+
+ if (baseTimeline.isValid()) {
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(baseTimeline));
+ if (propertyChanges.isValid())
+ propertyChanges.modelNode().variantProperty("enabled").setValue(false);
+ }
+
+ if (timeline.isValid()) { /* If timeline is invalid 'none' was selected */
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(timeline));
+ if (propertyChanges.isValid())
+ propertyChanges.modelNode().variantProperty("enabled").setValue(true);
+ }
+ }
+ });
+
+ resetRow(row);
+}
+
+void TimelineSettingsModel::updateAnimation(int row)
+{
+ timelineView()->executeInTransaction("TimelineSettingsModel::updateAnimation", [this, row](){
+ QmlModelState modelState(stateForRow(row));
+ QmlTimeline timeline(timelineForRow(row));
+ ModelNode animation(animationForRow(row));
+ QmlTimeline oldTimeline = timelineView()->timelineForState(modelState);
+ ModelNode oldAnimation = animationForTimelineAndState(oldTimeline, modelState);
+
+ if (modelState.isBaseState()) {
+ if (oldAnimation.isValid())
+ oldAnimation.variantProperty("running").setValue(false);
+ if (animation.isValid())
+ animation.variantProperty("running").setValue(true);
+ if (timeline.isValid() && timeline.modelNode().hasProperty("currentFrame"))
+ timeline.modelNode().removeProperty("currentFrame");
+ } else {
+ if (oldAnimation.isValid() && modelState.affectsModelNode(oldAnimation)) {
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(oldAnimation));
+ if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("running"))
+ propertyChanges.modelNode().removeProperty("running");
+ }
+
+ ModelNode baseAnimation(animationForRow(0));
+
+ if (baseAnimation.isValid()) {
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(baseAnimation));
+ if (propertyChanges.isValid()) {
+ propertyChanges.modelNode().variantProperty("running").setValue(false);
+ if (propertyChanges.modelNode().hasProperty("currentFrame"))
+ propertyChanges.modelNode().removeProperty("currentFrame");
+ }
+ }
+
+ if (animation.isValid()) { /* If animation is invalid 'none' was selected */
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(animation));
+ if (propertyChanges.isValid())
+ propertyChanges.modelNode().variantProperty("running").setValue(true);
+ }
+ }
+ });
+ resetRow(row);
+}
+
+void TimelineSettingsModel::updateFixedFrameRow(int row)
+{
+ timelineView()->executeInTransaction("TimelineSettingsModel::updateFixedFrameRow", [this, row](){
+ QmlModelState modelState(stateForRow(row));
+ QmlTimeline timeline(timelineForRow(row));
+
+ ModelNode animation = animationForTimelineAndState(timeline, modelState);
+
+ int fixedFrame = fixedFrameForRow(row);
+
+ if (modelState.isBaseState()) {
+ if (animation.isValid())
+ animation.variantProperty("running").setValue(false);
+ if (timeline.isValid())
+ timeline.modelNode().variantProperty("currentFrame").setValue(fixedFrame);
+ } else {
+ if (animation.isValid() && modelState.affectsModelNode(animation)) {
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(animation));
+ if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("running"))
+ propertyChanges.modelNode().removeProperty("running");
+ }
+
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(timeline));
+ if (propertyChanges.isValid())
+ propertyChanges.modelNode().variantProperty("currentFrame").setValue(fixedFrame);
+ }
+
+ });
+
+ resetRow(row);
+}
+
+void TimelineSettingsModel::resetRow(int row)
+{
+ m_lock = true;
+ QStandardItem *animationItem = item(row, AnimationRow);
+ QStandardItem *fixedFrameItem = item(row, FixedFrameRow);
+
+ QmlModelState modelState(stateForRow(row));
+ QmlTimeline timeline(timelineForRow(row));
+ ModelNode animation = animationForTimelineAndState(timeline, modelState);
+
+ if (animationItem) {
+ const QString animationId = animation.isValid() ? animation.id() : QString();
+ animationItem->setText(animationId);
+ }
+
+ if (fixedFrameItem) {
+ int fixedValue = propertyValueForState(timeline, modelState, "currentFrame");
+ if (fixedFrameItem->data(Qt::EditRole).toInt() != fixedValue)
+ fixedFrameItem->setData(fixedValue, Qt::EditRole);
+ }
+
+ m_lock = false;
+}
+
+QmlTimeline TimelineSettingsModel::timelineForRow(int row) const
+{
+ QStandardItem *standardItem = item(row, TimelineRow);
+
+ if (standardItem)
+ return QmlTimeline(timelineView()->modelNodeForId(standardItem->text()));
+
+ return QmlTimeline();
+}
+
+ModelNode TimelineSettingsModel::animationForRow(int row) const
+{
+ QStandardItem *standardItem = item(row, AnimationRow);
+
+ if (standardItem)
+ return timelineView()->modelNodeForId(standardItem->text());
+
+ return ModelNode();
+}
+
+ModelNode TimelineSettingsModel::stateForRow(int row) const
+{
+ QStandardItem *standardItem = item(row, StateRow);
+
+ if (standardItem)
+ return timelineView()->modelNodeForInternalId(standardItem->data().toInt());
+
+ return ModelNode();
+}
+
+int TimelineSettingsModel::fixedFrameForRow(int row) const
+{
+ QStandardItem *standardItem = item(row, FixedFrameRow);
+
+ if (standardItem)
+ return standardItem->data(Qt::EditRole).toInt();
+
+ return -1;
+}
+
+void TimelineSettingsModel::handleDataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight)
+{
+ if (topLeft != bottomRight) {
+ qWarning() << "TimelineSettingsModel::handleDataChanged multi edit?";
+ return;
+ }
+
+ if (m_lock)
+ return;
+
+ m_lock = true;
+
+ int currentColumn = topLeft.column();
+ int currentRow = topLeft.row();
+
+ switch (currentColumn) {
+ case StateRow: {
+ /* read only */
+ } break;
+ case TimelineRow: {
+ updateTimeline(currentRow);
+ } break;
+ case AnimationRow: {
+ updateAnimation(currentRow);
+ } break;
+ case FixedFrameRow: {
+ updateFixedFrameRow(currentRow);
+ } break;
+
+ default:
+ qWarning() << "ConnectionModel::handleDataChanged column" << currentColumn;
+ }
+
+ m_lock = false;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsmodel.h b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsmodel.h
index afd4b58e1b..afd4b58e1b 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsmodel.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesettingsmodel.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbar.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp
index adc49a97b1..adc49a97b1 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbar.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbar.h b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.h
index 43d42b83f9..43d42b83f9 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbar.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbutton.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbutton.cpp
index e6a9454186..e6a9454186 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbutton.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbutton.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbutton.h b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbutton.h
index cdf024c0b2..cdf024c0b2 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetoolbutton.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbutton.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetooldelegate.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp
index 51c5a7d088..51c5a7d088 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetooldelegate.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetooldelegate.h b/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.h
index f945c1a61b..f945c1a61b 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinetooldelegate.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineutils.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineutils.cpp
index 6873fc0b65..6873fc0b65 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineutils.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineutils.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineutils.h b/src/plugins/qmldesigner/components/timelineeditor/timelineutils.h
index 0758733769..0758733769 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineutils.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineutils.h
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
new file mode 100644
index 0000000000..f39a17db2f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
@@ -0,0 +1,610 @@
+/****************************************************************************
+**
+** 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 "timelineview.h"
+
+#include "easingcurve.h"
+#include "timelineactions.h"
+#include "timelineconstants.h"
+#include "timelinecontext.h"
+#include "timelinewidget.h"
+
+#include "timelinegraphicsscene.h"
+#include "timelinesettingsdialog.h"
+#include "timelinetoolbar.h"
+
+#include <bindingproperty.h>
+#include <exception.h>
+#include <modelnodecontextmenu_helper.h>
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <nodemetainfo.h>
+#include <rewritertransaction.h>
+#include <variantproperty.h>
+#include <qmldesignericons.h>
+#include <qmldesignerplugin.h>
+#include <qmlitemnode.h>
+#include <qmlobjectnode.h>
+#include <qmlstate.h>
+#include <qmltimeline.h>
+#include <qmltimelinekeyframegroup.h>
+#include <viewmanager.h>
+
+#include <coreplugin/icore.h>
+
+#include <utils/qtcassert.h>
+
+#include <designmodecontext.h>
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+#include <QTimer>
+
+namespace QmlDesigner {
+
+TimelineView::TimelineView(QObject *parent)
+ : AbstractView(parent)
+{
+ EasingCurve::registerStreamOperators();
+}
+
+TimelineView::~TimelineView() = default;
+
+void TimelineView::modelAttached(Model *model)
+{
+ AbstractView::modelAttached(model);
+ if (m_timelineWidget)
+ m_timelineWidget->init();
+}
+
+void TimelineView::modelAboutToBeDetached(Model *model)
+{
+ m_timelineWidget->reset();
+ setTimelineRecording(false);
+ AbstractView::modelAboutToBeDetached(model);
+}
+
+void TimelineView::nodeCreated(const ModelNode & /*createdNode*/) {}
+
+void TimelineView::nodeAboutToBeRemoved(const ModelNode &removedNode)
+{
+ if (removedNode.isValid()) {
+ if (QmlTimeline::isValidQmlTimeline(removedNode)) {
+ auto *toolBar = widget()->toolBar();
+
+ QString lastId = toolBar->currentTimelineId();
+ toolBar->removeTimeline(QmlTimeline(removedNode));
+ QString currentId = toolBar->currentTimelineId();
+
+ removedNode.setAuxiliaryData("removed@Internal", true);
+
+ if (currentId.isEmpty())
+ m_timelineWidget->graphicsScene()->clearTimeline();
+ if (lastId != currentId)
+ m_timelineWidget->setTimelineId(currentId);
+ } else if (removedNode.parentProperty().isValid()
+ && QmlTimeline::isValidQmlTimeline(removedNode.parentProperty().parentModelNode())) {
+ if (removedNode.hasBindingProperty("target")) {
+ const ModelNode target = removedNode.bindingProperty("target").resolveToModelNode();
+ if (target.isValid()) {
+ QmlTimeline timeline(removedNode.parentProperty().parentModelNode());
+ if (timeline.hasKeyframeGroupForTarget(target))
+ QTimer::singleShot(0, [this, target, timeline]() {
+ if (timeline.hasKeyframeGroupForTarget(target))
+ m_timelineWidget->graphicsScene()->invalidateSectionForTarget(target);
+ else
+ m_timelineWidget->graphicsScene()->invalidateScene();
+ });
+ }
+ }
+ }
+ }
+}
+
+void TimelineView::nodeRemoved(const ModelNode & /*removedNode*/,
+ const NodeAbstractProperty &parentProperty,
+ PropertyChangeFlags /*propertyChange*/)
+{
+ if (parentProperty.isValid()
+ && QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(
+ parentProperty.parentModelNode())) {
+ QmlTimelineKeyframeGroup frames(parentProperty.parentModelNode());
+ m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
+ }
+}
+
+void TimelineView::nodeReparented(const ModelNode &node,
+ const NodeAbstractProperty &newPropertyParent,
+ const NodeAbstractProperty & /*oldPropertyParent*/,
+ AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+ if (newPropertyParent.isValid()
+ && QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(
+ newPropertyParent.parentModelNode())) {
+ QmlTimelineKeyframeGroup frames(newPropertyParent.parentModelNode());
+ m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
+ } else if (QmlTimelineKeyframeGroup::checkKeyframesType(
+ node)) { /* During copy and paste type info might be incomplete */
+ QmlTimelineKeyframeGroup frames(node);
+ m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
+ }
+}
+
+void TimelineView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName>> &propertyList)
+{
+ QmlTimeline timeline = currentTimeline();
+ bool updated = false;
+ for (const auto &pair : propertyList) {
+ if (pair.second == "startFrame" || pair.second == "endFrame") {
+ if (QmlTimeline::isValidQmlTimeline(pair.first)) {
+ m_timelineWidget->invalidateTimelineDuration(pair.first);
+ }
+ } else if (pair.second == "currentFrame") {
+ if (QmlTimeline::isValidQmlTimeline(pair.first)) {
+ m_timelineWidget->invalidateTimelinePosition(pair.first);
+ }
+ } else if (!updated && timeline.hasTimeline(pair.first, pair.second)) {
+ m_timelineWidget->graphicsScene()->invalidateCurrentValues();
+ updated = true;
+ }
+ }
+}
+
+void TimelineView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
+ AbstractView::PropertyChangeFlags /*propertyChange*/)
+{
+ for (const auto &property : propertyList) {
+ if (property.name() == "frame"
+ && property.parentModelNode().type() == "QtQuick.Timeline.Keyframe"
+ && property.parentModelNode().isValid()
+ && property.parentModelNode().hasParentProperty()) {
+ const ModelNode framesNode
+ = property.parentModelNode().parentProperty().parentModelNode();
+ if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(framesNode)) {
+ QmlTimelineKeyframeGroup frames(framesNode);
+ m_timelineWidget->graphicsScene()->invalidateKeyframesForTarget(frames.target());
+ }
+ }
+ }
+}
+
+void TimelineView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/,
+ const QList<ModelNode> & /*lastSelectedNodeList*/)
+{
+ if (m_timelineWidget)
+ m_timelineWidget->graphicsScene()->update();
+}
+
+void TimelineView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList)
+{
+ for (const auto &property : propertyList) {
+ if (property.isNodeListProperty()) {
+ for (const auto &node : property.toNodeListProperty().toModelNodeList()) {
+ nodeAboutToBeRemoved(node);
+ }
+ }
+ }
+}
+
+void TimelineView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
+{
+ for (const auto &property : propertyList) {
+ if (property.name() == "keyframes" && property.parentModelNode().isValid()) {
+ if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(
+ property.parentModelNode())) {
+ QmlTimelineKeyframeGroup frames(property.parentModelNode());
+ m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
+ } else if (QmlTimeline::isValidQmlTimeline(property.parentModelNode())) {
+ m_timelineWidget->graphicsScene()->invalidateScene();
+ }
+ }
+ }
+}
+
+bool TimelineView::hasWidget() const
+{
+ return true;
+}
+
+void TimelineView::nodeIdChanged(const ModelNode &node, const QString &, const QString &)
+{
+ if (QmlTimeline::isValidQmlTimeline(node))
+ m_timelineWidget->init();
+}
+
+void TimelineView::currentStateChanged(const ModelNode &)
+{
+ if (m_timelineWidget)
+ m_timelineWidget->init();
+}
+
+TimelineWidget *TimelineView::widget() const
+{
+ return m_timelineWidget;
+}
+
+const QmlTimeline TimelineView::addNewTimeline()
+{
+ const TypeName timelineType = "QtQuick.Timeline.Timeline";
+
+ QTC_ASSERT(isAttached(), return QmlTimeline());
+
+ try {
+ ensureQtQuickTimelineImport();
+ } catch (const Exception &e) {
+ e.showException();
+ }
+
+ NodeMetaInfo metaInfo = model()->metaInfo(timelineType);
+
+ QTC_ASSERT(metaInfo.isValid(), return QmlTimeline());
+
+ ModelNode timelineNode;
+
+ executeInTransaction("TimelineView::addNewTimeline", [=, &timelineNode](){
+ bool hasTimelines = getTimelines().isEmpty();
+
+ timelineNode = createModelNode(timelineType,
+ metaInfo.majorVersion(),
+ metaInfo.minorVersion());
+ timelineNode.validId();
+
+ timelineNode.variantProperty("startFrame").setValue(0);
+ timelineNode.variantProperty("endFrame").setValue(1000);
+ timelineNode.variantProperty("enabled").setValue(hasTimelines);
+
+ rootModelNode().defaultNodeListProperty().reparentHere(timelineNode);
+ });
+
+ return QmlTimeline(timelineNode);
+}
+
+ModelNode TimelineView::addAnimation(QmlTimeline timeline)
+{
+ const TypeName animationType = "QtQuick.Timeline.TimelineAnimation";
+
+ QTC_ASSERT(timeline.isValid(), return ModelNode());
+
+ QTC_ASSERT(isAttached(), return ModelNode());
+
+ NodeMetaInfo metaInfo = model()->metaInfo(animationType);
+
+ QTC_ASSERT(metaInfo.isValid(), return ModelNode());
+
+ ModelNode animationNode;
+
+ executeInTransaction("TimelineView::addAnimation", [=, &animationNode](){
+ animationNode = createModelNode(animationType,
+ metaInfo.majorVersion(),
+ metaInfo.minorVersion());
+ animationNode.variantProperty("duration").setValue(timeline.duration());
+ animationNode.validId();
+
+ animationNode.variantProperty("from").setValue(timeline.startKeyframe());
+ animationNode.variantProperty("to").setValue(timeline.endKeyframe());
+
+ animationNode.variantProperty("loops").setValue(1);
+
+ animationNode.variantProperty("running").setValue(getAnimations(timeline).isEmpty());
+
+ timeline.modelNode().nodeListProperty("animations").reparentHere(animationNode);
+
+ if (timeline.modelNode().hasProperty("currentFrame"))
+ timeline.modelNode().removeProperty("currentFrame");
+ });
+
+ return animationNode;
+}
+
+void TimelineView::addNewTimelineDialog()
+{
+ auto timeline = addNewTimeline();
+ addAnimation(timeline);
+ openSettingsDialog();
+}
+
+void TimelineView::openSettingsDialog()
+{
+ auto dialog = new TimelineSettingsDialog(Core::ICore::dialogParent(), this);
+
+ auto timeline = m_timelineWidget->graphicsScene()->currentTimeline();
+ if (timeline.isValid())
+ dialog->setCurrentTimeline(timeline);
+
+ QObject::connect(dialog, &TimelineSettingsDialog::rejected, [this, dialog]() {
+ m_timelineWidget->init();
+ dialog->deleteLater();
+ });
+
+ QObject::connect(dialog, &TimelineSettingsDialog::accepted, [this, dialog]() {
+ m_timelineWidget->init();
+ dialog->deleteLater();
+ });
+
+ dialog->show();
+}
+
+void TimelineView::setTimelineRecording(bool value)
+{
+ ModelNode node = widget()->graphicsScene()->currentTimeline();
+
+ QTC_ASSERT(node.isValid(), return );
+
+ if (value) {
+ activateTimelineRecording(node);
+ } else {
+ deactivateTimelineRecording();
+ activateTimeline(node);
+ }
+}
+
+void TimelineView::customNotification(const AbstractView * /*view*/,
+ const QString &identifier,
+ const QList<ModelNode> &nodeList,
+ const QList<QVariant> &data)
+{
+ if (identifier == QStringLiteral("reset QmlPuppet")) {
+ QmlTimeline timeline = widget()->graphicsScene()->currentTimeline();
+ if (timeline.isValid())
+ timeline.modelNode().removeAuxiliaryData("currentFrame@NodeInstance");
+ } else if (identifier == "INSERT_KEYFRAME" && !nodeList.isEmpty() && !data.isEmpty()) {
+ insertKeyframe(nodeList.constFirst(), data.constFirst().toString().toUtf8());
+ }
+}
+
+void TimelineView::insertKeyframe(const ModelNode &target, const PropertyName &propertyName)
+{
+ QmlTimeline timeline = widget()->graphicsScene()->currentTimeline();
+ ModelNode targetNode = target;
+ if (timeline.isValid() && targetNode.isValid()
+ && QmlObjectNode::isValidQmlObjectNode(targetNode)) {
+ executeInTransaction("TimelineView::insertKeyframe", [=, &timeline, &targetNode](){
+
+ targetNode.validId();
+
+ QmlTimelineKeyframeGroup timelineFrames(
+ timeline.keyframeGroup(targetNode, propertyName));
+
+ QTC_ASSERT(timelineFrames.isValid(), return );
+
+ const qreal frame
+ = timeline.modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
+ const QVariant value = QmlObjectNode(targetNode).instanceValue(propertyName);
+
+ timelineFrames.setValue(value, frame);
+
+ });
+ }
+}
+
+QList<QmlTimeline> TimelineView::getTimelines() const
+{
+ QList<QmlTimeline> timelines;
+
+ if (!isAttached())
+ return timelines;
+
+ for (const ModelNode &modelNode : allModelNodes()) {
+ if (QmlTimeline::isValidQmlTimeline(modelNode) && !modelNode.hasAuxiliaryData("removed@Internal")) {
+ timelines.append(modelNode);
+ }
+ }
+ return timelines;
+}
+
+QList<ModelNode> TimelineView::getAnimations(const QmlTimeline &timeline)
+{
+ if (!timeline.isValid())
+ return QList<ModelNode>();
+
+ if (isAttached()) {
+ return Utils::filtered(timeline.modelNode().directSubModelNodes(),
+ [timeline](const ModelNode &node) {
+ if (node.metaInfo().isValid() && node.hasParentProperty()
+ && (node.parentProperty().parentModelNode()
+ == timeline.modelNode()))
+ return node.metaInfo().isSubclassOf(
+ "QtQuick.Timeline.TimelineAnimation");
+ return false;
+ });
+ }
+ return {};
+}
+
+QmlTimeline TimelineView::timelineForState(const ModelNode &state) const
+{
+ QmlModelState modelState(state);
+
+ const QList<QmlTimeline> &timelines = getTimelines();
+
+ if (modelState.isBaseState()) {
+ for (const auto &timeline : timelines) {
+ if (timeline.modelNode().hasVariantProperty("enabled")
+ && timeline.modelNode().variantProperty("enabled").value().toBool())
+ return timeline;
+ }
+ return QmlTimeline();
+ }
+
+ for (const auto &timeline : timelines) {
+ if (modelState.affectsModelNode(timeline)) {
+ QmlPropertyChanges propertyChanges(modelState.propertyChanges(timeline));
+
+ if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("enabled")
+ && propertyChanges.modelNode().variantProperty("enabled").value().toBool())
+ return timeline;
+ }
+ }
+ return QmlTimeline();
+}
+
+QmlModelState TimelineView::stateForTimeline(const QmlTimeline &timeline)
+{
+ if (timeline.modelNode().hasVariantProperty("enabled")
+ && timeline.modelNode().variantProperty("enabled").value().toBool()) {
+ return QmlModelState(rootModelNode());
+ }
+
+ for (const QmlModelState &state : QmlItemNode(rootModelNode()).states().allStates()) {
+ if (timelineForState(state) == timeline)
+ return state;
+ }
+
+ return QmlModelState();
+}
+
+void TimelineView::registerActions()
+{
+ auto &actionManager = QmlDesignerPlugin::instance()->viewManager().designerActionManager();
+
+ SelectionContextPredicate timelineEnabled = [this](const SelectionContext &context) {
+ return context.singleNodeIsSelected()
+ && widget()->graphicsScene()->currentTimeline().isValid();
+ };
+
+ SelectionContextPredicate timelineHasKeyframes =
+ [this](const SelectionContext &context) {
+ auto timeline = widget()->graphicsScene()->currentTimeline();
+ return !timeline.keyframeGroupsForTarget(context.currentSingleSelectedNode()).isEmpty();
+ };
+
+ SelectionContextPredicate timelineHasClipboard = [](const SelectionContext &context) {
+ return !context.fastUpdate() && TimelineActions::clipboardContainsKeyframes();
+ };
+
+ SelectionContextOperation deleteKeyframes = [this](const SelectionContext &context) {
+ auto mutator = widget()->graphicsScene()->currentTimeline();
+ if (mutator.isValid())
+ TimelineActions::deleteAllKeyframesForTarget(context.currentSingleSelectedNode(),
+ mutator);
+ };
+
+ SelectionContextOperation insertKeyframes = [this](const SelectionContext &context) {
+ auto mutator = widget()->graphicsScene()->currentTimeline();
+ if (mutator.isValid())
+ TimelineActions::insertAllKeyframesForTarget(context.currentSingleSelectedNode(),
+ mutator);
+ };
+
+ SelectionContextOperation copyKeyframes = [this](const SelectionContext &context) {
+ auto mutator = widget()->graphicsScene()->currentTimeline();
+ if (mutator.isValid())
+ TimelineActions::copyAllKeyframesForTarget(context.currentSingleSelectedNode(), mutator);
+ };
+
+ SelectionContextOperation pasteKeyframes = [this](const SelectionContext &context) {
+ auto mutator = widget()->graphicsScene()->currentTimeline();
+ if (mutator.isValid())
+ TimelineActions::pasteKeyframesToTarget(context.currentSingleSelectedNode(), mutator);
+ };
+
+ actionManager.addDesignerAction(new ActionGroup(TimelineConstants::timelineCategoryDisplayName,
+ TimelineConstants::timelineCategory,
+ TimelineConstants::priorityTimelineCategory,
+ timelineEnabled,
+ &SelectionContextFunctors::always));
+
+ actionManager.addDesignerAction(
+ new ModelNodeContextMenuAction("commandId timeline delete",
+ TimelineConstants::timelineDeleteKeyframesDisplayName,
+ {},
+ TimelineConstants::timelineCategory,
+ QKeySequence(),
+ 160,
+ deleteKeyframes,
+ timelineHasKeyframes));
+
+ actionManager.addDesignerAction(
+ new ModelNodeContextMenuAction("commandId timeline insert",
+ TimelineConstants::timelineInsertKeyframesDisplayName,
+ {},
+ TimelineConstants::timelineCategory,
+ QKeySequence(),
+ 140,
+ insertKeyframes,
+ timelineHasKeyframes));
+
+ actionManager.addDesignerAction(
+ new ModelNodeContextMenuAction("commandId timeline copy",
+ TimelineConstants::timelineCopyKeyframesDisplayName,
+ {},
+ TimelineConstants::timelineCategory,
+ QKeySequence(),
+ 120,
+ copyKeyframes,
+ timelineHasKeyframes));
+
+ actionManager.addDesignerAction(
+ new ModelNodeContextMenuAction("commandId timeline paste",
+ TimelineConstants::timelinePasteKeyframesDisplayName,
+ {},
+ TimelineConstants::timelineCategory,
+ QKeySequence(),
+ 100,
+ pasteKeyframes,
+ timelineHasClipboard));
+}
+
+TimelineWidget *TimelineView::createWidget()
+{
+ if (!m_timelineWidget)
+ m_timelineWidget = new TimelineWidget(this);
+
+ auto *timelineContext = new TimelineContext(m_timelineWidget);
+ Core::ICore::addContextObject(timelineContext);
+
+ return m_timelineWidget;
+}
+
+WidgetInfo TimelineView::widgetInfo()
+{
+ return createWidgetInfo(createWidget(),
+ nullptr,
+ QStringLiteral("Timelines"),
+ WidgetInfo::BottomPane,
+ 0,
+ tr("Timeline"));
+}
+
+bool TimelineView::hasQtQuickTimelineImport()
+{
+ if (isAttached()) {
+ Import import = Import::createLibraryImport("QtQuick.Timeline", "1.0");
+ return model()->hasImport(import, true, true);
+ }
+
+ return false;
+}
+
+void TimelineView::ensureQtQuickTimelineImport()
+{
+ if (!hasQtQuickTimelineImport()) {
+ Import timelineImport = Import::createLibraryImport("QtQuick.Timeline", "1.0");
+ model()->changeImports({timelineImport}, {});
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineview.h b/src/plugins/qmldesigner/components/timelineeditor/timelineview.h
index 057ff3047b..057ff3047b 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineview.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineview.h
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinewidget.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
index 8a58eb7dcf..8a58eb7dcf 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinewidget.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinewidget.h b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.h
index 3fd299a88a..3fd299a88a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinewidget.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.h
diff --git a/src/plugins/qmldesigner/componentsplugin/componentsplugin.cpp b/src/plugins/qmldesigner/componentsplugin/componentsplugin.cpp
index 21c27f4d13..ab65a44162 100644
--- a/src/plugins/qmldesigner/componentsplugin/componentsplugin.cpp
+++ b/src/plugins/qmldesigner/componentsplugin/componentsplugin.cpp
@@ -36,7 +36,6 @@
namespace QmlDesigner {
-
ComponentsPlugin::ComponentsPlugin()
{
TabViewIndexModel::registerDeclarativeType();
diff --git a/src/plugins/qmldesigner/designercore/filemanager/qmlrefactoring.cpp b/src/plugins/qmldesigner/designercore/filemanager/qmlrefactoring.cpp
index 809fe37ed4..7b30dcd179 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/qmlrefactoring.cpp
+++ b/src/plugins/qmldesigner/designercore/filemanager/qmlrefactoring.cpp
@@ -111,7 +111,7 @@ bool QmlRefactoring::addProperty(int parentLocation,
const TypeName &dynamicTypeName)
{
if (parentLocation < 0)
- return false;
+ return true; /* Node is not in hierarchy, yet and operation can be ignored. */
AddPropertyVisitor visit(*textModifier, parentLocation, name, value, propertyType, m_propertyOrder, dynamicTypeName);
return visit(qmlDocument->qmlProgram());
diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h
index d32a403e5c..dcbeb5ee74 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractview.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractview.h
@@ -39,6 +39,8 @@
#include <QObject>
#include <QPointer>
+#include <functional>
+
QT_BEGIN_NAMESPACE
class QStyle;
class QToolButton;
@@ -263,6 +265,9 @@ public:
void activateTimelineRecording(const ModelNode &timeline);
void deactivateTimelineRecording();
+ using OperationBlock = std::function<void()>;
+ bool executeInTransaction(const QByteArray &identifier, const OperationBlock &lambda);
+
protected:
void setModel(Model * model);
void removeModel();
diff --git a/src/plugins/qmldesigner/designercore/include/metainforeader.h b/src/plugins/qmldesigner/designercore/include/metainforeader.h
index 20672e0e05..eb725b5f86 100644
--- a/src/plugins/qmldesigner/designercore/include/metainforeader.h
+++ b/src/plugins/qmldesigner/designercore/include/metainforeader.h
@@ -39,7 +39,6 @@ class ItemLibraryEntry;
namespace Internal {
-
class MetaInfoReader : protected QmlJS::SimpleAbstractStreamReader
{
Q_DECLARE_TR_FUNCTIONS(QmlDesigner::Internal::MetaInfoReader)
diff --git a/src/plugins/qmldesigner/designercore/include/nodehints.h b/src/plugins/qmldesigner/designercore/include/nodehints.h
index 1e8b7d99e4..7fed390ee0 100644
--- a/src/plugins/qmldesigner/designercore/include/nodehints.h
+++ b/src/plugins/qmldesigner/designercore/include/nodehints.h
@@ -64,9 +64,11 @@ public:
bool isStackedContainer() const;
bool canBeReparentedTo(const ModelNode &potenialParent);
QString indexPropertyForStackedContainer() const;
+ QStringList visibleNonDefaultProperties() const;
bool takesOverRenderingOfChildren() const;
bool visibleInNavigator() const;
bool visibleInLibrary() const;
+ QString forceNonDefaultProperty() const;
QHash<QString, QString> hints() const;
static NodeHints fromModelNode(const ModelNode &modelNode);
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index 5d2d171ae7..09daa924aa 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -85,6 +85,7 @@ public:
bool defaultPropertyIsComponent() const;
TypeName typeName() const;
+ TypeName simplifiedTypeName() const;
int majorVersion() const;
int minorVersion() const;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index f857a36432..1560ebb3ff 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -53,10 +53,15 @@ public:
static bool isItemOrWindow(const ModelNode &modelNode);
static QmlItemNode createQmlItemNode(AbstractView *view,
+ const ItemLibraryEntry &itemLibraryEntry,
+ const QPointF &position,
+ QmlItemNode parentQmlItemNode);
+
+ static QmlObjectNode createQmlObjectNode(AbstractView *view,
const ItemLibraryEntry &itemLibraryEntry,
const QPointF &position,
QmlItemNode parentQmlItemNode);
- static QmlItemNode createQmlItemNode(AbstractView *view,
+ static QmlObjectNode createQmlObjectNode(AbstractView *view,
const ItemLibraryEntry &itemLibraryEntry,
const QPointF &position,
NodeAbstractProperty parentproperty);
diff --git a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
index dc2f0732ee..da21c17cd9 100644
--- a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
+++ b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
@@ -60,7 +60,7 @@ private: // functions
void addImport(int pos, const Import &import);
void removeImport(int pos);
void parseDirectories();
- QList<QFileInfo> watchedFiles(const QString &canonicalDirPath);
+ QFileInfoList watchedFiles(const QString &canonicalDirPath);
void unregisterQmlFile(const QFileInfo &fileInfo, const QString &qualifier);
void registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier, bool addToLibrary);
Model *model() const;
diff --git a/src/plugins/qmldesigner/designercore/include/viewmanager.h b/src/plugins/qmldesigner/designercore/include/viewmanager.h
index 4673e341cc..71c869916e 100644
--- a/src/plugins/qmldesigner/designercore/include/viewmanager.h
+++ b/src/plugins/qmldesigner/designercore/include/viewmanager.h
@@ -80,7 +80,7 @@ public:
void disableWidgets();
void enableWidgets();
- void pushFileOnCrumbleBar(const Utils::FileName &fileName);
+ void pushFileOnCrumbleBar(const Utils::FilePath &fileName);
void pushInFileComponentOnCrumbleBar(const ModelNode &modelNode);
void nextFileIsCalledInternally();
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
index 609db1fe95..c0723bf751 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
@@ -143,17 +143,17 @@ NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceV
const int second = 1000;
const int waitConstant = 8 * second;
if (m_qmlPuppetEditorProcess->waitForStarted(waitConstant)) {
- connect(m_qmlPuppetEditorProcess.data(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_qmlPuppetEditorProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
m_qmlPuppetEditorProcess.data(), &QProcess::deleteLater);
qCInfo(instanceViewBenchmark) << "puppets started:" << m_benchmarkTimer.elapsed();
if (runModus == NormalModus) {
m_qmlPuppetPreviewProcess->waitForStarted(waitConstant / 2);
- connect(m_qmlPuppetPreviewProcess.data(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_qmlPuppetPreviewProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
m_qmlPuppetPreviewProcess.data(), &QProcess::deleteLater);
m_qmlPuppetRenderProcess->waitForStarted(waitConstant / 2);
- connect(m_qmlPuppetRenderProcess.data(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(m_qmlPuppetRenderProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
m_qmlPuppetRenderProcess.data(), &QProcess::deleteLater);
}
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
index d0309aacaa..60565261d2 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
@@ -29,8 +29,8 @@
#include <QPointer>
#include <QProcess>
+#include <QElapsedTimer>
#include <QFile>
-#include <QTime>
#include <QTimer>
QT_BEGIN_NAMESPACE
@@ -127,7 +127,7 @@ private:
quint32 m_thirdLastReadCommandCounter = 0;
RunModus m_runModus;
int m_synchronizeId = -1;
- QTime m_benchmarkTimer;
+ QElapsedTimer m_benchmarkTimer;
bool m_destructing = false;
};
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
index 8ab932e8b1..0959dd4a9e 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
@@ -90,7 +90,7 @@ QHash<Core::Id, PuppetCreator::PuppetType> PuppetCreator::m_qml2PuppetForKitPupp
QByteArray PuppetCreator::qtHash() const
{
- QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
+ QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitAspect::qtVersion(m_kit);
if (currentQtVersion) {
return QCryptographicHash::hash(currentQtVersion->qmakeProperty("QT_INSTALL_DATA").toUtf8(),
QCryptographicHash::Sha1)
@@ -102,7 +102,7 @@ QByteArray PuppetCreator::qtHash() const
QDateTime PuppetCreator::qtLastModified() const
{
- QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
+ QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitAspect::qtVersion(m_kit);
if (currentQtVersion)
return QFileInfo(currentQtVersion->qmakeProperty("QT_INSTALL_LIBS")).lastModified();
@@ -153,7 +153,7 @@ QString PuppetCreator::getStyleConfigFileName() const
{
#ifndef QMLDESIGNER_TEST
if (m_currentProject) {
- for (const Utils::FileName &fileName : m_currentProject->files(ProjectExplorer::Project::SourceFiles)) {
+ for (const Utils::FilePath &fileName : m_currentProject->files(ProjectExplorer::Project::SourceFiles)) {
if (fileName.fileName() == "qtquickcontrols2.conf")
return fileName.toString();
}
@@ -419,10 +419,10 @@ QProcessEnvironment PuppetCreator::processEnvironment() const
Utils::Environment environment = Utils::Environment::systemEnvironment();
if (!useOnlyFallbackPuppet())
m_kit->addToEnvironment(environment);
- const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(m_kit);
+ const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(m_kit);
if (QTC_GUARD(qt)) { // Kits without a Qt version should not have a puppet!
// Update PATH to include QT_HOST_BINS
- const Utils::FileName qtBinPath = qt->binPath();
+ const Utils::FilePath qtBinPath = qt->binPath();
environment.prependOrSetPath(qtBinPath.toString());
}
environment.set("QML_BAD_GUI_RENDER_LOOP", "true");
@@ -472,10 +472,15 @@ QProcessEnvironment PuppetCreator::processEnvironment() const
if (!styleConfigFileName.isEmpty())
environment.appendOrSet("QT_QUICK_CONTROLS_CONF", styleConfigFileName);
+ QStringList customFileSelectors;
+
if (m_currentProject && m_currentProject->activeTarget()) {
QStringList designerImports = m_currentProject->activeTarget()
->additionalData("QmlDesignerImportPath").toStringList();
importPaths.append(designerImports);
+
+ customFileSelectors = m_currentProject->activeTarget()
+ ->additionalData("CustomFileSelectorsData").toStringList();
}
if (m_availablePuppetType == FallbackPuppet)
@@ -483,10 +488,14 @@ QProcessEnvironment PuppetCreator::processEnvironment() const
environment.appendOrSet("QML2_IMPORT_PATH", importPaths.join(pathSep), pathSep);
+ if (!customFileSelectors.isEmpty())
+ environment.appendOrSet("QML_FILE_SELECTORS", customFileSelectors.join(","), pathSep);
+
qCInfo(puppetStart) << Q_FUNC_INFO;
qCInfo(puppetStart) << "Puppet qrc mapping" << m_qrcMapping;
qCInfo(puppetStart) << "Puppet import paths:" << importPaths;
qCInfo(puppetStart) << "Puppet environment:" << environment.toStringList();
+ qCInfo(puppetStart) << "Puppet selectors:" << customFileSelectors;
return environment.toProcessEnvironment();
}
@@ -497,18 +506,18 @@ QString PuppetCreator::buildCommand() const
m_kit->addToEnvironment(environment);
ProjectExplorer::ToolChain *toolChain
- = ProjectExplorer::ToolChainKitInformation::toolChain(m_kit,
+ = ProjectExplorer::ToolChainKitAspect::toolChain(m_kit,
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (toolChain)
- return toolChain->makeCommand(environment);
+ return toolChain->makeCommand(environment).toString();
return QString();
}
QString PuppetCreator::qmakeCommand() const
{
- QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
+ QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitAspect::qtVersion(m_kit);
if (currentQtVersion)
return currentQtVersion->qmakeCommand().toString();
@@ -595,7 +604,7 @@ static bool nonEarlyQt5Version(const QtSupport::QtVersionNumber &currentQtVersio
bool PuppetCreator::qtIsSupported() const
{
- QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
+ QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitAspect::qtVersion(m_kit);
return currentQtVersion
&& currentQtVersion->isValid()
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
index be7623323d..dcb350c448 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
@@ -51,7 +51,6 @@
namespace QmlDesigner {
-
static bool isSwipeView(const ModelNode &node)
{
if (node.metaInfo().isValid()
@@ -193,6 +192,19 @@ QString NodeHints::indexPropertyForStackedContainer() const
return Internal::evaluateExpression(expression, modelNode(), ModelNode()).toString();
}
+QStringList NodeHints::visibleNonDefaultProperties() const
+{
+ if (!isValid())
+ return {};
+
+ const QString expression = m_hints.value("visibleNonDefaultProperties");
+
+ if (expression.isEmpty())
+ return {};
+
+ return Internal::evaluateExpression(expression, modelNode(), ModelNode()).toString().split(",");
+}
+
bool NodeHints::takesOverRenderingOfChildren() const
{
if (!isValid())
@@ -214,6 +226,16 @@ bool NodeHints::visibleInLibrary() const
return evaluateBooleanExpression("visibleInLibrary", true);
}
+QString NodeHints::forceNonDefaultProperty() const
+{
+ const QString expression = m_hints.value("forceNonDefaultProperty");
+
+ if (expression.isEmpty())
+ return {};
+
+ return Internal::evaluateExpression(expression, modelNode(), ModelNode()).toString();
+}
+
QHash<QString, QString> NodeHints::hints() const
{
return m_hints;
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index 9c88cd130a..25ff950644 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -1483,6 +1483,11 @@ TypeName NodeMetaInfo::typeName() const
return m_privateData->qualfiedTypeName();
}
+TypeName NodeMetaInfo::simplifiedTypeName() const
+{
+ return typeName().split('.').constLast();
+}
+
int NodeMetaInfo::majorVersion() const
{
return m_privateData->majorVersion();
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index bc9dd3c184..85a84af9a3 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -202,8 +202,8 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
dir.setNameFilters(QStringList(s_qmlFilePattern));
dir.setFilter(QDir::Files | QDir::Readable | QDir::CaseSensitive);
- QList<QFileInfo> monitoredList = watchedFiles(canonicalDirPath);
- QList<QFileInfo> newList;
+ QFileInfoList monitoredList = watchedFiles(canonicalDirPath);
+ QFileInfoList newList;
foreach (const QFileInfo &qmlFile, dir.entryInfoList()) {
if (QFileInfo(m_filePath.toLocalFile()) == qmlFile) {
// do not parse main file
@@ -280,9 +280,9 @@ void SubComponentManager::parseFile(const QString &canonicalFilePath)
}
// dirInfo must already contain a canonical path
-QList<QFileInfo> SubComponentManager::watchedFiles(const QString &canonicalDirPath)
+QFileInfoList SubComponentManager::watchedFiles(const QString &canonicalDirPath)
{
- QList<QFileInfo> files;
+ QFileInfoList files;
foreach (const QString &monitoredFile, m_watcher.files()) {
QFileInfo fileInfo(monitoredFile);
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index 68e11782df..eb7ed16b9a 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -44,7 +44,6 @@
namespace QmlDesigner {
-
/*!
\class QmlDesigner::AbstractView
\ingroup CoreModel
@@ -617,6 +616,20 @@ void AbstractView::deactivateTimelineRecording()
model()->d->notifyCurrentTimelineChanged(ModelNode());
}
+bool AbstractView::executeInTransaction(const QByteArray &identifier, const AbstractView::OperationBlock &lambda)
+{
+ try {
+ RewriterTransaction transaction = beginRewriterTransaction(identifier);
+ lambda();
+ transaction.commit();
+ } catch (const Exception &e) {
+ e.showException();
+ return false;
+ }
+
+ return true;
+}
+
QList<ModelNode> AbstractView::allModelNodes() const
{
return toModelNodeList(model()->d->allNodes());
diff --git a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
index 161cf1f9f5..8517f9cb82 100644
--- a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
@@ -178,29 +178,23 @@ void ModelMerger::replaceModel(const ModelNode &modelNode)
view()->model()->changeImports(modelNode.model()->imports(), {});
view()->model()->setFileUrl(modelNode.model()->fileUrl());
- try {
- RewriterTransaction transaction(view()->beginRewriterTransaction(QByteArrayLiteral("ModelMerger::replaceModel")));
-
- ModelNode rootNode(view()->rootModelNode());
-
- foreach (const PropertyName &propertyName, rootNode.propertyNames())
- rootNode.removeProperty(propertyName);
-
- QHash<QString, QString> idRenamingHash;
- setupIdRenamingHash(modelNode, idRenamingHash, view());
-
- syncAuxiliaryProperties(rootNode, modelNode);
- syncVariantProperties(rootNode, modelNode);
- syncBindingProperties(rootNode, modelNode, idRenamingHash);
- syncId(rootNode, modelNode, idRenamingHash);
- syncNodeProperties(rootNode, modelNode, idRenamingHash, view());
- syncNodeListProperties(rootNode, modelNode, idRenamingHash, view());
- m_view->changeRootNodeType(modelNode.type(), modelNode.majorVersion(), modelNode.minorVersion());
-
- transaction.commit();
- } catch (const RewritingException &e) {
- qWarning() << e.description(); //silent error
- }
+ view()->executeInTransaction("ModelMerger::replaceModel", [this, modelNode](){
+ ModelNode rootNode(view()->rootModelNode());
+
+ foreach (const PropertyName &propertyName, rootNode.propertyNames())
+ rootNode.removeProperty(propertyName);
+
+ QHash<QString, QString> idRenamingHash;
+ setupIdRenamingHash(modelNode, idRenamingHash, view());
+
+ syncAuxiliaryProperties(rootNode, modelNode);
+ syncVariantProperties(rootNode, modelNode);
+ syncBindingProperties(rootNode, modelNode, idRenamingHash);
+ syncId(rootNode, modelNode, idRenamingHash);
+ syncNodeProperties(rootNode, modelNode, idRenamingHash, view());
+ syncNodeListProperties(rootNode, modelNode, idRenamingHash, view());
+ m_view->changeRootNodeType(modelNode.type(), modelNode.majorVersion(), modelNode.minorVersion());
+ });
}
} //namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp b/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
index c7a9e5aa28..ba821dd788 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlanchors.cpp
@@ -31,7 +31,6 @@
namespace QmlDesigner {
-
static PropertyName lineTypeToString(AnchorLineType lineType)
{
switch (lineType) {
@@ -162,22 +161,23 @@ void QmlAnchors::setAnchor(AnchorLineType sourceAnchorLine,
const QmlItemNode &targetQmlItemNode,
AnchorLineType targetAnchorLine)
{
- RewriterTransaction transaction = qmlItemNode().view()->beginRewriterTransaction(QByteArrayLiteral("QmlAnchors::setAnchor"));
- if (qmlItemNode().isInBaseState()) {
- if ((qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill))
- || ((qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLineCenter)))) {
- removeAnchor(sourceAnchorLine);
- }
+ qmlItemNode().view()->executeInTransaction("QmlAnchors::setAnchor", [this, sourceAnchorLine, targetQmlItemNode, targetAnchorLine](){
+ if (qmlItemNode().isInBaseState()) {
+ if ((qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill))
+ || ((qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLineCenter)))) {
+ removeAnchor(sourceAnchorLine);
+ }
- const PropertyName propertyName = anchorPropertyName(sourceAnchorLine);
- ModelNode targetModelNode = targetQmlItemNode.modelNode();
- QString targetExpression = targetModelNode.validId();
- if (targetQmlItemNode.modelNode() == qmlItemNode().modelNode().parentProperty().parentModelNode())
- targetExpression = QLatin1String("parent");
- if (sourceAnchorLine != AnchorLineCenter && sourceAnchorLine != AnchorLineFill)
- targetExpression = targetExpression + QLatin1Char('.') + QString::fromLatin1(lineTypeToString(targetAnchorLine));
- qmlItemNode().modelNode().bindingProperty(propertyName).setExpression(targetExpression);
- }
+ const PropertyName propertyName = anchorPropertyName(sourceAnchorLine);
+ ModelNode targetModelNode = targetQmlItemNode.modelNode();
+ QString targetExpression = targetModelNode.validId();
+ if (targetQmlItemNode.modelNode() == qmlItemNode().modelNode().parentProperty().parentModelNode())
+ targetExpression = QLatin1String("parent");
+ if (sourceAnchorLine != AnchorLineCenter && sourceAnchorLine != AnchorLineFill)
+ targetExpression = targetExpression + QLatin1Char('.') + QString::fromLatin1(lineTypeToString(targetAnchorLine));
+ qmlItemNode().modelNode().bindingProperty(propertyName).setExpression(targetExpression);
+ }
+ });
}
bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
@@ -316,47 +316,49 @@ AnchorLine QmlAnchors::instanceAnchor(AnchorLineType sourceAnchorLine) const
void QmlAnchors::removeAnchor(AnchorLineType sourceAnchorLine)
{
- RewriterTransaction transaction = qmlItemNode().view()->beginRewriterTransaction(QByteArrayLiteral("QmlAnchors::removeAnchor"));
- if (qmlItemNode().isInBaseState()) {
- const PropertyName propertyName = anchorPropertyName(sourceAnchorLine);
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill)) {
- qmlItemNode().modelNode().removeProperty("anchors.fill");
- qmlItemNode().modelNode().bindingProperty("anchors.top").setExpression(QLatin1String("parent.top"));
- qmlItemNode().modelNode().bindingProperty("anchors.left").setExpression(QLatin1String("parent.left"));
- qmlItemNode().modelNode().bindingProperty("anchors.bottom").setExpression(QLatin1String("parent.bottom"));
- qmlItemNode().modelNode().bindingProperty("anchors.right").setExpression(QLatin1String("parent.right"));
+ qmlItemNode().view()->executeInTransaction("QmlAnchors::removeAnchor", [this, sourceAnchorLine](){
+ if (qmlItemNode().isInBaseState()) {
+ const PropertyName propertyName = anchorPropertyName(sourceAnchorLine);
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill)) {
+ qmlItemNode().modelNode().removeProperty("anchors.fill");
+ qmlItemNode().modelNode().bindingProperty("anchors.top").setExpression(QLatin1String("parent.top"));
+ qmlItemNode().modelNode().bindingProperty("anchors.left").setExpression(QLatin1String("parent.left"));
+ qmlItemNode().modelNode().bindingProperty("anchors.bottom").setExpression(QLatin1String("parent.bottom"));
+ qmlItemNode().modelNode().bindingProperty("anchors.right").setExpression(QLatin1String("parent.right"));
+
+ } else if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLineCenter)) {
+ qmlItemNode().modelNode().removeProperty("anchors.centerIn");
+ qmlItemNode().modelNode().bindingProperty("anchors.horizontalCenter").setExpression(QLatin1String("parent.horizontalCenter"));
+ qmlItemNode().modelNode().bindingProperty("anchors.verticalCenter").setExpression(QLatin1String("parent.verticalCenter"));
+ }
- } else if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLineCenter)) {
- qmlItemNode().modelNode().removeProperty("anchors.centerIn");
- qmlItemNode().modelNode().bindingProperty("anchors.horizontalCenter").setExpression(QLatin1String("parent.horizontalCenter"));
- qmlItemNode().modelNode().bindingProperty("anchors.verticalCenter").setExpression(QLatin1String("parent.verticalCenter"));
+ qmlItemNode().modelNode().removeProperty(propertyName);
}
-
- qmlItemNode().modelNode().removeProperty(propertyName);
- }
+ });
}
void QmlAnchors::removeAnchors()
{
- RewriterTransaction transaction = qmlItemNode().view()->beginRewriterTransaction(QByteArrayLiteral("QmlAnchors::removeAnchors"));
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill"))
- qmlItemNode().modelNode().removeProperty("anchors.fill");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn"))
- qmlItemNode().modelNode().removeProperty("anchors.centerIn");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.top"))
- qmlItemNode().modelNode().removeProperty("anchors.top");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.left"))
- qmlItemNode().modelNode().removeProperty("anchors.left");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.right"))
- qmlItemNode().modelNode().removeProperty("anchors.right");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.bottom"))
- qmlItemNode().modelNode().removeProperty("anchors.bottom");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.horizontalCenter"))
- qmlItemNode().modelNode().removeProperty("anchors.horizontalCenter");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.verticalCenter"))
- qmlItemNode().modelNode().removeProperty("anchors.verticalCenter");
- if (qmlItemNode().nodeInstance().hasAnchor("anchors.baseline"))
- qmlItemNode().modelNode().removeProperty("anchors.baseline");
+ qmlItemNode().view()->executeInTransaction("QmlAnchors::removeAnchors", [this](){
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill"))
+ qmlItemNode().modelNode().removeProperty("anchors.fill");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn"))
+ qmlItemNode().modelNode().removeProperty("anchors.centerIn");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.top"))
+ qmlItemNode().modelNode().removeProperty("anchors.top");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.left"))
+ qmlItemNode().modelNode().removeProperty("anchors.left");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.right"))
+ qmlItemNode().modelNode().removeProperty("anchors.right");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.bottom"))
+ qmlItemNode().modelNode().removeProperty("anchors.bottom");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.horizontalCenter"))
+ qmlItemNode().modelNode().removeProperty("anchors.horizontalCenter");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.verticalCenter"))
+ qmlItemNode().modelNode().removeProperty("anchors.verticalCenter");
+ if (qmlItemNode().nodeInstance().hasAnchor("anchors.baseline"))
+ qmlItemNode().modelNode().removeProperty("anchors.baseline");
+ });
}
bool QmlAnchors::instanceHasAnchor(AnchorLineType sourceAnchorLine) const
@@ -533,13 +535,14 @@ void QmlAnchors::removeMargin(AnchorLineType sourceAnchorLineType)
void QmlAnchors::removeMargins()
{
- RewriterTransaction transaction = qmlItemNode().view()->beginRewriterTransaction(QByteArrayLiteral("QmlAnchors::removeMargins"));
- removeMargin(AnchorLineLeft);
- removeMargin(AnchorLineRight);
- removeMargin(AnchorLineTop);
- removeMargin(AnchorLineBottom);
- removeMargin(AnchorLineHorizontalCenter);
- removeMargin(AnchorLineVerticalCenter);
+ qmlItemNode().view()->executeInTransaction("QmlAnchors::removeMargins", [this](){
+ removeMargin(AnchorLineLeft);
+ removeMargin(AnchorLineRight);
+ removeMargin(AnchorLineTop);
+ removeMargin(AnchorLineBottom);
+ removeMargin(AnchorLineHorizontalCenter);
+ removeMargin(AnchorLineVerticalCenter);
+ });
}
void QmlAnchors::fill()
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index f02ca1ead7..65b34f1de4 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -85,8 +85,15 @@ static QmlItemNode createQmlItemNodeFromSource(AbstractView *view, const QString
return QmlItemNode();
}
+QmlItemNode QmlItemNode::createQmlItemNode(AbstractView *view,
+ const ItemLibraryEntry &itemLibraryEntry,
+ const QPointF &position,
+ QmlItemNode parentQmlItemNode)
+{
+ return QmlItemNode(createQmlObjectNode(view, itemLibraryEntry, position, parentQmlItemNode));
+}
-QmlItemNode QmlItemNode::createQmlItemNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, const QPointF &position, QmlItemNode parentQmlItemNode)
+QmlObjectNode QmlItemNode::createQmlObjectNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, const QPointF &position, QmlItemNode parentQmlItemNode)
{
if (!parentQmlItemNode.isValid())
parentQmlItemNode = QmlItemNode(view->rootModelNode());
@@ -95,16 +102,14 @@ QmlItemNode QmlItemNode::createQmlItemNode(AbstractView *view, const ItemLibrary
NodeAbstractProperty parentProperty = parentQmlItemNode.defaultNodeAbstractProperty();
- return QmlItemNode::createQmlItemNode(view, itemLibraryEntry, position, parentProperty);
+ return QmlItemNode::createQmlObjectNode(view, itemLibraryEntry, position, parentProperty);
}
-QmlItemNode QmlItemNode::createQmlItemNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, const QPointF &position, NodeAbstractProperty parentproperty)
+QmlObjectNode QmlItemNode::createQmlObjectNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, const QPointF &position, NodeAbstractProperty parentproperty)
{
- QmlItemNode newQmlItemNode;
-
- try {
- RewriterTransaction transaction = view->beginRewriterTransaction(QByteArrayLiteral("QmlItemNode::createQmlItemNode"));
+ QmlObjectNode newQmlObjectNode;
+ view->executeInTransaction("QmlItemNode::createQmlItemNode", [=, &newQmlObjectNode, &parentproperty](){
NodeMetaInfo metaInfo = view->model()->metaInfo(itemLibraryEntry.typeName());
int minorVersion = metaInfo.minorVersion();
@@ -130,34 +135,31 @@ QmlItemNode QmlItemNode::createQmlItemNode(AbstractView *view, const ItemLibrary
}
}
- newQmlItemNode = QmlItemNode(view->createModelNode(itemLibraryEntry.typeName(), majorVersion, minorVersion, propertyPairList));
+ newQmlObjectNode = QmlItemNode(view->createModelNode(itemLibraryEntry.typeName(), majorVersion, minorVersion, propertyPairList));
} else {
- newQmlItemNode = createQmlItemNodeFromSource(view, itemLibraryEntry.qmlSource(), position);
+ newQmlObjectNode = createQmlItemNodeFromSource(view, itemLibraryEntry.qmlSource(), position);
}
if (parentproperty.isValid())
- parentproperty.reparentHere(newQmlItemNode);
+ parentproperty.reparentHere(newQmlObjectNode);
- if (!newQmlItemNode.isValid())
- return newQmlItemNode;
+ if (!newQmlObjectNode.isValid())
+ return;
- newQmlItemNode.setId(view->generateNewId(itemLibraryEntry.name()));
+ newQmlObjectNode.setId(view->generateNewId(itemLibraryEntry.name()));
for (const auto &propertyBindingEntry : propertyBindingList)
- newQmlItemNode.modelNode().bindingProperty(propertyBindingEntry.first).setExpression(propertyBindingEntry.second);
+ newQmlObjectNode.modelNode().bindingProperty(propertyBindingEntry.first).setExpression(propertyBindingEntry.second);
for (const auto &propertyBindingEntry : propertyEnumList)
- newQmlItemNode.modelNode().variantProperty(propertyBindingEntry.first).setEnumeration(propertyBindingEntry.second.toUtf8());
+ newQmlObjectNode.modelNode().variantProperty(propertyBindingEntry.first).setEnumeration(propertyBindingEntry.second.toUtf8());
- Q_ASSERT(newQmlItemNode.isValid());
- }
- catch (const RewritingException &e) {
- e.showException();
- }
+ Q_ASSERT(newQmlObjectNode.isValid());
+ });
- Q_ASSERT(newQmlItemNode.isValid());
+ Q_ASSERT(newQmlObjectNode.isValid());
- return newQmlItemNode;
+ return newQmlObjectNode;
}
QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QString &imageName, const QPointF &position, QmlItemNode parentQmlItemNode)
@@ -174,10 +176,8 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QS
{
QmlItemNode newQmlItemNode;
- if (parentproperty.isValid()) {
- RewriterTransaction transaction = view->beginRewriterTransaction(QByteArrayLiteral("QmlItemNode::createQmlItemNodeFromImage"));
-
- if (view->model()->hasNodeMetaInfo("QtQuick.Image")) {
+ if (parentproperty.isValid() && view->model()->hasNodeMetaInfo("QtQuick.Image")) {
+ view->executeInTransaction("QmlItemNode::createQmlItemNodeFromImage", [=, &newQmlItemNode, &parentproperty](){
NodeMetaInfo metaInfo = view->model()->metaInfo("QtQuick.Image");
QList<QPair<PropertyName, QVariant> > propertyPairList;
propertyPairList.append({PropertyName("x"), QVariant(qRound(position.x()))});
@@ -200,8 +200,7 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QS
newQmlItemNode.modelNode().variantProperty("fillMode").setEnumeration("Image.PreserveAspectFit");
Q_ASSERT(newQmlItemNode.isValid());
- }
- Q_ASSERT(newQmlItemNode.isValid());
+ });
}
return newQmlItemNode;
diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
index 65ed482bfb..53e29b7157 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
@@ -263,7 +263,7 @@ QString QmlObjectNode::stripedTranslatableText(const PropertyName &name) const
return regularExpressionPatter.cap(2);
return instanceValue(name).toString();
}
- return modelNode().variantProperty(name).value().toString();
+ return instanceValue(name).toString();
}
QString QmlObjectNode::expression(const PropertyName &name) const
diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
index 08105bf2be..8ab244fe2b 100644
--- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
@@ -41,12 +41,10 @@ using namespace QmlDesigner::Internal;
inline static QString properColorName(const QColor &color)
{
- QString s;
if (color.alpha() == 255)
- s.sprintf("#%02x%02x%02x", color.red(), color.green(), color.blue());
+ return QString::asprintf("#%02x%02x%02x", color.red(), color.green(), color.blue());
else
- s.sprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue());
- return s;
+ return QString::asprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue());
}
inline static QString doubleToString(double d)
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 739011f092..b9b82f5714 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -48,10 +48,10 @@
#include <qmljs/qmljscheck.h>
#include <qmljs/qmljsutils.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <qmljs/qmljsqrcparser.h>
#include <qmljs/qmljsinterpreter.h>
#include <qmljs/qmljsvalueowner.h>
+#include <utils/qrcparser.h>
#include <utils/qtcassert.h>
#include <QSet>
@@ -372,6 +372,13 @@ bool smartVeryFuzzyCompare(const QVariant &value1, const QVariant &value2)
return false;
}
+bool smartColorCompare(const QVariant &value1, const QVariant &value2)
+{
+ if ((value1.type() == QVariant::Color) || (value2.type() == QVariant::Color))
+ return value1.value<QColor>().rgba() == value2.value<QColor>().rgba();
+ return false;
+}
+
bool equals(const QVariant &a, const QVariant &b)
{
if (a.canConvert<QmlDesigner::Enumeration>() && b.canConvert<QmlDesigner::Enumeration>())
@@ -380,6 +387,8 @@ bool equals(const QVariant &a, const QVariant &b)
return true;
if (smartVeryFuzzyCompare(a, b))
return true;
+ if (smartColorCompare(a, b))
+ return true;
return false;
}
@@ -457,7 +466,7 @@ public:
if (!name.isEmpty() && name != QLatin1String("."))
typeName.prepend(name + QLatin1Char('.'));
} else if (importInfo.isValid() && importInfo.type() == ImportType::QrcDirectory) {
- QString path = QrcParser::normalizedQrcDirectoryPath(importInfo.path());
+ QString path = Utils::QrcParser::normalizedQrcDirectoryPath(importInfo.path());
path = path.mid(1, path.size() - ((path.size() > 1) ? 2 : 1));
const QString name = path.replace(QLatin1Char('/'), QLatin1Char('.'));
if (!name.isEmpty())
diff --git a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
index c22ce39ad1..c2f36fad90 100644
--- a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
@@ -384,7 +384,7 @@ void ViewManager::enableWidgets()
view->enableWidget();
}
-void ViewManager::pushFileOnCrumbleBar(const Utils::FileName &fileName)
+void ViewManager::pushFileOnCrumbleBar(const Utils::FilePath &fileName)
{
crumbleBar()->pushFile(fileName);
}
diff --git a/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp b/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp
index 149a76ef51..9b319a814d 100644
--- a/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp
+++ b/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.cpp
@@ -190,7 +190,7 @@ QStandardItem *WidgetPluginPath::createModelItem()
QStandardItem *failedCategory = nullptr;
const auto end = m_plugins.end();
for (auto it = m_plugins.begin(); it != end; ++it) {
- QStandardItem *pluginItem = new QStandardItem(Utils::FileName::fromString(it->path).fileName());
+ QStandardItem *pluginItem = new QStandardItem(Utils::FilePath::fromString(it->path).fileName());
if (instance(*it)) {
pluginItem->appendRow(new QStandardItem(QString::fromUtf8(it->instanceGuard->metaObject()->className())));
pathItem->appendRow(pluginItem);
diff --git a/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.h b/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.h
index 13ad38fcd3..2ad7d554f4 100644
--- a/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.h
+++ b/src/plugins/qmldesigner/designercore/pluginmanager/widgetpluginpath.h
@@ -40,8 +40,6 @@ namespace QmlDesigner {
class IWidgetPlugin;
namespace Internal {
-
-
// Dumb plugin data structure. Note that whereas QObjects can
// casted to an interface, QPointer does not work with the
// interface class, so, we need a separate QPointer as a guard
diff --git a/src/plugins/qmldesigner/designercore/rewritertransaction.cpp b/src/plugins/qmldesigner/designercore/rewritertransaction.cpp
index 1cbe8f8cac..1bae709e0c 100644
--- a/src/plugins/qmldesigner/designercore/rewritertransaction.cpp
+++ b/src/plugins/qmldesigner/designercore/rewritertransaction.cpp
@@ -39,8 +39,6 @@
namespace QmlDesigner {
-
-
QList<QByteArray> RewriterTransaction::m_identifierList;
bool RewriterTransaction::m_activeIdentifier = qEnvironmentVariableIsSet("QML_DESIGNER_TRACE_REWRITER_TRANSACTION");
diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp
index 7df99bd59b..5870927d52 100644
--- a/src/plugins/qmldesigner/designersettings.cpp
+++ b/src/plugins/qmldesigner/designersettings.cpp
@@ -76,6 +76,7 @@ void DesignerSettings::fromSettings(QSettings *settings)
restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true);
restoreValue(settings, DesignerSettingsKey::STANDALONE_MODE, false);
restoreValue(settings, DesignerSettingsKey::ENABLE_TIMELINEVIEW, false);
+ restoreValue(settings, DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT, QStringList());
settings->endGroup();
settings->endGroup();
diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h
index bdaa22bb4b..410abc267e 100644
--- a/src/plugins/qmldesigner/designersettings.h
+++ b/src/plugins/qmldesigner/designersettings.h
@@ -65,6 +65,7 @@ const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These setti
const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */
const char STANDALONE_MODE[] = "StandAloneMode";
const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView";
+const char SIMPLE_COLOR_PALETTE_CONTENT[] = "SimpleColorPaletteContent";
}
class DesignerSettings : public QHash<QByteArray, QVariant>
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index 8bce47b012..f171c89c0f 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -435,7 +435,7 @@ void DesignModeWidget::setupNavigatorHistory(Core::IEditor *editor)
m_toolBar->setCurrentEditor(editor);
}
-void DesignModeWidget::addNavigatorHistoryEntry(const Utils::FileName &fileName)
+void DesignModeWidget::addNavigatorHistoryEntry(const Utils::FilePath &fileName)
{
if (m_navigatorHistoryCounter > 0)
m_navigatorHistory.insert(m_navigatorHistoryCounter + 1, fileName.toString());
diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h
index 0642727cbe..b446cdf2e1 100644
--- a/src/plugins/qmldesigner/designmodewidget.h
+++ b/src/plugins/qmldesigner/designmodewidget.h
@@ -95,7 +95,7 @@ private: // functions
void setup();
bool isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const;
QmlDesigner::ModelNode nodeForPosition(int cursorPos) const;
- void addNavigatorHistoryEntry(const Utils::FileName &fileName);
+ void addNavigatorHistoryEntry(const Utils::FilePath &fileName);
QWidget *createCenterWidget();
QWidget *createCrumbleBarFrame();
diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp
index 7ce3bf7c4d..d264f286cc 100644
--- a/src/plugins/qmldesigner/documentmanager.cpp
+++ b/src/plugins/qmldesigner/documentmanager.cpp
@@ -316,19 +316,19 @@ void DocumentManager::addFileToVersionControl(const QString &directoryPath, cons
}
}
-Utils::FileName DocumentManager::currentFilePath()
+Utils::FilePath DocumentManager::currentFilePath()
{
return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->fileName();
}
-Utils::FileName DocumentManager::currentProjectDirPath()
+Utils::FilePath DocumentManager::currentProjectDirPath()
{
QTC_ASSERT(QmlDesignerPlugin::instance(), return {});
if (!QmlDesignerPlugin::instance()->currentDesignDocument())
return {};
- Utils::FileName qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
+ Utils::FilePath qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName);
if (!project)
return {};
@@ -338,7 +338,7 @@ Utils::FileName DocumentManager::currentProjectDirPath()
QStringList DocumentManager::isoIconsQmakeVariableValue(const QString &proPath)
{
- ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FileName::fromString(proPath));
+ ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FilePath::fromString(proPath));
if (!node) {
qCWarning(documentManagerLog) << "No node for .pro:" << proPath;
return QStringList();
@@ -361,7 +361,7 @@ QStringList DocumentManager::isoIconsQmakeVariableValue(const QString &proPath)
bool DocumentManager::setIsoIconsQmakeVariableValue(const QString &proPath, const QStringList &value)
{
- ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FileName::fromString(proPath));
+ ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FilePath::fromString(proPath));
if (!node) {
qCWarning(documentManagerLog) << "No node for .pro:" << proPath;
return false;
@@ -389,27 +389,24 @@ bool DocumentManager::setIsoIconsQmakeVariableValue(const QString &proPath, cons
void DocumentManager::findPathToIsoProFile(bool *iconResourceFileAlreadyExists, QString *resourceFilePath,
QString *resourceFileProPath, const QString &isoIconsQrcFile)
{
- Utils::FileName qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
+ Utils::FilePath qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName);
ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(qmlFileName)->parentFolderNode();
ProjectExplorer::Node *iconQrcFileNode = nullptr;
while (node && !iconQrcFileNode) {
- qCDebug(documentManagerLog) << "Checking" << node->displayName()
- << "(" << node << static_cast<int>(node->nodeType()) << ")";
+ qCDebug(documentManagerLog) << "Checking" << node->displayName() << "(" << node << ")";
- if (node->nodeType() == ProjectExplorer::NodeType::VirtualFolder && node->displayName() == "Resources") {
+ if (node->isVirtualFolderType() && node->displayName() == "Resources") {
auto virtualFolderNode = dynamic_cast<ProjectExplorer::VirtualFolderNode*>(node);
for (int subFolderIndex = 0; subFolderIndex < virtualFolderNode->folderNodes().size() && !iconQrcFileNode; ++subFolderIndex) {
ProjectExplorer::FolderNode *subFolderNode = virtualFolderNode->folderNodes().at(subFolderIndex);
qCDebug(documentManagerLog) << "Checking if" << subFolderNode->displayName() << "("
- << subFolderNode << static_cast<int>(subFolderNode->nodeType())
- << ") is" << isoIconsQrcFile;
+ << subFolderNode << ") is" << isoIconsQrcFile;
- if (subFolderNode->nodeType() == ProjectExplorer::NodeType::Folder
- && subFolderNode->displayName() == isoIconsQrcFile) {
+ if (subFolderNode->isFolderNodeType() && subFolderNode->displayName() == isoIconsQrcFile) {
qCDebug(documentManagerLog) << "Found" << isoIconsQrcFile << "in" << virtualFolderNode->filePath();
iconQrcFileNode = subFolderNode;
@@ -443,7 +440,7 @@ void DocumentManager::findPathToIsoProFile(bool *iconResourceFileAlreadyExists,
bool DocumentManager::isoProFileSupportsAddingExistingFiles(const QString &resourceFileProPath)
{
- ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FileName::fromString(resourceFileProPath));
+ ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FilePath::fromString(resourceFileProPath));
if (!node || !node->parentFolderNode())
return false;
ProjectExplorer::ProjectNode *projectNode = node->parentFolderNode()->asProjectNode();
@@ -459,7 +456,7 @@ bool DocumentManager::isoProFileSupportsAddingExistingFiles(const QString &resou
bool DocumentManager::addResourceFileToIsoProject(const QString &resourceFileProPath, const QString &resourceFilePath)
{
- ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FileName::fromString(resourceFileProPath));
+ ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FilePath::fromString(resourceFileProPath));
if (!node || !node->parentFolderNode())
return false;
ProjectExplorer::ProjectNode *projectNode = node->parentFolderNode()->asProjectNode();
@@ -480,7 +477,7 @@ bool DocumentManager::belongsToQmakeProject()
if (!QmlDesignerPlugin::instance()->currentDesignDocument())
return false;
- Utils::FileName qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
+ Utils::FilePath qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName);
if (!project)
return false;
diff --git a/src/plugins/qmldesigner/documentmanager.h b/src/plugins/qmldesigner/documentmanager.h
index 0c5bd20043..bb3b13c9ac 100644
--- a/src/plugins/qmldesigner/documentmanager.h
+++ b/src/plugins/qmldesigner/documentmanager.h
@@ -55,8 +55,8 @@ public:
static bool createFile(const QString &filePath, const QString &contents);
static void addFileToVersionControl(const QString &directoryPath, const QString &newFilePath);
- static Utils::FileName currentFilePath();
- static Utils::FileName currentProjectDirPath();
+ static Utils::FilePath currentFilePath();
+ static Utils::FilePath currentProjectDirPath();
static QStringList isoIconsQmakeVariableValue(const QString &proPath);
static bool setIsoIconsQmakeVariableValue(const QString &proPath, const QStringList &value);
diff --git a/src/plugins/qmldesigner/qmldesigner.pro b/src/plugins/qmldesigner/qmldesigner.pro
index 039c228fe5..1986677fac 100644
--- a/src/plugins/qmldesigner/qmldesigner.pro
+++ b/src/plugins/qmldesigner/qmldesigner.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS = qmldesignerplugin.pro qtquickplugin componentsplugin
+SUBDIRS = qmldesignerplugin.pro qtquickplugin componentsplugin qmlpreviewplugin
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/backendmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/backendmodel.cpp
deleted file mode 100644
index f356788a55..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/backendmodel.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review 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/algorithm.h>
-
-#include "backendmodel.h"
-
-#include "bindingproperty.h"
-#include "connectionview.h"
-#include "exception.h"
-#include "nodemetainfo.h"
-#include "nodeproperty.h"
-#include "rewriterview.h"
-#include "rewritertransaction.h"
-
-#include "addnewbackenddialog.h"
-
-#include <coreplugin/icore.h>
-#include <utils/qtcassert.h>
-
-namespace QmlDesigner {
-
-namespace Internal {
-
-BackendModel::BackendModel(ConnectionView *parent) :
- QStandardItemModel(parent)
- ,m_connectionView(parent)
-{
- connect(this, &QStandardItemModel::dataChanged, this, &BackendModel::handleDataChanged);
-}
-
-ConnectionView *QmlDesigner::Internal::BackendModel::connectionView() const
-{
- return m_connectionView;
-}
-
-void BackendModel::resetModel()
-{
- if (!m_connectionView->model())
- return;
-
- RewriterView *rewriterView = m_connectionView->model()->rewriterView();
-
- m_lock = true;
-
- beginResetModel();
- clear();
-
- setHorizontalHeaderLabels(QStringList({ tr("Type"), tr("Name"), tr("Singleton"), tr("Local") }));
-
- ModelNode rootNode = connectionView()->rootModelNode();
-
- static const PropertyTypeList simpleTypes = {"int", "real", "color", "string"};
-
- if (rewriterView)
- for (const CppTypeData &cppTypeData : rewriterView->getCppTypes())
- if (cppTypeData.isSingleton) {
- NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(cppTypeData.typeName.toUtf8());
- if (metaInfo.isValid() && !metaInfo.isSubclassOf("QtQuick.Item")) {
- auto type = new QStandardItem(cppTypeData.typeName);
- type->setData(cppTypeData.typeName, Qt::UserRole + 1);
- type->setData(true, Qt::UserRole + 2);
- type->setEditable(false);
-
- auto name = new QStandardItem(cppTypeData.typeName);
- name->setEditable(false);
-
- QStandardItem *singletonItem = new QStandardItem("");
- singletonItem->setCheckState(Qt::Checked);
-
- singletonItem->setCheckable(true);
- singletonItem->setEnabled(false);
-
- QStandardItem *inlineItem = new QStandardItem("");
-
- inlineItem->setCheckState(Qt::Unchecked);
-
- inlineItem->setCheckable(true);
- inlineItem->setEnabled(false);
-
- appendRow({ type, name, singletonItem, inlineItem });
- }
- }
-
- if (rootNode.isValid())
- foreach (const AbstractProperty &property ,rootNode.properties())
- if (property.isDynamic() && !simpleTypes.contains(property.dynamicTypeName())) {
-
- NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(property.dynamicTypeName());
- if (metaInfo.isValid() && !metaInfo.isSubclassOf("QtQuick.Item")) {
- QStandardItem *type = new QStandardItem(QString::fromUtf8(property.dynamicTypeName()));
- type->setEditable(false);
-
- type->setData(QString::fromUtf8(property.name()), Qt::UserRole + 1);
- type->setData(false, Qt::UserRole + 2);
- QStandardItem *name = new QStandardItem(QString::fromUtf8(property.name()));
-
- QStandardItem *singletonItem = new QStandardItem("");
- singletonItem->setCheckState(Qt::Unchecked);
-
- singletonItem->setCheckable(true);
- singletonItem->setEnabled(false);
-
- QStandardItem *inlineItem = new QStandardItem("");
-
- inlineItem->setCheckState(property.isNodeProperty() ? Qt::Checked : Qt::Unchecked);
-
- inlineItem->setCheckable(true);
- inlineItem->setEnabled(false);
-
- appendRow({ type, name, singletonItem, inlineItem });
- }
- }
-
- m_lock = false;
-
- endResetModel();
-}
-
-QStringList BackendModel::possibleCppTypes() const
-{
- RewriterView *rewriterView = m_connectionView->model()->rewriterView();
-
- QStringList list;
-
- if (rewriterView)
- foreach (const CppTypeData &cppTypeData, rewriterView->getCppTypes())
- list.append(cppTypeData.typeName);
-
- return list;
-}
-
-CppTypeData BackendModel::cppTypeDataForType(const QString &typeName) const
-{
- RewriterView *rewriterView = m_connectionView->model()->rewriterView();
-
- if (!rewriterView)
- return CppTypeData();
-
- return Utils::findOr(rewriterView->getCppTypes(), CppTypeData(), [&typeName](const CppTypeData &data) {
- return typeName == data.typeName;
- });
-}
-
-void BackendModel::deletePropertyByRow(int rowNumber)
-{
- Model *model = m_connectionView->model();
- if (!model)
- return;
-
- /* singleton case remove the import */
- if (data(index(rowNumber, 0), Qt::UserRole + 1).toBool()) {
- const QString typeName = data(index(rowNumber, 0), Qt::UserRole + 1).toString();
- CppTypeData cppTypeData = cppTypeDataForType(typeName);
-
- if (cppTypeData.isSingleton) {
-
- Import import = Import::createLibraryImport(cppTypeData.importUrl, cppTypeData.versionString);
-
- try {
- if (model->hasImport(import))
- model->changeImports({}, {import});
- } catch (const Exception &e) {
- e.showException();
- }
- }
- } else {
- const QString propertyName = data(index(rowNumber, 0), Qt::UserRole + 1).toString();
-
- ModelNode modelNode = connectionView()->rootModelNode();
-
- try {
- modelNode.removeProperty(propertyName.toUtf8());
- } catch (const Exception &e) {
- e.showException();
- }
- }
-
- resetModel();
-}
-
-void BackendModel::addNewBackend()
-{
- Model *model = m_connectionView->model();
- if (!model)
- return;
-
- AddNewBackendDialog dialog(Core::ICore::mainWindow());
-
- RewriterView *rewriterView = model->rewriterView();
-
- QStringList availableTypes;
-
- if (rewriterView)
- dialog.setupPossibleTypes(Utils::filtered(rewriterView->getCppTypes(), [model](const CppTypeData &cppTypeData) {
- return !cppTypeData.isSingleton || !model->metaInfo(cppTypeData.typeName.toUtf8()).isValid();
- /* Only show singletons if the import is missing */
- }));
-
- dialog.exec();
-
- if (dialog.applied()) {
- QStringList importSplit = dialog.importString().split(" ");
- if (importSplit.count() != 2) {
- qWarning() << Q_FUNC_INFO << "invalid import" << importSplit;
- QTC_ASSERT(false, return);
- }
-
- QString typeName = dialog.type();
-
- Import import = Import::createLibraryImport(importSplit.constFirst(), importSplit.constLast());
-
- try {
-
- /* We cannot add an import and add a node from that import in a single transaction.
- * We need the import to have the meta info available.
- */
-
- if (!model->hasImport(import))
- model->changeImports({import}, {});
-
- QString propertyName = m_connectionView->generateNewId(typeName);
-
- NodeMetaInfo metaInfo = model->metaInfo(typeName.toUtf8());
-
- QTC_ASSERT(metaInfo.isValid(), return);
-
- int minorVersion = metaInfo.minorVersion();
- int majorVersion = metaInfo.majorVersion();
-
- /* Add a property for non singleton types. For singletons just adding the import is enough. */
- if (!dialog.isSingleton()) {
- RewriterTransaction transaction = m_connectionView->beginRewriterTransaction("BackendModel::addNewBackend");
-
- if (dialog.localDefinition()) {
- ModelNode newNode = m_connectionView->createModelNode(metaInfo.typeName(), majorVersion, minorVersion);
-
- m_connectionView->rootModelNode().nodeProperty(propertyName.toUtf8()).setDynamicTypeNameAndsetModelNode(
- typeName.toUtf8(), newNode);
- } else {
- m_connectionView->rootModelNode().bindingProperty(
- propertyName.toUtf8()).setDynamicTypeNameAndExpression(typeName.toUtf8(), "null");
- }
- transaction.commit();
- }
-
- } catch (const Exception &e) {
- e.showException();
- }
- }
-
- resetModel();
-}
-
-void BackendModel::updatePropertyName(int rowNumber)
-{
- const PropertyName newName = data(index(rowNumber, 1)).toString().toUtf8();
- const PropertyName oldName = data(index(rowNumber, 0), Qt::UserRole + 1).toString().toUtf8();
-
- ModelNode rootModelNode = m_connectionView->rootModelNode();
-
- try {
- RewriterTransaction transaction = m_connectionView->beginRewriterTransaction("BackendModel::updatePropertyName");
-
- if (rootModelNode.property(oldName).isNodeProperty()) {
-
- const TypeName typeName = rootModelNode.nodeProperty(oldName).dynamicTypeName();
- const ModelNode targetModelNode = rootModelNode.nodeProperty(oldName).modelNode();
- const TypeName fullTypeName = targetModelNode.type();
- const int majorVersion = targetModelNode.majorVersion();
- const int minorVersion = targetModelNode.minorVersion();
-
- rootModelNode.removeProperty(oldName);
- ModelNode newNode = m_connectionView->createModelNode(fullTypeName, majorVersion, minorVersion);
- m_connectionView->rootModelNode().nodeProperty(newName).setDynamicTypeNameAndsetModelNode(typeName, newNode);
-
- } else if (rootModelNode.property(oldName).isBindingProperty()) {
- const QString expression = rootModelNode.bindingProperty(oldName).expression();
- const TypeName typeName = rootModelNode.bindingProperty(oldName).dynamicTypeName();
-
- rootModelNode.removeProperty(oldName);
- rootModelNode.bindingProperty(newName).setDynamicTypeNameAndExpression(typeName, expression);
- } else {
- qWarning() << Q_FUNC_INFO << oldName << newName << "failed...";
- QTC_ASSERT(false, return);
- }
-
- transaction.commit();
-
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-void BackendModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
-{
- if (m_lock)
- return;
-
- if (topLeft != bottomRight) {
- qWarning() << "BackendModel::handleDataChanged multi edit?";
- return;
- }
-
- m_lock = true;
-
- int currentColumn = topLeft.column();
- int currentRow = topLeft.row();
-
- switch (currentColumn) {
- case 0: {
- //updating user data
- } break;
- case 1: {
- updatePropertyName(currentRow);
- } break;
-
- default: qWarning() << "BindingModel::handleDataChanged column" << currentColumn;
- }
-
- m_lock = false;
-}
-
-} // namespace Internal
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.cpp
deleted file mode 100644
index cd8c92b82c..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/bindingmodel.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 "bindingmodel.h"
-
-#include "connectionview.h"
-
-#include <nodemetainfo.h>
-#include <nodeproperty.h>
-#include <bindingproperty.h>
-#include <variantproperty.h>
-#include <rewritingexception.h>
-#include <rewritertransaction.h>
-
-#include <QMessageBox>
-#include <QTimer>
-
-namespace QmlDesigner {
-
-namespace Internal {
-
-BindingModel::BindingModel(ConnectionView *parent)
- : QStandardItemModel(parent)
- , m_connectionView(parent)
-{
- connect(this, &QStandardItemModel::dataChanged, this, &BindingModel::handleDataChanged);
-}
-
-void BindingModel::resetModel()
-{
- beginResetModel();
- clear();
- setHorizontalHeaderLabels(QStringList({ tr("Item"), tr("Property"), tr("Source Item"),
- tr("Source Property") }));
-
- foreach (const ModelNode modelNode, m_selectedModelNodes)
- addModelNode(modelNode);
-
- endResetModel();
-}
-
-void BindingModel::bindingChanged(const BindingProperty &bindingProperty)
-{
- m_handleDataChanged = false;
-
- QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
- if (!selectedNodes.contains(bindingProperty.parentModelNode()))
- return;
- if (!m_lock) {
- int rowNumber = findRowForBinding(bindingProperty);
-
- if (rowNumber == -1) {
- addBindingProperty(bindingProperty);
- } else {
- updateBindingProperty(rowNumber);
- }
- }
-
- m_handleDataChanged = true;
-}
-
-void BindingModel::bindingRemoved(const BindingProperty &bindingProperty)
-{
- m_handleDataChanged = false;
-
- QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
- if (!selectedNodes.contains(bindingProperty.parentModelNode()))
- return;
- if (!m_lock) {
- int rowNumber = findRowForBinding(bindingProperty);
- removeRow(rowNumber);
- }
-
- m_handleDataChanged = true;
-}
-
-void BindingModel::selectionChanged(const QList<ModelNode> &selectedNodes)
-{
- m_handleDataChanged = false;
- m_selectedModelNodes = selectedNodes;
- resetModel();
- m_handleDataChanged = true;
-}
-
-ConnectionView *BindingModel::connectionView() const
-{
- return m_connectionView;
-}
-
-BindingProperty BindingModel::bindingPropertyForRow(int rowNumber) const
-{
-
- const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
- const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
-
- ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
-
- if (modelNode.isValid())
- return modelNode.bindingProperty(targetPropertyName.toLatin1());
-
- return BindingProperty();
-}
-
-QStringList BindingModel::possibleTargetProperties(const BindingProperty &bindingProperty) const
-{
- const ModelNode modelNode = bindingProperty.parentModelNode();
-
- if (!modelNode.isValid()) {
- qWarning() << " BindingModel::possibleTargetPropertiesForRow invalid model node";
- return QStringList();
- }
-
- NodeMetaInfo metaInfo = modelNode.metaInfo();
-
- if (metaInfo.isValid()) {
- QStringList possibleProperties;
- foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
- if (metaInfo.propertyIsWritable(propertyName))
- possibleProperties << QString::fromUtf8(propertyName);
- }
-
- return possibleProperties;
- }
-
- return QStringList();
-}
-
-QStringList BindingModel::possibleSourceProperties(const BindingProperty &bindingProperty) const
-{
- const QString expression = bindingProperty.expression();
- const QStringList stringlist = expression.split(QLatin1String("."));
-
- TypeName typeName;
-
- if (bindingProperty.parentModelNode().metaInfo().isValid()) {
- typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name());
- } else {
- qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
- }
-
- const QString &id = stringlist.constFirst();
-
- ModelNode modelNode = getNodeByIdOrParent(id, bindingProperty.parentModelNode());
-
- if (!modelNode.isValid()) {
- qWarning() << " BindingModel::possibleSourcePropertiesForRow invalid model node";
- return QStringList();
- }
-
- NodeMetaInfo metaInfo = modelNode.metaInfo();
-
- QStringList possibleProperties;
-
- foreach (VariantProperty variantProperty, modelNode.variantProperties()) {
- if (variantProperty.isDynamic())
- possibleProperties << QString::fromUtf8(variantProperty.name());
- }
-
- foreach (BindingProperty bindingProperty, modelNode.bindingProperties()) {
- if (bindingProperty.isDynamic())
- possibleProperties << QString::fromUtf8((bindingProperty.name()));
- }
-
- if (metaInfo.isValid()) {
- foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
- if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
- possibleProperties << QString::fromUtf8(propertyName);
- }
- } else {
- qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node";
- }
-
- return possibleProperties;
-}
-
-void BindingModel::deleteBindindByRow(int rowNumber)
-{
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
-
- if (bindingProperty.isValid()) {
- bindingProperty.parentModelNode().removeProperty(bindingProperty.name());
- }
-
- resetModel();
-}
-
-static PropertyName unusedProperty(const ModelNode &modelNode)
-{
- PropertyName propertyName = "none";
- if (modelNode.metaInfo().isValid()) {
- foreach (const PropertyName &propertyName, modelNode.metaInfo().propertyNames()) {
- if (modelNode.metaInfo().propertyIsWritable(propertyName) && !modelNode.hasProperty(propertyName))
- return propertyName;
- }
- }
-
- return propertyName;
-}
-
-void BindingModel::addBindingForCurrentNode()
-{
- if (connectionView()->selectedModelNodes().count() == 1) {
- const ModelNode modelNode = connectionView()->selectedModelNodes().constFirst();
- if (modelNode.isValid()) {
- try {
- modelNode.bindingProperty(unusedProperty(modelNode)).setExpression(QLatin1String("none.none"));
- } catch (RewritingException &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &BindingModel::handleException);
- }
- }
- } else {
- qWarning() << " BindingModel::addBindingForCurrentNode not one node selected";
- }
-}
-
-void BindingModel::addBindingProperty(const BindingProperty &property)
-{
- QStandardItem *idItem;
- QStandardItem *targetPropertyNameItem;
- QStandardItem *sourceIdItem;
- QStandardItem *sourcePropertyNameItem;
-
- QString idLabel = property.parentModelNode().id();
- if (idLabel.isEmpty())
- idLabel = property.parentModelNode().simplifiedTypeName();
- idItem = new QStandardItem(idLabel);
- updateCustomData(idItem, property);
- targetPropertyNameItem = new QStandardItem(QString::fromUtf8(property.name()));
- QList<QStandardItem*> items;
-
- items.append(idItem);
- items.append(targetPropertyNameItem);
-
- QString sourceNodeName;
- QString sourcePropertyName;
- getExpressionStrings(property, &sourceNodeName, &sourcePropertyName);
-
- sourceIdItem = new QStandardItem(sourceNodeName);
- sourcePropertyNameItem = new QStandardItem(sourcePropertyName);
-
- items.append(sourceIdItem);
- items.append(sourcePropertyNameItem);
- appendRow(items);
-}
-
-void BindingModel::updateBindingProperty(int rowNumber)
-{
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
-
- if (bindingProperty.isValid()) {
- QString targetPropertyName = QString::fromUtf8(bindingProperty.name());
- updateDisplayRole(rowNumber, TargetPropertyNameRow, targetPropertyName);
- QString sourceNodeName;
- QString sourcePropertyName;
- getExpressionStrings(bindingProperty, &sourceNodeName, &sourcePropertyName);
- updateDisplayRole(rowNumber, SourceModelNodeRow, sourceNodeName);
- updateDisplayRole(rowNumber, SourcePropertyNameRow, sourcePropertyName);
- }
-}
-
-void BindingModel::addModelNode(const ModelNode &modelNode)
-{
- foreach (const BindingProperty &bindingProperty, modelNode.bindingProperties()) {
- addBindingProperty(bindingProperty);
- }
-}
-
-void BindingModel::updateExpression(int row)
-{
- BindingProperty bindingProperty = bindingPropertyForRow(row);
-
- const QString sourceNode = data(index(row, SourceModelNodeRow)).toString().trimmed();
- const QString sourceProperty = data(index(row, SourcePropertyNameRow)).toString().trimmed();
-
- QString expression;
- if (sourceProperty.isEmpty()) {
- expression = sourceNode;
- } else {
- expression = sourceNode + QLatin1String(".") + sourceProperty;
- }
-
- RewriterTransaction transaction =
- connectionView()->beginRewriterTransaction(QByteArrayLiteral("BindingModel::updateExpression"));
- try {
- bindingProperty.setExpression(expression.trimmed());
- transaction.commit(); //committing in the try block
- } catch (Exception &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &BindingModel::handleException);
- }
-}
-
-void BindingModel::updatePropertyName(int rowNumber)
-{
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
-
- const PropertyName newName = data(index(rowNumber, TargetPropertyNameRow)).toString().toUtf8();
- const QString expression = bindingProperty.expression();
- const PropertyName dynamicPropertyType = bindingProperty.dynamicTypeName();
- ModelNode targetNode = bindingProperty.parentModelNode();
-
- if (!newName.isEmpty()) {
- RewriterTransaction transaction =
- connectionView()->beginRewriterTransaction(QByteArrayLiteral("BindingModel::updatePropertyName"));
- try {
- if (bindingProperty.isDynamic()) {
- targetNode.bindingProperty(newName).setDynamicTypeNameAndExpression(dynamicPropertyType, expression);
- } else {
- targetNode.bindingProperty(newName).setExpression(expression);
- }
- targetNode.removeProperty(bindingProperty.name());
- transaction.commit(); //committing in the try block
- } catch (Exception &e) { //better save then sorry
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &BindingModel::handleException);
- }
-
- QStandardItem* idItem = item(rowNumber, 0);
- BindingProperty newBindingProperty = targetNode.bindingProperty(newName);
- updateCustomData(idItem, newBindingProperty);
-
- } else {
- qWarning() << "BindingModel::updatePropertyName invalid property name";
- }
-}
-
-ModelNode BindingModel::getNodeByIdOrParent(const QString &id, const ModelNode &targetNode) const
-{
- ModelNode modelNode;
-
- if (id != QLatin1String("parent")) {
- modelNode = connectionView()->modelNodeForId(id);
- } else {
- if (targetNode.hasParentProperty()) {
- modelNode = targetNode.parentProperty().parentModelNode();
- }
- }
- return modelNode;
-}
-
-void BindingModel::updateCustomData(QStandardItem *item, const BindingProperty &bindingProperty)
-{
- item->setData(bindingProperty.parentModelNode().internalId(), Qt::UserRole + 1);
- item->setData(bindingProperty.name(), Qt::UserRole + 2);
-}
-
-int BindingModel::findRowForBinding(const BindingProperty &bindingProperty)
-{
- for (int i=0; i < rowCount(); i++) {
- if (compareBindingProperties(bindingPropertyForRow(i), bindingProperty))
- return i;
- }
- //not found
- return -1;
-}
-
-bool BindingModel::getExpressionStrings(const BindingProperty &bindingProperty, QString *sourceNode, QString *sourceProperty)
-{
- //### todo we assume no expressions yet
-
- const QString expression = bindingProperty.expression();
-
- if (true) {
- const QStringList stringList = expression.split(QLatin1String("."));
-
- *sourceNode = stringList.constFirst();
-
- QString propertyName;
-
- for (int i=1; i < stringList.count(); i++) {
- propertyName += stringList.at(i);
- if (i != stringList.count() - 1)
- propertyName += QLatin1String(".");
- }
- *sourceProperty = propertyName;
- }
- return true;
-}
-
-void BindingModel::updateDisplayRole(int row, int columns, const QString &string)
-{
- QModelIndex modelIndex = index(row, columns);
- if (data(modelIndex).toString() != string)
- setData(modelIndex, string);
-}
-
-void BindingModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
-{
- if (!m_handleDataChanged)
- return;
-
- if (topLeft != bottomRight) {
- qWarning() << "BindingModel::handleDataChanged multi edit?";
- return;
- }
-
- m_lock = true;
-
- int currentColumn = topLeft.column();
- int currentRow = topLeft.row();
-
- switch (currentColumn) {
- case TargetModelNodeRow: {
- //updating user data
- } break;
- case TargetPropertyNameRow: {
- updatePropertyName(currentRow);
- } break;
- case SourceModelNodeRow: {
- updateExpression(currentRow);
- } break;
- case SourcePropertyNameRow: {
- updateExpression(currentRow);
- } break;
-
- default: qWarning() << "BindingModel::handleDataChanged column" << currentColumn;
- }
-
- m_lock = false;
-}
-
-void BindingModel::handleException()
-{
- QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
- resetModel();
-}
-
-} // namespace Internal
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp
deleted file mode 100644
index 8cd297890e..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionmodel.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "connectionmodel.h"
-#include "connectionview.h"
-
-#include <bindingproperty.h>
-#include <variantproperty.h>
-#include <signalhandlerproperty.h>
-#include <rewritertransaction.h>
-#include <nodeabstractproperty.h>
-#include <exception.h>
-#include <nodemetainfo.h>
-
-#include <QStandardItemModel>
-#include <QMessageBox>
-#include <QTableView>
-#include <QTimer>
-
-namespace {
-
-QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &propertyNameList)
-{
- QStringList stringList;
- foreach (QmlDesigner::PropertyName propertyName, propertyNameList) {
- stringList << QString::fromUtf8(propertyName);
- }
- return stringList;
-}
-
-bool isConnection(const QmlDesigner::ModelNode &modelNode)
-{
- return (modelNode.type() == "Connections"
- || modelNode.type() == "QtQuick.Connections"
- || modelNode.type() == "Qt.Connections");
-
-}
-
-} //namespace
-
-namespace QmlDesigner {
-
-namespace Internal {
-
-ConnectionModel::ConnectionModel(ConnectionView *parent)
- : QStandardItemModel(parent)
- , m_connectionView(parent)
-{
- connect(this, &QStandardItemModel::dataChanged, this, &ConnectionModel::handleDataChanged);
-}
-
-void ConnectionModel::resetModel()
-{
- beginResetModel();
- clear();
- setHorizontalHeaderLabels(QStringList({ tr("Target"), tr("Signal Handler"), tr("Action") }));
-
- if (connectionView()->isAttached()) {
- foreach (const ModelNode modelNode, connectionView()->allModelNodes())
- addModelNode(modelNode);
- }
-
- const int columnWidthTarget = connectionView()->connectionTableView()->columnWidth(0);
- connectionView()->connectionTableView()->setColumnWidth(0, columnWidthTarget - 80);
-
- endResetModel();
-}
-
-SignalHandlerProperty ConnectionModel::signalHandlerPropertyForRow(int rowNumber) const
-{
- const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
- const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
-
- ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
-
- if (modelNode.isValid())
- return modelNode.signalHandlerProperty(targetPropertyName.toUtf8());
-
- return SignalHandlerProperty();
-}
-
-void ConnectionModel::addModelNode(const ModelNode &modelNode)
-{
- if (isConnection(modelNode))
- addConnection(modelNode);
-}
-
-void ConnectionModel::addConnection(const ModelNode &modelNode)
-{
- foreach (const AbstractProperty &property, modelNode.properties()) {
- if (property.isSignalHandlerProperty() && property.name() != "target") {
- addSignalHandler(property.toSignalHandlerProperty());
- }
- }
-}
-
-void ConnectionModel::addSignalHandler(const SignalHandlerProperty &signalHandlerProperty)
-{
- QStandardItem *targetItem;
- QStandardItem *signalItem;
- QStandardItem *actionItem;
-
- QString idLabel;
-
- ModelNode connectionsModelNode = signalHandlerProperty.parentModelNode();
-
- if (connectionsModelNode.bindingProperty("target").isValid()) {
- idLabel =connectionsModelNode.bindingProperty("target").expression();
- }
-
- targetItem = new QStandardItem(idLabel);
- updateCustomData(targetItem, signalHandlerProperty);
- const QString propertyName = QString::fromUtf8(signalHandlerProperty.name());
- const QString source = signalHandlerProperty.source();
-
- signalItem = new QStandardItem(propertyName);
- QList<QStandardItem*> items;
-
- items.append(targetItem);
- items.append(signalItem);
-
- actionItem = new QStandardItem(source);
-
- items.append(actionItem);
-
- appendRow(items);
-}
-
-void ConnectionModel::removeModelNode(const ModelNode &modelNode)
-{
- if (isConnection(modelNode))
- removeConnection(modelNode);
-}
-
-void ConnectionModel::removeConnection(const ModelNode & /*modelNode*/)
-{
- Q_ASSERT_X(false, "not implemented", Q_FUNC_INFO);
-}
-
-void ConnectionModel::updateSource(int row)
-{
- SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(row);
-
- const QString sourceString = data(index(row, SourceRow)).toString();
-
- RewriterTransaction transaction =
- connectionView()->beginRewriterTransaction(QByteArrayLiteral("ConnectionModel::updateSource"));
-
- try {
- signalHandlerProperty.setSource(sourceString);
- transaction.commit();
- }
- catch (Exception &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &ConnectionModel::handleException);
- }
-
-}
-
-void ConnectionModel::updateSignalName(int rowNumber)
-{
- SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(rowNumber);
-
- const PropertyName newName = data(index(rowNumber, TargetPropertyNameRow)).toString().toUtf8();
- const QString source = signalHandlerProperty.source();
- ModelNode connectionNode = signalHandlerProperty.parentModelNode();
-
- if (!newName.isEmpty()) {
- RewriterTransaction transaction =
- connectionView()->beginRewriterTransaction(QByteArrayLiteral("ConnectionModel::updateSignalName"));
- try {
- connectionNode.signalHandlerProperty(newName).setSource(source);
- connectionNode.removeProperty(signalHandlerProperty.name());
- transaction.commit(); //committing in the try block
- } catch (Exception &e) { //better save then sorry
- QMessageBox::warning(nullptr, tr("Error"), e.description());
- }
-
- QStandardItem* idItem = item(rowNumber, 0);
- SignalHandlerProperty newSignalHandlerProperty = connectionNode.signalHandlerProperty(newName);
- updateCustomData(idItem, newSignalHandlerProperty);
-
- } else {
- qWarning() << "BindingModel::updatePropertyName invalid property name";
- }
-}
-
-void ConnectionModel::updateTargetNode(int rowNumber)
-{
- SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(rowNumber);
- const QString newTarget = data(index(rowNumber, TargetModelNodeRow)).toString();
- ModelNode connectionNode = signalHandlerProperty.parentModelNode();
-
- if (!newTarget.isEmpty()) {
- RewriterTransaction transaction =
- connectionView()->beginRewriterTransaction(QByteArrayLiteral("ConnectionModel::updateTargetNode"));
- try {
- connectionNode.bindingProperty("target").setExpression(newTarget);
- transaction.commit(); //committing in the try block
- } catch (Exception &e) { //better save then sorry
- QMessageBox::warning(nullptr, tr("Error"), e.description());
- }
-
- QStandardItem* idItem = item(rowNumber, 0);
- updateCustomData(idItem, signalHandlerProperty);
-
- } else {
- qWarning() << "BindingModel::updatePropertyName invalid target id";
- }
-}
-
-void ConnectionModel::updateCustomData(QStandardItem *item, const SignalHandlerProperty &signalHandlerProperty)
-{
- item->setData(signalHandlerProperty.parentModelNode().internalId(), Qt::UserRole + 1);
- item->setData(signalHandlerProperty.name(), Qt::UserRole + 2);
-}
-
-ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connection) const
-{
- BindingProperty bindingProperty = connection.bindingProperty("target");
-
- if (bindingProperty.isValid()) {
- if (bindingProperty.expression() == QLatin1String("parent"))
- return connection.parentProperty().parentModelNode();
- return connectionView()->modelNodeForId(bindingProperty.expression());
- }
-
- return ModelNode();
-}
-
-void ConnectionModel::addConnection()
-{
- ModelNode rootModelNode = connectionView()->rootModelNode();
-
- if (rootModelNode.isValid() && rootModelNode.metaInfo().isValid()) {
-
- NodeMetaInfo nodeMetaInfo = connectionView()->model()->metaInfo("QtQuick.Connections");
-
- if (nodeMetaInfo.isValid()) {
- RewriterTransaction transaction =
- connectionView()->beginRewriterTransaction(QByteArrayLiteral("ConnectionModel::addConnection"));
- try {
- ModelNode newNode = connectionView()->createModelNode("QtQuick.Connections",
- nodeMetaInfo.majorVersion(),
- nodeMetaInfo.minorVersion());
-
- rootModelNode.nodeAbstractProperty(rootModelNode.metaInfo().defaultPropertyName()).reparentHere(newNode);
- newNode.signalHandlerProperty("onClicked").setSource(QLatin1String("print(\"clicked\")"));
-
- if (connectionView()->selectedModelNodes().count() == 1
- && !connectionView()->selectedModelNodes().constFirst().id().isEmpty()) {
- const ModelNode selectedNode = connectionView()->selectedModelNodes().constFirst();
- newNode.bindingProperty("target").setExpression(selectedNode.id());
- } else {
- newNode.bindingProperty("target").setExpression(QLatin1String("parent"));
- }
- transaction.commit();
- } catch (Exception &e) { //better save then sorry
- QMessageBox::warning(nullptr, tr("Error"), e.description());
- }
- }
- }
-}
-
-void ConnectionModel::bindingPropertyChanged(const BindingProperty &bindingProperty)
-{
- if (isConnection(bindingProperty.parentModelNode()))
- resetModel();
-}
-
-void ConnectionModel::variantPropertyChanged(const VariantProperty &variantProperty)
-{
- if (isConnection(variantProperty.parentModelNode()))
- resetModel();
-}
-
-void ConnectionModel::deleteConnectionByRow(int currentRow)
-{
- signalHandlerPropertyForRow(currentRow).parentModelNode().destroy();
-}
-
-void ConnectionModel::handleException()
-{
- QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
- resetModel();
-}
-
-void ConnectionModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
-{
- if (topLeft != bottomRight) {
- qWarning() << "ConnectionModel::handleDataChanged multi edit?";
- return;
- }
-
- m_lock = true;
-
- int currentColumn = topLeft.column();
- int currentRow = topLeft.row();
-
- switch (currentColumn) {
- case TargetModelNodeRow: {
- updateTargetNode(currentRow);
- } break;
- case TargetPropertyNameRow: {
- updateSignalName(currentRow);
- } break;
- case SourceRow: {
- updateSource(currentRow);
- } break;
-
- default: qWarning() << "ConnectionModel::handleDataChanged column" << currentColumn;
- }
-
- m_lock = false;
-}
-
-ConnectionView *ConnectionModel::connectionView() const
-{
- return m_connectionView;
-}
-
-QStringList ConnectionModel::getSignalsForRow(int row) const
-{
- QStringList stringList;
- SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(row);
-
- if (signalHandlerProperty.isValid()) {
- stringList.append(getPossibleSignalsForConnection(signalHandlerProperty.parentModelNode()));
- }
-
- return stringList;
-}
-
-QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &connection) const
-{
- QStringList stringList;
-
- if (connection.isValid()) {
- ModelNode targetNode = getTargetNodeForConnection(connection);
- if (targetNode.isValid() && targetNode.metaInfo().isValid()) {
- stringList.append(propertyNameListToStringList(targetNode.metaInfo().signalNames()));
- }
- }
-
- return stringList;
-}
-
-} // namespace Internal
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/delegates.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/delegates.cpp
deleted file mode 100644
index 1a9958f916..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/delegates.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 "delegates.h"
-
-#include "backendmodel.h"
-#include "connectionmodel.h"
-#include "bindingmodel.h"
-#include "dynamicpropertiesmodel.h"
-#include "connectionview.h"
-
-#include <bindingproperty.h>
-
-#include <utils/qtcassert.h>
-
-#include <QStyleFactory>
-#include <QItemEditorFactory>
-#include <QDebug>
-
-namespace QmlDesigner {
-
-namespace Internal {
-
-QStringList prependOnForSignalHandler(const QStringList &signalNames)
-{
- QStringList signalHandlerNames;
- foreach (const QString &signalName, signalNames) {
- QString signalHandlerName = signalName;
- if (!signalHandlerName.isEmpty()) {
- QChar firstChar = signalHandlerName.at(0).toUpper();
- signalHandlerName[0] = firstChar;
- signalHandlerName.prepend(QLatin1String("on"));
- signalHandlerNames.append(signalHandlerName);
- }
- }
- return signalHandlerNames;
-}
-
-PropertiesComboBox::PropertiesComboBox(QWidget *parent) : QComboBox(parent)
-{
- setEditable(true);
- setValidator(new QRegularExpressionValidator(QRegularExpression(QLatin1String("[a-z|A-Z|0-9|._-]*")), this));
-}
-
-QString PropertiesComboBox::text() const
-{
- return currentText();
-}
-
-void PropertiesComboBox::setText(const QString &text)
-{
- setEditText(text);
-}
-
-void PropertiesComboBox::disableValidator()
-{
- setValidator(nullptr);
-}
-
-ConnectionComboBox::ConnectionComboBox(QWidget *parent) : PropertiesComboBox(parent)
-{
-}
-
-QString ConnectionComboBox::text() const
-{
- int index = findText(currentText());
- if (index > -1) {
- QVariant variantData = itemData(index);
- if (variantData.isValid())
- return variantData.toString();
- }
-
- return currentText();
-}
-
-ConnectionEditorDelegate::ConnectionEditorDelegate(QWidget *parent)
- : QStyledItemDelegate(parent)
-{
-}
-
-void ConnectionEditorDelegate::paint(QPainter *painter,
- const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- QStyleOptionViewItem opt = option;
- opt.state &= ~QStyle::State_HasFocus;
- QStyledItemDelegate::paint(painter, opt, index);
-}
-
-BindingDelegate::BindingDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
-{
- static QItemEditorFactory *factory = nullptr;
- if (factory == nullptr) {
- factory = new QItemEditorFactory;
- QItemEditorCreatorBase *creator
- = new QItemEditorCreator<PropertiesComboBox>("text");
- factory->registerEditor(QVariant::String, creator);
- }
-
- setItemEditorFactory(factory);
-}
-
-QWidget *BindingDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
-
- const auto model = qobject_cast<const BindingModel*>(index.model());
- if (!model) {
- qWarning() << "BindingDelegate::createEditor no model";
- return widget;
- }
- if (!model->connectionView()) {
- qWarning() << "BindingDelegate::createEditor no connection view";
- return widget;
- }
-
- model->connectionView()->allModelNodes();
-
- auto bindingComboBox = qobject_cast<PropertiesComboBox*>(widget);
- if (!bindingComboBox) {
- qWarning() << "BindingDelegate::createEditor no bindingComboBox";
- return widget;
- }
-
- BindingProperty bindingProperty = model->bindingPropertyForRow(index.row());
-
- switch (index.column()) {
- case BindingModel::TargetModelNodeRow:
- return nullptr; //no editor
- case BindingModel::TargetPropertyNameRow: {
- bindingComboBox->addItems(model->possibleTargetProperties(bindingProperty));
- } break;
- case BindingModel::SourceModelNodeRow: {
- foreach (const ModelNode &modelNode, model->connectionView()->allModelNodes()) {
- if (!modelNode.id().isEmpty()) {
- bindingComboBox->addItem(modelNode.id());
- }
- }
- if (!bindingProperty.parentModelNode().isRootNode())
- bindingComboBox->addItem(QLatin1String("parent"));
- } break;
- case BindingModel::SourcePropertyNameRow: {
- bindingComboBox->addItems(model->possibleSourceProperties(bindingProperty));
- bindingComboBox->disableValidator();
- } break;
- default: qWarning() << "BindingDelegate::createEditor column" << index.column();
- }
-
- connect(bindingComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [=]() {
- auto delegate = const_cast<BindingDelegate*>(this);
- emit delegate->commitData(bindingComboBox);
- });
-
- return widget;
-}
-
-DynamicPropertiesDelegate::DynamicPropertiesDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
-{
-// static QItemEditorFactory *factory = 0;
-// if (factory == 0) {
-// factory = new QItemEditorFactory;
-// QItemEditorCreatorBase *creator
-// = new QItemEditorCreator<DynamicPropertiesComboBox>("text");
-// factory->registerEditor(QVariant::String, creator);
-// }
-
-// setItemEditorFactory(factory);
-}
-
-QWidget *DynamicPropertiesDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
-
- const auto model = qobject_cast<const DynamicPropertiesModel*>(index.model());
- if (!model) {
- qWarning() << "BindingDelegate::createEditor no model";
- return widget;
- }
-
- if (!model->connectionView()) {
- qWarning() << "BindingDelegate::createEditor no connection view";
- return widget;
- }
- model->connectionView()->allModelNodes();
-
- switch (index.column()) {
- case DynamicPropertiesModel::TargetModelNodeRow: {
- return nullptr; //no editor
- };
- case DynamicPropertiesModel::PropertyNameRow: {
- return QStyledItemDelegate::createEditor(parent, option, index);
- };
- case DynamicPropertiesModel::PropertyTypeRow: {
-
- auto dynamicPropertiesComboBox = new PropertiesComboBox(parent);
- connect(dynamicPropertiesComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [=]() {
- auto delegate = const_cast<DynamicPropertiesDelegate*>(this);
- emit delegate->commitData(dynamicPropertiesComboBox);
- });
-
- dynamicPropertiesComboBox->addItem(QLatin1String("alias"));
- //dynamicPropertiesComboBox->addItem(QLatin1String("Item"));
- dynamicPropertiesComboBox->addItem(QLatin1String("real"));
- dynamicPropertiesComboBox->addItem(QLatin1String("int"));
- dynamicPropertiesComboBox->addItem(QLatin1String("string"));
- dynamicPropertiesComboBox->addItem(QLatin1String("bool"));
- dynamicPropertiesComboBox->addItem(QLatin1String("url"));
- dynamicPropertiesComboBox->addItem(QLatin1String("color"));
- dynamicPropertiesComboBox->addItem(QLatin1String("variant"));
- return dynamicPropertiesComboBox;
- };
- case DynamicPropertiesModel::PropertyValueRow: {
- return QStyledItemDelegate::createEditor(parent, option, index);
- };
- default: qWarning() << "BindingDelegate::createEditor column" << index.column();
- }
-
- return nullptr;
-}
-
-ConnectionDelegate::ConnectionDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
-{
- static QItemEditorFactory *factory = nullptr;
- if (factory == nullptr) {
- factory = new QItemEditorFactory;
- QItemEditorCreatorBase *creator
- = new QItemEditorCreator<ConnectionComboBox>("text");
- factory->registerEditor(QVariant::String, creator);
- }
-
- setItemEditorFactory(factory);
-}
-
-QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
-
- QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
-
- const auto connectionModel = qobject_cast<const ConnectionModel*>(index.model());
-
- auto connectionComboBox = qobject_cast<ConnectionComboBox*>(widget);
-
- if (!connectionModel) {
- qWarning() << "ConnectionDelegate::createEditor no model";
- return widget;
- }
-
- if (!connectionModel->connectionView()) {
- qWarning() << "ConnectionDelegate::createEditor no connection view";
- return widget;
- }
-
- if (!connectionComboBox) {
- qWarning() << "ConnectionDelegate::createEditor no bindingComboBox";
- return widget;
- }
-
- switch (index.column()) {
- case ConnectionModel::TargetModelNodeRow: {
- foreach (const ModelNode &modelNode, connectionModel->connectionView()->allModelNodes()) {
- if (!modelNode.id().isEmpty()) {
- connectionComboBox->addItem(modelNode.id());
- }
- }
- } break;
- case ConnectionModel::TargetPropertyNameRow: {
- connectionComboBox->addItems(prependOnForSignalHandler(connectionModel->getSignalsForRow(index.row())));
- } break;
- case ConnectionModel::SourceRow: {
- ModelNode rootModelNode = connectionModel->connectionView()->rootModelNode();
- if (QmlItemNode::isValidQmlItemNode(rootModelNode) && !rootModelNode.id().isEmpty()) {
-
- QString itemText = tr("Change to default state");
- QString source = QString::fromLatin1("{ %1.state = \"\" }").arg(rootModelNode.id());
- connectionComboBox->addItem(itemText, source);
- connectionComboBox->disableValidator();
-
- foreach (const QmlModelState &state, QmlItemNode(rootModelNode).states().allStates()) {
- QString itemText = tr("Change state to %1").arg(state.name());
- QString source = QString::fromLatin1("{ %1.state = \"%2\" }").arg(rootModelNode.id()).arg(state.name());
- connectionComboBox->addItem(itemText, source);
- }
- }
- connectionComboBox->disableValidator();
- } break;
-
- default: qWarning() << "ConnectionDelegate::createEditor column" << index.column();
- }
-
- connect(connectionComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [=]() {
- auto delegate = const_cast<ConnectionDelegate*>(this);
- emit delegate->commitData(connectionComboBox);
- });
-
- return widget;
-}
-
-BackendDelegate::BackendDelegate(QWidget *parent) : ConnectionEditorDelegate(parent)
-{
-}
-
-QWidget *BackendDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- const auto model = qobject_cast<const BackendModel*>(index.model());
-
- model->connectionView()->allModelNodes();
-
- QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
-
- QTC_ASSERT(model, return widget);
- QTC_ASSERT(model->connectionView(), return widget);
-
- switch (index.column()) {
- case BackendModel::TypeNameColumn: {
- auto backendComboBox = new PropertiesComboBox(parent);
- backendComboBox->addItems(model->possibleCppTypes());
- connect(backendComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [=]() {
- auto delegate = const_cast<BackendDelegate*>(this);
- emit delegate->commitData(backendComboBox);
- });
- return backendComboBox;
- };
- case BackendModel::PropertyNameColumn: {
- return widget;
- };
- case BackendModel::IsSingletonColumn: {
- return nullptr; //no editor
- };
- case BackendModel::IsLocalColumn: {
- return nullptr; //no editor
- };
- default: qWarning() << "BackendDelegate::createEditor column" << index.column();
- }
-
- return widget;
-}
-
-} // namesapce Internal
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp
deleted file mode 100644
index 8d4186a5b5..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/dynamicpropertiesmodel.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "dynamicpropertiesmodel.h"
-
-#include "connectionview.h"
-
-#include <nodemetainfo.h>
-#include <nodeproperty.h>
-#include <variantproperty.h>
-#include <bindingproperty.h>
-#include <rewritingexception.h>
-#include <rewritertransaction.h>
-
-#include <utils/fileutils.h>
-
-#include <QMessageBox>
-#include <QTimer>
-#include <QUrl>
-
-namespace {
-
-bool compareVariantProperties(const QmlDesigner::VariantProperty &variantProperty01, const QmlDesigner::VariantProperty &variantProperty02)
-{
- if (variantProperty01.parentModelNode() != variantProperty02.parentModelNode())
- return false;
- if (variantProperty01.name() != variantProperty02.name())
- return false;
- return true;
-}
-
-QString idOrTypeNameForNode(const QmlDesigner::ModelNode &modelNode)
-{
- QString idLabel = modelNode.id();
- if (idLabel.isEmpty())
- idLabel = modelNode.simplifiedTypeName();
-
- 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;
-
- if (typeName == "int") {
- bool ok;
- returnValue = variant.toInt(&ok);
- if (!ok)
- returnValue = 0;
- } else if (typeName == "real") {
- bool ok;
- returnValue = variant.toReal(&ok);
- if (!ok)
- returnValue = 0.0;
-
- } else if (typeName == "string") {
- returnValue = variant.toString();
-
- } else if (typeName == "bool") {
- returnValue = variant.toBool();
- } else if (typeName == "url") {
- returnValue = variant.toUrl();
- } else if (typeName == "color") {
- if (QColor::isValidColor(variant.toString())) {
- returnValue = variant.toString();
- } else {
- returnValue = QColor(Qt::black);
- }
- } else if (typeName == "Item") {
- returnValue = 0;
- }
-
- return returnValue;
-}
-
-} //internal namespace
-
-namespace QmlDesigner {
-
-namespace Internal {
-
-DynamicPropertiesModel::DynamicPropertiesModel(ConnectionView *parent)
- : QStandardItemModel(parent)
- , m_connectionView(parent)
-{
- connect(this, &QStandardItemModel::dataChanged, this, &DynamicPropertiesModel::handleDataChanged);
-}
-
-void DynamicPropertiesModel::resetModel()
-{
- beginResetModel();
- clear();
- setHorizontalHeaderLabels(QStringList({ tr("Item"), tr("Property"), tr("Property Type"),
- tr("Property Value") }));
-
- foreach (const ModelNode modelNode, m_selectedModelNodes)
- addModelNode(modelNode);
-
- endResetModel();
-}
-
-void DynamicPropertiesModel::bindingPropertyChanged(const BindingProperty &bindingProperty)
-{
- if (!bindingProperty.isDynamic())
- return;
-
- m_handleDataChanged = false;
-
- QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
- if (!selectedNodes.contains(bindingProperty.parentModelNode()))
- return;
- if (!m_lock) {
- int rowNumber = findRowForBindingProperty(bindingProperty);
-
- if (rowNumber == -1) {
- addBindingProperty(bindingProperty);
- } else {
- updateBindingProperty(rowNumber);
- }
- }
-
- m_handleDataChanged = true;
-}
-
-void DynamicPropertiesModel::variantPropertyChanged(const VariantProperty &variantProperty)
-{
- if (!variantProperty.isDynamic())
- return;
-
- m_handleDataChanged = false;
-
- QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
- if (!selectedNodes.contains(variantProperty.parentModelNode()))
- return;
- if (!m_lock) {
- int rowNumber = findRowForVariantProperty(variantProperty);
-
- if (rowNumber == -1) {
- addVariantProperty(variantProperty);
- } else {
- updateVariantProperty(rowNumber);
- }
- }
-
- m_handleDataChanged = true;
-}
-
-void DynamicPropertiesModel::bindingRemoved(const BindingProperty &bindingProperty)
-{
- m_handleDataChanged = false;
-
- QList<ModelNode> selectedNodes = connectionView()->selectedModelNodes();
- if (!selectedNodes.contains(bindingProperty.parentModelNode()))
- return;
- if (!m_lock) {
- int rowNumber = findRowForBindingProperty(bindingProperty);
- removeRow(rowNumber);
- }
-
- m_handleDataChanged = true;
-}
-
-void DynamicPropertiesModel::selectionChanged(const QList<ModelNode> &selectedNodes)
-{
- m_handleDataChanged = false;
- m_selectedModelNodes = selectedNodes;
- resetModel();
- m_handleDataChanged = true;
-}
-
-ConnectionView *DynamicPropertiesModel::connectionView() const
-{
- return m_connectionView;
-}
-
-BindingProperty DynamicPropertiesModel::bindingPropertyForRow(int rowNumber) const
-{
-
- const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
- const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
-
- ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
-
- if (modelNode.isValid())
- return modelNode.bindingProperty(targetPropertyName.toUtf8());
-
- return BindingProperty();
-}
-
-VariantProperty DynamicPropertiesModel::variantPropertyForRow(int rowNumber) const
-{
- const int internalId = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 1).toInt();
- const QString targetPropertyName = data(index(rowNumber, TargetModelNodeRow), Qt::UserRole + 2).toString();
-
- ModelNode modelNode = connectionView()->modelNodeForInternalId(internalId);
-
- if (modelNode.isValid())
- return modelNode.variantProperty(targetPropertyName.toUtf8());
-
- return VariantProperty();
-}
-
-QStringList DynamicPropertiesModel::possibleTargetProperties(const BindingProperty &bindingProperty) const
-{
- const ModelNode modelNode = bindingProperty.parentModelNode();
-
- if (!modelNode.isValid()) {
- qWarning() << " BindingModel::possibleTargetPropertiesForRow invalid model node";
- return QStringList();
- }
-
- NodeMetaInfo metaInfo = modelNode.metaInfo();
-
- if (metaInfo.isValid()) {
- QStringList possibleProperties;
- foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
- if (metaInfo.propertyIsWritable(propertyName))
- possibleProperties << QString::fromUtf8(propertyName);
- }
-
- return possibleProperties;
- }
-
- return QStringList();
-}
-
-void DynamicPropertiesModel::addDynamicPropertyForCurrentNode()
-{
- if (connectionView()->selectedModelNodes().count() == 1) {
- const ModelNode modelNode = connectionView()->selectedModelNodes().constFirst();
- if (modelNode.isValid()) {
- try {
- modelNode.variantProperty(unusedProperty(modelNode)).setDynamicTypeNameAndValue("string", QLatin1String("none.none"));
- } catch (RewritingException &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &DynamicPropertiesModel::handleException);
- }
- }
- } else {
- qWarning() << " BindingModel::addBindingForCurrentNode not one node selected";
- }
-}
-
-QStringList DynamicPropertiesModel::possibleSourceProperties(const BindingProperty &bindingProperty) const
-{
- const QString expression = bindingProperty.expression();
- const QStringList stringlist = expression.split(QLatin1String("."));
-
- PropertyName typeName;
-
- if (bindingProperty.parentModelNode().metaInfo().isValid()) {
- typeName = bindingProperty.parentModelNode().metaInfo().propertyTypeName(bindingProperty.name());
- } else {
- qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for target node";
- }
-
- const QString &id = stringlist.constFirst();
-
- ModelNode modelNode = getNodeByIdOrParent(id, bindingProperty.parentModelNode());
-
- if (!modelNode.isValid()) {
- qWarning() << " BindingModel::possibleSourcePropertiesForRow invalid model node";
- return QStringList();
- }
-
- NodeMetaInfo metaInfo = modelNode.metaInfo();
-
- if (metaInfo.isValid()) {
- QStringList possibleProperties;
- foreach (const PropertyName &propertyName, metaInfo.propertyNames()) {
- if (metaInfo.propertyTypeName(propertyName) == typeName) //### todo proper check
- possibleProperties << QString::fromUtf8(propertyName);
- }
-
- return possibleProperties;
- } else {
- qWarning() << " BindingModel::possibleSourcePropertiesForRow no meta info for source node";
- }
-
- return QStringList();
-}
-
-void DynamicPropertiesModel::deleteDynamicPropertyByRow(int rowNumber)
-{
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
- if (bindingProperty.isValid()) {
- bindingProperty.parentModelNode().removeProperty(bindingProperty.name());
- }
-
- VariantProperty variantProperty = variantPropertyForRow(rowNumber);
-
- if (variantProperty.isValid()) {
- variantProperty.parentModelNode().removeProperty(variantProperty.name());
- }
-
- resetModel();
-}
-
-void DynamicPropertiesModel::addProperty(const QVariant &propertyValue,
- const QString &propertyType,
- const AbstractProperty &abstractProperty)
-{
- QList<QStandardItem*> items;
-
- QStandardItem *idItem;
- QStandardItem *propertyNameItem;
- QStandardItem *propertyTypeItem;
- QStandardItem *propertyValueItem;
-
- idItem = new QStandardItem(idOrTypeNameForNode(abstractProperty.parentModelNode()));
- updateCustomData(idItem, abstractProperty);
-
- propertyNameItem = new QStandardItem(QString::fromUtf8(abstractProperty.name()));
-
- items.append(idItem);
- items.append(propertyNameItem);
-
-
- propertyTypeItem = new QStandardItem(propertyType);
- items.append(propertyTypeItem);
-
- propertyValueItem = new QStandardItem();
- propertyValueItem->setData(propertyValue, Qt::DisplayRole);
- items.append(propertyValueItem);
-
- appendRow(items);
-}
-
-void DynamicPropertiesModel::addBindingProperty(const BindingProperty &property)
-{
- QVariant value = property.expression();
- QString type = QString::fromLatin1(property.dynamicTypeName());
- addProperty(value, type, property);
-}
-
-void DynamicPropertiesModel::addVariantProperty(const VariantProperty &property)
-{
- QVariant value = property.value();
- QString type = QString::fromLatin1(property.dynamicTypeName());
- addProperty(value, type, property);
-}
-
-void DynamicPropertiesModel::updateBindingProperty(int rowNumber)
-{
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
-
- if (bindingProperty.isValid()) {
- QString propertyName = QString::fromUtf8(bindingProperty.name());
- updateDisplayRole(rowNumber, PropertyNameRow, propertyName);
- QString value = bindingProperty.expression();
- QString type = QString::fromUtf8(bindingProperty.dynamicTypeName());
- updateDisplayRole(rowNumber, PropertyTypeRow, type);
- updateDisplayRole(rowNumber, PropertyValueRow, value);
- }
-}
-
-void DynamicPropertiesModel::updateVariantProperty(int rowNumber)
-{
- VariantProperty variantProperty = variantPropertyForRow(rowNumber);
-
- if (variantProperty.isValid()) {
- QString propertyName = QString::fromUtf8(variantProperty.name());
- updateDisplayRole(rowNumber, PropertyNameRow, propertyName);
- QVariant value = variantProperty.value();
- QString type = QString::fromUtf8(variantProperty.dynamicTypeName());
- updateDisplayRole(rowNumber, PropertyTypeRow, type);
-
- updateDisplayRoleFromVariant(rowNumber, PropertyValueRow, value);
- }
-}
-
-void DynamicPropertiesModel::addModelNode(const ModelNode &modelNode)
-{
- foreach (const BindingProperty &bindingProperty, modelNode.bindingProperties()) {
- if (bindingProperty.isDynamic())
- addBindingProperty(bindingProperty);
- }
-
- foreach (const VariantProperty &variantProperty, modelNode.variantProperties()) {
- if (variantProperty.isDynamic())
- addVariantProperty(variantProperty);
- }
-}
-
-void DynamicPropertiesModel::updateValue(int row)
-{
- BindingProperty bindingProperty = bindingPropertyForRow(row);
-
- if (bindingProperty.isBindingProperty()) {
- const QString expression = data(index(row, PropertyValueRow)).toString();
-
- RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updateValue"));
- try {
- bindingProperty.setDynamicTypeNameAndExpression(bindingProperty.dynamicTypeName(), expression);
- transaction.commit(); //committing in the try block
- } catch (Exception &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &DynamicPropertiesModel::handleException);
- }
- return;
- }
-
- VariantProperty variantProperty = variantPropertyForRow(row);
-
- if (variantProperty.isVariantProperty()) {
- const QVariant value = data(index(row, PropertyValueRow));
-
- RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updateValue"));
- try {
- variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(), value);
- transaction.commit(); //committing in the try block
- } catch (Exception &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &DynamicPropertiesModel::handleException);
- }
- }
-}
-
-void DynamicPropertiesModel::updatePropertyName(int rowNumber)
-{
- const PropertyName newName = data(index(rowNumber, PropertyNameRow)).toString().toUtf8();
- if (newName.isEmpty()) {
- qWarning() << "DynamicPropertiesModel::updatePropertyName invalid property name";
- return;
- }
-
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
-
- if (bindingProperty.isBindingProperty()) {
- const QString expression = bindingProperty.expression();
- const PropertyName dynamicPropertyType = bindingProperty.dynamicTypeName();
- ModelNode targetNode = bindingProperty.parentModelNode();
-
- RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updatePropertyName"));
- try {
- targetNode.bindingProperty(newName).setDynamicTypeNameAndExpression(dynamicPropertyType, expression);
- targetNode.removeProperty(bindingProperty.name());
- transaction.commit(); //committing in the try block
- } catch (Exception &e) { //better save then sorry
- QMessageBox::warning(nullptr, tr("Error"), e.description());
- }
-
- updateCustomData(rowNumber, targetNode.bindingProperty(newName));
- return;
- }
-
- VariantProperty variantProperty = variantPropertyForRow(rowNumber);
-
- if (variantProperty.isVariantProperty()) {
- const QVariant value = variantProperty.value();
- const PropertyName dynamicPropertyType = variantProperty.dynamicTypeName();
- ModelNode targetNode = variantProperty.parentModelNode();
-
- RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updatePropertyName"));
- try {
- targetNode.variantProperty(newName).setDynamicTypeNameAndValue(dynamicPropertyType, value);
- targetNode.removeProperty(variantProperty.name());
- transaction.commit(); //committing in the try block
- } catch (Exception &e) { //better save then sorry
- QMessageBox::warning(nullptr, tr("Error"), e.description());
- }
-
- updateCustomData(rowNumber, targetNode.variantProperty(newName));
- }
-}
-
-void DynamicPropertiesModel::updatePropertyType(int rowNumber)
-{
-
- const TypeName newType = data(index(rowNumber, PropertyTypeRow)).toString().toLatin1();
-
- if (newType.isEmpty()) {
- qWarning() << "DynamicPropertiesModel::updatePropertyName invalid property type";
- return;
- }
-
- BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
-
- if (bindingProperty.isBindingProperty()) {
- const QString expression = bindingProperty.expression();
- const PropertyName propertyName = bindingProperty.name();
- ModelNode targetNode = bindingProperty.parentModelNode();
-
- RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updatePropertyType"));
- try {
- targetNode.removeProperty(bindingProperty.name());
- targetNode.bindingProperty(propertyName).setDynamicTypeNameAndExpression(newType, expression);
- transaction.commit(); //committing in the try block
- } catch (Exception &e) { //better save then sorry
- QMessageBox::warning(nullptr, tr("Error"), e.description());
- }
-
- updateCustomData(rowNumber, targetNode.bindingProperty(propertyName));
- return;
- }
-
- VariantProperty variantProperty = variantPropertyForRow(rowNumber);
-
- if (variantProperty.isVariantProperty()) {
- const QVariant value = variantProperty.value();
- ModelNode targetNode = variantProperty.parentModelNode();
- const PropertyName propertyName = variantProperty.name();
-
- RewriterTransaction transaction = connectionView()->beginRewriterTransaction(QByteArrayLiteral("DynamicPropertiesModel::updatePropertyType"));
- try {
- targetNode.removeProperty(variantProperty.name());
- if (newType == "alias") { //alias properties have to be bindings
- targetNode.bindingProperty(propertyName).setDynamicTypeNameAndExpression(newType, QLatin1String("none.none"));
- } else {
- targetNode.variantProperty(propertyName).setDynamicTypeNameAndValue(newType, convertVariantForTypeName(value, newType));
- }
- transaction.commit(); //committing in the try block
- } catch (Exception &e) { //better save then sorry
- QMessageBox::warning(nullptr, tr("Error"), e.description());
- }
-
- updateCustomData(rowNumber, targetNode.variantProperty(propertyName));
-
- if (variantProperty.isVariantProperty()) {
- updateVariantProperty(rowNumber);
- } else if (bindingProperty.isBindingProperty()) {
- updateBindingProperty(rowNumber);
- }
- }
-}
-
-ModelNode DynamicPropertiesModel::getNodeByIdOrParent(const QString &id, const ModelNode &targetNode) const
-{
- ModelNode modelNode;
-
- if (id != QLatin1String("parent")) {
- modelNode = connectionView()->modelNodeForId(id);
- } else {
- if (targetNode.hasParentProperty()) {
- modelNode = targetNode.parentProperty().parentModelNode();
- }
- }
- return modelNode;
-}
-
-void DynamicPropertiesModel::updateCustomData(QStandardItem *item, const AbstractProperty &property)
-{
- item->setData(property.parentModelNode().internalId(), Qt::UserRole + 1);
- item->setData(property.name(), Qt::UserRole + 2);
-}
-
-void DynamicPropertiesModel::updateCustomData(int row, const AbstractProperty &property)
-{
- QStandardItem* idItem = item(row, 0);
- updateCustomData(idItem, property);
-}
-
-int DynamicPropertiesModel::findRowForBindingProperty(const BindingProperty &bindingProperty) const
-{
- for (int i=0; i < rowCount(); i++) {
- if (compareBindingProperties(bindingPropertyForRow(i), bindingProperty))
- return i;
- }
- //not found
- return -1;
-}
-
-int DynamicPropertiesModel::findRowForVariantProperty(const VariantProperty &variantProperty) const
-{
- for (int i=0; i < rowCount(); i++) {
- if (compareVariantProperties(variantPropertyForRow(i), variantProperty))
- return i;
- }
- //not found
- return -1;
-}
-
-bool DynamicPropertiesModel::getExpressionStrings(const BindingProperty &bindingProperty, QString *sourceNode, QString *sourceProperty)
-{
- //### todo we assume no expressions yet
-
- const QString expression = bindingProperty.expression();
-
- if (true) {
- const QStringList stringList = expression.split(QLatin1String("."));
-
- *sourceNode = stringList.constFirst();
-
- QString propertyName;
-
- for (int i=1; i < stringList.count(); i++) {
- propertyName += stringList.at(i);
- if (i != stringList.count() - 1)
- propertyName += QLatin1String(".");
- }
- *sourceProperty = propertyName;
- }
- return true;
-}
-
-void DynamicPropertiesModel::updateDisplayRole(int row, int columns, const QString &string)
-{
- QModelIndex modelIndex = index(row, columns);
- if (data(modelIndex).toString() != string)
- setData(modelIndex, string);
-}
-
-void DynamicPropertiesModel::updateDisplayRoleFromVariant(int row, int columns, const QVariant &variant)
-{
- QModelIndex modelIndex = index(row, columns);
- if (data(modelIndex) != variant)
- setData(modelIndex, variant);
-}
-
-
-void DynamicPropertiesModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
-{
- if (!m_handleDataChanged)
- return;
-
- if (topLeft != bottomRight) {
- qWarning() << "BindingModel::handleDataChanged multi edit?";
- return;
- }
-
- m_lock = true;
-
- int currentColumn = topLeft.column();
- int currentRow = topLeft.row();
-
- switch (currentColumn) {
- case TargetModelNodeRow: {
- //updating user data
- } break;
- case PropertyNameRow: {
- updatePropertyName(currentRow);
- } break;
- case PropertyTypeRow: {
- updatePropertyType(currentRow);
- } break;
- case PropertyValueRow: {
- updateValue(currentRow);
- } break;
-
- default: qWarning() << "BindingModel::handleDataChanged column" << currentColumn;
- }
-
- m_lock = false;
-}
-
-void DynamicPropertiesModel::handleException()
-{
- QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
- resetModel();
-}
-
-} // namespace Internal
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/cubicsegment.h b/src/plugins/qmldesigner/qmldesignerextension/pathtool/cubicsegment.h
deleted file mode 100644
index 260dcd2a6d..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/cubicsegment.h
+++ /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.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "controlpoint.h"
-
-#include <modelnode.h>
-
-#include <QMap>
-
-#include <QPointF>
-#include <QExplicitlySharedDataPointer>
-
-namespace QmlDesigner {
-
-
-class CubicSegmentData : public QSharedData
-{
-public:
- CubicSegmentData();
- ModelNode modelNode;
- ControlPoint firstControllPoint;
- ControlPoint secondControllPoint;
- ControlPoint thirdControllPoint;
- ControlPoint fourthControllPoint;
- QMap<QString, QVariant> attributes;
- double percent;
-};
-
-class CubicSegment
-{
- friend bool operator ==(const CubicSegment& firstCubicSegment, const CubicSegment& secondCubicSegment);
-
-public:
- CubicSegment();
-
- static CubicSegment create();
-
- void setModelNode(const ModelNode &modelNode);
- ModelNode modelNode() const;
-
- void setFirstControlPoint(const ControlPoint &firstControlPoint);
- void setFirstControlPoint(double x, double y);
- void setFirstControlPoint(const QPointF &coordiante);
-
- void setSecondControlPoint(const ControlPoint &secondControlPoint);
- void setSecondControlPoint(double x, double y);
- void setSecondControlPoint(const QPointF &coordiante);
-
- void setThirdControlPoint(const ControlPoint &thirdControlPoint);
- void setThirdControlPoint(double x, double y);
- void setThirdControlPoint(const QPointF &coordiante);
-
- void setFourthControlPoint(const ControlPoint &fourthControlPoint);
- void setFourthControlPoint(double x, double y);
- void setFourthControlPoint(const QPointF &coordiante);
-
- void setAttributes(const QMap<QString, QVariant> &attributes);
-
- void setPercent(double percent);
-
- ControlPoint firstControlPoint() const;
- ControlPoint secondControlPoint() const;
- ControlPoint thirdControlPoint() const;
- ControlPoint fourthControlPoint() const;
-
- const QMap<QString, QVariant> attributes() const;
-
- double percent() const;
-
- QList<ControlPoint> controlPoints() const;
-
- double firstControlX() const;
- double firstControlY() const;
- double secondControlX() const;
- double secondControlY() const;
- double thirdControlX() const;
- double thirdControlY() const;
- double fourthControlX() const;
- double fourthControlY() const;
- double quadraticControlX() const;
- double quadraticControlY() const;
-
- bool isValid() const;
- bool canBeConvertedToLine() const;
- bool canBeConvertedToQuad() const;
-
- QPointF sample(double t) const;
- double minimumDistance(const QPointF &pickPoint, double &t) const;
-
- QPair<CubicSegment, CubicSegment> split(double t);
-
- void makeStraightLine();
-
- void updateModelNode();
-
-private:
- QExplicitlySharedDataPointer<CubicSegmentData> d;
-};
-
-bool operator ==(const CubicSegment& firstCubicSegment, const CubicSegment& secondCubicSegment);
-QDebug operator<<(QDebug debug, const CubicSegment &cubicSegment);
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp b/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp
deleted file mode 100644
index ad5437f34e..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp
+++ /dev/null
@@ -1,980 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "pathitem.h"
-
-#include <exception.h>
-#include <nodeproperty.h>
-#include <variantproperty.h>
-#include <nodelistproperty.h>
-#include <rewritingexception.h>
-#include <rewritertransaction.h>
-#include <formeditorscene.h>
-#include <formeditorview.h>
-#include <theme.h>
-
-#include <QPainter>
-#include <QMenu>
-#include <QtDebug>
-#include <QGraphicsSceneMouseEvent>
-
-namespace QmlDesigner {
-
-PathItem::PathItem(FormEditorScene* scene)
- : m_selectionManipulator(this),
- m_lastPercent(-1.),
- m_formEditorItem(nullptr),
- m_dontUpdatePath(false)
-{
- scene->addItem(this);
- setFlag(QGraphicsItem::ItemIsMovable, false);
-}
-
-PathItem::~PathItem()
-{
- m_formEditorItem = nullptr;
-}
-
-static ModelNode pathModelNode(FormEditorItem *formEditorItem)
-{
- ModelNode modelNode = formEditorItem->qmlItemNode().modelNode();
-
- return modelNode.nodeProperty("path").modelNode();
-}
-
-using PropertyPair = QPair<PropertyName, QVariant>;
-
-void PathItem::writeLinePath(const ModelNode &pathNode, const CubicSegment &cubicSegment)
-{
- QList<PropertyPair> propertyList;
- propertyList.append(PropertyPair("x", cubicSegment.fourthControlX()));
- propertyList.append(PropertyPair("y", cubicSegment.fourthControlY()));
-
- ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathLine", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
- pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
-}
-
-void PathItem::writeQuadPath(const ModelNode &pathNode, const CubicSegment &cubicSegment)
-{
- QList<QPair<PropertyName, QVariant> > propertyList;
- propertyList.append(PropertyPair("controlX", cubicSegment.quadraticControlX()));
- propertyList.append(PropertyPair("controlY", cubicSegment.quadraticControlY()));
- propertyList.append(PropertyPair("x", cubicSegment.fourthControlX()));
- propertyList.append(PropertyPair("y", cubicSegment.fourthControlY()));
-
- ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathQuad", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
- pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
-}
-
-void PathItem::writeCubicPath(const ModelNode &pathNode, const CubicSegment &cubicSegment)
-{
- QList<QPair<PropertyName, QVariant> > propertyList;
- propertyList.append(PropertyPair("control1X", cubicSegment.secondControlX()));
- propertyList.append(PropertyPair("control1Y", cubicSegment.secondControlY()));
- propertyList.append(PropertyPair("control2X", cubicSegment.thirdControlX()));
- propertyList.append(PropertyPair("control2Y", cubicSegment.thirdControlY()));
- propertyList.append(PropertyPair("x", cubicSegment.fourthControlX()));
- propertyList.append(PropertyPair("y", cubicSegment.fourthControlY()));
-
- ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathCubic", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
- pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
-}
-
-void PathItem::writePathAttributes(const ModelNode &pathNode, const QMap<QString, QVariant> &attributes)
-{
- QMapIterator<QString, QVariant> attributesIterator(attributes);
- while (attributesIterator.hasNext()) {
- attributesIterator.next();
- QList<QPair<PropertyName, QVariant> > propertyList;
- propertyList.append(PropertyPair("name", attributesIterator.key()));
- propertyList.append(PropertyPair("value", attributesIterator.value()));
-
- ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathAttribute", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
- pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
- }
-}
-
-void PathItem::writePathPercent(const ModelNode& pathNode, double percent)
-{
- if (percent >= 0.0) {
- QList<QPair<PropertyName, QVariant> > propertyList;
- propertyList.append(PropertyPair("value", percent));
-
- ModelNode lineNode = pathNode.view()->createModelNode("QtQuick.PathPercent", pathNode.majorVersion(), pathNode.minorVersion(), propertyList);
- pathNode.nodeListProperty("pathElements").reparentHere(lineNode);
- }
-}
-
-void PathItem::writePathToProperty()
-{
- PathUpdateDisabler pathUpdateDisable(this);
-
- ModelNode pathNode = pathModelNode(formEditorItem());
-
- RewriterTransaction rewriterTransaction = pathNode.view()->beginRewriterTransaction(QByteArrayLiteral("PathItem::writePathToProperty"));
-
- QList<ModelNode> pathSegmentNodes = pathNode.nodeListProperty("pathElements").toModelNodeList();
-
- foreach (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) {
- writePathAttributes(pathNode, cubicSegment.attributes());
- writePathPercent(pathNode, cubicSegment.percent());
-
- if (cubicSegment.canBeConvertedToLine())
- writeLinePath(pathNode, cubicSegment);
- else if (cubicSegment.canBeConvertedToQuad())
- writeQuadPath(pathNode, cubicSegment);
- else
- writeCubicPath(pathNode, cubicSegment);
- }
-
- writePathAttributes(pathNode, m_lastAttributes);
- writePathPercent(pathNode, m_lastPercent);
- }
-
- rewriterTransaction.commit();
-}
-
-void PathItem::writePathAsCubicSegmentsOnly()
-{
- try {
- PathUpdateDisabler pathUpdateDisabler(this);
-
- ModelNode pathNode = pathModelNode(formEditorItem());
-
- RewriterTransaction rewriterTransaction =
- pathNode.view()->beginRewriterTransaction(QByteArrayLiteral("PathItem::writePathAsCubicSegmentsOnly"));
-
- QList<ModelNode> pathSegmentNodes = pathNode.nodeListProperty("pathElements").toModelNodeList();
-
- foreach (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) {
- writePathAttributes(pathNode, cubicSegment.attributes());
- writePathPercent(pathNode, cubicSegment.percent());
- writeCubicPath(pathNode, cubicSegment);
- }
-
- writePathAttributes(pathNode, m_lastAttributes);
- writePathPercent(pathNode, m_lastPercent);
- }
-
- rewriterTransaction.commit();
- } catch (const RewritingException &e) {
- e.showException();
- }
-}
-
-void PathItem::setFormEditorItem(FormEditorItem *formEditorItem)
-{
- m_formEditorItem = formEditorItem;
- setTransform(formEditorItem->sceneTransform());
- updatePath();
-
-// m_textEdit->setPlainText(m_formEditorItem->qmlItemNode().modelValue("path").toString());
-}
-
-static bool hasPath(FormEditorItem *formEditorItem)
-{
- ModelNode modelNode = formEditorItem->qmlItemNode().modelNode();
-
- return modelNode.hasProperty("path") && modelNode.property("path").isNodeProperty();
-}
-
-QPointF startPoint(const ModelNode &modelNode)
-{
- QPointF point;
-
- if (modelNode.hasProperty("startX"))
- point.setX(modelNode.variantProperty("startX").value().toDouble());
-
- if (modelNode.hasProperty("startY"))
- point.setY(modelNode.variantProperty("startY").value().toDouble());
-
- return point;
-}
-
-static void addCubicSegmentToPainterPath(const CubicSegment &cubicSegment, QPainterPath &painterPath)
-{
- painterPath.cubicTo(cubicSegment.secondControlPoint().coordinate(),
- cubicSegment.thirdControlPoint().coordinate(),
- cubicSegment.fourthControlPoint().coordinate());
-
-}
-
-static void drawCubicSegments(const QList<CubicSegment> &cubicSegments, QPainter *painter)
-{
- painter->save();
-
- QPainterPath curvePainterPath(cubicSegments.constFirst().firstControlPoint().coordinate());
-
- foreach (const CubicSegment &cubicSegment, cubicSegments)
- addCubicSegmentToPainterPath(cubicSegment, curvePainterPath);
-
- painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
- painter->drawPath(curvePainterPath);
-
- painter->restore();
-}
-
-static void drawControlLine(const CubicSegment &cubicSegment, QPainter *painter)
-{
- static const QPen solidPen(QColor(104, 183, 214), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
- painter->setPen(solidPen);
- painter->drawLine(cubicSegment.firstControlPoint().coordinate(),
- cubicSegment.secondControlPoint().coordinate());
-
- QVector<double> dashVector;
- dashVector.append(4);
- dashVector.append(4);
- QPen dashedPen(QColor(104, 183, 214), 1, Qt::CustomDashLine, Qt::FlatCap, Qt::MiterJoin);
- dashedPen.setDashPattern(dashVector);
- painter->setPen(dashedPen);
- painter->drawLine(cubicSegment.secondControlPoint().coordinate(),
- cubicSegment.thirdControlPoint().coordinate());
-
- painter->setPen(QPen(QColor(104, 183, 214), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
- painter->drawLine(cubicSegment.thirdControlPoint().coordinate(),
- cubicSegment.fourthControlPoint().coordinate());
-}
-
-static void drawControlLines(const QList<CubicSegment> &cubicSegments, QPainter *painter)
-{
- painter->save();
- painter->setRenderHint(QPainter::Antialiasing, false);
-
- foreach (const CubicSegment &cubicSegment, cubicSegments)
- drawControlLine(cubicSegment, painter);
-
- painter->restore();
-}
-
-static QRectF controlPointShape(-2, -2, 5, 5);
-
-static void drawControlPoint(const ControlPoint &controlPoint, const QList<ControlPoint> &selectionPoints, QPainter *painter)
-{
- static const QColor editPointColor(0, 110, 255);
- static const QColor controlVertexColor(0, 110, 255);
- static const QColor selectionPointColor(0, 255, 0);
-
- double originX = controlPoint.coordinate().x();
- double originY = controlPoint.coordinate().y();
-
- if (controlPoint.isEditPoint()) {
- if (selectionPoints.contains(controlPoint)) {
- painter->setBrush(selectionPointColor);
- painter->setPen(selectionPointColor);
- } else {
- painter->setBrush(editPointColor);
- painter->setPen(editPointColor);
- }
- painter->setRenderHint(QPainter::Antialiasing, false);
- painter->drawRect(controlPointShape.adjusted(originX -1, originY - 1, originX - 1, originY - 1));
- painter->setRenderHint(QPainter::Antialiasing, true);
- } else {
- if (selectionPoints.contains(controlPoint)) {
- painter->setBrush(selectionPointColor);
- painter->setPen(selectionPointColor);
- } else {
- painter->setBrush(controlVertexColor);
- painter->setPen(controlVertexColor);
- }
- painter->drawEllipse(controlPointShape.adjusted(originX, originY, originX, originY));
- }
-}
-
-static void drawControlPoints(const QList<ControlPoint> &controlPoints, const QList<ControlPoint> &selectionPoints, QPainter *painter)
-{
- painter->save();
-
- foreach (const ControlPoint &controlPoint, controlPoints)
- drawControlPoint(controlPoint, selectionPoints, painter);
-
- painter->restore();
-}
-
-static void drawPositionOverlay(const ControlPoint &controlPoint, QPainter *painter)
-{
- QPoint position = controlPoint.coordinate().toPoint();
- position.rx() += 3;
- position.ry() -= 3;
-
- QString postionText(QString(QLatin1String("x: %1 y: %2")).arg(controlPoint.coordinate().x()).arg(controlPoint.coordinate().y()));
- painter->drawText(position, postionText);
-}
-
-static void drawPostionOverlays(const QList<SelectionPoint> &selectedPoints, QPainter *painter)
-{
- painter->save();
- QFont font = painter->font();
- font.setPixelSize(Theme::instance()->smallFontPixelSize());
- painter->setFont(font);
- painter->setPen(QColor(0, 0, 0));
-
- foreach (const SelectionPoint &selectedPoint, selectedPoints)
- drawPositionOverlay(selectedPoint.controlPoint, painter);
-
- painter->restore();
-}
-
-static void drawMultiSelectionRectangle(const QRectF &selectionRectangle, QPainter *painter)
-{
- painter->save();
- static QColor selectionBrush(painter->pen().color());
- selectionBrush.setAlpha(50);
- painter->setRenderHint(QPainter::Antialiasing, false);
- painter->setBrush(selectionBrush);
- painter->drawRect(selectionRectangle);
- painter->restore();
-}
-
-void PathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
-{
- painter->save();
-
- painter->setRenderHint(QPainter::Antialiasing, true);
-
- if (!m_cubicSegments.isEmpty()) {
- drawCubicSegments(m_cubicSegments, painter);
- drawControlLines(m_cubicSegments, painter);
- drawControlPoints(controlPoints(), m_selectionManipulator.allControlPoints(), painter);
- drawPostionOverlays(m_selectionManipulator.singleSelectedPoints(), painter);
- if (m_selectionManipulator.isMultiSelecting())
- drawMultiSelectionRectangle(m_selectionManipulator.multiSelectionRectangle(), painter);
- }
-
- painter->restore();
-}
-
-FormEditorItem *PathItem::formEditorItem() const
-{
- return m_formEditorItem;
-}
-
-static CubicSegment createCubicSegmentForLine(const ModelNode &lineNode, const ControlPoint &startControlPoint)
-{
- CubicSegment cubicSegment = CubicSegment::create();
- cubicSegment.setModelNode(lineNode);
-
- if (lineNode.hasProperty("x")
- && lineNode.hasProperty("y")) {
-
- QPointF controlPoint0Line = startControlPoint.coordinate();
- QPointF controlPoint1Line(lineNode.variantProperty("x").value().toDouble(),
- lineNode.variantProperty("y").value().toDouble());
-
- QPointF controlPoint1Cubic = controlPoint0Line + (1./3.) * (controlPoint1Line - controlPoint0Line);
- QPointF controlPoint2Cubic = controlPoint0Line + (2./3.) * (controlPoint1Line - controlPoint0Line);
-
- cubicSegment.setFirstControlPoint(startControlPoint);
- cubicSegment.setSecondControlPoint(controlPoint1Cubic);
- cubicSegment.setThirdControlPoint(controlPoint2Cubic);
- cubicSegment.setFourthControlPoint(controlPoint1Line);
- } else {
- qWarning() << "PathLine has not all entries!";
- }
-
- return cubicSegment;
-}
-
-static CubicSegment createCubicSegmentForQuad(const ModelNode &quadNode, const ControlPoint &startControlPoint)
-{
- CubicSegment cubicSegment = CubicSegment::create();
- cubicSegment.setModelNode(quadNode);
-
- if (quadNode.hasProperty("controlX")
- && quadNode.hasProperty("controlY")
- && quadNode.hasProperty("x")
- && quadNode.hasProperty("y")) {
- QPointF controlPoint0Quad = startControlPoint.coordinate();
- QPointF controlPoint1Quad(quadNode.variantProperty("controlX").value().toDouble(),
- quadNode.variantProperty("controlY").value().toDouble());
- QPointF controlPoint2Quad(quadNode.variantProperty("x").value().toDouble(),
- quadNode.variantProperty("y").value().toDouble());
-
- QPointF controlPoint1Cubic = controlPoint0Quad + (2./3.) * (controlPoint1Quad - controlPoint0Quad);
- QPointF controlPoint2Cubic = controlPoint2Quad + (2./3.) * (controlPoint1Quad - controlPoint2Quad);
-
- cubicSegment.setFirstControlPoint(startControlPoint);
- cubicSegment.setSecondControlPoint(controlPoint1Cubic);
- cubicSegment.setThirdControlPoint(controlPoint2Cubic);
- cubicSegment.setFourthControlPoint(controlPoint2Quad);
- } else {
- qWarning() << "PathQuad has not all entries!";
- }
-
- return cubicSegment;
-}
-
-static CubicSegment createCubicSegmentForCubic(const ModelNode &cubicNode, const ControlPoint &startControlPoint)
-{
- CubicSegment cubicSegment = CubicSegment::create();
- cubicSegment.setModelNode(cubicNode);
-
- if (cubicNode.hasProperty("control1X")
- && cubicNode.hasProperty("control1Y")
- && cubicNode.hasProperty("control2X")
- && cubicNode.hasProperty("control2Y")
- && cubicNode.hasProperty("x")
- && cubicNode.hasProperty("y")) {
-
- cubicSegment.setFirstControlPoint(startControlPoint);
- cubicSegment.setSecondControlPoint(cubicNode.variantProperty("control1X").value().toDouble(),
- cubicNode.variantProperty("control1Y").value().toDouble());
- cubicSegment.setThirdControlPoint(cubicNode.variantProperty("control2X").value().toDouble(),
- cubicNode.variantProperty("control2Y").value().toDouble());
- cubicSegment.setFourthControlPoint(cubicNode.variantProperty("x").value().toDouble(),
- cubicNode.variantProperty("y").value().toDouble());
- } else {
- qWarning() << "PathCubic has not all entries!";
- }
-
- return cubicSegment;
-}
-
-static QRectF boundingRectForPath(const QList<ControlPoint> &controlPoints)
-{
- double xMinimum = 0.;
- double xMaximum = 0.;
- double yMinimum = 0.;
- double yMaximum = 0.;
-
- foreach (const ControlPoint & controlPoint, controlPoints) {
- xMinimum = qMin(xMinimum, controlPoint.coordinate().x());
- xMaximum = qMax(xMaximum, controlPoint.coordinate().x());
- yMinimum = qMin(yMinimum, controlPoint.coordinate().y());
- yMaximum = qMax(yMaximum, controlPoint.coordinate().y());
- }
-
- return QRect(xMinimum, yMinimum, xMaximum - xMinimum, yMaximum - yMinimum);
-}
-
-void PathItem::updateBoundingRect()
-{
- QRectF controlBoundingRect = boundingRectForPath(controlPoints()).adjusted(-100, -100, 200, 100);
-
- if (m_selectionManipulator.isMultiSelecting())
- controlBoundingRect = controlBoundingRect.united(m_selectionManipulator.multiSelectionRectangle());
-
- setBoundingRect(instanceBoundingRect().united(controlBoundingRect));
-}
-
-QRectF PathItem::instanceBoundingRect() const
-{
- if (formEditorItem())
- return formEditorItem()->qmlItemNode().instanceBoundingRect();
-
- return {};
-}
-
-void PathItem::readControlPoints()
-{
- ModelNode pathNode = pathModelNode(formEditorItem());
-
- m_cubicSegments.clear();
-
- if (pathNode.hasNodeListProperty("pathElements")) {
- ControlPoint firstControlPoint(startPoint(pathNode));
- firstControlPoint.setPathModelNode(pathNode);
- firstControlPoint.setPointType(StartPoint);
-
- QMap<QString, QVariant> actualAttributes;
- double percent = -1.0;
-
- foreach (const ModelNode &childNode, pathNode.nodeListProperty("pathElements").toModelNodeList()) {
-
- if (childNode.type() == "QtQuick.PathAttribute") {
- actualAttributes.insert(childNode.variantProperty("name").value().toString(), childNode.variantProperty("value").value());
- } else if (childNode.type() == "QtQuick.PathPercent") {
- percent = childNode.variantProperty("value").value().toDouble();
- } else {
- CubicSegment newCubicSegement;
-
- if (childNode.type() == "QtQuick.PathLine")
- newCubicSegement = createCubicSegmentForLine(childNode, firstControlPoint);
- else if (childNode.type() == "QtQuick.PathQuad")
- newCubicSegement = createCubicSegmentForQuad(childNode, firstControlPoint);
- else if (childNode.type() == "QtQuick.PathCubic")
- newCubicSegement = createCubicSegmentForCubic(childNode, firstControlPoint);
- else
- continue;
-
- newCubicSegement.setPercent(percent);
- newCubicSegement.setAttributes(actualAttributes);
-
- firstControlPoint = newCubicSegement.fourthControlPoint();
- qDebug() << "Can be converted to quad" << newCubicSegement.canBeConvertedToQuad();
- qDebug() << "Can be converted to line" << newCubicSegement.canBeConvertedToLine();
- m_cubicSegments.append(newCubicSegement);
- actualAttributes.clear();
- percent = -1.0;
- }
- }
-
- m_lastAttributes = actualAttributes;
- m_lastPercent = percent;
-
- if (m_cubicSegments.constFirst().firstControlPoint().coordinate() == m_cubicSegments.constLast().fourthControlPoint().coordinate()) {
- CubicSegment lastCubicSegment = m_cubicSegments.constLast();
- lastCubicSegment.setFourthControlPoint(m_cubicSegments.constFirst().firstControlPoint());
- lastCubicSegment.fourthControlPoint().setPathModelNode(pathNode);
- lastCubicSegment.fourthControlPoint().setPointType(StartAndEndPoint);
- }
- }
-}
-
-static CubicSegment getMinimumDistanceSegment(const QPointF &pickPoint, const QList<CubicSegment> &cubicSegments, double maximumDistance, double *t = nullptr)
-{
- CubicSegment minimumDistanceSegment;
- double actualMinimumDistance = maximumDistance;
-
- foreach (const CubicSegment &cubicSegment, cubicSegments) {
- double tSegment = 0.;
- double cubicSegmentMinimumDistance = cubicSegment.minimumDistance(pickPoint, tSegment);
- if (cubicSegmentMinimumDistance < actualMinimumDistance) {
- minimumDistanceSegment = cubicSegment;
- actualMinimumDistance = cubicSegmentMinimumDistance;
- if (t)
- *t = tSegment;
- }
- }
-
- return minimumDistanceSegment;
-}
-
-void PathItem::splitCubicSegment(CubicSegment &cubicSegment, double t)
-{
- QPair<CubicSegment, CubicSegment> newCubicSegmentPair = cubicSegment.split(t);
- int indexOfOldCubicSegment = m_cubicSegments.indexOf(cubicSegment);
-
- m_cubicSegments.removeAt(indexOfOldCubicSegment);
- m_cubicSegments.insert(indexOfOldCubicSegment, newCubicSegmentPair.first);
- m_cubicSegments.insert(indexOfOldCubicSegment + 1, newCubicSegmentPair.second);
-}
-
-void PathItem::closePath()
-{
- if (!m_cubicSegments.isEmpty()) {
- const CubicSegment &firstCubicSegment = m_cubicSegments.constFirst();
- CubicSegment lastCubicSegment = m_cubicSegments.constLast();
- lastCubicSegment.setFourthControlPoint(firstCubicSegment.firstControlPoint());
- writePathAsCubicSegmentsOnly();
- }
-}
-
-void PathItem::openPath()
-{
- if (!m_cubicSegments.isEmpty()) {
- const CubicSegment &firstCubicSegment = m_cubicSegments.constFirst();
- CubicSegment lastCubicSegment = m_cubicSegments.constLast();
- QPointF newEndPoint = firstCubicSegment.firstControlPoint().coordinate();
- newEndPoint.setX(newEndPoint.x() + 10.);
- lastCubicSegment.setFourthControlPoint(ControlPoint(newEndPoint));
- writePathAsCubicSegmentsOnly();
- }
-}
-
-QAction *PathItem::createClosedPathAction(QMenu *contextMenu) const
-{
- auto closedPathAction = new QAction(contextMenu);
- closedPathAction->setCheckable(true);
- closedPathAction->setChecked(isClosedPath());
- closedPathAction->setText(tr("Closed Path"));
- contextMenu->addAction(closedPathAction);
-
- if (m_cubicSegments.count() == 1)
- closedPathAction->setDisabled(true);
-
- return closedPathAction;
-}
-
-void PathItem::createGlobalContextMenu(const QPoint &menuPosition)
-{
- QMenu contextMenu;
-
- QAction *closedPathAction = createClosedPathAction(&contextMenu);
-
- QAction *activatedAction = contextMenu.exec(menuPosition);
-
- if (activatedAction == closedPathAction)
- makePathClosed(closedPathAction->isChecked());
-}
-
-void PathItem::createCubicSegmentContextMenu(CubicSegment &cubicSegment, const QPoint &menuPosition, double t)
-{
- QMenu contextMenu;
-
- auto splitSegmentAction = new QAction(&contextMenu);
- splitSegmentAction->setText(tr("Split Segment"));
- contextMenu.addAction(splitSegmentAction);
-
- auto straightLinePointAction = new QAction(&contextMenu);
- straightLinePointAction->setText(tr("Make Curve Segment Straight"));
- contextMenu.addAction(straightLinePointAction);
-
- if (m_cubicSegments.count() == 1 && isClosedPath())
- straightLinePointAction->setDisabled(true);
-
- QAction *closedPathAction = createClosedPathAction(&contextMenu);
-
- QAction *activatedAction = contextMenu.exec(menuPosition);
-
- if (activatedAction == straightLinePointAction) {
- cubicSegment.makeStraightLine();
- PathUpdateDisabler pathItemDisabler(this, PathUpdateDisabler::DontUpdatePath);
- RewriterTransaction rewriterTransaction =
- cubicSegment.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("PathItem::createCubicSegmentContextMenu"));
- cubicSegment.updateModelNode();
- rewriterTransaction.commit();
- } else if (activatedAction == splitSegmentAction) {
- splitCubicSegment(cubicSegment, t);
- writePathAsCubicSegmentsOnly();
- } else if (activatedAction == closedPathAction) {
- makePathClosed(closedPathAction->isChecked());
- }
-}
-
-
-void PathItem::createEditPointContextMenu(const ControlPoint &controlPoint, const QPoint &menuPosition)
-{
- QMenu contextMenu;
- auto removeEditPointAction = new QAction(&contextMenu);
- removeEditPointAction->setText(tr("Remove Edit Point"));
- contextMenu.addAction(removeEditPointAction);
-
- QAction *closedPathAction = createClosedPathAction(&contextMenu);
-
- if (m_cubicSegments.count() <= 1 || (m_cubicSegments.count() == 2 && isClosedPath()))
- removeEditPointAction->setDisabled(true);
-
- QAction *activatedAction = contextMenu.exec(menuPosition);
-
- if (activatedAction == removeEditPointAction)
- removeEditPoint(controlPoint);
- else if (activatedAction == closedPathAction)
- makePathClosed(closedPathAction->isChecked());
-}
-
-const QList<ControlPoint> PathItem::controlPoints() const
-{
- QList<ControlPoint> controlPointList;
- controlPointList.reserve((m_cubicSegments.count() * 4));
-
- if (!m_cubicSegments.isEmpty())
- controlPointList.append(m_cubicSegments.constFirst().firstControlPoint());
-
- foreach (const CubicSegment &cubicSegment, m_cubicSegments) {
- controlPointList.append(cubicSegment.secondControlPoint());
- controlPointList.append(cubicSegment.thirdControlPoint());
- controlPointList.append(cubicSegment.fourthControlPoint());
- }
-
- if (isClosedPath())
- controlPointList.pop_back();
-
- return controlPointList;
-}
-
-bool hasLineOrQuadPathElements(const QList<ModelNode> &modelNodes)
-{
- foreach (const ModelNode &modelNode, modelNodes) {
- if (modelNode.type() == "QtQuick.PathLine"
- || modelNode.type() == "QtQuick.PathQuad")
- return true;
- }
-
- return false;
-}
-
-void PathItem::updatePath()
-{
- if (m_dontUpdatePath)
- return;
-
- if (hasPath(formEditorItem())) {
- readControlPoints();
-
- ModelNode pathNode = pathModelNode(formEditorItem());
-
- if (hasLineOrQuadPathElements(pathNode.nodeListProperty("pathElements").toModelNodeList()))
- writePathAsCubicSegmentsOnly();
- }
-
- updateBoundingRect();
- update();
-}
-
-QRectF PathItem::boundingRect() const
-{
- return m_boundingRect;
-}
-
-void PathItem::setBoundingRect(const QRectF &boundingRect)
-{
- m_boundingRect = boundingRect;
-}
-
-static bool controlPointIsNearMousePosition(const ControlPoint &controlPoint, const QPointF &mousePosition)
-{
- QPointF distanceVector = controlPoint.coordinate() - mousePosition;
-
- if (distanceVector.manhattanLength() < 10)
- return true;
-
- return false;
-}
-
-static bool controlPointsAreNearMousePosition(const QList<ControlPoint> &controlPoints, const QPointF &mousePosition)
-{
- foreach (const ControlPoint &controlPoint, controlPoints) {
- if (controlPointIsNearMousePosition(controlPoint, mousePosition))
- return true;
- }
-
- return false;
-}
-
-static ControlPoint pickControlPoint(const QList<ControlPoint> &controlPoints, const QPointF &mousePosition)
-{
- foreach (const ControlPoint &controlPoint, controlPoints) {
- if (controlPointIsNearMousePosition(controlPoint, mousePosition))
- return controlPoint;
- }
-
- return ControlPoint();
-}
-
-void PathItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- if (m_selectionManipulator.hasMultiSelection()) {
- m_selectionManipulator.setStartPoint(event->pos());
- } else {
- ControlPoint pickedControlPoint = pickControlPoint(controlPoints(), event->pos());
-
- if (pickedControlPoint.isValid()) {
- m_selectionManipulator.addSingleControlPointSmartly(pickedControlPoint);
- m_selectionManipulator.startMoving(event->pos());
- } else {
- m_selectionManipulator.startMultiSelection(event->pos());
- }
- }
- }
-}
-
-bool hasMoveStartDistance(const QPointF &startPoint, const QPointF &updatePoint)
-{
- return (startPoint - updatePoint).manhattanLength() > 10;
-}
-
-void PathItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
-{
- if (controlPointsAreNearMousePosition(controlPoints(), event->pos()))
- setCursor(Qt::SizeAllCursor);
- else
- setCursor(Qt::ArrowCursor);
-
- PathUpdateDisabler pathUpdateDisabler(this, PathUpdateDisabler::DontUpdatePath);
- if (event->buttons().testFlag(Qt::LeftButton)) {
- if (m_selectionManipulator.isMultiSelecting()) {
- m_selectionManipulator.updateMultiSelection(event->pos());
- update();
- } else if (m_selectionManipulator.hasSingleSelection()) {
- setCursor(Qt::SizeAllCursor);
- m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
- updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
- updateBoundingRect();
- update();
- } else if (m_selectionManipulator.hasMultiSelection()) {
- setCursor(Qt::SizeAllCursor);
- if (m_selectionManipulator.isMoving()) {
- m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
- updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
- updateBoundingRect();
- update();
- } else if (hasMoveStartDistance(m_selectionManipulator.startPoint(), event->pos())) {
- m_selectionManipulator.startMoving(m_selectionManipulator.startPoint());
- m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
- updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
- updateBoundingRect();
- update();
- }
- }
- }
-}
-
-void PathItem::updatePathModelNodes(const QList<SelectionPoint> &changedPoints)
-{
- PathUpdateDisabler pathUpdateDisabler(this, PathUpdateDisabler::DontUpdatePath);
-
- try {
- RewriterTransaction rewriterTransaction =
- formEditorItem()->qmlItemNode().view()->beginRewriterTransaction(QByteArrayLiteral("PathItem::createCubicSegmentContextMenu"));
-
- foreach (SelectionPoint changedPoint, changedPoints)
- changedPoint.controlPoint.updateModelNode();
-
- rewriterTransaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-void PathItem::disablePathUpdates()
-{
- m_dontUpdatePath = true;
-}
-
-void PathItem::enablePathUpdates()
-{
- m_dontUpdatePath = false;
-}
-
-bool PathItem::pathUpdatesDisabled() const
-{
- return m_dontUpdatePath;
-}
-
-void PathItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- if (m_selectionManipulator.isMultiSelecting()) {
- m_selectionManipulator.updateMultiSelection(event->pos());
- m_selectionManipulator.endMultiSelection();
- } else if (m_selectionManipulator.hasSingleSelection()) {
- m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
- updatePathModelNodes(m_selectionManipulator.allSelectionSinglePoints());
- updateBoundingRect();
- m_selectionManipulator.clearSingleSelection();
- } else if (m_selectionManipulator.hasMultiSelection()) {
- if (m_selectionManipulator.isMoving()) {
- m_selectionManipulator.updateMoving(event->pos(), event->modifiers());
- m_selectionManipulator.endMoving();
- updatePathModelNodes(m_selectionManipulator.multiSelectedPoints());
- updateBoundingRect();
- } else {
- m_selectionManipulator.clearMultiSelection();
- }
- }
- } else if (event->button() == Qt::RightButton) {
- ControlPoint pickedControlPoint = pickControlPoint(controlPoints(), event->pos());
- if (pickedControlPoint.isEditPoint()) {
- createEditPointContextMenu(pickedControlPoint, event->screenPos());
- } else {
- double t = 0.0;
- CubicSegment minimumDistanceSegment = getMinimumDistanceSegment(event->pos(), m_cubicSegments, 20., &t);
- if (minimumDistanceSegment.isValid())
- createCubicSegmentContextMenu(minimumDistanceSegment, event->screenPos(), t);
- else
- createGlobalContextMenu(event->screenPos());
- }
- }
-
- update();
-
-}
-
-bool PathItem::isClosedPath() const
-{
- if (m_cubicSegments.isEmpty())
- return false;
-
- ControlPoint firstControlPoint = m_cubicSegments.constFirst().firstControlPoint();
- ControlPoint lastControlPoint = m_cubicSegments.constLast().fourthControlPoint();
-
- return firstControlPoint == lastControlPoint;
-}
-
-void PathItem::makePathClosed(bool pathShoudlBeClosed)
-{
- if (pathShoudlBeClosed && !isClosedPath())
- closePath();
- else if (!pathShoudlBeClosed && isClosedPath())
- openPath();
-}
-
-QList<CubicSegment> cubicSegmentsContainingControlPoint(const ControlPoint &controlPoint, const QList<CubicSegment> &allCubicSegments)
-{
- QList<CubicSegment> cubicSegmentsHasControlPoint;
-
- foreach (const CubicSegment &cubicSegment, allCubicSegments) {
- if (cubicSegment.controlPoints().contains(controlPoint))
- cubicSegmentsHasControlPoint.append(cubicSegment);
- }
-
- return cubicSegmentsHasControlPoint;
-}
-
-void PathItem::removeEditPoint(const ControlPoint &controlPoint)
-{
- QList<CubicSegment> cubicSegments = cubicSegmentsContainingControlPoint(controlPoint, m_cubicSegments);
-
- if (cubicSegments.count() == 1) {
- m_cubicSegments.removeOne(cubicSegments.constFirst());
- } else if (cubicSegments.count() == 2){
- CubicSegment mergedCubicSegment = CubicSegment::create();
- const CubicSegment &firstCubicSegment = cubicSegments.at(0);
- const CubicSegment &secondCubicSegment = cubicSegments.at(1);
- mergedCubicSegment.setFirstControlPoint(firstCubicSegment.firstControlPoint());
- mergedCubicSegment.setSecondControlPoint(firstCubicSegment.secondControlPoint());
- mergedCubicSegment.setThirdControlPoint(secondCubicSegment.thirdControlPoint());
- mergedCubicSegment.setFourthControlPoint(secondCubicSegment.fourthControlPoint());
-
- int indexOfFirstCubicSegment = m_cubicSegments.indexOf(firstCubicSegment);
- m_cubicSegments.removeAt(indexOfFirstCubicSegment);
- m_cubicSegments.removeAt(indexOfFirstCubicSegment);
- m_cubicSegments.insert(indexOfFirstCubicSegment, mergedCubicSegment);
- }
-
- writePathAsCubicSegmentsOnly();
-}
-
-PathUpdateDisabler::PathUpdateDisabler(PathItem *pathItem, PathUpdate updatePath)
- : m_pathItem(pathItem),
- m_updatePath(updatePath)
-{
- pathItem->disablePathUpdates();
-}
-
-PathUpdateDisabler::~PathUpdateDisabler()
-{
- m_pathItem->enablePathUpdates();
- if (m_updatePath == UpdatePath)
- m_pathItem->updatePath();
-}
-
-}
diff --git a/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension.pri b/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension.pri
deleted file mode 100644
index 597bd85338..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension.pri
+++ /dev/null
@@ -1,12 +0,0 @@
-DEFINES += QMLDESIGNEREXTENSION_LIBRARY
-
-INCLUDEPATH *= $$PWD
-
-# QmlDesignerExtension files
-
-include(sourcetool/sourcetool.pri)
-include(colortool/colortool.pri)
-include(texttool/texttool.pri)
-include(pathtool/pathtool.pri)
-include(timelineeditor/timelineeditor.pri)
-include(connectioneditor/connectioneditor.pri)
diff --git a/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension_global.h b/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension_global.h
deleted file mode 100644
index 82ed1b076c..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextension_global.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 <QtGlobal>
-
-#if defined(QMLDESIGNEREXTENSION_LIBRARY)
-# define QMLDESIGNEREXTENSIONSHARED_EXPORT Q_DECL_EXPORT
-#else
-# define QMLDESIGNEREXTENSIONSHARED_EXPORT Q_DECL_IMPORT
-#endif
diff --git a/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextensionconstants.h b/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextensionconstants.h
deleted file mode 100644
index 9bf41a2f54..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/qmldesignerextensionconstants.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
-
-namespace QmlDesignerExtension {
-namespace Constants {
-
-const char ACTION_ID[] = "QmlDesignerExtension.Action";
-const char MENU_ID[] = "QmlDesignerExtension.Menu";
-
-} // namespace QmlDesignerExtension
-} // namespace Constants
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvasstyledialog.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvasstyledialog.cpp
deleted file mode 100644
index f9a948fb14..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/canvasstyledialog.cpp
+++ /dev/null
@@ -1,124 +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 "canvasstyledialog.h"
-
-#include <QColorDialog>
-#include <QDoubleSpinBox>
-#include <QLabel>
-#include <QPaintEvent>
-#include <QPainter>
-#include <QVBoxLayout>
-
-namespace QmlDesigner {
-
-CanvasStyleDialog::CanvasStyleDialog(const CanvasStyle &style, QWidget *parent)
- : QDialog(parent)
- , m_aspect(new QDoubleSpinBox(this))
- , m_thinLineWidth(new QDoubleSpinBox(this))
- , m_thickLineWidth(new QDoubleSpinBox(this))
- , m_thinLineColor(new ColorControl(style.thinLineColor, this))
- , m_thickLineColor(new ColorControl(style.thickLineColor, this))
- , m_handleSize(new QDoubleSpinBox(this))
- , m_handleLineWidth(new QDoubleSpinBox(this))
- , m_endPointColor(new ColorControl(style.endPointColor, this))
- , m_interPointColor(new ColorControl(style.interPointColor, this))
- , m_curveWidth(new QDoubleSpinBox(this))
-{
- m_aspect->setValue(style.aspect);
- m_thinLineWidth->setValue(style.thinLineWidth);
- m_thickLineWidth->setValue(style.thickLineWidth);
- m_handleSize->setValue(style.handleSize);
- m_handleLineWidth->setValue(style.handleLineWidth);
- m_curveWidth->setValue(style.curveWidth);
-
- int labelWidth = QFontMetrics(this->font()).width("Inter Handle ColorXX");
- auto addControl = [labelWidth](QVBoxLayout *layout, const QString &name, QWidget *control) {
- auto *hbox = new QHBoxLayout;
-
- QLabel *label = new QLabel(name);
- label->setAlignment(Qt::AlignLeft);
- label->setFixedWidth(labelWidth);
-
- hbox->addWidget(label);
- hbox->addWidget(control);
- layout->addLayout(hbox);
- };
-
- auto layout = new QVBoxLayout;
- addControl(layout, "Aspect Ratio", m_aspect);
-
- addControl(layout, "Thin Line Width", m_thinLineWidth);
- addControl(layout, "Thin Line Color", m_thinLineColor);
-
- addControl(layout, "Thick Line Width", m_thickLineWidth);
- addControl(layout, "Thick Line Color", m_thickLineColor);
-
- addControl(layout, "Handle Size", m_handleSize);
- addControl(layout, "Handle Line Width", m_handleLineWidth);
- addControl(layout, "End Handle Color", m_endPointColor);
- addControl(layout, "Inter Handle Color", m_interPointColor);
-
- addControl(layout, "Curve Width", m_curveWidth);
-
- setLayout(layout);
-
- auto emitValueChanged = [this]() {
- CanvasStyle out;
- out.aspect = m_aspect->value();
- out.thinLineWidth = m_thinLineWidth->value();
- out.thickLineWidth = m_thickLineWidth->value();
- out.thinLineColor = m_thinLineColor->value();
- out.thickLineColor = m_thickLineColor->value();
- out.handleSize = m_handleSize->value();
- out.handleLineWidth = m_handleLineWidth->value();
- out.endPointColor = m_endPointColor->value();
- out.interPointColor = m_interPointColor->value();
- out.curveWidth = m_curveWidth->value();
- emit styleChanged(out);
- };
-
- auto doubleValueChanged = static_cast<void (QDoubleSpinBox::*)(double)>(
- &QDoubleSpinBox::valueChanged);
- auto colorValueChanged = &ColorControl::valueChanged;
-
- connect(m_aspect, doubleValueChanged, this, emitValueChanged);
-
- connect(m_thinLineWidth, doubleValueChanged, this, emitValueChanged);
- connect(m_thickLineWidth, doubleValueChanged, this, emitValueChanged);
-
- connect(m_thinLineColor, colorValueChanged, this, emitValueChanged);
- connect(m_thickLineColor, colorValueChanged, this, emitValueChanged);
-
- connect(m_handleSize, doubleValueChanged, this, emitValueChanged);
- connect(m_handleLineWidth, doubleValueChanged, this, emitValueChanged);
-
- connect(m_endPointColor, colorValueChanged, this, emitValueChanged);
- connect(m_interPointColor, colorValueChanged, this, emitValueChanged);
-
- connect(m_curveWidth, doubleValueChanged, this, emitValueChanged);
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.cpp
deleted file mode 100644
index 3437d3bd68..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.cpp
+++ /dev/null
@@ -1,500 +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 "easingcurve.h"
-#include "timelineutils.h"
-
-#include <QDataStream>
-#include <QDebug>
-#include <QLineF>
-#include <QPainterPath>
-#include <QPointF>
-
-#include <utils/qtcassert.h>
-
-namespace QmlDesigner {
-
-EasingCurve::EasingCurve()
- : QEasingCurve(QEasingCurve::BezierSpline)
- , m_active(-1)
- , m_start(0.0, 0.0)
-{}
-
-EasingCurve::EasingCurve(const QEasingCurve &curve)
- : QEasingCurve(curve)
- , m_active(-1)
- , m_start(0.0, 0.0)
-{}
-
-EasingCurve::EasingCurve(const EasingCurve &curve) = default;
-
-EasingCurve::EasingCurve(const QPointF &start, const QVector<QPointF> &points)
- : QEasingCurve(QEasingCurve::BezierSpline)
- , m_active(-1)
- , m_start(start)
-{
- fromCubicSpline(points);
-}
-
-EasingCurve::~EasingCurve() = default;
-
-bool EasingCurve::IsValidIndex(int idx)
-{
- return idx >= 0;
-}
-
-void EasingCurve::registerStreamOperators()
-{
- qRegisterMetaType<QmlDesigner::EasingCurve>("QmlDesigner::EasingCurve");
- qRegisterMetaType<QmlDesigner::NamedEasingCurve>("QmlDesigner::NamedEasingCurve");
- qRegisterMetaTypeStreamOperators<QmlDesigner::EasingCurve>("QmlDesigner::EasingCurve");
- qRegisterMetaTypeStreamOperators<QmlDesigner::NamedEasingCurve>("QmlDesigner::NamedEasingCurve");
-}
-
-int EasingCurve::count() const
-{
- return toCubicSpline().count();
-}
-
-int EasingCurve::active() const
-{
- return m_active;
-}
-
-int EasingCurve::segmentCount() const
-{
- return toCubicSpline().count() / 3;
-}
-
-bool EasingCurve::isLegal() const
-{
- QPainterPath painterPath(path());
-
- double increment = 1.0 / 30.0;
- QPointF max = painterPath.pointAtPercent(0.0);
- for (double i = increment; i <= 1.0; i += increment) {
- QPointF current = painterPath.pointAtPercent(i);
- if (current.x() < max.x())
- return false;
- else
- max = current;
- }
- return true;
-}
-
-bool EasingCurve::hasActive() const
-{
- QTC_ASSERT(m_active < toCubicSpline().size(), return false);
- return m_active >= 0;
-}
-
-bool EasingCurve::isValidIndex(int idx) const
-{
- return idx >= 0 && idx < toCubicSpline().size();
-}
-
-bool EasingCurve::isSmooth(int idx) const
-{
- auto iter = std::find(m_smoothIds.begin(), m_smoothIds.end(), idx);
- return iter != m_smoothIds.end();
-}
-
-bool EasingCurve::isHandle(int idx) const
-{
- return (idx + 1) % 3;
-}
-
-bool EasingCurve::isLeftHandle(int idx) const
-{
- return ((idx + 2) % 3) == 0;
-}
-
-QString EasingCurve::toString() const
-{
- QLatin1Char c(',');
- QString s = QLatin1String("[");
- for (const QPointF &point : toCubicSpline()) {
- auto x = QString::number(point.x(), 'g', 3);
- auto y = QString::number(point.y(), 'g', 3);
- s += x + c + y + c;
- }
-
- // Replace last "," with "]"
- s.chop(1);
- s.append(QLatin1Char(']'));
-
- return s;
-}
-
-bool EasingCurve::fromString(const QString &code)
-{
- if (code.startsWith(QLatin1Char('[')) && code.endsWith(QLatin1Char(']'))) {
- const QStringRef cleanCode(&code, 1, code.size() - 2);
- const auto stringList = cleanCode.split(QLatin1Char(','), QString::SkipEmptyParts);
-
- if (stringList.count() >= 6 && (stringList.count() % 6 == 0)) {
- bool checkX, checkY;
- QVector<QPointF> points;
- for (int i = 0; i < stringList.count(); ++i) {
- QPointF point;
- point.rx() = stringList[i].toDouble(&checkX);
- point.ry() = stringList[++i].toDouble(&checkY);
-
- if (!checkX || !checkY)
- return false;
-
- points.push_back(point);
- }
-
- if (points.constLast() != QPointF(1.0, 1.0))
- return false;
-
- QEasingCurve easingCurve(QEasingCurve::BezierSpline);
-
- for (int i = 0; i < points.count() / 3; ++i) {
- easingCurve.addCubicBezierSegment(points.at(i * 3),
- points.at(i * 3 + 1),
- points.at(i * 3 + 2));
- }
-
- fromCubicSpline(easingCurve.toCubicSpline());
- return true;
- }
- }
- return false;
-}
-
-QPointF EasingCurve::start() const
-{
- return m_start;
-}
-
-QPointF EasingCurve::end() const
-{
- return toCubicSpline().last();
-}
-
-QPainterPath EasingCurve::path() const
-{
- QPainterPath path;
- path.moveTo(m_start);
-
- QVector<QPointF> controlPoints = toCubicSpline();
-
- int numSegments = controlPoints.count() / 3;
- for (int i = 0; i < numSegments; i++) {
- QPointF p1 = controlPoints.at(i * 3);
- QPointF p2 = controlPoints.at(i * 3 + 1);
- QPointF p3 = controlPoints.at(i * 3 + 2);
- path.cubicTo(p1, p2, p3);
- }
-
- return path;
-}
-
-int EasingCurve::curvePoint(int idx) const
-{
- if (isHandle(idx)) {
- if (isLeftHandle(idx))
- return idx + 1;
- else
- return idx - 1;
- }
- return idx;
-}
-
-QPointF EasingCurve::point(int idx) const
-{
- QVector<QPointF> controlPoints = toCubicSpline();
-
- QTC_ASSERT(controlPoints.count() > idx || idx < 0, return QPointF());
-
- return controlPoints.at(idx);
-}
-
-int EasingCurve::hit(const QPointF &point, double threshold) const
-{
- int id = -1;
- qreal distance = std::numeric_limits<qreal>::max();
-
- QVector<QPointF> controlPoints = toCubicSpline();
- for (int i = 0; i < controlPoints.size() - 1; ++i) {
- qreal d = QLineF(point, controlPoints.at(i)).length();
- if (d < threshold && d < distance) {
- distance = d;
- id = i;
- }
- }
- return id;
-}
-
-void EasingCurve::makeDefault()
-{
- QVector<QPointF> controlPoints;
- controlPoints.append(QPointF(0.0, 0.2));
- controlPoints.append(QPointF(0.3, 0.5));
- controlPoints.append(QPointF(0.5, 0.5));
-
- controlPoints.append(QPointF(0.7, 0.5));
- controlPoints.append(QPointF(1.0, 0.8));
- controlPoints.append(QPointF(1.0, 1.0));
-
- fromCubicSpline(controlPoints);
-
- m_smoothIds.push_back(2);
-}
-
-void EasingCurve::clearActive()
-{
- m_active = -1;
-}
-
-void EasingCurve::setActive(int idx)
-{
- m_active = idx;
-}
-
-void EasingCurve::makeSmooth(int idx)
-{
- if (!isSmooth(idx) && !isHandle(idx)) {
- QVector<QPointF> controlPoints = toCubicSpline();
-
- QPointF before = m_start;
- if (idx > 3)
- before = controlPoints.at(idx - 3);
-
- QPointF after = end();
- if ((idx + 3) < controlPoints.count())
- after = controlPoints.at(idx + 3);
-
- QPointF tangent = (after - before) / 6;
-
- QPointF thisPoint = controlPoints.at(idx);
-
- if (idx > 0)
- controlPoints[idx - 1] = thisPoint - tangent;
-
- if (idx + 1 < controlPoints.count())
- controlPoints[idx + 1] = thisPoint + tangent;
-
- fromCubicSpline(controlPoints);
-
- m_smoothIds.push_back(idx);
- }
-}
-
-void EasingCurve::breakTangent(int idx)
-{
- if (isSmooth(idx) && !isHandle(idx)) {
- QVector<QPointF> controlPoints = toCubicSpline();
-
- QPointF before = m_start;
- if (idx > 3)
- before = controlPoints.at(idx - 3);
-
- QPointF after = end();
- if ((idx + 3) < controlPoints.count())
- after = controlPoints.at(idx + 3);
-
- QPointF thisPoint = controlPoints.at(idx);
-
- if (idx > 0)
- controlPoints[idx - 1] = (before - thisPoint) / 3 + thisPoint;
-
- if (idx + 1 < controlPoints.count())
- controlPoints[idx + 1] = (after - thisPoint) / 3 + thisPoint;
-
- fromCubicSpline(controlPoints);
-
- auto iter = std::find(m_smoothIds.begin(), m_smoothIds.end(), idx);
- m_smoothIds.erase(iter);
- }
-}
-
-void EasingCurve::addPoint(const QPointF &point)
-{
- QVector<QPointF> controlPoints = toCubicSpline();
-
- int splitIndex = 0;
- for (int i = 0; i < controlPoints.size() - 1; ++i) {
- if (!isHandle(i)) {
- if (controlPoints.at(i).x() > point.x())
- break;
-
- splitIndex = i;
- }
- }
-
- QPointF before = m_start;
- if (splitIndex > 0) {
- before = controlPoints.at(splitIndex);
- }
-
- QPointF after = end();
- if ((splitIndex + 3) < controlPoints.count()) {
- after = controlPoints.at(splitIndex + 3);
- }
-
- int newIdx;
-
- if (splitIndex > 0) {
- newIdx = splitIndex + 3;
- controlPoints.insert(splitIndex + 2, (point + after) / 2);
- controlPoints.insert(splitIndex + 2, point);
- controlPoints.insert(splitIndex + 2, (point + before) / 2);
- } else {
- newIdx = splitIndex + 2;
- controlPoints.insert(splitIndex + 1, (point + after) / 2);
- controlPoints.insert(splitIndex + 1, point);
- controlPoints.insert(splitIndex + 1, (point + before) / 2);
- }
-
- fromCubicSpline(controlPoints);
-
- QTC_ASSERT(!isHandle(newIdx), return );
-
- m_active = newIdx;
-
- breakTangent(newIdx);
- makeSmooth(newIdx);
-}
-
-void EasingCurve::setPoint(int idx, const QPointF &point)
-{
- if (!isValidIndex(idx))
- return;
-
- QVector<QPointF> controlPoints = toCubicSpline();
-
- controlPoints[idx] = point;
-
- fromCubicSpline(controlPoints);
-}
-
-void EasingCurve::movePoint(int idx, const QPointF &vector)
-{
- if (!isValidIndex(idx))
- return;
-
- QVector<QPointF> controlPoints = toCubicSpline();
-
- controlPoints[idx] += vector;
-
- fromCubicSpline(controlPoints);
-}
-
-void EasingCurve::deletePoint(int idx)
-{
- if (!isValidIndex(idx))
- return;
-
- QVector<QPointF> controlPoints = toCubicSpline();
-
- controlPoints.remove(idx - 1, 3);
-
- fromCubicSpline(controlPoints);
-}
-
-void EasingCurve::fromCubicSpline(const QVector<QPointF> &points)
-{
- QEasingCurve tmp(QEasingCurve::BezierSpline);
-
- int numSegments = points.count() / 3;
- for (int i = 0; i < numSegments; ++i) {
- tmp.addCubicBezierSegment(points.at(i * 3), points.at(i * 3 + 1), points.at(i * 3 + 2));
- }
- swap(tmp);
-}
-
-QDebug &operator<<(QDebug &stream, const EasingCurve &curve)
-{
- stream << static_cast<QEasingCurve>(curve);
- stream << "\"active:" << curve.m_active << "\"";
- stream << "\"smooth ids:" << curve.m_smoothIds << "\"";
- return stream;
-}
-
-QDataStream &operator<<(QDataStream &stream, const EasingCurve &curve)
-{
- // Ignore the active flag.
- stream << static_cast<QEasingCurve>(curve);
- stream << curve.toCubicSpline();
- stream << curve.m_smoothIds;
- return stream;
-}
-
-QDataStream &operator>>(QDataStream &stream, EasingCurve &curve)
-{
- // This is to circumvent a bug in QEasingCurve serialization.
- QVector<QPointF> points;
-
- // Ignore the active flag.
- stream >> static_cast<QEasingCurve &>(curve);
- stream >> points;
- curve.fromCubicSpline(points);
- stream >> curve.m_smoothIds;
-
- return stream;
-}
-
-NamedEasingCurve::NamedEasingCurve()
- : m_name()
- , m_curve()
-{}
-
-NamedEasingCurve::NamedEasingCurve(const QString &name, const EasingCurve &curve)
- : m_name(name)
- , m_curve(curve)
-{}
-
-NamedEasingCurve::NamedEasingCurve(const NamedEasingCurve &other) = default;
-
-NamedEasingCurve::~NamedEasingCurve() = default;
-
-QString NamedEasingCurve::name() const
-{
- return m_name;
-}
-
-EasingCurve NamedEasingCurve::curve() const
-{
- return m_curve;
-}
-
-QDataStream &operator<<(QDataStream &stream, const NamedEasingCurve &curve)
-{
- stream << curve.m_name;
- stream << curve.m_curve;
- return stream;
-}
-
-QDataStream &operator>>(QDataStream &stream, NamedEasingCurve &curve)
-{
- stream >> curve.m_name;
- stream >> curve.m_curve;
- return stream;
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.h b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.h
deleted file mode 100644
index bc27d17884..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurve.h
+++ /dev/null
@@ -1,155 +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 <QEasingCurve>
-#include <QMetaType>
-#include <QPointF>
-
-QT_FORWARD_DECLARE_CLASS(QPainterPath);
-
-namespace QmlDesigner {
-
-class EasingCurve : public QEasingCurve
-{
-public:
- EasingCurve();
-
- EasingCurve(const QEasingCurve &curve);
-
- EasingCurve(const EasingCurve &curve);
-
- EasingCurve(const QPointF &start, const QVector<QPointF> &points);
-
- virtual ~EasingCurve();
-
- static bool IsValidIndex(int idx);
-
- static void registerStreamOperators();
-
-public:
- int count() const;
-
- int active() const;
-
- int segmentCount() const;
-
- bool hasActive() const;
-
- bool isLegal() const;
-
- bool isValidIndex(int idx) const;
-
- bool isSmooth(int idx) const;
-
- bool isHandle(int idx) const;
-
- bool isLeftHandle(int idx) const;
-
- QString toString() const;
-
- QPointF start() const;
-
- QPointF end() const;
-
- QPainterPath path() const;
-
- int curvePoint(int idx) const;
-
- QPointF point(int idx) const;
-
- int hit(const QPointF &point, double threshold) const;
-
-public:
- void makeDefault();
-
- void clearActive();
-
- void setActive(int idx);
-
- void makeSmooth(int idx);
-
- void breakTangent(int idx);
-
- void addPoint(const QPointF &point);
-
- void setPoint(int idx, const QPointF &point);
-
- void movePoint(int idx, const QPointF &vector);
-
- void deletePoint(int idx);
-
- bool fromString(const QString &string);
-
- void fromCubicSpline(const QVector<QPointF> &points);
-
- friend QDebug &operator<<(QDebug &stream, const EasingCurve &curve);
-
- friend QDataStream &operator<<(QDataStream &stream, const EasingCurve &curve);
-
- friend QDataStream &operator>>(QDataStream &stream, EasingCurve &curve);
-
- friend std::ostream &operator<<(std::ostream &stream, const EasingCurve &curve);
-
- friend std::istream &operator>>(std::istream &stream, EasingCurve &curve);
-
-private:
- int m_active;
-
- QPointF m_start;
-
- std::vector<int> m_smoothIds;
-};
-
-class NamedEasingCurve
-{
-public:
- NamedEasingCurve();
-
- NamedEasingCurve(const QString &name, const EasingCurve &curve);
-
- NamedEasingCurve(const NamedEasingCurve &other);
-
- virtual ~NamedEasingCurve();
-
- QString name() const;
-
- EasingCurve curve() const;
-
- friend QDataStream &operator<<(QDataStream &stream, const NamedEasingCurve &curve);
-
- friend QDataStream &operator>>(QDataStream &stream, NamedEasingCurve &curve);
-
-private:
- QString m_name;
-
- EasingCurve m_curve;
-};
-
-} // namespace QmlDesigner
-
-Q_DECLARE_METATYPE(QmlDesigner::EasingCurve);
-Q_DECLARE_METATYPE(QmlDesigner::NamedEasingCurve);
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurvedialog.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurvedialog.cpp
deleted file mode 100644
index 5d6d66a472..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/easingcurvedialog.cpp
+++ /dev/null
@@ -1,307 +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 "easingcurvedialog.h"
-
-#include "preseteditor.h"
-#include "splineeditor.h"
-
-#include <QApplication>
-#include <QGridLayout>
-#include <QGroupBox>
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QMessageBox>
-#include <QPlainTextEdit>
-#include <QPushButton>
-#include <QSizePolicy>
-#include <QSpinBox>
-#include <QTabBar>
-#include <QTabWidget>
-#include <QVBoxLayout>
-
-#include <abstractview.h>
-#include <bindingproperty.h>
-#include <rewritingexception.h>
-#include <theme.h>
-#include <utils/qtcassert.h>
-
-namespace QmlDesigner {
-
-EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *parent)
- : QDialog(parent)
- , m_splineEditor(new SplineEditor(this))
- , m_text(new QPlainTextEdit(this))
- , m_presets(new PresetEditor(this))
- , m_durationLayout(new QHBoxLayout)
- , m_buttons(new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel
- | QDialogButtonBox::Ok))
- , m_label(new QLabel)
- , m_frames(frames)
-{
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
-
- auto tw = new QTabWidget;
- tw->setTabPosition(QTabWidget::East);
- tw->addTab(m_splineEditor, "Curve");
- tw->addTab(m_text, "Text");
-
- connect(tw, &QTabWidget::currentChanged, this, &EasingCurveDialog::tabClicked);
- connect(m_text, &QPlainTextEdit::textChanged, this, &EasingCurveDialog::textChanged);
-
- auto labelFont = m_label->font();
- labelFont.setPointSize(labelFont.pointSize() + 2);
- m_label->setFont(labelFont);
-
- auto hSpacing = qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
- auto vSpacing = qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
- auto *vbox = new QVBoxLayout;
- vbox->setContentsMargins(2, 0, 0, vSpacing);
- vbox->addWidget(m_label);
-
- auto *presetBar = new QTabBar;
-
- auto smallFont = presetBar->font();
- smallFont.setPixelSize(Theme::instance()->smallFontPixelSize());
-
- presetBar->setFont(smallFont);
- presetBar->setExpanding(false);
- presetBar->setDrawBase(false);
- presetBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
-
- auto *durationLabel = new QLabel("Duration (ms)");
- auto *durationEdit = new QSpinBox;
- durationEdit->setMaximum(std::numeric_limits<int>::max());
- durationEdit->setValue(1000);
- auto *animateButton = new QPushButton("Preview");
-
- m_durationLayout->setContentsMargins(0, vSpacing, 0, 0);
- m_durationLayout->addWidget(durationLabel);
- m_durationLayout->addWidget(durationEdit);
- m_durationLayout->addWidget(animateButton);
-
- m_durationLayout->insertSpacing(1, hSpacing);
- m_durationLayout->insertSpacing(2, hSpacing);
- m_durationLayout->insertSpacing(4, hSpacing);
- m_durationLayout->addStretch(hSpacing);
-
- m_buttons->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
- auto callButtonsClicked = [this](QAbstractButton *button) {
- buttonsClicked(m_buttons->standardButton(button));
- };
-
- connect(m_buttons, &QDialogButtonBox::clicked, this, callButtonsClicked);
-
- auto *buttonLayout = new QVBoxLayout;
- buttonLayout->setContentsMargins(0, vSpacing, 0, 0);
- buttonLayout->addWidget(m_buttons);
-
- auto *grid = new QGridLayout;
- grid->setVerticalSpacing(0);
- grid->addLayout(vbox, 0, 0);
- grid->addWidget(presetBar, 0, 1, Qt::AlignBottom);
-
- grid->addWidget(tw);
- grid->addWidget(m_presets, 1, 1);
- grid->addLayout(m_durationLayout, 2, 0);
- grid->addLayout(buttonLayout, 2, 1);
-
- auto *groupBox = new QGroupBox;
- groupBox->setLayout(grid);
-
- auto *tabWidget = new QTabWidget(this);
- tabWidget->addTab(groupBox, "Easing Curve Editor");
-
- auto *mainBox = new QVBoxLayout;
- mainBox->addWidget(tabWidget);
- setLayout(mainBox);
-
- connect(m_splineEditor,
- &SplineEditor::easingCurveChanged,
- this,
- &EasingCurveDialog::updateEasingCurve);
-
- connect(m_presets, &PresetEditor::presetChanged, m_splineEditor, &SplineEditor::setEasingCurve);
-
- connect(durationEdit,
- static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
- m_splineEditor,
- &SplineEditor::setDuration);
-
- connect(animateButton, &QPushButton::clicked, m_splineEditor, &SplineEditor::animate);
-
- m_presets->initialize(presetBar);
-
- m_splineEditor->setDuration(durationEdit->value());
-
- resize(QSize(1421, 918));
-}
-
-void EasingCurveDialog::initialize(const QString &curveString)
-{
- EasingCurve curve;
- if (curveString.isEmpty()) {
- QEasingCurve qcurve;
- qcurve.addCubicBezierSegment(QPointF(0.2, 0.2), QPointF(0.8, 0.8), QPointF(1.0, 1.0));
- curve = EasingCurve(qcurve);
- } else
- curve.fromString(curveString);
-
- m_splineEditor->setEasingCurve(curve);
-}
-
-void EasingCurveDialog::runDialog(const QList<ModelNode> &frames, QWidget *parent)
-{
- if (frames.empty())
- return;
-
- EasingCurveDialog dialog(frames, parent);
-
- ModelNode current = frames.last();
-
- if (current.hasBindingProperty("easing.bezierCurve"))
- dialog.initialize(current.bindingProperty("easing.bezierCurve").expression());
- else
- dialog.initialize("");
-
- dialog.exec();
-}
-
-bool EasingCurveDialog::apply()
-{
- QTC_ASSERT(!m_frames.empty(), return false);
-
- EasingCurve curve = m_splineEditor->easingCurve();
- if (!curve.isLegal()) {
- QMessageBox msgBox;
- msgBox.setText("Attempting to apply invalid curve to keyframe");
- msgBox.setInformativeText("Please solve the issue before proceeding.");
- msgBox.setStandardButtons(QMessageBox::Ok);
- msgBox.exec();
- return false;
- }
-
- try {
- AbstractView *view = m_frames.first().view();
- RewriterTransaction transaction(view->beginRewriterTransaction("EasingCurveDialog::apply"));
-
- auto expression = m_splineEditor->easingCurve().toString();
- for (const auto &frame : m_frames)
- frame.bindingProperty("easing.bezierCurve").setExpression(expression);
-
- transaction.commit();
- return true;
- } catch (const RewritingException &e) {
- e.showException();
- }
-
- return false;
-}
-
-void EasingCurveDialog::textChanged()
-{
- auto curve = m_splineEditor->easingCurve();
- curve.fromString(m_text->toPlainText());
- m_splineEditor->setEasingCurve(curve);
-}
-
-void EasingCurveDialog::tabClicked(int id)
-{
- if (auto tw = qobject_cast<const QTabWidget *>(sender())) {
- int seid = tw->indexOf(m_splineEditor);
- if (seid == id) {
- for (int i = 0; i < m_durationLayout->count(); ++i) {
- auto *item = m_durationLayout->itemAt(i);
- if (auto *widget = item->widget())
- widget->show();
- }
-
- auto curve = m_splineEditor->easingCurve();
- curve.fromString(m_text->toPlainText());
- m_splineEditor->setEasingCurve(curve);
-
- } else {
- for (int i = 0; i < m_durationLayout->count(); ++i) {
- auto *item = m_durationLayout->itemAt(i);
- if (auto *widget = item->widget())
- widget->hide();
- }
-
- auto curve = m_splineEditor->easingCurve();
- m_text->setPlainText(curve.toString());
- }
- }
-}
-
-void EasingCurveDialog::presetTabClicked(int id)
-{
- m_presets->activate(id);
-}
-
-void EasingCurveDialog::updateEasingCurve(const EasingCurve &curve)
-{
- if (!curve.isLegal()) {
- auto *save = m_buttons->button(QDialogButtonBox::Save);
- save->setEnabled(false);
-
- auto *ok = m_buttons->button(QDialogButtonBox::Ok);
- ok->setEnabled(false);
-
- m_label->setText("Invalid Curve!");
- } else {
- auto *save = m_buttons->button(QDialogButtonBox::Save);
- save->setEnabled(true);
-
- auto *ok = m_buttons->button(QDialogButtonBox::Ok);
- ok->setEnabled(true);
-
- m_label->setText("");
- }
-
- m_presets->update(curve);
-}
-
-void EasingCurveDialog::buttonsClicked(QDialogButtonBox::StandardButton button)
-{
- switch (button) {
- case QDialogButtonBox::Ok:
- if (apply())
- close();
- break;
-
- case QDialogButtonBox::Cancel:
- close();
- break;
-
- case QDialogButtonBox::Save:
- m_presets->writePresets(m_splineEditor->easingCurve());
- break;
-
- default:
- break;
- }
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/preseteditor.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/preseteditor.cpp
deleted file mode 100644
index 4e6f9c9f17..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/preseteditor.cpp
+++ /dev/null
@@ -1,560 +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 "preseteditor.h"
-
-#include "canvas.h"
-#include "easingcurve.h"
-#include "timelineicons.h"
-
-#include <QAbstractButton>
-#include <QApplication>
-#include <QContextMenuEvent>
-#include <QMenu>
-#include <QMessageBox>
-#include <QPainter>
-#include <QPixmap>
-#include <QSettings>
-#include <QStandardItemModel>
-#include <QString>
-
-#include <coreplugin/icore.h>
-#include <theme.h>
-
-namespace QmlDesigner {
-
-constexpr int iconWidth = 86;
-constexpr int iconHeight = 86;
-constexpr int itemFrame = 3;
-constexpr int itemWidth = iconWidth + 2 * itemFrame;
-constexpr int unsavedMarkSize = 18;
-
-constexpr int spacingg = 5;
-
-const QColor background = Qt::white;
-
-const QColor labelBackground = qRgb(0x70, 0x70, 0x70);
-const QColor canvasBackground = qRgb(0x46, 0x46, 0x46);
-const QColor curveLine = qRgb(0xe6, 0xe7, 0xe8);
-
-PresetItemDelegate::PresetItemDelegate() = default;
-
-void PresetItemDelegate::paint(QPainter *painter,
- const QStyleOptionViewItem &opt,
- const QModelIndex &index) const
-{
- QStyleOptionViewItem option = opt;
- initStyleOption(&option, index);
-
- auto *w = option.widget;
- auto *style = w == nullptr ? qApp->style() : w->style();
-
- QSize textSize = QSize(option.rect.width(),
- style->subElementRect(QStyle::SE_ItemViewItemText, &option, w).height());
-
- auto textRect = QRect(option.rect.topLeft(), textSize);
- textRect.moveBottom(option.rect.bottom());
-
- option.font.setPixelSize(Theme::instance()->smallFontPixelSize());
-
- painter->save();
- painter->fillRect(option.rect, canvasBackground);
-
- if (option.text.isEmpty())
- painter->fillRect(textRect, canvasBackground);
- else
- painter->fillRect(textRect, Theme::instance()->qmlDesignerButtonColor());
-
- style->drawControl(QStyle::CE_ItemViewItem, &option, painter, option.widget);
-
- QVariant dirty = option.index.data(PresetList::ItemRole_Dirty);
- if (dirty.isValid()) {
- if (dirty.toBool()) {
- QRect asteriskRect(option.rect.right() - unsavedMarkSize,
- itemFrame,
- unsavedMarkSize,
- unsavedMarkSize);
-
- QFont font = painter->font();
- font.setPixelSize(unsavedMarkSize);
- painter->setFont(font);
-
- auto pen = painter->pen();
- pen.setColor(Qt::white);
- painter->setPen(pen);
-
- painter->drawText(asteriskRect, Qt::AlignTop | Qt::AlignRight, "*");
- }
- }
- painter->restore();
-}
-
-QSize PresetItemDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const
-{
- QSize size = QStyledItemDelegate::sizeHint(opt, index);
- size.rwidth() = itemWidth;
- return size;
-}
-
-QIcon paintPreview()
-{
- QPixmap pm(iconWidth, iconHeight);
- pm.fill(canvasBackground);
- return QIcon(pm);
-}
-
-QIcon paintPreview(const EasingCurve &curve)
-{
- QPixmap pm(iconWidth, iconHeight);
- pm.fill(canvasBackground);
-
- QPainter painter(&pm);
- painter.setRenderHint(QPainter::Antialiasing, true);
-
- Canvas canvas(iconWidth, iconHeight, 2, 2, 9, 6, 0, 1);
- canvas.paintCurve(&painter, curve, curveLine);
-
- return QIcon(pm);
-}
-
-namespace Internal {
-
-static const char settingsKey[] = "EasingCurveList";
-static const char settingsFileName[] = "/EasingCurves.ini";
-
-QString settingsFullFilePath(const QSettings::Scope &scope)
-{
- if (scope == QSettings::SystemScope)
- return Core::ICore::installerResourcePath() + settingsFileName;
-
- return Core::ICore::userResourcePath() + settingsFileName;
-}
-
-} // namespace Internal
-
-PresetList::PresetList(QSettings::Scope scope, QWidget *parent)
- : QListView(parent)
- , m_scope(scope)
- , m_index(-1)
- , m_filename(Internal::settingsFullFilePath(scope))
-{
- int magic = 4;
- int scrollBarWidth = this->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
- const int width = 3 * itemWidth + 4 * spacingg + scrollBarWidth + magic;
-
- setFixedWidth(width);
-
- setModel(new QStandardItemModel);
-
- setItemDelegate(new PresetItemDelegate);
-
- setSpacing(spacingg);
-
- setUniformItemSizes(true);
-
- setIconSize(QSize(iconWidth, iconHeight));
-
- setSelectionMode(QAbstractItemView::SingleSelection);
-
- setViewMode(QListView::IconMode);
-
- setFlow(QListView::LeftToRight);
-
- setMovement(QListView::Static);
-
- setWrapping(true);
-
- setTextElideMode(Qt::ElideMiddle);
-
- setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
-}
-
-void PresetList::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
-{
- for (const QModelIndex &index : deselected.indexes()) {
- if (dirty(index)) {
- QMessageBox msgBox;
- msgBox.setText("The preset has been modified.");
- msgBox.setInformativeText("Do you want to save your changes?");
- msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard
- | QMessageBox::Cancel);
- msgBox.setDefaultButton(QMessageBox::Save);
-
- if (QAbstractButton *button = msgBox.button(QMessageBox::Discard))
- button->setText("Discard Changes");
-
- if (QAbstractButton *button = msgBox.button(QMessageBox::Cancel))
- button->setText("Cancel Selection");
-
- int ret = msgBox.exec();
-
- switch (ret) {
- case QMessageBox::Save:
- // Save the preset and continue selection.
- writePresets();
- break;
- case QMessageBox::Discard:
- // Discard changes to the curve and continue selection.
- revert(index);
- break;
-
- case QMessageBox::Cancel:
- // Cancel selection operation and leave the curve untouched.
- selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
- return;
-
- default:
- // should never be reachedDiscard
- break;
- }
- }
- }
-
- for (const auto &index : selected.indexes()) {
- QVariant curveData = model()->data(index, ItemRole_Data);
- if (curveData.isValid())
- emit presetChanged(curveData.value<EasingCurve>());
- }
-}
-
-bool PresetList::hasSelection() const
-{
- return selectionModel()->hasSelection();
-}
-
-bool PresetList::dirty(const QModelIndex &index) const
-{
- return model()->data(index, ItemRole_Dirty).toBool();
-}
-
-int PresetList::index() const
-{
- return m_index;
-}
-
-bool PresetList::isEditable(const QModelIndex &index) const
-{
- QFlags<Qt::ItemFlag> flags(model()->flags(index));
- return flags.testFlag(Qt::ItemIsEditable);
-}
-
-void PresetList::initialize(int index)
-{
- m_index = index;
-
- readPresets();
-}
-
-void PresetList::readPresets()
-{
- auto *simodel = qobject_cast<QStandardItemModel *>(model());
-
- simodel->clear();
-
- QList<NamedEasingCurve> curves = storedCurves();
-
- for (int i = 0; i < curves.size(); ++i) {
- QVariant curveData = QVariant::fromValue(curves[i].curve());
-
- auto *item = new QStandardItem(paintPreview(curves[i].curve()), curves[i].name());
- item->setData(curveData, ItemRole_Data);
- item->setEditable(m_scope == QSettings::UserScope);
- item->setToolTip(curves[i].name());
-
- simodel->setItem(i, item);
- }
-}
-
-void PresetList::writePresets()
-{
- QList<QVariant> presets;
- for (int i = 0; i < model()->rowCount(); ++i) {
- QModelIndex index = model()->index(i, 0);
-
- QVariant nameData = model()->data(index, Qt::DisplayRole);
- QVariant curveData = model()->data(index, ItemRole_Data);
-
- if (nameData.isValid() && curveData.isValid()) {
- NamedEasingCurve curve(nameData.toString(), curveData.value<QmlDesigner::EasingCurve>());
-
- presets << QVariant::fromValue(curve);
- }
-
- model()->setData(index, false, ItemRole_Dirty);
- }
-
- QSettings settings(m_filename, QSettings::IniFormat);
- settings.clear();
- settings.setValue(Internal::settingsKey, QVariant::fromValue(presets));
-}
-
-void PresetList::revert(const QModelIndex &index)
-{
- auto *simodel = qobject_cast<QStandardItemModel *>(model());
- if (auto *item = simodel->itemFromIndex(index)) {
- QString name = item->data(Qt::DisplayRole).toString();
- QList<NamedEasingCurve> curves = storedCurves();
-
- for (const auto &curve : curves) {
- if (curve.name() == name) {
- item->setData(false, ItemRole_Dirty);
- item->setData(paintPreview(curve.curve()), Qt::DecorationRole);
- item->setData(QVariant::fromValue(curve.curve()), ItemRole_Data);
- item->setToolTip(name);
- return;
- }
- }
- }
-}
-
-void PresetList::updateCurve(const EasingCurve &curve)
-{
- if (!selectionModel()->hasSelection())
- return;
-
- QVariant icon = QVariant::fromValue(paintPreview(curve));
- QVariant curveData = QVariant::fromValue(curve);
-
- for (const auto &index : selectionModel()->selectedIndexes())
- setItemData(index, curveData, icon);
-}
-
-void PresetList::contextMenuEvent(QContextMenuEvent *event)
-{
- event->accept();
-
- if (m_scope == QSettings::SystemScope)
- return;
-
- QMenu menu;
-
- QAction *addAction = menu.addAction(tr("Add Preset"));
-
- connect(addAction, &QAction::triggered, [&]() { createItem(); });
-
- if (selectionModel()->hasSelection()) {
- QAction *removeAction = menu.addAction(tr("Delete Selected Preset"));
- connect(removeAction, &QAction::triggered, [&]() { removeSelectedItem(); });
- }
-
- menu.exec(event->globalPos());
-}
-
-void PresetList::dataChanged(const QModelIndex &topLeft,
- const QModelIndex &bottomRight,
- const QVector<int> &roles)
-{
- if (topLeft == bottomRight && roles.contains(0)) {
- const QVariant name = model()->data(topLeft, 0);
- model()->setData(topLeft, name, Qt::ToolTipRole);
- }
-}
-
-void PresetList::createItem()
-{
- EasingCurve curve;
- curve.makeDefault();
- createItem(createUniqueName(), curve);
-}
-
-void PresetList::createItem(const QString &name, const EasingCurve &curve)
-{
- auto *item = new QStandardItem(paintPreview(curve), name);
- item->setData(QVariant::fromValue(curve), ItemRole_Data);
- item->setToolTip(name);
-
- int row = model()->rowCount();
- qobject_cast<QStandardItemModel *>(model())->setItem(row, item);
-
- QModelIndex index = model()->index(row, 0);
-
- // Why is that needed? SingleSelection is specified.
- selectionModel()->clear();
- selectionModel()->select(index, QItemSelectionModel::Select);
-}
-
-void PresetList::removeSelectedItem()
-{
- for (const auto &index : selectionModel()->selectedIndexes())
- model()->removeRow(index.row());
-
- writePresets();
-}
-
-void PresetList::setItemData(const QModelIndex &index, const QVariant &curve, const QVariant &icon)
-{
- if (isEditable(index)) {
- model()->setData(index, curve, PresetList::ItemRole_Data);
- model()->setData(index, true, PresetList::ItemRole_Dirty);
- model()->setData(index, icon, Qt::DecorationRole);
- }
-}
-
-QString PresetList::createUniqueName() const
-{
- QStringList names = allNames();
- auto nameIsUnique = [&](const QString &name) {
- auto iter = std::find(names.begin(), names.end(), name);
- if (iter == names.end())
- return true;
- else
- return false;
- };
-
- int counter = 0;
- QString tmp("Default");
- QString name = tmp;
-
- while (!nameIsUnique(name))
- name = tmp + QString(" %1").arg(counter++);
-
- return name;
-}
-
-QStringList PresetList::allNames() const
-{
- QStringList names;
- for (int i = 0; i < model()->rowCount(); ++i) {
- QModelIndex index = model()->index(i, 0);
- QVariant nameData = model()->data(index, Qt::DisplayRole);
- if (nameData.isValid())
- names << nameData.toString();
- }
-
- return names;
-}
-
-QList<NamedEasingCurve> PresetList::storedCurves() const
-{
- QSettings settings(m_filename, QSettings::IniFormat);
- QVariant presetSettings = settings.value(Internal::settingsKey);
-
- if (!presetSettings.isValid())
- return QList<NamedEasingCurve>();
-
- QList<QVariant> presets = presetSettings.toList();
-
- QList<NamedEasingCurve> out;
- for (const QVariant &preset : presets)
- if (preset.isValid())
- out << preset.value<NamedEasingCurve>();
-
- return out;
-}
-
-PresetEditor::PresetEditor(QWidget *parent)
- : QStackedWidget(parent)
- , m_presets(new PresetList(QSettings::SystemScope))
- , m_customs(new PresetList(QSettings::UserScope))
-{
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
-
- addWidget(m_presets);
- addWidget(m_customs);
-
- connect(m_presets, &PresetList::presetChanged, this, &PresetEditor::presetChanged);
- connect(m_customs, &PresetList::presetChanged, this, &PresetEditor::presetChanged);
-}
-
-void PresetEditor::initialize(QTabBar *bar)
-{
- m_presets->initialize(bar->addTab("Presets"));
- m_customs->initialize(bar->addTab("Custom"));
-
- connect(bar, &QTabBar::currentChanged, this, &PresetEditor::activate);
- connect(this, &PresetEditor::currentChanged, bar, &QTabBar::setCurrentIndex);
-
- m_presets->selectionModel()->clear();
- m_customs->selectionModel()->clear();
-
- activate(m_presets->index());
-}
-
-void PresetEditor::activate(int id)
-{
- if (id == m_presets->index())
- setCurrentWidget(m_presets);
- else
- setCurrentWidget(m_customs);
-}
-
-void PresetEditor::update(const EasingCurve &curve)
-{
- if (isCurrent(m_presets))
- m_presets->selectionModel()->clear();
- else {
- if (m_customs->selectionModel()->hasSelection()) {
- QVariant icon = QVariant::fromValue(paintPreview(curve));
- QVariant curveData = QVariant::fromValue(curve);
- for (const QModelIndex &index : m_customs->selectionModel()->selectedIndexes())
- m_customs->setItemData(index, curveData, icon);
- }
- }
-}
-
-bool PresetEditor::writePresets(const EasingCurve &curve)
-{
- if (!curve.isLegal()) {
- QMessageBox msgBox;
- msgBox.setText("Attempting to save invalid curve");
- msgBox.setInformativeText("Please solve the issue before proceeding.");
- msgBox.setStandardButtons(QMessageBox::Ok);
- msgBox.exec();
- return false;
- }
-
- if (auto current = qobject_cast<const PresetList *>(currentWidget())) {
- if (current->index() == m_presets->index()
- || (current->index() == m_customs->index() && !m_customs->hasSelection())) {
- bool ok;
- QString name = QInputDialog::getText(this,
- tr("Save Preset"),
- tr("Name"),
- QLineEdit::Normal,
- QString(),
- &ok);
-
- if (ok && !name.isEmpty()) {
- activate(m_customs->index());
- m_customs->createItem(name, curve);
- }
- }
-
- m_customs->writePresets();
- return true;
- }
-
- return false;
-}
-
-bool PresetEditor::isCurrent(PresetList *list)
-{
- if (auto current = qobject_cast<const PresetList *>(currentWidget()))
- return list->index() == current->index();
-
- return false;
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineactions.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineactions.cpp
deleted file mode 100644
index 419e9294a2..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineactions.cpp
+++ /dev/null
@@ -1,345 +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 "timelineactions.h"
-
-#include "timelineutils.h"
-#include "timelineview.h"
-
-#include <bindingproperty.h>
-#include <designdocument.h>
-#include <designdocumentview.h>
-#include <nodelistproperty.h>
-#include <nodemetainfo.h>
-#include <rewritertransaction.h>
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-#include <variantproperty.h>
-#include <qmldesignerplugin.h>
-#include <qmlobjectnode.h>
-#include <qmltimelinekeyframegroup.h>
-
-namespace QmlDesigner {
-
-TimelineActions::TimelineActions() = default;
-
-void TimelineActions::deleteAllKeyframesForTarget(const ModelNode &targetNode,
- const QmlTimeline &timeline)
-{
- try {
- RewriterTransaction transaction(targetNode.view()->beginRewriterTransaction(
- "TimelineActions::deleteAllKeyframesForTarget"));
-
- if (timeline.isValid()) {
- for (auto frames : timeline.keyframeGroupsForTarget(targetNode))
- frames.destroy();
- }
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-void TimelineActions::insertAllKeyframesForTarget(const ModelNode &targetNode,
- const QmlTimeline &timeline)
-{
- try {
- RewriterTransaction transaction(targetNode.view()->beginRewriterTransaction(
- "TimelineGraphicsScene::insertAllKeyframesForTarget"));
-
- auto object = QmlObjectNode(targetNode);
- if (timeline.isValid() && object.isValid()) {
- for (auto frames : timeline.keyframeGroupsForTarget(targetNode)) {
- QVariant value = object.instanceValue(frames.propertyName());
- frames.setValue(value, timeline.currentKeyframe());
- }
- }
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-void TimelineActions::copyAllKeyframesForTarget(const ModelNode &targetNode,
- const QmlTimeline &timeline)
-{
- DesignDocumentView::copyModelNodes(Utils::transform(timeline.keyframeGroupsForTarget(targetNode),
- &QmlTimelineKeyframeGroup::modelNode));
-}
-
-void TimelineActions::pasteKeyframesToTarget(const ModelNode &targetNode,
- const QmlTimeline &timeline)
-{
- if (timeline.isValid()) {
- QScopedPointer<Model> pasteModel(DesignDocumentView::pasteToModel());
-
- if (!pasteModel)
- return;
-
- DesignDocumentView view;
- pasteModel->attachView(&view);
-
- if (!view.rootModelNode().isValid())
- return;
-
- ModelNode rootNode = view.rootModelNode();
-
- //Sanity check
- if (!QmlTimelineKeyframeGroup::checkKeyframesType(rootNode)) {
- for (const ModelNode &node : rootNode.directSubModelNodes())
- if (!QmlTimelineKeyframeGroup::checkKeyframesType(node))
- return;
- }
-
- pasteModel->detachView(&view);
-
- try {
- targetNode.view()->model()->attachView(&view);
-
- RewriterTransaction transaction(
- view.beginRewriterTransaction("TimelineActions::pasteKeyframesToTarget"));
-
- ModelNode nonConstTargetNode = targetNode;
- nonConstTargetNode.validId();
-
- if (QmlTimelineKeyframeGroup::checkKeyframesType(rootNode)) {
- /* Single selection */
-
- ModelNode newNode = view.insertModel(rootNode);
- QmlTimelineKeyframeGroup frames(newNode);
- frames.setTarget(targetNode);
-
- timeline.modelNode().defaultNodeListProperty().reparentHere(newNode);
-
- } else {
- /* Multi selection */
- for (const ModelNode &node : rootNode.directSubModelNodes()) {
- ModelNode newNode = view.insertModel(node);
- QmlTimelineKeyframeGroup frames(newNode);
- frames.setTarget(targetNode);
- timeline.modelNode().defaultNodeListProperty().reparentHere(newNode);
- }
- }
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
- }
-}
-
-void TimelineActions::copyKeyframes(const QList<ModelNode> &keyframes)
-{
- QList<ModelNode> nodes;
- for (const auto &node : keyframes) {
- NodeAbstractProperty pp = node.parentProperty();
- QTC_ASSERT(pp.isValid(), return );
-
- ModelNode parentModelNode = pp.parentModelNode();
- for (const auto &property : parentModelNode.properties()) {
- auto name = property.name();
- if (property.isBindingProperty()) {
- BindingProperty bp = property.toBindingProperty();
- ModelNode bpNode = bp.resolveToModelNode();
- if (bpNode.isValid())
- node.setAuxiliaryData(name, bpNode.id());
- } else if (property.isVariantProperty()) {
- VariantProperty vp = property.toVariantProperty();
- node.setAuxiliaryData(name, vp.value());
- }
- }
-
- nodes << node;
- }
-
- DesignDocumentView::copyModelNodes(nodes);
-}
-
-bool isKeyframe(const ModelNode &node)
-{
- return node.isValid() && node.metaInfo().isValid()
- && node.metaInfo().isSubclassOf("QtQuick.Timeline.Keyframe");
-}
-
-QVariant getValue(const ModelNode &node)
-{
- if (node.isValid())
- return node.variantProperty("value").value();
-
- return QVariant();
-}
-
-qreal getTime(const ModelNode &node)
-{
- Q_ASSERT(node.isValid());
- Q_ASSERT(node.hasProperty("frame"));
-
- return node.variantProperty("frame").value().toReal();
-}
-
-QmlTimelineKeyframeGroup getFrameGroup(const ModelNode &node,
- AbstractView *timelineView,
- const QmlTimeline &timeline)
-{
- QVariant targetId = node.auxiliaryData("target");
- QVariant property = node.auxiliaryData("property");
-
- if (targetId.isValid() && property.isValid()) {
- ModelNode targetNode = timelineView->modelNodeForId(targetId.toString());
- if (targetNode.isValid()) {
- for (QmlTimelineKeyframeGroup frameGrp : timeline.keyframeGroupsForTarget(targetNode)) {
- if (frameGrp.propertyName() == property.toByteArray())
- return frameGrp;
- }
- }
- }
- return QmlTimelineKeyframeGroup();
-}
-
-void pasteKeyframe(const qreal expectedTime,
- const ModelNode &keyframe,
- AbstractView *timelineView,
- const QmlTimeline &timeline)
-{
- QmlTimelineKeyframeGroup group = getFrameGroup(keyframe, timelineView, timeline);
- if (group.isValid()) {
- const qreal clampedTime = TimelineUtils::clamp(expectedTime,
- timeline.startKeyframe(),
- timeline.endKeyframe());
-
- // Create a new frame ...
- group.setValue(getValue(keyframe), clampedTime);
-
- // ... look it up by time ...
- for (const ModelNode &key : group.keyframePositions()) {
- qreal time = key.variantProperty("frame").value().toReal();
- if (qFuzzyCompare(clampedTime, time)) {
- // ... and transfer the properties.
- for (const auto &property : keyframe.properties()) {
- if (property.name() == "frame" || property.name() == "value")
- continue;
-
- if (property.isVariantProperty()) {
- auto vp = property.toVariantProperty();
- key.variantProperty(vp.name()).setValue(vp.value());
- } else if (property.isBindingProperty()) {
- auto bp = property.toBindingProperty();
- key.bindingProperty(bp.name()).setExpression(bp.expression());
- }
- }
- }
- }
- }
-}
-
-std::vector<std::tuple<ModelNode, qreal>> getFramesRelative(const ModelNode &parent)
-{
- auto byTime = [](const ModelNode &lhs, const ModelNode &rhs) {
- return getTime(lhs) < getTime(rhs);
- };
-
- std::vector<std::tuple<ModelNode, qreal>> result;
-
- QList<ModelNode> sortedByTime;
- QList<ModelNode> subs(parent.directSubModelNodes());
-
- std::copy_if(subs.begin(), subs.end(), std::back_inserter(sortedByTime), &isKeyframe);
- std::sort(sortedByTime.begin(), sortedByTime.end(), byTime);
-
- if (!sortedByTime.empty()) {
- qreal firstTime = getTime(sortedByTime.first());
- for (ModelNode keyframe : sortedByTime)
- result.emplace_back(keyframe, getTime(keyframe) - firstTime);
- }
-
- return result;
-}
-
-void TimelineActions::pasteKeyframes(AbstractView *timelineView, const QmlTimeline &timeline)
-{
- QScopedPointer<Model> pasteModel(DesignDocumentView::pasteToModel());
-
- if (!pasteModel)
- return;
-
- DesignDocumentView view;
- pasteModel->attachView(&view);
-
- if (!view.rootModelNode().isValid())
- return;
-
- const qreal currentTime = timeline.currentKeyframe();
-
- ModelNode rootNode = view.rootModelNode();
-
- try {
- RewriterTransaction transaction(
- timelineView->beginRewriterTransaction("TimelineActions::pasteKeyframes"));
- if (isKeyframe(rootNode))
- pasteKeyframe(currentTime, rootNode, timelineView, timeline);
- else
- for (auto frame : getFramesRelative(rootNode))
- pasteKeyframe(currentTime + std::get<1>(frame),
- std::get<0>(frame),
- timelineView,
- timeline);
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-bool TimelineActions::clipboardContainsKeyframes()
-{
- QScopedPointer<Model> pasteModel(DesignDocumentView::pasteToModel());
-
- if (!pasteModel)
- return false;
-
- DesignDocumentView view;
- pasteModel->attachView(&view);
-
- if (!view.rootModelNode().isValid())
- return false;
-
- ModelNode rootNode = view.rootModelNode();
-
- if (!rootNode.hasAnySubModelNodes())
- return false;
-
- //Sanity check
- if (!QmlTimelineKeyframeGroup::checkKeyframesType(rootNode)) {
- for (const ModelNode &node : rootNode.directSubModelNodes())
- if (!QmlTimelineKeyframeGroup::checkKeyframesType(node))
- return false;
- }
-
- return true;
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.cpp
deleted file mode 100644
index 65f77a0e5f..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineanimationform.cpp
+++ /dev/null
@@ -1,262 +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 "timelineanimationform.h"
-#include "ui_timelineanimationform.h"
-
-#include <abstractview.h>
-#include <bindingproperty.h>
-#include <exception>
-#include <nodelistproperty.h>
-#include <nodemetainfo.h>
-#include <rewritertransaction.h>
-#include <signalhandlerproperty.h>
-#include <variantproperty.h>
-#include <qmlitemnode.h>
-#include <qmlobjectnode.h>
-
-#include <coreplugin/messagebox.h>
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-namespace QmlDesigner {
-
-TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::TimelineAnimationForm)
-{
- ui->setupUi(this);
-
- connectSpinBox(ui->duration, "duration");
- connectSpinBox(ui->loops, "loops");
-
- connectSpinBox(ui->startFrame, "from");
- connectSpinBox(ui->endFrame, "to");
-
- connect(ui->loops, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this]() {
- ui->continuous->setChecked(ui->loops->value() == -1);
- });
-
- connect(ui->continuous, &QCheckBox::toggled, [this](bool checked) {
- if (checked) {
- setProperty("loops", -1);
- ui->loops->setValue(-1);
- } else {
- setProperty("loops", 1);
- ui->loops->setValue(1);
- }
- });
-
- connect(ui->idLineEdit, &QLineEdit::editingFinished, [this]() {
- QTC_ASSERT(m_timeline.isValid(), return );
-
- static QString lastString;
-
- const QString newId = ui->idLineEdit->text();
-
- if (lastString == newId)
- return;
-
- lastString = newId;
-
- if (newId == animation().id())
- return;
-
- bool error = false;
-
- if (!ModelNode::isValidId(newId)) {
- Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
- tr("%1 is an invalid id.").arg(newId));
- error = true;
- } else if (animation().view()->hasId(newId)) {
- Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
- tr("%1 already exists.").arg(newId));
- } else {
- animation().setIdWithRefactoring(newId);
- error = true;
- }
-
- if (error) {
- lastString.clear();
- ui->idLineEdit->setText(animation().id());
- }
- });
-
- connect(ui->running, &QCheckBox::clicked, [this](bool checked) {
- if (checked) {
- setProperty("running", true);
- } else {
- setProperty("running", false);
- }
- });
-
- connect(ui->pingPong, &QCheckBox::clicked, [this](bool checked) {
- if (checked) {
- setProperty("pingPong", true);
- } else {
- setProperty("pingPong", false);
- }
- });
-
- connect(ui->transitionToState,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
- [this](int index) {
- if (!m_animation.isValid())
- return;
- if (!m_animation.view()->rootModelNode().hasId())
- return;
-
- ModelNode rootNode = m_animation.view()->rootModelNode();
-
- if (index == 0) {
- if (m_animation.signalHandlerProperty("onFinished").isValid())
- m_animation.removeProperty("onFinished");
- } else if (index == 1) {
- m_animation.signalHandlerProperty("onFinished")
- .setSource(rootNode.id() + ".state = \"" + "\"");
- } else {
- m_animation.signalHandlerProperty("onFinished")
- .setSource(rootNode.id() + ".state = \""
- + ui->transitionToState->currentText() + "\"");
- }
- });
-}
-
-TimelineAnimationForm::~TimelineAnimationForm()
-{
- delete ui;
-}
-
-void TimelineAnimationForm::setup(const ModelNode &animation)
-{
- m_timeline = QmlTimeline(animation.parentProperty().parentModelNode());
- setAnimation(animation);
- setupAnimation();
-}
-
-ModelNode TimelineAnimationForm::animation() const
-{
- return m_animation;
-}
-
-void TimelineAnimationForm::setAnimation(const ModelNode &animation)
-{
- m_animation = animation;
-}
-
-void TimelineAnimationForm::setupAnimation()
-{
- if (!m_animation.isValid())
- setEnabled(false);
-
- if (m_animation.isValid()) {
- setEnabled(true);
-
- ui->idLineEdit->setText(m_animation.id());
-
- if (m_animation.hasVariantProperty("duration"))
- ui->duration->setValue(m_animation.variantProperty("duration").value().toInt());
- else
- ui->duration->setValue(0);
-
- ui->startFrame->setValue(m_animation.variantProperty("from").value().toInt());
- ui->endFrame->setValue(m_animation.variantProperty("to").value().toInt());
-
- if (m_animation.hasVariantProperty("loops"))
- ui->loops->setValue(m_animation.variantProperty("loops").value().toInt());
- else
- ui->loops->setValue(0);
-
- if (m_animation.hasVariantProperty("running"))
- ui->running->setChecked(m_animation.variantProperty("running").value().toBool());
- else
- ui->running->setChecked(false);
-
- if (m_animation.hasVariantProperty("pingPong"))
- ui->pingPong->setChecked(m_animation.variantProperty("pingPong").value().toBool());
- else
- ui->pingPong->setChecked(false);
-
- ui->continuous->setChecked(ui->loops->value() == -1);
- }
-
- populateStateComboBox();
-
- ui->duration->setEnabled(m_animation.isValid());
- ui->running->setEnabled(m_animation.isValid());
- ui->continuous->setEnabled(m_animation.isValid());
- ui->loops->setEnabled(m_animation.isValid());
-}
-
-void TimelineAnimationForm::setProperty(const PropertyName &propertyName, const QVariant &value)
-{
- QTC_ASSERT(m_animation.isValid(), return );
-
- try {
- m_animation.variantProperty(propertyName).setValue(value);
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-void TimelineAnimationForm::connectSpinBox(QSpinBox *spinBox, const PropertyName &propertyName)
-{
- connect(spinBox, &QSpinBox::editingFinished, [this, propertyName, spinBox]() {
- setProperty(propertyName, spinBox->value());
- });
-}
-
-void TimelineAnimationForm::populateStateComboBox()
-{
- ui->transitionToState->clear();
- ui->transitionToState->addItem(tr("none"));
- ui->transitionToState->addItem(tr("Base State"));
- if (!m_animation.isValid())
- return;
- QmlObjectNode rootNode = QmlObjectNode(m_animation.view()->rootModelNode());
- if (rootNode.isValid() && rootNode.modelNode().hasId()) {
- for (const QmlModelState &state : QmlItemNode(rootNode).states().allStates()) {
- ui->transitionToState
- ->addItem(state.modelNode().variantProperty("name").value().toString(),
- QVariant::fromValue<ModelNode>(state.modelNode()));
- }
- if (m_animation.signalHandlerProperty("onFinished").isValid()) {
- const QString source = m_animation.signalHandlerProperty("onFinished").source();
- const QStringList list = source.split("=");
- if (list.count() == 2) {
- QString name = list.last().trimmed();
- name.chop(1);
- name.remove(0, 1);
- if (name.isEmpty())
- ui->transitionToState->setCurrentIndex(1);
- else
- ui->transitionToState->setCurrentText(name);
- }
- }
- }
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicslayout.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicslayout.cpp
deleted file mode 100644
index 57daef4966..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicslayout.cpp
+++ /dev/null
@@ -1,160 +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 "timelinegraphicslayout.h"
-
-#include "timelinegraphicsscene.h"
-#include "timelineplaceholder.h"
-#include "timelinesectionitem.h"
-#include "timelineview.h"
-
-#include <QGraphicsLinearLayout>
-
-#include <cmath>
-
-namespace QmlDesigner {
-
-TimelineGraphicsLayout::TimelineGraphicsLayout(TimelineGraphicsScene *scene, TimelineItem *parent)
- : TimelineItem(parent)
- , m_layout(new QGraphicsLinearLayout)
- , m_rulerItem(TimelineRulerSectionItem::create(scene, this))
- , m_placeholder1(TimelinePlaceholder::create(scene, this))
- , m_placeholder2(TimelinePlaceholder::create(scene, this))
-{
- m_layout->setOrientation(Qt::Vertical);
- m_layout->setSpacing(0);
- m_layout->setContentsMargins(0, 0, 0, 0);
-
- m_layout->addItem(m_rulerItem);
- m_layout->addItem(m_placeholder1);
- m_layout->addItem(m_placeholder2);
-
- setLayout(m_layout);
-
- setPos(QPointF(0, 0));
-
- connect(m_rulerItem,
- &TimelineRulerSectionItem::rulerClicked,
- this,
- &TimelineGraphicsLayout::rulerClicked);
-}
-
-TimelineGraphicsLayout::~TimelineGraphicsLayout() = default;
-
-double TimelineGraphicsLayout::rulerWidth() const
-{
- return m_rulerItem->preferredWidth();
-}
-
-double TimelineGraphicsLayout::rulerScaling() const
-{
- return m_rulerItem->rulerScaling();
-}
-
-double TimelineGraphicsLayout::rulerDuration() const
-{
- return m_rulerItem->rulerDuration();
-}
-
-double TimelineGraphicsLayout::startFrame() const
-{
- return m_rulerItem->startFrame();
-}
-
-double TimelineGraphicsLayout::endFrame() const
-{
- return m_rulerItem->endFrame();
-}
-
-void TimelineGraphicsLayout::setWidth(int width)
-{
- m_rulerItem->setSizeHints(width);
- m_placeholder1->setMinimumWidth(width);
- m_placeholder2->setMinimumWidth(width);
- setPreferredWidth(width);
- setMaximumWidth(width);
-}
-
-void TimelineGraphicsLayout::setTimeline(const QmlTimeline &timeline)
-{
- m_layout->removeItem(m_rulerItem);
- m_layout->removeItem(m_placeholder1);
- m_layout->removeItem(m_placeholder2);
-
- m_rulerItem->setParentItem(nullptr);
- m_placeholder1->setParentItem(nullptr);
- m_placeholder2->setParentItem(nullptr);
-
- qDeleteAll(this->childItems());
-
- m_rulerItem->setParentItem(this);
- m_rulerItem->invalidateRulerSize(timeline);
- m_layout->addItem(m_rulerItem);
-
- m_placeholder1->setParentItem(this);
- m_layout->addItem(m_placeholder1);
-
- m_layout->invalidate();
-
- if (timeline.isValid()) {
- for (const ModelNode &target : timeline.allTargets()) {
- auto item = TimelineSectionItem::create(timeline, target, this);
- m_layout->addItem(item);
- }
- }
-
- m_placeholder2->setParentItem(this);
- m_layout->addItem(m_placeholder2);
-
- if (auto *scene = timelineScene())
- if (auto *view = scene->timelineView())
- if (!timeline.isValid() && view->isAttached())
- emit scaleFactorChanged(0);
-}
-
-void TimelineGraphicsLayout::setRulerScaleFactor(int factor)
-{
- m_rulerItem->setRulerScaleFactor(factor);
-}
-
-void TimelineGraphicsLayout::invalidate()
-{
- m_layout->invalidate();
-}
-
-int TimelineGraphicsLayout::maximumScrollValue() const
-{
- const qreal w = this->geometry().width() - qreal(TimelineConstants::sectionWidth);
- const qreal duration = m_rulerItem->rulerDuration() + m_rulerItem->rulerDuration() * 0.1;
- const qreal maxr = m_rulerItem->rulerScaling() * duration - w;
- return std::round(qMax(maxr, 0.0));
-}
-
-void TimelineGraphicsLayout::activate()
-{
- m_layout->activate();
-}
-
-} // End namespace QmlDesigner.
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicsscene.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicsscene.cpp
deleted file mode 100644
index eb09492397..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinegraphicsscene.cpp
+++ /dev/null
@@ -1,733 +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 "timelinegraphicsscene.h"
-
-#include "timelineactions.h"
-#include "timelinegraphicslayout.h"
-#include "timelineitem.h"
-#include "timelinemovableabstractitem.h"
-#include "timelinemovetool.h"
-#include "timelineplaceholder.h"
-#include "timelinepropertyitem.h"
-#include "timelinesectionitem.h"
-#include "timelinetoolbar.h"
-#include "timelineview.h"
-#include "timelinewidget.h"
-
-#include <designdocumentview.h>
-#include <exception.h>
-#include <rewritertransaction.h>
-#include <rewriterview.h>
-#include <viewmanager.h>
-#include <qmldesignerplugin.h>
-#include <qmlobjectnode.h>
-#include <qmltimelinekeyframegroup.h>
-
-#include <bindingproperty.h>
-
-#include <nodeabstractproperty.h>
-#include <nodelistproperty.h>
-#include <variantproperty.h>
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-#include <QComboBox>
-#include <QGraphicsLinearLayout>
-#include <QGraphicsProxyWidget>
-#include <QGraphicsSceneMouseEvent>
-#include <QGraphicsView>
-#include <QKeyEvent>
-
-#include <cmath>
-
-namespace QmlDesigner {
-
-QList<QmlTimelineKeyframeGroup> allTimelineFrames(const QmlTimeline &timeline)
-{
- QList<QmlTimelineKeyframeGroup> returnList;
-
- for (const ModelNode &childNode :
- timeline.modelNode().defaultNodeListProperty().toModelNodeList()) {
- if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(childNode))
- returnList.append(QmlTimelineKeyframeGroup(childNode));
- }
-
- return returnList;
-}
-
-TimelineGraphicsScene::TimelineGraphicsScene(TimelineWidget *parent)
- : QGraphicsScene(parent)
- , m_parent(parent)
- , m_layout(new TimelineGraphicsLayout(this))
- , m_currentFrameIndicator(new TimelineFrameHandle)
- , m_tools(this)
-{
- addItem(m_layout);
- addItem(m_currentFrameIndicator);
-
- setSceneRect(m_layout->geometry());
-
- connect(m_layout, &QGraphicsWidget::geometryChanged, this, [this]() {
- auto rect = m_layout->geometry();
-
- setSceneRect(rect);
-
- if (auto *gview = graphicsView())
- gview->setSceneRect(rect.adjusted(0, TimelineConstants::rulerHeight, 0, 0));
-
- if (auto *rview = rulerView())
- rview->setSceneRect(rect);
-
- m_currentFrameIndicator->setHeight(m_layout->geometry().height());
- });
-
- auto moveFrameIndicator = [this](const QPointF &pos) {
- m_currentFrameIndicator->commitPosition(pos);
- };
- connect(m_layout, &TimelineGraphicsLayout::rulerClicked, moveFrameIndicator);
-
- auto changeScale = [this](int factor) {
- timelineWidget()->changeScaleFactor(factor);
- setRulerScaling(qreal(factor));
- };
- connect(m_layout, &TimelineGraphicsLayout::scaleFactorChanged, changeScale);
-}
-
-TimelineGraphicsScene::~TimelineGraphicsScene()
-{
- QSignalBlocker block(this);
- clearSelection();
- qDeleteAll(items());
-}
-
-void TimelineGraphicsScene::onShow()
-{
- if (timelineView()->isAttached()) {
- auto timeline = currentTimeline();
- if (timeline.isValid()) {
- int cf = std::round(timeline.currentKeyframe());
- setCurrentFrame(cf);
- }
-
- emit m_layout->scaleFactorChanged(0);
- }
-}
-
-void TimelineGraphicsScene::setTimeline(const QmlTimeline &timeline)
-{
- if (qFuzzyCompare(timeline.duration(), 0.0))
- return;
-
- m_layout->setTimeline(timeline);
-}
-
-void TimelineGraphicsScene::clearTimeline()
-{
- m_layout->setTimeline(QmlTimeline());
-}
-
-void TimelineGraphicsScene::setWidth(int width)
-{
- m_layout->setWidth(width);
- invalidateScrollbar();
-}
-
-void TimelineGraphicsScene::invalidateLayout()
-{
- m_layout->invalidate();
-}
-
-void TimelineGraphicsScene::setCurrenFrame(const QmlTimeline &timeline, qreal frame)
-{
- if (timeline.isValid())
- m_currentFrameIndicator->setPosition(frame);
- else
- m_currentFrameIndicator->setPosition(0);
-
- invalidateCurrentValues();
-}
-
-void TimelineGraphicsScene::setCurrentFrame(int frame)
-{
- QmlTimeline timeline(timelineModelNode());
-
- if (timeline.isValid()) {
- timeline.modelNode().setAuxiliaryData("currentFrame@NodeInstance", frame);
- m_currentFrameIndicator->setPosition(frame + timeline.startKeyframe());
- } else {
- m_currentFrameIndicator->setPosition(0);
- }
-
- invalidateCurrentValues();
-
- emitStatusBarFrameMessageChanged(frame);
-}
-
-void TimelineGraphicsScene::setStartFrame(int frame)
-{
- QmlTimeline timeline(timelineModelNode());
-
- if (timeline.isValid())
- timeline.modelNode().variantProperty("startFrame").setValue(frame);
-}
-
-void TimelineGraphicsScene::setEndFrame(int frame)
-{
- QmlTimeline timeline(timelineModelNode());
-
- if (timeline.isValid())
- timeline.modelNode().variantProperty("endFrame").setValue(frame);
-}
-
-qreal TimelineGraphicsScene::rulerScaling() const
-{
- return m_layout->rulerScaling();
-}
-
-int TimelineGraphicsScene::rulerWidth() const
-{
- return m_layout->rulerWidth();
-}
-
-qreal TimelineGraphicsScene::rulerDuration() const
-{
- return m_layout->rulerDuration();
-}
-
-qreal TimelineGraphicsScene::startFrame() const
-{
- return m_layout->startFrame();
-}
-
-qreal TimelineGraphicsScene::endFrame() const
-{
- return m_layout->endFrame();
-}
-
-qreal TimelineGraphicsScene::mapToScene(qreal x) const
-{
- return TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
- + (x - startFrame()) * rulerScaling() - scrollOffset();
-}
-
-qreal TimelineGraphicsScene::mapFromScene(qreal x) const
-{
- auto xPosOffset = (x - TimelineConstants::sectionWidth - TimelineConstants::timelineLeftOffset)
- + scrollOffset();
-
- return xPosOffset / rulerScaling() + startFrame();
-}
-
-qreal TimelineGraphicsScene::currentFramePosition() const
-{
- return currentTimeline().currentKeyframe();
-}
-
-QVector<qreal> TimelineGraphicsScene::keyframePositions() const
-{
- QVector<qreal> positions;
- for (const auto &frames : allTimelineFrames(currentTimeline()))
- positions.append(keyframePositions(frames));
- return positions;
-}
-
-QVector<qreal> TimelineGraphicsScene::keyframePositions(const QmlTimelineKeyframeGroup &frames) const
-{
- const QList<ModelNode> keyframes = frames.keyframePositions();
- QVector<qreal> positions;
- for (const ModelNode &modelNode : keyframes)
- positions.append(modelNode.variantProperty("frame").value().toReal());
- return positions;
-}
-
-void TimelineGraphicsScene::setRulerScaling(int scaleFactor)
-{
- const qreal oldOffset = scrollOffset();
- const qreal oldScaling = m_layout->rulerScaling();
- const qreal oldPosition = mapToScene(currentFramePosition());
- m_layout->setRulerScaleFactor(scaleFactor);
-
- const qreal newScaling = m_layout->rulerScaling();
- const qreal newPosition = mapToScene(currentFramePosition());
-
- const qreal newOffset = oldOffset + (newPosition - oldPosition);
-
- if (std::isinf(oldScaling) || std::isinf(newScaling))
- setScrollOffset(0);
- else {
- setScrollOffset(std::round(newOffset));
-
- const qreal start = mapToScene(startFrame());
- const qreal head = TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset;
-
- if (start - head > 0)
- setScrollOffset(0);
- }
-
- invalidateSections();
- QmlTimeline timeline(timelineModelNode());
-
- if (timeline.isValid())
- setCurrenFrame(timeline,
- timeline.modelNode().auxiliaryData("currentFrame@NodeInstance").toReal());
-
- invalidateScrollbar();
- update();
-}
-
-void TimelineGraphicsScene::commitCurrentFrame(qreal frame)
-{
- QmlTimeline timeline(timelineModelNode());
-
- if (timeline.isValid()) {
- timeline.modelNode().setAuxiliaryData("currentFrame@NodeInstance", qRound(frame));
- setCurrenFrame(timeline, qRound(frame));
- invalidateCurrentValues();
- }
- emitStatusBarFrameMessageChanged(int(frame));
-}
-
-QList<TimelineKeyframeItem *> TimelineGraphicsScene::selectedKeyframes() const
-{
- return m_selectedKeyframes;
-}
-
-bool TimelineGraphicsScene::hasSelection() const
-{
- return !m_selectedKeyframes.empty();
-}
-
-bool TimelineGraphicsScene::isCurrent(TimelineKeyframeItem *keyframe) const
-{
- if (m_selectedKeyframes.empty())
- return false;
-
- return m_selectedKeyframes.back() == keyframe;
-}
-
-bool TimelineGraphicsScene::isKeyframeSelected(TimelineKeyframeItem *keyframe) const
-{
- return m_selectedKeyframes.contains(keyframe);
-}
-
-bool TimelineGraphicsScene::multipleKeyframesSelected() const
-{
- return m_selectedKeyframes.count() > 1;
-}
-
-void TimelineGraphicsScene::invalidateSectionForTarget(const ModelNode &target)
-{
- if (!target.isValid())
- return;
-
- bool found = false;
- for (auto child : m_layout->childItems())
- TimelineSectionItem::updateDataForTarget(child, target, &found);
-
- if (!found)
- invalidateScene();
-
- clearSelection();
- invalidateLayout();
-}
-
-void TimelineGraphicsScene::invalidateKeyframesForTarget(const ModelNode &target)
-{
- for (auto child : m_layout->childItems())
- TimelineSectionItem::updateFramesForTarget(child, target);
-}
-
-void TimelineGraphicsScene::invalidateScene()
-{
- ModelNode node = timelineView()->modelNodeForId(
- timelineWidget()->toolBar()->currentTimelineId());
- setTimeline(QmlTimeline(node));
- invalidateScrollbar();
-}
-
-void TimelineGraphicsScene::invalidateScrollbar()
-{
- double max = m_layout->maximumScrollValue();
- timelineWidget()->setupScrollbar(0, max, scrollOffset());
- if (scrollOffset() > max)
- setScrollOffset(max);
-}
-
-void TimelineGraphicsScene::invalidateCurrentValues()
-{
- for (auto item : items())
- TimelinePropertyItem::updateTextEdit(item);
-}
-
-void TimelineGraphicsScene::invalidateRecordButtonsStatus()
-{
- for (auto item : items())
- TimelinePropertyItem::updateRecordButtonStatus(item);
-}
-
-int TimelineGraphicsScene::scrollOffset() const
-{
- return m_scrollOffset;
-}
-
-void TimelineGraphicsScene::setScrollOffset(int offset)
-{
- m_scrollOffset = offset;
- emitScrollOffsetChanged();
- update();
-}
-
-QGraphicsView *TimelineGraphicsScene::graphicsView() const
-{
- for (auto *v : views())
- if (v->objectName() == "SceneView")
- return v;
-
- return nullptr;
-}
-
-QGraphicsView *TimelineGraphicsScene::rulerView() const
-{
- for (auto *v : views())
- if (v->objectName() == "RulerView")
- return v;
-
- return nullptr;
-}
-
-QmlTimeline TimelineGraphicsScene::currentTimeline() const
-{
- return QmlTimeline(timelineModelNode());
-}
-
-QRectF TimelineGraphicsScene::selectionBounds() const
-{
- QRectF bbox;
-
- for (auto *frame : m_selectedKeyframes)
- bbox = bbox.united(frame->rect());
-
- return bbox;
-}
-
-void TimelineGraphicsScene::selectKeyframes(const SelectionMode &mode,
- const QList<TimelineKeyframeItem *> &items)
-{
- if (mode == SelectionMode::Remove || mode == SelectionMode::Toggle) {
- for (auto *item : items) {
- if (auto *keyframe = TimelineMovableAbstractItem::asTimelineKeyframeItem(item)) {
- if (m_selectedKeyframes.contains(keyframe)) {
- keyframe->setHighlighted(false);
- m_selectedKeyframes.removeAll(keyframe);
-
- } else if (mode == SelectionMode::Toggle) {
- if (!m_selectedKeyframes.contains(keyframe)) {
- keyframe->setHighlighted(true);
- m_selectedKeyframes << keyframe;
- }
- }
- }
- }
-
- } else {
- if (mode == SelectionMode::New)
- clearSelection();
-
- for (auto item : items) {
- if (auto *keyframe = TimelineMovableAbstractItem::asTimelineKeyframeItem(item)) {
- if (!m_selectedKeyframes.contains(keyframe)) {
- keyframe->setHighlighted(true);
- m_selectedKeyframes.append(keyframe);
- }
- }
- }
- }
- emit selectionChanged();
-}
-
-void TimelineGraphicsScene::clearSelection()
-{
- for (auto *keyframe : m_selectedKeyframes)
- if (keyframe)
- keyframe->setHighlighted(false);
-
- m_selectedKeyframes.clear();
-}
-
-QList<QGraphicsItem *> TimelineGraphicsScene::itemsAt(const QPointF &pos)
-{
- QTransform transform;
-
- if (auto *gview = graphicsView())
- transform = gview->transform();
-
- return items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder, transform);
-}
-
-void TimelineGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
- m_tools.mousePressEvent(topItem, event);
- QGraphicsScene::mousePressEvent(event);
-}
-
-void TimelineGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
-{
- auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
- m_tools.mouseMoveEvent(topItem, event);
- QGraphicsScene::mouseMoveEvent(event);
-}
-
-void TimelineGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
- auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
- /* The tool has handle the event last. */
- QGraphicsScene::mouseReleaseEvent(event);
- m_tools.mouseReleaseEvent(topItem, event);
-}
-
-void TimelineGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
-{
- auto topItem = TimelineMovableAbstractItem::topMoveableItem(itemsAt(event->scenePos()));
- m_tools.mouseDoubleClickEvent(topItem, event);
- QGraphicsScene::mouseDoubleClickEvent(event);
-}
-
-void TimelineGraphicsScene::keyPressEvent(QKeyEvent *keyEvent)
-{
- if (qgraphicsitem_cast<QGraphicsProxyWidget *>(focusItem())) {
- keyEvent->ignore();
- QGraphicsScene::keyPressEvent(keyEvent);
- return;
- }
-
- if (keyEvent->modifiers().testFlag(Qt::ControlModifier)) {
- switch (keyEvent->key()) {
- case Qt::Key_C:
- copySelectedKeyframes();
- break;
-
- case Qt::Key_V:
- pasteSelectedKeyframes();
- break;
-
- default:
- QGraphicsScene::keyPressEvent(keyEvent);
- break;
- }
- } else {
- switch (keyEvent->key()) {
- case Qt::Key_Left:
- emit scroll(TimelineUtils::Side::Left);
- keyEvent->accept();
- break;
-
- case Qt::Key_Right:
- emit scroll(TimelineUtils::Side::Right);
- keyEvent->accept();
- break;
-
- default:
- QGraphicsScene::keyPressEvent(keyEvent);
- break;
- }
- }
-}
-
-void TimelineGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
-{
- if (qgraphicsitem_cast<QGraphicsProxyWidget *>(focusItem())) {
- keyEvent->ignore();
- QGraphicsScene::keyReleaseEvent(keyEvent);
- return;
- }
-
- switch (keyEvent->key()) {
- case Qt::Key_Delete:
- handleKeyframeDeletion();
- break;
-
- default:
- break;
- }
-
- QGraphicsScene::keyReleaseEvent(keyEvent);
-}
-
-void TimelineGraphicsScene::invalidateSections()
-{
- for (auto child : m_layout->childItems())
- TimelineSectionItem::updateData(child);
-
- clearSelection();
- invalidateLayout();
-}
-
-TimelineView *TimelineGraphicsScene::timelineView() const
-{
- return m_parent->timelineView();
-}
-
-TimelineWidget *TimelineGraphicsScene::timelineWidget() const
-{
- return m_parent;
-}
-
-TimelineToolBar *TimelineGraphicsScene::toolBar() const
-{
- return timelineWidget()->toolBar();
-}
-
-ModelNode TimelineGraphicsScene::timelineModelNode() const
-{
- if (timelineView()->isAttached()) {
- const QString timelineId = timelineWidget()->toolBar()->currentTimelineId();
- return timelineView()->modelNodeForId(timelineId);
- }
-
- return ModelNode();
-}
-
-void TimelineGraphicsScene::handleKeyframeDeletion()
-{
- QList<ModelNode> nodesToBeDeleted;
- for (auto keyframe : m_selectedKeyframes) {
- nodesToBeDeleted.append(keyframe->frameNode());
- }
- deleteKeyframes(nodesToBeDeleted);
-}
-
-void TimelineGraphicsScene::deleteAllKeyframesForTarget(const ModelNode &targetNode)
-{
- TimelineActions::deleteAllKeyframesForTarget(targetNode, currentTimeline());
-}
-
-void TimelineGraphicsScene::insertAllKeyframesForTarget(const ModelNode &targetNode)
-{
- TimelineActions::insertAllKeyframesForTarget(targetNode, currentTimeline());
-}
-
-void TimelineGraphicsScene::copyAllKeyframesForTarget(const ModelNode &targetNode)
-{
- TimelineActions::copyAllKeyframesForTarget(targetNode, currentTimeline());
-}
-
-void TimelineGraphicsScene::pasteKeyframesToTarget(const ModelNode &targetNode)
-{
- TimelineActions::pasteKeyframesToTarget(targetNode, currentTimeline());
-}
-
-void TimelineGraphicsScene::copySelectedKeyframes()
-{
- TimelineActions::copyKeyframes(
- Utils::transform(m_selectedKeyframes, &TimelineKeyframeItem::frameNode));
-}
-
-void TimelineGraphicsScene::pasteSelectedKeyframes()
-{
- TimelineActions::pasteKeyframes(timelineView(), currentTimeline());
-}
-
-void TimelineGraphicsScene::handleKeyframeInsertion(const ModelNode &target,
- const PropertyName &propertyName)
-{
- timelineView()->insertKeyframe(target, propertyName);
-}
-
-void TimelineGraphicsScene::deleteKeyframeGroup(const ModelNode &group)
-{
- if (!QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(group))
- return;
-
- ModelNode nonConst = group;
-
- try {
- RewriterTransaction transaction(timelineView()->beginRewriterTransaction(
- "TimelineGraphicsScene::handleKeyframeGroupDeletion"));
-
- nonConst.destroy();
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-void TimelineGraphicsScene::deleteKeyframes(const QList<ModelNode> &frames)
-{
- try {
- RewriterTransaction transaction(timelineView()->beginRewriterTransaction(
- "TimelineGraphicsScene::handleKeyframeDeletion"));
-
- for (auto keyframe : frames) {
- if (keyframe.isValid()) {
- ModelNode frame = keyframe;
- ModelNode parent = frame.parentProperty().parentModelNode();
- keyframe.destroy();
- if (parent.isValid() && parent.defaultNodeListProperty().isEmpty())
- parent.destroy();
- }
- }
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-}
-
-void TimelineGraphicsScene::activateLayout()
-{
- m_layout->activate();
-}
-
-void TimelineGraphicsScene::emitScrollOffsetChanged()
-{
- for (QGraphicsItem *item : items())
- TimelineMovableAbstractItem::emitScrollOffsetChanged(item);
-}
-
-void TimelineGraphicsScene::emitStatusBarFrameMessageChanged(int frame)
-{
- emit statusBarMessageChanged(
- QString(TimelineConstants::timelineStatusBarFrameNumber).arg(frame));
-}
-
-bool TimelineGraphicsScene::event(QEvent *event)
-{
- switch (event->type()) {
- case QEvent::ShortcutOverride:
- if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Delete) {
- QGraphicsScene::keyPressEvent(static_cast<QKeyEvent *>(event));
- event->accept();
- return true;
- }
- Q_FALLTHROUGH();
- default:
- return QGraphicsScene::event(event);
- }
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovetool.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovetool.cpp
deleted file mode 100644
index 49d35b781b..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinemovetool.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 "timelinemovetool.h"
-
-#include "timelinegraphicsscene.h"
-#include "timelinemovableabstractitem.h"
-#include "timelinepropertyitem.h"
-#include "timelineview.h"
-
-#include <exception.h>
-
-#include <QGraphicsScene>
-#include <QGraphicsSceneMouseEvent>
-
-#include <cmath>
-
-namespace QmlDesigner {
-
-static QPointF mapPointToItem(TimelineMovableAbstractItem *item, const QPointF &pos)
-{
- if (auto parent = item->parentItem())
- return parent->mapFromScene(pos);
- return pos;
-}
-
-QPointF mapToItem(TimelineMovableAbstractItem *item, const QPointF &pos)
-{
- if (auto parent = item->parentItem())
- return parent->mapFromScene(pos);
- return pos;
-}
-
-QPointF mapToItem(TimelineMovableAbstractItem *item, QGraphicsSceneMouseEvent *event)
-{
- if (auto parent = item->parentItem())
- return parent->mapFromScene(event->scenePos());
- return event->scenePos();
-}
-
-TimelineMoveTool::TimelineMoveTool(TimelineGraphicsScene *scene, TimelineToolDelegate *delegate)
- : TimelineAbstractTool(scene, delegate)
-{}
-
-void TimelineMoveTool::mousePressEvent(TimelineMovableAbstractItem *item,
- QGraphicsSceneMouseEvent *event)
-{
- Q_UNUSED(item);
- Q_UNUSED(event);
-}
-
-void TimelineMoveTool::mouseMoveEvent(TimelineMovableAbstractItem *item,
- QGraphicsSceneMouseEvent *event)
-{
- Q_UNUSED(item);
-
- if (!currentItem())
- return;
-
- if (auto *current = currentItem()->asTimelineKeyframeItem()) {
- const qreal sourceFrame = qRound(current->mapFromSceneToFrame(current->rect().center().x()));
- const qreal targetFrame = qRound(current->mapFromSceneToFrame(event->scenePos().x()));
- qreal deltaFrame = targetFrame - sourceFrame;
-
- const qreal minFrame = scene()->startFrame();
- const qreal maxFrame = scene()->endFrame();
-
- auto bbox = scene()->selectionBounds().united(current->rect());
-
- double firstFrame = std::round(current->mapFromSceneToFrame(bbox.center().x()));
- double lastFrame = std::round(current->mapFromSceneToFrame(bbox.center().x()));
-
- if ((lastFrame + deltaFrame) > maxFrame)
- deltaFrame = maxFrame - lastFrame;
-
- if ((firstFrame + deltaFrame) <= minFrame)
- deltaFrame = minFrame - firstFrame;
-
- current->setPosition(sourceFrame + deltaFrame);
-
- for (auto *keyframe : scene()->selectedKeyframes()) {
- if (keyframe != current) {
- qreal pos = std::round(current->mapFromSceneToFrame(keyframe->rect().center().x()));
- keyframe->setPosition(pos + deltaFrame);
- }
- }
-
- } else {
- currentItem()->itemMoved(mapPointToItem(currentItem(), startPosition()),
- mapToItem(currentItem(), event));
- }
-}
-
-void TimelineMoveTool::mouseReleaseEvent(TimelineMovableAbstractItem *item,
- QGraphicsSceneMouseEvent *event)
-{
- Q_UNUSED(item);
- Q_UNUSED(event);
-
- if (auto *current = currentItem()) {
- if (current->asTimelineFrameHandle()) {
- double mousePos = event->pos().x();
- double start = current->mapFromFrameToScene(scene()->startFrame());
- double end = current->mapFromFrameToScene(scene()->endFrame());
-
- if (mousePos < start) {
- scene()->setCurrentFrame(scene()->startFrame());
- scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(scene()->startFrame()));
- return;
- } else if (mousePos > end) {
- scene()->setCurrentFrame(scene()->endFrame());
- scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(scene()->endFrame()));
- return;
- }
- }
-
- try {
- RewriterTransaction transaction(scene()->timelineView()->beginRewriterTransaction(
- "TimelineMoveTool::mouseReleaseEvent"));
-
- current->commitPosition(mapToItem(current, current->rect().center()));
-
- if (current->asTimelineKeyframeItem()) {
- double frame = std::round(
- current->mapFromSceneToFrame(current->rect().center().x()));
-
- scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(frame));
-
- for (auto keyframe : scene()->selectedKeyframes())
- if (keyframe != current)
- keyframe->commitPosition(mapToItem(current, keyframe->rect().center()));
- }
-
- transaction.commit();
-
- } catch (const Exception &e) {
- e.showException();
- }
- }
-}
-
-void TimelineMoveTool::mouseDoubleClickEvent(TimelineMovableAbstractItem *item,
- QGraphicsSceneMouseEvent *event)
-{
- Q_UNUSED(item);
- Q_UNUSED(event);
-}
-
-void TimelineMoveTool::keyPressEvent(QKeyEvent *keyEvent)
-{
- Q_UNUSED(keyEvent);
-}
-
-void TimelineMoveTool::keyReleaseEvent(QKeyEvent *keyEvent)
-{
- Q_UNUSED(keyEvent);
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinepropertyitem.cpp
deleted file mode 100644
index d0b89dfef4..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinepropertyitem.cpp
+++ /dev/null
@@ -1,647 +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 "timelinepropertyitem.h"
-
-#include "abstractview.h"
-#include "easingcurvedialog.h"
-#include "setframevaluedialog.h"
-#include "timelineconstants.h"
-#include "timelinegraphicsscene.h"
-#include "timelineicons.h"
-#include "timelinetoolbar.h"
-#include "timelinetoolbutton.h"
-
-#include <rewritertransaction.h>
-#include <rewritingexception.h>
-#include <theme.h>
-#include <variantproperty.h>
-#include <qmlobjectnode.h>
-
-#include <coreplugin/icore.h>
-#include <utils/qtcassert.h>
-#include <utils/utilsicons.h>
-
-#include <utils/algorithm.h>
-#include <utils/fileutils.h>
-
-#include <coreplugin/icore.h>
-
-#include <QCursor>
-#include <QGraphicsProxyWidget>
-#include <QGraphicsSceneMouseEvent>
-#include <QGraphicsView>
-#include <QLineEdit>
-#include <QMenu>
-#include <QPainter>
-
-#include <algorithm>
-
-namespace QmlDesigner {
-
-static bool s_blockUpdates = false;
-
-static qreal findNext(const QVector<qreal> &vector, qreal current)
-{
- for (qreal n : vector)
- if (n > current)
- return n;
- return current;
-}
-
-static qreal findPrev(const QVector<qreal> &vector, qreal current)
-{
- for (qreal n : vector)
- if (n < current)
- return n;
- return current;
-}
-
-static QVector<qreal> getPositions(const QmlTimelineKeyframeGroup &frames)
-{
- const QList<ModelNode> keyframes = frames.keyframePositions();
- QVector<qreal> positions;
- for (const ModelNode &modelNode : keyframes)
- positions.append(modelNode.variantProperty("frame").value().toReal());
- return positions;
-}
-
-static ModelNode getModelNodeForFrame(const QmlTimelineKeyframeGroup &frames, qreal frame)
-{
- if (frames.isValid()) {
- const QList<ModelNode> keyframes = frames.keyframePositions();
- for (const ModelNode &modelNode : keyframes)
- if (qFuzzyCompare(modelNode.variantProperty("frame").value().toReal(), frame))
- return modelNode;
- }
-
- return {};
-}
-
-static void setEasingCurve(TimelineGraphicsScene *scene, const QList<ModelNode> &keys)
-{
- QTC_ASSERT(scene, return );
- EasingCurveDialog::runDialog(keys);
-}
-
-static void editValue(const ModelNode &frame, const QString &propertyName)
-{
- const QVariant value = frame.variantProperty("value").value();
- auto dialog = new SetFrameValueDialog(Core::ICore::dialogParent());
-
- dialog->lineEdit()->setText(value.toString());
- dialog->setPropertName(propertyName);
-
- QObject::connect(dialog, &SetFrameValueDialog::rejected, [dialog]() { dialog->deleteLater(); });
-
- QObject::connect(dialog, &SetFrameValueDialog::accepted, [dialog, frame, value]() {
- dialog->deleteLater();
- int userType = value.userType();
- const QVariant result = dialog->lineEdit()->text();
-
- if (result.canConvert(userType)) {
- QVariant newValue = result;
- newValue.convert(userType);
- // canConvert gives true in case if the result is a double but the usertype was interger
- // try to fix that with a workaround to convert it to double if convertion resulted in isNull
- if (newValue.isNull()) {
- newValue = result;
- newValue.convert(QMetaType::Double);
- }
- frame.variantProperty("value").setValue(result);
- }
- });
-
- dialog->show();
-}
-
-TimelinePropertyItem *TimelinePropertyItem::create(const QmlTimelineKeyframeGroup &frames,
- TimelineSectionItem *parent)
-{
- ModelNode modelnode = frames.target();
-
- bool isRecording = false;
-
- if (frames.isValid())
- isRecording = frames.isRecording();
-
- auto item = new TimelinePropertyItem(parent);
-
- auto sectionItem = new QGraphicsWidget(item);
-
- sectionItem->setGeometry(0,
- 0,
- TimelineConstants::sectionWidth,
- TimelineConstants::sectionHeight);
-
- sectionItem->setZValue(10);
- sectionItem->setCursor(Qt::ArrowCursor);
-
- item->m_frames = frames;
- item->setToolTip(item->propertyName());
- item->resize(parent->size());
- item->setupKeyframes();
-
- TimelineToolButton *buttonPrev
- = new TimelineToolButton(new QAction(TimelineIcons::PREVIOUS_KEYFRAME.icon(),
- tr("Previous Frame")),
- sectionItem);
- buttonPrev->setToolTip("Jump to previous frame.");
-
- TimelineToolButton *buttonNext
- = new TimelineToolButton(new QAction(TimelineIcons::NEXT_KEYFRAME.icon(), tr("Next Frame")),
- sectionItem);
- buttonNext->setToolTip("Jump to next frame.");
-
- connect(buttonPrev, &TimelineToolButton::clicked, item, [item]() {
- if (item->m_frames.isValid()) {
- QVector<qreal> positions = getPositions(item->m_frames);
- std::sort(positions.begin(), positions.end(), std::greater<qreal>());
- const qreal prev = findPrev(positions, item->currentFrame());
- item->timelineScene()->commitCurrentFrame(prev);
- }
- });
-
- connect(buttonNext, &TimelineToolButton::clicked, item, [item]() {
- if (item->m_frames.isValid()) {
- QVector<qreal> positions = getPositions(item->m_frames);
- std::sort(positions.begin(), positions.end(), std::less<qreal>());
- const qreal next = findNext(positions, item->currentFrame());
- item->timelineScene()->commitCurrentFrame(next);
- }
- });
-
- QIcon autoKeyIcon = TimelineUtils::mergeIcons(TimelineIcons::GLOBAL_RECORD_KEYFRAMES,
- TimelineIcons::GLOBAL_RECORD_KEYFRAMES_OFF);
- auto recact = new QAction(autoKeyIcon, tr("Auto Record"));
- recact->setCheckable(true);
- recact->setChecked(isRecording);
-
- auto toggleRecord = [frames](bool check) { frames.toogleRecording(check); };
- connect(recact, &QAction::toggled, toggleRecord);
- item->m_recording = new TimelineToolButton(recact, sectionItem);
- item->m_recording->setToolTip("Per property recording");
-
- const int buttonsY = (TimelineConstants::sectionHeight - 1 - TimelineConstants::toolButtonSize)
- / 2;
- buttonPrev->setPos(2, buttonsY);
- buttonNext->setPos(buttonPrev->size().width() + TimelineConstants::toolButtonSize + 4, buttonsY);
- item->m_recording->setPos(buttonNext->geometry().right() + 2, buttonsY);
-
- QRectF hideToolTipDummy(buttonPrev->geometry().topRight(), buttonNext->geometry().bottomLeft());
-
- auto *dummy = new QGraphicsRectItem(sectionItem);
- dummy->setPen(Qt::NoPen);
- dummy->setRect(hideToolTipDummy);
- dummy->setToolTip("Frame indicator");
-
- if (!item->m_frames.isValid())
- return item;
-
- QmlObjectNode objectNode(modelnode);
- if (!objectNode.isValid())
- return item;
-
- auto nameOfType = objectNode.modelNode().metaInfo().propertyTypeName(
- item->m_frames.propertyName());
- item->m_control = createTimelineControl(nameOfType);
- if (item->m_control) {
- item->m_control->setSize((TimelineConstants::sectionWidth / 2.6) - 10,
- item->size().height() - 2 + 1);
- item->m_control->connect(item);
- QGraphicsProxyWidget *proxy = item->timelineScene()->addWidget(item->m_control->widget());
- proxy->setParentItem(sectionItem);
- proxy->setPos(qreal(TimelineConstants::sectionWidth) * 2.0 / 3, 0);
- item->updateTextEdit();
- }
-
- updateRecordButtonStatus(item);
-
- return item;
-}
-
-int TimelinePropertyItem::type() const
-{
- return Type;
-}
-
-void TimelinePropertyItem::updateData()
-{
- for (auto child : childItems())
- delete qgraphicsitem_cast<TimelineMovableAbstractItem *>(child);
-
- setupKeyframes();
- updateTextEdit();
-}
-
-void TimelinePropertyItem::updateFrames()
-{
- for (auto child : (childItems())) {
- if (auto frameItem = qgraphicsitem_cast<TimelineMovableAbstractItem *>(child))
- static_cast<TimelineKeyframeItem *>(frameItem)->updateFrame();
- }
-}
-
-bool TimelinePropertyItem::isSelected() const
-{
- if (m_frames.isValid() && m_frames.target().isValid())
- return m_frames.target().isSelected();
-
- return false;
-}
-
-QString convertVariant(const QVariant &variant)
-{
- if (variant.userType() == QMetaType::QColor)
- return variant.toString();
-
- return QString::number(variant.toFloat(), 'f', 2);
-}
-
-void TimelinePropertyItem::updateTextEdit()
-{
- if (!m_frames.isValid())
- return;
-
- QmlObjectNode objectNode(m_frames.target());
- if (objectNode.isValid() && m_control)
- m_control->setControlValue(objectNode.instanceValue(m_frames.propertyName()));
-}
-
-void TimelinePropertyItem::updateTextEdit(QGraphicsItem *item)
-{
- if (auto timelinePropertyItem = qgraphicsitem_cast<TimelinePropertyItem *>(item))
- timelinePropertyItem->updateTextEdit();
-}
-
-void TimelinePropertyItem::updateRecordButtonStatus(QGraphicsItem *item)
-{
- if (auto timelinePropertyItem = qgraphicsitem_cast<TimelinePropertyItem *>(item)) {
- auto frames = timelinePropertyItem->m_frames;
- if (frames.isValid()) {
- timelinePropertyItem->m_recording->setChecked(frames.isRecording());
- if (frames.timeline().isValid())
- timelinePropertyItem->m_recording->setDisabled(frames.timeline().isRecording());
- }
- }
-}
-
-QmlTimelineKeyframeGroup TimelinePropertyItem::frames() const
-{
- return m_frames;
-}
-
-QString TimelinePropertyItem::propertyName() const
-{
- if (m_frames.isValid())
- return QString::fromUtf8(m_frames.propertyName());
- return QString();
-}
-
-void TimelinePropertyItem::changePropertyValue(const QVariant &value)
-{
- Q_ASSERT(m_frames.isValid());
-
- auto timeline = timelineScene()->currentTimeline();
-
- if (timelineScene()->toolBar()->recording() || m_recording->isChecked()) {
- QmlTimelineKeyframeGroup frames = m_frames;
- auto deferredFunc = [frames, value, timeline]() {
- auto constFrames = frames;
- qreal frame = timeline.modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
- try {
- constFrames.setValue(value, frame);
- } catch (const RewritingException &e) {
- e.showException();
- }
- };
-
- // QmlTimelineKeyframeGroup::setValue might create a new keyframe.
- // This might result in a temporal cleanup of the graphicsscene and
- // therefore a deletion of this property item.
- // Adding a keyframe to this already deleted item results in a crash.
- QTimer::singleShot(0, deferredFunc);
-
- } else {
- QmlObjectNode objectNode(m_frames.target());
- objectNode.setVariantProperty(m_frames.propertyName(), value);
- }
-}
-
-static int devicePixelHeight(const QPixmap &pixmap)
-{
- return pixmap.height() / pixmap.devicePixelRatioF();
-}
-
-void TimelinePropertyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
-{
- painter->save();
-
- static const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker();
- static const QColor textColor = Theme::getColor(Theme::PanelTextColorLight);
- static const QColor backgroundColor = Theme::instance()
- ->qmlDesignerBackgroundColorDarkAlternate();
-
- static const QPixmap keyframe = TimelineIcons::KEYFRAME.pixmap();
- static const QPixmap isKeyframe = TimelineIcons::IS_KEYFRAME.pixmap();
-
- painter->fillRect(0, 0, TimelineConstants::sectionWidth, size().height(), backgroundColor);
- painter->fillRect(TimelineConstants::textIndentationProperties - 4,
- 0,
- TimelineConstants::sectionWidth - TimelineConstants::textIndentationProperties
- + 4,
- size().height(),
- backgroundColor.darker(110));
-
- painter->setPen(penColor);
-
- drawLine(painter,
- TimelineConstants::sectionWidth - 1,
- 0,
- TimelineConstants::sectionWidth - 1,
- size().height());
-
- drawLine(painter,
- TimelineConstants::textIndentationProperties - 4,
- TimelineConstants::sectionHeight - 1,
- size().width(),
- TimelineConstants::sectionHeight - 1);
-
- painter->setPen(textColor);
-
- const QFontMetrics metrics(font());
-
- const QString elidedText = metrics.elidedText(propertyName(),
- Qt::ElideMiddle,
- qreal(TimelineConstants::sectionWidth) * 2.0 / 3
- - TimelineConstants::textIndentationProperties,
- 0);
-
- painter->drawText(TimelineConstants::textIndentationProperties, 12, elidedText);
-
- const bool onKeyFrame = m_frames.isValid() && getPositions(m_frames).contains(currentFrame());
- painter->drawPixmap(TimelineConstants::toolButtonSize + 3,
- (TimelineConstants::sectionHeight - 1 - devicePixelHeight(isKeyframe)) / 2,
- onKeyFrame ? isKeyframe : keyframe);
- painter->restore();
-}
-
-void TimelinePropertyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
- if (event->pos().x() < TimelineConstants::toolButtonSize * 2 + 3
- && event->pos().x() > TimelineConstants::toolButtonSize) {
- QMenu mainMenu;
-
- const ModelNode currentFrameNode = getModelNodeForFrame(m_frames, currentFrame());
-
- QAction *insertAction = mainMenu.addAction(tr("Insert Keyframe"));
- QObject::connect(insertAction, &QAction::triggered, [this]() {
- timelineScene()->handleKeyframeInsertion(m_frames.target(), propertyName().toUtf8());
- });
-
- QAction *removeAction = mainMenu.addAction(tr("Delete Keyframe"));
- QObject::connect(removeAction, &QAction::triggered, [this, currentFrameNode]() {
- timelineScene()->deleteKeyframes({currentFrameNode});
- });
-
- QAction *editEasingAction = mainMenu.addAction(tr("Edit Easing Curve..."));
- QObject::connect(editEasingAction, &QAction::triggered, [this, currentFrameNode]() {
- setEasingCurve(timelineScene(), {currentFrameNode});
- });
-
- QAction *editValueAction = mainMenu.addAction(tr("Edit Value for Keyframe..."));
- QObject::connect(editValueAction, &QAction::triggered, [this, currentFrameNode]() {
- editValue(currentFrameNode, propertyName());
- });
-
- const bool hasKeyframe = currentFrameNode.isValid();
-
- insertAction->setEnabled(!hasKeyframe);
- removeAction->setEnabled(hasKeyframe);
- editEasingAction->setEnabled(hasKeyframe);
- editValueAction->setEnabled(hasKeyframe);
-
- mainMenu.exec(event->screenPos());
- event->accept();
- } else if (event->pos().x() > TimelineConstants::toolButtonSize * 3 + 3
- && event->pos().x() < TimelineConstants::sectionWidth) {
- QMenu mainMenu;
- QAction *deleteAction = mainMenu.addAction(tr("Remove Property"));
-
- QObject::connect(deleteAction, &QAction::triggered, [this]() {
- auto deleteKeyframeGroup = [this]() { timelineScene()->deleteKeyframeGroup(m_frames); };
- QTimer::singleShot(0, deleteKeyframeGroup);
- });
-
- mainMenu.exec(event->screenPos());
- event->accept();
- }
-}
-
-TimelinePropertyItem::TimelinePropertyItem(TimelineSectionItem *parent)
- : TimelineItem(parent)
-{
- setPreferredHeight(TimelineConstants::sectionHeight);
- setMinimumHeight(TimelineConstants::sectionHeight);
- setMaximumHeight(TimelineConstants::sectionHeight);
-}
-
-void TimelinePropertyItem::setupKeyframes()
-{
- for (const ModelNode &frame : m_frames.keyframePositions())
- new TimelineKeyframeItem(this, frame);
-}
-
-qreal TimelinePropertyItem::currentFrame()
-{
- QmlTimeline timeline = timelineScene()->currentTimeline();
- if (timeline.isValid())
- return timeline.currentKeyframe();
- return 0;
-}
-
-TimelineKeyframeItem::TimelineKeyframeItem(TimelinePropertyItem *parent, const ModelNode &frame)
- : TimelineMovableAbstractItem(parent)
- , m_frame(frame)
-
-{
- setPosition(frame.variantProperty("frame").value().toReal());
- setCursor(Qt::ClosedHandCursor);
-}
-
-TimelineKeyframeItem::~TimelineKeyframeItem()
-{
- timelineScene()->selectKeyframes(SelectionMode::Remove, {this});
-}
-
-void TimelineKeyframeItem::updateFrame()
-{
- if (s_blockUpdates)
- return;
-
- QTC_ASSERT(m_frame.isValid(), return );
- setPosition(m_frame.variantProperty("frame").value().toReal());
-}
-
-void TimelineKeyframeItem::setPosition(qreal position)
-{
- int offset = (TimelineConstants::sectionHeight - TimelineConstants::keyFrameSize) / 2;
- const qreal scenePostion = mapFromFrameToScene(position);
-
- setRect(scenePostion - TimelineConstants::keyFrameSize / 2,
- offset,
- TimelineConstants::keyFrameSize,
- TimelineConstants::keyFrameSize);
-}
-
-void TimelineKeyframeItem::setPositionInteractive(const QPointF &postion)
-{
- qreal left = postion.x() - qreal(TimelineConstants::keyFrameSize) / qreal(2);
- setRect(left, rect().y(), rect().width(), rect().height());
-}
-
-void TimelineKeyframeItem::commitPosition(const QPointF &point)
-{
- setPositionInteractive(point);
-
- const qreal frame = qRound(mapFromSceneToFrame(rect().center().x()));
-
- setPosition(frame);
-
- QTC_ASSERT(m_frame.isValid(), return );
-
- blockUpdates();
-
- try {
- RewriterTransaction transaction(
- m_frame.view()->beginRewriterTransaction("TimelineKeyframeItem::commitPosition"));
-
- m_frame.variantProperty("frame").setValue(frame);
- transaction.commit();
- } catch (const RewritingException &e) {
- e.showException();
- }
-
- enableUpdates();
-}
-
-TimelineKeyframeItem *TimelineKeyframeItem::asTimelineKeyframeItem()
-{
- return this;
-}
-
-void TimelineKeyframeItem::blockUpdates()
-{
- s_blockUpdates = true;
-}
-
-void TimelineKeyframeItem::enableUpdates()
-{
- s_blockUpdates = false;
-}
-
-bool TimelineKeyframeItem::hasManualBezier() const
-{
- return m_frame.isValid() && m_frame.hasProperty("easing.bezierCurve");
-}
-
-void TimelineKeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
-{
- if (rect().x() < TimelineConstants::sectionWidth - rect().width() / 2)
- return;
-
- painter->save();
-
- Utils::Icon icon([this]() {
- const bool itemIsSelected = propertyItem()->isSelected();
- const bool manualBezier = hasManualBezier();
-
- if (m_highlight && manualBezier) {
- return TimelineIcons::KEYFRAME_MANUALBEZIER_SELECTED;
- } else if (m_highlight) {
- return TimelineIcons::KEYFRAME_LINEAR_SELECTED;
- } else if (itemIsSelected && manualBezier) {
- return TimelineIcons::KEYFRAME_MANUALBEZIER_ACTIVE;
- } else if (itemIsSelected) {
- return TimelineIcons::KEYFRAME_LINEAR_ACTIVE;
- } else if (manualBezier) {
- return TimelineIcons::KEYFRAME_MANUALBEZIER_INACTIVE;
- }
-
- return TimelineIcons::KEYFRAME_LINEAR_INACTIVE;
- }());
-
- painter->drawPixmap(rect().topLeft() - QPointF(0, 1), icon.pixmap());
-
- painter->restore();
-}
-
-ModelNode TimelineKeyframeItem::frameNode() const
-{
- return m_frame;
-}
-
-void TimelineKeyframeItem::setHighlighted(bool b)
-{
- m_highlight = b;
- update();
-}
-
-TimelinePropertyItem *TimelineKeyframeItem::propertyItem() const
-{
- /* The parentItem is always a TimelinePropertyItem. See constructor */
- return qgraphicsitem_cast<TimelinePropertyItem *>(parentItem());
-}
-
-void TimelineKeyframeItem::scrollOffsetChanged()
-{
- updateFrame();
-}
-
-void TimelineKeyframeItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
- QMenu mainMenu;
- QAction *removeAction = mainMenu.addAction(tr("Delete Keyframe"));
- QObject::connect(removeAction, &QAction::triggered, [this]() {
- timelineScene()->handleKeyframeDeletion();
- });
-
- QAction *editEasingAction = mainMenu.addAction(tr("Edit Easing Curve..."));
- QObject::connect(editEasingAction, &QAction::triggered, [this]() {
- const QList<ModelNode> keys = Utils::transform(timelineScene()->selectedKeyframes(),
- &TimelineKeyframeItem::m_frame);
-
- setEasingCurve(timelineScene(), keys);
- });
-
- QAction *editValueAction = mainMenu.addAction(tr("Edit Value for Keyframe..."));
- QObject::connect(editValueAction, &QAction::triggered, [this]() {
- editValue(m_frame, propertyItem()->propertyName());
- });
-
- mainMenu.exec(event->screenPos());
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesectionitem.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesectionitem.cpp
deleted file mode 100644
index 3c24b38d35..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesectionitem.cpp
+++ /dev/null
@@ -1,1067 +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 "timelinesectionitem.h"
-
-#include "abstractview.h"
-#include "timelineactions.h"
-#include "timelineconstants.h"
-#include "timelinegraphicsscene.h"
-#include "timelineicons.h"
-#include "timelinepropertyitem.h"
-#include "timelinetoolbutton.h"
-#include "timelineutils.h"
-
-#include <qmltimeline.h>
-#include <qmltimelinekeyframegroup.h>
-
-#include <rewritingexception.h>
-
-#include <theme.h>
-
-#include <utils/qtcassert.h>
-
-#include <QAction>
-#include <QColorDialog>
-#include <QComboBox>
-#include <QGraphicsProxyWidget>
-#include <QGraphicsScene>
-#include <QGraphicsSceneMouseEvent>
-#include <QGraphicsView>
-#include <QHBoxLayout>
-#include <QMenu>
-#include <QPainter>
-#include <QToolBar>
-
-#include <QGraphicsView>
-
-#include <QDebug>
-
-#include <cmath>
-
-static int textOffset = 8;
-
-namespace QmlDesigner {
-
-class ClickDummy : public TimelineItem
-{
-public:
- explicit ClickDummy(TimelineSectionItem *parent)
- : TimelineItem(parent)
- {
- setGeometry(0, 0, TimelineConstants::sectionWidth, TimelineConstants::sectionHeight);
-
- setZValue(10);
- setCursor(Qt::ArrowCursor);
- }
-
-protected:
- void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override
- {
- scene()->sendEvent(parentItem(), event);
- }
- void mousePressEvent(QGraphicsSceneMouseEvent *event) override
- {
- scene()->sendEvent(parentItem(), event);
- }
- void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
- {
- scene()->sendEvent(parentItem(), event);
- }
- void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override
- {
- scene()->sendEvent(parentItem(), event);
- }
-};
-
-TimelineSectionItem::TimelineSectionItem(TimelineItem *parent)
- : TimelineItem(parent)
-{}
-
-TimelineSectionItem *TimelineSectionItem::create(const QmlTimeline &timeline,
- const ModelNode &target,
- TimelineItem *parent)
-{
- auto item = new TimelineSectionItem(parent);
-
- if (target.isValid())
- item->setToolTip(target.id());
-
- item->m_targetNode = target;
- item->m_timeline = timeline;
-
- item->createPropertyItems();
-
- item->m_dummyItem = new ClickDummy(item);
- item->m_dummyItem->update();
-
- item->m_barItem = new TimelineBarItem(item);
- item->invalidateBar();
- item->invalidateHeight();
-
- return item;
-}
-
-void TimelineSectionItem::invalidateBar()
-{
- qreal min = m_timeline.minActualKeyframe(m_targetNode);
- qreal max = m_timeline.maxActualKeyframe(m_targetNode);
-
- const qreal sceneMin = m_barItem->mapFromFrameToScene(min);
-
- QRectF barRect(sceneMin,
- 0,
- (max - min) * m_barItem->rulerScaling(),
- TimelineConstants::sectionHeight - 1);
-
- m_barItem->setRect(barRect);
-}
-
-int TimelineSectionItem::type() const
-{
- return Type;
-}
-
-void TimelineSectionItem::updateData(QGraphicsItem *item)
-{
- if (auto sectionItem = qgraphicsitem_cast<TimelineSectionItem *>(item))
- sectionItem->updateData();
-}
-
-void TimelineSectionItem::updateDataForTarget(QGraphicsItem *item, const ModelNode &target, bool *b)
-{
- if (!target.isValid())
- return;
-
- if (auto sectionItem = qgraphicsitem_cast<TimelineSectionItem *>(item)) {
- if (sectionItem->m_targetNode == target) {
- sectionItem->updateData();
- if (b)
- *b = true;
- }
- }
-}
-
-void TimelineSectionItem::updateFramesForTarget(QGraphicsItem *item, const ModelNode &target)
-{
- if (auto sectionItem = qgraphicsitem_cast<TimelineSectionItem *>(item)) {
- if (sectionItem->m_targetNode == target)
- sectionItem->updateFrames();
- }
-}
-
-void TimelineSectionItem::moveAllFrames(qreal offset)
-{
- if (m_timeline.isValid())
- m_timeline.moveAllKeyframes(m_targetNode, offset);
-}
-
-void TimelineSectionItem::scaleAllFrames(qreal scale)
-{
- if (m_timeline.isValid())
- m_timeline.scaleAllKeyframes(m_targetNode, scale);
-}
-
-qreal TimelineSectionItem::firstFrame()
-{
- if (!m_timeline.isValid())
- return 0;
-
- return m_timeline.minActualKeyframe(m_targetNode);
-}
-
-AbstractView *TimelineSectionItem::view() const
-{
- return m_timeline.view();
-}
-
-bool TimelineSectionItem::isSelected() const
-{
- return m_targetNode.isValid() && m_targetNode.isSelected();
-}
-
-ModelNode TimelineSectionItem::targetNode() const
-{
- return m_targetNode;
-}
-
-QVector<qreal> TimelineSectionItem::keyframePositions() const
-{
- QVector<qreal> out;
- for (auto frame : m_timeline.keyframeGroupsForTarget(m_targetNode))
- out.append(timelineScene()->keyframePositions(frame));
-
- return out;
-}
-
-QTransform rotatationTransform(qreal degrees)
-{
- QTransform transform;
- transform.rotate(degrees);
-
- return transform;
-}
-
-QPixmap rotateby90(const QPixmap &pixmap)
-{
- QImage sourceImage = pixmap.toImage();
- QImage destImage(pixmap.height(), pixmap.width(), sourceImage.format());
-
- for (int x = 0; x < pixmap.width(); x++)
- for (int y = 0; y < pixmap.height(); y++)
- destImage.setPixel(y, x, sourceImage.pixel(x, y));
-
- QPixmap result = QPixmap::fromImage(destImage);
-
- result.setDevicePixelRatio(pixmap.devicePixelRatio());
-
- return result;
-}
-
-static int devicePixelHeight(const QPixmap &pixmap)
-{
- return pixmap.height() / pixmap.devicePixelRatioF();
-}
-
-void TimelineSectionItem::paint(QPainter *painter,
- const QStyleOptionGraphicsItem * /*option*/,
- QWidget *)
-{
- if (m_targetNode.isValid()) {
- painter->save();
-
- const QColor textColor = Theme::getColor(Theme::PanelTextColorLight);
- const QColor penColor = Theme::instance()->qmlDesignerBackgroundColorDarker();
- QColor brushColor = Theme::getColor(Theme::BackgroundColorDark);
-
- int fillOffset = 0;
- if (isSelected()) {
- brushColor = Theme::getColor(Theme::QmlDesigner_HighlightColor);
- fillOffset = 1;
- }
-
- painter->fillRect(0,
- 0,
- TimelineConstants::sectionWidth,
- TimelineConstants::sectionHeight - fillOffset,
- brushColor);
- painter->fillRect(TimelineConstants::sectionWidth,
- 0,
- size().width() - TimelineConstants::sectionWidth,
- size().height(),
- Theme::instance()->qmlDesignerBackgroundColorDarkAlternate());
-
- painter->setPen(penColor);
- drawLine(painter,
- TimelineConstants::sectionWidth - 1,
- 0,
- TimelineConstants::sectionWidth - 1,
- size().height() - 1);
- drawLine(painter,
- TimelineConstants::sectionWidth,
- TimelineConstants::sectionHeight - 1,
- size().width(),
- TimelineConstants::sectionHeight - 1);
-
- static const QPixmap arrow = Theme::getPixmap("down-arrow");
-
- static const QPixmap arrow90 = rotateby90(arrow);
-
- const QPixmap rotatedArrow = collapsed() ? arrow90 : arrow;
-
- const int textOffset = QFontMetrics(font()).ascent()
- + (TimelineConstants::sectionHeight - QFontMetrics(font()).height())
- / 2;
-
- painter->drawPixmap(collapsed() ? 6 : 4,
- (TimelineConstants::sectionHeight - devicePixelHeight(rotatedArrow)) / 2,
- rotatedArrow);
-
- painter->setPen(textColor);
-
- QFontMetrics fm(painter->font());
- const QString elidedId = fm.elidedText(m_targetNode.id(),
- Qt::ElideMiddle,
- TimelineConstants::sectionWidth
- - TimelineConstants::textIndentationSections);
- painter->drawText(TimelineConstants::textIndentationSections, textOffset, elidedId);
-
- painter->restore();
- }
-}
-
-void TimelineSectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->pos().y() > TimelineConstants::sectionHeight
- || event->pos().x() < TimelineConstants::textIndentationSections) {
- TimelineItem::mouseDoubleClickEvent(event);
- return;
- }
-
- if (event->button() == Qt::LeftButton) {
- event->accept();
- toggleCollapsed();
- }
-}
-
-void TimelineSectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->pos().y() > TimelineConstants::sectionHeight) {
- TimelineItem::mousePressEvent(event);
- return;
- }
-
- if (event->button() == Qt::LeftButton)
- event->accept();
-}
-
-void TimelineSectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
- if (event->pos().y() > TimelineConstants::sectionHeight) {
- TimelineItem::mouseReleaseEvent(event);
- return;
- }
-
- if (event->button() != Qt::LeftButton)
- return;
-
- event->accept();
-
- if (event->pos().x() > TimelineConstants::textIndentationSections
- && event->button() == Qt::LeftButton) {
- if (m_targetNode.isValid())
- m_targetNode.view()->setSelectedModelNode(m_targetNode);
- } else {
- toggleCollapsed();
- }
- update();
-}
-
-void TimelineSectionItem::resizeEvent(QGraphicsSceneResizeEvent *event)
-{
- TimelineItem::resizeEvent(event);
-
- for (auto child : propertyItems()) {
- TimelinePropertyItem *item = static_cast<TimelinePropertyItem *>(child);
- item->resize(size().width(), TimelineConstants::sectionHeight);
- }
-}
-
-void TimelineSectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
- if (event->pos().x() < TimelineConstants::sectionWidth
- && event->pos().y() < TimelineConstants::sectionHeight) {
- QMenu mainMenu;
-
- auto timeline = timelineScene()->currentTimeline();
-
- QAction *removeAction = mainMenu.addAction(
- TimelineConstants::timelineDeleteKeyframesDisplayName);
- QObject::connect(removeAction, &QAction::triggered, [this]() {
- timelineScene()->deleteAllKeyframesForTarget(m_targetNode);
- });
-
- QAction *addKeyframesAction = mainMenu.addAction(
- TimelineConstants::timelineInsertKeyframesDisplayName);
- QObject::connect(addKeyframesAction, &QAction::triggered, [this]() {
- timelineScene()->insertAllKeyframesForTarget(m_targetNode);
- });
-
- QAction *copyAction = mainMenu.addAction(
- TimelineConstants::timelineCopyKeyframesDisplayName);
- QObject::connect(copyAction, &QAction::triggered, [this]() {
- timelineScene()->copyAllKeyframesForTarget(m_targetNode);
- });
-
- QAction *pasteAction = mainMenu.addAction(
- TimelineConstants::timelinePasteKeyframesDisplayName);
- QObject::connect(pasteAction, &QAction::triggered, [this]() {
- timelineScene()->pasteKeyframesToTarget(m_targetNode);
- });
-
- pasteAction->setEnabled(TimelineActions::clipboardContainsKeyframes());
-
- mainMenu.exec(event->screenPos());
- event->accept();
- }
-}
-
-void TimelineSectionItem::updateData()
-{
- invalidateBar();
- resize(rulerWidth(), size().height());
- invalidateProperties();
- update();
-}
-
-void TimelineSectionItem::updateFrames()
-{
- invalidateBar();
- invalidateFrames();
- update();
-}
-
-void TimelineSectionItem::invalidateHeight()
-{
- int height = 0;
- bool visible = true;
-
- if (collapsed()) {
- height = TimelineConstants::sectionHeight;
- visible = false;
- } else {
- height = TimelineConstants::sectionHeight
- + m_timeline.keyframeGroupsForTarget(m_targetNode).count()
- * TimelineConstants::sectionHeight;
- visible = true;
- }
-
- for (auto child : propertyItems())
- child->setVisible(visible);
-
- setPreferredHeight(height);
- setMinimumHeight(height);
- setMaximumHeight(height);
- timelineScene()->activateLayout();
-}
-
-void TimelineSectionItem::invalidateProperties()
-{
- for (auto child : propertyItems()) {
- delete child;
- }
-
- createPropertyItems();
-
- for (auto child : propertyItems()) {
- TimelinePropertyItem *item = static_cast<TimelinePropertyItem *>(child);
- item->updateData();
- item->resize(size().width(), TimelineConstants::sectionHeight);
- }
- invalidateHeight();
-}
-
-void TimelineSectionItem::invalidateFrames()
-{
- for (auto child : propertyItems()) {
- TimelinePropertyItem *item = static_cast<TimelinePropertyItem *>(child);
- item->updateFrames();
- }
-}
-
-bool TimelineSectionItem::collapsed() const
-{
- return m_targetNode.isValid() && !m_targetNode.hasAuxiliaryData("timeline_expanded");
-}
-
-void TimelineSectionItem::createPropertyItems()
-{
- auto framesList = m_timeline.keyframeGroupsForTarget(m_targetNode);
-
- int yPos = TimelineConstants::sectionHeight;
- for (const auto &frames : framesList) {
- auto item = TimelinePropertyItem::create(frames, this);
- item->setY(yPos);
- yPos = yPos + TimelineConstants::sectionHeight;
- }
-}
-
-qreal TimelineSectionItem::rulerWidth() const
-{
- return static_cast<TimelineGraphicsScene *>(scene())->rulerWidth();
-}
-
-void TimelineSectionItem::toggleCollapsed()
-{
- QTC_ASSERT(m_targetNode.isValid(), return );
-
- if (collapsed())
- m_targetNode.setAuxiliaryData("timeline_expanded", true);
- else
- m_targetNode.removeAuxiliaryData("timeline_expanded");
-
- invalidateHeight();
-}
-
-QList<QGraphicsItem *> TimelineSectionItem::propertyItems() const
-{
- QList<QGraphicsItem *> list;
-
- for (auto child : childItems()) {
- if (m_barItem != child && m_dummyItem != child)
- list.append(child);
- }
-
- return list;
-}
-
-TimelineRulerSectionItem::TimelineRulerSectionItem(TimelineItem *parent)
- : TimelineItem(parent)
-{
- setPreferredHeight(TimelineConstants::rulerHeight);
- setMinimumHeight(TimelineConstants::rulerHeight);
- setMaximumHeight(TimelineConstants::rulerHeight);
- setZValue(10);
-}
-
-static void drawCenteredText(QPainter *p, int x, int y, const QString &text)
-{
- QRect rect(x - 16, y - 4, 32, 8);
- p->drawText(rect, Qt::AlignCenter, text);
-}
-
-TimelineRulerSectionItem *TimelineRulerSectionItem::create(QGraphicsScene *parentScene,
- TimelineItem *parent)
-{
- auto item = new TimelineRulerSectionItem(parent);
- item->setMaximumHeight(TimelineConstants::rulerHeight);
-
- auto widget = new QWidget;
- widget->setFixedWidth(TimelineConstants::sectionWidth);
-
- auto toolBar = new QToolBar;
- toolBar->setFixedHeight(TimelineConstants::rulerHeight);
-
- auto layout = new QHBoxLayout(widget);
- layout->addWidget(toolBar);
- layout->setMargin(0);
-
- layout->addWidget(toolBar);
- layout->setMargin(0);
-
- QGraphicsProxyWidget *proxy = parentScene->addWidget(widget);
- proxy->setParentItem(item);
-
- return item;
-}
-
-void TimelineRulerSectionItem::invalidateRulerSize(const QmlTimeline &timeline)
-{
- m_duration = timeline.duration();
- m_start = timeline.startKeyframe();
- m_end = timeline.endKeyframe();
-}
-
-void TimelineRulerSectionItem::setRulerScaleFactor(int scaling)
-{
- qreal blend = qreal(scaling) / 100.0;
-
- qreal width = size().width() - qreal(TimelineConstants::sectionWidth);
- qreal duration = rulerDuration();
-
- qreal offset = duration * 0.1;
- qreal maxCount = duration + offset;
- qreal minCount = width
- / qreal(TimelineConstants::keyFrameSize
- + 2 * TimelineConstants::keyFrameMargin);
-
- qreal count = maxCount < minCount ? maxCount : TimelineUtils::lerp(blend, minCount, maxCount);
-
- if (count > std::numeric_limits<qreal>::min() && count <= maxCount)
- m_scaling = width / count;
- else
- m_scaling = 1.0;
-
- update();
-}
-
-int TimelineRulerSectionItem::getRulerScaleFactor() const
-{
- qreal width = size().width() - qreal(TimelineConstants::sectionWidth);
- qreal duration = rulerDuration();
-
- qreal offset = duration * 0.1;
- qreal maxCount = duration + offset;
- qreal minCount = width
- / qreal(TimelineConstants::keyFrameSize
- + 2 * TimelineConstants::keyFrameMargin);
-
- if (maxCount < minCount)
- return -1;
-
- qreal rcount = width / m_scaling;
- qreal rblend = TimelineUtils::reverseLerp(rcount, minCount, maxCount);
-
- int rfactor = std::round(rblend * 100);
- return TimelineUtils::clamp(rfactor, 0, 100);
-}
-
-qreal TimelineRulerSectionItem::rulerScaling() const
-{
- return m_scaling;
-}
-
-qreal TimelineRulerSectionItem::rulerDuration() const
-{
- return m_duration;
-}
-
-qreal TimelineRulerSectionItem::durationViewportLength() const
-{
- return m_duration * m_scaling;
-}
-
-qreal TimelineRulerSectionItem::startFrame() const
-{
- return m_start;
-}
-
-qreal TimelineRulerSectionItem::endFrame() const
-{
- return m_end;
-}
-
-void TimelineRulerSectionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
-{
- static const QColor backgroundColor = Theme::instance()
- ->qmlDesignerBackgroundColorDarkAlternate();
- static const QColor penColor = Theme::getColor(Theme::PanelTextColorLight);
- static const QColor highlightColor = Theme::instance()->Theme::qmlDesignerButtonColor();
- static const QColor handleColor = Theme::getColor(Theme::QmlDesigner_HighlightColor);
-
- painter->save();
- painter->save();
- painter->setRenderHint(QPainter::Antialiasing);
- painter->translate(-timelineScene()->scrollOffset(), 0);
- painter->fillRect(TimelineConstants::sectionWidth,
- 0,
- size().width() - TimelineConstants::sectionWidth,
- size().height(),
- backgroundColor);
-
- painter->translate(TimelineConstants::timelineLeftOffset, 0);
-
- const QRectF rangeRect(TimelineConstants::sectionWidth,
- 0,
- m_duration * m_scaling,
- size().height());
-
- const qreal radius = 5;
- const qreal handleWidth = TimelineConstants::timelineBounds * 2;
- QRectF boundsRect(0, rangeRect.y(), handleWidth, rangeRect.height());
-
- boundsRect.moveRight(rangeRect.left() + TimelineConstants::timelineBounds);
-
- QPainterPath leftBoundsPath;
- leftBoundsPath.addRoundedRect(boundsRect, radius, radius);
- painter->fillPath(leftBoundsPath, handleColor);
-
- boundsRect.moveLeft(rangeRect.right() - TimelineConstants::timelineBounds);
-
- QPainterPath rightBoundsPath;
- rightBoundsPath.addRoundedRect(boundsRect, radius, radius);
- painter->fillPath(rightBoundsPath, handleColor);
-
- painter->fillRect(rangeRect, highlightColor);
-
- painter->setPen(penColor);
-
- const int height = size().height() - 1;
-
- drawLine(painter,
- TimelineConstants::sectionWidth + timelineScene()->scrollOffset()
- - TimelineConstants::timelineLeftOffset,
- height,
- size().width() + timelineScene()->scrollOffset(),
- height);
-
- QFont font = painter->font();
- font.setPixelSize(8);
- painter->setFont(font);
-
- paintTicks(painter);
-
- painter->restore();
-
- painter->fillRect(0, 0, TimelineConstants::sectionWidth, size().height(), backgroundColor);
- painter->restore();
-}
-
-void TimelineRulerSectionItem::paintTicks(QPainter *painter)
-{
- const int totalWidth = size().width() / m_scaling + timelineScene()->scrollOffset() / m_scaling;
-
- QFontMetrics fm(painter->font());
-
- int minSpacingText = fm.width(QString("X%1X").arg(rulerDuration()));
- int minSpacingLine = 5;
-
- int deltaText = 0;
- int deltaLine = 0;
-
- // Marks possibly at [1, 5, 10, 50, 100, ...]
- int spacing = 1;
- bool toggle = true;
- while (deltaText == 0) {
- int distance = spacing * m_scaling;
-
- if (distance > minSpacingLine && deltaLine == 0)
- deltaLine = spacing;
-
- if (distance > minSpacingText) {
- deltaText = spacing;
- break;
- }
-
- if (toggle) {
- spacing *= 5;
- toggle = false;
- } else {
- spacing *= 2;
- toggle = true;
- }
- }
-
- int height = size().height();
-
- for (int i = timelineScene()->scrollOffset() / m_scaling; i < totalWidth; ++i) {
- if ((i % deltaText) == 0) {
- drawCenteredText(painter,
- TimelineConstants::sectionWidth + i * m_scaling,
- textOffset,
- QString::number(m_start + i));
-
- drawLine(painter,
- TimelineConstants::sectionWidth + i * m_scaling,
- height - 2,
- TimelineConstants::sectionWidth + i * m_scaling,
- height * 0.6);
-
- } else if ((i % deltaLine) == 0) {
- drawLine(painter,
- TimelineConstants::sectionWidth + i * m_scaling,
- height - 2,
- TimelineConstants::sectionWidth + i * m_scaling,
- height * 0.75);
- }
- }
-}
-
-void TimelineRulerSectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- TimelineItem::mousePressEvent(event);
- emit rulerClicked(event->pos());
-}
-
-void TimelineRulerSectionItem::resizeEvent(QGraphicsSceneResizeEvent *event)
-{
- QGraphicsWidget::resizeEvent(event);
-
- auto factor = getRulerScaleFactor();
-
- if (factor < 0) {
- if (event->oldSize().width() < event->newSize().width())
- factor = 0;
- else
- factor = 100;
- }
-
- emit scaleFactorChanged(factor);
-}
-
-void TimelineRulerSectionItem::setSizeHints(int width)
-{
- const int rulerWidth = width;
- setPreferredWidth(rulerWidth);
- setMinimumWidth(rulerWidth);
- setMaximumWidth(rulerWidth);
-}
-
-TimelineBarItem::TimelineBarItem(TimelineSectionItem *parent)
- : TimelineMovableAbstractItem(parent)
-{
- setAcceptHoverEvents(true);
- setPen(Qt::NoPen);
-}
-
-void TimelineBarItem::itemMoved(const QPointF &start, const QPointF &end)
-{
- if (isActiveHandle(Location::Undefined))
- dragInit(rect(), start);
-
- const qreal min = qreal(TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
- - scrollOffset());
- const qreal max = qreal(timelineScene()->rulerWidth() - TimelineConstants::sectionWidth
- + rect().width());
-
- if (isActiveHandle(Location::Center))
- dragCenter(rect(), end, min, max);
- else
- dragHandle(rect(), end, min, max);
-
- timelineScene()->statusBarMessageChanged(
- tr("Range from %1 to %2")
- .arg(qRound(mapFromSceneToFrame(rect().x())))
- .arg(qRound(mapFromSceneToFrame(rect().width() + rect().x()))));
-}
-
-void TimelineBarItem::commitPosition(const QPointF & /*point*/)
-{
- if (sectionItem()->view()) {
- if (m_handle != Location::Undefined) {
- qreal scaleFactor = rect().width() / m_oldRect.width();
-
- qreal moved = (rect().topLeft().x() - m_oldRect.topLeft().x()) / rulerScaling();
- qreal supposedFirstFrame = qRound(sectionItem()->firstFrame() + moved);
-
- try {
- RewriterTransaction transaction(sectionItem()->view()->beginRewriterTransaction(
- "TimelineBarItem::commitPosition"));
- sectionItem()->scaleAllFrames(scaleFactor);
- sectionItem()->moveAllFrames(supposedFirstFrame - sectionItem()->firstFrame());
- transaction.commit();
- } catch (const RewritingException &e) {
- e.showException();
- }
- }
- }
-
- m_handle = Location::Undefined;
- m_bounds = Location::Undefined;
- m_pivot = 0.0;
- m_oldRect = QRectF();
-}
-
-void TimelineBarItem::scrollOffsetChanged()
-{
- sectionItem()->invalidateBar();
-}
-
-void TimelineBarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- QColor brushColorSelected = Theme::getColor(Theme::QmlDesigner_HighlightColor);
- QColor brushColor = Theme::getColor(Theme::QmlDesigner_HighlightColor).darker(120);
- const QColor indicatorColor = Theme::getColor(Theme::PanelTextColorLight);
-
- ModelNode target = sectionItem()->targetNode();
- if (target.isValid()) {
- QColor overrideColor = target.auxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE).value<QColor>();
- if (overrideColor.isValid()) {
- brushColorSelected = overrideColor;
- brushColor = brushColorSelected.darker(120);
- }
- }
-
- const QRectF itemRect = rect();
-
- painter->save();
- painter->setClipRect(TimelineConstants::sectionWidth,
- 0,
- itemRect.width() + itemRect.x(),
- itemRect.height());
-
- if (sectionItem()->isSelected())
- painter->fillRect(itemRect, brushColorSelected);
- else
- painter->fillRect(itemRect, brushColor);
-
- auto positions = sectionItem()->keyframePositions();
- std::sort(positions.begin(), positions.end());
-
- auto fcompare = [](auto v1, auto v2) { return qFuzzyCompare(v1, v2); };
- auto unique = std::unique(positions.begin(), positions.end(), fcompare);
- positions.erase(unique, positions.end());
-
- painter->setPen(indicatorColor);
- auto margin = itemRect.height() * 0.166;
- auto p1y = itemRect.top() + margin;
- auto p2y = itemRect.bottom() - margin;
- for (auto pos : positions) {
- auto px = mapFromFrameToScene(pos) + 0.5;
- painter->drawLine(QLineF(px, p1y, px, p2y));
- }
- painter->restore();
-}
-
-void TimelineBarItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
-{
- const auto p = event->pos();
-
- QRectF left, right;
- if (handleRects(rect(), left, right)) {
- if (left.contains(p) || right.contains(p)) {
- if (cursor().shape() != Qt::SizeHorCursor)
- setCursor(QCursor(Qt::SizeHorCursor));
- } else if (rect().contains(p)) {
- if (cursor().shape() != Qt::ClosedHandCursor)
- setCursor(QCursor(Qt::ClosedHandCursor));
- }
- } else {
- if (rect().contains(p))
- setCursor(QCursor(Qt::ClosedHandCursor));
- }
-}
-
-void TimelineBarItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
-{
- QMenu menu;
- QAction* overrideColor = menu.addAction(tr("Override Color"));
-
- auto setColor = [this] () {
- ModelNode target = sectionItem()->targetNode();
- if (target.isValid()) {
- QColor current = target.auxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE).value<QColor>();
- QColor color = QColorDialog::getColor(current, nullptr);
- if (color.isValid())
- target.setAuxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE, color);
- }
- };
-
- QObject::connect(overrideColor, &QAction::triggered, setColor);
-
- QAction* resetColor = menu.addAction(tr("Reset Color"));
- auto reset = [this]() {
- ModelNode target = sectionItem()->targetNode();
- if (target.isValid())
- target.removeAuxiliaryData(TimelineConstants::C_BAR_ITEM_OVERRIDE);
- };
- QObject::connect(resetColor, &QAction::triggered, reset);
-
- menu.exec(event->screenPos());
-}
-
-TimelineSectionItem *TimelineBarItem::sectionItem() const
-{
- /* The parentItem is always a TimelineSectionItem. See constructor */
- return qgraphicsitem_cast<TimelineSectionItem *>(parentItem());
-}
-
-void TimelineBarItem::dragInit(const QRectF &rect, const QPointF &pos)
-{
- QRectF left, right;
- m_oldRect = rect;
- if (handleRects(rect, left, right)) {
- if (left.contains(pos)) {
- m_handle = Location::Left;
- m_pivot = pos.x() - left.topLeft().x();
- } else if (right.contains(pos)) {
- m_handle = Location::Right;
- m_pivot = pos.x() - right.topRight().x();
- } else if (rect.contains(pos)) {
- m_handle = Location::Center;
- m_pivot = pos.x() - rect.topLeft().x();
- }
-
- } else {
- if (rect.contains(pos)) {
- m_handle = Location::Center;
- m_pivot = pos.x() - rect.topLeft().x();
- }
- }
-}
-
-void TimelineBarItem::dragCenter(QRectF rect, const QPointF &pos, qreal min, qreal max)
-{
- if (validateBounds(pos.x() - rect.topLeft().x())) {
- rect.moveLeft(pos.x() - m_pivot);
- if (rect.topLeft().x() < min) {
- rect.moveLeft(min);
- setOutOfBounds(Location::Left);
- } else if (rect.topRight().x() > max) {
- rect.moveRight(max);
- setOutOfBounds(Location::Right);
- }
- setRect(rect);
- }
-}
-
-void TimelineBarItem::dragHandle(QRectF rect, const QPointF &pos, qreal min, qreal max)
-{
- QRectF left, right;
- handleRects(rect, left, right);
-
- if (isActiveHandle(Location::Left)) {
- if (validateBounds(pos.x() - left.topLeft().x())) {
- rect.setLeft(pos.x() - m_pivot);
- if (rect.left() < min) {
- rect.setLeft(min);
- setOutOfBounds(Location::Left);
- } else if (rect.left() >= rect.right() - minimumBarWidth)
- rect.setLeft(rect.right() - minimumBarWidth);
-
- setRect(rect);
- }
- } else if (isActiveHandle(Location::Right)) {
- if (validateBounds(pos.x() - right.topRight().x())) {
- rect.setRight(pos.x() - m_pivot);
- if (rect.right() > max) {
- rect.setRight(max);
- setOutOfBounds(Location::Right);
- } else if (rect.right() <= rect.left() + minimumBarWidth)
- rect.setRight(rect.left() + minimumBarWidth);
-
- setRect(rect);
- }
- }
-}
-
-bool TimelineBarItem::handleRects(const QRectF &rect, QRectF &left, QRectF &right) const
-{
- if (rect.width() < minimumBarWidth)
- return false;
-
- const qreal handleSize = rect.height();
-
- auto handleRect = QRectF(0, 0, handleSize, handleSize);
- handleRect.moveCenter(rect.center());
-
- handleRect.moveLeft(rect.left());
- left = handleRect;
-
- handleRect.moveRight(rect.right());
- right = handleRect;
-
- return true;
-}
-
-bool TimelineBarItem::isActiveHandle(Location location) const
-{
- return m_handle == location;
-}
-
-void TimelineBarItem::setOutOfBounds(Location location)
-{
- m_bounds = location;
-}
-
-bool TimelineBarItem::validateBounds(qreal distance)
-{
- if (m_bounds == Location::Left) {
- if (distance > m_pivot)
- m_bounds = Location::Center;
- return false;
-
- } else if (m_bounds == Location::Right) {
- if (distance < m_pivot)
- m_bounds = Location::Center;
- return false;
- }
- return true;
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsmodel.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsmodel.cpp
deleted file mode 100644
index 509a8878e8..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelinesettingsmodel.cpp
+++ /dev/null
@@ -1,502 +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 "timelinesettingsmodel.h"
-
-#include "timelineview.h"
-
-#include <modelnode.h>
-#include <variantproperty.h>
-#include <qmlitemnode.h>
-
-#include <utils/qtcassert.h>
-
-#include <QComboBox>
-#include <QItemEditorFactory>
-#include <QMessageBox>
-#include <QStyledItemDelegate>
-#include <QTimer>
-
-namespace QmlDesigner {
-
-class CustomDelegate : public QStyledItemDelegate
-{
-public:
- explicit CustomDelegate(QWidget *parent = nullptr);
- void paint(QPainter *painter,
- const QStyleOptionViewItem &option,
- const QModelIndex &index) const override;
-};
-
-CustomDelegate::CustomDelegate(QWidget *parent)
- : QStyledItemDelegate(parent)
-{}
-
-void CustomDelegate::paint(QPainter *painter,
- const QStyleOptionViewItem &option,
- const QModelIndex &index) const
-{
- QStyleOptionViewItem opt = option;
- opt.state &= ~QStyle::State_HasFocus;
- QStyledItemDelegate::paint(painter, opt, index);
-}
-
-class TimelineEditorDelegate : public CustomDelegate
-{
-public:
- TimelineEditorDelegate(QWidget *parent = nullptr);
- QWidget *createEditor(QWidget *parent,
- const QStyleOptionViewItem &option,
- const QModelIndex &index) const override;
-};
-
-TimelineEditorDelegate::TimelineEditorDelegate(QWidget *parent)
- : CustomDelegate(parent)
-{
- static QItemEditorFactory *factory = nullptr;
- if (factory == nullptr) {
- factory = new QItemEditorFactory;
- QItemEditorCreatorBase *creator = new QItemEditorCreator<QComboBox>("currentText");
- factory->registerEditor(QVariant::String, creator);
- }
-
- setItemEditorFactory(factory);
-}
-
-QWidget *TimelineEditorDelegate::createEditor(QWidget *parent,
- const QStyleOptionViewItem &option,
- const QModelIndex &index) const
-{
- QWidget *widget = QStyledItemDelegate::createEditor(parent, option, index);
-
- const auto timelineSettingsModel = qobject_cast<const TimelineSettingsModel *>(index.model());
-
- auto comboBox = qobject_cast<QComboBox *>(widget);
-
- QTC_ASSERT(timelineSettingsModel, return widget);
- QTC_ASSERT(timelineSettingsModel->timelineView(), return widget);
-
- QmlTimeline qmlTimeline = timelineSettingsModel->timelineForRow(index.row());
-
- switch (index.column()) {
- case TimelineSettingsModel::TimelineRow: {
- QTC_ASSERT(comboBox, return widget);
- comboBox->addItem(TimelineSettingsModel::tr("None"));
- for (const auto &timeline : timelineSettingsModel->timelineView()->getTimelines()) {
- if (!timeline.modelNode().id().isEmpty())
- comboBox->addItem(timeline.modelNode().id());
- }
- } break;
- case TimelineSettingsModel::AnimationRow: {
- QTC_ASSERT(comboBox, return widget);
- comboBox->addItem(TimelineSettingsModel::tr("None"));
- for (const auto &animation :
- timelineSettingsModel->timelineView()->getAnimations(qmlTimeline)) {
- if (!animation.id().isEmpty())
- comboBox->addItem(animation.id());
- }
- } break;
- case TimelineSettingsModel::FixedFrameRow: {
- } break;
-
- default:
- qWarning() << "TimelineEditorDelegate::createEditor column" << index.column();
- }
-
- if (comboBox) {
- connect(comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, [=]() {
- auto delegate = const_cast<TimelineEditorDelegate *>(this);
- emit delegate->commitData(comboBox);
- });
- }
-
- return widget;
-}
-
-TimelineSettingsModel::TimelineSettingsModel(QObject *parent, TimelineView *view)
- : QStandardItemModel(parent)
- , m_timelineView(view)
-{
- connect(this, &QStandardItemModel::dataChanged, this, &TimelineSettingsModel::handleDataChanged);
-}
-
-void TimelineSettingsModel::resetModel()
-{
- beginResetModel();
- clear();
- setHorizontalHeaderLabels(
- QStringList({tr("State"), tr("Timeline"), tr("Animation"), tr("Fixed Frame")}));
-
- if (timelineView()->isAttached() && timelineView()->rootModelNode().hasId()) {
- addState(ModelNode());
- for (const QmlModelState &state :
- QmlItemNode(timelineView()->rootModelNode()).states().allStates())
- addState(state);
- }
-
- endResetModel();
-}
-
-TimelineView *TimelineSettingsModel::timelineView() const
-{
- return m_timelineView;
-}
-
-void TimelineSettingsModel::setupDelegates(QAbstractItemView *view)
-{
- view->setItemDelegate(new TimelineEditorDelegate);
-}
-
-static int propertyValueForState(const ModelNode &modelNode,
- QmlModelState state,
- const PropertyName &propertyName)
-{
- if (!modelNode.isValid())
- return -1;
-
- if (state.isBaseState()) {
- if (modelNode.hasVariantProperty(propertyName))
- return modelNode.variantProperty(propertyName).value().toInt();
- return -1;
- }
-
- if (state.hasPropertyChanges(modelNode)) {
- QmlPropertyChanges propertyChanges(state.propertyChanges(modelNode));
- if (propertyChanges.modelNode().hasVariantProperty(propertyName))
- return propertyChanges.modelNode().variantProperty(propertyName).value().toInt();
- }
-
- return -1;
-}
-
-static QStandardItem *createStateItem(const ModelNode &state)
-{
- if (state.isValid())
- return new QStandardItem(state.variantProperty("name").value().toString());
- else
- return new QStandardItem(TimelineSettingsModel::tr("Base State"));
-}
-
-void TimelineSettingsModel::addState(const ModelNode &state)
-{
- QList<QStandardItem *> items;
-
- QmlTimeline timeline = timelineView()->timelineForState(state);
- const QString timelineId = timeline.isValid() ? timeline.modelNode().id() : QString("");
- ModelNode animation = animationForTimelineAndState(timeline, state);
- const QString animationId = animation.isValid() ? animation.id() : QString("");
-
- QStandardItem *stateItem = createStateItem(state);
- auto *timelinelItem = new QStandardItem(timelineId);
- auto *animationItem = new QStandardItem(animationId);
- auto *fixedFrameItem = new QStandardItem("");
-
- stateItem->setData(state.internalId());
- stateItem->setFlags(Qt::ItemIsEnabled);
-
- int fixedValue = propertyValueForState(timeline, state, "currentFrame");
- fixedFrameItem->setData(fixedValue, Qt::EditRole);
-
- items.append(stateItem);
- items.append(timelinelItem);
- items.append(animationItem);
- items.append(fixedFrameItem);
-
- appendRow(items);
-}
-
-void TimelineSettingsModel::handleException()
-{
- QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
- resetModel();
-}
-
-ModelNode TimelineSettingsModel::animationForTimelineAndState(const QmlTimeline &timeline,
- const ModelNode &state)
-{
- QmlModelState modelState(state);
-
- if (!timeline.isValid())
- return ModelNode();
-
- const QList<ModelNode> &animations = timelineView()->getAnimations(timeline);
-
- if (modelState.isBaseState()) {
- for (const auto &animation : animations) {
- if (animation.hasVariantProperty("running")
- && animation.variantProperty("running").value().toBool())
- return animation;
- }
- return ModelNode();
- }
-
- for (const auto &animation : animations) {
- if (modelState.affectsModelNode(animation)) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(animation));
-
- if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("running")
- && propertyChanges.modelNode().variantProperty("running").value().toBool())
- return animation;
- }
- }
- return ModelNode();
-}
-
-void TimelineSettingsModel::updateTimeline(int row)
-{
- QmlModelState modelState(stateForRow(row));
- QmlTimeline timeline(timelineForRow(row));
- ModelNode animation(animationForRow(row));
- QmlTimeline oldTimeline = timelineView()->timelineForState(modelState);
-
- RewriterTransaction transaction = timelineView()->beginRewriterTransaction(
- QByteArrayLiteral("TimelineSettingsModel::updateTimeline"));
-
- try {
- if (modelState.isBaseState()) {
- if (oldTimeline.isValid())
- oldTimeline.modelNode().variantProperty("enabled").setValue(false);
- if (timeline.isValid())
- timeline.modelNode().variantProperty("enabled").setValue(true);
- } else {
- if (oldTimeline.isValid() && modelState.affectsModelNode(oldTimeline)) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(oldTimeline));
- if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("enabled"))
- propertyChanges.modelNode().removeProperty("enabled");
- }
-
- QmlTimeline baseTimeline(timelineForRow(0));
-
- if (baseTimeline.isValid()) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(baseTimeline));
- if (propertyChanges.isValid())
- propertyChanges.modelNode().variantProperty("enabled").setValue(false);
- }
-
- if (timeline.isValid()) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(timeline));
- if (propertyChanges.isValid())
- propertyChanges.modelNode().variantProperty("enabled").setValue(true);
- }
- }
-
- } catch (Exception &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &TimelineSettingsModel::handleException);
- }
-
- resetRow(row);
-}
-
-void TimelineSettingsModel::updateAnimation(int row)
-{
- QmlModelState modelState(stateForRow(row));
- QmlTimeline timeline(timelineForRow(row));
- ModelNode animation(animationForRow(row));
- QmlTimeline oldTimeline = timelineView()->timelineForState(modelState);
- ModelNode oldAnimation = animationForTimelineAndState(oldTimeline, modelState);
-
- RewriterTransaction transaction = timelineView()->beginRewriterTransaction(
- QByteArrayLiteral("TimelineSettingsModel::updateAnimation"));
-
- try {
- if (modelState.isBaseState()) {
- if (oldAnimation.isValid())
- oldAnimation.variantProperty("running").setValue(false);
- if (animation.isValid())
- animation.variantProperty("running").setValue(true);
- if (timeline.isValid() && timeline.modelNode().hasProperty("currentFrame"))
- timeline.modelNode().removeProperty("currentFrame");
- } else {
- if (oldAnimation.isValid() && modelState.affectsModelNode(oldAnimation)) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(oldAnimation));
- if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("running"))
- propertyChanges.modelNode().removeProperty("running");
- }
-
- ModelNode baseAnimation(animationForRow(0));
-
- if (baseAnimation.isValid()) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(baseAnimation));
- if (propertyChanges.isValid()) {
- propertyChanges.modelNode().variantProperty("running").setValue(false);
- if (propertyChanges.modelNode().hasProperty("currentFrame"))
- propertyChanges.modelNode().removeProperty("currentFrame");
- }
- }
-
- if (animation.isValid()) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(animation));
- if (propertyChanges.isValid())
- propertyChanges.modelNode().variantProperty("running").setValue(true);
- }
- }
- } catch (Exception &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &TimelineSettingsModel::handleException);
- }
-
- resetRow(row);
-}
-
-void TimelineSettingsModel::updateFixedFrameRow(int row)
-{
- QmlModelState modelState(stateForRow(row));
- QmlTimeline timeline(timelineForRow(row));
-
- ModelNode animation = animationForTimelineAndState(timeline, modelState);
-
- RewriterTransaction transaction = timelineView()->beginRewriterTransaction(
- QByteArrayLiteral("TimelineSettingsModel::updateFixedFrameRow"));
-
- int fixedFrame = fixedFrameForRow(row);
-
- try {
- if (modelState.isBaseState()) {
- if (animation.isValid())
- animation.variantProperty("running").setValue(false);
- if (timeline.isValid())
- timeline.modelNode().variantProperty("currentFrame").setValue(fixedFrame);
- } else {
- if (animation.isValid() && modelState.affectsModelNode(animation)) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(animation));
- if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("running"))
- propertyChanges.modelNode().removeProperty("running");
- }
-
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(timeline));
- if (propertyChanges.isValid())
- propertyChanges.modelNode().variantProperty("currentFrame").setValue(fixedFrame);
- }
- } catch (Exception &e) {
- m_exceptionError = e.description();
- QTimer::singleShot(200, this, &TimelineSettingsModel::handleException);
- }
-
- resetRow(row);
-}
-
-void TimelineSettingsModel::resetRow(int row)
-{
- m_lock = true;
- QStandardItem *animationItem = item(row, AnimationRow);
- QStandardItem *fixedFrameItem = item(row, FixedFrameRow);
-
- QmlModelState modelState(stateForRow(row));
- QmlTimeline timeline(timelineForRow(row));
- ModelNode animation = animationForTimelineAndState(timeline, modelState);
-
- if (animationItem) {
- const QString animationId = animation.isValid() ? animation.id() : QString();
- animationItem->setText(animationId);
- }
-
- if (fixedFrameItem) {
- int fixedValue = propertyValueForState(timeline, modelState, "currentFrame");
- if (fixedFrameItem->data(Qt::EditRole).toInt() != fixedValue)
- fixedFrameItem->setData(fixedValue, Qt::EditRole);
- }
-
- m_lock = false;
-}
-
-QmlTimeline TimelineSettingsModel::timelineForRow(int row) const
-{
- QStandardItem *standardItem = item(row, TimelineRow);
-
- if (standardItem)
- return QmlTimeline(timelineView()->modelNodeForId(standardItem->text()));
-
- return QmlTimeline();
-}
-
-ModelNode TimelineSettingsModel::animationForRow(int row) const
-{
- QStandardItem *standardItem = item(row, AnimationRow);
-
- if (standardItem)
- return timelineView()->modelNodeForId(standardItem->text());
-
- return ModelNode();
-}
-
-ModelNode TimelineSettingsModel::stateForRow(int row) const
-{
- QStandardItem *standardItem = item(row, StateRow);
-
- if (standardItem)
- return timelineView()->modelNodeForInternalId(standardItem->data().toInt());
-
- return ModelNode();
-}
-
-int TimelineSettingsModel::fixedFrameForRow(int row) const
-{
- QStandardItem *standardItem = item(row, FixedFrameRow);
-
- if (standardItem)
- return standardItem->data(Qt::EditRole).toInt();
-
- return -1;
-}
-
-void TimelineSettingsModel::handleDataChanged(const QModelIndex &topLeft,
- const QModelIndex &bottomRight)
-{
- if (topLeft != bottomRight) {
- qWarning() << "TimelineSettingsModel::handleDataChanged multi edit?";
- return;
- }
-
- if (m_lock)
- return;
-
- m_lock = true;
-
- int currentColumn = topLeft.column();
- int currentRow = topLeft.row();
-
- switch (currentColumn) {
- case StateRow: {
- /* read only */
- } break;
- case TimelineRow: {
- updateTimeline(currentRow);
- } break;
- case AnimationRow: {
- updateAnimation(currentRow);
- } break;
- case FixedFrameRow: {
- updateFixedFrameRow(currentRow);
- } break;
-
- default:
- qWarning() << "ConnectionModel::handleDataChanged column" << currentColumn;
- }
-
- m_lock = false;
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineview.cpp b/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineview.cpp
deleted file mode 100644
index 653ed27ba7..0000000000
--- a/src/plugins/qmldesigner/qmldesignerextension/timelineeditor/timelineview.cpp
+++ /dev/null
@@ -1,625 +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 "timelineview.h"
-
-#include "easingcurve.h"
-#include "timelineactions.h"
-#include "timelineconstants.h"
-#include "timelinecontext.h"
-#include "timelinewidget.h"
-
-#include "timelinegraphicsscene.h"
-#include "timelinesettingsdialog.h"
-#include "timelinetoolbar.h"
-
-#include <bindingproperty.h>
-#include <exception.h>
-#include <modelnodecontextmenu_helper.h>
-#include <nodeabstractproperty.h>
-#include <nodelistproperty.h>
-#include <nodemetainfo.h>
-#include <rewritertransaction.h>
-#include <variantproperty.h>
-#include <qmldesignericons.h>
-#include <qmldesignerplugin.h>
-#include <qmlitemnode.h>
-#include <qmlobjectnode.h>
-#include <qmlstate.h>
-#include <qmltimeline.h>
-#include <qmltimelinekeyframegroup.h>
-#include <viewmanager.h>
-
-#include <coreplugin/icore.h>
-
-#include <utils/qtcassert.h>
-
-#include <designmodecontext.h>
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-#include <QTimer>
-
-namespace QmlDesigner {
-
-TimelineView::TimelineView(QObject *parent)
- : AbstractView(parent)
-{
- EasingCurve::registerStreamOperators();
-}
-
-TimelineView::~TimelineView() = default;
-
-void TimelineView::modelAttached(Model *model)
-{
- AbstractView::modelAttached(model);
- if (m_timelineWidget)
- m_timelineWidget->init();
-}
-
-void TimelineView::modelAboutToBeDetached(Model *model)
-{
- m_timelineWidget->reset();
- setTimelineRecording(false);
- AbstractView::modelAboutToBeDetached(model);
-}
-
-void TimelineView::nodeCreated(const ModelNode & /*createdNode*/) {}
-
-void TimelineView::nodeAboutToBeRemoved(const ModelNode &removedNode)
-{
- if (removedNode.isValid()) {
- if (QmlTimeline::isValidQmlTimeline(removedNode)) {
- auto *toolBar = widget()->toolBar();
-
- QString lastId = toolBar->currentTimelineId();
- toolBar->removeTimeline(QmlTimeline(removedNode));
- QString currentId = toolBar->currentTimelineId();
-
- removedNode.setAuxiliaryData("removed@Internal", true);
-
- if (currentId.isEmpty())
- m_timelineWidget->graphicsScene()->clearTimeline();
- if (lastId != currentId)
- m_timelineWidget->setTimelineId(currentId);
- } else if (removedNode.parentProperty().isValid()
- && QmlTimeline::isValidQmlTimeline(removedNode.parentProperty().parentModelNode())) {
- if (removedNode.hasBindingProperty("target")) {
- const ModelNode target = removedNode.bindingProperty("target").resolveToModelNode();
- if (target.isValid()) {
- QmlTimeline timeline(removedNode.parentProperty().parentModelNode());
- if (timeline.hasKeyframeGroupForTarget(target))
- QTimer::singleShot(0, [this, target, timeline]() {
- if (timeline.hasKeyframeGroupForTarget(target))
- m_timelineWidget->graphicsScene()->invalidateSectionForTarget(target);
- else
- m_timelineWidget->graphicsScene()->invalidateScene();
- });
- }
- }
- }
- }
-}
-
-void TimelineView::nodeRemoved(const ModelNode & /*removedNode*/,
- const NodeAbstractProperty &parentProperty,
- PropertyChangeFlags /*propertyChange*/)
-{
- if (parentProperty.isValid()
- && QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(
- parentProperty.parentModelNode())) {
- QmlTimelineKeyframeGroup frames(parentProperty.parentModelNode());
- m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
- }
-}
-
-void TimelineView::nodeReparented(const ModelNode &node,
- const NodeAbstractProperty &newPropertyParent,
- const NodeAbstractProperty & /*oldPropertyParent*/,
- AbstractView::PropertyChangeFlags /*propertyChange*/)
-{
- if (newPropertyParent.isValid()
- && QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(
- newPropertyParent.parentModelNode())) {
- QmlTimelineKeyframeGroup frames(newPropertyParent.parentModelNode());
- m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
- } else if (QmlTimelineKeyframeGroup::checkKeyframesType(
- node)) { /* During copy and paste type info might be incomplete */
- QmlTimelineKeyframeGroup frames(node);
- m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
- }
-}
-
-void TimelineView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName>> &propertyList)
-{
- QmlTimeline timeline = currentTimeline();
- bool updated = false;
- for (const auto &pair : propertyList) {
- if (pair.second == "startFrame" || pair.second == "endFrame") {
- if (QmlTimeline::isValidQmlTimeline(pair.first)) {
- m_timelineWidget->invalidateTimelineDuration(pair.first);
- }
- } else if (pair.second == "currentFrame") {
- if (QmlTimeline::isValidQmlTimeline(pair.first)) {
- m_timelineWidget->invalidateTimelinePosition(pair.first);
- }
- } else if (!updated && timeline.hasTimeline(pair.first, pair.second)) {
- m_timelineWidget->graphicsScene()->invalidateCurrentValues();
- updated = true;
- }
- }
-}
-
-void TimelineView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
- AbstractView::PropertyChangeFlags /*propertyChange*/)
-{
- for (const auto &property : propertyList) {
- if (property.name() == "frame"
- && property.parentModelNode().type() == "QtQuick.Timeline.Keyframe"
- && property.parentModelNode().isValid()
- && property.parentModelNode().hasParentProperty()) {
- const ModelNode framesNode
- = property.parentModelNode().parentProperty().parentModelNode();
- if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(framesNode)) {
- QmlTimelineKeyframeGroup frames(framesNode);
- m_timelineWidget->graphicsScene()->invalidateKeyframesForTarget(frames.target());
- }
- }
- }
-}
-
-void TimelineView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/,
- const QList<ModelNode> & /*lastSelectedNodeList*/)
-{
- if (m_timelineWidget)
- m_timelineWidget->graphicsScene()->update();
-}
-
-void TimelineView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList)
-{
- for (const auto &property : propertyList) {
- if (property.isNodeListProperty()) {
- for (const auto &node : property.toNodeListProperty().toModelNodeList()) {
- nodeAboutToBeRemoved(node);
- }
- }
- }
-}
-
-void TimelineView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
-{
- for (const auto &property : propertyList) {
- if (property.name() == "keyframes" && property.parentModelNode().isValid()) {
- if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(
- property.parentModelNode())) {
- QmlTimelineKeyframeGroup frames(property.parentModelNode());
- m_timelineWidget->graphicsScene()->invalidateSectionForTarget(frames.target());
- } else if (QmlTimeline::isValidQmlTimeline(property.parentModelNode())) {
- m_timelineWidget->graphicsScene()->invalidateScene();
- }
- }
- }
-}
-
-bool TimelineView::hasWidget() const
-{
- return true;
-}
-
-void TimelineView::nodeIdChanged(const ModelNode &node, const QString &, const QString &)
-{
- if (QmlTimeline::isValidQmlTimeline(node))
- m_timelineWidget->init();
-}
-
-void TimelineView::currentStateChanged(const ModelNode &)
-{
- if (m_timelineWidget)
- m_timelineWidget->init();
-}
-
-TimelineWidget *TimelineView::widget() const
-{
- return m_timelineWidget;
-}
-
-const QmlTimeline TimelineView::addNewTimeline()
-{
- const TypeName timelineType = "QtQuick.Timeline.Timeline";
-
- QTC_ASSERT(isAttached(), return QmlTimeline());
-
- try {
- ensureQtQuickTimelineImport();
- } catch (const Exception &e) {
- e.showException();
- }
-
- NodeMetaInfo metaInfo = model()->metaInfo(timelineType);
-
- QTC_ASSERT(metaInfo.isValid(), return QmlTimeline());
-
- ModelNode timelineNode;
-
- try {
- RewriterTransaction transaction(beginRewriterTransaction("TimelineView::addNewTimeline"));
-
- bool hasTimelines = getTimelines().isEmpty();
-
- timelineNode = createModelNode(timelineType,
- metaInfo.majorVersion(),
- metaInfo.minorVersion());
- timelineNode.validId();
-
- timelineNode.variantProperty("startFrame").setValue(0);
- timelineNode.variantProperty("endFrame").setValue(1000);
- timelineNode.variantProperty("enabled").setValue(hasTimelines);
-
- rootModelNode().defaultNodeListProperty().reparentHere(timelineNode);
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-
- return QmlTimeline(timelineNode);
-}
-
-ModelNode TimelineView::addAnimation(QmlTimeline timeline)
-{
- const TypeName animationType = "QtQuick.Timeline.TimelineAnimation";
-
- QTC_ASSERT(timeline.isValid(), return ModelNode());
-
- QTC_ASSERT(isAttached(), return ModelNode());
-
- NodeMetaInfo metaInfo = model()->metaInfo(animationType);
-
- QTC_ASSERT(metaInfo.isValid(), return ModelNode());
-
- ModelNode animationNode;
- try {
- RewriterTransaction transaction(
- beginRewriterTransaction("TimelineSettingsDialog::addAnimation"));
-
- animationNode = createModelNode(animationType,
- metaInfo.majorVersion(),
- metaInfo.minorVersion());
- animationNode.variantProperty("duration").setValue(timeline.duration());
- animationNode.validId();
-
- animationNode.variantProperty("from").setValue(timeline.startKeyframe());
- animationNode.variantProperty("to").setValue(timeline.endKeyframe());
-
- animationNode.variantProperty("loops").setValue(1);
-
- animationNode.variantProperty("running").setValue(getAnimations(timeline).isEmpty());
-
- timeline.modelNode().nodeListProperty("animations").reparentHere(animationNode);
-
- if (timeline.modelNode().hasProperty("currentFrame"))
- timeline.modelNode().removeProperty("currentFrame");
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
-
- return animationNode;
-}
-
-void TimelineView::addNewTimelineDialog()
-{
- auto timeline = addNewTimeline();
- addAnimation(timeline);
- openSettingsDialog();
-}
-
-void TimelineView::openSettingsDialog()
-{
- auto dialog = new TimelineSettingsDialog(Core::ICore::dialogParent(), this);
-
- auto timeline = m_timelineWidget->graphicsScene()->currentTimeline();
- if (timeline.isValid())
- dialog->setCurrentTimeline(timeline);
-
- QObject::connect(dialog, &TimelineSettingsDialog::rejected, [this, dialog]() {
- m_timelineWidget->init();
- dialog->deleteLater();
- });
-
- QObject::connect(dialog, &TimelineSettingsDialog::accepted, [this, dialog]() {
- m_timelineWidget->init();
- dialog->deleteLater();
- });
-
- dialog->show();
-}
-
-void TimelineView::setTimelineRecording(bool value)
-{
- ModelNode node = widget()->graphicsScene()->currentTimeline();
-
- QTC_ASSERT(node.isValid(), return );
-
- if (value) {
- activateTimelineRecording(node);
- } else {
- deactivateTimelineRecording();
- activateTimeline(node);
- }
-}
-
-void TimelineView::customNotification(const AbstractView * /*view*/,
- const QString &identifier,
- const QList<ModelNode> &nodeList,
- const QList<QVariant> &data)
-{
- if (identifier == QStringLiteral("reset QmlPuppet")) {
- QmlTimeline timeline = widget()->graphicsScene()->currentTimeline();
- if (timeline.isValid())
- timeline.modelNode().removeAuxiliaryData("currentFrame@NodeInstance");
- } else if (identifier == "INSERT_KEYFRAME" && !nodeList.isEmpty() && !data.isEmpty()) {
- insertKeyframe(nodeList.constFirst(), data.constFirst().toString().toUtf8());
- }
-}
-
-void TimelineView::insertKeyframe(const ModelNode &target, const PropertyName &propertyName)
-{
- QmlTimeline timeline = widget()->graphicsScene()->currentTimeline();
- ModelNode targetNode = target;
- if (timeline.isValid() && targetNode.isValid()
- && QmlObjectNode::isValidQmlObjectNode(targetNode)) {
- try {
- RewriterTransaction transaction(
- beginRewriterTransaction("TimelineView::insertKeyframe"));
-
- targetNode.validId();
-
- QmlTimelineKeyframeGroup timelineFrames(
- timeline.keyframeGroup(targetNode, propertyName));
-
- QTC_ASSERT(timelineFrames.isValid(), return );
-
- const qreal frame
- = timeline.modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
- const QVariant value = QmlObjectNode(targetNode).instanceValue(propertyName);
-
- timelineFrames.setValue(value, frame);
-
- transaction.commit();
- } catch (const Exception &e) {
- e.showException();
- }
- }
-}
-
-QList<QmlTimeline> TimelineView::getTimelines() const
-{
- QList<QmlTimeline> timelines;
-
- if (!isAttached())
- return timelines;
-
- for (const ModelNode &modelNode : allModelNodes()) {
- if (QmlTimeline::isValidQmlTimeline(modelNode) && !modelNode.hasAuxiliaryData("removed@Internal")) {
- timelines.append(modelNode);
- }
- }
- return timelines;
-}
-
-QList<ModelNode> TimelineView::getAnimations(const QmlTimeline &timeline)
-{
- if (!timeline.isValid())
- return QList<ModelNode>();
-
- if (isAttached()) {
- return Utils::filtered(timeline.modelNode().directSubModelNodes(),
- [timeline](const ModelNode &node) {
- if (node.metaInfo().isValid() && node.hasParentProperty()
- && (node.parentProperty().parentModelNode()
- == timeline.modelNode()))
- return node.metaInfo().isSubclassOf(
- "QtQuick.Timeline.TimelineAnimation");
- return false;
- });
- }
- return {};
-}
-
-QmlTimeline TimelineView::timelineForState(const ModelNode &state) const
-{
- QmlModelState modelState(state);
-
- const QList<QmlTimeline> &timelines = getTimelines();
-
- if (modelState.isBaseState()) {
- for (const auto &timeline : timelines) {
- if (timeline.modelNode().hasVariantProperty("enabled")
- && timeline.modelNode().variantProperty("enabled").value().toBool())
- return timeline;
- }
- return QmlTimeline();
- }
-
- for (const auto &timeline : timelines) {
- if (modelState.affectsModelNode(timeline)) {
- QmlPropertyChanges propertyChanges(modelState.propertyChanges(timeline));
-
- if (propertyChanges.isValid() && propertyChanges.modelNode().hasProperty("enabled")
- && propertyChanges.modelNode().variantProperty("enabled").value().toBool())
- return timeline;
- }
- }
- return QmlTimeline();
-}
-
-QmlModelState TimelineView::stateForTimeline(const QmlTimeline &timeline)
-{
- if (timeline.modelNode().hasVariantProperty("enabled")
- && timeline.modelNode().variantProperty("enabled").value().toBool()) {
- return QmlModelState(rootModelNode());
- }
-
- for (const QmlModelState &state : QmlItemNode(rootModelNode()).states().allStates()) {
- if (timelineForState(state) == timeline)
- return state;
- }
-
- return QmlModelState();
-}
-
-void TimelineView::registerActions()
-{
- auto &actionManager = QmlDesignerPlugin::instance()->viewManager().designerActionManager();
-
- SelectionContextPredicate timelineEnabled = [this](const SelectionContext &context) {
- return context.singleNodeIsSelected()
- && widget()->graphicsScene()->currentTimeline().isValid();
- };
-
- SelectionContextPredicate timelineHasKeyframes =
- [this](const SelectionContext &context) {
- auto timeline = widget()->graphicsScene()->currentTimeline();
- return !timeline.keyframeGroupsForTarget(context.currentSingleSelectedNode()).isEmpty();
- };
-
- SelectionContextPredicate timelineHasClipboard = [](const SelectionContext &context) {
- return !context.fastUpdate() && TimelineActions::clipboardContainsKeyframes();
- };
-
- SelectionContextOperation deleteKeyframes = [this](const SelectionContext &context) {
- auto mutator = widget()->graphicsScene()->currentTimeline();
- if (mutator.isValid())
- TimelineActions::deleteAllKeyframesForTarget(context.currentSingleSelectedNode(),
- mutator);
- };
-
- SelectionContextOperation insertKeyframes = [this](const SelectionContext &context) {
- auto mutator = widget()->graphicsScene()->currentTimeline();
- if (mutator.isValid())
- TimelineActions::insertAllKeyframesForTarget(context.currentSingleSelectedNode(),
- mutator);
- };
-
- SelectionContextOperation copyKeyframes = [this](const SelectionContext &context) {
- auto mutator = widget()->graphicsScene()->currentTimeline();
- if (mutator.isValid())
- TimelineActions::copyAllKeyframesForTarget(context.currentSingleSelectedNode(), mutator);
- };
-
- SelectionContextOperation pasteKeyframes = [this](const SelectionContext &context) {
- auto mutator = widget()->graphicsScene()->currentTimeline();
- if (mutator.isValid())
- TimelineActions::pasteKeyframesToTarget(context.currentSingleSelectedNode(), mutator);
- };
-
- actionManager.addDesignerAction(new ActionGroup(TimelineConstants::timelineCategoryDisplayName,
- TimelineConstants::timelineCategory,
- TimelineConstants::priorityTimelineCategory,
- timelineEnabled,
- &SelectionContextFunctors::always));
-
- actionManager.addDesignerAction(
- new ModelNodeContextMenuAction("commandId timeline delete",
- TimelineConstants::timelineDeleteKeyframesDisplayName,
- {},
- TimelineConstants::timelineCategory,
- QKeySequence(),
- 160,
- deleteKeyframes,
- timelineHasKeyframes));
-
- actionManager.addDesignerAction(
- new ModelNodeContextMenuAction("commandId timeline insert",
- TimelineConstants::timelineInsertKeyframesDisplayName,
- {},
- TimelineConstants::timelineCategory,
- QKeySequence(),
- 140,
- insertKeyframes,
- timelineHasKeyframes));
-
- actionManager.addDesignerAction(
- new ModelNodeContextMenuAction("commandId timeline copy",
- TimelineConstants::timelineCopyKeyframesDisplayName,
- {},
- TimelineConstants::timelineCategory,
- QKeySequence(),
- 120,
- copyKeyframes,
- timelineHasKeyframes));
-
- actionManager.addDesignerAction(
- new ModelNodeContextMenuAction("commandId timeline paste",
- TimelineConstants::timelinePasteKeyframesDisplayName,
- {},
- TimelineConstants::timelineCategory,
- QKeySequence(),
- 100,
- pasteKeyframes,
- timelineHasClipboard));
-}
-
-TimelineWidget *TimelineView::createWidget()
-{
- if (!m_timelineWidget)
- m_timelineWidget = new TimelineWidget(this);
-
- auto *timelineContext = new TimelineContext(m_timelineWidget);
- Core::ICore::addContextObject(timelineContext);
-
- return m_timelineWidget;
-}
-
-WidgetInfo TimelineView::widgetInfo()
-{
- return createWidgetInfo(createWidget(),
- nullptr,
- QStringLiteral("Timelines"),
- WidgetInfo::BottomPane,
- 0,
- tr("Timeline"));
-}
-
-bool TimelineView::hasQtQuickTimelineImport()
-{
- if (isAttached()) {
- Import import = Import::createLibraryImport("QtQuick.Timeline", "1.0");
- return model()->hasImport(import, true, true);
- }
-
- return false;
-}
-
-void TimelineView::ensureQtQuickTimelineImport()
-{
- if (!hasQtQuickTimelineImport()) {
- Import timelineImport = Import::createLibraryImport("QtQuick.Timeline", "1.0");
- model()->changeImports({timelineImport}, {});
- }
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index 42fd9fbefa..eb16cbedd1 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -217,13 +217,13 @@ void QmlDesignerPlugin::extensionsInitialized()
});
}
-static QStringList allUiQmlFilesforCurrentProject(const Utils::FileName &fileName)
+static QStringList allUiQmlFilesforCurrentProject(const Utils::FilePath &fileName)
{
QStringList list;
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(fileName);
if (currentProject) {
- foreach (const Utils::FileName &fileName, currentProject->files(ProjectExplorer::Project::SourceFiles)) {
+ foreach (const Utils::FilePath &fileName, currentProject->files(ProjectExplorer::Project::SourceFiles)) {
if (fileName.endsWith(".ui.qml"))
list.append(fileName.toString());
}
@@ -232,7 +232,7 @@ static QStringList allUiQmlFilesforCurrentProject(const Utils::FileName &fileNam
return list;
}
-static QString projectPath(const Utils::FileName &fileName)
+static QString projectPath(const Utils::FilePath &fileName)
{
QString path;
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(fileName);
@@ -304,7 +304,7 @@ void QmlDesignerPlugin::showDesigner()
d->mainWidget.initialize();
- const Utils::FileName fileName = Core::EditorManager::currentEditor()->document()->filePath();
+ const Utils::FilePath fileName = Core::EditorManager::currentEditor()->document()->filePath();
const QStringList allUiQmlFiles = allUiQmlFilesforCurrentProject(fileName);
if (warningsForQmlFilesInsteadOfUiQmlEnabled() && !fileName.endsWith(".ui.qml") && !allUiQmlFiles.isEmpty()) {
OpenUiQmlFileDialog dialog(&d->mainWidget);
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.pro b/src/plugins/qmldesigner/qmldesignerplugin.pro
index cc78fdc5db..52e3e19a44 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.pro
+++ b/src/plugins/qmldesigner/qmldesignerplugin.pro
@@ -2,6 +2,7 @@ QT += quickwidgets core-private
CONFIG += exceptions
INCLUDEPATH += $$PWD
+INCLUDEPATH += $$PWD/components
unix:!openbsd:!osx: LIBS += -lrt # posix shared memory
@@ -20,7 +21,13 @@ include(components/stateseditor/stateseditor.pri)
include(components/resources/resources.pri)
include(components/debugview/debugview.pri)
include(components/importmanager/importmanager.pri)
-include(qmldesignerextension/qmldesignerextension.pri)
+include(components/sourcetool/sourcetool.pri)
+include(components/colortool/colortool.pri)
+include(components/texttool/texttool.pri)
+include(components/pathtool/pathtool.pri)
+include(components/timelineeditor/timelineeditor.pri)
+include(components/connectioneditor/connectioneditor.pri)
+include(components/curveeditor/curveeditor.pri)
BUILD_PUPPET_IN_CREATOR_BINPATH = $$(BUILD_PUPPET_IN_CREATOR_BINPATH)
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs
index 3360a53214..4cba901e20 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.qbs
+++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs
@@ -29,7 +29,7 @@ Project {
cpp.defines: base.concat([
"DESIGNER_CORE_LIBRARY",
- "TIMELINE_QML_PATH=\"" + FileInfo.joinPaths(path, "qmldesignerextension",
+ "TIMELINE_QML_PATH=\"" + FileInfo.joinPaths(path, "components",
"timelineeditor", "qml") + "\""
])
cpp.enableExceptions: true
@@ -42,7 +42,10 @@ Project {
"../../../share/qtcreator/qml/qmlpuppet/container",
"../../../share/qtcreator/qml/qmlpuppet/commands",
"../../../share/qtcreator/qml/qmlpuppet/types",
+ "components",
"components/componentcore",
+ "components/curveeditor",
+ "components/connectioneditor",
"components/debugview",
"components/importmanager",
"components/integration",
@@ -52,10 +55,7 @@ Project {
"components/navigator",
"components/pluginmanager",
"components/stateseditor",
- "components/texteditor",
- "qmldesignerextension",
- "qmldesignerextension/connectioneditor",
- "qmldesignerextension/timelineeditor",
+ "components/texteditor"
])
Properties {
@@ -562,6 +562,14 @@ Project {
"propertyeditor/fileresourcesmodel.h",
"propertyeditor/gradientmodel.cpp",
"propertyeditor/gradientmodel.h",
+ "propertyeditor/gradientpresetcustomlistmodel.cpp",
+ "propertyeditor/gradientpresetcustomlistmodel.h",
+ "propertyeditor/gradientpresetdefaultlistmodel.cpp",
+ "propertyeditor/gradientpresetdefaultlistmodel.h",
+ "propertyeditor/gradientpresetitem.cpp",
+ "propertyeditor/gradientpresetitem.h",
+ "propertyeditor/gradientpresetlistmodel.cpp",
+ "propertyeditor/gradientpresetlistmodel.h",
"propertyeditor/propertyeditorcontextobject.cpp",
"propertyeditor/propertyeditorcontextobject.h",
"propertyeditor/propertyeditortransaction.cpp",
@@ -580,6 +588,12 @@ Project {
"propertyeditor/qmlanchorbindingproxy.h",
"propertyeditor/qmlmodelnodeproxy.cpp",
"propertyeditor/qmlmodelnodeproxy.h",
+ "propertyeditor/simplecolorpalette.cpp",
+ "propertyeditor/simplecolorpalette.h",
+ "propertyeditor/simplecolorpalettemodel.cpp",
+ "propertyeditor/simplecolorpalettemodel.h",
+ "propertyeditor/simplecolorpalettesingleton.cpp",
+ "propertyeditor/simplecolorpalettesingleton.h",
"resources/resources.qrc",
"stateseditor/stateseditorimageprovider.cpp",
"stateseditor/stateseditorimageprovider.h",
@@ -594,7 +608,7 @@ Project {
Group {
name: "extension"
- prefix: "qmldesignerextension/"
+ prefix: "components/"
files: [
"colortool/colortool.cpp",
"colortool/colortool.h",
@@ -618,6 +632,49 @@ Project {
"connectioneditor/dynamicpropertiesmodel.cpp",
"connectioneditor/dynamicpropertiesmodel.h",
"connectioneditor/stylesheet.css",
+ "curveeditor/animationcurve.cpp",
+ "curveeditor/animationcurve.h",
+ "curveeditor/curveeditor.cpp",
+ "curveeditor/curveeditor.h",
+ "curveeditor/curveeditormodel.cpp",
+ "curveeditor/curveeditormodel.h",
+ "curveeditor/curveeditorstyle.h",
+ "curveeditor/keyframe.cpp",
+ "curveeditor/keyframe.h",
+ "curveeditor/treeitem.cpp",
+ "curveeditor/treeitem.h",
+ "curveeditor/detail/colorcontrol.cpp",
+ "curveeditor/detail/colorcontrol.h",
+ "curveeditor/detail/curveeditorstyledialog.cpp",
+ "curveeditor/detail/curveeditorstyledialog.h",
+ "curveeditor/detail/curveitem.cpp",
+ "curveeditor/detail/curveitem.h",
+ "curveeditor/detail/curvesegment.cpp",
+ "curveeditor/detail/curvesegment.h",
+ "curveeditor/detail/graphicsscene.cpp",
+ "curveeditor/detail/graphicsscene.h",
+ "curveeditor/detail/graphicsview.cpp",
+ "curveeditor/detail/graphicsview.h",
+ "curveeditor/detail/handleitem.cpp",
+ "curveeditor/detail/handleitem.h",
+ "curveeditor/detail/keyframeitem.cpp",
+ "curveeditor/detail/keyframeitem.h",
+ "curveeditor/detail/playhead.cpp",
+ "curveeditor/detail/playhead.h",
+ "curveeditor/detail/selectableitem.cpp",
+ "curveeditor/detail/selectableitem.h",
+ "curveeditor/detail/selector.cpp",
+ "curveeditor/detail/selector.h",
+ "curveeditor/detail/shortcut.cpp",
+ "curveeditor/detail/shortcut.h",
+ "curveeditor/detail/treeitemdelegate.cpp",
+ "curveeditor/detail/treeitemdelegate.h",
+ "curveeditor/detail/treemodel.cpp",
+ "curveeditor/detail/treemodel.h",
+ "curveeditor/detail/treeview.cpp",
+ "curveeditor/detail/treeview.h",
+ "curveeditor/detail/utils.cpp",
+ "curveeditor/detail/utils.h",
"pathtool/controlpoint.cpp",
"pathtool/controlpoint.h",
"pathtool/cubicsegment.cpp",
@@ -630,8 +687,6 @@ Project {
"pathtool/pathtool.h",
"pathtool/pathtoolview.cpp",
"pathtool/pathtoolview.h",
- "qmldesignerextensionconstants.h",
- "qmldesignerextension_global.h",
"sourcetool/sourcetool.cpp",
"sourcetool/sourcetool.h",
"texttool/textedititem.cpp",
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png
new file mode 100644
index 0000000000..b56467d4ea
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png
new file mode 100644
index 0000000000..93c49a04eb
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/images/live_preview@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo
new file mode 100644
index 0000000000..5bfe70cffd
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreview.metainfo
@@ -0,0 +1,2 @@
+MetaInfo {
+}
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp
new file mode 100644
index 0000000000..1fe99825c3
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** 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 "qmlpreviewplugin.h"
+#include "qmlpreviewactions.h"
+
+#include <zoomaction.h>
+
+#include <utils/utilsicons.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/project.h>
+
+#include <QLabel>
+#include <QComboBox>
+#include <QPointer>
+
+namespace QmlDesigner {
+
+using namespace ProjectExplorer;
+
+const Utils::Icon previewIcon({
+ {":/qmlpreviewplugin/images/live_preview.png", Utils::Theme::IconsBaseColor}});
+
+static void handleAction(const SelectionContext &context)
+{
+ if (context.view()->isAttached()) {
+ if (context.toggled()) {
+ ProjectExplorerPlugin::runStartupProject(Constants::QML_PREVIEW_RUN_MODE);
+ QmlPreviewPlugin::setQmlFile();
+ } else {
+ QmlPreviewPlugin::stopAllRunControls();
+ }
+ }
+}
+
+QmlPreviewAction::QmlPreviewAction() : ModelNodeAction("LivePreview",
+ "Live Preview",
+ previewIcon.icon(),
+ QmlPreviewPlugin::tr("Show Live Preview"),
+ ComponentCoreConstants::qmlPreviewCategory,
+ QKeySequence("Alt+p"),
+ 20,
+ &handleAction,
+ &SelectionContextFunctors::always)
+{
+ if (!QmlPreviewPlugin::getPreviewPlugin())
+ defaultAction()->setVisible(false);
+
+ defaultAction()->setCheckable(true);
+}
+
+void QmlPreviewAction::updateContext()
+{
+ if (selectionContext().view()->isAttached())
+ QmlPreviewPlugin::setQmlFile();
+
+ defaultAction()->setSelectionContext(selectionContext());
+}
+
+ActionInterface::Type QmlPreviewAction::type() const
+{
+ return ToolBarAction;
+}
+
+ZoomPreviewAction::ZoomPreviewAction()
+ : m_zoomAction(new ZoomAction(nullptr))
+{
+ QObject::connect(m_zoomAction.get(), &ZoomAction::zoomLevelChanged, [=](float d) {
+ QmlPreviewPlugin::setZoomFactor(d);
+ });
+ if (!QmlPreviewPlugin::getPreviewPlugin())
+ m_zoomAction->setVisible(false);
+}
+
+ZoomPreviewAction::~ZoomPreviewAction()
+= default;
+
+QAction *ZoomPreviewAction::action() const
+{
+ return m_zoomAction.get();
+}
+
+QByteArray ZoomPreviewAction::category() const
+{
+ return ComponentCoreConstants::qmlPreviewCategory;
+}
+
+QByteArray ZoomPreviewAction::menuId() const
+{
+ return QByteArray();
+}
+
+int ZoomPreviewAction::priority() const
+{
+ return 19;
+}
+
+ActionInterface::Type ZoomPreviewAction::type() const
+{
+ return ToolBarAction;
+}
+
+void ZoomPreviewAction::currentContextChanged(const SelectionContext &)
+{}
+
+quint16 FpsLabelAction::lastValidFrames = 0;
+QList<QPointer<QLabel>> FpsLabelAction::fpsHandlerLabelList;
+
+FpsLabelAction::FpsLabelAction(QObject *parent)
+ : QWidgetAction(parent)
+{
+}
+
+void FpsLabelAction::fpsHandler(quint16 fpsValues[8])
+{
+ quint16 frames = fpsValues[0];
+ if (frames != 0)
+ lastValidFrames = frames;
+ QString fpsText("%1 FPS");
+ if (lastValidFrames == 0 || (frames == 0 && lastValidFrames < 2))
+ fpsText = fpsText.arg("--");
+ else
+ fpsText = fpsText.arg(lastValidFrames);
+ for (QPointer<QLabel> label : fpsHandlerLabelList) {
+ if (label)
+ label->setText(fpsText);
+ }
+}
+
+void FpsLabelAction::cleanFpsCounter()
+{
+ lastValidFrames = 0;
+ quint16 nullInitialized[8] = {0};
+ fpsHandler(nullInitialized);
+}
+
+QWidget *FpsLabelAction::createWidget(QWidget *parent)
+{
+ auto label = new QLabel(parent);
+ auto originList = fpsHandlerLabelList;
+ fpsHandlerLabelList.clear();
+ fpsHandlerLabelList.append(label);
+ for (const auto &labelPointer : originList) {
+ if (labelPointer)
+ fpsHandlerLabelList.append(labelPointer);
+ }
+
+ return label;
+}
+
+void FpsLabelAction::refreshFpsLabel(quint16 frames)
+{
+ for (const auto &labelPointer : fpsHandlerLabelList) {
+ if (labelPointer)
+ labelPointer->setText(QString("%1 FPS").arg(frames));
+ }
+}
+
+FpsAction::FpsAction() : m_fpsLabelAction(new FpsLabelAction(nullptr))
+{}
+
+QAction *FpsAction::action() const
+{
+ return m_fpsLabelAction.get();
+}
+
+QByteArray FpsAction::category() const
+{
+ return ComponentCoreConstants::qmlPreviewCategory;
+}
+
+QByteArray FpsAction::menuId() const
+{
+ return QByteArray();
+}
+
+int FpsAction::priority() const
+{
+ return 19;
+}
+
+ActionInterface::Type FpsAction::type() const
+{
+ return ToolBarAction;
+}
+
+void FpsAction::currentContextChanged(const SelectionContext &)
+{}
+
+SwitchLanguageComboboxAction::SwitchLanguageComboboxAction(QObject *parent)
+ : QWidgetAction(parent)
+{
+ connect(ProjectExplorer::SessionManager::instance(),
+ &ProjectExplorer::SessionManager::startupProjectChanged,
+ this,
+ &SwitchLanguageComboboxAction::refreshProjectLocales);
+}
+
+QWidget *SwitchLanguageComboboxAction::createWidget(QWidget *parent)
+{
+ QPointer<QComboBox> comboBox = new QComboBox(parent);
+ comboBox->setToolTip(tr("Switch the language used by preview."));
+ connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, comboBox](int index) {
+ if (index == 0)
+ emit currentLocaleChanged("");
+ else
+ emit currentLocaleChanged(comboBox->currentText());
+ });
+
+ auto refreshComboBoxFunction = [this, comboBox] (ProjectExplorer::Project *project) {
+ if (comboBox) {
+ refreshProjectLocales(project);
+ comboBox->clear();
+ comboBox->addItem(tr("Default"));
+ comboBox->addItems(m_localeStrings);
+ }
+ };
+ connect(ProjectExplorer::SessionManager::instance(),
+ &ProjectExplorer::SessionManager::startupProjectChanged,
+ refreshComboBoxFunction);
+
+ if (auto project = SessionManager::startupProject())
+ refreshComboBoxFunction(project);
+
+ return comboBox;
+}
+
+void SwitchLanguageComboboxAction::refreshProjectLocales(Project *project)
+{
+ if (!project)
+ return;
+ m_localeStrings.clear();
+ const auto projectDirectory = project->rootProjectDirectory().toFileInfo().absoluteFilePath();
+ const QDir languageDirectory(projectDirectory + "/i18n");
+ const auto qmFiles = languageDirectory.entryList({"qml_*.qm"});
+ m_localeStrings = Utils::transform(qmFiles, [](const QString &qmFile) {
+ const int localeStartPosition = qmFile.lastIndexOf("_") + 1;
+ const int localeEndPosition = qmFile.size() - QString(".qm").size();
+ const QString locale = qmFile.left(localeEndPosition).mid(localeStartPosition);
+ return locale;
+ });
+}
+
+SwitchLanguageAction::SwitchLanguageAction()
+ : m_switchLanguageAction(new SwitchLanguageComboboxAction(nullptr))
+{
+ QObject::connect(m_switchLanguageAction.get(), &SwitchLanguageComboboxAction::currentLocaleChanged,
+ &QmlPreviewPlugin::setLanguageLocale);
+}
+
+QAction *SwitchLanguageAction::action() const
+{
+ return m_switchLanguageAction.get();
+}
+
+QByteArray SwitchLanguageAction::category() const
+{
+ return ComponentCoreConstants::qmlPreviewCategory;
+}
+
+QByteArray SwitchLanguageAction::menuId() const
+{
+ return QByteArray();
+}
+
+int SwitchLanguageAction::priority() const
+{
+ return 10;
+}
+
+ActionInterface::Type SwitchLanguageAction::type() const
+{
+ return ToolBarAction;
+}
+
+void SwitchLanguageAction::currentContextChanged(const SelectionContext &)
+{}
+
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h
new file mode 100644
index 0000000000..8a71ee07c2
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewactions.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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 <actioninterface.h>
+#include <modelnodecontextmenu_helper.h>
+
+#include <QByteArray>
+
+#include <QWidgetAction>
+#include <memory>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+QT_FORWARD_DECLARE_CLASS(QLabel)
+
+
+namespace QmlPreview {
+using QmlPreviewFpsHandler = void (*)(quint16 *);
+}
+
+namespace ProjectExplorer {
+class Project;
+}
+
+namespace QmlDesigner {
+class ZoomAction;
+
+class QmlPreviewAction : public ModelNodeAction
+{
+public:
+ QmlPreviewAction();
+
+ void updateContext() override;
+
+ Type type() const override;
+};
+
+class ZoomPreviewAction : public ActionInterface
+{
+public:
+ ZoomPreviewAction();
+ ~ZoomPreviewAction() override;
+ QAction *action() const override;
+ QByteArray category() const override;
+ QByteArray menuId() const override;
+ int priority() const override;
+ Type type() const override;
+ void currentContextChanged(const SelectionContext &) override;
+
+private:
+ std::unique_ptr<ZoomAction> m_zoomAction;
+};
+
+class FpsLabelAction : public QWidgetAction
+{
+public:
+ explicit FpsLabelAction(QObject *parent = nullptr);
+ static void fpsHandler(quint16 fpsValues[8]);
+ static void cleanFpsCounter();
+protected:
+ QWidget *createWidget(QWidget *parent) override;
+private:
+ static void refreshFpsLabel(quint16 frames);
+ static QPointer<QLabel> m_labelInstance;
+ static QList<QPointer<QLabel>> fpsHandlerLabelList;
+ static quint16 lastValidFrames;
+};
+
+class FpsAction : public ActionInterface
+{
+public:
+ FpsAction();
+ QAction *action() const override;
+ QByteArray category() const override;
+ QByteArray menuId() const override;
+ int priority() const override;
+ Type type() const override;
+ void currentContextChanged(const SelectionContext &) override;
+private:
+ std::unique_ptr<FpsLabelAction> m_fpsLabelAction;
+};
+
+class SwitchLanguageComboboxAction : public QWidgetAction
+{
+ Q_OBJECT
+public:
+ explicit SwitchLanguageComboboxAction(QObject *parent = nullptr);
+signals:
+ void currentLocaleChanged(const QString& string);
+protected:
+ QWidget *createWidget(QWidget *parent) override;
+private:
+ void refreshProjectLocales(ProjectExplorer::Project *project);
+ QStringList m_localeStrings;
+};
+
+class SwitchLanguageAction : public ActionInterface
+{
+public:
+ SwitchLanguageAction();
+ QAction *action() const override;
+ QByteArray category() const override;
+ QByteArray menuId() const override;
+ int priority() const override;
+ Type type() const override;
+ void currentContextChanged(const SelectionContext &) override;
+private:
+ std::unique_ptr<SwitchLanguageComboboxAction> m_switchLanguageAction;
+};
+
+} // namespace QmlDesigner
+Q_DECLARE_METATYPE(QmlPreview::QmlPreviewFpsHandler);
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp
new file mode 100644
index 0000000000..5a3c1c4e09
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** 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 "qmlpreviewplugin.h"
+#include "qmlpreviewactions.h"
+
+#include <modelnodecontextmenu_helper.h>
+#include <componentcore_constants.h>
+#include <qmldesignerplugin.h>
+#include <viewmanager.h>
+#include <actioninterface.h>
+#include <zoomaction.h>
+
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/pluginspec.h>
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
+
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
+
+namespace QmlPreview {
+using QmlPreviewRunControlList = QList<ProjectExplorer::RunControl *>;
+}
+
+Q_DECLARE_METATYPE(QmlPreview::QmlPreviewRunControlList)
+
+namespace QmlDesigner {
+static QObject *s_previewPlugin = nullptr;
+
+QmlPreviewPlugin::QmlPreviewPlugin()
+{
+ DesignerActionManager &designerActionManager =
+ QmlDesignerPlugin::instance()->designerActionManager();
+ auto previewAction = new QmlPreviewAction();
+ designerActionManager.addDesignerAction(new ActionGroup(
+ QString(),
+ ComponentCoreConstants::qmlPreviewCategory,
+ ComponentCoreConstants::priorityQmlPreviewCategory,
+ &SelectionContextFunctors::always));
+ s_previewPlugin = getPreviewPlugin();
+
+ if (s_previewPlugin) {
+ bool connected = connect(s_previewPlugin, SIGNAL(runningPreviewsChanged(const QmlPreviewRunControlList &)),
+ this, SLOT(handleRunningPreviews()));
+ QTC_ASSERT(connected, qWarning() << "something wrong with the runningPreviewsChanged signal");
+ }
+
+ designerActionManager.addDesignerAction(previewAction);
+
+ auto zoomAction = new ZoomPreviewAction;
+ designerActionManager.addDesignerAction(zoomAction);
+
+ auto separator = new SeperatorDesignerAction(ComponentCoreConstants::qmlPreviewCategory, 0);
+ designerActionManager.addDesignerAction(separator);
+
+ m_previewToggleAction = previewAction->defaultAction();
+
+ if (s_previewPlugin) {
+ auto fpsAction = new FpsAction;
+ designerActionManager.addDesignerAction(fpsAction);
+ s_previewPlugin->setProperty("fpsHandler", QVariant::fromValue<QmlPreview::QmlPreviewFpsHandler>(FpsLabelAction::fpsHandler));
+ auto switchLanguageAction = new SwitchLanguageAction;
+ designerActionManager.addDesignerAction(switchLanguageAction);
+ }
+}
+
+QString QmlPreviewPlugin::pluginName() const
+{
+ return QLatin1String("QmlPreviewPlugin");
+}
+
+void QmlPreviewPlugin::stopAllRunControls()
+{
+ QTC_ASSERT(s_previewPlugin, return);
+
+ const QVariant variant = s_previewPlugin->property("runningPreviews");
+ auto runControls = variant.value<QmlPreview::QmlPreviewRunControlList>();
+
+ for (ProjectExplorer::RunControl *runControl : runControls)
+ runControl->initiateStop();
+
+}
+
+void QmlPreviewPlugin::handleRunningPreviews()
+{
+ QTC_ASSERT(s_previewPlugin, return);
+
+ const QVariant variant = s_previewPlugin->property("runningPreviews");
+ if (variant.isValid()) {
+ // the QmlPreview::QmlPreviewRunControlList type have to be available and used in the qmlpreview plugin
+ QTC_ASSERT(variant.canConvert<QmlPreview::QmlPreviewRunControlList>(), return);
+ auto runControls = variant.value<QmlPreview::QmlPreviewRunControlList>();
+ m_previewToggleAction->setChecked(!runControls.isEmpty());
+ if (runControls.isEmpty())
+ FpsLabelAction::cleanFpsCounter();
+ }
+}
+
+QString QmlPreviewPlugin::metaInfo() const
+{
+ return QLatin1String(":/qmlpreviewplugin/qmlpreview.metainfo");
+}
+
+void QmlPreviewPlugin::setQmlFile()
+{
+ if (s_previewPlugin) {
+ const Utils::FileName qmlFileName =
+ QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
+ s_previewPlugin->setProperty("previewedFile", qmlFileName.toString());
+ }
+}
+
+float QmlPreviewPlugin::zoomFactor()
+{
+ QVariant zoomFactorVariant = 1.0;
+ if (s_previewPlugin && !s_previewPlugin->property("zoomFactor").isNull())
+ zoomFactorVariant = s_previewPlugin->property("zoomFactor");
+ return zoomFactorVariant.toFloat();
+}
+
+void QmlPreviewPlugin::setZoomFactor(float zoomFactor)
+{
+ if (s_previewPlugin)
+ s_previewPlugin->setProperty("zoomFactor", zoomFactor);
+}
+
+void QmlPreviewPlugin::setLanguageLocale(const QString &locale)
+{
+ if (s_previewPlugin)
+ s_previewPlugin->setProperty("locale", locale);
+}
+
+QObject *QmlPreviewPlugin::getPreviewPlugin()
+{
+ auto pluginIt = std::find_if(ExtensionSystem::PluginManager::plugins().begin(),
+ ExtensionSystem::PluginManager::plugins().end(),
+ [](const ExtensionSystem::PluginSpec *p) {
+ return p->name() == "QmlPreview";
+ });
+
+ if (pluginIt != ExtensionSystem::PluginManager::plugins().constEnd())
+ return (*pluginIt)->plugin();
+
+ return nullptr;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h
new file mode 100644
index 0000000000..7f50d76696
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 <iwidgetplugin.h>
+
+#include <QMetaType>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+namespace QmlDesigner {
+
+class QmlPreviewPlugin : public QObject, QmlDesigner::IWidgetPlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QmlDesignerPlugin" FILE "qmlpreviewplugin.json")
+
+ Q_DISABLE_COPY(QmlPreviewPlugin)
+ Q_INTERFACES(QmlDesigner::IWidgetPlugin)
+
+public:
+ QmlPreviewPlugin();
+ ~QmlPreviewPlugin() override = default;
+
+ QString metaInfo() const override;
+ QString pluginName() const override;
+
+ static void stopAllRunControls();
+ static void setQmlFile();
+ static QObject *getPreviewPlugin();
+
+ static float zoomFactor();
+ static void setZoomFactor(float zoomFactor);
+ static void setLanguageLocale(const QString &locale);
+signals:
+ void fpsChanged(quint16 frames);
+
+private slots:
+ void handleRunningPreviews();
+
+private:
+ QAction *m_previewToggleAction = nullptr;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json
new file mode 100644
index 0000000000..72a2c27087
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.json
@@ -0,0 +1,6 @@
+{
+ "Vendor" : "The Qt Company Ltd",
+ "Category" : "Qt Quick",
+ "Description" : "Plugin for integrating QmlPreview into QmlDesigner",
+ "Url" : "http://www.qt.io"
+}
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri
new file mode 100644
index 0000000000..1808b69266
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pri
@@ -0,0 +1,10 @@
+QT *= qml quick core
+
+VPATH += $$PWD
+
+SOURCES += qmlpreviewplugin.cpp
+HEADERS += qmlpreviewplugin.h
+SOURCES += qmlpreviewactions.cpp
+HEADERS += qmlpreviewactions.h
+
+RESOURCES += qmlpreviewplugin.qrc
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro
new file mode 100644
index 0000000000..ec8c9b1d63
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.pro
@@ -0,0 +1,18 @@
+TARGET = qmlpreviewplugin
+TEMPLATE = lib
+CONFIG += plugin
+
+include(../../../../qtcreator.pri)\
+
+include (../designercore/iwidgetplugin.pri)
+include (../qmldesigner_dependencies.pri)
+
+LIBS += -L$$IDE_PLUGIN_PATH
+LIBS += -l$$qtLibraryName(QmlDesigner)
+LIBS += -l$$qtLibraryName(ExtensionSystem)
+LIBS += -l$$qtLibraryName(Core)
+LIBS += -l$$qtLibraryName(ProjectExplorer)
+LIBS += -l$$qtLibraryName(Utils)
+
+include(qmlpreviewplugin.pri)
+include(../plugindestdir.pri)
diff --git a/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc
new file mode 100644
index 0000000000..3f8cc2a077
--- /dev/null
+++ b/src/plugins/qmldesigner/qmlpreviewplugin/qmlpreviewplugin.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/qmlpreviewplugin">
+ <file>qmlpreview.metainfo</file>
+ <file>images/live_preview.png</file>
+ <file>images/live_preview@2x.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp
index c3936edf5b..4100d451ee 100644
--- a/src/plugins/qmldesigner/shortcutmanager.cpp
+++ b/src/plugins/qmldesigner/shortcutmanager.cpp
@@ -159,7 +159,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
//Close All
Core::ActionManager::registerAction(&m_closeAllEditorsAction, Core::Constants::CLOSEALL, qmlDesignerMainContext);
- connect(&m_closeAllEditorsAction, &QAction::triggered, em, &Core::EditorManager::closeAllEditors);
+ connect(&m_closeAllEditorsAction, &QAction::triggered, em, &Core::EditorManager::closeAllDocuments);
//Close All Others Action
Core::ActionManager::registerAction(&m_closeOtherEditorsAction, Core::Constants::CLOSEOTHERS, qmlDesignerMainContext);
diff --git a/src/plugins/qmljseditor/CMakeLists.txt b/src/plugins/qmljseditor/CMakeLists.txt
new file mode 100644
index 0000000000..c931d1729d
--- /dev/null
+++ b/src/plugins/qmljseditor/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_qtc_plugin(QmlJSEditor
+ DEPENDS LanguageUtils qmljs QmlEditorWidgets
+ PLUGIN_DEPENDS Core ProjectExplorer QmlJSTools TextEditor
+ SOURCES
+ qmlexpressionundercursor.cpp qmlexpressionundercursor.h
+ qmljsautocompleter.cpp qmljsautocompleter.h
+ qmljscompletionassist.cpp qmljscompletionassist.h
+ qmljscomponentfromobjectdef.cpp qmljscomponentfromobjectdef.h
+ qmljscomponentnamedialog.cpp qmljscomponentnamedialog.h qmljscomponentnamedialog.ui
+ qmljseditingsettingspage.cpp qmljseditingsettingspage.h qmljseditingsettingspage.ui
+ qmljseditor.cpp qmljseditor.h
+ qmljseditor_global.h
+ qmljseditorconstants.h
+ qmljseditordocument.cpp qmljseditordocument.h qmljseditordocument_p.h
+ qmljseditorplugin.cpp qmljseditorplugin.h
+ qmljsfindreferences.cpp qmljsfindreferences.h
+ qmljshighlighter.cpp qmljshighlighter.h
+ qmljshoverhandler.cpp qmljshoverhandler.h
+ qmljsoutline.cpp qmljsoutline.h
+ qmljsoutlinetreeview.cpp qmljsoutlinetreeview.h
+ qmljsquickfix.cpp qmljsquickfix.h
+ qmljsquickfixassist.cpp qmljsquickfixassist.h
+ qmljsquickfixes.cpp
+ qmljsreuse.cpp qmljsreuse.h
+ qmljssemantichighlighter.cpp qmljssemantichighlighter.h
+ qmljssemanticinfoupdater.cpp qmljssemanticinfoupdater.h
+ qmljstextmark.cpp qmljstextmark.h
+ qmljswrapinloader.cpp qmljswrapinloader.h
+ qmloutlinemodel.cpp qmloutlinemodel.h
+ qmltaskmanager.cpp qmltaskmanager.h
+ quicktoolbar.cpp quicktoolbar.h
+ EXPLICIT_MOC qmljseditor.h
+)
diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp
index b307cb59ab..a581a2a2f3 100644
--- a/src/plugins/qmljseditor/qmljscompletionassist.cpp
+++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "qmljscompletionassist.h"
+#include "qmljseditor.h"
#include "qmljseditorconstants.h"
#include "qmljsreuse.h"
#include "qmlexpressionundercursor.h"
diff --git a/src/plugins/qmljseditor/qmljscompletionassist.h b/src/plugins/qmljseditor/qmljscompletionassist.h
index c737587f88..df697ef5e1 100644
--- a/src/plugins/qmljseditor/qmljscompletionassist.h
+++ b/src/plugins/qmljseditor/qmljscompletionassist.h
@@ -25,8 +25,9 @@
#pragma once
-#include "qmljseditor.h"
+#include "qmljseditor_global.h"
+#include <qmljstools/qmljssemanticinfo.h>
#include <texteditor/codeassist/assistproposalitem.h>
#include <texteditor/codeassist/genericproposalmodel.h>
#include <texteditor/codeassist/completionassistprovider.h>
diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
index a88d615082..3afca0b036 100644
--- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
+++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
@@ -192,7 +192,7 @@ public:
if (path == QFileInfo(currentFileName).path()) {
// hack for the common case, next version should use the wizard
ProjectExplorer::Node * oldFileNode =
- ProjectExplorer::ProjectTree::nodeForFile(Utils::FileName::fromString(currentFileName));
+ ProjectExplorer::ProjectTree::nodeForFile(Utils::FilePath::fromString(currentFileName));
if (oldFileNode) {
ProjectExplorer::FolderNode *containingFolder = oldFileNode->parentFolderNode();
if (containingFolder)
diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h
index e61b992996..1d6dc4cdc4 100644
--- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h
+++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h
@@ -25,6 +25,7 @@
#pragma once
+#include "qmljseditor_global.h"
#include "qmljsquickfix.h"
namespace QmlJSEditor {
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 458cb55b6e..61576372ea 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -119,7 +119,7 @@ void QmlJSEditorWidget::finalizeInitialization()
m_updateUsesTimer.setSingleShot(true);
connect(&m_updateUsesTimer, &QTimer::timeout, this, &QmlJSEditorWidget::updateUses);
connect(this, &QPlainTextEdit::cursorPositionChanged,
- &m_updateUsesTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ &m_updateUsesTimer, QOverload<>::of(&QTimer::start));
m_updateOutlineIndexTimer.setInterval(UPDATE_OUTLINE_INTERVAL);
m_updateOutlineIndexTimer.setSingleShot(true);
@@ -138,7 +138,7 @@ void QmlJSEditorWidget::finalizeInitialization()
connect(&m_contextPaneTimer, &QTimer::timeout, this, &QmlJSEditorWidget::updateContextPane);
if (m_contextPane) {
connect(this, &QmlJSEditorWidget::cursorPositionChanged,
- &m_contextPaneTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ &m_contextPaneTimer, QOverload<>::of(&QTimer::start));
connect(m_contextPane, &IContextPane::closed, this, &QmlJSEditorWidget::showTextMarker);
}
@@ -520,13 +520,13 @@ void QmlJSEditorWidget::createToolBar()
policy.setHorizontalPolicy(QSizePolicy::Expanding);
m_outlineCombo->setSizePolicy(policy);
- connect(m_outlineCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_outlineCombo, QOverload<int>::of(&QComboBox::activated),
this, &QmlJSEditorWidget::jumpToOutlineElement);
connect(m_qmlJsEditorDocument->outlineModel(), &QmlOutlineModel::updated,
static_cast<QTreeView *>(m_outlineCombo->view()), &QTreeView::expandAll);
connect(this, &QmlJSEditorWidget::cursorPositionChanged,
- &m_updateOutlineIndexTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ &m_updateOutlineIndexTimer, QOverload<>::of(&QTimer::start));
insertExtraToolBarWidget(TextEditorWidget::Left, m_outlineCombo);
}
diff --git a/src/plugins/qmljseditor/qmljseditordocument.cpp b/src/plugins/qmljseditor/qmljseditordocument.cpp
index 2f30f324cb..18348907f4 100644
--- a/src/plugins/qmljseditor/qmljseditordocument.cpp
+++ b/src/plugins/qmljseditor/qmljseditordocument.cpp
@@ -459,7 +459,7 @@ QmlJSEditorDocumentPrivate::QmlJSEditorDocumentPrivate(QmlJSEditorDocument *pare
m_updateDocumentTimer.setInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL);
m_updateDocumentTimer.setSingleShot(true);
connect(q->document(), &QTextDocument::contentsChanged,
- &m_updateDocumentTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ &m_updateDocumentTimer, QOverload<>::of(&QTimer::start));
connect(&m_updateDocumentTimer, &QTimer::timeout,
this, &QmlJSEditorDocumentPrivate::reparseDocument);
connect(modelManager, &ModelManagerInterface::documentUpdated,
@@ -477,7 +477,7 @@ QmlJSEditorDocumentPrivate::QmlJSEditorDocumentPrivate(QmlJSEditorDocument *pare
connect(&m_reupdateSemanticInfoTimer, &QTimer::timeout,
this, &QmlJSEditorDocumentPrivate::reupdateSemanticInfo);
connect(modelManager, &ModelManagerInterface::libraryInfoUpdated,
- &m_reupdateSemanticInfoTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ &m_reupdateSemanticInfoTimer, QOverload<>::of(&QTimer::start));
// outline model
m_updateOutlineModelTimer.setInterval(UPDATE_OUTLINE_INTERVAL);
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index 6479ba13ad..9cea65e3ef 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -43,9 +43,9 @@
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/parser/qmljsastfwd_p.h>
#include <qmljs/qmljsutils.h>
-#include <qmljs/qmljsqrcparser.h>
#include <texteditor/texteditor.h>
#include <utils/executeondestruction.h>
+#include <utils/qrcparser.h>
#include <utils/tooltip/tooltip.h>
#include <QDir>
@@ -133,7 +133,7 @@ static inline QString getModuleName(const ScopeChain &scopeChain, const Document
const QString name = relativeDir.replace(QLatin1Char('/'), QLatin1Char('.'));
return name;
} else if (importInfo.isValid() && importInfo.type() == ImportType::QrcDirectory) {
- QString path = QrcParser::normalizedQrcDirectoryPath(importInfo.path());
+ QString path = Utils::QrcParser::normalizedQrcDirectoryPath(importInfo.path());
path = path.mid(1, path.size() - ((path.size() > 1) ? 2 : 1));
const QString name = path.replace(QLatin1Char('/'), QLatin1Char('.'));
return name;
diff --git a/src/plugins/qmljseditor/qmljsoutline.cpp b/src/plugins/qmljseditor/qmljsoutline.cpp
index 228839573b..0eb0d40161 100644
--- a/src/plugins/qmljseditor/qmljsoutline.cpp
+++ b/src/plugins/qmljseditor/qmljsoutline.cpp
@@ -47,7 +47,6 @@ enum {
namespace QmlJSEditor {
namespace Internal {
-
QmlJSOutlineFilterModel::QmlJSOutlineFilterModel(QObject *parent) :
QSortFilterProxyModel(parent)
{
diff --git a/src/plugins/qmljseditor/qmljsoutline.h b/src/plugins/qmljseditor/qmljsoutline.h
index 0a50667ae2..1e4b1d20d1 100644
--- a/src/plugins/qmljseditor/qmljsoutline.h
+++ b/src/plugins/qmljseditor/qmljsoutline.h
@@ -25,8 +25,6 @@
#pragma once
-#include "qmljseditor.h"
-
#include <texteditor/ioutlinewidget.h>
#include <QSortFilterProxyModel>
@@ -42,6 +40,7 @@ namespace QmlJS { class Editor; }
namespace QmlJSEditor {
namespace Internal {
+class QmlJSEditorWidget;
class QmlJSOutlineTreeView;
class QmlJSOutlineFilterModel : public QSortFilterProxyModel
diff --git a/src/plugins/qmljseditor/qmljsquickfix.h b/src/plugins/qmljseditor/qmljsquickfix.h
index 856b4f29c8..37d4c134b6 100644
--- a/src/plugins/qmljseditor/qmljsquickfix.h
+++ b/src/plugins/qmljseditor/qmljsquickfix.h
@@ -25,8 +25,6 @@
#pragma once
-#include "qmljseditor.h"
-
#include <texteditor/quickfix.h>
#include <qmljs/parser/qmljsastfwd_p.h>
#include <qmljs/qmljsdocument.h>
diff --git a/src/plugins/qmljseditor/qmljsquickfixassist.cpp b/src/plugins/qmljseditor/qmljsquickfixassist.cpp
index 21b44faaa5..37efbaf39c 100644
--- a/src/plugins/qmljseditor/qmljsquickfixassist.cpp
+++ b/src/plugins/qmljseditor/qmljsquickfixassist.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "qmljsquickfixassist.h"
+#include "qmljseditor.h"
#include "qmljseditorconstants.h"
#include "qmljseditordocument.h"
diff --git a/src/plugins/qmljseditor/qmljsquickfixassist.h b/src/plugins/qmljseditor/qmljsquickfixassist.h
index f638465d4b..83d328fc80 100644
--- a/src/plugins/qmljseditor/qmljsquickfixassist.h
+++ b/src/plugins/qmljseditor/qmljsquickfixassist.h
@@ -25,9 +25,8 @@
#pragma once
-#include "qmljseditor.h"
-
#include <qmljstools/qmljsrefactoringchanges.h>
+#include <qmljstools/qmljssemanticinfo.h>
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/iassistprovider.h>
@@ -35,6 +34,8 @@
namespace QmlJSEditor {
namespace Internal {
+class QmlJSEditorWidget;
+
class QmlJSQuickFixAssistInterface : public TextEditor::AssistInterface
{
public:
diff --git a/src/plugins/qmljseditor/qmljssemanticinfoupdater.h b/src/plugins/qmljseditor/qmljssemanticinfoupdater.h
index 85a3fce29f..bfd32596fb 100644
--- a/src/plugins/qmljseditor/qmljssemanticinfoupdater.h
+++ b/src/plugins/qmljseditor/qmljssemanticinfoupdater.h
@@ -25,7 +25,8 @@
#pragma once
-#include "qmljseditor.h"
+#include <qmljs/qmljsdocument.h>
+#include <qmljstools/qmljssemanticinfo.h>
#include <QWaitCondition>
#include <QModelIndex>
diff --git a/src/plugins/qmljseditor/qmljstextmark.cpp b/src/plugins/qmljseditor/qmljstextmark.cpp
index 7c427a4d00..4ef80eb7a2 100644
--- a/src/plugins/qmljseditor/qmljstextmark.cpp
+++ b/src/plugins/qmljseditor/qmljstextmark.cpp
@@ -59,7 +59,7 @@ static Core::Id cartegoryForSeverity(QmlJS::Severity::Enum kind)
return isWarning(kind) ? QMLJS_WARNING : QMLJS_ERROR;
}
-QmlJSTextMark::QmlJSTextMark(const FileName &fileName,
+QmlJSTextMark::QmlJSTextMark(const FilePath &fileName,
const QmlJS::DiagnosticMessage &diagnostic,
const QmlJSTextMark::RemovedFromEditorHandler &removedHandler)
: TextEditor::TextMark(fileName, int(diagnostic.loc.startLine),
@@ -70,7 +70,7 @@ QmlJSTextMark::QmlJSTextMark(const FileName &fileName,
init(isWarning(diagnostic.kind), diagnostic.message);
}
-QmlJSTextMark::QmlJSTextMark(const FileName &fileName,
+QmlJSTextMark::QmlJSTextMark(const FilePath &fileName,
const QmlJS::StaticAnalysis::Message &message,
const QmlJSTextMark::RemovedFromEditorHandler &removedHandler)
: TextEditor::TextMark(fileName, int(message.location.startLine),
diff --git a/src/plugins/qmljseditor/qmljstextmark.h b/src/plugins/qmljseditor/qmljstextmark.h
index e9bc567451..7034838e66 100644
--- a/src/plugins/qmljseditor/qmljstextmark.h
+++ b/src/plugins/qmljseditor/qmljstextmark.h
@@ -38,10 +38,10 @@ class QmlJSTextMark : public TextEditor::TextMark
public:
using RemovedFromEditorHandler = std::function<void(QmlJSTextMark *)>;
- QmlJSTextMark(const Utils::FileName &fileName,
+ QmlJSTextMark(const Utils::FilePath &fileName,
const QmlJS::DiagnosticMessage &diagnostic,
const RemovedFromEditorHandler &removedHandler);
- QmlJSTextMark(const Utils::FileName &fileName,
+ QmlJSTextMark(const Utils::FilePath &fileName,
const QmlJS::StaticAnalysis::Message &message,
const RemovedFromEditorHandler &removedHandler);
diff --git a/src/plugins/qmljseditor/qmltaskmanager.cpp b/src/plugins/qmljseditor/qmltaskmanager.cpp
index 0a20b7569f..c9b5b83b24 100644
--- a/src/plugins/qmljseditor/qmltaskmanager.cpp
+++ b/src/plugins/qmljseditor/qmltaskmanager.cpp
@@ -60,9 +60,9 @@ QmlTaskManager::QmlTaskManager()
connect(&m_updateDelay, &QTimer::timeout, this, [this] { updateMessagesNow(); });
}
-static QList<Task> convertToTasks(const QList<DiagnosticMessage> &messages, const FileName &fileName, Core::Id category)
+static Tasks convertToTasks(const QList<DiagnosticMessage> &messages, const FilePath &fileName, Core::Id category)
{
- QList<Task> result;
+ Tasks result;
foreach (const DiagnosticMessage &msg, messages) {
Task::TaskType type = msg.isError() ? Task::Error : Task::Warning;
Task task(type, msg.message, fileName, msg.loc.startLine, category);
@@ -71,7 +71,7 @@ static QList<Task> convertToTasks(const QList<DiagnosticMessage> &messages, cons
return result;
}
-static QList<Task> convertToTasks(const QList<StaticAnalysis::Message> &messages, const FileName &fileName, Core::Id category)
+static Tasks convertToTasks(const QList<StaticAnalysis::Message> &messages, const FilePath &fileName, Core::Id category)
{
QList<DiagnosticMessage> diagnostics;
foreach (const StaticAnalysis::Message &msg, messages)
@@ -101,17 +101,17 @@ void QmlTaskManager::collectMessages(
result.fileName = fileName;
if (document->language().isFullySupportedLanguage()) {
result.tasks = convertToTasks(document->diagnosticMessages(),
- FileName::fromString(fileName),
+ FilePath::fromString(fileName),
Constants::TASK_CATEGORY_QML);
if (updateSemantic) {
result.tasks += convertToTasks(linkMessages.value(fileName),
- FileName::fromString(fileName),
+ FilePath::fromString(fileName),
Constants::TASK_CATEGORY_QML_ANALYSIS);
Check checker(document, context);
result.tasks += convertToTasks(checker(),
- FileName::fromString(fileName),
+ FilePath::fromString(fileName),
Constants::TASK_CATEGORY_QML_ANALYSIS);
}
}
@@ -179,7 +179,7 @@ void QmlTaskManager::displayAllResults()
void QmlTaskManager::insertTask(const Task &task)
{
- QList<Task> tasks = m_docsWithTasks.value(task.file.toString());
+ Tasks tasks = m_docsWithTasks.value(task.file.toString());
tasks.append(task);
m_docsWithTasks.insert(task.file.toString(), tasks);
TaskHub::addTask(task);
@@ -188,7 +188,7 @@ void QmlTaskManager::insertTask(const Task &task)
void QmlTaskManager::removeTasksForFile(const QString &fileName)
{
if (m_docsWithTasks.contains(fileName)) {
- const QList<Task> tasks = m_docsWithTasks.value(fileName);
+ const Tasks tasks = m_docsWithTasks.value(fileName);
foreach (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 646aed7a22..dfc8174ba1 100644
--- a/src/plugins/qmljseditor/qmltaskmanager.h
+++ b/src/plugins/qmljseditor/qmltaskmanager.h
@@ -65,7 +65,7 @@ private:
{
public:
QString fileName;
- QList<ProjectExplorer::Task> tasks;
+ ProjectExplorer::Tasks tasks;
};
static void collectMessages(QFutureInterface<FileErrorMessages> &future,
QmlJS::Snapshot snapshot,
@@ -74,7 +74,7 @@ private:
bool updateSemantic);
private:
- QHash<QString, QList<ProjectExplorer::Task> > m_docsWithTasks;
+ QHash<QString, ProjectExplorer::Tasks > m_docsWithTasks;
QFutureWatcher<FileErrorMessages> m_messageCollector;
QTimer m_updateDelay;
bool m_updatingSemantic = false;
diff --git a/src/plugins/qmljstools/CMakeLists.txt b/src/plugins/qmljstools/CMakeLists.txt
new file mode 100644
index 0000000000..bdfcb519ff
--- /dev/null
+++ b/src/plugins/qmljstools/CMakeLists.txt
@@ -0,0 +1,26 @@
+add_qtc_plugin(QmlJSTools
+ DEPENDS LanguageUtils
+ PUBLIC_DEPENDS qmljs
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer QtSupport TextEditor
+ SOURCES
+ qmljsbundleprovider.cpp qmljsbundleprovider.h
+ qmljscodestylepreferencesfactory.cpp qmljscodestylepreferencesfactory.h
+ qmljscodestylesettingspage.cpp qmljscodestylesettingspage.h qmljscodestylesettingspage.ui
+ qmljsfunctionfilter.cpp qmljsfunctionfilter.h
+ qmljsindenter.cpp qmljsindenter.h
+ qmljslocatordata.cpp qmljslocatordata.h
+ qmljsmodelmanager.cpp qmljsmodelmanager.h
+ qmljsqtstylecodeformatter.cpp qmljsqtstylecodeformatter.h
+ qmljsrefactoringchanges.cpp qmljsrefactoringchanges.h
+ qmljssemanticinfo.cpp qmljssemanticinfo.h
+ qmljstools.qrc
+ qmljstools_global.h
+ qmljstoolsconstants.h
+ qmljstoolsplugin.cpp qmljstoolsplugin.h
+ qmljstoolssettings.cpp qmljstoolssettings.h
+)
+
+extend_qtc_plugin(QmlJSTools
+ CONDITION WITH_TESTS
+ SOURCES qmljstools_test.cpp
+)
diff --git a/src/plugins/qmljstools/qmljsbundleprovider.cpp b/src/plugins/qmljstools/qmljsbundleprovider.cpp
index 7fb0a03a26..176d66b33d 100644
--- a/src/plugins/qmljstools/qmljsbundleprovider.cpp
+++ b/src/plugins/qmljstools/qmljsbundleprovider.cpp
@@ -98,7 +98,7 @@ void BasicBundleProvider::mergeBundlesForKit(ProjectExplorer::Kit *kit
bundles.mergeBundleForLanguage(Dialect::QmlTypeInfo, defaultQmltypesBundle());
bundles.mergeBundleForLanguage(Dialect::QmlProject, defaultQmlprojectBundle());
- QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit);
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
if (!qtVersion) {
QmlBundle b2(defaultQt5QtQuick2Bundle());
bundles.mergeBundleForLanguage(Dialect::Qml, b2);
diff --git a/src/plugins/qmljstools/qmljsfunctionfilter.cpp b/src/plugins/qmljstools/qmljsfunctionfilter.cpp
index e13dd041d4..324f4f7559 100644
--- a/src/plugins/qmljstools/qmljsfunctionfilter.cpp
+++ b/src/plugins/qmljstools/qmljsfunctionfilter.cpp
@@ -79,7 +79,7 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
const QRegularExpressionMatch match = regexp.match(info.symbolName);
if (match.hasMatch()) {
- QVariant id = qVariantFromValue(info);
+ QVariant id = QVariant::fromValue(info);
Core::LocatorFilterEntry filterEntry(this, info.displayName, id/*, info.icon*/);
filterEntry.extraInfo = info.extraInfo;
filterEntry.highlightInfo = highlightInfo(match);
diff --git a/src/plugins/qmljstools/qmljsinterpreter.cpp b/src/plugins/qmljstools/qmljsinterpreter.cpp
deleted file mode 100644
index a8e855a532..0000000000
--- a/src/plugins/qmljstools/qmljsinterpreter.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 "qmljsinterpreter.h"
-
-namespace QmlJSTools {
-namespace Internal {
-
-bool QmlJSInterpreter::canEvaluate(QString code)
-{
- int yyaction = 0;
- int yytoken = -1;
- int yytos = -1;
-
- setCode(code, 1);
- m_tokens.append(T_FEED_JS_PROGRAM);
-
- do {
- if (++yytos == m_stateStack.size())
- m_stateStack.resize(m_stateStack.size() * 2);
-
- m_stateStack[yytos] = yyaction;
-
-again:
- if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT) {
- if (m_tokens.isEmpty())
- yytoken = lex();
- else
- yytoken = m_tokens.takeFirst();
- }
-
- yyaction = t_action(yyaction, yytoken);
- if (yyaction > 0) {
- if (yyaction == ACCEPT_STATE) {
- --yytos;
- return true;
- }
- yytoken = -1;
- } else if (yyaction < 0) {
- const int ruleno = -yyaction - 1;
- yytos -= rhs[ruleno];
- yyaction = nt_action(m_stateStack[yytos], lhs[ruleno] - TERMINAL_COUNT);
- }
- } while (yyaction);
-
- const int errorState = m_stateStack[yytos];
- if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && canInsertAutomaticSemicolon(yytoken)) {
- yyaction = errorState;
- m_tokens.prepend(yytoken);
- yytoken = T_SEMICOLON;
- goto again;
- }
-
- if (yytoken != EOF_SYMBOL)
- return true;
-
- return false;
-}
-
-} // namespace Internal
-} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljsinterpreter.h b/src/plugins/qmljstools/qmljsinterpreter.h
deleted file mode 100644
index b3d1f8c717..0000000000
--- a/src/plugins/qmljstools/qmljsinterpreter.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 <qmljs/parser/qmljslexer_p.h>
-#include <qmljs/parser/qmljsengine_p.h>
-
-#include <QVector>
-#include <QString>
-#include <QList>
-
-namespace QmlJSTools {
-namespace Internal {
-
-class QmlJSInterpreter: QmlJS::Lexer
-{
-public:
- QmlJSInterpreter()
- : Lexer(&m_engine),
- m_stateStack(128)
- {
- }
-
- bool canEvaluate(QString code);
-
-private:
- QmlJS::Engine m_engine;
- QVector<int> m_stateStack;
- QList<int> m_tokens;
-};
-
-} // namespace Internal
-} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljslocatordata.cpp b/src/plugins/qmljstools/qmljslocatordata.cpp
index 01725f1d9f..3b68bf6521 100644
--- a/src/plugins/qmljstools/qmljslocatordata.cpp
+++ b/src/plugins/qmljstools/qmljslocatordata.cpp
@@ -48,7 +48,7 @@ LocatorData::LocatorData()
connect(manager, &ModelManagerInterface::projectInfoUpdated,
[manager](const ModelManagerInterface::ProjectInfo &info) {
QStringList files;
- for (const Utils::FileName &f: info.project->files(ProjectExplorer::Project::SourceFiles))
+ for (const Utils::FilePath &f: info.project->files(ProjectExplorer::Project::SourceFiles))
files << f.toString();
manager->updateSourceFiles(files, true);
});
@@ -82,7 +82,7 @@ public:
if (!doc->componentName().isEmpty())
m_documentContext = doc->componentName();
else
- m_documentContext = Utils::FileName::fromString(doc->fileName()).fileName();
+ m_documentContext = Utils::FilePath::fromString(doc->fileName()).fileName();
accept(doc->ast(), m_documentContext);
return m_entries;
}
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index d328886f9e..2d996f4985 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -94,11 +94,11 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
return fn && fn->fileType() == FileType::QML
&& qmlTypeNames.contains(Utils::mimeTypeForFile(fn->filePath().toString(),
MimeMatchMode::MatchExtension).name());
- }), &FileName::toString);
+ }), &FilePath::toString);
activeTarget = project->activeTarget();
}
Kit *activeKit = activeTarget ? activeTarget->kit() : KitManager::defaultKit();
- QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(activeKit);
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(activeKit);
bool preferDebugDump = false;
bool setPreferDump = false;
@@ -168,7 +168,6 @@ void setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &projectInfo)
namespace Internal {
-
QHash<QString,Dialect> ModelManager::initLanguageForSuffix() const
{
QHash<QString,Dialect> res = ModelManagerInterface::languageForSuffix();
diff --git a/src/plugins/qmlpreview/CMakeLists.txt b/src/plugins/qmlpreview/CMakeLists.txt
new file mode 100644
index 0000000000..1788cb3847
--- /dev/null
+++ b/src/plugins/qmlpreview/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_qtc_plugin(QmlPreview
+ DEPENDS QmlDebug qmljs
+ PLUGIN_DEPENDS Core ProjectExplorer QmlJSTools QtSupport ResourceEditor
+ SOURCES
+ qmlpreviewclient.cpp qmlpreviewclient.h
+ qmlpreviewconnectionmanager.cpp qmlpreviewconnectionmanager.h
+ qmlpreviewfileontargetfinder.cpp qmlpreviewfileontargetfinder.h
+ qmlpreviewplugin.cpp qmlpreviewplugin.h
+ qmlpreviewruncontrol.cpp qmlpreviewruncontrol.h
+ qmlpreview_global.h
+)
+
+extend_qtc_plugin(QmlPreview
+ CONDITION WITH_TESTS
+ SOURCES
+ tests/qmlpreviewclient_test.cpp tests/qmlpreviewclient_test.h
+ tests/qmlpreviewplugin_test.cpp tests/qmlpreviewplugin_test.h
+)
diff --git a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp
index ad9c6467b6..af67b55f1c 100644
--- a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp
@@ -49,7 +49,7 @@ QmlPreviewConnectionManager::QmlPreviewConnectionManager(QObject *parent) :
void QmlPreviewConnectionManager::setTarget(ProjectExplorer::Target *target)
{
QtSupport::BaseQtVersion::populateQmlFileFinder(&m_projectFileFinder, target);
- m_projectFileFinder.setAdditionalSearchDirectories(Utils::FileNameList());
+ m_projectFileFinder.setAdditionalSearchDirectories(Utils::FilePathList());
m_targetFileFinder.setTarget(target);
}
diff --git a/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp b/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp
index 95ed107fea..02b8161ed2 100644
--- a/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewfileontargetfinder.cpp
@@ -72,7 +72,7 @@ QString QmlPreviewFileOnTargetFinder::findPath(const QString &filePath, bool *su
// Try the current node first. It's likely that this is the one we're looking for and if there
// is any ambiguity (same file mapped to multiple qrc paths) it should take precedence.
- ProjectExplorer::Node *currentNode = ProjectExplorer::ProjectTree::findCurrentNode();
+ ProjectExplorer::Node *currentNode = ProjectExplorer::ProjectTree::currentNode();
if (currentNode && currentNode->filePath().toString() == filePath) {
const QString path = resourceNodePath(currentNode);
if (!path.isEmpty())
@@ -101,7 +101,7 @@ QString QmlPreviewFileOnTargetFinder::findPath(const QString &filePath, bool *su
if (success) {
// On desktop, if there is no "remote" path, then the application will load the local path.
- *success = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(m_target->kit())
+ *success = ProjectExplorer::DeviceTypeKitAspect::deviceTypeId(m_target->kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
}
return filePath;
diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.cpp b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
index b60996ae1f..630bd06fa1 100644
--- a/src/plugins/qmlpreview/qmlpreviewplugin.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
@@ -76,7 +76,7 @@ signals:
static QByteArray defaultFileLoader(const QString &filename, bool *success)
{
if (Core::DocumentModel::Entry *entry
- = Core::DocumentModel::entryForFilePath(Utils::FileName::fromString(filename))) {
+ = Core::DocumentModel::entryForFilePath(Utils::FilePath::fromString(filename))) {
if (!entry->isSuspended) {
*success = true;
return entry->document->contents();
@@ -111,7 +111,7 @@ bool QmlPreviewPlugin::initialize(const QStringList &arguments, QString *errorSt
auto constraint = [](RunConfiguration *runConfiguration) {
Target *target = runConfiguration ? runConfiguration->target() : nullptr;
Kit *kit = target ? target->kit() : nullptr;
- return DeviceTypeKitInformation::deviceTypeId(kit) == Constants::DESKTOP_DEVICE_TYPE;
+ return DeviceTypeKitAspect::deviceTypeId(kit) == Constants::DESKTOP_DEVICE_TYPE;
};
RunControl::registerWorker<LocalQmlPreviewSupport>(Constants::QML_PREVIEW_RUN_MODE, constraint);
@@ -143,7 +143,7 @@ bool QmlPreviewPlugin::initialize(const QStringList &arguments, QString *errorSt
Constants::G_FILE_OTHER);
action->setVisible(false);
connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged, action, [action]() {
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
const FileNode *fileNode = node ? node->asFileNode() : nullptr;
action->setVisible(fileNode ? fileNode->fileType() == FileType::QML : false);
});
@@ -196,9 +196,9 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlPreviewPlugin::aboutToShutdown()
return SynchronousShutdown;
}
-QList<QObject *> QmlPreviewPlugin::createTestObjects() const
+QVector<QObject *> QmlPreviewPlugin::createTestObjects() const
{
- QList<QObject *> tests;
+ QVector<QObject *> tests;
#ifdef WITH_TESTS
tests.append(new QmlPreviewClientTest);
tests.append(new QmlPreviewPluginTest);
@@ -297,8 +297,8 @@ void QmlPreviewPlugin::setFileLoader(QmlPreviewFileLoader fileLoader)
void QmlPreviewPlugin::previewCurrentFile()
{
- const Node *currentNode = ProjectTree::findCurrentNode();
- if (!currentNode || currentNode->nodeType() != NodeType::File
+ const Node *currentNode = ProjectTree::currentNode();
+ if (!currentNode || !currentNode->asFileNode()
|| currentNode->asFileNode()->fileType() != FileType::QML)
return;
diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.h b/src/plugins/qmlpreview/qmlpreviewplugin.h
index f1e780cf1d..559cbb81dd 100644
--- a/src/plugins/qmlpreview/qmlpreviewplugin.h
+++ b/src/plugins/qmlpreview/qmlpreviewplugin.h
@@ -25,9 +25,10 @@
#pragma once
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <extensionsystem/iplugin.h>
#include <qmljs/qmljsdialect.h>
+
#include <QUrl>
#include <QThread>
@@ -63,7 +64,7 @@ public:
bool initialize(const QStringList &arguments, QString *errorString) override;
void extensionsInitialized() override;
ShutdownFlag aboutToShutdown() override;
- QList<QObject *> createTestObjects() const override;
+ QVector<QObject *> createTestObjects() const override;
QString previewedFile() const;
void setPreviewedFile(const QString &previewedFile);
diff --git a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp
index c54208f2ee..0a8ac9fb1a 100644
--- a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp
@@ -50,21 +50,20 @@ QmlPreviewRunner::QmlPreviewRunner(ProjectExplorer::RunControl *runControl,
: RunWorker(runControl)
{
setId("QmlPreviewRunner");
- m_connectionManager.reset(new Internal::QmlPreviewConnectionManager(this));
- m_connectionManager->setFileLoader(fileLoader);
- m_connectionManager->setFileClassifier(fileClassifier);
- m_connectionManager->setFpsHandler(fpsHandler);
+ m_connectionManager.setFileLoader(fileLoader);
+ m_connectionManager.setFileClassifier(fileClassifier);
+ m_connectionManager.setFpsHandler(fpsHandler);
connect(this, &QmlPreviewRunner::loadFile,
- m_connectionManager.data(), &Internal::QmlPreviewConnectionManager::loadFile);
+ &m_connectionManager, &Internal::QmlPreviewConnectionManager::loadFile);
connect(this, &QmlPreviewRunner::rerun,
- m_connectionManager.data(), &Internal::QmlPreviewConnectionManager::rerun);
+ &m_connectionManager, &Internal::QmlPreviewConnectionManager::rerun);
connect(this, &QmlPreviewRunner::zoom,
- m_connectionManager.data(), &Internal::QmlPreviewConnectionManager::zoom);
+ &m_connectionManager, &Internal::QmlPreviewConnectionManager::zoom);
connect(this, &QmlPreviewRunner::language,
- m_connectionManager.data(), &Internal::QmlPreviewConnectionManager::language);
- connect(m_connectionManager.data(), &Internal::QmlPreviewConnectionManager::connectionOpened,
+ &m_connectionManager, &Internal::QmlPreviewConnectionManager::language);
+ connect(&m_connectionManager, &Internal::QmlPreviewConnectionManager::connectionOpened,
this, [this, initialZoom, initialLocale]() {
if (initialZoom > 0)
emit zoom(initialZoom);
@@ -73,15 +72,15 @@ QmlPreviewRunner::QmlPreviewRunner(ProjectExplorer::RunControl *runControl,
emit ready();
});
- connect(m_connectionManager.data(), &Internal::QmlPreviewConnectionManager::restart,
- runControl, [runControl, this]() {
+ connect(&m_connectionManager, &Internal::QmlPreviewConnectionManager::restart,
+ runControl, [runControl]() {
if (!runControl->isRunning())
return;
- ProjectExplorer::RunConfiguration *runConfig = runControl->runConfiguration();
- connect(runControl, &ProjectExplorer::RunControl::stopped, runConfig, [runConfig](){
+ connect(runControl, &ProjectExplorer::RunControl::stopped, runControl, [runControl]() {
ProjectExplorer::ProjectExplorerPlugin::runRunConfiguration(
- runConfig, ProjectExplorer::Constants::QML_PREVIEW_RUN_MODE, true);
+ runControl->runConfiguration(),
+ ProjectExplorer::Constants::QML_PREVIEW_RUN_MODE, true);
});
runControl->initiateStop();
@@ -90,17 +89,14 @@ QmlPreviewRunner::QmlPreviewRunner(ProjectExplorer::RunControl *runControl,
void QmlPreviewRunner::start()
{
- ProjectExplorer::Target *target = nullptr;
- if (ProjectExplorer::RunConfiguration *config = runControl()->runConfiguration())
- target = config->target();
- m_connectionManager->setTarget(target);
- m_connectionManager->connectToServer(serverUrl());
+ m_connectionManager.setTarget(runControl()->target());
+ m_connectionManager.connectToServer(serverUrl());
reportStarted();
}
void QmlPreviewRunner::stop()
{
- m_connectionManager->disconnectFromServer();
+ m_connectionManager.disconnectFromServer();
reportStopped();
}
diff --git a/src/plugins/qmlpreview/qmlpreviewruncontrol.h b/src/plugins/qmlpreview/qmlpreviewruncontrol.h
index 889e7f641b..7a25a62c10 100644
--- a/src/plugins/qmlpreview/qmlpreviewruncontrol.h
+++ b/src/plugins/qmlpreview/qmlpreviewruncontrol.h
@@ -56,7 +56,7 @@ private:
void start() override;
void stop() override;
- QScopedPointer<Internal::QmlPreviewConnectionManager> m_connectionManager;
+ Internal::QmlPreviewConnectionManager m_connectionManager;
};
class LocalQmlPreviewSupport : public ProjectExplorer::SimpleTargetRunner
diff --git a/src/plugins/qmlpreview/tests/qmlpreviewplugin_test.cpp b/src/plugins/qmlpreview/tests/qmlpreviewplugin_test.cpp
index 3b84cd4d4f..9ca2f38b08 100644
--- a/src/plugins/qmlpreview/tests/qmlpreviewplugin_test.cpp
+++ b/src/plugins/qmlpreview/tests/qmlpreviewplugin_test.cpp
@@ -43,7 +43,7 @@ QmlPreviewPluginTest::QmlPreviewPluginTest(QObject *parent) : QObject(parent)
static ExtensionSystem::IPlugin *getPlugin()
{
- const QList<ExtensionSystem::PluginSpec *> plugins = ExtensionSystem::PluginManager::plugins();
+ const QVector<ExtensionSystem::PluginSpec *> plugins = ExtensionSystem::PluginManager::plugins();
auto it = std::find_if(plugins.begin(), plugins.end(), [](ExtensionSystem::PluginSpec *spec) {
return spec->name() == "QmlPreview";
});
diff --git a/src/plugins/qmlprofiler/CMakeLists.txt b/src/plugins/qmlprofiler/CMakeLists.txt
new file mode 100644
index 0000000000..63df2d6a01
--- /dev/null
+++ b/src/plugins/qmlprofiler/CMakeLists.txt
@@ -0,0 +1,75 @@
+add_qtc_plugin(QmlProfiler
+ DEPENDS QmlDebug qmljs Tracing Qt5::QuickWidgets
+ PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport TextEditor
+ SOURCES
+ debugmessagesmodel.cpp debugmessagesmodel.h
+ flamegraphmodel.cpp flamegraphmodel.h
+ flamegraphview.cpp flamegraphview.h
+ inputeventsmodel.cpp inputeventsmodel.h
+ memoryusagemodel.cpp memoryusagemodel.h
+ pixmapcachemodel.cpp pixmapcachemodel.h
+ qml/qmlprofiler.qrc
+ qmlevent.cpp qmlevent.h
+ qmleventlocation.cpp qmleventlocation.h
+ qmleventtype.cpp qmleventtype.h
+ qmlnote.cpp qmlnote.h
+ qmlprofiler_global.h
+ qmlprofileractions.cpp qmlprofileractions.h
+ qmlprofileranimationsmodel.cpp qmlprofileranimationsmodel.h
+ qmlprofilerattachdialog.cpp qmlprofilerattachdialog.h qmlprofilerattachdialog.ui
+ qmlprofilerbindingloopsrenderpass.cpp qmlprofilerbindingloopsrenderpass.h
+ qmlprofilerclientmanager.cpp qmlprofilerclientmanager.h
+ qmlprofilerconfigwidget.cpp qmlprofilerconfigwidget.h qmlprofilerconfigwidget.ui
+ qmlprofilerconstants.h
+ qmlprofilerdetailsrewriter.cpp qmlprofilerdetailsrewriter.h
+ qmlprofilereventsview.h
+ qmlprofilereventtypes.h
+ qmlprofilermodelmanager.cpp qmlprofilermodelmanager.h
+ qmlprofilernotesmodel.cpp qmlprofilernotesmodel.h
+ qmlprofileroptionspage.cpp qmlprofileroptionspage.h
+ qmlprofilerplugin.cpp qmlprofilerplugin.h
+ qmlprofilerrangemodel.cpp qmlprofilerrangemodel.h
+ qmlprofilerrunconfigurationaspect.cpp qmlprofilerrunconfigurationaspect.h
+ qmlprofilerruncontrol.cpp qmlprofilerruncontrol.h
+ qmlprofilersettings.cpp qmlprofilersettings.h
+ qmlprofilerstatemanager.cpp qmlprofilerstatemanager.h
+ qmlprofilerstatewidget.cpp qmlprofilerstatewidget.h
+ qmlprofilerstatisticsmodel.cpp qmlprofilerstatisticsmodel.h
+ qmlprofilerstatisticsview.cpp qmlprofilerstatisticsview.h
+ qmlprofilertextmark.cpp qmlprofilertextmark.h
+ qmlprofilertimelinemodel.cpp qmlprofilertimelinemodel.h
+ qmlprofilertool.cpp qmlprofilertool.h
+ qmlprofilertraceclient.cpp qmlprofilertraceclient.h
+ qmlprofilertracefile.cpp qmlprofilertracefile.h
+ qmlprofilertraceview.cpp qmlprofilertraceview.h
+ qmlprofilerviewmanager.cpp qmlprofilerviewmanager.h
+ qmltypedevent.cpp qmltypedevent.h
+ scenegraphtimelinemodel.cpp scenegraphtimelinemodel.h
+)
+
+extend_qtc_plugin(QmlProfiler
+ CONDITION WITH_TESTS
+ SOURCES
+ tests/debugmessagesmodel_test.cpp tests/debugmessagesmodel_test.h
+ tests/fakedebugserver.cpp tests/fakedebugserver.h
+ tests/flamegraphmodel_test.cpp tests/flamegraphmodel_test.h
+ tests/flamegraphview_test.cpp tests/flamegraphview_test.h
+ tests/inputeventsmodel_test.cpp tests/inputeventsmodel_test.h
+ tests/localqmlprofilerrunner_test.cpp tests/localqmlprofilerrunner_test.h
+ tests/memoryusagemodel_test.cpp tests/memoryusagemodel_test.h
+ tests/pixmapcachemodel_test.cpp tests/pixmapcachemodel_test.h
+ tests/qmlevent_test.cpp tests/qmlevent_test.h
+ tests/qmleventlocation_test.cpp tests/qmleventlocation_test.h
+ tests/qmleventtype_test.cpp tests/qmleventtype_test.h
+ tests/qmlnote_test.cpp tests/qmlnote_test.h
+ tests/qmlprofileranimationsmodel_test.cpp tests/qmlprofileranimationsmodel_test.h
+ tests/qmlprofilerattachdialog_test.cpp tests/qmlprofilerattachdialog_test.h
+ tests/qmlprofilerbindingloopsrenderpass_test.cpp tests/qmlprofilerbindingloopsrenderpass_test.h
+ tests/qmlprofilerclientmanager_test.cpp tests/qmlprofilerclientmanager_test.h
+ tests/qmlprofilerconfigwidget_test.cpp tests/qmlprofilerconfigwidget_test.h
+ tests/qmlprofilerdetailsrewriter_test.cpp tests/qmlprofilerdetailsrewriter_test.h
+ tests/qmlprofilertool_test.cpp tests/qmlprofilertool_test.h
+ tests/qmlprofilertraceclient_test.cpp tests/qmlprofilertraceclient_test.h
+ tests/qmlprofilertraceview_test.cpp tests/qmlprofilertraceview_test.h
+ tests/tests.qrc
+)
diff --git a/src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp b/src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp
index 392bf15927..43b1d500a0 100644
--- a/src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerattachdialog.cpp
@@ -56,7 +56,7 @@ QmlProfilerAttachDialog::QmlProfilerAttachDialog(QWidget *parent) :
d->kitChooser = new KitChooser(this);
d->kitChooser->setKitPredicate([](const Kit *kit) {
- return DeviceKitInformation::device(kit) != nullptr;
+ return DeviceKitAspect::device(kit) != nullptr;
});
d->kitChooser->populate();
diff --git a/src/plugins/qmlprofiler/qmlprofilerconfigwidget.cpp b/src/plugins/qmlprofiler/qmlprofilerconfigwidget.cpp
index 8a83eb64da..37994fd436 100644
--- a/src/plugins/qmlprofiler/qmlprofilerconfigwidget.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerconfigwidget.cpp
@@ -38,7 +38,7 @@ QmlProfilerConfigWidget::QmlProfilerConfigWidget(QmlProfilerSettings *settings,
connect(m_ui->flushEnabled, &QCheckBox::toggled,
m_settings, &QmlProfilerSettings::setFlushEnabled);
- connect(m_ui->flushInterval, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_ui->flushInterval, QOverload<int>::of(&QSpinBox::valueChanged),
m_settings, &QmlProfilerSettings::setFlushInterval);
connect(m_ui->aggregateTraces, &QCheckBox::toggled,
diff --git a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
index e96a92623f..cc97f7eb6a 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
@@ -112,7 +112,7 @@ void QmlProfilerDetailsRewriter::requestDetailsForLocation(int typeId,
QString QmlProfilerDetailsRewriter::getLocalFile(const QString &remoteFile)
{
- const QString localFile = m_projectFinder.findFile(remoteFile);
+ const QString localFile = m_projectFinder.findFile(remoteFile).first().toString();
const QFileInfo fileInfo(localFile);
if (!fileInfo.exists() || !fileInfo.isReadable())
return QString();
diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
index e3a2a1aa3f..942ab9344d 100644
--- a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
@@ -80,12 +80,34 @@ namespace Internal {
Q_GLOBAL_STATIC(QmlProfilerSettings, qmlProfilerGlobalSettings)
+bool constraint(RunConfiguration *runConfiguration)
+{
+ Target *target = runConfiguration ? runConfiguration->target() : nullptr;
+ Kit *kit = target ? target->kit() : nullptr;
+ return DeviceTypeKitAspect::deviceTypeId(kit)
+ == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+}
+
+class QmlProfilerRunWorkerFactory : public RunWorkerFactory
+{
+public:
+ QmlProfilerRunWorkerFactory(QmlProfilerTool *tool)
+ {
+ addSupportedRunMode(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ setProducer([tool](RunControl *runControl) {
+ return new LocalQmlProfilerSupport(tool, runControl);
+ });
+ addConstraint(constraint);
+ }
+};
+
class QmlProfilerPluginPrivate
{
public:
QmlProfilerTool m_profilerTool;
QmlProfilerOptionsPage m_profilerOptionsPage;
QmlProfilerActions m_actions;
+ QmlProfilerRunWorkerFactory m_profilerWorkerFactory{&m_profilerTool};
};
bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorString)
@@ -102,13 +124,6 @@ void QmlProfilerPlugin::extensionsInitialized()
RunConfiguration::registerAspect<QmlProfilerRunConfigurationAspect>();
- auto constraint = [](RunConfiguration *runConfiguration) {
- Target *target = runConfiguration ? runConfiguration->target() : nullptr;
- Kit *kit = target ? target->kit() : nullptr;
- return DeviceTypeKitInformation::deviceTypeId(kit)
- == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
- };
-
RunControl::registerWorkerCreator(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE,
[this](RunControl *runControl) {
auto runner = new QmlProfilerRunner(runControl);
@@ -116,11 +131,6 @@ void QmlProfilerPlugin::extensionsInitialized()
&d->m_profilerTool, &QmlProfilerTool::finalizeRunControl);
return runner;
});
-
- RunControl::registerWorker(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE,
- [this](ProjectExplorer::RunControl *runControl) {
- return new LocalQmlProfilerSupport(&d->m_profilerTool, runControl);
- }, constraint);
}
ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown()
@@ -139,9 +149,9 @@ QmlProfilerSettings *QmlProfilerPlugin::globalSettings()
return qmlProfilerGlobalSettings();
}
-QList<QObject *> QmlProfiler::Internal::QmlProfilerPlugin::createTestObjects() const
+QVector<QObject *> QmlProfiler::Internal::QmlProfilerPlugin::createTestObjects() const
{
- QList<QObject *> tests;
+ QVector<QObject *> tests;
#ifdef WITH_TESTS
tests << new DebugMessagesModelTest;
tests << new FlameGraphModelTest;
diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.h b/src/plugins/qmlprofiler/qmlprofilerplugin.h
index 73383bb500..d0a76d2537 100644
--- a/src/plugins/qmlprofiler/qmlprofilerplugin.h
+++ b/src/plugins/qmlprofiler/qmlprofilerplugin.h
@@ -44,7 +44,7 @@ private:
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final;
ShutdownFlag aboutToShutdown() final;
- QList<QObject *> createTestObjects() const final;
+ QVector<QObject *> createTestObjects() const final;
class QmlProfilerPluginPrivate *d = nullptr;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
index e1e476df36..c9cc305d75 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
@@ -204,9 +204,8 @@ QUrl QmlProfilerRunner::serverUrl() const
static QUrl localServerUrl(RunControl *runControl)
{
QUrl serverUrl;
- RunConfiguration *runConfiguration = runControl->runConfiguration();
- Kit *kit = runConfiguration->target()->kit();
- const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
+ Kit *kit = runControl->kit();
+ const QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit);
if (version) {
if (version->qtVersion() >= QtSupport::QtVersionNumber(5, 6, 0))
serverUrl = Utils::urlFromLocalSocket();
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.h b/src/plugins/qmlprofiler/qmlprofilerruncontrol.h
index 48bc789414..0bdd9315cb 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.h
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.h
@@ -27,7 +27,7 @@
#include "qmlprofilerstatemanager.h"
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/outputformat.h>
#include <utils/port.h>
diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
index 6d7b69eb45..3630d6a2d2 100644
--- a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
@@ -39,7 +39,7 @@ namespace QmlProfiler {
namespace Internal {
QmlProfilerTextMark::QmlProfilerTextMark(QmlProfilerViewManager *viewManager, int typeId,
- const FileName &fileName, int lineNumber) :
+ const FilePath &fileName, int lineNumber) :
TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY, 3.5), m_viewManager(viewManager),
m_typeIds(1, typeId)
{
@@ -116,7 +116,7 @@ void QmlProfilerTextMarkModel::createMarks(QmlProfilerViewManager *viewManager,
lineNumber = id.lineNumber;
m_marks << new QmlProfilerTextMark(viewManager,
id.typeId,
- FileName::fromString(fileName),
+ FilePath::fromString(fileName),
id.lineNumber);
}
}
diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.h b/src/plugins/qmlprofiler/qmlprofilertextmark.h
index 8ed4576ea1..5b529cd3c1 100644
--- a/src/plugins/qmlprofiler/qmlprofilertextmark.h
+++ b/src/plugins/qmlprofiler/qmlprofilertextmark.h
@@ -36,7 +36,7 @@ class QmlProfilerTextMark : public TextEditor::TextMark
{
public:
QmlProfilerTextMark(QmlProfilerViewManager *viewManager, int typeId,
- const Utils::FileName &fileName, int lineNumber);
+ const Utils::FilePath &fileName, int lineNumber);
void addTypeId(int typeId);
void paintIcon(QPainter *painter, const QRect &rect) const override;
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index 628ef5e517..ba5228f7c1 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -300,16 +300,12 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
{
d->m_toolBusy = true;
auto runControl = runWorker->runControl();
- auto runConfiguration = runControl->runConfiguration();
- if (runConfiguration) {
- auto aspect = static_cast<QmlProfilerRunConfigurationAspect *>(
- runConfiguration->aspect(Constants::SETTINGS));
- if (aspect) {
- if (auto settings = static_cast<const QmlProfilerSettings *>(aspect->currentSettings())) {
- d->m_profilerConnections->setFlushInterval(settings->flushEnabled() ?
- settings->flushInterval() : 0);
- d->m_profilerModelManager->setAggregateTraces(settings->aggregateTraces());
- }
+ if (auto aspect = static_cast<QmlProfilerRunConfigurationAspect *>(
+ runControl->aspect(Constants::SETTINGS))) {
+ if (auto settings = static_cast<const QmlProfilerSettings *>(aspect->currentSettings())) {
+ d->m_profilerConnections->setFlushInterval(settings->flushEnabled() ?
+ settings->flushInterval() : 0);
+ d->m_profilerModelManager->setAggregateTraces(settings->aggregateTraces());
}
}
@@ -322,8 +318,8 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
if (d->m_profilerConnections->isConnecting()) {
showNonmodalWarning(tr("The application finished before a connection could be "
"established. No data was loaded."));
- d->m_profilerConnections->disconnectFromServer();
}
+ d->m_profilerConnections->disconnectFromServer();
};
connect(runControl, &RunControl::stopped, this, handleStop);
@@ -341,8 +337,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
// Initialize m_projectFinder
//
- d->m_profilerModelManager->populateFileFinder(runConfiguration ? runConfiguration->target()
- : nullptr);
+ d->m_profilerModelManager->populateFileFinder(runControl->target());
connect(d->m_profilerConnections, &QmlProfilerClientManager::connectionFailed,
runWorker, [this, runWorker]() {
@@ -543,7 +538,7 @@ ProjectExplorer::RunControl *QmlProfilerTool::attachToWaitingApplication()
QUrl serverUrl;
- IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+ IDevice::ConstPtr device = DeviceKitAspect::device(kit);
QTC_ASSERT(device, return nullptr);
QUrl toolControl = device->toolControlChannel(IDevice::QmlControlChannel);
serverUrl.setScheme(Utils::urlTcpScheme());
@@ -552,8 +547,8 @@ ProjectExplorer::RunControl *QmlProfilerTool::attachToWaitingApplication()
d->m_viewContainer->perspective()->select();
- auto runConfig = RunConfiguration::startupRunConfiguration();
- auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ auto runControl = new RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl->setRunConfiguration(RunConfiguration::startupRunConfiguration());
auto profiler = new QmlProfilerRunner(runControl);
profiler->setServerUrl(serverUrl);
connect(profiler, &QmlProfilerRunner::starting, this, &QmlProfilerTool::finalizeRunControl);
diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
index a4721bf450..e96f4da649 100644
--- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
+++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
@@ -64,8 +64,7 @@ void LocalQmlProfilerRunnerTest::testRunner()
serverUrl.setScheme(Utils::urlSocketScheme());
serverUrl.setPath("invalid");
- runControl = new ProjectExplorer::RunControl(nullptr,
- ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
runControl->setRunnable(debuggee);
profiler = new LocalQmlProfilerSupport(&tool, runControl, serverUrl);
@@ -115,8 +114,7 @@ void LocalQmlProfilerRunnerTest::testRunner()
// comma is used to specify a test function. In this case, an invalid one.
debuggee.commandLineArguments = QString("-test QmlProfiler,");
- runControl = new ProjectExplorer::RunControl(nullptr,
- ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
runControl->setRunnable(debuggee);
profiler = new LocalQmlProfilerSupport(&tool, runControl, serverUrl);
connectRunner();
@@ -135,8 +133,7 @@ void LocalQmlProfilerRunnerTest::testRunner()
debuggee.commandLineArguments.clear();
serverUrl.clear();
serverUrl = Utils::urlFromLocalHostAndFreePort();
- runControl = new ProjectExplorer::RunControl(nullptr,
- ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
runControl->setRunnable(debuggee);
profiler = new LocalQmlProfilerSupport(&tool, runControl, serverUrl);
connectRunner();
@@ -161,8 +158,7 @@ void LocalQmlProfilerRunnerTest::testRunner()
serverUrl.setPath(file.fileName());
}
- runControl = new ProjectExplorer::RunControl(nullptr,
- ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
+ runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
runControl->setRunnable(debuggee);
profiler = new LocalQmlProfilerSupport(&tool, runControl, serverUrl);
connectRunner();
diff --git a/src/plugins/qmlprofiler/tests/qmlnote_test.h b/src/plugins/qmlprofiler/tests/qmlnote_test.h
index 0842e6f423..0a678e32e7 100644
--- a/src/plugins/qmlprofiler/tests/qmlnote_test.h
+++ b/src/plugins/qmlprofiler/tests/qmlnote_test.h
@@ -30,7 +30,6 @@
namespace QmlProfiler {
namespace Internal {
-
class QmlNoteTest : public QObject
{
Q_OBJECT
diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerattachdialog_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerattachdialog_test.cpp
index e37a9f0ec0..d0a2856cd8 100644
--- a/src/plugins/qmlprofiler/tests/qmlprofilerattachdialog_test.cpp
+++ b/src/plugins/qmlprofiler/tests/qmlprofilerattachdialog_test.cpp
@@ -46,16 +46,15 @@ void QmlProfilerAttachDialogTest::testAccessors()
dialog.setPort(4444);
QCOMPARE(dialog.port(), 4444);
- auto newKit = std::make_unique<ProjectExplorer::Kit>("dings");
- ProjectExplorer::Kit *newKitPtr = newKit.get();
ProjectExplorer::KitManager *kitManager = ProjectExplorer::KitManager::instance();
QVERIFY(kitManager);
- QVERIFY(kitManager->registerKit(std::move(newKit)));
+ ProjectExplorer::Kit * const newKit = kitManager->registerKit({}, "dings");
+ QVERIFY(newKit);
dialog.setKitId("dings");
- QCOMPARE(dialog.kit(), newKitPtr);
+ QCOMPARE(dialog.kit(), newKit);
- kitManager->deregisterKit(newKitPtr);
+ kitManager->deregisterKit(newKit);
}
} // namespace Internal
diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp
index 9a2dede657..3c938b3e15 100644
--- a/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp
+++ b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp
@@ -41,28 +41,21 @@
namespace QmlProfiler {
namespace Internal {
-class DummyProjectNode : public ProjectExplorer::ProjectNode
-{
-public:
- DummyProjectNode(const Utils::FileName &file) : ProjectExplorer::ProjectNode(file)
- {}
-};
-
class DummyProject : public ProjectExplorer::Project
{
Q_OBJECT
public:
- DummyProject(const Utils::FileName &file) :
+ DummyProject(const Utils::FilePath &file) :
ProjectExplorer::Project(QString(), file, {})
{
auto fileNode
- = std::make_unique<ProjectExplorer::FileNode>(file, ProjectExplorer::FileType::Source, false);
- auto root = std::make_unique<DummyProjectNode>(file);
+ = std::make_unique<ProjectExplorer::FileNode>(file, ProjectExplorer::FileType::Source);
+ auto root = std::make_unique<ProjectExplorer::ProjectNode>(file);
root->addNode(std::move(fileNode));
fileNode = std::make_unique<ProjectExplorer::FileNode>(
- Utils::FileName::fromLatin1(
+ Utils::FilePath::fromString(
":/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp"),
- ProjectExplorer::FileType::Source, false);
+ ProjectExplorer::FileType::Source);
root->addNode(std::move(fileNode));
setRootProjectNode(std::move(root));
setDisplayName(file.toString());
@@ -188,10 +181,10 @@ void QmlProfilerDetailsRewriterTest::testPopulateFileFinder()
QCOMPARE(m_rewriter.getLocalFile("Test.qml"), QString());
// Test that the rewriter will populate from available projects if given nullptr as parameter.
- DummyProject *project1 = new DummyProject(Utils::FileName::fromString(":/nix.nix"));
+ DummyProject *project1 = new DummyProject(Utils::FilePath::fromString(":/nix.nix"));
ProjectExplorer::SessionManager::addProject(project1);
DummyProject *project2 = new DummyProject(
- Utils::FileName::fromString(":/qmlprofiler/tests/Test.qml"));
+ Utils::FilePath::fromString(":/qmlprofiler/tests/Test.qml"));
ProjectExplorer::SessionManager::addProject(project2);
m_rewriter.populateFileFinder(nullptr);
QCOMPARE(m_rewriter.getLocalFile("Test.qml"),
@@ -210,7 +203,7 @@ void QmlProfilerDetailsRewriterTest::seedRewriter()
QFutureInterface<void> result;
QmlJS::PathsAndLanguages lPaths;
lPaths.maybeInsert(
- Utils::FileName::fromString(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)),
+ Utils::FilePath::fromString(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath)),
QmlJS::Dialect::Qml);
QmlJS::ModelManagerInterface::importScan(result, QmlJS::ModelManagerInterface::workingCopy(),
lPaths, m_modelManager, false);
@@ -226,10 +219,10 @@ void QmlProfilerDetailsRewriterTest::seedRewriter()
QVERIFY(!doc->source().isEmpty());
auto kit = std::make_unique<ProjectExplorer::Kit>();
- ProjectExplorer::SysRootKitInformation::setSysRoot(
- kit.get(), Utils::FileName::fromLatin1("/nowhere"));
+ ProjectExplorer::SysRootKitAspect::setSysRoot(
+ kit.get(), Utils::FilePath::fromString("/nowhere"));
- DummyProject *project = new DummyProject(Utils::FileName::fromString(filename));
+ DummyProject *project = new DummyProject(Utils::FilePath::fromString(filename));
ProjectExplorer::SessionManager::addProject(project);
{
diff --git a/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp
index 8f7ecb778e..66edba16da 100644
--- a/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp
+++ b/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp
@@ -29,7 +29,7 @@
#include <coreplugin/icore.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitmanager.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <qmlprofiler/qmlprofilerattachdialog.h>
#include <qmlprofiler/qmlprofilerclientmanager.h>
#include <qmlprofiler/qmlprofilermodelmanager.h>
@@ -44,14 +44,13 @@ namespace Internal {
void QmlProfilerToolTest::testAttachToWaitingApplication()
{
- auto newKit = std::make_unique<ProjectExplorer::Kit>("fookit");
- ProjectExplorer::Kit * newKitPtr = newKit.get();
ProjectExplorer::KitManager *kitManager = ProjectExplorer::KitManager::instance();
QVERIFY(kitManager);
- QVERIFY(kitManager->registerKit(std::move(newKit)));
+ ProjectExplorer::Kit * const newKit = kitManager->registerKit({}, "fookit");
+ QVERIFY(newKit);
QSettings *settings = Core::ICore::settings();
QVERIFY(settings);
- settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/kitId"), newKitPtr->id().toSetting());
+ settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/kitId"), newKit->id().toSetting());
QmlProfilerTool profilerTool;
diff --git a/src/plugins/qmlprojectmanager/CMakeLists.txt b/src/plugins/qmlprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..ddef6f61f2
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_qtc_plugin(QmlProjectManager
+ DEPENDS qmljs
+ PLUGIN_DEPENDS Core ProjectExplorer QtSupport
+ SOURCES
+ fileformat/filefilteritems.cpp fileformat/filefilteritems.h
+ fileformat/qmlprojectfileformat.cpp fileformat/qmlprojectfileformat.h
+ fileformat/qmlprojectitem.cpp fileformat/qmlprojectitem.h
+ qmlproject.cpp qmlproject.h
+ qmlproject.qrc
+ qmlprojectconstants.h
+ qmlprojectmanager_global.h
+ qmlprojectmanagerconstants.h
+ qmlprojectnodes.cpp qmlprojectnodes.h
+ qmlprojectplugin.cpp qmlprojectplugin.h
+ qmlprojectrunconfiguration.cpp qmlprojectrunconfiguration.h
+)
diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
index 233712dc06..9f0a16a921 100644
--- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp
@@ -175,7 +175,7 @@ bool FileFilterBaseItem::matchesFile(const QString &filePath) const
return true;
}
- const QString &fileName = Utils::FileName::fromString(filePath).fileName();
+ const QString &fileName = Utils::FilePath::fromString(filePath).fileName();
if (!fileMatches(fileName))
return false;
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
index 9947f2f7d5..2102147c29 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
@@ -63,7 +63,7 @@ void setupFileFilterItem(QmlProjectManager::FileFilterBaseItem *fileFilterItem,
namespace QmlProjectManager {
-QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FileName &fileName, QString *errorMessage)
+QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fileName, QString *errorMessage)
{
QmlJS::SimpleReader simpleQmlJSReader;
@@ -88,6 +88,10 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FileName &fi
if (importPathsProperty.isValid())
projectItem->setImportPaths(importPathsProperty.toStringList());
+ const QVariant fileSelectorsProperty = rootNode->property(QLatin1String("fileSelectors"));
+ if (fileSelectorsProperty.isValid())
+ projectItem->setFileSelectors(fileSelectorsProperty.toStringList());
+
const QVariant targetDirectoryPropery = rootNode->property("targetDirectory");
if (targetDirectoryPropery.isValid())
projectItem->setTargetDirectory(targetDirectoryPropery.toString());
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h
index 70c5870347..9453ac8d71 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h
@@ -39,7 +39,7 @@ class QmlProjectFileFormat
Q_DECLARE_TR_FUNCTIONS(QmlProjectManager::QmlProjectFileFormat)
public:
- static QmlProjectItem *parseProjectFile(const Utils::FileName &fileName,
+ static QmlProjectItem *parseProjectFile(const Utils::FilePath &fileName,
QString *errorMessage = nullptr);
};
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
index 514a5bdff3..e82e90fedc 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp
@@ -59,6 +59,12 @@ void QmlProjectItem::setImportPaths(const QStringList &importPaths)
m_importPaths = importPaths;
}
+void QmlProjectItem::setFileSelectors(const QStringList &selectors)
+{
+ if (m_fileSelectors != selectors)
+ m_fileSelectors = selectors;
+}
+
/* Returns list of absolute paths */
QStringList QmlProjectItem::files() const
{
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
index 086b34a7b8..4ba9afcd5f 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
@@ -54,6 +54,9 @@ public:
QStringList importPaths() const { return m_importPaths; }
void setImportPaths(const QStringList &paths);
+ QStringList fileSelectors() const { return m_fileSelectors; }
+ void setFileSelectors(const QStringList &selectors);
+
QStringList files() const;
bool matchesFile(const QString &filePath) const;
@@ -72,6 +75,7 @@ protected:
QString m_sourceDirectory;
QString m_targetDirectory;
QStringList m_importPaths;
+ QStringList m_fileSelectors;
QString m_mainFile;
QList<Utils::EnvironmentItem> m_environment;
QList<QmlProjectContentItem *> m_content; // content property
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index e516862617..5b518ccc87 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -56,13 +56,13 @@ using namespace ProjectExplorer;
namespace QmlProjectManager {
-QmlProject::QmlProject(const Utils::FileName &fileName) :
+QmlProject::QmlProject(const Utils::FilePath &fileName) :
Project(QString::fromLatin1(Constants::QMLPROJECT_MIMETYPE), fileName,
[this]() { refreshProjectFile(); })
{
const QString normalized
= Utils::FileUtils::normalizePathName(fileName.toFileInfo().canonicalFilePath());
- m_canonicalProjectDir = Utils::FileName::fromString(normalized).parentDir();
+ m_canonicalProjectDir = Utils::FilePath::fromString(normalized).parentDir();
setId(QmlProjectManager::Constants::QML_PROJECT_ID);
setProjectLanguages(Context(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID));
@@ -97,7 +97,7 @@ void QmlProject::onKitChanged()
refresh(Configuration);
}
-Utils::FileName QmlProject::canonicalProjectDir() const
+Utils::FilePath QmlProject::canonicalProjectDir() const
{
return m_canonicalProjectDir;
}
@@ -165,7 +165,7 @@ void QmlProject::refresh(RefreshOptions options)
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
modelManager->defaultProjectInfoForProject(this);
foreach (const QString &searchPath, makeAbsolute(canonicalProjectDir(), customImportPaths()))
- projectInfo.importPaths.maybeInsert(Utils::FileName::fromString(searchPath),
+ projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(searchPath),
QmlJS::Dialect::Qml);
modelManager->updateProjectInfo(projectInfo, this);
@@ -186,24 +186,24 @@ void QmlProject::setMainFile(const QString &mainFilePath)
m_projectItem.data()->setMainFile(mainFilePath);
}
-Utils::FileName QmlProject::targetDirectory(const Target *target) const
+Utils::FilePath QmlProject::targetDirectory(const Target *target) const
{
- if (DeviceTypeKitInformation::deviceTypeId(target->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(target->kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return canonicalProjectDir();
- return m_projectItem ? Utils::FileName::fromString(m_projectItem->targetDirectory())
- : Utils::FileName();
+ return m_projectItem ? Utils::FilePath::fromString(m_projectItem->targetDirectory())
+ : Utils::FilePath();
}
-Utils::FileName QmlProject::targetFile(const Utils::FileName &sourceFile,
+Utils::FilePath QmlProject::targetFile(const Utils::FilePath &sourceFile,
const Target *target) const
{
const QDir sourceDir(m_projectItem ? m_projectItem->sourceDirectory()
: canonicalProjectDir().toString());
const QDir targetDir(targetDirectory(target).toString());
const QString relative = sourceDir.relativeFilePath(sourceFile.toString());
- return Utils::FileName::fromString(QDir::cleanPath(targetDir.absoluteFilePath(relative)));
+ return Utils::FilePath::fromString(QDir::cleanPath(targetDir.absoluteFilePath(relative)));
}
QList<Utils::EnvironmentItem> QmlProject::environment() const
@@ -225,6 +225,13 @@ QStringList QmlProject::customImportPaths() const
return {};
}
+QStringList QmlProject::customFileSelectors() const
+{
+ if (m_projectItem)
+ return m_projectItem.data()->fileSelectors();
+ return {};
+}
+
bool QmlProject::addFiles(const QStringList &filePaths)
{
QStringList toAdd;
@@ -245,7 +252,7 @@ bool QmlProject::needsBuildConfigurations() const
return false;
}
-QStringList QmlProject::makeAbsolute(const Utils::FileName &path, const QStringList &relativePaths)
+QStringList QmlProject::makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths)
{
if (path.isEmpty())
return relativePaths;
@@ -256,6 +263,13 @@ QStringList QmlProject::makeAbsolute(const Utils::FileName &path, const QStringL
});
}
+QVariant QmlProject::additionalData(Id id, const Target *) const
+{
+ if (id == Constants::customFileSelectorsData)
+ return customFileSelectors();
+ return {};
+}
+
void QmlProject::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString> &removed)
{
refresh(Files);
@@ -273,15 +287,15 @@ void QmlProject::refreshTargetDirectory()
updateDeploymentData(target);
}
-QList<Task> QmlProject::projectIssues(const Kit *k) const
+Tasks QmlProject::projectIssues(const Kit *k) const
{
- QList<Task> result = Project::projectIssues(k);
+ Tasks result = Project::projectIssues(k);
- const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
+ const QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
if (!version)
result.append(createProjectTask(Task::TaskType::Error, tr("No Qt version set in kit.")));
- IDevice::ConstPtr dev = DeviceKitInformation::device(k);
+ IDevice::ConstPtr dev = DeviceKitAspect::device(k);
if (dev.isNull())
result.append(createProjectTask(Task::TaskType::Error, tr("Kit has no device.")));
@@ -347,6 +361,11 @@ Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *erro
return RestoreResult::Ok;
}
+ProjectExplorer::DeploymentKnowledge QmlProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Perfect;
+}
+
void QmlProject::generateProjectTree()
{
if (!m_projectItem)
@@ -355,12 +374,12 @@ void QmlProject::generateProjectTree()
auto newRoot = std::make_unique<Internal::QmlProjectNode>(this);
for (const QString &f : m_projectItem.data()->files()) {
- const Utils::FileName fileName = Utils::FileName::fromString(f);
+ const Utils::FilePath fileName = Utils::FilePath::fromString(f);
const FileType fileType = (fileName == projectFilePath())
? FileType::Project : FileNode::fileTypeForFileName(fileName);
- newRoot->addNestedNode(std::make_unique<FileNode>(fileName, fileType, false));
+ newRoot->addNestedNode(std::make_unique<FileNode>(fileName, fileType));
}
- newRoot->addNestedNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project, false));
+ newRoot->addNestedNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project));
setRootProjectNode(std::move(newRoot));
refreshTargetDirectory();
@@ -371,7 +390,7 @@ void QmlProject::updateDeploymentData(ProjectExplorer::Target *target)
if (!m_projectItem)
return;
- if (DeviceTypeKitInformation::deviceTypeId(target->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(target->kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
return;
}
@@ -380,7 +399,7 @@ void QmlProject::updateDeploymentData(ProjectExplorer::Target *target)
for (const QString &file : m_projectItem->files()) {
deploymentData.addFile(
file,
- targetFile(Utils::FileName::fromString(file), target).parentDir().toString());
+ targetFile(Utils::FilePath::fromString(file), target).parentDir().toString());
}
target->setDeploymentData(deploymentData);
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index 8f7bf30c04..b3ce817f19 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -45,10 +45,10 @@ class QMLPROJECTMANAGER_EXPORT QmlProject : public ProjectExplorer::Project
Q_OBJECT
public:
- explicit QmlProject(const Utils::FileName &filename);
+ explicit QmlProject(const Utils::FilePath &filename);
~QmlProject() override;
- QList<ProjectExplorer::Task> projectIssues(const ProjectExplorer::Kit *k) const final;
+ ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
bool validProjectFile() const;
@@ -62,15 +62,16 @@ public:
void refresh(RefreshOptions options);
- Utils::FileName canonicalProjectDir() const;
+ Utils::FilePath canonicalProjectDir() const;
QString mainFile() const;
void setMainFile(const QString &mainFilePath);
- Utils::FileName targetDirectory(const ProjectExplorer::Target *target) const;
- Utils::FileName targetFile(const Utils::FileName &sourceFile,
+ Utils::FilePath targetDirectory(const ProjectExplorer::Target *target) const;
+ Utils::FilePath targetFile(const Utils::FilePath &sourceFile,
const ProjectExplorer::Target *target) const;
QList<Utils::EnvironmentItem> environment() const;
QStringList customImportPaths() const;
+ QStringList customFileSelectors() const;
bool addFiles(const QStringList &filePaths);
@@ -78,11 +79,16 @@ public:
bool needsBuildConfigurations() const final;
- static QStringList makeAbsolute(const Utils::FileName &path, const QStringList &relativePaths);
+ static QStringList makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths);
+
+ QVariant additionalData(Core::Id id, const ProjectExplorer::Target *target) const override;
+
protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
private:
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+
void generateProjectTree();
void updateDeploymentData(ProjectExplorer::Target *target);
void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed);
@@ -97,7 +103,7 @@ private:
ProjectExplorer::Target *m_activeTarget = nullptr;
QPointer<QmlProjectItem> m_projectItem;
- Utils::FileName m_canonicalProjectDir;
+ Utils::FilePath m_canonicalProjectDir;
};
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectconstants.h b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
index ea6b6b4e79..eb2ddcddb1 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectconstants.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectconstants.h
@@ -31,6 +31,7 @@ namespace QmlProjectManager {
namespace Constants {
const char * const QMLPROJECT_MIMETYPE = QmlJSTools::Constants::QMLPROJECT_MIMETYPE;
+const char customFileSelectorsData[] = "CustomFileSelectorsData";
} // namespace Constants
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp b/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp
deleted file mode 100644
index 0a81e39bf4..0000000000
--- a/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.cpp
+++ /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.
-**
-****************************************************************************/
-
-#include "qmlprojectenvironmentaspect.h"
-
-#include "qmlproject.h"
-
-#include <projectexplorer/kit.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/target.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace QmlProjectManager {
-
-enum BaseEnvironmentBase {
- SystemEnvironmentBase = 0,
- CleanEnvironmentBase
-};
-
-Environment QmlProjectEnvironmentAspect::baseEnvironment() const
-{
- Environment env = baseEnvironmentBase() == SystemEnvironmentBase
- ? Environment::systemEnvironment()
- : Environment();
-
- if (auto project = qobject_cast<const QmlProject *>(m_target->project()))
- env.modify(project->environment());
-
- return env;
-}
-
-QmlProjectEnvironmentAspect::QmlProjectEnvironmentAspect(Target *target)
- : m_target(target)
-{
- if (DeviceTypeKitInformation::deviceTypeId(target->kit())
- == Constants::DESKTOP_DEVICE_TYPE)
- addPreferredBaseEnvironment(SystemEnvironmentBase, tr("System Environment"));
-
- addSupportedBaseEnvironment(CleanEnvironmentBase, tr("Clean Environment"));
-}
-
-} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.h b/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.h
deleted file mode 100644
index 65880649fb..0000000000
--- a/src/plugins/qmlprojectmanager/qmlprojectenvironmentaspect.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 <projectexplorer/environmentaspect.h>
-
-namespace QmlProjectManager {
-
-class QmlProjectEnvironmentAspect : public ProjectExplorer::EnvironmentAspect
-{
- Q_OBJECT
-
-public:
- QmlProjectEnvironmentAspect(ProjectExplorer::Target *target);
-
- Utils::Environment baseEnvironment() const override;
-
-private:
- ProjectExplorer::Target *m_target;
-};
-
-} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro
index b179dac63e..ffd837e827 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro
@@ -4,8 +4,9 @@ include(../../qtcreatorplugin.pri)
include(fileformat/fileformat.pri)
DEFINES += QMLPROJECTMANAGER_LIBRARY
-HEADERS += qmlproject.h \
- qmlprojectenvironmentaspect.h \
+
+HEADERS += \
+ qmlproject.h \
qmlprojectplugin.h \
qmlprojectconstants.h \
qmlprojectnodes.h \
@@ -13,8 +14,8 @@ HEADERS += qmlproject.h \
qmlprojectmanager_global.h \
qmlprojectmanagerconstants.h
-SOURCES += qmlproject.cpp \
- qmlprojectenvironmentaspect.cpp \
+SOURCES += \
+ qmlproject.cpp \
qmlprojectplugin.cpp \
qmlprojectnodes.cpp \
qmlprojectrunconfiguration.cpp
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
index 1403127694..258ef8d754 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
@@ -18,7 +18,6 @@ QtcPlugin {
"qmlproject.cpp", "qmlproject.h",
"qmlproject.qrc",
"qmlprojectconstants.h",
- "qmlprojectenvironmentaspect.cpp", "qmlprojectenvironmentaspect.h",
"qmlprojectmanager_global.h",
"qmlprojectmanagerconstants.h",
"qmlprojectnodes.cpp", "qmlprojectnodes.h",
diff --git a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
index 195681aebe..7b311c2cf6 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
@@ -53,18 +53,13 @@ QmlProjectNode::QmlProjectNode(QmlProject *project) : ProjectNode(project->proje
setIcon(qmlProjectIcon);
}
-bool QmlProjectNode::showInSimpleTree() const
-{
- return true;
-}
-
bool QmlProjectNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == AddNewFile || action == EraseFile)
return true;
QTC_ASSERT(node, return false);
- if (action == Rename && node->nodeType() == NodeType::File) {
+ if (action == Rename && node->asFileNode()) {
const FileNode *fileNode = node->asFileNode();
QTC_ASSERT(fileNode, return false);
return fileNode->fileType() != FileType::Project;
diff --git a/src/plugins/qmlprojectmanager/qmlprojectnodes.h b/src/plugins/qmlprojectmanager/qmlprojectnodes.h
index 6a3f688b3d..4d6fe4cfcf 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectnodes.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectnodes.h
@@ -38,7 +38,6 @@ class QmlProjectNode : public ProjectExplorer::ProjectNode
public:
QmlProjectNode(QmlProject *project);
- bool showInSimpleTree() const override;
bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
bool deleteFiles(const QStringList &filePaths) override;
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
index 6e460d3e0b..d20f4caa43 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
@@ -25,12 +25,13 @@
#include "qmlprojectplugin.h"
#include "qmlproject.h"
-#include "qmlprojectrunconfigurationfactory.h"
+#include "qmlprojectrunconfiguration.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <projectexplorer/projectmanager.h>
+#include <projectexplorer/runcontrol.h>
#include <qmljstools/qmljstoolsconstants.h>
@@ -39,16 +40,24 @@ using namespace ProjectExplorer;
namespace QmlProjectManager {
namespace Internal {
+class QmlProjectPluginPrivate
+{
+public:
+ QmlProjectRunConfigurationFactory runConfigFactory;
+ SimpleRunWorkerFactory<SimpleTargetRunner, QmlProjectRunConfiguration>
+ runWorkerFactory{ProjectExplorer::Constants::NORMAL_RUN_MODE};
+};
+
QmlProjectPlugin::~QmlProjectPlugin()
{
- delete m_rcFactory;
+ delete d;
}
bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
{
Q_UNUSED(errorMessage)
- m_rcFactory = new QmlProjectRunConfigurationFactory;
+ d = new QmlProjectPluginPrivate;
ProjectManager::registerProjectType<QmlProject>(QmlJSTools::Constants::QMLPROJECT_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForSuffix(":/qmlproject/images/qmlproject.png", "qmlproject");
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.h b/src/plugins/qmlprojectmanager/qmlprojectplugin.h
index d08738cfa9..10a407216d 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.h
@@ -43,7 +43,7 @@ private:
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final {}
- class QmlProjectRunConfigurationFactory *m_rcFactory = nullptr;
+ class QmlProjectPluginPrivate *d = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index 6b8742f9dc..f2e54f6444 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -26,14 +26,15 @@
#include "qmlprojectrunconfiguration.h"
#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
-#include "qmlprojectenvironmentaspect.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
+#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
@@ -41,10 +42,12 @@
#include <qtsupport/qtsupportconstants.h>
#include <qtsupport/desktopqtversion.h>
+#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcprocess.h>
#include <utils/winutils.h>
+
#include <qmljstools/qmljstoolsconstants.h>
#include <QComboBox>
@@ -55,6 +58,7 @@
using namespace Core;
using namespace ProjectExplorer;
using namespace QtSupport;
+using namespace Utils;
namespace QmlProjectManager {
@@ -125,7 +129,7 @@ void MainQmlFileAspect::addToConfigurationLayout(QFormLayout *layout)
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::fileListChanged,
this, &MainQmlFileAspect::updateFileComboBox);
- connect(m_fileListCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_fileListCombo, QOverload<int>::of(&QComboBox::activated),
this, &MainQmlFileAspect::setMainScript);
layout->addRow(QmlProjectRunConfiguration::tr("Main QML file:"), m_fileListCombo);
@@ -169,7 +173,7 @@ void MainQmlFileAspect::updateFileComboBox()
QModelIndex currentIndex;
QStringList sortedFiles = Utils::transform(m_project->files(Project::AllFiles),
- &Utils::FileName::toString);
+ &Utils::FilePath::toString);
// make paths relative to project directory
QStringList relativeFiles;
@@ -275,10 +279,30 @@ void MainQmlFileAspect::changeCurrentFile(IEditor *editor)
QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- addAspect<QmlProjectEnvironmentAspect>(target);
+ auto envAspect = addAspect<EnvironmentAspect>();
+
+ auto envModifier = [target](Environment env) {
+ if (auto project = qobject_cast<const QmlProject *>(target->project()))
+ env.modify(project->environment());
+ return env;
+ };
+
+ const Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(target->kit());
+ if (deviceTypeId == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
+ envAspect->addPreferredBaseEnvironment(tr("System Environment"), [envModifier] {
+ return envModifier(Environment::systemEnvironment());
+ });
+ }
+
+ envAspect->addSupportedBaseEnvironment(tr("Clean Environment"), [envModifier] {
+ return envModifier(Environment());
+ });
+
+ setExecutableGetter([this] { return FilePath::fromString(theExecutable()); });
+
m_qmlViewerAspect = addAspect<BaseStringAspect>();
m_qmlViewerAspect->setLabelText(tr("QML Viewer:"));
- m_qmlViewerAspect->setPlaceHolderText(executable());
+ m_qmlViewerAspect->setPlaceHolderText(executable().toString());
m_qmlViewerAspect->setDisplayStyle(BaseStringAspect::LineEditDisplay);
m_qmlViewerAspect->setHistoryCompleter("QmlProjectManager.viewer.history");
@@ -292,7 +316,6 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
this, &QmlProjectRunConfiguration::updateEnabledState);
setOutputFormatter<QtSupport::QtOutputFormatter>();
-
connect(target, &Target::kitChanged,
this, &QmlProjectRunConfiguration::updateEnabledState);
@@ -303,9 +326,9 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
Runnable QmlProjectRunConfiguration::runnable() const
{
Runnable r;
- r.executable = executable();
+ r.executable = executable().toString();
r.commandLineArguments = commandLineArguments();
- r.environment = aspect<QmlProjectEnvironmentAspect>()->environment();
+ r.environment = aspect<EnvironmentAspect>()->environment();
r.workingDirectory = static_cast<QmlProject *>(project())->targetDirectory(target()).toString();
return r;
}
@@ -314,9 +337,9 @@ QString QmlProjectRunConfiguration::disabledReason() const
{
if (mainScript().isEmpty())
return tr("No script file to execute.");
- if (DeviceTypeKitInformation::deviceTypeId(target()->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(target()->kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE
- && !QFileInfo::exists(executable())) {
+ && !executable().exists()) {
return tr("No qmlscene found.");
}
if (executable().isEmpty())
@@ -324,17 +347,17 @@ QString QmlProjectRunConfiguration::disabledReason() const
return RunConfiguration::disabledReason();
}
-QString QmlProjectRunConfiguration::executable() const
+QString QmlProjectRunConfiguration::theExecutable() const
{
const QString qmlViewer = m_qmlViewerAspect->value();
if (!qmlViewer.isEmpty())
return qmlViewer;
- BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
+ BaseQtVersion *version = QtKitAspect::qtVersion(target()->kit());
if (!version) // No Qt version in Kit. Don't try to run qmlscene.
return QString();
- const Id deviceType = DeviceTypeKitInformation::deviceTypeId(target()->kit());
+ const Id deviceType = DeviceTypeKitAspect::deviceTypeId(target()->kit());
if (deviceType == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
// If not given explicitly by Qt Version, try to pick it from $PATH.
return version->type() == QtSupport::Constants::DESKTOPQT
@@ -342,7 +365,7 @@ QString QmlProjectRunConfiguration::executable() const
: QString("qmlscene");
}
- IDevice::ConstPtr dev = DeviceKitInformation::device(target()->kit());
+ IDevice::ConstPtr dev = DeviceKitAspect::device(target()->kit());
if (dev.isNull()) // No device set. We don't know where to run qmlscene.
return QString();
@@ -356,7 +379,7 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
// arguments in .user file
QString args = aspect<ArgumentsAspect>()->arguments(macroExpander());
const Target *currentTarget = target();
- const IDevice::ConstPtr device = DeviceKitInformation::device(currentTarget->kit());
+ const IDevice::ConstPtr device = DeviceKitAspect::device(currentTarget->kit());
const Utils::OsType osType = device ? device->osType() : Utils::HostOsInfo::hostOs();
// arguments from .qmlproject file
@@ -367,7 +390,12 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
Utils::QtcProcess::addArg(&args, importPath, osType);
}
- const QString main = project->targetFile(Utils::FileName::fromString(mainScript()),
+ for (const QString &fileSelector : project->customFileSelectors()) {
+ Utils::QtcProcess::addArg(&args, QLatin1String("-S"), osType);
+ Utils::QtcProcess::addArg(&args, fileSelector, osType);
+ }
+
+ const QString main = project->targetFile(Utils::FilePath::fromString(mainScript()),
currentTarget).toString();
if (!main.isEmpty())
Utils::QtcProcess::addArg(&args, main, osType);
@@ -376,16 +404,12 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
void QmlProjectRunConfiguration::updateEnabledState()
{
- bool qmlFileFound = m_mainQmlFileAspect->isQmlFilePresent();
- if (!qmlFileFound) {
- setEnabled(false);
- } else {
- const QString exe = executable();
- if (exe.isEmpty())
- setEnabled(false);
- else
- RunConfiguration::updateEnabledState();
+ bool enabled = false;
+ if (m_mainQmlFileAspect->isQmlFilePresent() && !executable().isEmpty()) {
+ Project *p = target()->project();
+ enabled = !p->isParsing() && p->hasParsingData();
}
+ setEnabled(enabled);
}
bool MainQmlFileAspect::isQmlFilePresent()
@@ -408,7 +432,7 @@ bool MainQmlFileAspect::isQmlFilePresent()
// find a qml file with lowercase filename. This is slow, but only done
// in initialization/other border cases.
const auto files = m_project->files(Project::AllFiles);
- for (const Utils::FileName &filename : files) {
+ for (const Utils::FilePath &filename : files) {
const QFileInfo fi = filename.toFileInfo();
if (!filename.isEmpty() && fi.baseName().at(0).isLower()) {
@@ -442,8 +466,6 @@ QmlProjectRunConfigurationFactory::QmlProjectRunConfigurationFactory()
registerRunConfiguration<QmlProjectRunConfiguration>
("QmlProjectManager.QmlRunConfiguration.QmlScene");
addSupportedProjectType(QmlProjectManager::Constants::QML_PROJECT_ID);
-
- addRunWorkerFactory<SimpleTargetRunner>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
}
} // namespace Internal
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
index adfd3103a7..8a18fd0ef9 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
@@ -47,7 +47,7 @@ private:
void updateEnabledState() final;
QString mainScript() const;
- QString executable() const;
+ QString theExecutable() const;
QString commandLineArguments() const;
ProjectExplorer::BaseStringAspect *m_qmlViewerAspect;
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp
deleted file mode 100644
index e5abbcc0b3..0000000000
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp
+++ /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.
-**
-****************************************************************************/
-
-#include "qmlprojectrunconfigurationfactory.h"
-#include "qmlprojectmanagerconstants.h"
-#include "qmlproject.h"
-#include "qmlprojectrunconfiguration.h"
-
-namespace QmlProjectManager {
-namespace Internal {
-
-QmlProjectRunConfigurationFactory::QmlProjectRunConfigurationFactory() :
- ProjectExplorer::FixedRunConfigurationFactory(QmlProjectRunConfiguration::tr("QML Scene"), false)
-{
- registerRunConfiguration<QmlProjectRunConfiguration>(Constants::QML_SCENE_RC_ID);
- addSupportedProjectType(QmlProjectManager::Constants::QML_PROJECT_ID);
-}
-
-} // namespace Internal
-} // namespace QmlProjectManager
-
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.h
deleted file mode 100644
index 0a94d3c4f3..0000000000
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.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/runconfiguration.h>
-
-namespace QmlProjectManager {
-namespace Internal {
-
-class QmlProjectRunConfigurationFactory : public ProjectExplorer::FixedRunConfigurationFactory
-{
-public:
- QmlProjectRunConfigurationFactory();
-};
-
-} // namespace Internal
-} // namespace QmlProjectManager
diff --git a/src/plugins/qnx/CMakeLists.txt b/src/plugins/qnx/CMakeLists.txt
new file mode 100644
index 0000000000..75a060d264
--- /dev/null
+++ b/src/plugins/qnx/CMakeLists.txt
@@ -0,0 +1,29 @@
+add_qtc_plugin(Qnx
+ DEPENDS QtcSsh QmlDebug Qt5::Xml
+ PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport RemoteLinux
+ SOURCES
+ qnx.qrc
+ qnx_export.h
+ qnxanalyzesupport.cpp qnxanalyzesupport.h
+ qnxbaseqtconfigwidget.cpp qnxbaseqtconfigwidget.h
+ qnxconfiguration.cpp qnxconfiguration.h
+ qnxconfigurationmanager.cpp qnxconfigurationmanager.h
+ qnxconstants.h
+ 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
+ qnxdevicewizard.cpp qnxdevicewizard.h
+ qnxplugin.cpp qnxplugin.h
+ qnxqtversion.cpp qnxqtversion.h
+ qnxrunconfiguration.cpp qnxrunconfiguration.h
+ qnxsettingspage.cpp qnxsettingspage.h
+ qnxsettingswidget.cpp qnxsettingswidget.h qnxsettingswidget.ui
+ qnxtoolchain.cpp qnxtoolchain.h
+ qnxutils.cpp qnxutils.h
+ qnxversionnumber.cpp qnxversionnumber.h
+ slog2inforunner.cpp slog2inforunner.h
+)
diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro
index eee23e08ca..fd9fffccf4 100644
--- a/src/plugins/qnx/qnx.pro
+++ b/src/plugins/qnx/qnx.pro
@@ -5,12 +5,10 @@ include(../../qtcreatorplugin.pri)
SOURCES += qnxplugin.cpp \
qnxbaseqtconfigwidget.cpp \
qnxutils.cpp \
- qnxdevicefactory.cpp \
qnxdevicewizard.cpp \
qnxrunconfiguration.cpp \
qnxanalyzesupport.cpp \
qnxdebugsupport.cpp \
- qnxqtversionfactory.cpp \
qnxqtversion.cpp \
qnxdevice.cpp \
qnxdevicetester.cpp \
@@ -30,12 +28,10 @@ HEADERS += qnxplugin.h\
qnxconstants.h \
qnxbaseqtconfigwidget.h \
qnxutils.h \
- qnxdevicefactory.h \
qnxdevicewizard.h \
qnxrunconfiguration.h \
qnxanalyzesupport.h \
qnxdebugsupport.h \
- qnxqtversionfactory.h \
qnxqtversion.h \
qnxdevice.h \
qnxdevicetester.h \
diff --git a/src/plugins/qnx/qnx.qbs b/src/plugins/qnx/qnx.qbs
index 2f29172038..3865766004 100644
--- a/src/plugins/qnx/qnx.qbs
+++ b/src/plugins/qnx/qnx.qbs
@@ -32,8 +32,6 @@ QtcPlugin {
"qnxdebugsupport.h",
"qnxdevice.cpp",
"qnxdevice.h",
- "qnxdevicefactory.cpp",
- "qnxdevicefactory.h",
"qnxdevicewizard.cpp",
"qnxdevicewizard.h",
"qnxdeviceprocesslist.cpp",
@@ -57,8 +55,6 @@ QtcPlugin {
"qnxplugin.h",
"qnxqtversion.cpp",
"qnxqtversion.h",
- "qnxqtversionfactory.cpp",
- "qnxqtversionfactory.h",
"qnxrunconfiguration.cpp",
"qnxrunconfiguration.h",
"qnxutils.cpp",
diff --git a/src/plugins/qnx/qnxconfiguration.cpp b/src/plugins/qnx/qnxconfiguration.cpp
index 0619b439b7..d05ae172ff 100644
--- a/src/plugins/qnx/qnxconfiguration.cpp
+++ b/src/plugins/qnx/qnxconfiguration.cpp
@@ -69,7 +69,7 @@ const QLatin1String SdpEnvFileKey("NDKEnvFile");
QnxConfiguration::QnxConfiguration() = default;
-QnxConfiguration::QnxConfiguration(const FileName &sdpEnvFile)
+QnxConfiguration::QnxConfiguration(const FilePath &sdpEnvFile)
{
setDefaultConfiguration(sdpEnvFile);
readInformation();
@@ -83,26 +83,26 @@ QnxConfiguration::QnxConfiguration(const QVariantMap &data)
m_version = QnxVersionNumber(data.value(QNXVersionKey).toString());
- setDefaultConfiguration(FileName::fromString(envFilePath));
+ setDefaultConfiguration(FilePath::fromString(envFilePath));
readInformation();
}
-FileName QnxConfiguration::envFile() const
+FilePath QnxConfiguration::envFile() const
{
return m_envFile;
}
-FileName QnxConfiguration::qnxTarget() const
+FilePath QnxConfiguration::qnxTarget() const
{
return m_qnxTarget;
}
-FileName QnxConfiguration::qnxHost() const
+FilePath QnxConfiguration::qnxHost() const
{
return m_qnxHost;
}
-FileName QnxConfiguration::qccCompilerPath() const
+FilePath QnxConfiguration::qccCompilerPath() const
{
return m_qccCompiler;
}
@@ -177,8 +177,8 @@ void QnxConfiguration::deactivate()
foreach (Kit *kit, KitManager::kits()) {
if (kit->isAutoDetected()
- && DeviceTypeKitInformation::deviceTypeId(kit) == Constants::QNX_QNX_OS_TYPE
- && toolChainsToRemove.contains(ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID)))
+ && DeviceTypeKitAspect::deviceTypeId(kit) == Constants::QNX_QNX_OS_TYPE
+ && toolChainsToRemove.contains(ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID)))
KitManager::deregisterKit(kit);
}
@@ -209,7 +209,7 @@ bool QnxConfiguration::canCreateKits() const
[this](const Target &target) -> bool { return qnxQtVersion(target); });
}
-FileName QnxConfiguration::sdpPath() const
+FilePath QnxConfiguration::sdpPath() const
{
return envFile().parentDir();
}
@@ -220,7 +220,7 @@ QnxQtVersion *QnxConfiguration::qnxQtVersion(const Target &target) const
QtVersionManager::instance()->versions(Utils::equal(&BaseQtVersion::type,
QString::fromLatin1(Constants::QNX_QNX_QT)))) {
auto qnxQt = dynamic_cast<QnxQtVersion *>(version);
- if (qnxQt && FileName::fromString(qnxQt->sdpPath()) == sdpPath()) {
+ if (qnxQt && FilePath::fromString(qnxQt->sdpPath()) == sdpPath()) {
foreach (const Abi &qtAbi, version->qtAbis()) {
if ((qtAbi == target.m_abi) && (qnxQt->cpuDir() == target.cpuDir()))
return qnxQt;
@@ -265,7 +265,8 @@ QVariant QnxConfiguration::createDebugger(const Target &target)
QnxToolChain *QnxConfiguration::createToolChain(const Target &target)
{
- auto toolChain = new QnxToolChain(ToolChain::AutoDetection);
+ auto toolChain = new QnxToolChain;
+ toolChain->setDetection(ToolChain::AutoDetection);
toolChain->setLanguage(ProjectExplorer::Constants::CXX_LANGUAGE_ID);
toolChain->setTargetAbi(target.m_abi);
toolChain->setDisplayName(
@@ -291,49 +292,45 @@ QList<ToolChain *> QnxConfiguration::findToolChain(const QList<ToolChain *> &alr
});
}
-ProjectExplorer::Kit *QnxConfiguration::createKit(
- const Target &target,
- QnxToolChain *toolChain,
- const QVariant &debugger)
+void QnxConfiguration::createKit(const Target &target, QnxToolChain *toolChain,
+ const QVariant &debugger)
{
QnxQtVersion *qnxQt = qnxQtVersion(target);
// Do not create incomplete kits if no qt qnx version found
if (!qnxQt)
- return nullptr;
-
- auto kit = std::make_unique<Kit>();
- Kit *kptr = kit.get();
+ return;
- QtKitInformation::setQtVersion(kptr, qnxQt);
- ToolChainKitInformation::setToolChain(kptr, toolChain);
- ToolChainKitInformation::clearToolChain(kptr, ProjectExplorer::Constants::C_LANGUAGE_ID);
+ const auto init = [&](Kit *k) {
+ QtKitAspect::setQtVersion(k, qnxQt);
+ ToolChainKitAspect::setToolChain(k, toolChain);
+ ToolChainKitAspect::clearToolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID);
- if (debugger.isValid())
- DebuggerKitInformation::setDebugger(kptr, debugger);
+ if (debugger.isValid())
+ DebuggerKitAspect::setDebugger(k, debugger);
- DeviceTypeKitInformation::setDeviceTypeId(kptr, Constants::QNX_QNX_OS_TYPE);
- // TODO: Add sysroot?
+ DeviceTypeKitAspect::setDeviceTypeId(k, Constants::QNX_QNX_OS_TYPE);
+ // TODO: Add sysroot?
- kit->setUnexpandedDisplayName(
- QCoreApplication::translate(
- "Qnx::Internal::QnxConfiguration",
- "Kit for %1 (%2)")
- .arg(displayName())
- .arg(target.shortDescription()));
+ k->setUnexpandedDisplayName(
+ QCoreApplication::translate(
+ "Qnx::Internal::QnxConfiguration",
+ "Kit for %1 (%2)")
+ .arg(displayName())
+ .arg(target.shortDescription()));
- kit->setAutoDetected(true);
- kit->setAutoDetectionSource(envFile().toString());
- kit->setMutable(DeviceKitInformation::id(), true);
+ k->setAutoDetected(true);
+ k->setAutoDetectionSource(envFile().toString());
+ k->setMutable(DeviceKitAspect::id(), true);
- kit->setSticky(ToolChainKitInformation::id(), true);
- kit->setSticky(DeviceTypeKitInformation::id(), true);
- kit->setSticky(SysRootKitInformation::id(), true);
- kit->setSticky(DebuggerKitInformation::id(), true);
- kit->setSticky(QmakeProjectManager::Constants::KIT_INFORMATION_ID, true);
+ k->setSticky(ToolChainKitAspect::id(), true);
+ k->setSticky(DeviceTypeKitAspect::id(), true);
+ k->setSticky(SysRootKitAspect::id(), true);
+ k->setSticky(DebuggerKitAspect::id(), true);
+ k->setSticky(QmakeProjectManager::Constants::KIT_INFORMATION_ID, true);
+ };
// add kit with device and qt version not sticky
- KitManager::registerKit(std::move(kit));
- return kptr;
+ KitManager::registerKit(init);
}
QStringList QnxConfiguration::validationErrors() const
@@ -357,14 +354,14 @@ void QnxConfiguration::setVersion(const QnxVersionNumber &version)
void QnxConfiguration::readInformation()
{
- QString qConfigPath = FileName(m_qnxConfiguration).appendPath("qconfig").toString();
+ const QString qConfigPath = m_qnxConfiguration.pathAppended("qconfig").toString();
QList <ConfigInstallInformation> installInfoList = QnxUtils::installedConfigs(qConfigPath);
if (installInfoList.isEmpty())
return;
foreach (const ConfigInstallInformation &info, installInfoList) {
- if (m_qnxHost == FileName::fromString(info.host)
- && m_qnxTarget == FileName::fromString(info.target)) {
+ if (m_qnxHost == FilePath::fromString(info.host)
+ && m_qnxTarget == FilePath::fromString(info.target)) {
m_configName = info.name;
setVersion(QnxVersionNumber(info.version));
break;
@@ -372,21 +369,21 @@ void QnxConfiguration::readInformation()
}
}
-void QnxConfiguration::setDefaultConfiguration(const Utils::FileName &envScript)
+void QnxConfiguration::setDefaultConfiguration(const Utils::FilePath &envScript)
{
QTC_ASSERT(!envScript.isEmpty(), return);
m_envFile = envScript;
m_qnxEnv = QnxUtils::qnxEnvironmentFromEnvFile(m_envFile.toString());
foreach (const EnvironmentItem &item, m_qnxEnv) {
if (item.name == QLatin1String("QNX_CONFIGURATION"))
- m_qnxConfiguration = FileName::fromString(item.value);
+ m_qnxConfiguration = FilePath::fromString(item.value);
else if (item.name == QLatin1String("QNX_TARGET"))
- m_qnxTarget = FileName::fromString(item.value);
+ m_qnxTarget = FilePath::fromString(item.value);
else if (item.name == QLatin1String("QNX_HOST"))
- m_qnxHost = FileName::fromString(item.value);
+ m_qnxHost = FilePath::fromString(item.value);
}
- FileName qccPath = FileName::fromString(HostOsInfo::withExecutableSuffix(
+ FilePath qccPath = FilePath::fromString(HostOsInfo::withExecutableSuffix(
m_qnxHost.toString() + QLatin1String("/usr/bin/qcc")));
if (qccPath.exists())
@@ -404,7 +401,7 @@ void QnxConfiguration::setDefaultConfiguration(const Utils::FileName &envScript)
}
const QnxConfiguration::Target *QnxConfiguration::findTargetByDebuggerPath(
- const FileName &path) const
+ const FilePath &path) const
{
auto it = std::find_if(m_targets.begin(), m_targets.end(),
[path](const Target &target) { return target.m_debuggerPath == path; });
@@ -421,13 +418,13 @@ void QnxConfiguration::updateTargets()
void QnxConfiguration::assignDebuggersToTargets()
{
- QDir hostUsrBinDir(FileName(m_qnxHost).appendPath("usr/bin").toString());
+ const QDir hostUsrBinDir(m_qnxHost.pathAppended("usr/bin").toString());
QStringList debuggerNames = hostUsrBinDir.entryList(
QStringList(HostOsInfo::withExecutableSuffix(QLatin1String("nto*-gdb"))),
QDir::Files);
foreach (const QString &debuggerName, debuggerNames) {
- FileName debuggerPath = FileName::fromString(hostUsrBinDir.path())
- .appendPath(debuggerName);
+ const FilePath debuggerPath = FilePath::fromString(hostUsrBinDir.path())
+ .pathAppended(debuggerName);
DebuggerItem item;
item.setCommand(debuggerPath);
item.reinitializeFromFile();
diff --git a/src/plugins/qnx/qnxconfiguration.h b/src/plugins/qnx/qnxconfiguration.h
index 613167a68c..ebb77c825f 100644
--- a/src/plugins/qnx/qnxconfiguration.h
+++ b/src/plugins/qnx/qnxconfiguration.h
@@ -54,13 +54,13 @@ class QnxConfiguration
{
public:
QnxConfiguration();
- QnxConfiguration(const Utils::FileName &sdpEnvFile);
+ QnxConfiguration(const Utils::FilePath &sdpEnvFile);
QnxConfiguration(const QVariantMap &data);
- Utils::FileName envFile() const;
- Utils::FileName qnxTarget() const;
- Utils::FileName qnxHost() const;
- Utils::FileName qccCompilerPath() const;
+ Utils::FilePath envFile() const;
+ Utils::FilePath qnxTarget() const;
+ Utils::FilePath qnxHost() const;
+ Utils::FilePath qccCompilerPath() const;
QList<Utils::EnvironmentItem> qnxEnv() const;
QnxVersionNumber version() const;
QVariantMap toMap() const;
@@ -72,7 +72,7 @@ public:
void deactivate();
bool isActive() const;
bool canCreateKits() const;
- Utils::FileName sdpPath() const;
+ Utils::FilePath sdpPath() const;
QList<ProjectExplorer::ToolChain *> autoDetect(
const QList<ProjectExplorer::ToolChain *> &alreadyKnown);
@@ -88,22 +88,22 @@ private:
void readInformation();
- void setDefaultConfiguration(const Utils::FileName &envScript);
+ void setDefaultConfiguration(const Utils::FilePath &envScript);
QString m_configName;
- Utils::FileName m_envFile;
- Utils::FileName m_qnxConfiguration;
- Utils::FileName m_qnxTarget;
- Utils::FileName m_qnxHost;
- Utils::FileName m_qccCompiler;
+ Utils::FilePath m_envFile;
+ Utils::FilePath m_qnxConfiguration;
+ Utils::FilePath m_qnxTarget;
+ Utils::FilePath m_qnxHost;
+ Utils::FilePath m_qccCompiler;
QList<Utils::EnvironmentItem> m_qnxEnv;
QnxVersionNumber m_version;
class Target
{
public:
- Target(const ProjectExplorer::Abi &abi, const Utils::FileName &path)
+ Target(const ProjectExplorer::Abi &abi, const Utils::FilePath &path)
: m_abi(abi), m_path(path)
{
}
@@ -112,8 +112,8 @@ private:
QString cpuDir() const;
ProjectExplorer::Abi m_abi;
- Utils::FileName m_path;
- Utils::FileName m_debuggerPath;
+ Utils::FilePath m_path;
+ Utils::FilePath m_debuggerPath;
};
QList<Target> m_targets;
@@ -123,11 +123,9 @@ private:
void createTools(const Target &target);
QVariant createDebugger(const Target &target);
QnxToolChain *createToolChain(const Target &target);
- ProjectExplorer::Kit *createKit(const Target &target,
- QnxToolChain *toolChain,
- const QVariant &debugger);
+ void createKit(const Target &target, QnxToolChain *toolChain, const QVariant &debugger);
- const Target *findTargetByDebuggerPath(const Utils::FileName &path) const;
+ const Target *findTargetByDebuggerPath(const Utils::FilePath &path) const;
void updateTargets();
void assignDebuggersToTargets();
diff --git a/src/plugins/qnx/qnxconfigurationmanager.cpp b/src/plugins/qnx/qnxconfigurationmanager.cpp
index 2f026bbcb5..f44313d233 100644
--- a/src/plugins/qnx/qnxconfigurationmanager.cpp
+++ b/src/plugins/qnx/qnxconfigurationmanager.cpp
@@ -36,9 +36,9 @@ const QLatin1String QNXConfigDataKey("QNXConfiguration.");
const QLatin1String QNXConfigCountKey("QNXConfiguration.Count");
const QLatin1String QNXConfigsFileVersionKey("Version");
-static Utils::FileName qnxConfigSettingsFileName()
+static Utils::FilePath qnxConfigSettingsFileName()
{
- return Utils::FileName::fromString(Core::ICore::userResourcePath() + QLatin1String("/qnx/")
+ return Utils::FilePath::fromString(Core::ICore::userResourcePath() + QLatin1String("/qnx/")
+ QLatin1String(Constants::QNX_CONFIGS_FILENAME));
}
@@ -94,7 +94,7 @@ bool QnxConfigurationManager::addConfiguration(QnxConfiguration *config)
return true;
}
-QnxConfiguration *QnxConfigurationManager::configurationFromEnvFile(const Utils::FileName &envFile) const
+QnxConfiguration *QnxConfigurationManager::configurationFromEnvFile(const Utils::FilePath &envFile) const
{
foreach (QnxConfiguration *c, m_configurations) {
if (c->envFile() == envFile)
diff --git a/src/plugins/qnx/qnxconfigurationmanager.h b/src/plugins/qnx/qnxconfigurationmanager.h
index 938a098250..83e148afa9 100644
--- a/src/plugins/qnx/qnxconfigurationmanager.h
+++ b/src/plugins/qnx/qnxconfigurationmanager.h
@@ -45,7 +45,7 @@ public:
QList<QnxConfiguration*> configurations() const;
void removeConfiguration(QnxConfiguration *config);
bool addConfiguration(QnxConfiguration *config);
- QnxConfiguration* configurationFromEnvFile(const Utils::FileName &envFile) const;
+ QnxConfiguration* configurationFromEnvFile(const Utils::FilePath &envFile) const;
protected slots:
void saveConfigs();
diff --git a/src/plugins/qnx/qnxconstants.h b/src/plugins/qnx/qnxconstants.h
index ecd31d6b3d..05c5a17618 100644
--- a/src/plugins/qnx/qnxconstants.h
+++ b/src/plugins/qnx/qnxconstants.h
@@ -41,7 +41,7 @@ const char QNX_QNX_RUNCONFIGURATION_PREFIX[] = "Qt4ProjectManager.QNX.QNXRunConf
const char QNX_QNX_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.QNX.QNXDeployConfiguration";
-const char QNX_QNX_OS_TYPE[] = "QnxOsType";
+const char QNX_QNX_OS_TYPE[] = "QnxOsType"; // Also used for device type.
const char QNX_DEBUG_EXECUTABLE[] = "pdebug";
diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp
index f53b27df36..0ea96961dc 100644
--- a/src/plugins/qnx/qnxdebugsupport.cpp
+++ b/src/plugins/qnx/qnxdebugsupport.cpp
@@ -72,7 +72,7 @@ namespace Internal {
static QStringList searchPaths(Kit *kit)
{
- auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(kit));
+ auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitAspect::qtVersion(kit));
if (!qtVersion)
return {};
@@ -85,10 +85,8 @@ static QStringList searchPaths(Kit *kit)
searchPaths << qtVersion->qmakeProperty("QT_INSTALL_PLUGINS") + '/' + dir;
searchPaths << qtVersion->qmakeProperty("QT_INSTALL_LIBS");
- searchPaths << qtVersion->qnxTarget().appendPath(qtVersion->cpuDir()).appendPath("lib")
- .toString();
- searchPaths << qtVersion->qnxTarget().appendPath(qtVersion->cpuDir()).appendPath("usr/lib")
- .toString();
+ searchPaths << qtVersion->qnxTarget().pathAppended(qtVersion->cpuDir() + "/lib").toString();
+ searchPaths << qtVersion->qnxTarget().pathAppended(qtVersion->cpuDir() + "/usr/lib").toString();
return searchPaths;
}
@@ -148,16 +146,13 @@ QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
addStartDependency(debuggeeRunner);
- auto runConfig = qobject_cast<QnxRunConfiguration *>(runControl->runConfiguration());
- QTC_ASSERT(runConfig, return);
- Target *target = runConfig->target();
- Kit *k = target->kit();
+ Kit *k = runControl->kit();
setStartMode(AttachToRemoteServer);
setCloseMode(KillAtClose);
setUseCtrlCStub(true);
setSolibSearchPath(searchPaths(k));
- if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(k)))
+ if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitAspect::qtVersion(k)))
setSysRoot(qtVersion->qnxTarget());
}
@@ -241,7 +236,7 @@ void QnxAttachDebugSupport::showProcessesDialog()
{
auto kitChooser = new KitChooser;
kitChooser->setKitPredicate([](const Kit *k) {
- return k->isValid() && DeviceTypeKitInformation::deviceTypeId(k) == Constants::QNX_QNX_OS_TYPE;
+ return k->isValid() && DeviceTypeKitAspect::deviceTypeId(k) == Constants::QNX_QNX_OS_TYPE;
});
QnxAttachDebugDialog dlg(kitChooser);
@@ -269,7 +264,8 @@ void QnxAttachDebugSupport::showProcessesDialog()
localExecutable = aspect->fileName().toString();
}
- auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ runControl->setRunConfiguration(runConfig);
auto debugger = new QnxAttachDebugSupport(runControl);
debugger->setStartMode(AttachToRemoteServer);
debugger->setCloseMode(DetachAtClose);
@@ -279,7 +275,7 @@ void QnxAttachDebugSupport::showProcessesDialog()
// setRunControlName(tr("Remote: \"%1\" - Process %2").arg(remoteChannel).arg(m_process.pid));
debugger->setRunControlName(tr("Remote QNX process %1").arg(pid));
debugger->setSolibSearchPath(searchPaths(kit));
- if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(kit)))
+ if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitAspect::qtVersion(kit)))
debugger->setSysRoot(qtVersion->qnxTarget());
debugger->setUseContinueInsteadOfRun(true);
diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
index 0e4a0b6ff5..aec85826a2 100644
--- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
+++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp
@@ -256,6 +256,11 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles(
if (dirPath.isEmpty())
return result;
+ static const QStringList unusedDirs = {"include", "mkspecs", "cmake", "pkgconfig"};
+ const QString dp = dirPath.endsWith('/') ? dirPath.left(dirPath.size() - 1) : dirPath;
+ if (unusedDirs.contains(dp))
+ return result;
+
QDir dir(dirPath);
QFileInfoList list = dir.entryInfoList(nameFilters,
QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
@@ -265,6 +270,10 @@ QList<DeployableFile> QnxDeployQtLibrariesDialog::gatherFiles(
result.append(gatherFiles(fileInfo.absoluteFilePath(), baseDirPath.isEmpty() ?
dirPath : baseDirPath));
} else {
+ static const QStringList unusedSuffixes = {"cmake", "la", "prl", "a", "pc"};
+ if (unusedSuffixes.contains(fileInfo.suffix()))
+ continue;
+
QString remoteDir;
if (baseDirPath.isEmpty()) {
remoteDir = fullRemoteDirectory() + QLatin1Char('/') +
@@ -292,12 +301,9 @@ void QnxDeployQtLibrariesDialog::checkRemoteDirectoryExistance()
QTC_CHECK(m_state == Inactive);
m_state = CheckingRemoteDirectory;
-
m_ui->deployLogWindow->appendPlainText(tr("Checking existence of \"%1\"")
.arg(fullRemoteDirectory()));
-
- const QByteArray cmd = "test -d " + fullRemoteDirectory().toLatin1();
- m_processRunner->run(cmd, m_device->sshParameters());
+ m_processRunner->run("test -d " + fullRemoteDirectory(), m_device->sshParameters());
}
void QnxDeployQtLibrariesDialog::removeRemoteDirectory()
@@ -305,11 +311,8 @@ void QnxDeployQtLibrariesDialog::removeRemoteDirectory()
QTC_CHECK(m_state == CheckingRemoteDirectory);
m_state = RemovingRemoteDirectory;
-
m_ui->deployLogWindow->appendPlainText(tr("Removing \"%1\"").arg(fullRemoteDirectory()));
-
- const QByteArray cmd = "rm -rf " + fullRemoteDirectory().toLatin1();
- m_processRunner->run(cmd, m_device->sshParameters());
+ m_processRunner->run("rm -rf " + fullRemoteDirectory(), m_device->sshParameters());
}
} // namespace Internal
diff --git a/src/plugins/qnx/qnxdevice.cpp b/src/plugins/qnx/qnxdevice.cpp
index 49cd195ccd..7794dbde1b 100644
--- a/src/plugins/qnx/qnxdevice.cpp
+++ b/src/plugins/qnx/qnxdevice.cpp
@@ -24,13 +24,17 @@
****************************************************************************/
#include "qnxdevice.h"
+
+#include "qnxconstants.h"
#include "qnxdevicetester.h"
#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 <ssh/sshconnection.h>
#include <utils/port.h>
@@ -46,8 +50,7 @@ using namespace ProjectExplorer;
using namespace Utils;
namespace Qnx {
-
-using namespace Internal;
+namespace Internal {
const char QnxVersionKey[] = "QnxVersion";
@@ -148,11 +151,6 @@ QVariantMap QnxDevice::toMap() const
return map;
}
-IDevice::Ptr QnxDevice::clone() const
-{
- return Ptr(new QnxDevice(*this));
-}
-
PortsGatheringMethod::Ptr QnxDevice::portsGatheringMethod() const
{
return PortsGatheringMethod::Ptr(new QnxPortsGatheringMethod);
@@ -179,4 +177,25 @@ DeviceProcessSignalOperation::Ptr QnxDevice::signalOperation() const
new QnxDeviceProcessSignalOperation(sshParameters()));
}
+// Factory
+
+QnxDeviceFactory::QnxDeviceFactory()
+ : ProjectExplorer::IDeviceFactory(Constants::QNX_QNX_OS_TYPE)
+{
+ setDisplayName(tr("QNX Device"));
+ setCombinedIcon(":/qnx/images/qnxdevicesmall.png",
+ ":/qnx/images/qnxdevice.png");
+ setCanCreate(true);
+ setConstructionFunction(&QnxDevice::create);
+}
+
+ProjectExplorer::IDevice::Ptr QnxDeviceFactory::create() const
+{
+ QnxDeviceWizard wizard;
+ if (wizard.exec() != QDialog::Accepted)
+ return ProjectExplorer::IDevice::Ptr();
+ return wizard.device();
+}
+
+} // namespace Internal
} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdevice.h b/src/plugins/qnx/qnxdevice.h
index 5a120d92b1..ae6a268143 100644
--- a/src/plugins/qnx/qnxdevice.h
+++ b/src/plugins/qnx/qnxdevice.h
@@ -30,8 +30,9 @@
#include <remotelinux/linuxdevice.h>
namespace Qnx {
+namespace Internal {
-class QNX_EXPORT QnxDevice : public RemoteLinux::LinuxDevice
+class QnxDevice : public RemoteLinux::LinuxDevice
{
Q_DECLARE_TR_FUNCTIONS(Qnx::Internal::QnxDevice)
@@ -40,7 +41,6 @@ public:
using ConstPtr = QSharedPointer<const QnxDevice>;
static Ptr create() { return Ptr(new QnxDevice); }
- ProjectExplorer::IDevice::Ptr clone() const override;
ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const override;
ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const override;
@@ -69,4 +69,15 @@ private:
mutable int m_versionNumber = 0;
};
+class QnxDeviceFactory : public ProjectExplorer::IDeviceFactory
+{
+ Q_OBJECT
+
+public:
+ QnxDeviceFactory();
+
+ ProjectExplorer::IDevice::Ptr create() const override;
+};
+
+} // namespace Internal
} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdevicefactory.cpp b/src/plugins/qnx/qnxdevicefactory.cpp
deleted file mode 100644
index 02e2e45465..0000000000
--- a/src/plugins/qnx/qnxdevicefactory.cpp
+++ /dev/null
@@ -1,61 +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 "qnxdevicefactory.h"
-
-#include "qnxconstants.h"
-#include "qnxdevicewizard.h"
-#include "qnxdevice.h"
-
-#include <utils/qtcassert.h>
-
-namespace Qnx {
-namespace Internal {
-
-QnxDeviceFactory::QnxDeviceFactory()
- : ProjectExplorer::IDeviceFactory(Constants::QNX_QNX_OS_TYPE)
-{
- setDisplayName(tr("QNX Device"));
- setCombinedIcon(":/qnx/images/qnxdevicesmall.png",
- ":/qnx/images/qnxdevice.png");
- setCanCreate(true);
- setConstructionFunction(&QnxDevice::create);
-}
-
-ProjectExplorer::IDevice::Ptr QnxDeviceFactory::create() const
-{
- QnxDeviceWizard wizard;
- if (wizard.exec() != QDialog::Accepted)
- return ProjectExplorer::IDevice::Ptr();
- return wizard.device();
-}
-
-Core::Id QnxDeviceFactory::deviceType()
-{
- return Core::Id(Constants::QNX_QNX_OS_TYPE);
-}
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdevicefactory.h b/src/plugins/qnx/qnxdevicefactory.h
deleted file mode 100644
index 9b08ec5efe..0000000000
--- a/src/plugins/qnx/qnxdevicefactory.h
+++ /dev/null
@@ -1,46 +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 <projectexplorer/devicesupport/idevicefactory.h>
-
-namespace Qnx {
-namespace Internal {
-
-class QnxDeviceFactory : public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-
-public:
- QnxDeviceFactory();
-
- ProjectExplorer::IDevice::Ptr create() const override;
-
- static Core::Id deviceType();
-};
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdeviceprocess.cpp b/src/plugins/qnx/qnxdeviceprocess.cpp
index 5a2b5ecfd3..46067672dc 100644
--- a/src/plugins/qnx/qnxdeviceprocess.cpp
+++ b/src/plugins/qnx/qnxdeviceprocess.cpp
@@ -26,6 +26,7 @@
#include "qnxdeviceprocess.h"
#include <projectexplorer/devicesupport/sshdeviceprocess.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/qtcprocess.h>
diff --git a/src/plugins/qnx/qnxdeviceprocesssignaloperation.h b/src/plugins/qnx/qnxdeviceprocesssignaloperation.h
index b51eb9c847..be3795bba0 100644
--- a/src/plugins/qnx/qnxdeviceprocesssignaloperation.h
+++ b/src/plugins/qnx/qnxdeviceprocesssignaloperation.h
@@ -28,8 +28,6 @@
#include <remotelinux/remotelinuxsignaloperation.h>
namespace Qnx {
-class QnxDevice;
-
namespace Internal {
class QnxDeviceProcessSignalOperation : public RemoteLinux::RemoteLinuxSignalOperation
@@ -42,7 +40,7 @@ private:
QString killProcessByNameCommandLine(const QString &filePath) const override;
QString interruptProcessByNameCommandLine(const QString &filePath) const override;
- friend class Qnx::QnxDevice;
+ friend class QnxDevice;
};
} // namespace Internal
diff --git a/src/plugins/qnx/qnxdevicetester.cpp b/src/plugins/qnx/qnxdevicetester.cpp
index b1374519d8..5196043ad2 100644
--- a/src/plugins/qnx/qnxdevicetester.cpp
+++ b/src/plugins/qnx/qnxdevicetester.cpp
@@ -113,8 +113,7 @@ void QnxDeviceTester::handleGenericTestFinished(TestResult result)
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")
- .toLatin1(),
+ .arg("/var/run/qtc_xxxx.pid"),
m_deviceConfiguration->sshParameters());
}
@@ -189,7 +188,7 @@ void QnxDeviceTester::testNextCommand()
QString command = m_commandsToTest[m_currentCommandIndex];
emit progressMessage(tr("Checking for %1...").arg(command));
- m_processRunner->run("command -v " + command.toLatin1(), m_deviceConfiguration->sshParameters());
+ m_processRunner->run("command -v " + command, m_deviceConfiguration->sshParameters());
}
void QnxDeviceTester::setFinished()
diff --git a/src/plugins/qnx/qnxplugin.cpp b/src/plugins/qnx/qnxplugin.cpp
index e316742f2c..06f2701715 100644
--- a/src/plugins/qnx/qnxplugin.cpp
+++ b/src/plugins/qnx/qnxplugin.cpp
@@ -30,9 +30,7 @@
#include "qnxconstants.h"
#include "qnxdebugsupport.h"
#include "qnxdevice.h"
-#include "qnxdevicefactory.h"
#include "qnxqtversion.h"
-#include "qnxqtversionfactory.h"
#include "qnxrunconfiguration.h"
#include "qnxsettingspage.h"
#include "qnxtoolchain.h"
@@ -89,7 +87,7 @@ public:
setConfigBaseId(Constants::QNX_QNX_DEPLOYCONFIGURATION_ID);
setDefaultDisplayName(QCoreApplication::translate("Qnx::Internal::QnxDeployConfiguration",
"Deploy to QNX Device"));
- addSupportedTargetDeviceType(QnxDeviceFactory::deviceType());
+ addSupportedTargetDeviceType(Constants::QNX_QNX_OS_TYPE);
setUseDeploymentDataView();
addInitialStep(DeviceCheckBuildStep::stepId());
@@ -116,6 +114,13 @@ public:
QnxRunConfigurationFactory runConfigFactory;
QnxSettingsPage settingsPage;
QnxToolChainFactory toolChainFactory;
+
+ SimpleRunWorkerFactory<SimpleTargetRunner, QnxRunConfiguration>
+ runWorkerFactory{ProjectExplorer::Constants::NORMAL_RUN_MODE};
+ SimpleRunWorkerFactory<QnxDebugSupport, QnxRunConfiguration>
+ debugWorkerFactory{ProjectExplorer::Constants::DEBUG_RUN_MODE};
+ SimpleRunWorkerFactory<QnxQmlProfilerSupport, QnxRunConfiguration>
+ qmlProfilerWorkerFactory;
};
static QnxPluginPrivate *dd = nullptr;
@@ -132,24 +137,6 @@ bool QnxPlugin::initialize(const QStringList &arguments, QString *errorString)
dd = new QnxPluginPrivate;
- auto constraint = [](RunConfiguration *runConfig) {
- if (!runConfig->isEnabled()
- || !runConfig->id().name().startsWith(Constants::QNX_QNX_RUNCONFIGURATION_PREFIX)) {
- return false;
- }
-
- auto dev = DeviceKitInformation::device(runConfig->target()->kit())
- .dynamicCast<const QnxDevice>();
- return !dev.isNull();
- };
-
- RunControl::registerWorker<SimpleTargetRunner>
- (ProjectExplorer::Constants::NORMAL_RUN_MODE, constraint);
- RunControl::registerWorker<QnxDebugSupport>
- (ProjectExplorer::Constants::DEBUG_RUN_MODE, constraint);
- RunControl::registerWorker<QnxQmlProfilerSupport>
- (ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, constraint);
-
return true;
}
@@ -174,15 +161,11 @@ void QnxPlugin::extensionsInitialized()
void QnxPluginPrivate::updateDebuggerActions()
{
- bool hasValidQnxKit = false;
-
- auto matcher = DeviceTypeKitInformation::deviceTypePredicate(Constants::QNX_QNX_OS_TYPE);
- foreach (Kit *qnxKit, KitManager::kits(matcher)) {
- if (qnxKit->isValid() && !DeviceKitInformation::device(qnxKit).isNull()) {
- hasValidQnxKit = true;
- break;
- }
- }
+ const bool hasValidQnxKit = KitManager::kit([](const Kit *kit) {
+ return kit->isValid()
+ && DeviceTypeKitAspect::deviceTypeId(kit) == Constants::QNX_QNX_OS_TYPE
+ && !DeviceKitAspect::device(kit).isNull();
+ }) != nullptr;
m_attachToQnxApplication.setVisible(hasValidQnxKit);
m_debugSeparator->setVisible(hasValidQnxKit);
diff --git a/src/plugins/qnx/qnxqtversion.cpp b/src/plugins/qnx/qnxqtversion.cpp
index 7e8540139b..ffddcf7811 100644
--- a/src/plugins/qnx/qnxqtversion.cpp
+++ b/src/plugins/qnx/qnxqtversion.cpp
@@ -46,23 +46,6 @@ static char SDP_PATH_KEY[] = "SDKPath";
QnxQtVersion::QnxQtVersion() = default;
-QnxQtVersion::QnxQtVersion(const Utils::FileName &path, bool isAutoDetected,
- const QString &autoDetectionSource) :
- QtSupport::BaseQtVersion(path, isAutoDetected, autoDetectionSource)
-{
- setUnexpandedDisplayName(defaultUnexpandedDisplayName(path, false));
-}
-
-QnxQtVersion *QnxQtVersion::clone() const
-{
- return new QnxQtVersion(*this);
-}
-
-QString QnxQtVersion::type() const
-{
- return QLatin1String(Constants::QNX_QNX_QT);
-}
-
QString QnxQtVersion::description() const
{
//: Qt Version is meant for QNX
@@ -97,17 +80,17 @@ QString QnxQtVersion::qnxHost() const
return QString();
}
-Utils::FileName QnxQtVersion::qnxTarget() const
+Utils::FilePath QnxQtVersion::qnxTarget() const
{
if (!m_environmentUpToDate)
updateEnvironment();
foreach (const Utils::EnvironmentItem &item, m_qnxEnv) {
if (item.name == QLatin1String(Constants::QNX_TARGET_KEY))
- return Utils::FileName::fromUserInput(item.value);
+ return Utils::FilePath::fromUserInput(item.value);
}
- return Utils::FileName();
+ return Utils::FilePath();
}
QString QnxQtVersion::cpuDir() const
@@ -135,10 +118,10 @@ void QnxQtVersion::fromMap(const QVariantMap &map)
setSdpPath(QDir::fromNativeSeparators(map.value(QLatin1String(SDP_PATH_KEY)).toString()));
}
-QList<ProjectExplorer::Abi> QnxQtVersion::detectQtAbis() const
+ProjectExplorer::Abis QnxQtVersion::detectQtAbis() const
{
ensureMkSpecParsed();
- return QnxUtils::convertAbis(qtAbisFromLibrary(qtCorePaths()));
+ return QnxUtils::convertAbis(BaseQtVersion::detectQtAbis());
}
void QnxQtVersion::addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const
@@ -206,5 +189,16 @@ QList<Utils::EnvironmentItem> QnxQtVersion::environment() const
return QnxUtils::qnxEnvironment(sdpPath());
}
+
+// Factory
+
+QnxQtVersionFactory::QnxQtVersionFactory()
+{
+ setQtVersionCreator([] { return new QnxQtVersion; });
+ setSupportedType(Constants::QNX_QNX_QT);
+ setPriority(50);
+ setRestrictionChecker([](const SetupData &setup) { return setup.isQnx; });
+}
+
} // namespace Internal
} // namespace Qnx
diff --git a/src/plugins/qnx/qnxqtversion.h b/src/plugins/qnx/qnxqtversion.h
index 6bea0ed4b1..6479954bf8 100644
--- a/src/plugins/qnx/qnxqtversion.h
+++ b/src/plugins/qnx/qnxqtversion.h
@@ -29,6 +29,7 @@
#include "qnxqtversion.h"
#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtversionfactory.h>
#include <utils/environment.h>
@@ -39,12 +40,6 @@ class QnxQtVersion : public QtSupport::BaseQtVersion
{
public:
QnxQtVersion();
- QnxQtVersion(const Utils::FileName &path,
- bool isAutoDetected = false,
- const QString &autoDetectionSource = QString());
- QnxQtVersion *clone() const override;
-
- QString type() const override;
QString description() const override;
@@ -52,14 +47,14 @@ public:
QSet<Core::Id> targetDeviceTypes() const override;
QString qnxHost() const;
- Utils::FileName qnxTarget() const;
+ Utils::FilePath qnxTarget() const;
QString cpuDir() const;
QVariantMap toMap() const override;
void fromMap(const QVariantMap &map) override;
- QList<ProjectExplorer::Abi> detectQtAbis() const override;
+ ProjectExplorer::Abis detectQtAbis() const override;
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const override;
Utils::Environment qmakeRunEnvironment() const override;
@@ -87,5 +82,11 @@ private:
mutable QList<Utils::EnvironmentItem> m_qnxEnv;
};
+class QnxQtVersionFactory : public QtSupport::QtVersionFactory
+{
+public:
+ QnxQtVersionFactory();
+};
+
} // namespace Internal
} // namespace Qnx
diff --git a/src/plugins/qnx/qnxqtversionfactory.cpp b/src/plugins/qnx/qnxqtversionfactory.cpp
deleted file mode 100644
index abf2743cc8..0000000000
--- a/src/plugins/qnx/qnxqtversionfactory.cpp
+++ /dev/null
@@ -1,79 +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 "qnxqtversionfactory.h"
-
-#include "qnxconstants.h"
-#include "qnxutils.h"
-#include "qnxqtversion.h"
-
-#include <qtsupport/profilereader.h>
-
-#include <QFileInfo>
-
-using namespace Qnx;
-using namespace Qnx::Internal;
-
-QnxQtVersionFactory::QnxQtVersionFactory(QObject *parent) :
- QtSupport::QtVersionFactory(parent)
-{
-}
-
-QnxQtVersionFactory::~QnxQtVersionFactory() = default;
-
-bool QnxQtVersionFactory::canRestore(const QString &type)
-{
- return type == QLatin1String(Constants::QNX_QNX_QT);
-}
-
-QtSupport::BaseQtVersion *QnxQtVersionFactory::restore(const QString &type, const QVariantMap &data)
-{
- if (!canRestore(type))
- return nullptr;
- auto v = new QnxQtVersion;
- v->fromMap(data);
- return v;
-}
-
-int QnxQtVersionFactory::priority() const
-{
- return 50;
-}
-
-QtSupport::BaseQtVersion *QnxQtVersionFactory::create(const Utils::FileName &qmakePath,
- ProFileEvaluator *evaluator,
- bool isAutoDetected,
- const QString &autoDetectionSource)
-{
- QFileInfo fi = qmakePath.toFileInfo();
- if (!fi.exists() || !fi.isExecutable() || !fi.isFile())
- return nullptr;
-
- if (evaluator->contains(QLatin1String("QNX_CPUDIR"))) {
- return new QnxQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
- }
-
- return nullptr;
-}
diff --git a/src/plugins/qnx/qnxqtversionfactory.h b/src/plugins/qnx/qnxqtversionfactory.h
deleted file mode 100644
index e15165be42..0000000000
--- a/src/plugins/qnx/qnxqtversionfactory.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 <qtsupport/qtversionfactory.h>
-
-namespace Qnx {
-namespace Internal {
-
-class QnxQtVersionFactory : public QtSupport::QtVersionFactory
-{
- Q_OBJECT
-public:
- explicit QnxQtVersionFactory(QObject *parent = nullptr);
- ~QnxQtVersionFactory() override;
-
- bool canRestore(const QString &type) override;
- QtSupport::BaseQtVersion *restore(const QString &type, const QVariantMap &data) override;
-
- int priority() const override;
- QtSupport::BaseQtVersion *create(const Utils::FileName &qmakePath,
- ProFileEvaluator *evaluator,
- bool isAutoDetected = false,
- const QString &autoDetectionSource = QString()) override;
-};
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxrunconfiguration.cpp b/src/plugins/qnx/qnxrunconfiguration.cpp
index f9aa3b93fc..d098daabb8 100644
--- a/src/plugins/qnx/qnxrunconfiguration.cpp
+++ b/src/plugins/qnx/qnxrunconfiguration.cpp
@@ -27,6 +27,8 @@
#include "qnxconstants.h"
+#include <projectexplorer/runcontrol.h>
+
using namespace ProjectExplorer;
using namespace RemoteLinux;
diff --git a/src/plugins/qnx/qnxsettingswidget.cpp b/src/plugins/qnx/qnxsettingswidget.cpp
index 6ca598db6a..cafc639ce7 100644
--- a/src/plugins/qnx/qnxsettingswidget.cpp
+++ b/src/plugins/qnx/qnxsettingswidget.cpp
@@ -49,7 +49,7 @@ QnxSettingsWidget::QnxSettingsWidget(QWidget *parent) :
this, &QnxSettingsWidget::addConfiguration);
connect(m_ui->removeButton, &QAbstractButton::clicked,
this, &QnxSettingsWidget::removeConfiguration);
- connect(m_ui->configsCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->configsCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &QnxSettingsWidget::updateInformation);
connect(m_ui->generateKitsCheckBox, &QAbstractButton::toggled,
this, &QnxSettingsWidget::generateKits);
@@ -83,7 +83,7 @@ void QnxSettingsWidget::addConfiguration()
if (envFile.isEmpty())
return;
- QnxConfiguration *config = new QnxConfiguration(Utils::FileName::fromString(envFile));
+ QnxConfiguration *config = new QnxConfiguration(Utils::FilePath::fromString(envFile));
if (m_qnxConfigManager->configurations().contains(config)
|| !config->isValid()) {
QMessageBox::warning(Core::ICore::mainWindow(), tr("Warning"),
diff --git a/src/plugins/qnx/qnxtoolchain.cpp b/src/plugins/qnx/qnxtoolchain.cpp
index 8dc621442c..0a515287ea 100644
--- a/src/plugins/qnx/qnxtoolchain.cpp
+++ b/src/plugins/qnx/qnxtoolchain.cpp
@@ -44,16 +44,16 @@ namespace Internal {
static const char CompilerSdpPath[] = "Qnx.QnxToolChain.NDKPath";
static const char CpuDirKey[] = "Qnx.QnxToolChain.CpuDir";
-static QList<Abi> detectTargetAbis(const FileName &sdpPath)
+static Abis detectTargetAbis(const FilePath &sdpPath)
{
- QList<Abi> result;
- FileName qnxTarget;
+ Abis result;
+ FilePath qnxTarget;
if (!sdpPath.fileName().isEmpty()) {
QList<Utils::EnvironmentItem> environment = QnxUtils::qnxEnvironment(sdpPath.toString());
foreach (const Utils::EnvironmentItem &item, environment) {
- if (item.name == QLatin1Literal("QNX_TARGET"))
- qnxTarget = FileName::fromString(item.value);
+ if (item.name == QLatin1String("QNX_TARGET"))
+ qnxTarget = FilePath::fromString(item.value);
}
}
@@ -100,19 +100,12 @@ static QStringList reinterpretOptions(const QStringList &args)
return arguments;
}
-QnxToolChain::QnxToolChain(ToolChain::Detection d)
- : GccToolChain(Constants::QNX_TOOLCHAIN_ID, d)
+QnxToolChain::QnxToolChain()
+ : GccToolChain(Constants::QNX_TOOLCHAIN_ID)
{
setOptionsReinterpreter(&reinterpretOptions);
}
-QnxToolChain::QnxToolChain(Core::Id l, ToolChain::Detection d)
- : QnxToolChain(d)
-{
- setLanguage(l);
-}
-
-
QString QnxToolChain::typeDisplayName() const
{
return QnxToolChainFactory::tr("QCC");
@@ -131,15 +124,14 @@ void QnxToolChain::addToEnvironment(Environment &env) const
GccToolChain::addToEnvironment(env);
}
-FileNameList QnxToolChain::suggestedMkspecList() const
+QStringList QnxToolChain::suggestedMkspecList() const
{
- FileNameList mkspecList;
- mkspecList << FileName::fromLatin1("qnx-armle-v7-qcc");
- mkspecList << FileName::fromLatin1("qnx-x86-qcc");
- mkspecList << FileName::fromLatin1("qnx-aarch64le-qcc");
- mkspecList << FileName::fromLatin1("qnx-x86-64-qcc");
-
- return mkspecList;
+ return {
+ "qnx-armle-v7-qcc",
+ "qnx-x86-qcc",
+ "qnx-aarch64le-qcc",
+ "qnx-x86-64-qcc"
+ };
}
QVariantMap QnxToolChain::toMap() const
@@ -193,7 +185,7 @@ void QnxToolChain::setCpuDir(const QString &cpuDir)
GccToolChain::DetectedAbisResult QnxToolChain::detectSupportedAbis() const
{
- return detectTargetAbis(FileName::fromString(m_sdpPath));
+ return detectTargetAbis(FilePath::fromString(m_sdpPath));
}
bool QnxToolChain::operator ==(const ToolChain &other) const
@@ -213,6 +205,10 @@ bool QnxToolChain::operator ==(const ToolChain &other) const
QnxToolChainFactory::QnxToolChainFactory()
{
setDisplayName(tr("QCC"));
+ setSupportedToolChainType(Constants::QNX_TOOLCHAIN_ID);
+ setSupportedLanguages({ProjectExplorer::Constants::CXX_LANGUAGE_ID});
+ setToolchainConstructor([] { return new QnxToolChain; });
+ setUserCreatable(true);
}
QList<ProjectExplorer::ToolChain *> QnxToolChainFactory::autoDetect(
@@ -226,36 +222,6 @@ QList<ProjectExplorer::ToolChain *> QnxToolChainFactory::autoDetect(
return tcs;
}
-QSet<Core::Id> QnxToolChainFactory::supportedLanguages() const
-{
- return {ProjectExplorer::Constants::CXX_LANGUAGE_ID};
-}
-
-bool QnxToolChainFactory::canRestore(const QVariantMap &data)
-{
- return typeIdFromMap(data) == Constants::QNX_TOOLCHAIN_ID;
-}
-
-ToolChain *QnxToolChainFactory::restore(const QVariantMap &data)
-{
- auto tc = new QnxToolChain(ToolChain::ManualDetection);
- if (tc->fromMap(data))
- return tc;
-
- delete tc;
- return nullptr;
-}
-
-bool QnxToolChainFactory::canCreate()
-{
- return true;
-}
-
-ToolChain *QnxToolChainFactory::create(Core::Id l)
-{
- return new QnxToolChain(l, ToolChain::ManualDetection);
-}
-
//---------------------------------------------------------------------------------
// QnxToolChainConfigWidget
//---------------------------------------------------------------------------------
@@ -276,7 +242,7 @@ QnxToolChainConfigWidget::QnxToolChainConfigWidget(QnxToolChain *tc)
m_sdpPath->setPath(tc->sdpPath());
m_sdpPath->setEnabled(!tc->isAutoDetected());
- QList<Abi> abiList = detectTargetAbis(m_sdpPath->fileName());
+ const Abis abiList = detectTargetAbis(m_sdpPath->fileName());
m_abiWidget->setAbis(abiList, tc->targetAbi());
m_abiWidget->setEnabled(!tc->isAutoDetected() && !abiList.isEmpty());
@@ -328,9 +294,9 @@ bool QnxToolChainConfigWidget::isDirtyImpl() const
void QnxToolChainConfigWidget::handleSdpPathChange()
{
- Abi currentAbi = m_abiWidget->currentAbi();
- bool customAbi = m_abiWidget->isCustomAbi();
- QList<Abi> abiList = detectTargetAbis(m_sdpPath->fileName());
+ const Abi currentAbi = m_abiWidget->currentAbi();
+ const bool customAbi = m_abiWidget->isCustomAbi();
+ const Abis abiList = detectTargetAbis(m_sdpPath->fileName());
m_abiWidget->setEnabled(!abiList.isEmpty());
diff --git a/src/plugins/qnx/qnxtoolchain.h b/src/plugins/qnx/qnxtoolchain.h
index 8474714b78..b514ac15f3 100644
--- a/src/plugins/qnx/qnxtoolchain.h
+++ b/src/plugins/qnx/qnxtoolchain.h
@@ -34,15 +34,14 @@ namespace Internal {
class QnxToolChain : public ProjectExplorer::GccToolChain
{
public:
- explicit QnxToolChain(Detection d);
- explicit QnxToolChain(Core::Id l, Detection d);
+ QnxToolChain();
QString typeDisplayName() const override;
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() override;
void addToEnvironment(Utils::Environment &env) const override;
- Utils::FileNameList suggestedMkspecList() const override;
+ QStringList suggestedMkspecList() const override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &data) override;
@@ -75,14 +74,6 @@ public:
QList<ProjectExplorer::ToolChain *> autoDetect(
const QList<ProjectExplorer::ToolChain *> &alreadyKnown) override;
-
- QSet<Core::Id> supportedLanguages() const override;
-
- bool canRestore(const QVariantMap &data) override;
- ProjectExplorer::ToolChain *restore(const QVariantMap &data) override;
-
- bool canCreate() override;
- ProjectExplorer::ToolChain *create(Core::Id l) override;
};
//----------------------------------------------------------------------------
diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp
index 8178c33f09..9d61864558 100644
--- a/src/plugins/qnx/qnxutils.cpp
+++ b/src/plugins/qnx/qnxutils.cpp
@@ -211,7 +211,7 @@ QList<Utils::EnvironmentItem> QnxUtils::qnxEnvironment(const QString &sdpPath)
return qnxEnvironmentFromEnvFile(envFilePath(sdpPath));
}
-QList<QnxTarget> QnxUtils::findTargets(const Utils::FileName &basePath)
+QList<QnxTarget> QnxUtils::findTargets(const Utils::FilePath &basePath)
{
using namespace Utils;
QList<QnxTarget> result;
@@ -219,7 +219,7 @@ QList<QnxTarget> QnxUtils::findTargets(const Utils::FileName &basePath)
QDirIterator iterator(basePath.toString());
while (iterator.hasNext()) {
iterator.next();
- FileName libc = FileName::fromString(iterator.filePath()).appendPath("lib/libc.so");
+ const FilePath libc = FilePath::fromString(iterator.filePath()).pathAppended("lib/libc.so");
if (libc.exists()) {
auto abis = Abi::abisOfBinary(libc);
if (abis.isEmpty()) {
@@ -230,7 +230,7 @@ QList<QnxTarget> QnxUtils::findTargets(const Utils::FileName &basePath)
if (abis.count() > 1)
qWarning() << libc << "has more than one ABI ... processing all";
- FileName path = FileName::fromString(iterator.filePath());
+ FilePath path = FilePath::fromString(iterator.filePath());
for (Abi abi : abis)
result.append(QnxTarget(path, QnxUtils::convertAbi(abi)));
}
@@ -251,7 +251,7 @@ Abi QnxUtils::convertAbi(const Abi &abi)
return abi;
}
-QList<Abi> QnxUtils::convertAbis(const QList<Abi> &abis)
+Abis QnxUtils::convertAbis(const Abis &abis)
{
return Utils::transform(abis, &QnxUtils::convertAbi);
}
diff --git a/src/plugins/qnx/qnxutils.h b/src/plugins/qnx/qnxutils.h
index 505a1a5bff..ae8367e43b 100644
--- a/src/plugins/qnx/qnxutils.h
+++ b/src/plugins/qnx/qnxutils.h
@@ -57,11 +57,11 @@ public:
class QnxTarget
{
public:
- QnxTarget(const Utils::FileName &path, const ProjectExplorer::Abi &abi) :
+ QnxTarget(const Utils::FilePath &path, const ProjectExplorer::Abi &abi) :
m_path(path), m_abi(abi)
{
}
- Utils::FileName m_path;
+ Utils::FilePath m_path;
ProjectExplorer::Abi m_abi;
};
@@ -75,9 +75,9 @@ public:
static QString defaultTargetVersion(const QString &sdpPath);
static QList<ConfigInstallInformation> installedConfigs(const QString &configPath = QString());
static QList<Utils::EnvironmentItem> qnxEnvironment(const QString &sdpPath);
- static QList<QnxTarget> findTargets(const Utils::FileName &basePath);
+ static QList<QnxTarget> findTargets(const Utils::FilePath &basePath);
static ProjectExplorer::Abi convertAbi(const ProjectExplorer::Abi &abi);
- static QList<ProjectExplorer::Abi> convertAbis(const QList<ProjectExplorer::Abi> &abis);
+ static ProjectExplorer::Abis convertAbis(const ProjectExplorer::Abis &abis);
};
} // namespace Internal
diff --git a/src/plugins/qnx/slog2inforunner.cpp b/src/plugins/qnx/slog2inforunner.cpp
index 113d589a3c..aec6d74a6f 100644
--- a/src/plugins/qnx/slog2inforunner.cpp
+++ b/src/plugins/qnx/slog2inforunner.cpp
@@ -45,7 +45,7 @@ Slog2InfoRunner::Slog2InfoRunner(RunControl *runControl)
: RunWorker(runControl)
{
setId("Slog2InfoRunner");
- m_applicationId = runControl->runConfiguration()->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.
diff --git a/src/plugins/qnx/slog2inforunner.h b/src/plugins/qnx/slog2inforunner.h
index 048915baac..3aa94a9878 100644
--- a/src/plugins/qnx/slog2inforunner.h
+++ b/src/plugins/qnx/slog2inforunner.h
@@ -27,7 +27,7 @@
#include <QObject>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <remotelinux/linuxdevice.h>
#include <utils/outputformat.h>
diff --git a/src/plugins/qtsupport/CMakeLists.txt b/src/plugins/qtsupport/CMakeLists.txt
new file mode 100644
index 0000000000..125e949b35
--- /dev/null
+++ b/src/plugins/qtsupport/CMakeLists.txt
@@ -0,0 +1,35 @@
+add_qtc_plugin(QtSupport
+ DEPENDS Qt5::Xml
+ PUBLIC_DEPENDS ProParser
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer ResourceEditor
+ SOURCES
+ baseqtversion.cpp baseqtversion.h
+ codegenerator.cpp codegenerator.h
+ codegensettings.cpp codegensettings.h
+ codegensettingspage.cpp codegensettingspage.h
+ codegensettingspagewidget.ui
+ desktopqtversion.cpp desktopqtversion.h
+ exampleslistmodel.cpp exampleslistmodel.h
+ gettingstartedwelcomepage.cpp gettingstartedwelcomepage.h
+ profilereader.cpp profilereader.h
+ qmldumptool.cpp qmldumptool.h
+ qscxmlcgenerator.cpp qscxmlcgenerator.h
+ qtconfigwidget.cpp qtconfigwidget.h
+ qtcppkitinfo.cpp qtcppkitinfo.h
+ qtkitinformation.cpp qtkitinformation.h
+ qtoptionspage.cpp qtoptionspage.h
+ qtoutputformatter.cpp qtoutputformatter.h
+ qtparser.cpp qtparser.h
+ qtprojectimporter.cpp qtprojectimporter.h
+ qtsupport.qrc
+ qtsupport_global.h
+ qtsupportconstants.h
+ qtsupportplugin.cpp qtsupportplugin.h
+ qttestparser.cpp qttestparser.h
+ qtversionfactory.cpp qtversionfactory.h
+ qtversioninfo.ui
+ qtversionmanager.cpp qtversionmanager.h qtversionmanager.ui
+ screenshotcropper.cpp screenshotcropper.h
+ showbuildlog.ui
+ uicgenerator.cpp uicgenerator.h
+)
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index 4f58331d49..2dd4160a3b 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -28,8 +28,10 @@
#include "qmldumptool.h"
#include "qtkitinformation.h"
+#include "qtversionfactory.h"
#include "qtversionmanager.h"
#include "profilereader.h"
+
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <proparser/qmakevfs.h>
@@ -193,18 +195,19 @@ bool QtVersionNumber::operator >=(const QtVersionNumber &b) const
// BaseQtVersion
///////////////
-BaseQtVersion::BaseQtVersion(const FileName &qmakeCommand, bool isAutodetected, const QString &autodetectionSource)
- : m_id(QtVersionManager::getUniqueId()),
- m_isAutodetected(isAutodetected),
- m_autodetectionSource(autodetectionSource),
- m_qmakeCommand(qmakeCommand)
-{ }
-BaseQtVersion::BaseQtVersion(const BaseQtVersion &other) = default;
BaseQtVersion::BaseQtVersion() = default;
BaseQtVersion::~BaseQtVersion() = default;
-QString BaseQtVersion::defaultUnexpandedDisplayName(const FileName &qmakePath, bool fromPath)
+void BaseQtVersion::setupQmakePathAndId(const FilePath &qmakeCommand)
+{
+ m_id = QtVersionManager::getUniqueId();
+ QTC_CHECK(m_qmakeCommand.isEmpty()); // Should only be used once.
+ m_qmakeCommand = qmakeCommand;
+ setUnexpandedDisplayName(defaultUnexpandedDisplayName(m_qmakeCommand, false));
+}
+
+QString BaseQtVersion::defaultUnexpandedDisplayName(const FilePath &qmakePath, bool fromPath)
{
QString location;
if (qmakePath.isEmpty()) {
@@ -349,34 +352,34 @@ QSet<Id> BaseQtVersion::availableFeatures() const
return features;
}
-QList<Task> BaseQtVersion::validateKit(const Kit *k)
+Tasks BaseQtVersion::validateKit(const Kit *k)
{
- QList<Task> result;
+ Tasks result;
- BaseQtVersion *version = QtKitInformation::qtVersion(k);
+ BaseQtVersion *version = QtKitAspect::qtVersion(k);
Q_ASSERT(version == this);
- const QList<Abi> qtAbis = version->qtAbis();
+ const Abis qtAbis = version->qtAbis();
if (qtAbis.isEmpty()) // No need to test if Qt does not know anyway...
return result;
- const Id dt = DeviceTypeKitInformation::deviceTypeId(k);
+ const Id dt = DeviceTypeKitAspect::deviceTypeId(k);
const QSet<Id> tdt = targetDeviceTypes();
if (!tdt.isEmpty() && !tdt.contains(dt)) {
result << Task(Task::Warning,
QCoreApplication::translate("BaseQtVersion",
"Device type is not supported by Qt version."),
- FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
+ FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
}
- ToolChain *tc = ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (tc) {
Abi targetAbi = tc->targetAbi();
bool fuzzyMatch = false;
bool fullMatch = false;
QString qtAbiString;
- foreach (const Abi &qtAbi, qtAbis) {
+ for (const Abi &qtAbi : qtAbis) {
if (!qtAbiString.isEmpty())
qtAbiString.append(' ');
qtAbiString.append(qtAbi.toString());
@@ -397,73 +400,76 @@ QList<Task> BaseQtVersion::validateKit(const Kit *k)
"The compiler \"%1\" (%2) may not produce code compatible with the Qt version \"%3\" (%4).");
message = message.arg(tc->displayName(), targetAbi.toString(),
version->displayName(), qtAbiString);
- result << Task(fuzzyMatch ? Task::Warning : Task::Error, message, FileName(), -1,
+ result << Task(fuzzyMatch ? Task::Warning : Task::Error, message, FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
}
+ } else if (ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID)) {
+ const QString message = QCoreApplication::translate("BaseQtVersion",
+ "The kit has a Qt version, but no C++ compiler.");
+ result << Task(Task::Warning, message, FilePath(), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
}
return result;
}
-FileName BaseQtVersion::headerPath() const
+FilePath BaseQtVersion::headerPath() const
{
- return FileName::fromUserInput(qmakeProperty("QT_INSTALL_HEADERS"));
+ return FilePath::fromUserInput(qmakeProperty("QT_INSTALL_HEADERS"));
}
-FileName BaseQtVersion::docsPath() const
+FilePath BaseQtVersion::docsPath() const
{
- return FileName::fromUserInput(qmakeProperty("QT_INSTALL_DOCS"));
+ return FilePath::fromUserInput(qmakeProperty("QT_INSTALL_DOCS"));
}
-FileName BaseQtVersion::libraryPath() const
+FilePath BaseQtVersion::libraryPath() const
{
- return FileName::fromUserInput(qmakeProperty("QT_INSTALL_LIBS"));
+ return FilePath::fromUserInput(qmakeProperty("QT_INSTALL_LIBS"));
}
-FileName BaseQtVersion::pluginPath() const
+FilePath BaseQtVersion::pluginPath() const
{
- return FileName::fromUserInput(qmakeProperty("QT_INSTALL_PLUGINS"));
+ return FilePath::fromUserInput(qmakeProperty("QT_INSTALL_PLUGINS"));
}
-FileName BaseQtVersion::qmlPath() const
+FilePath BaseQtVersion::qmlPath() const
{
- return FileName::fromUserInput(qmakeProperty("QT_INSTALL_QML"));
+ return FilePath::fromUserInput(qmakeProperty("QT_INSTALL_QML"));
}
-FileName BaseQtVersion::binPath() const
+FilePath BaseQtVersion::binPath() const
{
- return FileName::fromUserInput(qmakeProperty("QT_HOST_BINS"));
+ return FilePath::fromUserInput(qmakeProperty("QT_HOST_BINS"));
}
-FileName BaseQtVersion::mkspecsPath() const
+FilePath BaseQtVersion::mkspecsPath() const
{
- FileName result = FileName::fromUserInput(qmakeProperty("QT_HOST_DATA"));
+ const FilePath result = FilePath::fromUserInput(qmakeProperty("QT_HOST_DATA"));
if (result.isEmpty())
- result = FileName::fromUserInput(qmakeProperty("QMAKE_MKSPECS"));
- else
- result.appendPath("mkspecs");
- return result;
+ return FilePath::fromUserInput(qmakeProperty("QMAKE_MKSPECS"));
+ return result.pathAppended("mkspecs");
}
-FileName BaseQtVersion::qmlBinPath() const
+FilePath BaseQtVersion::qmlBinPath() const
{
- return FileName::fromUserInput(m_mkspecValues.value("QT.qml.bins"));
+ return FilePath::fromUserInput(m_mkspecValues.value("QT.qml.bins"));
}
-FileName BaseQtVersion::librarySearchPath() const
+FilePath BaseQtVersion::librarySearchPath() const
{
return HostOsInfo::isWindowsHost()
- ? FileName::fromUserInput(qmakeProperty("QT_INSTALL_BINS")) : libraryPath();
+ ? FilePath::fromUserInput(qmakeProperty("QT_INSTALL_BINS")) : libraryPath();
}
-FileNameList BaseQtVersion::directoriesToIgnoreInProjectTree() const
+FilePathList BaseQtVersion::directoriesToIgnoreInProjectTree() const
{
- FileNameList result;
- const FileName mkspecPathGet = mkspecsPath();
+ FilePathList result;
+ const FilePath mkspecPathGet = mkspecsPath();
result.append(mkspecPathGet);
- FileName mkspecPathSrc = FileName::fromUserInput(qmakeProperty("QT_HOST_DATA", PropertyVariantSrc));
+ FilePath mkspecPathSrc = FilePath::fromUserInput(qmakeProperty("QT_HOST_DATA", PropertyVariantSrc));
if (!mkspecPathSrc.isEmpty()) {
- mkspecPathSrc.appendPath("mkspecs");
+ mkspecPathSrc = mkspecPathSrc.pathAppended("mkspecs");
if (mkspecPathSrc != mkspecPathGet)
result.append(mkspecPathSrc);
}
@@ -504,6 +510,11 @@ void BaseQtVersion::setId(int id)
m_id = id;
}
+void BaseQtVersion::setIsAutodetected(bool isAutodetected)
+{
+ m_isAutodetected = isAutodetected;
+}
+
void BaseQtVersion::fromMap(const QVariantMap &map)
{
m_id = map.value(Constants::QTVERSIONID).toInt();
@@ -518,12 +529,12 @@ void BaseQtVersion::fromMap(const QVariantMap &map)
if (string.startsWith('~'))
string.remove(0, 1).prepend(QDir::homePath());
- m_qtSources = Utils::FileName::fromUserInput(
+ m_qtSources = Utils::FilePath::fromUserInput(
map.value(QTVERSIONSOURCEPATH).toString());
// Handle ABIs provided by the SDKTool:
// Note: Creator does not write these settings itself, so it has to come from the SDKTool!
- m_qtAbis = Utils::transform(map.value(QTVERSION_ABIS, QStringList()).toStringList(), &Abi::fromString);
+ m_qtAbis = Utils::transform<Abis>(map.value(QTVERSION_ABIS).toStringList(), &Abi::fromString);
m_qtAbis = Utils::filtered(m_qtAbis, &Abi::isValid);
m_hasQtAbis = !m_qtAbis.isEmpty();
@@ -535,7 +546,7 @@ void BaseQtVersion::fromMap(const QVariantMap &map)
string = BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget());
}
- m_qmakeCommand = Utils::FileName::fromString(string);
+ m_qmakeCommand = Utils::FilePath::fromString(string);
}
QVariantMap BaseQtVersion::toMap() const
@@ -604,12 +615,12 @@ QStringList BaseQtVersion::warningReason() const
return ret;
}
-FileName BaseQtVersion::qmakeCommand() const
+FilePath BaseQtVersion::qmakeCommand() const
{
return m_qmakeCommand;
}
-QList<Abi> BaseQtVersion::qtAbis() const
+Abis BaseQtVersion::qtAbis() const
{
if (!m_hasQtAbis) {
m_qtAbis = detectQtAbis();
@@ -618,6 +629,11 @@ QList<Abi> BaseQtVersion::qtAbis() const
return m_qtAbis;
}
+Abis BaseQtVersion::detectQtAbis() const
+{
+ return qtAbisFromLibrary(qtCorePaths());
+}
+
bool BaseQtVersion::equals(BaseQtVersion *other)
{
if (m_qmakeCommand != other->m_qmakeCommand)
@@ -639,6 +655,12 @@ int BaseQtVersion::uniqueId() const
return m_id;
}
+QString BaseQtVersion::type() const
+{
+ QTC_ASSERT(m_factory, return QString());
+ return m_factory->supportedType();
+}
+
bool BaseQtVersion::isAutodetected() const
{
return m_isAutodetected;
@@ -683,7 +705,7 @@ QString BaseQtVersion::toHtml(bool verbose) const
} else {
str << "<tr><td><b>" << QCoreApplication::translate("BaseQtVersion", "ABI:")
<< "</b></td>";
- const QList<Abi> abis = qtAbis();
+ const Abis abis = qtAbis();
if (abis.isEmpty()) {
str << "<td>" << Abi().toString() << "</td></tr>";
} else {
@@ -696,7 +718,7 @@ QString BaseQtVersion::toHtml(bool verbose) const
str << "<tr><td><b>" << QCoreApplication::translate("BaseQtVersion", "Source:")
<< "</b></td><td>" << sourcePath().toUserOutput() << "</td></tr>";
str << "<tr><td><b>" << QCoreApplication::translate("BaseQtVersion", "mkspec:")
- << "</b></td><td>" << mkspec().toUserOutput() << "</td></tr>";
+ << "</b></td><td>" << QDir::toNativeSeparators(mkspec()) << "</td></tr>";
str << "<tr><td><b>" << QCoreApplication::translate("BaseQtVersion", "qmake:")
<< "</b></td><td>" << m_qmakeCommand.toUserOutput() << "</td></tr>";
ensureMkSpecParsed();
@@ -750,21 +772,16 @@ QString BaseQtVersion::toHtml(bool verbose) const
return rc;
}
-void BaseQtVersion::updateSourcePath() const
+FilePath BaseQtVersion::sourcePath() const
{
- if (!m_sourcePath.isEmpty())
- return;
- updateVersionInfo();
- m_sourcePath = sourcePath(m_versionInfo);
-}
-
-FileName BaseQtVersion::sourcePath() const
-{
- updateSourcePath();
+ if (m_sourcePath.isEmpty()) {
+ updateVersionInfo();
+ m_sourcePath = sourcePath(m_versionInfo);
+ }
return m_sourcePath;
}
-FileName BaseQtVersion::qtPackageSourcePath() const
+FilePath BaseQtVersion::qtPackageSourcePath() const
{
return m_qtSources;
}
@@ -881,13 +898,13 @@ void BaseQtVersion::updateMkspec() const
if (m_mkspecFullPath.isEmpty())
return;
- FileName baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo());
+ FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo());
if (m_mkspec.isChildOf(baseMkspecDir)) {
m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir);
// qDebug() << "Setting mkspec to"<<mkspec;
} else {
- FileName sourceMkSpecPath = sourcePath().appendPath("mkspecs");
+ const FilePath sourceMkSpecPath = sourcePath().pathAppended("mkspecs");
if (m_mkspec.isChildOf(sourceMkSpecPath)) {
m_mkspec = m_mkspec.relativeChildPath(sourceMkSpecPath);
} else {
@@ -948,22 +965,23 @@ void BaseQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const
m_mkspecValues.insert(ns, evaluator->value(ns));
}
-FileName BaseQtVersion::mkspec() const
+QString BaseQtVersion::mkspec() const
{
updateMkspec();
- return m_mkspec;
+ return m_mkspec.toString();
}
-FileName BaseQtVersion::mkspecFor(ToolChain *tc) const
+QString BaseQtVersion::mkspecFor(ToolChain *tc) const
{
- FileName versionSpec = mkspec();
+ QString versionSpec = mkspec();
if (!tc)
return versionSpec;
- const FileNameList tcSpecList = tc->suggestedMkspecList();
+ const QStringList tcSpecList = tc->suggestedMkspecList();
if (tcSpecList.contains(versionSpec))
return versionSpec;
- foreach (const FileName &tcSpec, tcSpecList) {
+
+ for (const QString &tcSpec : tcSpecList) {
if (hasMkspec(tcSpec))
return tcSpec;
}
@@ -971,24 +989,24 @@ FileName BaseQtVersion::mkspecFor(ToolChain *tc) const
return versionSpec;
}
-FileName BaseQtVersion::mkspecPath() const
+FilePath BaseQtVersion::mkspecPath() const
{
updateMkspec();
return m_mkspecFullPath;
}
-bool BaseQtVersion::hasMkspec(const FileName &spec) const
+bool BaseQtVersion::hasMkspec(const QString &spec) const
{
if (spec.isEmpty())
return true; // default spec of a Qt version
QDir mkspecDir = QDir(QDir::fromNativeSeparators(qmakeProperty("QT_HOST_DATA"))
+ "/mkspecs/");
- const QString absSpec = mkspecDir.absoluteFilePath(spec.toString());
+ const QString absSpec = mkspecDir.absoluteFilePath(spec);
if (QFileInfo(absSpec).isDir() && QFileInfo(absSpec + "/qmake.conf").isFile())
return true;
mkspecDir.setPath(sourcePath().toString() + "/mkspecs/");
- const QString absSrcSpec = mkspecDir.absoluteFilePath(spec.toString());
+ const QString absSrcSpec = mkspecDir.absoluteFilePath(spec);
return absSrcSpec != absSpec
&& QFileInfo(absSrcSpec).isDir()
&& QFileInfo(absSrcSpec + "/qmake.conf").isFile();
@@ -1181,151 +1199,151 @@ BaseQtVersion::createMacroExpander(const std::function<const BaseQtVersion *()>
};
};
std::unique_ptr<Utils::MacroExpander> expander(new Utils::MacroExpander);
- expander->setDisplayName(QtKitInformation::tr("Qt version"));
+ expander->setDisplayName(QtKitAspect::tr("Qt version"));
expander->registerVariable(
"Qt:Version",
- QtKitInformation::tr("The version string of the current Qt version."),
+ QtKitAspect::tr("The version string of the current Qt version."),
versionProperty([](const BaseQtVersion *version) {
return version->qtVersionString();
}));
expander->registerVariable(
"Qt:Type",
- QtKitInformation::tr("The type of the current Qt version."),
+ QtKitAspect::tr("The type of the current Qt version."),
versionProperty([](const BaseQtVersion *version) {
return version->type();
}));
expander->registerVariable(
"Qt:Mkspec",
- QtKitInformation::tr("The mkspec of the current Qt version."),
+ QtKitAspect::tr("The mkspec of the current Qt version."),
versionProperty([](const BaseQtVersion *version) {
- return version->mkspec().toUserOutput();
+ return QDir::toNativeSeparators(version->mkspec());
}));
expander->registerVariable(
"Qt:QT_INSTALL_PREFIX",
- QtKitInformation::tr("The installation prefix of the current Qt version."),
+ QtKitAspect::tr("The installation prefix of the current Qt version."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_PREFIX");
}));
expander->registerVariable(
"Qt:QT_INSTALL_DATA",
- QtKitInformation::tr("The installation location of the current Qt version's data."),
+ QtKitAspect::tr("The installation location of the current Qt version's data."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_DATA");
}));
expander->registerVariable(
"Qt:QT_INSTALL_HEADERS",
- QtKitInformation::tr("The installation location of the current Qt version's header files."),
+ QtKitAspect::tr("The installation location of the current Qt version's header files."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_HEADERS");
}));
expander->registerVariable(
"Qt:QT_INSTALL_LIBS",
- QtKitInformation::tr("The installation location of the current Qt version's library files."),
+ QtKitAspect::tr("The installation location of the current Qt version's library files."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_LIBS");
}));
expander->registerVariable(
"Qt:QT_INSTALL_DOCS",
- QtKitInformation::tr("The installation location of the current Qt version's documentation files."),
+ QtKitAspect::tr("The installation location of the current Qt version's documentation files."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_DOCS");
}));
expander->registerVariable(
"Qt:QT_INSTALL_BINS",
- QtKitInformation::tr("The installation location of the current Qt version's executable files."),
+ QtKitAspect::tr("The installation location of the current Qt version's executable files."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_BINS");
}));
expander->registerVariable(
"Qt:QT_INSTALL_PLUGINS",
- QtKitInformation::tr("The installation location of the current Qt version's plugins."),
+ QtKitAspect::tr("The installation location of the current Qt version's plugins."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_PLUGINS");
}));
expander->registerVariable(
"Qt:QT_INSTALL_QML",
- QtKitInformation::tr("The installation location of the current Qt version's QML files."),
+ QtKitAspect::tr("The installation location of the current Qt version's QML files."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_QML");
}));
expander->registerVariable(
"Qt:QT_INSTALL_IMPORTS",
- QtKitInformation::tr("The installation location of the current Qt version's imports."),
+ QtKitAspect::tr("The installation location of the current Qt version's imports."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_IMPORTS");
}));
expander->registerVariable(
"Qt:QT_INSTALL_TRANSLATIONS",
- QtKitInformation::tr("The installation location of the current Qt version's translation files."),
+ QtKitAspect::tr("The installation location of the current Qt version's translation files."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_TRANSLATIONS");
}));
expander->registerVariable(
"Qt:QT_INSTALL_CONFIGURATION",
- QtKitInformation::tr("The installation location of the current Qt version's translation files."),
+ QtKitAspect::tr("The installation location of the current Qt version's translation files."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_CONFIGURATION");
}));
expander->registerVariable(
"Qt:QT_INSTALL_EXAMPLES",
- QtKitInformation::tr("The installation location of the current Qt version's examples."),
+ QtKitAspect::tr("The installation location of the current Qt version's examples."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_EXAMPLES");
}));
expander->registerVariable(
"Qt:QT_INSTALL_DEMOS",
- QtKitInformation::tr("The installation location of the current Qt version's demos."),
+ QtKitAspect::tr("The installation location of the current Qt version's demos."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_DEMOS");
}));
expander->registerVariable(
"Qt:QMAKE_MKSPECS",
- QtKitInformation::tr("The current Qt version's default mkspecs (Qt 4)."),
+ QtKitAspect::tr("The current Qt version's default mkspecs (Qt 4)."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QMAKE_MKSPECS");
}));
expander->registerVariable(
"Qt:QMAKE_SPEC",
- QtKitInformation::tr("The current Qt version's default mkspec (Qt 5; host system)."),
+ QtKitAspect::tr("The current Qt version's default mkspec (Qt 5; host system)."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QMAKE_SPEC");
}));
expander->registerVariable(
"Qt:QMAKE_XSPEC",
- QtKitInformation::tr("The current Qt version's default mkspec (Qt 5; target system)."),
+ QtKitAspect::tr("The current Qt version's default mkspec (Qt 5; target system)."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QMAKE_XSPEC");
}));
expander->registerVariable(
"Qt:QMAKE_VERSION",
- QtKitInformation::tr("The current Qt's qmake version."),
+ QtKitAspect::tr("The current Qt's qmake version."),
versionProperty([](const BaseQtVersion *version) {
return version->qmakeProperty(version->m_versionInfo, "QMAKE_VERSION");
}));
// FIXME: Re-enable once we can detect expansion loops.
// expander->registerVariable("Qt:Name",
- // QtKitInformation::tr("The display name of the current Qt version."),
+ // QtKitAspect::tr("The display name of the current Qt version."),
// versionProperty([](BaseQtVersion *version) {
// return version->displayName();
// }));
@@ -1346,8 +1364,8 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar
const QList<ProjectExplorer::Project *> projects = ProjectExplorer::SessionManager::projects();
QTC_CHECK(projects.isEmpty() || startupProject);
- Utils::FileName projectDirectory;
- Utils::FileNameList sourceFiles;
+ Utils::FilePath projectDirectory;
+ Utils::FilePathList sourceFiles;
// Sort files from startupProject to the front of the list ...
if (startupProject) {
@@ -1368,11 +1386,11 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar
// ... and find the sysroot and qml directory if we have any target at all.
const ProjectExplorer::Kit *kit = target ? target->kit() : nullptr;
- const Utils::FileName activeSysroot = ProjectExplorer::SysRootKitInformation::sysRoot(kit);
+ const Utils::FilePath activeSysroot = ProjectExplorer::SysRootKitAspect::sysRoot(kit);
const QtSupport::BaseQtVersion *qtVersion = QtVersionManager::isLoaded()
- ? QtSupport::QtKitInformation::qtVersion(kit) : nullptr;
- Utils::FileNameList additionalSearchDirectories = qtVersion
- ? Utils::FileNameList({qtVersion->qmlPath()}) : Utils::FileNameList();
+ ? QtSupport::QtKitAspect::qtVersion(kit) : nullptr;
+ Utils::FilePathList additionalSearchDirectories = qtVersion
+ ? Utils::FilePathList({qtVersion->qmlPath()}) : Utils::FilePathList();
if (target) {
for (const ProjectExplorer::DeployableFile &file : target->deploymentData().allFiles())
@@ -1449,16 +1467,16 @@ void BaseQtVersion::recheckDumper()
m_versionInfoUpToDate = false;
}
-QList<Task> BaseQtVersion::reportIssuesImpl(const QString &proFile, const QString &buildDir) const
+Tasks BaseQtVersion::reportIssuesImpl(const QString &proFile, const QString &buildDir) const
{
Q_UNUSED(proFile);
Q_UNUSED(buildDir);
- QList<Task> results;
+ Tasks results;
if (!isValid()) {
//: %1: Reason for being invalid
const QString msg = QCoreApplication::translate("QmakeProjectManager::QtVersion", "The Qt version is invalid: %1").arg(invalidReason());
- results.append(Task(Task::Error, msg, FileName(), -1,
+ results.append(Task(Task::Error, msg, FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
@@ -1468,16 +1486,16 @@ QList<Task> BaseQtVersion::reportIssuesImpl(const QString &proFile, const QStrin
//: %1: Path to qmake executable
const QString msg = QCoreApplication::translate("QmakeProjectManager::QtVersion",
"The qmake command \"%1\" was not found or is not executable.").arg(qmakeCommand().toUserOutput());
- results.append(Task(Task::Error, msg, FileName(), -1,
+ results.append(Task(Task::Error, msg, FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
return results;
}
-QList<Task> BaseQtVersion::reportIssues(const QString &proFile, const QString &buildDir) const
+Tasks BaseQtVersion::reportIssues(const QString &proFile, const QString &buildDir) const
{
- QList<Task> results = reportIssuesImpl(proFile, buildDir);
+ Tasks results = reportIssuesImpl(proFile, buildDir);
Utils::sort(results);
return results;
}
@@ -1487,7 +1505,7 @@ QtConfigWidget *BaseQtVersion::createConfigurationWidget() const
return nullptr;
}
-static QByteArray runQmakeQuery(const FileName &binary, const Environment &env,
+static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env,
QString *error)
{
QTC_ASSERT(error, return QByteArray());
@@ -1519,7 +1537,7 @@ static QByteArray runQmakeQuery(const FileName &binary, const Environment &env,
return process.readAllStandardOutput();
}
-bool BaseQtVersion::queryQMakeVariables(const FileName &binary, const Environment &env,
+bool BaseQtVersion::queryQMakeVariables(const FilePath &binary, const Environment &env,
QHash<ProKey, ProString> *versionInfo, QString *error)
{
QString tmp;
@@ -1541,7 +1559,7 @@ bool BaseQtVersion::queryQMakeVariables(const FileName &binary, const Environmen
// Try running qmake with all kinds of tool chains set up in the environment.
// This is required to make non-static qmakes work on windows where every tool chain
// tries to be incompatible with any other.
- QList<Abi> abiList = Abi::abisOfBinary(binary);
+ Abis abiList = Abi::abisOfBinary(binary);
const QList<ToolChain *> tcList
= ToolChainManager::toolChains([&abiList](const ToolChain *t) { return abiList.contains(t->targetAbi()); });
for (ToolChain *tc : tcList) {
@@ -1561,19 +1579,19 @@ bool BaseQtVersion::queryQMakeVariables(const FileName &binary, const Environmen
return true;
}
-FileName BaseQtVersion::mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProString> &versionInfo)
+FilePath BaseQtVersion::mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProString> &versionInfo)
{
QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc);
if (dataDir.isEmpty())
- return FileName();
- return FileName::fromUserInput(dataDir + "/mkspecs");
+ return FilePath();
+ return FilePath::fromUserInput(dataDir + "/mkspecs");
}
-FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo)
+FilePath BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo)
{
- FileName baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo);
+ FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo);
if (baseMkspecDir.isEmpty())
- return FileName();
+ return FilePath();
bool qt5 = false;
QString theSpec = qmakeProperty(versionInfo, "QMAKE_XSPEC");
@@ -1582,8 +1600,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
else
qt5 = true;
- FileName mkspecFullPath = baseMkspecDir;
- mkspecFullPath.appendPath(theSpec);
+ FilePath mkspecFullPath = baseMkspecDir.pathAppended(theSpec);
// qDebug() << "default mkspec is located at" << mkspecFullPath;
@@ -1608,7 +1625,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
// We sometimes get a mix of different slash styles here...
possibleFullPath = possibleFullPath.replace('\\', '/');
if (QFileInfo::exists(possibleFullPath)) // Only if the path exists
- mkspecFullPath = FileName::fromUserInput(possibleFullPath);
+ mkspecFullPath = FilePath::fromUserInput(possibleFullPath);
}
break;
}
@@ -1629,7 +1646,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
if (value.contains("XCODE")) {
// we don't want to generate xcode projects...
// qDebug() << "default mkspec is xcode, falling back to g++";
- return baseMkspecDir.appendPath("macx-g++");
+ return baseMkspecDir.pathAppended("macx-g++");
}
}
break;
@@ -1642,18 +1659,18 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve
//resolve mkspec link
QString rspec = mkspecFullPath.toFileInfo().symLinkTarget();
if (!rspec.isEmpty())
- mkspecFullPath = FileName::fromUserInput(
+ mkspecFullPath = FilePath::fromUserInput(
QDir(baseMkspecDir.toString()).absoluteFilePath(rspec));
}
}
return mkspecFullPath;
}
-FileName BaseQtVersion::sourcePath(const QHash<ProKey, ProString> &versionInfo)
+FilePath BaseQtVersion::sourcePath(const QHash<ProKey, ProString> &versionInfo)
{
const QString qt5Source = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX/src");
if (!qt5Source.isEmpty())
- return Utils::FileName::fromString(QFileInfo(qt5Source).canonicalFilePath());
+ return Utils::FilePath::fromString(QFileInfo(qt5Source).canonicalFilePath());
const QString installData = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX");
QString sourcePath = installData;
@@ -1672,12 +1689,12 @@ FileName BaseQtVersion::sourcePath(const QHash<ProKey, ProString> &versionInfo)
}
}
}
- return FileName::fromUserInput(QFileInfo(sourcePath).canonicalFilePath());
+ return FilePath::fromUserInput(QFileInfo(sourcePath).canonicalFilePath());
}
-bool BaseQtVersion::isInSourceDirectory(const Utils::FileName &filePath)
+bool BaseQtVersion::isInSourceDirectory(const Utils::FilePath &filePath)
{
- const Utils::FileName &source = sourcePath();
+ const Utils::FilePath &source = sourcePath();
if (source.isEmpty())
return false;
QDir dir = QDir(source.toString());
@@ -1686,9 +1703,9 @@ bool BaseQtVersion::isInSourceDirectory(const Utils::FileName &filePath)
return filePath.isChildOf(dir);
}
-bool BaseQtVersion::isSubProject(const Utils::FileName &filePath) const
+bool BaseQtVersion::isSubProject(const Utils::FilePath &filePath) const
{
- const Utils::FileName &source = sourcePath();
+ const Utils::FilePath &source = sourcePath();
if (!source.isEmpty()) {
QDir dir = QDir(source.toString());
if (dir.dirName() == "qtbase")
@@ -1712,7 +1729,7 @@ bool BaseQtVersion::isSubProject(const Utils::FileName &filePath) const
bool BaseQtVersion::isQmlDebuggingSupported(Kit *k, QString *reason)
{
QTC_ASSERT(k, return false);
- BaseQtVersion *version = QtKitInformation::qtVersion(k);
+ BaseQtVersion *version = QtKitAspect::qtVersion(k);
if (!version) {
if (reason)
*reason = QCoreApplication::translate("BaseQtVersion", "No Qt version.");
@@ -1741,7 +1758,7 @@ bool BaseQtVersion::isQmlDebuggingSupported(QString *reason) const
bool BaseQtVersion::isQtQuickCompilerSupported(Kit *k, QString *reason)
{
QTC_ASSERT(k, return false);
- BaseQtVersion *version = QtKitInformation::qtVersion(k);
+ BaseQtVersion *version = QtKitAspect::qtVersion(k);
if (!version) {
if (reason)
*reason = QCoreApplication::translate("BaseQtVersion", "No Qt version.");
@@ -1774,7 +1791,7 @@ bool BaseQtVersion::isQtQuickCompilerSupported(QString *reason) const
return true;
}
-FileNameList BaseQtVersion::qtCorePaths() const
+FilePathList BaseQtVersion::qtCorePaths() const
{
updateVersionInfo();
const QString &versionString = m_qtVersionString;
@@ -1792,28 +1809,28 @@ FileNameList BaseQtVersion::qtCorePaths() const
result += QDir(installBinDir).entryInfoList(filters);
return result;
}();
- FileNameList staticLibs;
- FileNameList dynamicLibs;
+ FilePathList staticLibs;
+ FilePathList dynamicLibs;
for (const QFileInfo &info : entryInfoList) {
const QString file = info.fileName();
if (info.isDir()
&& file.startsWith("QtCore")
&& file.endsWith(".framework")) {
// handle Framework
- FileName lib(info);
- dynamicLibs.append(lib.appendPath(file.left(file.lastIndexOf('.'))));
+ const FilePath lib = FilePath::fromFileInfo(info);
+ dynamicLibs.append(lib.pathAppended(file.left(file.lastIndexOf('.'))));
} else if (info.isReadable()) {
if (file.startsWith("libQtCore")
|| file.startsWith("libQt5Core")
|| file.startsWith("QtCore")
|| file.startsWith("Qt5Core")) {
if (file.endsWith(".a") || file.endsWith(".lib"))
- staticLibs.append(FileName(info));
+ staticLibs.append(FilePath::fromFileInfo(info));
else if (file.endsWith(".dll")
|| file.endsWith(QString::fromLatin1(".so.") + versionString)
|| file.endsWith(".so")
|| file.endsWith(QLatin1Char('.') + versionString + ".dylib"))
- dynamicLibs.append(FileName(info));
+ dynamicLibs.append(FilePath::fromFileInfo(info));
}
}
}
@@ -1823,7 +1840,7 @@ FileNameList BaseQtVersion::qtCorePaths() const
return dynamicLibs;
}
-static QByteArray scanQtBinaryForBuildString(const FileName &library)
+static QByteArray scanQtBinaryForBuildString(const FilePath &library)
{
QFile lib(library.toString());
QByteArray buildString;
@@ -1976,10 +1993,10 @@ static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &pr
return Abi(arch, os, flavor, format, wordWidth);
}
-static Abi scanQtBinaryForBuildStringAndRefineAbi(const FileName &library,
+static Abi scanQtBinaryForBuildStringAndRefineAbi(const FilePath &library,
const Abi &probableAbi)
{
- static QHash<Utils::FileName, Abi> results;
+ static QHash<Utils::FilePath, Abi> results;
if (!results.contains(library)) {
const QByteArray buildString = scanQtBinaryForBuildString(library);
@@ -1988,10 +2005,10 @@ static Abi scanQtBinaryForBuildStringAndRefineAbi(const FileName &library,
return results.value(library);
}
-QList<Abi> BaseQtVersion::qtAbisFromLibrary(const FileNameList &coreLibraries)
+Abis BaseQtVersion::qtAbisFromLibrary(const FilePathList &coreLibraries)
{
- QList<Abi> res;
- foreach (const FileName &library, coreLibraries) {
+ Abis res;
+ for (const FilePath &library : coreLibraries) {
for (Abi abi : Abi::abisOfBinary(library)) {
Abi tmp = abi;
if (abi.osFlavor() == Abi::UnknownFlavor)
diff --git a/src/plugins/qtsupport/baseqtversion.h b/src/plugins/qtsupport/baseqtversion.h
index 34627bfb62..34e33b1c20 100644
--- a/src/plugins/qtsupport/baseqtversion.h
+++ b/src/plugins/qtsupport/baseqtversion.h
@@ -31,6 +31,7 @@
#include <utils/macroexpander.h>
#include <projectexplorer/abi.h>
+#include <projectexplorer/task.h>
#include <QSet>
#include <QStringList>
@@ -48,7 +49,6 @@ class Kit;
class ToolChain;
class HeaderPath;
class Target;
-class Task;
} // namespace ProjectExplorer
QT_BEGIN_NAMESPACE
@@ -64,6 +64,7 @@ namespace QtSupport
class QtConfigWidget;
class BaseQtVersion;
+class QtVersionFactory;
// Wrapper to make the std::unique_ptr<Utils::MacroExpander> "copyable":
class MacroExpanderWrapper
@@ -113,7 +114,6 @@ public:
virtual ~BaseQtVersion();
virtual void fromMap(const QVariantMap &map);
- virtual BaseQtVersion *clone() const = 0;
virtual bool equals(BaseQtVersion *other);
bool isAutodetected() const;
@@ -126,7 +126,7 @@ public:
// All valid Ids are >= 0
int uniqueId() const;
- virtual QString type() const = 0;
+ QString type() const;
virtual QVariantMap toMap() const;
virtual bool isValid() const;
@@ -137,8 +137,8 @@ public:
virtual QString description() const = 0;
virtual QString toHtml(bool verbose) const;
- QList<ProjectExplorer::Abi> qtAbis() const;
- virtual QList<ProjectExplorer::Abi> detectQtAbis() const = 0;
+ ProjectExplorer::Abis qtAbis() const;
+ virtual ProjectExplorer::Abis detectQtAbis() const;
enum PropertyVariant { PropertyVariantDev, PropertyVariantGet, PropertyVariantSrc };
QString qmakeProperty(const QByteArray &name,
@@ -148,16 +148,16 @@ public:
virtual Utils::Environment qmakeRunEnvironment() const;
// source path defined by qmake property QT_INSTALL_PREFIX/src or by qmake.stash QT_SOURCE_TREE
- virtual Utils::FileName sourcePath() const;
+ Utils::FilePath sourcePath() const;
// returns source path for installed qt packages and empty string for self build qt
- Utils::FileName qtPackageSourcePath() const;
- bool isInSourceDirectory(const Utils::FileName &filePath);
- bool isSubProject(const Utils::FileName &filePath) const;
+ Utils::FilePath qtPackageSourcePath() const;
+ bool isInSourceDirectory(const Utils::FilePath &filePath);
+ bool isSubProject(const Utils::FilePath &filePath) const;
// used by UiCodeModelSupport
- virtual QString uicCommand() const;
- virtual QString designerCommand() const;
- virtual QString linguistCommand() const;
+ QString uicCommand() const;
+ QString designerCommand() const;
+ QString linguistCommand() const;
QString qscxmlcCommand() const;
QString qtVersionString() const;
@@ -172,19 +172,19 @@ public:
bool hasDemos() const;
QString demosPath() const;
- virtual QString frameworkInstallPath() const;
+ QString frameworkInstallPath() const;
// former local functions
- Utils::FileName qmakeCommand() const;
+ Utils::FilePath qmakeCommand() const;
/// @returns the name of the mkspec
- Utils::FileName mkspec() const;
- Utils::FileName mkspecFor(ProjectExplorer::ToolChain *tc) const;
+ QString mkspec() const;
+ QString mkspecFor(ProjectExplorer::ToolChain *tc) const;
/// @returns the full path to the default directory
/// specifally not the directory the symlink/ORIGINAL_QMAKESPEC points to
- Utils::FileName mkspecPath() const;
+ Utils::FilePath mkspecPath() const;
- bool hasMkspec(const Utils::FileName &spec) const;
+ bool hasMkspec(const QString &spec) const;
enum QmakeBuildConfig
{
@@ -201,39 +201,39 @@ public:
/// Check a .pro-file/Qt version combination on possible issues
/// @return a list of tasks, ordered on severity (errors first, then
/// warnings and finally info items.
- QList<ProjectExplorer::Task> reportIssues(const QString &proFile, const QString &buildDir) const;
+ ProjectExplorer::Tasks reportIssues(const QString &proFile, const QString &buildDir) const;
static bool isQmlDebuggingSupported(ProjectExplorer::Kit *k, QString *reason = nullptr);
bool isQmlDebuggingSupported(QString *reason = nullptr) const;
static bool isQtQuickCompilerSupported(ProjectExplorer::Kit *k, QString *reason = nullptr);
bool isQtQuickCompilerSupported(QString *reason = nullptr) const;
- virtual QString qmlDumpTool(bool debugVersion) const;
+ QString qmlDumpTool(bool debugVersion) const;
- virtual bool hasQmlDump() const;
- virtual bool hasQmlDumpWithRelocatableFlag() const;
- virtual bool needsQmlDump() const;
+ bool hasQmlDump() const;
+ bool hasQmlDumpWithRelocatableFlag() const;
+ bool needsQmlDump() const;
virtual QtConfigWidget *createConfigurationWidget() const;
- static QString defaultUnexpandedDisplayName(const Utils::FileName &qmakePath,
+ static QString defaultUnexpandedDisplayName(const Utils::FilePath &qmakePath,
bool fromPath = false);
virtual QSet<Core::Id> targetDeviceTypes() const = 0;
- virtual QList<ProjectExplorer::Task> validateKit(const ProjectExplorer::Kit *k);
+ virtual ProjectExplorer::Tasks validateKit(const ProjectExplorer::Kit *k);
- Utils::FileName headerPath() const;
- Utils::FileName docsPath() const;
- Utils::FileName libraryPath() const;
- Utils::FileName pluginPath() const;
- Utils::FileName qmlPath() const;
- Utils::FileName binPath() const;
- Utils::FileName mkspecsPath() const;
- Utils::FileName qmlBinPath() const;
- Utils::FileName librarySearchPath() const;
+ Utils::FilePath headerPath() const;
+ Utils::FilePath docsPath() const;
+ Utils::FilePath libraryPath() const;
+ Utils::FilePath pluginPath() const;
+ Utils::FilePath qmlPath() const;
+ Utils::FilePath binPath() const;
+ Utils::FilePath mkspecsPath() const;
+ Utils::FilePath qmlBinPath() const;
+ Utils::FilePath librarySearchPath() const;
- Utils::FileNameList directoriesToIgnoreInProjectTree() const;
+ Utils::FilePathList directoriesToIgnoreInProjectTree() const;
QString qtNamespace() const;
QString qtLibInfix() const;
@@ -253,43 +253,46 @@ public:
const ProjectExplorer::Target *target);
QSet<Core::Id> features() const;
+ void setIsAutodetected(bool isAutodetected);
+
protected:
virtual QSet<Core::Id> availableFeatures() const;
+
BaseQtVersion();
- BaseQtVersion(const Utils::FileName &path, bool isAutodetected = false, const QString &autodetectionSource = QString());
- BaseQtVersion(const BaseQtVersion &other);
+ BaseQtVersion(const BaseQtVersion &other) = delete;
- virtual QList<ProjectExplorer::Task> reportIssuesImpl(const QString &proFile, const QString &buildDir) const;
+ virtual ProjectExplorer::Tasks reportIssuesImpl(const QString &proFile, const QString &buildDir) const;
// helper function for desktop and simulator to figure out the supported abis based on the libraries
- Utils::FileNameList qtCorePaths() const;
- static QList<ProjectExplorer::Abi> qtAbisFromLibrary(const Utils::FileNameList &coreLibraries);
+ Utils::FilePathList qtCorePaths() const;
+ static ProjectExplorer::Abis qtAbisFromLibrary(const Utils::FilePathList &coreLibraries);
void ensureMkSpecParsed() const;
virtual void parseMkSpec(ProFileEvaluator *) const;
private:
+ void setupQmakePathAndId(const Utils::FilePath &path);
void setAutoDetectionSource(const QString &autodetectionSource);
- void updateSourcePath() const;
void updateVersionInfo() const;
enum HostBinaries { Designer, Linguist, Uic, QScxmlc };
QString findHostBinary(HostBinaries binary) const;
void updateMkspec() const;
QHash<ProKey, ProString> versionInfo() const;
- static bool queryQMakeVariables(const Utils::FileName &binary,
+ static bool queryQMakeVariables(const Utils::FilePath &binary,
const Utils::Environment &env,
QHash<ProKey, ProString> *versionInfo,
QString *error = nullptr);
static QString qmakeProperty(const QHash<ProKey, ProString> &versionInfo,
const QByteArray &name,
PropertyVariant variant = PropertyVariantGet);
- static Utils::FileName mkspecDirectoryFromVersionInfo(const QHash<ProKey,ProString> &versionInfo);
- static Utils::FileName mkspecFromVersionInfo(const QHash<ProKey,ProString> &versionInfo);
- static Utils::FileName sourcePath(const QHash<ProKey,ProString> &versionInfo);
+ static Utils::FilePath mkspecDirectoryFromVersionInfo(const QHash<ProKey,ProString> &versionInfo);
+ static Utils::FilePath mkspecFromVersionInfo(const QHash<ProKey,ProString> &versionInfo);
+ static Utils::FilePath sourcePath(const QHash<ProKey,ProString> &versionInfo);
void setId(int id); // used by the qtversionmanager for legacy restore
// and by the qtoptionspage to replace Qt versions
int m_id = -1;
+ const QtVersionFactory *m_factory = nullptr; // The factory that created us.
bool m_isAutodetected = false;
mutable bool m_hasQmlDump = false; // controlled by m_versionInfoUpToDate
@@ -312,24 +315,24 @@ private:
QString m_unexpandedDisplayName;
QString m_autodetectionSource;
QSet<Core::Id> m_overrideFeatures;
- mutable Utils::FileName m_sourcePath;
- mutable Utils::FileName m_qtSources;
+ mutable Utils::FilePath m_sourcePath;
+ mutable Utils::FilePath m_qtSources;
- mutable Utils::FileName m_mkspec;
- mutable Utils::FileName m_mkspecFullPath;
+ mutable Utils::FilePath m_mkspec;
+ mutable Utils::FilePath m_mkspecFullPath;
mutable QHash<QString, QString> m_mkspecValues;
mutable QHash<ProKey, ProString> m_versionInfo;
- Utils::FileName m_qmakeCommand;
+ Utils::FilePath m_qmakeCommand;
mutable QString m_qtVersionString;
mutable QString m_uicCommand;
mutable QString m_designerCommand;
mutable QString m_linguistCommand;
mutable QString m_qscxmlcCommand;
- mutable QList<ProjectExplorer::Abi> m_qtAbis;
+ mutable ProjectExplorer::Abis m_qtAbis;
MacroExpanderWrapper m_expander;
};
diff --git a/src/plugins/qtsupport/codegensettingspage.cpp b/src/plugins/qtsupport/codegensettingspage.cpp
index 39e64db8a2..8f45c02a14 100644
--- a/src/plugins/qtsupport/codegensettingspage.cpp
+++ b/src/plugins/qtsupport/codegensettingspage.cpp
@@ -94,7 +94,7 @@ CodeGenSettingsPage::CodeGenSettingsPage(QObject *parent) :
{
m_parameters.fromSettings(Core::ICore::settings());
setId(Constants::CODEGEN_SETTINGS_PAGE_ID);
- setDisplayName(QCoreApplication::translate("QtSupport", Constants::CODEGEN_SETTINGS_PAGE_NAME));
+ setDisplayName(QCoreApplication::translate("QtSupport", "Qt Class Generation"));
setCategory(CppTools::Constants::CPP_SETTINGS_CATEGORY);
}
diff --git a/src/plugins/qtsupport/desktopqtversion.cpp b/src/plugins/qtsupport/desktopqtversion.cpp
index fa7ae205bc..c3d23cb5bf 100644
--- a/src/plugins/qtsupport/desktopqtversion.cpp
+++ b/src/plugins/qtsupport/desktopqtversion.cpp
@@ -38,7 +38,7 @@
#include <QCoreApplication>
#include <QFileInfo>
-using namespace QtSupport;
+namespace QtSupport {
DesktopQtVersion::DesktopQtVersion()
: BaseQtVersion()
@@ -46,22 +46,6 @@ DesktopQtVersion::DesktopQtVersion()
}
-DesktopQtVersion::DesktopQtVersion(const Utils::FileName &path, bool isAutodetected, const QString &autodetectionSource)
- : BaseQtVersion(path, isAutodetected, autodetectionSource)
-{
- setUnexpandedDisplayName(defaultUnexpandedDisplayName(path, false));
-}
-
-DesktopQtVersion *DesktopQtVersion::clone() const
-{
- return new DesktopQtVersion(*this);
-}
-
-QString DesktopQtVersion::type() const
-{
- return QLatin1String(Constants::DESKTOPQT);
-}
-
QStringList DesktopQtVersion::warningReason() const
{
QStringList ret = BaseQtVersion::warningReason();
@@ -72,11 +56,6 @@ QStringList DesktopQtVersion::warningReason() const
return ret;
}
-QList<ProjectExplorer::Abi> DesktopQtVersion::detectQtAbis() const
-{
- return qtAbisFromLibrary(qtCorePaths());
-}
-
QString DesktopQtVersion::description() const
{
return QCoreApplication::translate("QtVersion", "Desktop", "Qt Version is meant for the desktop");
@@ -101,6 +80,7 @@ QSet<Core::Id> DesktopQtVersion::targetDeviceTypes() const
void DesktopQtVersion::fromMap(const QVariantMap &map)
{
BaseQtVersion::fromMap(map);
+ // Clear the cached qmlscene command, it might not match the restored path anymore.
m_qmlsceneCommand.clear();
}
@@ -108,28 +88,31 @@ QString DesktopQtVersion::qmlsceneCommand() const
{
if (!isValid())
return QString();
+
if (!m_qmlsceneCommand.isNull())
return m_qmlsceneCommand;
- m_qmlsceneCommand = findTargetBinary(QmlScene);
+
+ ensureMkSpecParsed();
+
+ const QString path =
+ qmlBinPath().pathAppended(Utils::HostOsInfo::withExecutableSuffix("qmlscene")).toString();
+
+ m_qmlsceneCommand = QFileInfo(path).isFile() ? path : QString();
+
return m_qmlsceneCommand;
}
-DesktopQtVersion::DesktopQtVersion(const DesktopQtVersion &other) = default;
+namespace Internal {
-QString DesktopQtVersion::findTargetBinary(TargetBinaries binary) const
-{
- QString path;
-
- ensureMkSpecParsed();
- switch (binary) {
- case QmlScene:
- path = qmlBinPath().appendPath(
- Utils::HostOsInfo::withExecutableSuffix("qmlscene")).toString();
- break;
- default:
- // Can't happen
- QTC_ASSERT(false, return QString());
- }
+// Factory
- return QFileInfo(path).isFile() ? path : QString();
+DesktopQtVersionFactory::DesktopQtVersionFactory()
+{
+ setQtVersionCreator([] { return new DesktopQtVersion; });
+ setSupportedType(QtSupport::Constants::DESKTOPQT);
+ setPriority(0); // Lowest of all, we want to be the fallback
+ // No further restrictions. We are the fallback :) so we don't care what kind of qt it is.
}
+
+} // Internal
+} // QtSupport
diff --git a/src/plugins/qtsupport/desktopqtversion.h b/src/plugins/qtsupport/desktopqtversion.h
index 3ab82689ae..01e304e23e 100644
--- a/src/plugins/qtsupport/desktopqtversion.h
+++ b/src/plugins/qtsupport/desktopqtversion.h
@@ -25,6 +25,8 @@
#pragma once
+#include <qtsupport/qtversionfactory.h>
+
#include "baseqtversion.h"
namespace QtSupport {
@@ -33,15 +35,9 @@ class QTSUPPORT_EXPORT DesktopQtVersion : public BaseQtVersion
{
public:
DesktopQtVersion();
- DesktopQtVersion(const Utils::FileName &path, bool isAutodetected = false, const QString &autodetectionSource = QString());
- DesktopQtVersion *clone() const override;
-
- QString type() const override;
QStringList warningReason() const override;
- QList<ProjectExplorer::Abi> detectQtAbis() const override;
-
QString description() const override;
QSet<Core::Id> availableFeatures() const override;
@@ -51,15 +47,17 @@ public:
QString qmlsceneCommand() const;
-protected:
- DesktopQtVersion(const DesktopQtVersion &other);
-
private:
+ mutable QString m_qmlsceneCommand;
+};
- enum TargetBinaries { QmlScene };
- QString findTargetBinary(TargetBinaries binary) const;
+namespace Internal {
- mutable QString m_qmlsceneCommand;
+class DesktopQtVersionFactory : public QtVersionFactory
+{
+public:
+ DesktopQtVersionFactory();
};
+} // Internal
} // QtSupport
diff --git a/src/plugins/qtsupport/desktopqtversionfactory.cpp b/src/plugins/qtsupport/desktopqtversionfactory.cpp
deleted file mode 100644
index ac633aa58c..0000000000
--- a/src/plugins/qtsupport/desktopqtversionfactory.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 "desktopqtversionfactory.h"
-#include "desktopqtversion.h"
-#include <qtsupport/qtsupportconstants.h>
-
-#include <QFileInfo>
-
-using namespace QtSupport;
-using namespace QtSupport::Internal;
-
-DesktopQtVersionFactory::DesktopQtVersionFactory(QObject *parent)
- : QtVersionFactory(parent)
-{
-
-}
-
-DesktopQtVersionFactory::~DesktopQtVersionFactory() = default;
-
-bool DesktopQtVersionFactory::canRestore(const QString &type)
-{
- return type == QLatin1String(Constants::DESKTOPQT);
-}
-
-BaseQtVersion *DesktopQtVersionFactory::restore(const QString &type, const QVariantMap &data)
-{
- if (!canRestore(type))
- return nullptr;
- auto v = new DesktopQtVersion;
- v->fromMap(data);
- return v;
-}
-
-int DesktopQtVersionFactory::priority() const
-{
- // Lowest of all, we want to be the fallback
- return 0;
-}
-
-BaseQtVersion *DesktopQtVersionFactory::create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator, bool isAutoDetected, const QString &autoDetectionSource)
-{
- Q_UNUSED(evaluator);
- // we are the fallback :) so we don't care what kind of qt it is
- QFileInfo fi = qmakePath.toFileInfo();
- if (fi.exists() && fi.isExecutable() && fi.isFile())
- return new DesktopQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
- return nullptr;
-}
diff --git a/src/plugins/qtsupport/desktopqtversionfactory.h b/src/plugins/qtsupport/desktopqtversionfactory.h
deleted file mode 100644
index 7f5f476d45..0000000000
--- a/src/plugins/qtsupport/desktopqtversionfactory.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 "qtversionfactory.h"
-
-namespace QtSupport {
-namespace Internal {
-
-class DesktopQtVersionFactory : public QtVersionFactory
-{
-public:
- explicit DesktopQtVersionFactory(QObject *parent = nullptr);
- ~DesktopQtVersionFactory() override;
-
- bool canRestore(const QString &type) override;
- BaseQtVersion *restore(const QString &type, const QVariantMap &data) override;
-
- int priority() const override;
- BaseQtVersion *create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator,
- bool isAutoDetected = false, const QString &autoDetectionSource = QString()) override;
-};
-
-} // Internal
-} // QtSupport
diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp
index f83496ef54..ee0d88088a 100644
--- a/src/plugins/qtsupport/exampleslistmodel.cpp
+++ b/src/plugins/qtsupport/exampleslistmodel.cpp
@@ -504,7 +504,7 @@ void ExampleSetModel::updateQtVersionList()
// prioritize default qt version
ProjectExplorer::Kit *defaultKit = ProjectExplorer::KitManager::defaultKit();
- BaseQtVersion *defaultVersion = QtKitInformation::qtVersion(defaultKit);
+ BaseQtVersion *defaultVersion = QtKitAspect::qtVersion(defaultKit);
if (defaultVersion && versions.contains(defaultVersion))
versions.move(versions.indexOf(defaultVersion), 0);
diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
index 943b9d08bd..fdc594866e 100644
--- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
+++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
@@ -151,17 +151,17 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI
} else {
QString error;
QString targetDir = destBaseDir + QLatin1Char('/') + exampleDirName;
- if (FileUtils::copyRecursively(FileName::fromString(projectDir),
- FileName::fromString(targetDir), &error)) {
+ if (FileUtils::copyRecursively(FilePath::fromString(projectDir),
+ FilePath::fromString(targetDir), &error)) {
// set vars to new location
const QStringList::Iterator end = filesToOpen.end();
for (QStringList::Iterator it = filesToOpen.begin(); it != end; ++it)
it->replace(projectDir, targetDir);
foreach (const QString &dependency, dependencies) {
- FileName targetFile = FileName::fromString(targetDir);
- targetFile.appendPath(QDir(dependency).dirName());
- if (!FileUtils::copyRecursively(FileName::fromString(dependency), targetFile,
+ const FilePath targetFile = FilePath::fromString(targetDir)
+ .pathAppended(QDir(dependency).dirName());
+ if (!FileUtils::copyRecursively(FilePath::fromString(dependency), targetFile,
&error)) {
QMessageBox::warning(ICore::mainWindow(), tr("Cannot Copy Project"), error);
// do not fail, just warn;
@@ -544,7 +544,7 @@ public:
int xx = 0;
int yy = y + tagsBase;
for (const QString &tag : item.tags) {
- const int ww = tagsFontMetrics.width(tag) + 5;
+ const int ww = tagsFontMetrics.horizontalAdvance(tag) + 5;
if (xx + ww > w - 30) {
yy += 15;
xx = 0;
@@ -644,7 +644,7 @@ public:
ExampleSetModel *exampleSetModel = m_examplesModel->exampleSetModel();
exampleSetSelector->setModel(exampleSetModel);
exampleSetSelector->setCurrentIndex(exampleSetModel->selectedExampleSet());
- connect(exampleSetSelector, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(exampleSetSelector, QOverload<int>::of(&QComboBox::activated),
exampleSetModel, &ExampleSetModel::selectExampleSet);
connect(exampleSetModel, &ExampleSetModel::selectedExampleSetChanged,
exampleSetSelector, &QComboBox::setCurrentIndex);
diff --git a/src/plugins/qtsupport/qmldumptool.cpp b/src/plugins/qtsupport/qmldumptool.cpp
index 045353d004..dc9f766144 100644
--- a/src/plugins/qtsupport/qmldumptool.cpp
+++ b/src/plugins/qtsupport/qmldumptool.cpp
@@ -85,7 +85,7 @@ void QmlDumpTool::pathAndEnvironment(const ProjectExplorer::Kit *k, bool preferD
if (!k)
return;
- const BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
+ const BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
if (version && !version->hasQmlDump())
return;
diff --git a/src/plugins/qtsupport/qscxmlcgenerator.cpp b/src/plugins/qtsupport/qscxmlcgenerator.cpp
index 7874cde57d..415a6ea701 100644
--- a/src/plugins/qtsupport/qscxmlcgenerator.cpp
+++ b/src/plugins/qtsupport/qscxmlcgenerator.cpp
@@ -42,8 +42,8 @@ static QLoggingCategory log("qtc.qscxmlcgenerator", QtWarningMsg);
static const char TaskCategory[] = "Task.Category.ExtraCompiler.QScxmlc";
QScxmlcGenerator::QScxmlcGenerator(const Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent) :
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent) :
ProcessExtraCompiler(project, source, targets, parent),
m_tmpdir("qscxmlgenerator")
{
@@ -52,14 +52,14 @@ QScxmlcGenerator::QScxmlcGenerator(const Project *project,
m_impl = m_tmpdir.path() + QLatin1Char('/') + targets[1].fileName();
}
-QList<Task> QScxmlcGenerator::parseIssues(const QByteArray &processStderr)
+Tasks QScxmlcGenerator::parseIssues(const QByteArray &processStderr)
{
- QList<Task> issues;
+ Tasks issues;
foreach (const QByteArray &line, processStderr.split('\n')) {
QByteArrayList tokens = line.split(':');
if (tokens.length() > 4) {
- Utils::FileName file = Utils::FileName::fromUtf8(tokens[0]);
+ Utils::FilePath file = Utils::FilePath::fromUtf8(tokens[0]);
int line = tokens[1].toInt();
// int column = tokens[2].toInt(); <- nice, but not needed for now.
Task::TaskType type = tokens[3].trimmed() == "error" ?
@@ -72,19 +72,19 @@ QList<Task> QScxmlcGenerator::parseIssues(const QByteArray &processStderr)
}
-Utils::FileName QScxmlcGenerator::command() const
+Utils::FilePath QScxmlcGenerator::command() const
{
QtSupport::BaseQtVersion *version = nullptr;
Target *target;
if ((target = project()->activeTarget()))
- version = QtSupport::QtKitInformation::qtVersion(target->kit());
+ version = QtSupport::QtKitAspect::qtVersion(target->kit());
else
- version = QtSupport::QtKitInformation::qtVersion(KitManager::defaultKit());
+ version = QtSupport::QtKitAspect::qtVersion(KitManager::defaultKit());
if (!version)
- return Utils::FileName();
+ return Utils::FilePath();
- return Utils::FileName::fromString(version->qscxmlcCommand());
+ return Utils::FilePath::fromString(version->qscxmlcCommand());
}
QStringList QScxmlcGenerator::arguments() const
@@ -95,14 +95,14 @@ QStringList QScxmlcGenerator::arguments() const
tmpFile().fileName()});
}
-Utils::FileName QScxmlcGenerator::workingDirectory() const
+Utils::FilePath QScxmlcGenerator::workingDirectory() const
{
- return Utils::FileName::fromString(m_tmpdir.path());
+ return Utils::FilePath::fromString(m_tmpdir.path());
}
bool QScxmlcGenerator::prepareToRun(const QByteArray &sourceContents)
{
- const Utils::FileName fn = tmpFile();
+ const Utils::FilePath fn = tmpFile();
QFile input(fn.toString());
if (!input.open(QIODevice::WriteOnly))
return false;
@@ -115,11 +115,10 @@ bool QScxmlcGenerator::prepareToRun(const QByteArray &sourceContents)
FileNameToContentsHash QScxmlcGenerator::handleProcessFinished(QProcess *process)
{
Q_UNUSED(process);
- const Utils::FileName wd = workingDirectory();
+ const Utils::FilePath wd = workingDirectory();
FileNameToContentsHash result;
- forEachTarget([&](const Utils::FileName &target) {
- Utils::FileName file = wd;
- file.appendPath(target.fileName());
+ forEachTarget([&](const Utils::FilePath &target) {
+ const Utils::FilePath file = wd.pathAppended(target.fileName());
QFile generated(file.toString());
if (!generated.open(QIODevice::ReadOnly))
return;
@@ -128,11 +127,9 @@ FileNameToContentsHash QScxmlcGenerator::handleProcessFinished(QProcess *process
return result;
}
-Utils::FileName QScxmlcGenerator::tmpFile() const
+Utils::FilePath QScxmlcGenerator::tmpFile() const
{
- Utils::FileName wd = workingDirectory();
- wd.appendPath(source().fileName());
- return wd;
+ return workingDirectory().pathAppended(source().fileName());
}
FileType QScxmlcGeneratorFactory::sourceType() const
@@ -146,8 +143,8 @@ QString QScxmlcGeneratorFactory::sourceTag() const
}
ExtraCompiler *QScxmlcGeneratorFactory::create(
- const Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets)
+ const Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets)
{
annouceCreation(project, source, targets);
diff --git a/src/plugins/qtsupport/qscxmlcgenerator.h b/src/plugins/qtsupport/qscxmlcgenerator.h
index 64a852c9e6..37c7617ed6 100644
--- a/src/plugins/qtsupport/qscxmlcgenerator.h
+++ b/src/plugins/qtsupport/qscxmlcgenerator.h
@@ -37,19 +37,19 @@ class QScxmlcGenerator : public ProjectExplorer::ProcessExtraCompiler
{
Q_OBJECT
public:
- QScxmlcGenerator(const ProjectExplorer::Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent = 0);
+ QScxmlcGenerator(const ProjectExplorer::Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent = 0);
protected:
- Utils::FileName command() const override;
+ Utils::FilePath command() const override;
QStringList arguments() const override;
- Utils::FileName workingDirectory() const override;
+ Utils::FilePath workingDirectory() const override;
private:
- Utils::FileName tmpFile() const;
+ Utils::FilePath tmpFile() const;
ProjectExplorer::FileNameToContentsHash handleProcessFinished(QProcess *process) override;
bool prepareToRun(const QByteArray &sourceContents) override;
- QList<ProjectExplorer::Task> parseIssues(const QByteArray &processStderr) override;
+ ProjectExplorer::Tasks parseIssues(const QByteArray &processStderr) override;
Utils::TemporaryDirectory m_tmpdir;
QString m_header;
@@ -67,8 +67,8 @@ public:
QString sourceTag() const override;
ProjectExplorer::ExtraCompiler *create(const ProjectExplorer::Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets) override;
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets) override;
};
} // QtSupport
diff --git a/src/plugins/qtsupport/qtcppkitinfo.cpp b/src/plugins/qtsupport/qtcppkitinfo.cpp
index 2028400ee4..07e404cce4 100644
--- a/src/plugins/qtsupport/qtcppkitinfo.cpp
+++ b/src/plugins/qtsupport/qtcppkitinfo.cpp
@@ -35,7 +35,7 @@ using namespace CppTools;
CppKitInfo::CppKitInfo(ProjectExplorer::Project *project)
: KitInfo(project)
{
- if (kit && (qtVersion = QtKitInformation::qtVersion(kit))) {
+ if (kit && (qtVersion = QtKitAspect::qtVersion(kit))) {
if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0))
projectPartQtVersion = ProjectPart::Qt4;
else
diff --git a/src/plugins/qtsupport/qtkitconfigwidget.cpp b/src/plugins/qtsupport/qtkitconfigwidget.cpp
deleted file mode 100644
index 8b32ba44de..0000000000
--- a/src/plugins/qtsupport/qtkitconfigwidget.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 "qtkitconfigwidget.h"
-
-#include "qtsupportconstants.h"
-#include "qtkitinformation.h"
-#include "qtversionmanager.h"
-
-#include <coreplugin/icore.h>
-
-#include <utils/qtcassert.h>
-#include <utils/algorithm.h>
-
-#include <QComboBox>
-#include <QPushButton>
-
-namespace QtSupport {
-namespace Internal {
-
-QtKitConfigWidget::QtKitConfigWidget(ProjectExplorer::Kit *k, const ProjectExplorer::KitInformation *ki) :
- KitConfigWidget(k, ki)
-{
- m_combo = new QComboBox;
- m_combo->setSizePolicy(QSizePolicy::Ignored, m_combo->sizePolicy().verticalPolicy());
- m_combo->addItem(tr("None"), -1);
-
- QList<int> versionIds = Utils::transform(QtVersionManager::versions(), &BaseQtVersion::uniqueId);
- versionsChanged(versionIds, QList<int>(), QList<int>());
-
- m_manageButton = new QPushButton(KitConfigWidget::msgManage());
-
- refresh();
- m_combo->setToolTip(toolTip());
-
- connect(m_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &QtKitConfigWidget::currentWasChanged);
-
- connect(QtVersionManager::instance(), &QtVersionManager::qtVersionsChanged,
- this, &QtKitConfigWidget::versionsChanged);
-
- connect(m_manageButton, &QAbstractButton::clicked, this, &QtKitConfigWidget::manageQtVersions);
-}
-
-QtKitConfigWidget::~QtKitConfigWidget()
-{
- delete m_combo;
- delete m_manageButton;
-}
-
-QString QtKitConfigWidget::displayName() const
-{
- return tr("Qt version");
-}
-
-QString QtKitConfigWidget::toolTip() const
-{
- return tr("The Qt library to use for all projects using this kit.<br>"
- "A Qt version is required for qmake-based projects "
- "and optional when using other build systems.");
-}
-
-void QtKitConfigWidget::makeReadOnly()
-{
- m_combo->setEnabled(false);
-}
-
-void QtKitConfigWidget::refresh()
-{
- m_combo->setCurrentIndex(findQtVersion(QtKitInformation::qtVersionId(m_kit)));
-}
-
-QWidget *QtKitConfigWidget::mainWidget() const
-{
- return m_combo;
-}
-
-QWidget *QtKitConfigWidget::buttonWidget() const
-{
- return m_manageButton;
-}
-
-static QString itemNameFor(const BaseQtVersion *v)
-{
- QTC_ASSERT(v, return QString());
- QString name = v->displayName();
- if (!v->isValid())
- name = QCoreApplication::translate("QtSupport::Internal::QtKitConfigWidget", "%1 (invalid)").arg(v->displayName());
- return name;
-}
-
-void QtKitConfigWidget::versionsChanged(const QList<int> &added, const QList<int> &removed,
- const QList<int> &changed)
-{
- foreach (const int id, added) {
- BaseQtVersion *v = QtVersionManager::version(id);
- QTC_CHECK(v);
- QTC_CHECK(findQtVersion(id) < 0);
- m_combo->addItem(itemNameFor(v), id);
- }
- foreach (const int id, removed) {
- int pos = findQtVersion(id);
- if (pos >= 0) // We do not include invalid Qt versions, so do not try to remove those.
- m_combo->removeItem(pos);
- }
- foreach (const int id, changed) {
- BaseQtVersion *v = QtVersionManager::version(id);
- int pos = findQtVersion(id);
- QTC_CHECK(pos >= 0);
- m_combo->setItemText(pos, itemNameFor(v));
- }
-}
-
-void QtKitConfigWidget::manageQtVersions()
-{
- Core::ICore::showOptionsDialog(Constants::QTVERSION_SETTINGS_PAGE_ID, buttonWidget());
-}
-
-void QtKitConfigWidget::currentWasChanged(int idx)
-{
- QtKitInformation::setQtVersionId(m_kit, m_combo->itemData(idx).toInt());
-}
-
-int QtKitConfigWidget::findQtVersion(const int id) const
-{
- for (int i = 0; i < m_combo->count(); ++i) {
- if (id == m_combo->itemData(i).toInt())
- return i;
- }
- return -1;
-}
-
-} // namespace Internal
-} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qtkitconfigwidget.h b/src/plugins/qtsupport/qtkitconfigwidget.h
deleted file mode 100644
index 76cd30d5b5..0000000000
--- a/src/plugins/qtsupport/qtkitconfigwidget.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 <projectexplorer/kitconfigwidget.h>
-
-QT_BEGIN_NAMESPACE
-class QComboBox;
-class QPushButton;
-QT_END_NAMESPACE
-
-namespace QtSupport {
-namespace Internal {
-
-class QtKitConfigWidget : public ProjectExplorer::KitConfigWidget
-{
- Q_OBJECT
-
-public:
- QtKitConfigWidget(ProjectExplorer::Kit *k, const ProjectExplorer::KitInformation *ki);
- ~QtKitConfigWidget() override;
-
- QString displayName() const override;
-
- void makeReadOnly() override;
-
- void refresh() override;
- QWidget *mainWidget() const override;
- QWidget *buttonWidget() const override;
- QString toolTip() const override;
-
-private:
- void versionsChanged(const QList<int> &added, const QList<int> &removed, const QList<int> &changed);
- void manageQtVersions();
- void currentWasChanged(int idx);
- int findQtVersion(const int id) const;
-
- QComboBox *m_combo;
- QPushButton *m_manageButton;
-};
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp
index 3e55fb3fd0..3319aa732a 100644
--- a/src/plugins/qtsupport/qtkitinformation.cpp
+++ b/src/plugins/qtsupport/qtkitinformation.cpp
@@ -27,51 +27,173 @@
#include <QRegExp>
-#include "qtkitconfigwidget.h"
#include "qtsupportconstants.h"
#include "qtversionmanager.h"
#include "qtparser.h"
+#include "qttestparser.h"
+#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/task.h>
-
#include <utils/algorithm.h>
#include <utils/buildablehelperlibrary.h>
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
+#include <QComboBox>
+#include <QPushButton>
+
using namespace ProjectExplorer;
using namespace Utils;
namespace QtSupport {
+namespace Internal {
-QtKitInformation::QtKitInformation()
+class QtKitAspectWidget : public KitAspectWidget
{
- setObjectName(QLatin1String("QtKitInformation"));
- setId(QtKitInformation::id());
+ Q_DECLARE_TR_FUNCTIONS(QtSupport::QtKitAspectWidget)
+public:
+ QtKitAspectWidget(Kit *k, const KitAspect *ki) : KitAspectWidget(k, ki)
+ {
+ m_combo = new QComboBox;
+ m_combo->setSizePolicy(QSizePolicy::Ignored, m_combo->sizePolicy().verticalPolicy());
+ m_combo->addItem(tr("None"), -1);
+
+ QList<int> versionIds = Utils::transform(QtVersionManager::versions(), &BaseQtVersion::uniqueId);
+ versionsChanged(versionIds, QList<int>(), QList<int>());
+
+ m_manageButton = new QPushButton(KitAspectWidget::msgManage());
+
+ refresh();
+ m_combo->setToolTip(ki->description());
+
+ connect(m_combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &QtKitAspectWidget::currentWasChanged);
+
+ connect(QtVersionManager::instance(), &QtVersionManager::qtVersionsChanged,
+ this, &QtKitAspectWidget::versionsChanged);
+
+ connect(m_manageButton, &QAbstractButton::clicked, this, &QtKitAspectWidget::manageQtVersions);
+ }
+
+ ~QtKitAspectWidget() override
+ {
+ delete m_combo;
+ delete m_manageButton;
+ }
+
+private:
+ void makeReadOnly() override { m_combo->setEnabled(false); }
+ QWidget *mainWidget() const override { return m_combo; }
+ QWidget *buttonWidget() const override { return m_manageButton; }
+
+ void refresh() override
+ {
+ m_combo->setCurrentIndex(findQtVersion(QtKitAspect::qtVersionId(m_kit)));
+ }
+
+private:
+ static QString itemNameFor(const BaseQtVersion *v)
+ {
+ QTC_ASSERT(v, return QString());
+ QString name = v->displayName();
+ if (!v->isValid())
+ name = QCoreApplication::translate("QtSupport::Internal::QtKitConfigWidget", "%1 (invalid)").arg(v->displayName());
+ return name;
+ }
+
+ void versionsChanged(const QList<int> &added, const QList<int> &removed, const QList<int> &changed)
+ {
+ foreach (const int id, added) {
+ BaseQtVersion *v = QtVersionManager::version(id);
+ QTC_CHECK(v);
+ QTC_CHECK(findQtVersion(id) < 0);
+ m_combo->addItem(itemNameFor(v), id);
+ }
+ foreach (const int id, removed) {
+ int pos = findQtVersion(id);
+ if (pos >= 0) // We do not include invalid Qt versions, so do not try to remove those.
+ m_combo->removeItem(pos);
+ }
+ foreach (const int id, changed) {
+ BaseQtVersion *v = QtVersionManager::version(id);
+ int pos = findQtVersion(id);
+ QTC_CHECK(pos >= 0);
+ m_combo->setItemText(pos, itemNameFor(v));
+ }
+ }
+
+ void manageQtVersions()
+ {
+ Core::ICore::showOptionsDialog(Constants::QTVERSION_SETTINGS_PAGE_ID, buttonWidget());
+ }
+
+ void currentWasChanged(int idx)
+ {
+ QtKitAspect::setQtVersionId(m_kit, m_combo->itemData(idx).toInt());
+ }
+
+ int findQtVersion(const int id) const
+ {
+ for (int i = 0; i < m_combo->count(); ++i) {
+ if (id == m_combo->itemData(i).toInt())
+ return i;
+ }
+ return -1;
+ }
+
+ QComboBox *m_combo;
+ QPushButton *m_manageButton;
+};
+} // namespace Internal
+
+QtKitAspect::QtKitAspect()
+{
+ setObjectName(QLatin1String("QtKitAspect"));
+ setId(QtKitAspect::id());
+ setDisplayName(tr("Qt version"));
+ setDescription(tr("The Qt library to use for all projects using this kit.<br>"
+ "A Qt version is required for qmake-based projects "
+ "and optional when using other build systems."));
setPriority(26000);
connect(KitManager::instance(), &KitManager::kitsLoaded,
- this, &QtKitInformation::kitsWereLoaded);
+ this, &QtKitAspect::kitsWereLoaded);
}
-QVariant QtKitInformation::defaultValue(const Kit *k) const
+void QtKitAspect::setup(ProjectExplorer::Kit *k)
{
- Q_UNUSED(k);
-
- // find "Qt in PATH":
- BaseQtVersion *result = QtVersionManager::version(equal(&BaseQtVersion::autodetectionSource,
- QString::fromLatin1("PATH")));
- if (result)
- return result->uniqueId();
-
- // Use *any* desktop Qt:
- result = QtVersionManager::version(equal(&BaseQtVersion::type,
- QString::fromLatin1(QtSupport::Constants::DESKTOPQT)));
- return result ? result->uniqueId() : -1;
+ if (!k || k->hasValue(id()))
+ return;
+ const Abi tcAbi = ToolChainKitAspect::targetAbi(k);
+ const Core::Id deviceType = DeviceTypeKitAspect::deviceTypeId(k);
+
+ const QList<BaseQtVersion *> matches
+ = QtVersionManager::versions([&tcAbi, &deviceType](const BaseQtVersion *qt) {
+ return qt->targetDeviceTypes().contains(deviceType)
+ && Utils::contains(qt->qtAbis(), [&tcAbi](const Abi &qtAbi) {
+ return qtAbi.isCompatibleWith(tcAbi); });
+ });
+ if (matches.empty())
+ return;
+
+ // An MSVC 2015 toolchain is compatible with an MSVC 2017 Qt, but we prefer an
+ // MSVC 2015 Qt if we find one.
+ const QList<BaseQtVersion *> exactMatches = Utils::filtered(matches,
+ [&tcAbi](const BaseQtVersion *qt) {
+ return qt->qtAbis().contains(tcAbi);
+ });
+ const QList<BaseQtVersion *> &candidates = !exactMatches.empty() ? exactMatches : matches;
+
+ BaseQtVersion * const qtFromPath = QtVersionManager::version(
+ equal(&BaseQtVersion::autodetectionSource, QString::fromLatin1("PATH")));
+ if (qtFromPath && candidates.contains(qtFromPath))
+ k->setValue(id(), qtFromPath->uniqueId());
+ else
+ k->setValue(id(), candidates.first()->uniqueId());
}
-QList<ProjectExplorer::Task> QtKitInformation::validate(const ProjectExplorer::Kit *k) const
+Tasks QtKitAspect::validate(const ProjectExplorer::Kit *k) const
{
QTC_ASSERT(QtVersionManager::isLoaded(), return { });
BaseQtVersion *version = qtVersion(k);
@@ -81,7 +203,7 @@ QList<ProjectExplorer::Task> QtKitInformation::validate(const ProjectExplorer::K
return version->validateKit(k);
}
-void QtKitInformation::fix(ProjectExplorer::Kit *k)
+void QtKitAspect::fix(ProjectExplorer::Kit *k)
{
QTC_ASSERT(QtVersionManager::isLoaded(), return);
BaseQtVersion *version = qtVersion(k);
@@ -91,36 +213,39 @@ void QtKitInformation::fix(ProjectExplorer::Kit *k)
}
}
-ProjectExplorer::KitConfigWidget *QtKitInformation::createConfigWidget(ProjectExplorer::Kit *k) const
+ProjectExplorer::KitAspectWidget *QtKitAspect::createConfigWidget(ProjectExplorer::Kit *k) const
{
QTC_ASSERT(k, return nullptr);
- return new Internal::QtKitConfigWidget(k, this);
+ return new Internal::QtKitAspectWidget(k, this);
}
-QString QtKitInformation::displayNamePostfix(const ProjectExplorer::Kit *k) const
+QString QtKitAspect::displayNamePostfix(const ProjectExplorer::Kit *k) const
{
BaseQtVersion *version = qtVersion(k);
return version ? version->displayName() : QString();
}
-ProjectExplorer::KitInformation::ItemList
-QtKitInformation::toUserOutput(const ProjectExplorer::Kit *k) const
+ProjectExplorer::KitAspect::ItemList
+QtKitAspect::toUserOutput(const ProjectExplorer::Kit *k) const
{
BaseQtVersion *version = qtVersion(k);
- return ItemList() << qMakePair(tr("Qt version"), version ? version->displayName() : tr("None"));
+ return {{tr("Qt version"), version ? version->displayName() : tr("None")}};
}
-void QtKitInformation::addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const
+void QtKitAspect::addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const
{
BaseQtVersion *version = qtVersion(k);
if (version)
version->addToEnvironment(k, env);
}
-ProjectExplorer::IOutputParser *QtKitInformation::createOutputParser(const ProjectExplorer::Kit *k) const
+ProjectExplorer::IOutputParser *QtKitAspect::createOutputParser(const ProjectExplorer::Kit *k) const
{
- if (qtVersion(k))
- return new QtParser;
+ if (qtVersion(k)) {
+ const auto parser = new Internal::QtTestParser;
+ parser->appendOutputParser(new QtParser);
+ return parser;
+ }
return nullptr;
}
@@ -129,7 +254,7 @@ class QtMacroSubProvider
public:
QtMacroSubProvider(Kit *kit)
: expander(BaseQtVersion::createMacroExpander(
- [kit] { return QtKitInformation::qtVersion(kit); }))
+ [kit] { return QtKitAspect::qtVersion(kit); }))
{}
MacroExpander *operator()() const
@@ -140,7 +265,7 @@ public:
std::shared_ptr<MacroExpander> expander;
};
-void QtKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expander) const
+void QtKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
QTC_ASSERT(kit, return);
expander->registerSubProvider(QtMacroSubProvider(kit));
@@ -157,18 +282,18 @@ void QtKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expander) con
});
}
-Core::Id QtKitInformation::id()
+Core::Id QtKitAspect::id()
{
return "QtSupport.QtInformation";
}
-int QtKitInformation::qtVersionId(const ProjectExplorer::Kit *k)
+int QtKitAspect::qtVersionId(const ProjectExplorer::Kit *k)
{
if (!k)
return -1;
int id = -1;
- QVariant data = k->value(QtKitInformation::id(), -1);
+ QVariant data = k->value(QtKitAspect::id(), -1);
if (data.type() == QVariant::Int) {
bool ok;
id = data.toInt(&ok);
@@ -183,18 +308,18 @@ int QtKitInformation::qtVersionId(const ProjectExplorer::Kit *k)
return id;
}
-void QtKitInformation::setQtVersionId(ProjectExplorer::Kit *k, const int id)
+void QtKitAspect::setQtVersionId(ProjectExplorer::Kit *k, const int id)
{
QTC_ASSERT(k, return);
- k->setValue(QtKitInformation::id(), id);
+ k->setValue(QtKitAspect::id(), id);
}
-BaseQtVersion *QtKitInformation::qtVersion(const ProjectExplorer::Kit *k)
+BaseQtVersion *QtKitAspect::qtVersion(const ProjectExplorer::Kit *k)
{
return QtVersionManager::version(qtVersionId(k));
}
-void QtKitInformation::setQtVersion(ProjectExplorer::Kit *k, const BaseQtVersion *v)
+void QtKitAspect::setQtVersion(ProjectExplorer::Kit *k, const BaseQtVersion *v)
{
if (!v)
setQtVersionId(k, -1);
@@ -202,7 +327,7 @@ void QtKitInformation::setQtVersion(ProjectExplorer::Kit *k, const BaseQtVersion
setQtVersionId(k, v->uniqueId());
}
-void QtKitInformation::qtVersionsChanged(const QList<int> &addedIds,
+void QtKitAspect::qtVersionsChanged(const QList<int> &addedIds,
const QList<int> &removedIds,
const QList<int> &changedIds)
{
@@ -216,29 +341,29 @@ void QtKitInformation::qtVersionsChanged(const QList<int> &addedIds,
}
}
-void QtKitInformation::kitsWereLoaded()
+void QtKitAspect::kitsWereLoaded()
{
foreach (ProjectExplorer::Kit *k, ProjectExplorer::KitManager::kits())
fix(k);
connect(QtVersionManager::instance(), &QtVersionManager::qtVersionsChanged,
- this, &QtKitInformation::qtVersionsChanged);
+ this, &QtKitAspect::qtVersionsChanged);
}
-Kit::Predicate QtKitInformation::platformPredicate(Core::Id platform)
+Kit::Predicate QtKitAspect::platformPredicate(Core::Id platform)
{
return [platform](const Kit *kit) -> bool {
- BaseQtVersion *version = QtKitInformation::qtVersion(kit);
+ BaseQtVersion *version = QtKitAspect::qtVersion(kit);
return version && version->targetDeviceTypes().contains(platform);
};
}
-Kit::Predicate QtKitInformation::qtVersionPredicate(const QSet<Core::Id> &required,
+Kit::Predicate QtKitAspect::qtVersionPredicate(const QSet<Core::Id> &required,
const QtVersionNumber &min,
const QtVersionNumber &max)
{
return [required, min, max](const Kit *kit) -> bool {
- BaseQtVersion *version = QtKitInformation::qtVersion(kit);
+ BaseQtVersion *version = QtKitAspect::qtVersion(kit);
if (!version)
return false;
QtVersionNumber current = version->qtVersion();
@@ -250,16 +375,30 @@ Kit::Predicate QtKitInformation::qtVersionPredicate(const QSet<Core::Id> &requir
};
}
-QSet<Core::Id> QtKitInformation::supportedPlatforms(const Kit *k) const
+QSet<Core::Id> QtKitAspect::supportedPlatforms(const Kit *k) const
{
- BaseQtVersion *version = QtKitInformation::qtVersion(k);
+ BaseQtVersion *version = QtKitAspect::qtVersion(k);
return version ? version->targetDeviceTypes() : QSet<Core::Id>();
}
-QSet<Core::Id> QtKitInformation::availableFeatures(const Kit *k) const
+QSet<Core::Id> QtKitAspect::availableFeatures(const Kit *k) const
{
- BaseQtVersion *version = QtKitInformation::qtVersion(k);
+ BaseQtVersion *version = QtKitAspect::qtVersion(k);
return version ? version->features() : QSet<Core::Id>();
}
+int QtKitAspect::weight(const Kit *k) const
+{
+ const BaseQtVersion * const qt = qtVersion(k);
+ if (!qt)
+ return 0;
+ if (!qt->targetDeviceTypes().contains(DeviceTypeKitAspect::deviceTypeId(k)))
+ return 0;
+ const Abi tcAbi = ToolChainKitAspect::targetAbi(k);
+ if (qt->qtAbis().contains(tcAbi))
+ return 2;
+ return Utils::contains(qt->qtAbis(), [&tcAbi](const Abi &qtAbi) {
+ return qtAbi.isCompatibleWith(tcAbi); }) ? 1 : 0;
+}
+
} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qtkitinformation.h b/src/plugins/qtsupport/qtkitinformation.h
index 459b9b2440..d155b8ea5f 100644
--- a/src/plugins/qtsupport/qtkitinformation.h
+++ b/src/plugins/qtsupport/qtkitinformation.h
@@ -35,19 +35,19 @@ namespace Utils { class MacroExpander; }
namespace QtSupport {
-class QTSUPPORT_EXPORT QtKitInformation : public ProjectExplorer::KitInformation
+class QTSUPPORT_EXPORT QtKitAspect : public ProjectExplorer::KitAspect
{
Q_OBJECT
public:
- QtKitInformation();
+ QtKitAspect();
- QVariant defaultValue(const ProjectExplorer::Kit *k) const override;
+ void setup(ProjectExplorer::Kit *k) override;
- QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *k) const override;
+ ProjectExplorer::Tasks validate(const ProjectExplorer::Kit *k) const override;
void fix(ProjectExplorer::Kit *) override;
- ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const override;
+ ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const override;
QString displayNamePostfix(const ProjectExplorer::Kit *k) const override;
@@ -73,6 +73,8 @@ public:
QSet<Core::Id> availableFeatures(const ProjectExplorer::Kit *k) const override;
private:
+ int weight(const ProjectExplorer::Kit *k) const override;
+
void qtVersionsChanged(const QList<int> &addedIds,
const QList<int> &removedIds,
const QList<int> &changedIds);
diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp
index f891f38184..c2269ebe07 100644
--- a/src/plugins/qtsupport/qtoptionspage.cpp
+++ b/src/plugins/qtsupport/qtoptionspage.cpp
@@ -156,7 +156,7 @@ QtOptionsPage::QtOptionsPage()
: m_widget(0)
{
setId(Constants::QTVERSION_SETTINGS_PAGE_ID);
- setDisplayName(QCoreApplication::translate("QtSupport", Constants::QTVERSION_SETTINGS_PAGE_NAME));
+ setDisplayName(QCoreApplication::translate("QtSupport", "Qt Versions"));
setCategory(ProjectExplorer::Constants::KITS_SETTINGS_CATEGORY);
}
@@ -258,9 +258,6 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent)
userChangedCurrentVersion();
updateCleanUpButton();
- connect(QtVersionManager::instance(), &QtVersionManager::dumpUpdatedFor,
- this, &QtOptionsPageWidget::qtVersionsDumpUpdated);
-
connect(QtVersionManager::instance(), &QtVersionManager::qtVersionsChanged,
this, &QtOptionsPageWidget::updateQtVersions);
@@ -333,19 +330,6 @@ void QtOptionsPageWidget::toolChainsUpdated()
});
}
-void QtOptionsPageWidget::qtVersionsDumpUpdated(const FileName &qmakeCommand)
-{
- m_model->forItemsAtLevel<2>([qmakeCommand](QtVersionItem *item) {
- if (item->version()->qmakeCommand() == qmakeCommand)
- item->version()->recheckDumper();
- });
-
- if (currentVersion() && currentVersion()->qmakeCommand() == qmakeCommand) {
- updateWidgets();
- updateDescriptionLabel();
- }
-}
-
void QtOptionsPageWidget::setInfoWidgetVisibility()
{
m_ui->versionInfoWidget->setVisible(m_ui->infoWidget->state() == DetailsWidget::Collapsed);
@@ -357,7 +341,7 @@ void QtOptionsPageWidget::infoAnchorClicked(const QUrl &url)
QDesktopServices::openUrl(url);
}
-static QString formatAbiHtmlList(const QList<Abi> &abis)
+static QString formatAbiHtmlList(const Abis &abis)
{
QString result = QStringLiteral("<ul><li>");
for (int i = 0, count = abis.size(); i < count; ++i) {
@@ -385,8 +369,8 @@ QtOptionsPageWidget::ValidityInfo QtOptionsPageWidget::validInformation(const Ba
}
// Do we have tool chain issues?
- QList<Abi> missingToolChains;
- const QList<Abi> qtAbis = version->qtAbis();
+ Abis missingToolChains;
+ const Abis qtAbis = version->qtAbis();
for (const Abi &abi : qtAbis) {
const auto abiCompatePred = [&abi] (const ToolChain *tc)
@@ -538,7 +522,7 @@ void QtOptionsPageWidget::updateQtVersions(const QList<int> &additions, const QL
// Add changed/added items:
foreach (int a, toAdd) {
- BaseQtVersion *version = QtVersionManager::version(a)->clone();
+ BaseQtVersion *version = QtVersionFactory::cloneQtVersion(QtVersionManager::version(a));
auto *item = new QtVersionItem(version);
// Insert in the right place:
@@ -558,20 +542,20 @@ QtOptionsPageWidget::~QtOptionsPageWidget()
void QtOptionsPageWidget::addQtDir()
{
- FileName qtVersion = FileName::fromString(
+ FilePath qtVersion = FilePath::fromString(
QFileDialog::getOpenFileName(this,
tr("Select a qmake Executable"),
QString(),
BuildableHelperLibrary::filterForQmakeFileDialog(),
0,
QFileDialog::DontResolveSymlinks));
- if (qtVersion.isNull())
+ if (qtVersion.isEmpty())
return;
QFileInfo fi = qtVersion.toFileInfo();
// should add all qt versions here ?
if (BuildableHelperLibrary::isQtChooser(fi))
- qtVersion = FileName::fromString(BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget()));
+ qtVersion = FilePath::fromString(BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget()));
auto checkAlreadyExists = [qtVersion](Utils::TreeItem *parent) {
for (int i = 0; i < parent->childCount(); ++i) {
@@ -630,14 +614,14 @@ void QtOptionsPageWidget::editPath()
{
BaseQtVersion *current = currentVersion();
QString dir = currentVersion()->qmakeCommand().toFileInfo().absolutePath();
- FileName qtVersion = FileName::fromString(
+ FilePath qtVersion = FilePath::fromString(
QFileDialog::getOpenFileName(this,
tr("Select a qmake Executable"),
dir,
BuildableHelperLibrary::filterForQmakeFileDialog(),
0,
QFileDialog::DontResolveSymlinks));
- if (qtVersion.isNull())
+ if (qtVersion.isEmpty())
return;
BaseQtVersion *version = QtVersionFactory::createQtVersionFromQMakePath(qtVersion);
if (!version)
@@ -769,7 +753,7 @@ void QtOptionsPageWidget::apply()
m_model->forItemsAtLevel<2>([&versions](QtVersionItem *item) {
item->setChanged(false);
- versions.append(item->version()->clone());
+ versions.append(QtVersionFactory::cloneQtVersion(item->version()));
});
QtVersionManager::setNewQtVersions(versions);
diff --git a/src/plugins/qtsupport/qtoptionspage.h b/src/plugins/qtsupport/qtoptionspage.h
index fc7899c9e0..04af543355 100644
--- a/src/plugins/qtsupport/qtoptionspage.h
+++ b/src/plugins/qtsupport/qtoptionspage.h
@@ -95,7 +95,6 @@ private:
void cleanUpQtVersions();
void toolChainsUpdated();
- void qtVersionsDumpUpdated(const Utils::FileName &qmakeCommand);
void setInfoWidgetVisibility();
void infoAnchorClicked(const QUrl &);
diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp
index 84f8e692a1..1bffe659cc 100644
--- a/src/plugins/qtsupport/qtoutputformatter.cpp
+++ b/src/plugins/qtsupport/qtoutputformatter.cpp
@@ -75,7 +75,7 @@ public:
const QRegularExpression qtTestFailUnix;
const QRegularExpression qtTestFailWin;
QPointer<Project> project;
- QString lastLine;
+ QList<FormattedText> lastLine;
FileInProjectFinder projectFinder;
QTextCursor cursor;
};
@@ -135,36 +135,45 @@ void QtOutputFormatter::appendMessage(const QString &txt, OutputFormat format)
appendMessage(txt, charFormat(format));
}
-void QtOutputFormatter::appendMessagePart(const QString &txt, const QTextCharFormat &format)
+void QtOutputFormatter::appendMessagePart(const QString &txt, const QTextCharFormat &fmt)
{
QString deferredText;
const int length = txt.length();
for (int start = 0, pos = -1; start < length; start = pos + 1) {
+ bool linkHandled = false;
pos = txt.indexOf('\n', start);
const QString newPart = txt.mid(start, (pos == -1) ? -1 : pos - start + 1);
- const QString line = d->lastLine + newPart;
+ QString line = newPart;
+ QTextCharFormat format = fmt;
+ if (!d->lastLine.isEmpty()) {
+ line = d->lastLine.last().text + newPart;
+ format = d->lastLine.last().format;
+ }
LinkResult lr = matchLine(line);
if (!lr.href.isEmpty()) {
// Found something && line continuation
- d->cursor.insertText(deferredText, format);
+ d->cursor.insertText(deferredText, fmt);
deferredText.clear();
if (!d->lastLine.isEmpty())
clearLastLine();
appendLine(lr, line, format);
+ linkHandled = true;
} else {
// Found nothing, just emit the new part
deferredText += newPart;
}
if (pos == -1) {
- d->lastLine = line;
+ d->lastLine.clear();
+ if (!linkHandled)
+ d->lastLine.append(FormattedText(line, format));
break;
}
d->lastLine.clear(); // Handled line continuation
}
- d->cursor.insertText(deferredText, format);
+ d->cursor.insertText(deferredText, fmt);
}
void QtOutputFormatter::appendMessage(const QString &txt, const QTextCharFormat &format)
@@ -178,6 +187,8 @@ void QtOutputFormatter::appendMessage(const QString &txt, const QTextCharFormat
appendMessagePart(output.text, output.format);
d->cursor.endEditBlock();
+
+ emit contentChanged();
}
void QtOutputFormatter::appendLine(const LinkResult &lr, const QString &line, OutputFormat format)
@@ -212,13 +223,14 @@ void QtOutputFormatter::handleLink(const QString &href)
":(\\d+)$"); // column
const QRegularExpressionMatch qmlLineColumnMatch = qmlLineColumnLink.match(href);
+ const auto getFileToOpen = [this](const QUrl &fileUrl) {
+ return chooseFileFromList(d->projectFinder.findFile(fileUrl)).toString();
+ };
if (qmlLineColumnMatch.hasMatch()) {
const QUrl fileUrl = QUrl(qmlLineColumnMatch.captured(1));
const int line = qmlLineColumnMatch.captured(2).toInt();
const int column = qmlLineColumnMatch.captured(3).toInt();
-
- openEditor(d->projectFinder.findFile(fileUrl), line, column - 1);
-
+ openEditor(getFileToOpen(fileUrl), line, column - 1);
return;
}
@@ -229,7 +241,7 @@ void QtOutputFormatter::handleLink(const QString &href)
if (qmlLineMatch.hasMatch()) {
const QUrl fileUrl = QUrl(qmlLineMatch.captured(1));
const int line = qmlLineMatch.captured(2).toInt();
- openEditor(d->projectFinder.findFile(fileUrl), line);
+ openEditor(getFileToOpen(fileUrl), line);
return;
}
@@ -258,7 +270,7 @@ void QtOutputFormatter::handleLink(const QString &href)
}
if (!fileName.isEmpty()) {
- fileName = d->projectFinder.findFile(QUrl::fromLocalFile(fileName));
+ fileName = getFileToOpen(QUrl::fromLocalFile(fileName));
openEditor(fileName, line);
return;
}
@@ -274,7 +286,8 @@ void QtOutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText)
void QtOutputFormatter::clearLastLine()
{
OutputFormatter::clearLastLine();
- d->lastLine.clear();
+ if (!d->lastLine.isEmpty())
+ d->lastLine.removeLast();
}
void QtOutputFormatter::openEditor(const QString &fileName, int line, int column)
@@ -447,6 +460,13 @@ static QTextCharFormat blueFormat()
return result;
}
+static QTextCharFormat greenFormat()
+{
+ QTextCharFormat result;
+ result.setForeground(QColor(0, 127, 0));
+ return result;
+}
+
void QtSupportPlugin::testQtOutputFormatter_appendMessage_data()
{
QTest::addColumn<QString>("inputText");
@@ -500,24 +520,24 @@ void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi()
formatter.setPlainTextEdit(&edit);
const QString inputText =
- "\x1b[38;2;0;0;127mHello\n"
- "Object::Test in test.cpp:123\n"
- "\x1b[38;2;0;0;127mHello\n";
+ "\x1b[38;2;0;127;0mGreen "
+ "file://test.cpp:123 "
+ "\x1b[38;2;0;0;127mBlue\n";
const QString outputText =
- "Hello\n"
- "Object::Test in test.cpp:123\n"
- "Hello\n";
+ "Green "
+ "file://test.cpp:123 "
+ "Blue\n";
formatter.appendMessage(inputText, QTextCharFormat());
QCOMPARE(edit.toPlainText(), outputText);
edit.moveCursor(QTextCursor::Start);
- QCOMPARE(edit.currentCharFormat(), blueFormat());
+ QCOMPARE(edit.currentCharFormat(), greenFormat());
- edit.moveCursor(QTextCursor::Down);
- edit.moveCursor(QTextCursor::EndOfLine);
- QCOMPARE(edit.currentCharFormat(), linkFormat(QTextCharFormat(), "test.cpp:123"));
+ edit.moveCursor(QTextCursor::WordRight);
+ edit.moveCursor(QTextCursor::Right);
+ QCOMPARE(edit.currentCharFormat(), linkFormat(QTextCharFormat(), "file://test.cpp:123"));
edit.moveCursor(QTextCursor::End);
QCOMPARE(edit.currentCharFormat(), blueFormat());
diff --git a/src/plugins/qtsupport/qtoutputformatter.h b/src/plugins/qtsupport/qtoutputformatter.h
index c3eedc2475..45f1a1e396 100644
--- a/src/plugins/qtsupport/qtoutputformatter.h
+++ b/src/plugins/qtsupport/qtoutputformatter.h
@@ -33,8 +33,8 @@
#define QT_QML_URL_REGEXP "(?:file|qrc):(?://)?/.+?"
#define QT_ASSERT_REGEXP "ASSERT: .* in file (.+, line \\d+)"
#define QT_ASSERT_X_REGEXP "ASSERT failure in .*: \".*\", file (.+, line \\d+)"
-#define QT_TEST_FAIL_UNIX_REGEXP "^ Loc: \\[(.*)\\]$"
-#define QT_TEST_FAIL_WIN_REGEXP "^(.*\\(\\d+\\)) : failure location\\s*$"
+#define QT_TEST_FAIL_UNIX_REGEXP "^ Loc: \\[((?<file>.+)\\((?<line>\\d+)\\))\\]$"
+#define QT_TEST_FAIL_WIN_REGEXP "^((?<file>.+)\\((?<line>\\d+)\\)) : failure location\\s*$"
namespace ProjectExplorer { class Project; }
@@ -70,7 +70,7 @@ protected:
private:
void updateProjectFileList();
LinkResult matchLine(const QString &line) const;
- void appendMessagePart(const QString &txt, const QTextCharFormat &format);
+ void appendMessagePart(const QString &txt, const QTextCharFormat &fmt);
void appendLine(const LinkResult &lr, const QString &line, Utils::OutputFormat format);
void appendLine(const LinkResult &lr, const QString &line, const QTextCharFormat &format);
void appendMessage(const QString &text, const QTextCharFormat &format) override;
diff --git a/src/plugins/qtsupport/qtparser.cpp b/src/plugins/qtsupport/qtparser.cpp
index a1642222f1..6176e281c4 100644
--- a/src/plugins/qtsupport/qtparser.cpp
+++ b/src/plugins/qtsupport/qtparser.cpp
@@ -58,7 +58,7 @@ void QtParser::stdError(const QString &line)
if (level.compare(QLatin1String("Note"), Qt::CaseInsensitive) == 0)
type = Task::Unknown;
Task task(type, m_mocRegExp.cap(5).trimmed() /* description */,
- Utils::FileName::fromUserInput(m_mocRegExp.cap(1)) /* filename */,
+ Utils::FilePath::fromUserInput(m_mocRegExp.cap(1)) /* filename */,
lineno,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
@@ -69,7 +69,7 @@ void QtParser::stdError(const QString &line)
if (m_translationRegExp.cap(1) == QLatin1String("Error"))
type = Task::Error;
Task task(type, m_translationRegExp.cap(2),
- Utils::FileName::fromUserInput(m_translationRegExp.cap(3)) /* filename */,
+ Utils::FilePath::fromUserInput(m_translationRegExp.cap(3)) /* filename */,
-1,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
@@ -96,19 +96,19 @@ void QtSupportPlugin::testQtOutputParser_data()
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
+ QTest::addColumn<Tasks >("tasks");
QTest::addColumn<QString>("outputLines");
QTest::newRow("pass-through stdout")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
<< QString::fromLatin1("Sometext\n") << QString()
- << QList<ProjectExplorer::Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through stderr")
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("Sometext\n")
- << QList<ProjectExplorer::Task>()
+ << Tasks()
<< QString();
QTest::newRow("pass-through gcc infos")
<< QString::fromLatin1("/temp/test/untitled8/main.cpp: In function `int main(int, char**)':\n"
@@ -123,60 +123,60 @@ void QtSupportPlugin::testQtOutputParser_data()
"../../scriptbug/main.cpp: In instantiation of void bar(i) [with i = double]:\n"
"../../scriptbug/main.cpp:8: instantiated from void foo(i) [with i = double]\n"
"../../scriptbug/main.cpp:22: instantiated from here\n")
- << QList<ProjectExplorer::Task>()
+ << Tasks()
<< QString();
QTest::newRow("qdoc warning")
<< QString::fromLatin1("/home/user/dev/qt5/qtscript/src/script/api/qscriptengine.cpp:295: warning: Can't create link to 'Object Trees & Ownership'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>() << Task(Task::Warning,
+ << (Tasks() << Task(Task::Warning,
QLatin1String("Can't create link to 'Object Trees & Ownership'"),
- Utils::FileName::fromUserInput(QLatin1String("/home/user/dev/qt5/qtscript/src/script/api/qscriptengine.cpp")), 295,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/user/dev/qt5/qtscript/src/script/api/qscriptengine.cpp")), 295,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))
<< QString();
QTest::newRow("moc warning")
<< QString::fromLatin1("..\\untitled\\errorfile.h:0: Warning: No relevant classes found. No output generated.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>() << Task(Task::Warning,
+ << (Tasks() << Task(Task::Warning,
QLatin1String("No relevant classes found. No output generated."),
- Utils::FileName::fromUserInput(QLatin1String("..\\untitled\\errorfile.h")), 0,
+ Utils::FilePath::fromUserInput(QLatin1String("..\\untitled\\errorfile.h")), 0,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))
<< QString();
QTest::newRow("moc warning 2")
<< QString::fromLatin1("c:\\code\\test.h(96): Warning: Property declaration ) has no READ accessor function. The property will be invalid.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>() << Task(Task::Warning,
+ << (Tasks() << Task(Task::Warning,
QLatin1String("Property declaration ) has no READ accessor function. The property will be invalid."),
- Utils::FileName::fromUserInput(QLatin1String("c:\\code\\test.h")), 96,
+ Utils::FilePath::fromUserInput(QLatin1String("c:\\code\\test.h")), 96,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))
<< QString();
QTest::newRow("moc note")
<< QString::fromLatin1("/home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated.")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>() << Task(Task::Unknown,
+ << (Tasks() << Task(Task::Unknown,
QLatin1String("No relevant classes found. No output generated."),
- Utils::FileName::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
+ Utils::FilePath::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))
<< QString();
QTest::newRow("ninja with moc")
<< QString::fromLatin1("E:/sandbox/creator/loaden/src/libs/utils/iwelcomepage.h(54): Error: Undefined interface")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>() << Task(Task::Error,
+ << (Tasks() << Task(Task::Error,
QLatin1String("Undefined interface"),
- Utils::FileName::fromUserInput(QLatin1String("E:/sandbox/creator/loaden/src/libs/utils/iwelcomepage.h")), 54,
+ Utils::FilePath::fromUserInput(QLatin1String("E:/sandbox/creator/loaden/src/libs/utils/iwelcomepage.h")), 54,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))
<< QString();
QTest::newRow("translation")
<< QString::fromLatin1("Warning: dropping duplicate messages in '/some/place/qtcreator_fr.qm'")
<< OutputParserTester::STDERR
<< QString() << QString()
- << (QList<ProjectExplorer::Task>() << Task(Task::Warning,
+ << (Tasks() << Task(Task::Warning,
QLatin1String("dropping duplicate messages"),
- Utils::FileName::fromUserInput(QLatin1String("/some/place/qtcreator_fr.qm")), -1,
+ Utils::FilePath::fromUserInput(QLatin1String("/some/place/qtcreator_fr.qm")), -1,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))
<< QString();
}
@@ -187,7 +187,7 @@ void QtSupportPlugin::testQtOutputParser()
testbench.appendOutputParser(new QtParser);
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QList<Task>, tasks);
+ QFETCH(Tasks, tasks);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QString, outputLines);
diff --git a/src/plugins/qtsupport/qtprojectimporter.cpp b/src/plugins/qtsupport/qtprojectimporter.cpp
index a218ee2b5e..0e4124f7d9 100644
--- a/src/plugins/qtsupport/qtprojectimporter.cpp
+++ b/src/plugins/qtsupport/qtprojectimporter.cpp
@@ -45,22 +45,22 @@ using namespace ProjectExplorer;
namespace QtSupport {
-QtProjectImporter::QtProjectImporter(const Utils::FileName &path) : ProjectImporter(path)
+QtProjectImporter::QtProjectImporter(const Utils::FilePath &path) : ProjectImporter(path)
{
- useTemporaryKitInformation(QtKitInformation::id(),
+ useTemporaryKitAspect(QtKitAspect::id(),
[this](Kit *k, const QVariantList &vl) {cleanupTemporaryQt(k, vl);},
[this](Kit *k, const QVariantList &vl) {persistTemporaryQt(k, vl);});
}
QtProjectImporter::QtVersionData
-QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath) const
+QtProjectImporter::findOrCreateQtVersion(const Utils::FilePath &qmakePath) const
{
QtVersionData result;
result.qt = QtVersionManager::version(Utils::equal(&BaseQtVersion::qmakeCommand, qmakePath));
if (result.qt) {
// Check if version is a temporary qt
const int qtId = result.qt->uniqueId();
- result.isTemporary = hasKitWithTemporaryData(QtKitInformation::id(), qtId);
+ result.isTemporary = hasKitWithTemporaryData(QtKitAspect::id(), qtId);
return result;
}
@@ -80,10 +80,10 @@ Kit *QtProjectImporter::createTemporaryKit(const QtVersionData &versionData,
const ProjectImporter::KitSetupFunction &additionalSetup) const
{
return ProjectImporter::createTemporaryKit([&additionalSetup, &versionData, this](Kit *k) -> void {
- QtKitInformation::setQtVersion(k, versionData.qt);
+ QtKitAspect::setQtVersion(k, versionData.qt);
if (versionData.qt) {
if (versionData.isTemporary)
- addTemporaryData(QtKitInformation::id(), versionData.qt->uniqueId(), k);
+ addTemporaryData(QtKitAspect::id(), versionData.qt->uniqueId(), k);
k->setUnexpandedDisplayName(versionData.qt->displayName());;
}
@@ -108,7 +108,7 @@ void QtProjectImporter::cleanupTemporaryQt(Kit *k, const QVariantList &vl)
BaseQtVersion *version = versionFromVariant(vl.at(0));
QTC_ASSERT(version, return);
QtVersionManager::removeVersion(version);
- QtKitInformation::setQtVersion(k, nullptr); // Always mark Kit as not using this Qt
+ QtKitAspect::setQtVersion(k, nullptr); // Always mark Kit as not using this Qt
}
void QtProjectImporter::persistTemporaryQt(Kit *k, const QVariantList &vl)
@@ -118,7 +118,7 @@ void QtProjectImporter::persistTemporaryQt(Kit *k, const QVariantList &vl)
QTC_ASSERT(vl.count() == 1, return);
const QVariant data = vl.at(0);
BaseQtVersion *tmpVersion = versionFromVariant(data);
- BaseQtVersion *actualVersion = QtKitInformation::qtVersion(k);
+ BaseQtVersion *actualVersion = QtKitAspect::qtVersion(k);
// User changed Kit away from temporary Qt that was set up:
if (tmpVersion && actualVersion != tmpVersion)
@@ -144,9 +144,9 @@ namespace Internal {
struct DirectoryData {
DirectoryData(const QString &ip,
Kit *k = nullptr, bool ink = false,
- const Utils::FileName &qp = Utils::FileName(), bool inq = false) :
+ const Utils::FilePath &qp = Utils::FilePath(), bool inq = false) :
isNewKit(ink), isNewQt(inq),
- importPath(Utils::FileName::fromString(ip)),
+ importPath(Utils::FilePath::fromString(ip)),
kit(k), qmakePath(qp)
{ }
@@ -160,15 +160,15 @@ struct DirectoryData {
const bool isNewKit = false;
const bool isNewQt = false;
- const Utils::FileName importPath;
+ const Utils::FilePath importPath;
Kit *const kit = nullptr;
- const Utils::FileName qmakePath;
+ const Utils::FilePath qmakePath;
};
class TestQtProjectImporter : public QtProjectImporter
{
public:
- TestQtProjectImporter(const Utils::FileName &pp, const QList<void *> &testData) :
+ TestQtProjectImporter(const Utils::FilePath &pp, const QList<void *> &testData) :
QtProjectImporter(pp),
m_testData(testData)
{ }
@@ -178,7 +178,7 @@ public:
bool allDeleted() const { return m_deletedTestData.count() == m_testData.count();}
protected:
- QList<void *> examineDirectory(const Utils::FileName &importPath) const override;
+ QList<void *> examineDirectory(const Utils::FilePath &importPath) const override;
bool matchKit(void *directoryData, const Kit *k) const override;
Kit *createKit(void *directoryData) const override;
const QList<BuildInfo> buildInfoListForKit(const Kit *k, void *directoryData) const override;
@@ -186,7 +186,7 @@ protected:
private:
const QList<void *> m_testData;
- mutable Utils::FileName m_path;
+ mutable Utils::FilePath m_path;
mutable QVector<void*> m_deletedTestData;
QList<Kit *> m_deletedKits;
@@ -197,7 +197,7 @@ QStringList TestQtProjectImporter::importCandidates()
return QStringList();
}
-QList<void *> TestQtProjectImporter::examineDirectory(const Utils::FileName &importPath) const
+QList<void *> TestQtProjectImporter::examineDirectory(const Utils::FilePath &importPath) const
{
m_path = importPath;
@@ -228,7 +228,7 @@ Kit *TestQtProjectImporter::createKit(void *directoryData) const
// New temporary kit:
return createTemporaryKit(findOrCreateQtVersion(dd->qmakePath),
[dd](Kit *k) {
- BaseQtVersion *qt = QtKitInformation::qtVersion(k);
+ BaseQtVersion *qt = QtKitAspect::qtVersion(k);
QMap<Core::Id, QVariant> toKeep;
for (const Core::Id &key : k->allKeys()) {
if (key.toString().startsWith("PE.tmp."))
@@ -237,7 +237,7 @@ Kit *TestQtProjectImporter::createKit(void *directoryData) const
k->copyFrom(dd->kit);
for (auto i = toKeep.constBegin(); i != toKeep.constEnd(); ++i)
k->setValue(i.key(), i.value());
- QtKitInformation::setQtVersion(k, qt);
+ QtKitAspect::setQtVersion(k, qt);
});
}
@@ -268,14 +268,14 @@ void TestQtProjectImporter::deleteDirectoryData(void *directoryData) const
delete static_cast<DirectoryData *>(directoryData);
}
-static Utils::FileName setupQmake(const BaseQtVersion *qt, const QString &path)
+static Utils::FilePath setupQmake(const BaseQtVersion *qt, const QString &path)
{
const QFileInfo fi = QFileInfo(qt->qmakeCommand().toFileInfo().canonicalFilePath());
const QString qmakeFile = path + "/" + fi.fileName();
if (!QFile::copy(fi.absoluteFilePath(), qmakeFile))
- return Utils::FileName();
+ return Utils::FilePath();
- return Utils::FileName::fromString(qmakeFile);
+ return Utils::FilePath::fromString(qmakeFile);
}
void QtSupportPlugin::testQtProjectImporter_oneProject_data()
@@ -362,7 +362,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
Kit *defaultKit = KitManager::defaultKit();
QVERIFY(defaultKit);
- BaseQtVersion *defaultQt = QtKitInformation::qtVersion(defaultKit);
+ BaseQtVersion *defaultQt = QtKitAspect::qtVersion(defaultKit);
QVERIFY(defaultQt);
const Utils::TemporaryDirectory tempDir1("tmp1");
@@ -373,12 +373,12 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
// Templates referrenced by test data:
QVector<Kit *> kitTemplates = {defaultKit, defaultKit->clone(), defaultKit->clone()};
// Customize kit numbers 1 and 2:
- QtKitInformation::setQtVersion(kitTemplates[1], nullptr);
- QtKitInformation::setQtVersion(kitTemplates[2], nullptr);
- SysRootKitInformation::setSysRoot(kitTemplates[1], Utils::FileName::fromString("/some/path"));
- SysRootKitInformation::setSysRoot(kitTemplates[2], Utils::FileName::fromString("/some/other/path"));
+ QtKitAspect::setQtVersion(kitTemplates[1], nullptr);
+ QtKitAspect::setQtVersion(kitTemplates[2], nullptr);
+ SysRootKitAspect::setSysRoot(kitTemplates[1], Utils::FilePath::fromString("/some/path"));
+ SysRootKitAspect::setSysRoot(kitTemplates[2], Utils::FilePath::fromString("/some/other/path"));
- QVector<Utils::FileName> qmakePaths = {defaultQt->qmakeCommand(),
+ QVector<Utils::FilePath> qmakePaths = {defaultQt->qmakeCommand(),
setupQmake(defaultQt, tempDir1.path()),
setupQmake(defaultQt, tempDir2.path())};
@@ -405,13 +405,13 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
testData.append(new DirectoryData(appDir,
(kitIndex < 0) ? nullptr : kitTemplates.at(kitIndex),
(kitIndex > 0), /* new Kit */
- (qtIndex < 0) ? Utils::FileName() : qmakePaths.at(qtIndex),
+ (qtIndex < 0) ? Utils::FilePath() : qmakePaths.at(qtIndex),
(qtIndex > 0) /* new Qt */));
}
// Finally set up importer:
// Copy the directoryData so that importer is free to delete it later.
- TestQtProjectImporter importer(Utils::FileName::fromString(tempDir1.path()),
+ TestQtProjectImporter importer(Utils::FilePath::fromString(tempDir1.path()),
Utils::transform(testData, [](DirectoryData *i) {
return static_cast<void *>(new DirectoryData(*i));
}));
@@ -421,7 +421,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
// --------------------------------------------------------------------
// choose an existing directory to "import"
- const QList<BuildInfo> buildInfo = importer.import(Utils::FileName::fromString(appDir), true);
+ const QList<BuildInfo> buildInfo = importer.import(Utils::FilePath::fromString(appDir), true);
// VALIDATE: Basic TestImporter state:
QCOMPARE(importer.projectFilePath().toString(), tempDir1.path());
@@ -445,7 +445,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
Kit *newKit = KitManager::kit(bi.kitId);
QVERIFY(newKit);
- const int newQtId = QtKitInformation::qtVersionId(newKit);
+ const int newQtId = QtKitAspect::qtVersionId(newKit);
// VALIDATE: Qt id is unchanged (unless it is a new Qt)
if (!dd->isNewQt)
@@ -468,7 +468,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
QCOMPARE(templateKeys.count(), newKitKeys.count()); // existing kit needs to be unchanged!
for (Core::Id id : templateKeys) {
- if (id == QtKitInformation::id())
+ if (id == QtKitAspect::id())
continue; // with the exception of the Qt one...
QVERIFY(newKit->hasValue(id));
QVERIFY(dd->kit->value(id) == newKit->value(id));
@@ -497,7 +497,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
templateKit = defaultKit;
} else {
templateKit = dd->kit->clone(true);
- QtKitInformation::setQtVersionId(templateKit, QtKitInformation::qtVersionId(newKit));
+ QtKitAspect::setQtVersionId(templateKit, QtKitAspect::qtVersionId(newKit));
}
const QList<Core::Id> templateKitKeys = templateKit->allKeys();
@@ -522,7 +522,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
const QList<Core::Id> newKitKeys = newKit->allKeys();
const Core::Id newKitId = newKit->id();
- const int qtId = QtKitInformation::qtVersionId(newKit);
+ const int qtId = QtKitAspect::qtVersionId(newKit);
// VALIDATE: Kit Id has not changed
QCOMPARE(newKitId, newKitIdAfterImport);
@@ -539,7 +539,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
// VALIDATE: All the kit values are as set up in the template before
QCOMPARE(newKitKeys.count(), templateKitKeys.count());
for (Core::Id id : templateKitKeys) {
- if (id == QtKitInformation::id())
+ if (id == QtKitAspect::id())
continue;
QVERIFY(newKit->hasValue(id));
QVERIFY(newKit->value(id) == templateKit->value(id));
@@ -553,7 +553,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
// VALIDATE: All keys that got added during import are gone
QCOMPARE(newKitKeys.count(), templateKitKeys.count());
for (Core::Id id : newKitKeys) {
- if (id == QtKitInformation::id())
+ if (id == QtKitAspect::id())
continue; // Will be checked by Qt version later
QVERIFY(templateKit->hasValue(id));
QVERIFY(newKit->value(id) == templateKit->value(id));
@@ -562,7 +562,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
if (qtIsPersistent) {
// VALIDATE: Qt is used in the Kit:
- QVERIFY(QtKitInformation::qtVersionId(newKit) == qtId);
+ QVERIFY(QtKitAspect::qtVersionId(newKit) == qtId);
// VALIDATE: Qt is still in QtVersionManager
QVERIFY(QtVersionManager::version(qtId));
@@ -571,10 +571,10 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
QCOMPARE(QtVersionManager::version(qtId)->qmakeCommand(), dd->qmakePath);
// VALIDATE: Kit uses the expected Qt
- QCOMPARE(QtKitInformation::qtVersionId(newKit), qtId);
+ QCOMPARE(QtKitAspect::qtVersionId(newKit), qtId);
} else {
// VALIDATE: Qt was reset in the kit
- QVERIFY(QtKitInformation::qtVersionId(newKit) == -1);
+ QVERIFY(QtKitAspect::qtVersionId(newKit) == -1);
// VALIDATE: New kit is still visible in KitManager
QVERIFY(KitManager::kit(newKitId)); // Cleanup Kit does not unregister Kits, so it does
@@ -584,7 +584,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
QVERIFY(!QtVersionManager::version(qtId));
// VALIDATE: Qt version was reset on the kit
- QVERIFY(newKit->value(QtKitInformation::id()).toInt() == -1); // new Qt will be reset to invalid!
+ QVERIFY(newKit->value(QtKitAspect::id()).toInt() == -1); // new Qt will be reset to invalid!
}
if (templateKit != defaultKit)
diff --git a/src/plugins/qtsupport/qtprojectimporter.h b/src/plugins/qtsupport/qtprojectimporter.h
index 082a689bb8..2736787f32 100644
--- a/src/plugins/qtsupport/qtprojectimporter.h
+++ b/src/plugins/qtsupport/qtprojectimporter.h
@@ -37,7 +37,7 @@ class BaseQtVersion;
class QTSUPPORT_EXPORT QtProjectImporter : public ProjectExplorer::ProjectImporter
{
public:
- QtProjectImporter(const Utils::FileName &path);
+ QtProjectImporter(const Utils::FilePath &path);
class QtVersionData
{
@@ -47,7 +47,7 @@ public:
};
protected:
- QtVersionData findOrCreateQtVersion(const Utils::FileName &qmakePath) const;
+ QtVersionData findOrCreateQtVersion(const Utils::FilePath &qmakePath) const;
ProjectExplorer::Kit *createTemporaryKit(const QtVersionData &versionData,
const KitSetupFunction &setup) const;
diff --git a/src/plugins/qtsupport/qtsupport.pro b/src/plugins/qtsupport/qtsupport.pro
index 17797f6294..4c5900027f 100644
--- a/src/plugins/qtsupport/qtsupport.pro
+++ b/src/plugins/qtsupport/qtsupport.pro
@@ -15,9 +15,9 @@ HEADERS += \
qtprojectimporter.h \
qtsupportplugin.h \
qtsupport_global.h \
- qtkitconfigwidget.h \
qtkitinformation.h \
qtoutputformatter.h \
+ qttestparser.h \
qtversionmanager.h \
qtversionfactory.h \
baseqtversion.h \
@@ -29,7 +29,6 @@ HEADERS += \
exampleslistmodel.h \
screenshotcropper.h \
qtconfigwidget.h \
- desktopqtversionfactory.h \
desktopqtversion.h \
uicgenerator.h \
qscxmlcgenerator.h
@@ -42,9 +41,9 @@ SOURCES += \
qtcppkitinfo.cpp \
qtprojectimporter.cpp \
qtsupportplugin.cpp \
- qtkitconfigwidget.cpp \
qtkitinformation.cpp \
qtoutputformatter.cpp \
+ qttestparser.cpp \
qtversionmanager.cpp \
qtversionfactory.cpp \
baseqtversion.cpp \
@@ -55,7 +54,6 @@ SOURCES += \
exampleslistmodel.cpp \
screenshotcropper.cpp \
qtconfigwidget.cpp \
- desktopqtversionfactory.cpp \
desktopqtversion.cpp \
uicgenerator.cpp \
qscxmlcgenerator.cpp
diff --git a/src/plugins/qtsupport/qtsupport.qbs b/src/plugins/qtsupport/qtsupport.qbs
index 8be90315eb..7e2aa71e32 100644
--- a/src/plugins/qtsupport/qtsupport.qbs
+++ b/src/plugins/qtsupport/qtsupport.qbs
@@ -82,8 +82,6 @@ Project {
"qmldumptool.h",
"qscxmlcgenerator.cpp",
"qscxmlcgenerator.h",
- "qtkitconfigwidget.cpp",
- "qtkitconfigwidget.h",
"qtkitinformation.cpp",
"qtkitinformation.h",
"qtoptionspage.cpp",
@@ -96,6 +94,8 @@ Project {
"qtsupportconstants.h",
"qtsupportplugin.cpp",
"qtsupportplugin.h",
+ "qttestparser.cpp",
+ "qttestparser.h",
"qtversionfactory.cpp",
"qtversionfactory.h",
"qtversioninfo.ui",
@@ -112,8 +112,8 @@ Project {
Group {
name: "QtVersion"
files: [
- "desktopqtversion.cpp", "desktopqtversion.h",
- "desktopqtversionfactory.cpp", "desktopqtversionfactory.h",
+ "desktopqtversion.cpp",
+ "desktopqtversion.h",
]
}
diff --git a/src/plugins/qtsupport/qtsupportconstants.h b/src/plugins/qtsupport/qtsupportconstants.h
index 202378ef2e..f8a453d13d 100644
--- a/src/plugins/qtsupport/qtsupportconstants.h
+++ b/src/plugins/qtsupport/qtsupportconstants.h
@@ -30,10 +30,7 @@ namespace Constants {
// Qt settings pages
const char QTVERSION_SETTINGS_PAGE_ID[] = "H.Qt Versions";
-const char QTVERSION_SETTINGS_PAGE_NAME[] = QT_TRANSLATE_NOOP("QtSupport", "Qt Versions");
-
const char CODEGEN_SETTINGS_PAGE_ID[] = "Class Generation";
-const char CODEGEN_SETTINGS_PAGE_NAME[] = QT_TRANSLATE_NOOP("QtSupport", "Qt Class Generation");
// QtVersions
const char DESKTOPQT[] = "Qt4ProjectManager.QtVersion.Desktop";
diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp
index 2d99d01e38..5faa9f7a1a 100644
--- a/src/plugins/qtsupport/qtsupportplugin.cpp
+++ b/src/plugins/qtsupport/qtsupportplugin.cpp
@@ -27,14 +27,17 @@
#include "codegenerator.h"
#include "codegensettingspage.h"
-#include "desktopqtversionfactory.h"
+#include "desktopqtversion.h"
#include "gettingstartedwelcomepage.h"
#include "qtkitinformation.h"
#include "qtoptionspage.h"
+#include "qtsupportconstants.h"
+#include "qtversionfactory.h"
#include "qtversionmanager.h"
#include "uicgenerator.h"
#include "qscxmlcgenerator.h"
+#include "desktopqtversion.h"
#include "profilereader.h"
#include <coreplugin/icore.h>
@@ -65,6 +68,8 @@ public:
ExamplesWelcomePage examplesPage{true};
ExamplesWelcomePage tutorialPage{false};
+
+ QtKitAspect qtKiAspect;
};
QtSupportPlugin::~QtSupportPlugin()
@@ -80,12 +85,10 @@ bool QtSupportPlugin::initialize(const QStringList &arguments, QString *errorMes
ProFileEvaluator::initialize();
new ProFileCacheManager(this);
- JsExpander::registerQObjectForJs(QLatin1String("QtSupport"), new CodeGenerator);
+ JsExpander::registerGlobalObject<CodeGenerator>("QtSupport");
d = new QtSupportPluginPrivate;
- ProjectExplorer::KitManager::registerKitInformation<QtKitInformation>();
-
(void) new UicGeneratorFactory(this);
(void) new QScxmlcGeneratorFactory(this);
@@ -100,7 +103,7 @@ static QString qmakeProperty(const char *propertyName)
if (!project || !project->activeTarget())
return QString();
- const BaseQtVersion *qtVersion = QtKitInformation::qtVersion(project->activeTarget()->kit());
+ const BaseQtVersion *qtVersion = QtKitAspect::qtVersion(project->activeTarget()->kit());
if (!qtVersion)
return QString();
return qtVersion->qmakeProperty(propertyName);
diff --git a/src/plugins/qtsupport/qtsupportplugin.h b/src/plugins/qtsupport/qtsupportplugin.h
index b5e950733b..7899a1bab4 100644
--- a/src/plugins/qtsupport/qtsupportplugin.h
+++ b/src/plugins/qtsupport/qtsupportplugin.h
@@ -48,6 +48,7 @@ private:
private slots:
void testQtOutputParser_data();
void testQtOutputParser();
+ void testQtTestOutputParser();
void testQtOutputFormatter_data();
void testQtOutputFormatter();
void testQtOutputFormatter_appendMessage_data();
diff --git a/src/plugins/qtsupport/qttestparser.cpp b/src/plugins/qtsupport/qttestparser.cpp
new file mode 100644
index 0000000000..901613437e
--- /dev/null
+++ b/src/plugins/qtsupport/qttestparser.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** 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 "qttestparser.h"
+
+#include "qtoutputformatter.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+#include <utils/hostosinfo.h>
+#include <utils/qtcassert.h>
+
+#include <QDir>
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
+
+#ifdef WITH_TESTS
+#include "qtsupportplugin.h"
+#include <projectexplorer/outputparser_test.h>
+#include <QTest>
+#endif // WITH_TESTS
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace QtSupport {
+namespace Internal {
+
+void QtTestParser::stdOutput(const QString &line)
+{
+ const QString theLine = rightTrimmed(line);
+ static const QRegularExpression triggerPattern("^(?:XPASS|FAIL!) : .+$");
+ QTC_CHECK(triggerPattern.isValid());
+ if (triggerPattern.match(theLine).hasMatch()) {
+ emitCurrentTask();
+ m_currentTask = Task(Task::Error, theLine, FilePath(), -1,
+ Constants::TASK_CATEGORY_AUTOTEST);
+ return;
+ }
+ if (m_currentTask.isNull()) {
+ IOutputParser::stdOutput(line);
+ return;
+ }
+ static const QRegularExpression locationPattern(HostOsInfo::isWindowsHost()
+ ? QString(QT_TEST_FAIL_WIN_REGEXP)
+ : QString(QT_TEST_FAIL_UNIX_REGEXP));
+ QTC_CHECK(locationPattern.isValid());
+ const QRegularExpressionMatch match = locationPattern.match(theLine);
+ if (match.hasMatch()) {
+ m_currentTask.file = FilePath::fromString(
+ QDir::fromNativeSeparators(match.captured("file")));
+ m_currentTask.line = match.captured("line").toInt();
+ emitCurrentTask();
+ return;
+ }
+ m_currentTask.description.append('\n').append(theLine);
+}
+
+void QtTestParser::emitCurrentTask()
+{
+ if (!m_currentTask.isNull()) {
+ emit taskAdded(m_currentTask);
+ m_currentTask.clear();
+ }
+}
+
+#ifdef WITH_TESTS
+void QtSupportPlugin::testQtTestOutputParser()
+{
+ OutputParserTester testbench;
+ testbench.appendOutputParser(new QtTestParser);
+ const QString input = "random output\n"
+ "PASS : MyTest::someTest()\n"
+ "XPASS : MyTest::someTest()\n"
+#ifdef Q_OS_WIN
+ "C:\\dev\\tests\\tst_mytest.cpp(154) : failure location\n"
+#else
+ " Loc: [/home/me/tests/tst_mytest.cpp(154)]\n"
+#endif
+ "FAIL! : MyTest::someOtherTest(init) Compared values are not the same\n"
+ " Actual (exceptionCaught): 0\n"
+ " Expected (true) : 1\n"
+#ifdef Q_OS_WIN
+ "C:\\dev\\tests\\tst_mytest.cpp(220) : failure location\n"
+#else
+ " Loc: [/home/me/tests/tst_mytest.cpp(220)]\n"
+#endif
+ "XPASS: irrelevant\n"
+ "PASS : MyTest::anotherTest()";
+ const QString expectedChildOutput =
+ "random output\n"
+ "PASS : MyTest::someTest()\n"
+ "XPASS: irrelevant\n"
+ "PASS : MyTest::anotherTest()\n";
+ const FilePath theFile = FilePath::fromString(HostOsInfo::isWindowsHost()
+ ? QString("C:/dev/tests/tst_mytest.cpp") : QString("/home/me/tests/tst_mytest.cpp"));
+ const Tasks expectedTasks{
+ Task(Task::Error, "XPASS : MyTest::someTest()", theFile, 154,
+ Constants::TASK_CATEGORY_AUTOTEST),
+ Task(Task::Error, "FAIL! : MyTest::someOtherTest(init) "
+ "Compared values are not the same\n"
+ " Actual (exceptionCaught): 0\n"
+ " Expected (true) : 1",
+ theFile, 220, Constants::TASK_CATEGORY_AUTOTEST)};
+ testbench.testParsing(input, OutputParserTester::STDOUT, expectedTasks, expectedChildOutput,
+ QString(), QString());
+}
+#endif // WITH_TESTS
+
+} // namespace Internal
+} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qttestparser.h b/src/plugins/qtsupport/qttestparser.h
new file mode 100644
index 0000000000..28ca1f3b04
--- /dev/null
+++ b/src/plugins/qtsupport/qttestparser.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 <projectexplorer/ioutputparser.h>
+#include <projectexplorer/task.h>
+
+namespace QtSupport {
+namespace Internal {
+
+class QtTestParser : public ProjectExplorer::IOutputParser
+{
+ Q_OBJECT
+private:
+ void stdOutput(const QString &line) override;
+ void doFlush() override { emitCurrentTask(); }
+
+ void emitCurrentTask();
+
+ ProjectExplorer::Task m_currentTask;
+};
+
+} // namespace Internal
+} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qtversionfactory.cpp b/src/plugins/qtsupport/qtversionfactory.cpp
index ebc8ae36ee..4560667d8f 100644
--- a/src/plugins/qtsupport/qtversionfactory.cpp
+++ b/src/plugins/qtsupport/qtversionfactory.cpp
@@ -30,16 +30,19 @@
#include <proparser/qmakevfs.h>
#include <extensionsystem/pluginmanager.h>
+
#include <utils/algorithm.h>
#include <utils/environment.h>
+#include <utils/qtcassert.h>
+
+#include <QFileInfo>
using namespace QtSupport;
using namespace QtSupport::Internal;
static QList<QtVersionFactory *> g_qtVersionFactories;
-QtVersionFactory::QtVersionFactory(QObject *parent) :
- QObject(parent)
+QtVersionFactory::QtVersionFactory()
{
g_qtVersionFactories.append(this);
}
@@ -54,13 +57,27 @@ const QList<QtVersionFactory *> QtVersionFactory::allQtVersionFactories()
return g_qtVersionFactories;
}
-BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath(const Utils::FileName &qmakePath, bool isAutoDetected, const QString &autoDetectionSource, QString *error)
+bool QtVersionFactory::canRestore(const QString &type)
+{
+ return type == m_supportedType;
+}
+
+BaseQtVersion *QtVersionFactory::restore(const QString &type, const QVariantMap &data)
+{
+ QTC_ASSERT(canRestore(type), return nullptr);
+ QTC_ASSERT(m_creator, return nullptr);
+ BaseQtVersion *version = create();
+ version->fromMap(data);
+ return version;
+}
+
+BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath(const Utils::FilePath &qmakePath, bool isAutoDetected, const QString &autoDetectionSource, QString *error)
{
QHash<ProKey, ProString> versionInfo;
if (!BaseQtVersion::queryQMakeVariables(qmakePath, Utils::Environment::systemEnvironment(),
&versionInfo, error))
return 0;
- Utils::FileName mkspec = BaseQtVersion::mkspecFromVersionInfo(versionInfo);
+ Utils::FilePath mkspec = BaseQtVersion::mkspecFromVersionInfo(versionInfo);
QMakeVfs vfs;
QMakeGlobals globals;
@@ -76,15 +93,79 @@ BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath(const Utils::FileN
return l->priority() > r->priority();
});
+ QFileInfo fi = qmakePath.toFileInfo();
+ if (!fi.exists() || !fi.isExecutable() || !fi.isFile())
+ return nullptr;
+
+ SetupData setup;
+ setup.config = evaluator.values("CONFIG");
+ setup.platforms = evaluator.values("QMAKE_PLATFORM"); // It's a list in general.
+ setup.isQnx = !evaluator.value("QNX_CPUDIR").isEmpty();
+
foreach (QtVersionFactory *factory, factories) {
- BaseQtVersion *ver = factory->create(qmakePath, &evaluator, isAutoDetected, autoDetectionSource);
- if (ver) {
+ if (!factory->m_restrictionChecker || factory->m_restrictionChecker(setup)) {
+ BaseQtVersion *ver = factory->create();
+ QTC_ASSERT(ver, continue);
+ ver->setupQmakePathAndId(qmakePath);
+ ver->setAutoDetectionSource(autoDetectionSource);
+ ver->setIsAutodetected(isAutoDetected);
ProFileCacheManager::instance()->decRefCount();
return ver;
}
}
ProFileCacheManager::instance()->decRefCount();
- if (error)
- *error = tr("No factory found for qmake: \"%1\"").arg(qmakePath.toUserOutput());
+ if (error) {
+ *error = QCoreApplication::translate("QtSupport::QtVersionFactory",
+ "No factory found for qmake: \"%1\"").arg(qmakePath.toUserOutput());
+ }
return 0;
}
+
+BaseQtVersion *QtVersionFactory::create() const
+{
+ QTC_ASSERT(m_creator, return nullptr);
+ BaseQtVersion *version = m_creator();
+ version->m_factory = this;
+ return version;
+}
+
+QString QtVersionFactory::supportedType() const
+{
+ return m_supportedType;
+}
+
+BaseQtVersion *QtVersionFactory::cloneQtVersion(const BaseQtVersion *source)
+{
+ QTC_ASSERT(source, return nullptr);
+ const QString sourceType = source->type();
+ for (QtVersionFactory *factory : g_qtVersionFactories) {
+ if (factory->m_supportedType == sourceType) {
+ BaseQtVersion *version = factory->create();
+ QTC_ASSERT(version, return nullptr);
+ version->fromMap(source->toMap());
+ return version;
+ }
+ }
+ QTC_CHECK(false);
+ return nullptr;
+}
+
+void QtVersionFactory::setQtVersionCreator(const std::function<BaseQtVersion *()> &creator)
+{
+ m_creator = creator;
+}
+
+void QtVersionFactory::setRestrictionChecker(const std::function<bool(const SetupData &)> &checker)
+{
+ m_restrictionChecker = checker;
+}
+
+void QtVersionFactory::setSupportedType(const QString &type)
+{
+ m_supportedType = type;
+}
+
+void QtVersionFactory::setPriority(int priority)
+{
+ m_priority = priority;
+}
diff --git a/src/plugins/qtsupport/qtversionfactory.h b/src/plugins/qtsupport/qtversionfactory.h
index fad90280cd..4bafe40c14 100644
--- a/src/plugins/qtsupport/qtversionfactory.h
+++ b/src/plugins/qtsupport/qtversionfactory.h
@@ -27,45 +27,58 @@
#include "qtsupport_global.h"
-#include <QObject>
#include <QVariantMap>
-QT_BEGIN_NAMESPACE
-class QSettings;
-class ProFileEvaluator;
-QT_END_NAMESPACE
-
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace QtSupport {
class BaseQtVersion;
-class QTSUPPORT_EXPORT QtVersionFactory : public QObject
+class QTSUPPORT_EXPORT QtVersionFactory
{
- Q_OBJECT
-
public:
- explicit QtVersionFactory(QObject *parent = nullptr);
- ~QtVersionFactory() override;
+ QtVersionFactory();
+ virtual ~QtVersionFactory();
static const QList<QtVersionFactory *> allQtVersionFactories();
- virtual bool canRestore(const QString &type) = 0;
- virtual BaseQtVersion *restore(const QString &type, const QVariantMap &data) = 0;
+ bool canRestore(const QString &type);
+ BaseQtVersion *restore(const QString &type, const QVariantMap &data);
/// factories with higher priority are asked first to identify
/// a qtversion, the priority of the desktop factory is 0 and
/// the desktop factory claims to handle all paths
- virtual int priority() const = 0;
- virtual BaseQtVersion *create(const Utils::FileName &qmakePath,
- ProFileEvaluator *evaluator,
- bool isAutoDetected = false,
- const QString &autoDetectionSource = QString()) = 0;
+ int priority() const { return m_priority; }
+
+ QString supportedType() const;
static BaseQtVersion *createQtVersionFromQMakePath(
- const Utils::FileName &qmakePath, bool isAutoDetected = false,
+ const Utils::FilePath &qmakePath, bool isAutoDetected = false,
const QString &autoDetectionSource = QString(), QString *error = nullptr);
+
+ static BaseQtVersion *cloneQtVersion(const BaseQtVersion *source);
+
+protected:
+ struct SetupData
+ {
+ QStringList platforms;
+ QStringList config;
+ bool isQnx = false; // eeks...
+ };
+
+ void setQtVersionCreator(const std::function<BaseQtVersion *()> &creator);
+ void setRestrictionChecker(const std::function<bool(const SetupData &)> &checker);
+ void setSupportedType(const QString &type);
+ void setPriority(int priority);
+
+private:
+ BaseQtVersion *create() const;
+
+ std::function<BaseQtVersion *()> m_creator;
+ std::function<bool(const SetupData &)> m_restrictionChecker;
+ QString m_supportedType;
+ int m_priority = 0;
};
} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp
index c67edb4a36..36e720a8f0 100644
--- a/src/plugins/qtsupport/qtversionmanager.cpp
+++ b/src/plugins/qtsupport/qtversionmanager.cpp
@@ -75,14 +75,14 @@ static PersistentSettingsWriter *m_writer = nullptr;
enum { debug = 0 };
-static FileName globalSettingsFileName()
+static FilePath globalSettingsFileName()
{
- return FileName::fromString(Core::ICore::installerResourcePath() + QTVERSION_FILENAME);
+ return FilePath::fromString(Core::ICore::installerResourcePath() + QTVERSION_FILENAME);
}
-static FileName settingsFileName(const QString &path)
+static FilePath settingsFileName(const QString &path)
{
- return FileName::fromString(Core::ICore::userResourcePath() + path);
+ return FilePath::fromString(Core::ICore::userResourcePath() + path);
}
@@ -109,7 +109,7 @@ QtVersionManager::QtVersionManager()
m_writer = nullptr;
m_idcount = 1;
- qRegisterMetaType<FileName>();
+ qRegisterMetaType<FilePath>();
// Give the file a bit of time to settle before reading it...
m_fileWatcherTimer->setInterval(2000);
@@ -134,11 +134,11 @@ void QtVersionManager::triggerQtVersionRestore()
emit m_instance->qtVersionsChanged(m_versions.keys(), QList<int>(), QList<int>());
saveQtVersions();
- const FileName configFileName = globalSettingsFileName();
+ const FilePath configFileName = globalSettingsFileName();
if (configFileName.exists()) {
m_configFileWatcher = new FileSystemWatcher(m_instance);
connect(m_configFileWatcher, &FileSystemWatcher::fileChanged,
- m_fileWatcherTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ m_fileWatcherTimer, QOverload<>::of(&QTimer::start));
m_configFileWatcher->addFile(configFileName.toString(),
FileSystemWatcher::WatchModifiedDate);
} // exists
@@ -178,7 +178,7 @@ static bool restoreQtVersions()
const QList<QtVersionFactory *> factories = QtVersionFactory::allQtVersionFactories();
PersistentSettingsReader reader;
- FileName filename = settingsFileName(QLatin1String(QTVERSION_FILENAME));
+ FilePath filename = settingsFileName(QLatin1String(QTVERSION_FILENAME));
if (!reader.load(filename))
return false;
@@ -234,7 +234,7 @@ void QtVersionManager::updateFromInstaller(bool emitSignal)
{
m_fileWatcherTimer->stop();
- const FileName path = globalSettingsFileName();
+ const FilePath path = globalSettingsFileName();
// Handle overwritting of data:
if (m_configFileWatcher) {
m_configFileWatcher->removeFile(path.toString());
@@ -408,16 +408,16 @@ static QString qmakePath(const QString &qtchooser, const QString &version)
return QString();
}
-static FileNameList gatherQmakePathsFromQtChooser()
+static FilePathList gatherQmakePathsFromQtChooser()
{
const QString qtchooser = QStandardPaths::findExecutable(QStringLiteral("qtchooser"));
if (qtchooser.isEmpty())
- return FileNameList();
+ return FilePathList();
QList<QByteArray> versions = runQtChooser(qtchooser, QStringList("-l"));
- QSet<FileName> foundQMakes;
+ QSet<FilePath> foundQMakes;
foreach (const QByteArray &version, versions) {
- FileName possibleQMake = FileName::fromString(
+ FilePath possibleQMake = FilePath::fromString(
qmakePath(qtchooser, QString::fromLocal8Bit(version)));
if (!possibleQMake.isEmpty())
foundQMakes << possibleQMake;
@@ -427,14 +427,12 @@ static FileNameList gatherQmakePathsFromQtChooser()
static void findSystemQt()
{
- FileNameList systemQMakes;
- FileName systemQMakePath = BuildableHelperLibrary::findSystemQt(Environment::systemEnvironment());
- if (!systemQMakePath.isEmpty())
- systemQMakes << systemQMakePath;
+ FilePathList systemQMakes
+ = BuildableHelperLibrary::findQtsInEnvironment(Environment::systemEnvironment());
systemQMakes.append(gatherQmakePathsFromQtChooser());
- foreach (const FileName &qmakePath, Utils::filteredUnique(systemQMakes)) {
+ foreach (const FilePath &qmakePath, Utils::filteredUnique(systemQMakes)) {
BaseQtVersion *version
= QtVersionFactory::createQtVersionFromQMakePath(qmakePath, false, QLatin1String("PATH"));
if (version) {
@@ -483,15 +481,6 @@ static void updateDocumentation()
Core::HelpManager::registerDocumentation(files);
}
-void QtVersionManager::updateDumpFor(const FileName &qmakeCommand)
-{
- foreach (BaseQtVersion *v, versions()) {
- if (v->qmakeCommand() == qmakeCommand)
- v->recheckDumper();
- }
- emit dumpUpdatedFor(qmakeCommand);
-}
-
int QtVersionManager::getUniqueId()
{
return m_idcount++;
@@ -602,7 +591,7 @@ void QtVersionManager::setNewQtVersions(QList<BaseQtVersion *> newVersions)
emit m_instance->qtVersionsChanged(addedVersions, removedVersions, changedVersions);
}
-BaseQtVersion *QtVersionManager::qtVersionForQMakeBinary(const FileName &qmakePath)
+BaseQtVersion *QtVersionManager::qtVersionForQMakeBinary(const FilePath &qmakePath)
{
return version(Utils::equal(&BaseQtVersion::qmakeCommand, qmakePath));
}
diff --git a/src/plugins/qtsupport/qtversionmanager.h b/src/plugins/qtsupport/qtversionmanager.h
index 790dc543ff..4a9d077752 100644
--- a/src/plugins/qtsupport/qtversionmanager.h
+++ b/src/plugins/qtsupport/qtversionmanager.h
@@ -58,7 +58,7 @@ public:
// Sorting is potentially expensive since it might require qmake --query to run for each version!
static QList<BaseQtVersion *> sortVersions(const QList<BaseQtVersion *> &input);
- static BaseQtVersion *qtVersionForQMakeBinary(const Utils::FileName &qmakePath);
+ static BaseQtVersion *qtVersionForQMakeBinary(const Utils::FilePath &qmakePath);
static void addVersion(BaseQtVersion *version);
static void removeVersion(BaseQtVersion *version);
@@ -67,13 +67,9 @@ public:
signals:
// content of BaseQtVersion objects with qmake path might have changed
- void dumpUpdatedFor(const Utils::FileName &qmakeCommand);
void qtVersionsChanged(const QList<int> &addedIds, const QList<int> &removedIds, const QList<int> &changedIds);
void qtVersionsLoaded();
-public slots:
- void updateDumpFor(const Utils::FileName &qmakeCommand);
-
private:
void updateFromInstaller(bool emitSignal = true);
void triggerQtVersionRestore();
diff --git a/src/plugins/qtsupport/screenshotcropper.cpp b/src/plugins/qtsupport/screenshotcropper.cpp
index 1865826ebf..79e10a8b84 100644
--- a/src/plugins/qtsupport/screenshotcropper.cpp
+++ b/src/plugins/qtsupport/screenshotcropper.cpp
@@ -52,7 +52,7 @@ Q_GLOBAL_STATIC(AreasOfInterest, welcomeScreenAreas)
static inline QString fileNameForPath(const QString &path)
{
- return Utils::FileName::fromString(path).fileName();
+ return Utils::FilePath::fromString(path).fileName();
}
static QRect cropRectForAreaOfInterest(const QSize &imageSize, const QSize &cropSize, const QRect &areaOfInterest)
diff --git a/src/plugins/qtsupport/uicgenerator.cpp b/src/plugins/qtsupport/uicgenerator.cpp
index 89e8713b22..9d86893278 100644
--- a/src/plugins/qtsupport/uicgenerator.cpp
+++ b/src/plugins/qtsupport/uicgenerator.cpp
@@ -43,32 +43,31 @@ using namespace ProjectExplorer;
namespace QtSupport {
-UicGenerator::UicGenerator(const Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent) :
+UicGenerator::UicGenerator(const Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent) :
ProcessExtraCompiler(project, source, targets, parent)
{
QTC_ASSERT(targets.count() == 1, return);
}
-Utils::FileName UicGenerator::command() const
+Utils::FilePath UicGenerator::command() const
{
QtSupport::BaseQtVersion *version = nullptr;
Target *target;
if ((target = project()->activeTarget()))
- version = QtSupport::QtKitInformation::qtVersion(target->kit());
+ version = QtSupport::QtKitAspect::qtVersion(target->kit());
else
- version = QtSupport::QtKitInformation::qtVersion(KitManager::defaultKit());
+ version = QtSupport::QtKitAspect::qtVersion(KitManager::defaultKit());
if (!version)
- return Utils::FileName();
+ return Utils::FilePath();
- return Utils::FileName::fromString(version->uicCommand());
+ return Utils::FilePath::fromString(version->uicCommand());
}
-void UicGenerator::handleProcessStarted(QProcess *process, const QByteArray &sourceContents)
+QStringList UicGenerator::arguments() const
{
- process->write(sourceContents);
- process->closeWriteChannel();
+ return {source().toString()};
}
FileNameToContentsHash UicGenerator::handleProcessFinished(QProcess *process)
@@ -77,7 +76,7 @@ FileNameToContentsHash UicGenerator::handleProcessFinished(QProcess *process)
if (process->exitStatus() != QProcess::NormalExit && process->exitCode() != 0)
return result;
- const Utils::FileNameList targetList = targets();
+ const Utils::FilePathList 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
@@ -97,8 +96,8 @@ QString UicGeneratorFactory::sourceTag() const
}
ExtraCompiler *UicGeneratorFactory::create(const Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets)
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets)
{
annouceCreation(project, source, targets);
diff --git a/src/plugins/qtsupport/uicgenerator.h b/src/plugins/qtsupport/uicgenerator.h
index b0253eb73c..1253e8f1ab 100644
--- a/src/plugins/qtsupport/uicgenerator.h
+++ b/src/plugins/qtsupport/uicgenerator.h
@@ -36,12 +36,12 @@ class UicGenerator : public ProjectExplorer::ProcessExtraCompiler
{
Q_OBJECT
public:
- UicGenerator(const ProjectExplorer::Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets, QObject *parent = 0);
+ UicGenerator(const ProjectExplorer::Project *project, const Utils::FilePath &source,
+ const Utils::FilePathList &targets, QObject *parent = 0);
protected:
- Utils::FileName command() const override;
- void handleProcessStarted(QProcess *process, const QByteArray &sourceContents) override;
+ Utils::FilePath command() const override;
+ QStringList arguments() const override;
ProjectExplorer::FileNameToContentsHash handleProcessFinished(QProcess *process) override;
};
@@ -56,8 +56,8 @@ public:
QString sourceTag() const override;
ProjectExplorer::ExtraCompiler *create(const ProjectExplorer::Project *project,
- const Utils::FileName &source,
- const Utils::FileNameList &targets) override;
+ const Utils::FilePath &source,
+ const Utils::FilePathList &targets) override;
};
} // QtSupport
diff --git a/src/plugins/remotelinux/CMakeLists.txt b/src/plugins/remotelinux/CMakeLists.txt
new file mode 100644
index 0000000000..63c97b1686
--- /dev/null
+++ b/src/plugins/remotelinux/CMakeLists.txt
@@ -0,0 +1,49 @@
+add_qtc_plugin(RemoteLinux
+ DEPENDS QmlDebug QtcSsh
+ PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
+ SOURCES
+ abstractpackagingstep.cpp abstractpackagingstep.h
+ abstractremotelinuxdeployservice.cpp abstractremotelinuxdeployservice.h
+ abstractremotelinuxdeploystep.cpp abstractremotelinuxdeploystep.h
+ abstractuploadandinstallpackageservice.cpp abstractuploadandinstallpackageservice.h
+ deploymenttimeinfo.cpp deploymenttimeinfo.h
+ embeddedlinuxqtversion.cpp embeddedlinuxqtversion.h
+ genericdirectuploadservice.cpp genericdirectuploadservice.h
+ genericdirectuploadstep.cpp genericdirectuploadstep.h
+ genericlinuxdeviceconfigurationwidget.cpp genericlinuxdeviceconfigurationwidget.h genericlinuxdeviceconfigurationwidget.ui
+ genericlinuxdeviceconfigurationwizard.cpp genericlinuxdeviceconfigurationwizard.h
+ genericlinuxdeviceconfigurationwizardpages.cpp genericlinuxdeviceconfigurationwizardpages.h
+ genericlinuxdeviceconfigurationwizardsetuppage.ui
+ linuxdevice.cpp linuxdevice.h
+ linuxdeviceprocess.cpp linuxdeviceprocess.h
+ linuxdevicetester.cpp linuxdevicetester.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
+ tarpackagecreationstep.cpp tarpackagecreationstep.h
+ typespecificdeviceconfigurationlistmodel.cpp typespecificdeviceconfigurationlistmodel.h
+ uploadandinstalltarpackagestep.cpp uploadandinstalltarpackagestep.h
+)
diff --git a/src/plugins/remotelinux/abstractpackagingstep.cpp b/src/plugins/remotelinux/abstractpackagingstep.cpp
index 75a6fe2fa7..c328837628 100644
--- a/src/plugins/remotelinux/abstractpackagingstep.cpp
+++ b/src/plugins/remotelinux/abstractpackagingstep.cpp
@@ -114,10 +114,8 @@ bool AbstractPackagingStep::isPackagingNeeded() const
const DeploymentData &dd = target()->deploymentData();
for (int i = 0; i < dd.fileCount(); ++i) {
- if (Utils::FileUtils::isFileNewerThan(dd.fileAt(i).localFilePath(),
- packageInfo.lastModified())) {
+ if (dd.fileAt(i).localFilePath().isNewerThan(packageInfo.lastModified()))
return true;
- }
}
return false;
@@ -154,7 +152,7 @@ void AbstractPackagingStep::setDeploymentDataModified()
void AbstractPackagingStep::raiseError(const QString &errorMessage)
{
- Task task = Task(Task::Error, errorMessage, Utils::FileName(), -1,
+ Task task = Task(Task::Error, errorMessage, Utils::FilePath(), -1,
Constants::TASK_CATEGORY_DEPLOYMENT);
emit addTask(task);
emit addOutput(errorMessage, BuildStep::OutputFormat::Stderr);
@@ -162,7 +160,7 @@ void AbstractPackagingStep::raiseError(const QString &errorMessage)
void AbstractPackagingStep::raiseWarning(const QString &warningMessage)
{
- Task task = Task(Task::Warning, warningMessage, Utils::FileName(), -1,
+ Task task = Task(Task::Warning, warningMessage, Utils::FilePath(), -1,
Constants::TASK_CATEGORY_DEPLOYMENT);
emit addTask(task);
emit addOutput(warningMessage, OutputFormat::ErrorMessage);
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
index c5f60d3e29..c6d184ec12 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
+++ b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
@@ -114,7 +114,7 @@ bool AbstractRemoteLinuxDeployService::hasRemoteFileChanged(
void AbstractRemoteLinuxDeployService::setTarget(Target *target)
{
d->target = target;
- d->deviceConfiguration = DeviceKitInformation::device(profile());
+ d->deviceConfiguration = DeviceKitAspect::device(profile());
}
void AbstractRemoteLinuxDeployService::setDevice(const IDevice::ConstPtr &device)
@@ -126,9 +126,9 @@ void AbstractRemoteLinuxDeployService::start()
{
QTC_ASSERT(d->state == Inactive, return);
- QString errorMsg;
- if (!isDeploymentPossible(&errorMsg)) {
- emit errorMessage(errorMsg);
+ const CheckResult check = isDeploymentPossible();
+ if (!check) {
+ emit errorMessage(check.errorMessage());
emit finished();
return;
}
@@ -165,14 +165,11 @@ void AbstractRemoteLinuxDeployService::stop()
}
}
-bool AbstractRemoteLinuxDeployService::isDeploymentPossible(QString *whyNot) const
+CheckResult AbstractRemoteLinuxDeployService::isDeploymentPossible() const
{
- if (!deviceConfiguration()) {
- if (whyNot)
- *whyNot = tr("No device configuration set.");
- return false;
- }
- return true;
+ if (!deviceConfiguration())
+ return CheckResult::failure(tr("No device configuration set."));
+ return CheckResult::success();
}
QVariantMap AbstractRemoteLinuxDeployService::exportDeployTimes() const
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeployservice.h b/src/plugins/remotelinux/abstractremotelinuxdeployservice.h
index 9e55708d65..6ebf2d7592 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeployservice.h
+++ b/src/plugins/remotelinux/abstractremotelinuxdeployservice.h
@@ -43,6 +43,22 @@ class Target;
namespace RemoteLinux {
namespace Internal { class AbstractRemoteLinuxDeployServicePrivate; }
+class REMOTELINUX_EXPORT CheckResult
+{
+public:
+ static CheckResult success() { return {true, {}}; }
+ static CheckResult failure(const QString &error = {}) { return {false, error}; }
+
+ operator bool() const { return m_ok; }
+ QString errorMessage() const { return m_error; }
+
+private:
+ CheckResult(bool ok, const QString &error) : m_ok(ok), m_error(error) {}
+
+ bool m_ok = false;
+ QString m_error;
+};
+
class REMOTELINUX_EXPORT AbstractRemoteLinuxDeployService : public QObject
{
Q_OBJECT
@@ -60,7 +76,7 @@ public:
QVariantMap exportDeployTimes() const;
void importDeployTimes(const QVariantMap &map);
- virtual bool isDeploymentPossible(QString *whyNot = nullptr) const;
+ virtual CheckResult isDeploymentPossible() const;
signals:
void errorMessage(const QString &message);
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp b/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
index 5827c4fa94..45e34bda29 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
+++ b/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
@@ -69,11 +69,12 @@ QVariantMap AbstractRemoteLinuxDeployStep::toMap() const
bool AbstractRemoteLinuxDeployStep::init()
{
- QString error;
deployService()->setTarget(target());
- const bool canDeploy = initInternal(&error);
- if (!canDeploy)
- emit addOutput(tr("Cannot deploy: %1").arg(error), OutputFormat::ErrorMessage);
+ const CheckResult canDeploy = initInternal();
+ if (!canDeploy) {
+ emit addOutput(tr("Cannot deploy: %1").arg(canDeploy.errorMessage()),
+ OutputFormat::ErrorMessage);
+ }
return canDeploy;
}
@@ -114,7 +115,7 @@ void AbstractRemoteLinuxDeployStep::handleProgressMessage(const QString &message
void AbstractRemoteLinuxDeployStep::handleErrorMessage(const QString &message)
{
- ProjectExplorer::Task task = Task(Task::Error, message, Utils::FileName(), -1,
+ ProjectExplorer::Task task = Task(Task::Error, message, Utils::FilePath(), -1,
Constants::TASK_CATEGORY_DEPLOYMENT);
emit addTask(task, 1); // TODO correct?
emit addOutput(message, OutputFormat::ErrorMessage);
@@ -123,7 +124,7 @@ void AbstractRemoteLinuxDeployStep::handleErrorMessage(const QString &message)
void AbstractRemoteLinuxDeployStep::handleWarningMessage(const QString &message)
{
- ProjectExplorer::Task task = Task(Task::Warning, message, Utils::FileName(), -1,
+ ProjectExplorer::Task task = Task(Task::Warning, message, Utils::FilePath(), -1,
Constants::TASK_CATEGORY_DEPLOYMENT);
emit addTask(task, 1); // TODO correct?
emit addOutput(message, OutputFormat::ErrorMessage);
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeploystep.h b/src/plugins/remotelinux/abstractremotelinuxdeploystep.h
index 03741d3367..e8fac039b7 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeploystep.h
+++ b/src/plugins/remotelinux/abstractremotelinuxdeploystep.h
@@ -27,12 +27,11 @@
#include "remotelinux_export.h"
-#include <projectexplorer/buildstep.h>
+#include "abstractremotelinuxdeployservice.h"
-#include <QVariantMap>
+#include <projectexplorer/buildstep.h>
namespace RemoteLinux {
-class AbstractRemoteLinuxDeployService;
namespace Internal { class AbstractRemoteLinuxDeployStepPrivate; }
@@ -52,7 +51,7 @@ protected:
void doCancel() override;
explicit AbstractRemoteLinuxDeployStep(ProjectExplorer::BuildStepList *bsl, Core::Id id);
- virtual bool initInternal(QString *error = nullptr) = 0;
+ virtual CheckResult initInternal() = 0;
private:
void handleProgressMessage(const QString &message);
diff --git a/src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp b/src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp
index ee79ba4ec8..18ac23f496 100644
--- a/src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp
+++ b/src/plugins/remotelinux/abstractuploadandinstallpackageservice.cpp
@@ -110,7 +110,7 @@ void AbstractUploadAndInstallPackageService::doDeploy()
QTC_ASSERT(d->state == Inactive, return);
d->state = Uploading;
- const QString fileName = Utils::FileName::fromString(packageFilePath()).fileName();
+ const QString fileName = Utils::FilePath::fromString(packageFilePath()).fileName();
const QString remoteFilePath = uploadDir() + QLatin1Char('/') + fileName;
connect(d->uploader, &PackageUploader::progress,
this, &AbstractUploadAndInstallPackageService::progressMessage);
@@ -148,7 +148,7 @@ void AbstractUploadAndInstallPackageService::handleUploadFinished(const QString
emit progressMessage(tr("Successfully uploaded package file."));
const QString remoteFilePath = uploadDir() + QLatin1Char('/')
- + Utils::FileName::fromString(packageFilePath()).fileName();
+ + Utils::FilePath::fromString(packageFilePath()).fileName();
d->state = Installing;
emit progressMessage(tr("Installing package to device..."));
connect(packageInstaller(), &AbstractRemoteLinuxPackageInstaller::stdoutData,
diff --git a/src/plugins/remotelinux/deploymenttimeinfo.cpp b/src/plugins/remotelinux/deploymenttimeinfo.cpp
index d3b9dcee61..e43dd75ca7 100644
--- a/src/plugins/remotelinux/deploymenttimeinfo.cpp
+++ b/src/plugins/remotelinux/deploymenttimeinfo.cpp
@@ -88,8 +88,8 @@ public:
QString host;
if (kit) {
- systemRoot = SysRootKitInformation::sysRoot(kit).toString();
- const IDevice::ConstPtr deviceConfiguration = DeviceKitInformation::device(kit);
+ systemRoot = SysRootKitAspect::sysRoot(kit).toString();
+ const IDevice::ConstPtr deviceConfiguration = DeviceKitAspect::device(kit);
host = deviceConfiguration->sshParameters().host();
}
diff --git a/src/plugins/remotelinux/embeddedlinuxqtversion.cpp b/src/plugins/remotelinux/embeddedlinuxqtversion.cpp
index 1aad59919c..e315cf066a 100644
--- a/src/plugins/remotelinux/embeddedlinuxqtversion.cpp
+++ b/src/plugins/remotelinux/embeddedlinuxqtversion.cpp
@@ -35,36 +35,34 @@
namespace RemoteLinux {
namespace Internal {
-EmbeddedLinuxQtVersion::EmbeddedLinuxQtVersion(const Utils::FileName &path, bool isAutodetected,
- const QString &autodetectionSource)
- : BaseQtVersion(path, isAutodetected, autodetectionSource)
+QString EmbeddedLinuxQtVersion::description() const
{
- setUnexpandedDisplayName(defaultUnexpandedDisplayName(path, false));
+ return QCoreApplication::translate("QtVersion", "Embedded Linux", "Qt Version is used for embedded Linux development");
}
-EmbeddedLinuxQtVersion *EmbeddedLinuxQtVersion::clone() const
+QSet<Core::Id> EmbeddedLinuxQtVersion::targetDeviceTypes() const
{
- return new EmbeddedLinuxQtVersion(*this);
+ return {Constants::GenericLinuxOsType};
}
-QString EmbeddedLinuxQtVersion::type() const
-{
- return QLatin1String(RemoteLinux::Constants::EMBEDDED_LINUX_QT);
-}
-QList<ProjectExplorer::Abi> EmbeddedLinuxQtVersion::detectQtAbis() const
-{
- return qtAbisFromLibrary(qtCorePaths());
-}
+// Factory
-QString EmbeddedLinuxQtVersion::description() const
+EmbeddedLinuxQtVersionFactory::EmbeddedLinuxQtVersionFactory()
{
- return QCoreApplication::translate("QtVersion", "Embedded Linux", "Qt Version is used for embedded Linux development");
-}
+ setQtVersionCreator([] { return new EmbeddedLinuxQtVersion; });
+ setSupportedType(RemoteLinux::Constants::EMBEDDED_LINUX_QT);
+ setPriority(10);
-QSet<Core::Id> EmbeddedLinuxQtVersion::targetDeviceTypes() const
-{
- return {Constants::GenericLinuxOsType};
+ setRestrictionChecker([](const SetupData &) {
+ const EmbeddedLinuxQtVersion tempVersion;
+ const ProjectExplorer::Abis abis = tempVersion.qtAbis();
+
+ // Note: This fails for e.g. intel/meego cross builds on x86 linux machines.
+ return abis.count() == 1
+ && abis.at(0).os() == ProjectExplorer::Abi::LinuxOS
+ && !ProjectExplorer::Abi::hostAbi().isCompatibleWith(abis.at(0));
+ });
}
} // namespace Internal
diff --git a/src/plugins/remotelinux/embeddedlinuxqtversion.h b/src/plugins/remotelinux/embeddedlinuxqtversion.h
index f9b823e428..e70eea1df3 100644
--- a/src/plugins/remotelinux/embeddedlinuxqtversion.h
+++ b/src/plugins/remotelinux/embeddedlinuxqtversion.h
@@ -26,6 +26,7 @@
#pragma once
#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtversionfactory.h>
namespace RemoteLinux {
namespace Internal {
@@ -34,18 +35,17 @@ class EmbeddedLinuxQtVersion : public QtSupport::BaseQtVersion
{
public:
EmbeddedLinuxQtVersion() = default;
- EmbeddedLinuxQtVersion(const Utils::FileName &path, bool isAutodetected = false,
- const QString &autodetectionSource = QString());
- EmbeddedLinuxQtVersion *clone() const override;
-
- QString type() const override;
-
- QList<ProjectExplorer::Abi> detectQtAbis() const override;
QString description() const override;
QSet<Core::Id> targetDeviceTypes() const override;
};
+class EmbeddedLinuxQtVersionFactory : public QtSupport::QtVersionFactory
+{
+public:
+ EmbeddedLinuxQtVersionFactory();
+};
+
} // namespace Internal
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/embeddedlinuxqtversionfactory.cpp b/src/plugins/remotelinux/embeddedlinuxqtversionfactory.cpp
deleted file mode 100644
index c804c0a012..0000000000
--- a/src/plugins/remotelinux/embeddedlinuxqtversionfactory.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 "embeddedlinuxqtversionfactory.h"
-
-#include "embeddedlinuxqtversion.h"
-#include "remotelinux_constants.h"
-
-#include <QFileInfo>
-
-namespace RemoteLinux {
-namespace Internal {
-
-EmbeddedLinuxQtVersionFactory::EmbeddedLinuxQtVersionFactory(QObject *parent)
- : QtSupport::QtVersionFactory(parent)
-{
-}
-
-EmbeddedLinuxQtVersionFactory::~EmbeddedLinuxQtVersionFactory() = default;
-
-bool EmbeddedLinuxQtVersionFactory::canRestore(const QString &type)
-{
- return type == QLatin1String(RemoteLinux::Constants::EMBEDDED_LINUX_QT);
-}
-
-QtSupport::BaseQtVersion *EmbeddedLinuxQtVersionFactory::restore(const QString &type, const QVariantMap &data)
-{
- if (!canRestore(type))
- return nullptr;
- auto v = new EmbeddedLinuxQtVersion;
- v->fromMap(data);
- return v;
-}
-
-int EmbeddedLinuxQtVersionFactory::priority() const
-{
- return 10;
-}
-
-QtSupport::BaseQtVersion *EmbeddedLinuxQtVersionFactory::create(const Utils::FileName &qmakePath,
- ProFileEvaluator *evaluator,
- bool isAutoDetected,
- const QString &autoDetectionSource)
-{
- Q_UNUSED(evaluator);
-
- QFileInfo fi = qmakePath.toFileInfo();
- if (!fi.exists() || !fi.isExecutable() || !fi.isFile())
- return nullptr;
-
- auto version = new EmbeddedLinuxQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
-
- QList<ProjectExplorer::Abi> abis = version->qtAbis();
- // Note: This fails for e.g. intel/meego cross builds on x86 linux machines.
- if (abis.count() == 1
- && abis.at(0).os() == ProjectExplorer::Abi::LinuxOS
- && !ProjectExplorer::Abi::hostAbi().isCompatibleWith(abis.at(0)))
- return version;
-
- delete version;
- return nullptr;
-}
-
-} // namespace Internal
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/embeddedlinuxqtversionfactory.h b/src/plugins/remotelinux/embeddedlinuxqtversionfactory.h
deleted file mode 100644
index 7737a8de7a..0000000000
--- a/src/plugins/remotelinux/embeddedlinuxqtversionfactory.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 <qtsupport/qtversionfactory.h>
-
-namespace RemoteLinux {
-namespace Internal {
-
-class EmbeddedLinuxQtVersionFactory : public QtSupport::QtVersionFactory
-{
-public:
- explicit EmbeddedLinuxQtVersionFactory(QObject *parent = nullptr);
- ~EmbeddedLinuxQtVersionFactory() override;
-
- bool canRestore(const QString &type) override;
- QtSupport::BaseQtVersion *restore(const QString &type, const QVariantMap &data) override;
-
- int priority() const override;
- QtSupport::BaseQtVersion *create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator,
- bool isAutoDetected = false,
- const QString &autoDetectionSource = QString()) override;
-};
-
-} // Internal
-} // RemoteLinux
diff --git a/src/plugins/remotelinux/genericdirectuploadservice.cpp b/src/plugins/remotelinux/genericdirectuploadservice.cpp
index 014ed5db62..84779d373e 100644
--- a/src/plugins/remotelinux/genericdirectuploadservice.cpp
+++ b/src/plugins/remotelinux/genericdirectuploadservice.cpp
@@ -238,8 +238,7 @@ void GenericDirectUploadService::queryFiles()
continue;
}
// We'd like to use --format=%Y, but it's not supported by busybox.
- const QByteArray statCmd = "stat -t "
- + Utils::QtcProcess::quoteArgUnix(file.remoteFilePath()).toUtf8();
+ const QString statCmd = "stat -t " + Utils::QtcProcess::quoteArgUnix(file.remoteFilePath());
SshRemoteProcess * const statProc = connection()->createRemoteProcess(statCmd).release();
statProc->setParent(this);
connect(statProc, &SshRemoteProcess::done, this,
@@ -328,7 +327,7 @@ void GenericDirectUploadService::chmod()
const QString command = QLatin1String("chmod a+x ")
+ Utils::QtcProcess::quoteArgUnix(f.remoteFilePath());
SshRemoteProcess * const chmodProc
- = connection()->createRemoteProcess(command.toUtf8()).release();
+ = connection()->createRemoteProcess(command).release();
chmodProc->setParent(this);
connect(chmodProc, &SshRemoteProcess::done, this,
[this, chmodProc, state = d->state](const QString &error) {
diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp
index a3f234685e..27668c0a50 100644
--- a/src/plugins/remotelinux/genericdirectuploadstep.cpp
+++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp
@@ -71,12 +71,11 @@ GenericDirectUploadStep::~GenericDirectUploadStep()
delete d;
}
-bool GenericDirectUploadStep::initInternal(QString *error)
+CheckResult GenericDirectUploadStep::initInternal()
{
- d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
d->deployService.setIncrementalDeployment(d->incrementalAspect->value());
d->deployService.setIgnoreMissingFiles(d->ignoreMissingFilesAspect->value());
- return d->deployService.isDeploymentPossible(error);
+ return d->deployService.isDeploymentPossible();
}
GenericDirectUploadService *GenericDirectUploadStep::deployService() const
@@ -84,6 +83,12 @@ GenericDirectUploadService *GenericDirectUploadStep::deployService() const
return &d->deployService;
}
+void GenericDirectUploadStep::doRun()
+{
+ d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
+ AbstractRemoteLinuxDeployStep::doRun();
+}
+
Core::Id GenericDirectUploadStep::stepId()
{
return "RemoteLinux.DirectUploadStep";
diff --git a/src/plugins/remotelinux/genericdirectuploadstep.h b/src/plugins/remotelinux/genericdirectuploadstep.h
index 5751e833b6..fa9b98205c 100644
--- a/src/plugins/remotelinux/genericdirectuploadstep.h
+++ b/src/plugins/remotelinux/genericdirectuploadstep.h
@@ -40,13 +40,14 @@ public:
explicit GenericDirectUploadStep(ProjectExplorer::BuildStepList *bsl);
~GenericDirectUploadStep() override;
- bool initInternal(QString *error = nullptr) override;
+ CheckResult initInternal() override;
static Core::Id stepId();
static QString displayName();
private:
GenericDirectUploadService *deployService() const override;
+ void doRun() override;
Internal::GenericDirectUploadStepPrivate *d;
};
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp
deleted file mode 100644
index f044da4f4d..0000000000
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.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 "genericlinuxdeviceconfigurationfactory.h"
-
-#include "genericlinuxdeviceconfigurationwizard.h"
-#include "linuxdevice.h"
-#include "remotelinux_constants.h"
-
-#include <coreplugin/icore.h>
-
-#include <utils/qtcassert.h>
-
-using namespace ProjectExplorer;
-
-namespace RemoteLinux {
-
-GenericLinuxDeviceConfigurationFactory::GenericLinuxDeviceConfigurationFactory()
- : IDeviceFactory(Constants::GenericLinuxOsType)
-{
- setDisplayName(tr("Generic Linux Device"));
- setIcon(QIcon());
- setCanCreate(true);
- setConstructionFunction(&LinuxDevice::create);
-}
-
-IDevice::Ptr GenericLinuxDeviceConfigurationFactory::create() const
-{
- GenericLinuxDeviceConfigurationWizard wizard(Core::ICore::mainWindow());
- if (wizard.exec() != QDialog::Accepted)
- return IDevice::Ptr();
- return wizard.device();
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h
deleted file mode 100644
index 889840b337..0000000000
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.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 "remotelinux_export.h"
-
-#include <projectexplorer/devicesupport/idevicefactory.h>
-
-namespace RemoteLinux {
-
-class REMOTELINUX_EXPORT GenericLinuxDeviceConfigurationFactory
- : public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-
-public:
- GenericLinuxDeviceConfigurationFactory();
-
- ProjectExplorer::IDevice::Ptr create() const override;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
index 5957ac428b..4f7eaf229d 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
@@ -56,11 +56,11 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget(
this, &GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged);
connect(m_ui->timeoutSpinBox, &QAbstractSpinBox::editingFinished,
this, &GenericLinuxDeviceConfigurationWidget::timeoutEditingFinished);
- connect(m_ui->timeoutSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_ui->timeoutSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &GenericLinuxDeviceConfigurationWidget::timeoutEditingFinished);
connect(m_ui->sshPortSpinBox, &QAbstractSpinBox::editingFinished,
this, &GenericLinuxDeviceConfigurationWidget::sshPortEditingFinished);
- connect(m_ui->sshPortSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_ui->sshPortSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &GenericLinuxDeviceConfigurationWidget::sshPortEditingFinished);
connect(m_ui->portsLineEdit, &QLineEdit::editingFinished,
this, &GenericLinuxDeviceConfigurationWidget::handleFreePortsChanged);
diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp
index aa291079f2..6e05739c01 100644
--- a/src/plugins/remotelinux/linuxdevice.cpp
+++ b/src/plugins/remotelinux/linuxdevice.cpp
@@ -26,6 +26,7 @@
#include "linuxdevice.h"
#include "genericlinuxdeviceconfigurationwidget.h"
+#include "genericlinuxdeviceconfigurationwizard.h"
#include "linuxdeviceprocess.h"
#include "linuxdevicetester.h"
#include "publickeydeploymentdialog.h"
@@ -33,12 +34,17 @@
#include "remotelinuxsignaloperation.h"
#include "remotelinuxenvironmentreader.h"
+#include <coreplugin/icore.h>
#include <coreplugin/id.h>
#include <coreplugin/messagemanager.h>
+
#include <projectexplorer/devicesupport/sshdeviceprocesslist.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
+
#include <ssh/sshremoteprocessrunner.h>
+
#include <utils/algorithm.h>
+#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/port.h>
#include <utils/qtcassert.h>
@@ -190,35 +196,42 @@ LinuxDevice::LinuxDevice()
}
}});
+ setOpenTerminal([this](const Utils::Environment &env, const QString &workingDir) {
+ DeviceProcess * const proc = createProcess(nullptr);
+ QObject::connect(proc, &DeviceProcess::finished, [proc] {
+ if (!proc->errorString().isEmpty()) {
+ Core::MessageManager::write(tr("Error running remote shell: %1")
+ .arg(proc->errorString()),
+ Core::MessageManager::ModeSwitch);
+ }
+ proc->deleteLater();
+ });
+ QObject::connect(proc, &DeviceProcess::error, [proc] {
+ Core::MessageManager::write(tr("Error starting remote shell."),
+ Core::MessageManager::ModeSwitch);
+ 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.executable = "/bin/sh";
+
+ proc->setRunInTerminal(true);
+ proc->start(runnable);
+ });
+
if (Utils::HostOsInfo::isAnyUnixHost()) {
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
- DeviceProcess * const proc = device->createProcess(nullptr);
- QObject::connect(proc, &DeviceProcess::finished, [proc] {
- if (!proc->errorString().isEmpty()) {
- Core::MessageManager::write(tr("Error running remote shell: %1")
- .arg(proc->errorString()),
- Core::MessageManager::ModeSwitch);
- }
- proc->deleteLater();
- });
- QObject::connect(proc, &DeviceProcess::error, [proc] {
- Core::MessageManager::write(tr("Error starting remote shell."),
- Core::MessageManager::ModeSwitch);
- proc->deleteLater();
- });
- Runnable runnable;
- runnable.device = device;
- proc->setRunInTerminal(true);
- proc->start(runnable);
+ device->openTerminal(Utils::Environment(), QString());
}});
}
}
-IDevice::Ptr LinuxDevice::clone() const
-{
- return Ptr(new LinuxDevice(*this));
-}
-
DeviceProcess *LinuxDevice::createProcess(QObject *parent) const
{
return new LinuxDeviceProcess(sharedFromThis(), parent);
@@ -284,4 +297,26 @@ bool LinuxDevice::supportsRSync() const
return extraData("RemoteLinux.SupportsRSync").toBool();
}
+namespace Internal {
+
+// Factory
+
+LinuxDeviceFactory::LinuxDeviceFactory()
+ : IDeviceFactory(Constants::GenericLinuxOsType)
+{
+ setDisplayName(tr("Generic Linux Device"));
+ setIcon(QIcon());
+ setCanCreate(true);
+ setConstructionFunction(&LinuxDevice::create);
+}
+
+IDevice::Ptr LinuxDeviceFactory::create() const
+{
+ GenericLinuxDeviceConfigurationWizard wizard(Core::ICore::mainWindow());
+ if (wizard.exec() != QDialog::Accepted)
+ return IDevice::Ptr();
+ return wizard.device();
+}
+
+}
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h
index 6f00a58d14..18faf4ae05 100644
--- a/src/plugins/remotelinux/linuxdevice.h
+++ b/src/plugins/remotelinux/linuxdevice.h
@@ -28,6 +28,7 @@
#include "remotelinux_export.h"
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefactory.h>
#include <QCoreApplication>
@@ -46,7 +47,6 @@ public:
QString displayType() const override;
ProjectExplorer::IDeviceWidget *createWidget() override;
Utils::OsType osType() const override;
- ProjectExplorer::IDevice::Ptr clone() const override;
bool canCreateProcess() const override { return true; }
ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const override;
@@ -66,4 +66,17 @@ protected:
LinuxDevice();
};
+namespace Internal {
+
+class LinuxDeviceFactory : public ProjectExplorer::IDeviceFactory
+{
+ Q_OBJECT
+
+public:
+ LinuxDeviceFactory();
+
+ ProjectExplorer::IDevice::Ptr create() const override;
+};
+
+} // namespace Internal
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/linuxdeviceprocess.cpp b/src/plugins/remotelinux/linuxdeviceprocess.cpp
index 004ca63d2a..ca08b44ec9 100644
--- a/src/plugins/remotelinux/linuxdeviceprocess.cpp
+++ b/src/plugins/remotelinux/linuxdeviceprocess.cpp
@@ -25,18 +25,15 @@
#include "linuxdeviceprocess.h"
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
-#include <utils/qtcprocess.h>
using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux {
-static QString quote(const QString &s) { return Utils::QtcProcess::quoteArgUnix(s); }
-
LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer<const ProjectExplorer::IDevice> &device,
QObject *parent)
: ProjectExplorer::SshDeviceProcess(device, parent), m_processId(0)
@@ -78,41 +75,41 @@ qint64 LinuxDeviceProcess::processId() const
QString LinuxDeviceProcess::fullCommandLine(const Runnable &runnable) const
{
- const Environment env = runnable.environment;
+ CommandLine cmd;
- QString fullCommandLine;
- foreach (const QString &filePath, rcFilesToSource())
- fullCommandLine += QString::fromLatin1("test -f %1 && . %1;").arg(filePath);
- if (!runnable.workingDirectory.isEmpty()) {
- fullCommandLine.append(QLatin1String("cd ")).append(quote(runnable.workingDirectory))
- .append(QLatin1String(" && "));
+ for (const QString &filePath : rcFilesToSource()) {
+ cmd.addArgs({"test", "-f", filePath});
+ cmd.addArgs("&&");
+ cmd.addArgs({".", filePath});
+ cmd.addArgs(";");
}
- QString envString;
- for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
- if (!envString.isEmpty())
- envString += QLatin1Char(' ');
- envString.append(env.key(it)).append(QLatin1String("='")).append(env.value(it))
- .append(QLatin1Char('\''));
+
+ if (!runnable.workingDirectory.isEmpty()) {
+ cmd.addArgs({"cd", runnable.workingDirectory});
+ cmd.addArgs("&&");
}
+
if (!runInTerminal())
- fullCommandLine.append("echo $$ && ");
- if (!envString.isEmpty())
- fullCommandLine.append(envString);
+ cmd.addArgs("echo $$ && ");
+
+ const Environment &env = runnable.environment;
+ for (auto it = env.constBegin(); it != env.constEnd(); ++it)
+ cmd.addArgs(env.key(it) + "='" + env.value(it) + '\'');
+
if (!runInTerminal())
- fullCommandLine.append(" exec ");
- fullCommandLine.append(quote(runnable.executable));
- if (!runnable.commandLineArguments.isEmpty()) {
- fullCommandLine.append(QLatin1Char(' '));
- fullCommandLine.append(runnable.commandLineArguments);
- }
- return fullCommandLine;
+ cmd.addArg("exec");
+
+ cmd.addArg(runnable.executable);
+ cmd.addArgs(runnable.commandLineArguments);
+
+ return cmd.arguments();
}
-QStringList LinuxDeviceProcess::rcFilesToSource() const
+const QStringList LinuxDeviceProcess::rcFilesToSource() const
{
if (!m_rcFilesToSource.isEmpty())
return m_rcFilesToSource;
- return QStringList() << QLatin1String("/etc/profile") << QLatin1String("$HOME/.profile");
+ return {"/etc/profile", "$HOME/.profile"};
}
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/linuxdeviceprocess.h b/src/plugins/remotelinux/linuxdeviceprocess.h
index 4b565029cc..b917222018 100644
--- a/src/plugins/remotelinux/linuxdeviceprocess.h
+++ b/src/plugins/remotelinux/linuxdeviceprocess.h
@@ -49,7 +49,7 @@ private:
QString fullCommandLine(const ProjectExplorer::Runnable &) const override;
qint64 processId() const override;
- QStringList rcFilesToSource() const;
+ const QStringList rcFilesToSource() const;
QStringList m_rcFilesToSource;
QByteArray m_processIdString;
diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp
index a555c22e86..bef26118c3 100644
--- a/src/plugins/remotelinux/linuxdevicetester.cpp
+++ b/src/plugins/remotelinux/linuxdevicetester.cpp
@@ -226,11 +226,12 @@ void GenericLinuxDeviceTester::testRsync()
if (d->rsyncProcess.error() == QProcess::FailedToStart)
handleRsyncFinished();
});
- connect(&d->rsyncProcess, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
- [this] {
+ connect(&d->rsyncProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, [this] {
handleRsyncFinished();
});
- const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection);
+ const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection,
+ RsyncDeployStep::defaultFlags());
const QStringList args = QStringList(cmdLine.options)
<< "-n" << "--exclude=*" << (cmdLine.remoteHostSpec + ":/tmp");
d->rsyncProcess.start("rsync", args);
diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp
new file mode 100644
index 0000000000..c9d3578b79
--- /dev/null
+++ b/src/plugins/remotelinux/makeinstallstep.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** 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 "makeinstallstep.h"
+
+#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/deployconfiguration.h>
+#include <projectexplorer/processparameters.h>
+#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/task.h>
+#include <utils/fileutils.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
+#include <QDirIterator>
+#include <QFileInfo>
+#include <QFormLayout>
+#include <QTemporaryDir>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace RemoteLinux {
+namespace Internal {
+
+const char MakeAspectId[] = "RemoteLinux.MakeInstall.Make";
+const char InstallRootAspectId[] = "RemoteLinux.MakeInstall.InstallRoot";
+const char CleanInstallRootAspectId[] = "RemoteLinux.MakeInstall.CleanInstallRoot";
+const char FullCommandLineAspectId[] = "RemoteLinux.MakeInstall.FullCommandLine";
+
+MakeInstallStep::MakeInstallStep(BuildStepList *parent) : MakeStep(parent, stepId())
+{
+ setDefaultDisplayName(displayName());
+
+ const auto makeAspect = addAspect<ExecutableAspect>();
+ makeAspect->setId(MakeAspectId);
+ makeAspect->setSettingsKey(MakeAspectId);
+ makeAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
+ makeAspect->setLabelText(tr("Command:"));
+ connect(makeAspect, &ExecutableAspect::changed,
+ this, &MakeInstallStep::updateCommandFromAspect);
+
+ const auto installRootAspect = addAspect<BaseStringAspect>();
+ installRootAspect->setId(InstallRootAspectId);
+ installRootAspect->setSettingsKey(InstallRootAspectId);
+ installRootAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
+ installRootAspect->setExpectedKind(PathChooser::Directory);
+ installRootAspect->setLabelText(tr("Install root:"));
+ connect(installRootAspect, &BaseStringAspect::changed,
+ this, &MakeInstallStep::updateArgsFromAspect);
+
+ const auto cleanInstallRootAspect = addAspect<BaseBoolAspect>();
+ cleanInstallRootAspect->setId(CleanInstallRootAspectId);
+ cleanInstallRootAspect->setSettingsKey(CleanInstallRootAspectId);
+ cleanInstallRootAspect->setLabel(tr("Clean install root first"));
+ cleanInstallRootAspect->setValue(false);
+
+ const auto commandLineAspect = addAspect<BaseStringAspect>();
+ commandLineAspect->setId(FullCommandLineAspectId);
+ commandLineAspect->setDisplayStyle(BaseStringAspect::LabelDisplay);
+ commandLineAspect->setLabelText(tr("Full command line:"));
+
+ QTemporaryDir tmpDir;
+ installRootAspect->setFileName(FilePath::fromString(tmpDir.path()));
+ const MakeInstallCommand cmd = target()->makeInstallCommand(tmpDir.path());
+ QTC_ASSERT(!cmd.command.isEmpty(), return);
+ makeAspect->setExecutable(cmd.command);
+}
+
+Core::Id MakeInstallStep::stepId()
+{
+ return "RemoteLinux.MakeInstall";
+}
+
+QString MakeInstallStep::displayName()
+{
+ return tr("Install into temporary host directory");
+}
+
+BuildStepConfigWidget *MakeInstallStep::createConfigWidget()
+{
+ return BuildStep::createConfigWidget();
+}
+
+bool MakeInstallStep::init()
+{
+ if (!MakeStep::init())
+ return false;
+ const QString rootDirPath = installRoot().toString();
+ if (rootDirPath.isEmpty()) {
+ emit addTask(Task(Task::Error, tr("You must provide an install root."), FilePath(), -1,
+ Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return false;
+ }
+ QDir rootDir(rootDirPath);
+ if (cleanInstallRoot() && !rootDir.removeRecursively()) {
+ emit addTask(Task(Task::Error, tr("The install root \"%1\" could not be cleaned.")
+ .arg(installRoot().toUserOutput()),
+ FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return false;
+ }
+ if (!rootDir.exists() && !QDir::root().mkpath(rootDirPath)) {
+ emit addTask(Task(Task::Error, tr("The install root \"%1\" could not be created.")
+ .arg(installRoot().toUserOutput()),
+ FilePath(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return false;
+ }
+ if (this == deployConfiguration()->stepList()->steps().last()) {
+ emit addTask(Task(Task::Warning, tr("The \"make install\" step should probably not be "
+ "last in the list of deploy steps. "
+ "Consider moving it up."), FilePath(), -1,
+ Constants::TASK_CATEGORY_BUILDSYSTEM));
+ }
+ const MakeInstallCommand cmd = target()->makeInstallCommand(installRoot().toString());
+ if (cmd.environment.size() > 0) {
+ Environment env = processParameters()->environment();
+ for (auto it = cmd.environment.constBegin(); it != cmd.environment.constEnd(); ++it)
+ env.set(it.key(), it.value());
+ processParameters()->setEnvironment(env);
+ }
+ m_noInstallTarget = false;
+ const auto buildStep = buildConfiguration()
+ ->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
+ ->firstOfType<AbstractProcessStep>();
+ m_isCmakeProject = buildStep && buildStep->processParameters()->command().toString()
+ .contains("cmake");
+ return true;
+}
+
+void MakeInstallStep::finish(bool success)
+{
+ if (success) {
+ m_deploymentData = DeploymentData();
+ m_deploymentData.setLocalInstallRoot(installRoot());
+ QDirIterator dit(installRoot().toString(), QDir::Files, QDirIterator::Subdirectories);
+ while (dit.hasNext()) {
+ dit.next();
+ const QFileInfo fi = dit.fileInfo();
+ m_deploymentData.addFile(fi.filePath(),
+ fi.dir().path().mid(installRoot().toString().length()));
+ }
+ target()->setDeploymentData(m_deploymentData);
+ } else if (m_noInstallTarget && m_isCmakeProject) {
+ emit addTask(Task(Task::Warning, tr("You need to add an install statement to your "
+ "CMakeLists.txt file for deployment to work."),
+ FilePath(), -1, ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT));
+ }
+ MakeStep::finish(success);
+}
+
+void MakeInstallStep::stdError(const QString &line)
+{
+ // When using Makefiles: "No rule to make target 'install'"
+ // When using ninja: "ninja: error: unknown target 'install'"
+ if (line.contains("target 'install'"))
+ m_noInstallTarget = true;
+ MakeStep::stdError(line);
+}
+
+FilePath MakeInstallStep::installRoot() const
+{
+ return static_cast<BaseStringAspect *>(aspect(InstallRootAspectId))->fileName();
+}
+
+bool MakeInstallStep::cleanInstallRoot() const
+{
+ return static_cast<BaseBoolAspect *>(aspect(CleanInstallRootAspectId))->value();
+}
+
+void MakeInstallStep::updateCommandFromAspect()
+{
+ setMakeCommand(aspect<ExecutableAspect>()->executable());
+ updateFullCommandLine();
+}
+
+void MakeInstallStep::updateArgsFromAspect()
+{
+ setUserArguments(QtcProcess::joinArgs(target()->makeInstallCommand(
+ static_cast<BaseStringAspect *>(aspect(InstallRootAspectId))->fileName().toString())
+ .arguments));
+ updateFullCommandLine();
+}
+
+void MakeInstallStep::updateFullCommandLine()
+{
+ static_cast<BaseStringAspect *>(aspect(FullCommandLineAspectId))->setValue(
+ QDir::toNativeSeparators(
+ QtcProcess::quoteArg(effectiveMakeCommand().toString()))
+ + ' ' + userArguments());
+}
+
+bool MakeInstallStep::fromMap(const QVariantMap &map)
+{
+ if (!MakeStep::fromMap(map))
+ return false;
+ updateCommandFromAspect();
+ updateArgsFromAspect();
+ return true;
+}
+
+} // namespace Internal
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/makeinstallstep.h b/src/plugins/remotelinux/makeinstallstep.h
new file mode 100644
index 0000000000..5620c966b4
--- /dev/null
+++ b/src/plugins/remotelinux/makeinstallstep.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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 <projectexplorer/deploymentdata.h>
+#include <projectexplorer/makestep.h>
+
+namespace Utils { class FilePath; }
+
+namespace RemoteLinux {
+namespace Internal {
+
+class MakeInstallStep : public ProjectExplorer::MakeStep
+{
+ Q_OBJECT
+public:
+ MakeInstallStep(ProjectExplorer::BuildStepList *parent);
+
+ static Core::Id stepId();
+ static QString displayName();
+
+private:
+ bool fromMap(const QVariantMap &map) override;
+ ProjectExplorer::BuildStepConfigWidget * createConfigWidget() override;
+ bool init() override;
+ void finish(bool success) override;
+ void stdError(const QString &line) override;
+
+ Utils::FilePath installRoot() const;
+ bool cleanInstallRoot() const;
+
+ void updateCommandFromAspect();
+ void updateArgsFromAspect();
+ void updateFullCommandLine();
+
+ ProjectExplorer::DeploymentData m_deploymentData;
+ bool m_noInstallTarget = false;
+ bool m_isCmakeProject = false;
+};
+
+} // namespace Internal
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro
index 027cc59b22..5314e25d64 100644
--- a/src/plugins/remotelinux/remotelinux.pro
+++ b/src/plugins/remotelinux/remotelinux.pro
@@ -4,7 +4,7 @@ include(../../qtcreatorplugin.pri)
HEADERS += \
embeddedlinuxqtversion.h \
- embeddedlinuxqtversionfactory.h \
+ makeinstallstep.h \
remotelinuxenvironmentaspect.h \
remotelinuxenvironmentaspectwidget.h \
remotelinuxplugin.h \
@@ -13,7 +13,6 @@ HEADERS += \
remotelinuxrunconfiguration.h \
publickeydeploymentdialog.h \
genericlinuxdeviceconfigurationwizard.h \
- genericlinuxdeviceconfigurationfactory.h \
remotelinuxdebugsupport.h \
genericlinuxdeviceconfigurationwizardpages.h \
abstractremotelinuxdeploystep.h \
@@ -49,7 +48,7 @@ HEADERS += \
SOURCES += \
embeddedlinuxqtversion.cpp \
- embeddedlinuxqtversionfactory.cpp \
+ makeinstallstep.cpp \
remotelinuxenvironmentaspect.cpp \
remotelinuxenvironmentaspectwidget.cpp \
remotelinuxplugin.cpp \
@@ -57,7 +56,6 @@ SOURCES += \
remotelinuxrunconfiguration.cpp \
publickeydeploymentdialog.cpp \
genericlinuxdeviceconfigurationwizard.cpp \
- genericlinuxdeviceconfigurationfactory.cpp \
remotelinuxdebugsupport.cpp \
genericlinuxdeviceconfigurationwizardpages.cpp \
abstractremotelinuxdeploystep.cpp \
@@ -92,8 +90,7 @@ SOURCES += \
FORMS += \
genericlinuxdeviceconfigurationwizardsetuppage.ui \
- genericlinuxdeviceconfigurationwidget.ui \
- remotelinuxcheckforfreediskspacestepwidget.ui
+ genericlinuxdeviceconfigurationwidget.ui
RESOURCES += remotelinux.qrc
diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs
index 1f553d662b..e2a9551393 100644
--- a/src/plugins/remotelinux/remotelinux.qbs
+++ b/src/plugins/remotelinux/remotelinux.qbs
@@ -29,14 +29,10 @@ Project {
"deploymenttimeinfo.h",
"embeddedlinuxqtversion.cpp",
"embeddedlinuxqtversion.h",
- "embeddedlinuxqtversionfactory.cpp",
- "embeddedlinuxqtversionfactory.h",
"genericdirectuploadservice.cpp",
"genericdirectuploadservice.h",
"genericdirectuploadstep.cpp",
"genericdirectuploadstep.h",
- "genericlinuxdeviceconfigurationfactory.cpp",
- "genericlinuxdeviceconfigurationfactory.h",
"genericlinuxdeviceconfigurationwidget.cpp",
"genericlinuxdeviceconfigurationwidget.h",
"genericlinuxdeviceconfigurationwidget.ui",
@@ -51,6 +47,8 @@ Project {
"linuxdeviceprocess.h",
"linuxdevicetester.cpp",
"linuxdevicetester.h",
+ "makeinstallstep.cpp",
+ "makeinstallstep.h",
"packageuploader.cpp",
"packageuploader.h",
"publickeydeploymentdialog.cpp",
@@ -62,7 +60,6 @@ Project {
"remotelinuxcheckforfreediskspaceservice.h",
"remotelinuxcheckforfreediskspacestep.cpp",
"remotelinuxcheckforfreediskspacestep.h",
- "remotelinuxcheckforfreediskspacestepwidget.ui",
"remotelinuxcustomcommanddeploymentstep.cpp",
"remotelinuxcustomcommanddeploymentstep.h",
"remotelinuxcustomcommanddeployservice.cpp",
@@ -105,7 +102,7 @@ Project {
"typespecificdeviceconfigurationlistmodel.h",
"uploadandinstalltarpackagestep.cpp",
"uploadandinstalltarpackagestep.h",
- "images/embeddedtarget.png"
+ "images/embeddedtarget.png",
]
Export {
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
index de2d43906c..e1d2447c51 100644
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
+++ b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp
@@ -102,18 +102,15 @@ void RemoteLinuxCheckForFreeDiskSpaceService::handleProcessFinished()
stopDeployment();
}
-bool RemoteLinuxCheckForFreeDiskSpaceService::isDeploymentPossible(QString *whyNot) const
+CheckResult RemoteLinuxCheckForFreeDiskSpaceService::isDeploymentPossible() const
{
- if (!AbstractRemoteLinuxDeployService::isDeploymentPossible(whyNot))
- return false;
if (!d->pathToCheck.startsWith(QLatin1Char('/'))) {
- if (whyNot) {
- *whyNot = tr("Cannot check for free disk space: \"%1\" is not an absolute path.")
- .arg(d->pathToCheck);
- }
- return false;
+ return CheckResult::failure(
+ tr("Cannot check for free disk space: \"%1\" is not an absolute path.")
+ .arg(d->pathToCheck));
}
- return true;
+
+ return AbstractRemoteLinuxDeployService::isDeploymentPossible();
}
void RemoteLinuxCheckForFreeDiskSpaceService::doDeploy()
@@ -125,7 +122,7 @@ void RemoteLinuxCheckForFreeDiskSpaceService::doDeploy()
this, &RemoteLinuxCheckForFreeDiskSpaceService::handleStdErr);
const QString command = QString::fromLatin1("df -k %1 |tail -n 1 |sed 's/ */ /g' "
"|cut -d ' ' -f 4").arg(d->pathToCheck);
- d->processRunner->run(command.toUtf8(), deviceConfiguration()->sshParameters());
+ d->processRunner->run(command, deviceConfiguration()->sshParameters());
}
void RemoteLinuxCheckForFreeDiskSpaceService::stopDeployment()
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h
index 3d6e76f5fb..2819eb00c7 100644
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h
+++ b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.h
@@ -49,7 +49,7 @@ private:
void doDeviceSetup() override { handleDeviceSetupDone(true); }
void stopDeviceSetup() override { handleDeviceSetupDone(false); }
- bool isDeploymentPossible(QString *whyNot) const override;
+ CheckResult isDeploymentPossible() const override;
void doDeploy() override;
void stopDeployment() override;
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp b/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp
index 457e64292f..1070083eeb 100644
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp
+++ b/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.cpp
@@ -24,11 +24,10 @@
****************************************************************************/
#include "remotelinuxcheckforfreediskspacestep.h"
-#include "ui_remotelinuxcheckforfreediskspacestepwidget.h"
#include "remotelinuxcheckforfreediskspaceservice.h"
-#include <QString>
+#include <projectexplorer/projectconfigurationaspects.h>
#include <limits>
@@ -36,69 +35,44 @@ using namespace ProjectExplorer;
namespace RemoteLinux {
namespace Internal {
-namespace {
-class RemoteLinuxCheckForFreeDiskSpaceStepWidget : public BuildStepConfigWidget
-{
- Q_OBJECT
-
-public:
- explicit RemoteLinuxCheckForFreeDiskSpaceStepWidget(RemoteLinuxCheckForFreeDiskSpaceStep &step)
- : BuildStepConfigWidget(&step), m_step(step)
- {
- const QString displayName = QLatin1String("<b>")
- + RemoteLinuxCheckForFreeDiskSpaceStep::displayName() + QLatin1String("</b>");
- setDisplayName(displayName);
- setSummaryText(displayName);
-
- m_ui.setupUi(this);
- m_ui.requiredSpaceSpinBox->setSuffix(tr("MB"));
- m_ui.requiredSpaceSpinBox->setMinimum(1);
- m_ui.requiredSpaceSpinBox->setMaximum(std::numeric_limits<int>::max());
-
- m_ui.pathLineEdit->setText(m_step.pathToCheck());
- m_ui.requiredSpaceSpinBox->setValue(m_step.requiredSpaceInBytes()/multiplier);
-
- connect(m_ui.pathLineEdit, &QLineEdit::textChanged,
- this, &RemoteLinuxCheckForFreeDiskSpaceStepWidget::handlePathChanged);
- connect(m_ui.requiredSpaceSpinBox,
- static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
- this, &RemoteLinuxCheckForFreeDiskSpaceStepWidget::handleRequiredSpaceChanged);
- }
-
-private:
- void handlePathChanged() { m_step.setPathToCheck(m_ui.pathLineEdit->text().trimmed()); }
- void handleRequiredSpaceChanged() {
- m_step.setRequiredSpaceInBytes(quint64(m_ui.requiredSpaceSpinBox->value())*multiplier);
- }
-
- static const int multiplier = 1024*1024;
-
- Ui::RemoteLinuxCheckForFreeDiskSpaceStepWidget m_ui;
- RemoteLinuxCheckForFreeDiskSpaceStep &m_step;
-};
-
-} // anonymous namespace
+const char PathToCheckAspectId[] = "PathToCheckAspectId";
const char PathToCheckKey[] = "RemoteLinux.CheckForFreeDiskSpaceStep.PathToCheck";
+
+const char RequiredSpaceAspectId[] = "RequiredSpaceAspectId";
const char RequiredSpaceKey[] = "RemoteLinux.CheckForFreeDiskSpaceStep.RequiredSpace";
class RemoteLinuxCheckForFreeDiskSpaceStepPrivate
{
public:
RemoteLinuxCheckForFreeDiskSpaceService deployService;
- QString pathToCheck;
- quint64 requiredSpaceInBytes;
};
+
} // namespace Internal
+using namespace Internal;
RemoteLinuxCheckForFreeDiskSpaceStep::RemoteLinuxCheckForFreeDiskSpaceStep(BuildStepList *bsl)
: AbstractRemoteLinuxDeployStep(bsl, stepId())
{
d = new Internal::RemoteLinuxCheckForFreeDiskSpaceStepPrivate;
setDefaultDisplayName(displayName());
- setPathToCheck("/");
- setRequiredSpaceInBytes(5*1024*1024);
+
+ auto pathToCheckAspect = addAspect<BaseStringAspect>();
+ pathToCheckAspect->setId(PathToCheckAspectId);
+ pathToCheckAspect->setSettingsKey(PathToCheckKey);
+ pathToCheckAspect->setDisplayStyle(BaseStringAspect::LineEditDisplay);
+ pathToCheckAspect->setValue("/");
+ pathToCheckAspect->setLabelText(tr("Remote path to check for free space:"));
+
+ auto requiredSpaceAspect = addAspect<BaseIntegerAspect>();
+ requiredSpaceAspect->setId(RequiredSpaceAspectId);
+ requiredSpaceAspect->setSettingsKey(RequiredSpaceKey);
+ 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());
}
RemoteLinuxCheckForFreeDiskSpaceStep::~RemoteLinuxCheckForFreeDiskSpaceStep()
@@ -106,54 +80,13 @@ RemoteLinuxCheckForFreeDiskSpaceStep::~RemoteLinuxCheckForFreeDiskSpaceStep()
delete d;
}
-void RemoteLinuxCheckForFreeDiskSpaceStep::setPathToCheck(const QString &path)
-{
- d->pathToCheck = path;
-}
-
-QString RemoteLinuxCheckForFreeDiskSpaceStep::pathToCheck() const
-{
- return d->pathToCheck;
-}
-
-void RemoteLinuxCheckForFreeDiskSpaceStep::setRequiredSpaceInBytes(quint64 space)
-{
- d->requiredSpaceInBytes = space;
-}
-
-quint64 RemoteLinuxCheckForFreeDiskSpaceStep::requiredSpaceInBytes() const
-{
- return d->requiredSpaceInBytes;
-}
-
-bool RemoteLinuxCheckForFreeDiskSpaceStep::fromMap(const QVariantMap &map)
-{
- if (!AbstractRemoteLinuxDeployStep::fromMap(map))
- return false;
- d->pathToCheck = map.value(QLatin1String(Internal::PathToCheckKey)).toString();
- d->requiredSpaceInBytes = map.value(QLatin1String(Internal::RequiredSpaceKey)).toULongLong();
- return true;
-}
-
-QVariantMap RemoteLinuxCheckForFreeDiskSpaceStep::toMap() const
+CheckResult RemoteLinuxCheckForFreeDiskSpaceStep::initInternal()
{
- QVariantMap map = AbstractRemoteLinuxDeployStep::toMap();
- map.insert(QLatin1String(Internal::PathToCheckKey), d->pathToCheck);
- map.insert(QLatin1String(Internal::RequiredSpaceKey), d->requiredSpaceInBytes);
- return map;
-}
-
-BuildStepConfigWidget *RemoteLinuxCheckForFreeDiskSpaceStep::createConfigWidget()
-{
- return new Internal::RemoteLinuxCheckForFreeDiskSpaceStepWidget(*this);
-}
-
-bool RemoteLinuxCheckForFreeDiskSpaceStep::initInternal(QString *error)
-{
- Q_UNUSED(error);
- d->deployService.setPathToCheck(d->pathToCheck);
- d->deployService.setRequiredSpaceInBytes(d->requiredSpaceInBytes);
- return true;
+ d->deployService.setPathToCheck(
+ static_cast<BaseStringAspect *>(aspect(PathToCheckAspectId))->value());
+ d->deployService.setRequiredSpaceInBytes(
+ static_cast<BaseIntegerAspect *>(aspect(RequiredSpaceAspectId))->value());
+ return CheckResult::success();
}
AbstractRemoteLinuxDeployService *RemoteLinuxCheckForFreeDiskSpaceStep::deployService() const
@@ -172,5 +105,3 @@ QString RemoteLinuxCheckForFreeDiskSpaceStep::displayName()
}
} // namespace RemoteLinux
-
-#include "remotelinuxcheckforfreediskspacestep.moc"
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h b/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h
index f102c93c62..afd5887f33 100644
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h
+++ b/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestep.h
@@ -37,21 +37,11 @@ public:
explicit RemoteLinuxCheckForFreeDiskSpaceStep(ProjectExplorer::BuildStepList *bsl);
~RemoteLinuxCheckForFreeDiskSpaceStep() override;
- void setPathToCheck(const QString &path);
- QString pathToCheck() const;
-
- void setRequiredSpaceInBytes(quint64 space);
- quint64 requiredSpaceInBytes() const;
-
static Core::Id stepId();
static QString displayName();
protected:
- bool fromMap(const QVariantMap &map) override;
- QVariantMap toMap() const override;
- ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
-
- bool initInternal(QString *error) override;
+ CheckResult initInternal() override;
AbstractRemoteLinuxDeployService *deployService() const override;
private:
diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestepwidget.ui b/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestepwidget.ui
deleted file mode 100644
index b310833f6c..0000000000
--- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspacestepwidget.ui
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>RemoteLinuxCheckForFreeDiskSpaceStepWidget</class>
- <widget class="QWidget" name="RemoteLinuxCheckForFreeDiskSpaceStepWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>420</width>
- <height>74</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string/>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="pathLabel">
- <property name="text">
- <string>Remote path to check for free space:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="pathLineEdit"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="requiredSpaceLabel">
- <property name="text">
- <string>Required disk space:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="requiredSpaceSpinBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="suffix">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp b/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp
index de2dc30da4..87c82e52f8 100644
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp
+++ b/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.cpp
@@ -58,10 +58,10 @@ RemoteLinuxCustomCommandDeploymentStep::~RemoteLinuxCustomCommandDeploymentStep(
delete d;
}
-bool RemoteLinuxCustomCommandDeploymentStep::initInternal(QString *error)
+CheckResult RemoteLinuxCustomCommandDeploymentStep::initInternal()
{
d->service.setCommandLine(d->commandLineAspect->value().trimmed());
- return d->service.isDeploymentPossible(error);
+ return d->service.isDeploymentPossible();
}
AbstractRemoteLinuxDeployService *RemoteLinuxCustomCommandDeploymentStep::deployService() const
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h b/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h
index a8f036f8da..325ceb0ebd 100644
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h
+++ b/src/plugins/remotelinux/remotelinuxcustomcommanddeploymentstep.h
@@ -42,7 +42,7 @@ public:
static QString displayName();
private:
- bool initInternal(QString *error) override;
+ CheckResult initInternal() override;
AbstractRemoteLinuxDeployService *deployService() const override;
Internal::RemoteLinuxCustomCommandDeploymentStepPrivate *d;
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
index ffa1dfe6af..471ace1a0e 100644
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
+++ b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
@@ -66,19 +66,14 @@ void RemoteLinuxCustomCommandDeployService::setCommandLine(const QString &comman
d->commandLine = commandLine;
}
-bool RemoteLinuxCustomCommandDeployService::isDeploymentPossible(QString *whyNot) const
+CheckResult RemoteLinuxCustomCommandDeployService::isDeploymentPossible() const
{
- QTC_ASSERT(d->state == Inactive, return false);
-
- if (!AbstractRemoteLinuxDeployService::isDeploymentPossible(whyNot))
- return false;
- if (d->commandLine.isEmpty()) {
- if (whyNot)
- *whyNot = tr("No command line given.");
- return false;
- }
+ QTC_ASSERT(d->state == Inactive, return CheckResult::failure());
+
+ if (d->commandLine.isEmpty())
+ return CheckResult::failure(tr("No command line given."));
- return true;
+ return AbstractRemoteLinuxDeployService::isDeploymentPossible();
}
void RemoteLinuxCustomCommandDeployService::doDeploy()
@@ -96,7 +91,7 @@ void RemoteLinuxCustomCommandDeployService::doDeploy()
emit progressMessage(tr("Starting remote command \"%1\"...").arg(d->commandLine));
d->state = Running;
- d->runner->run(d->commandLine.toUtf8(), deviceConfiguration()->sshParameters());
+ d->runner->run(d->commandLine, deviceConfiguration()->sshParameters());
}
void RemoteLinuxCustomCommandDeployService::stopDeployment()
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
index 33b0e67b1d..cc2f7fb129 100644
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
+++ b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.h
@@ -41,7 +41,7 @@ public:
void setCommandLine(const QString &commandLine);
bool isDeploymentNecessary() const override { return true; }
- bool isDeploymentPossible(QString *whyNot = nullptr) const override;
+ CheckResult isDeploymentPossible() const override;
protected:
void doDeviceSetup() override { handleDeviceSetupDone(true); }
diff --git a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
index d72db3c2a8..a375716aab 100644
--- a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
@@ -30,6 +30,7 @@
#include "remotelinuxx11forwardingaspect.h"
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtoutputformatter.h>
diff --git a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
index eebf891e91..5143efe7d9 100644
--- a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
+++ b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
@@ -34,7 +34,7 @@ namespace RemoteLinux {
namespace Internal {
LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl)
- : DebuggerRunTool(runControl, nullptr, false)
+ : DebuggerRunTool(runControl, DebuggerRunTool::DoNotAllowTerminal)
{
setId("LinuxDeviceDebugSupport");
diff --git a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
index 11723a5a25..88cd76f66d 100644
--- a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
@@ -27,6 +27,7 @@
#include "genericdirectuploadstep.h"
#include "linuxdevice.h"
+#include "makeinstallstep.h"
#include "remotelinuxcheckforfreediskspacestep.h"
#include "remotelinuxkillappstep.h"
#include "remotelinux_constants.h"
@@ -60,14 +61,19 @@ RemoteLinuxDeployConfigurationFactory::RemoteLinuxDeployConfigurationFactory()
"Deploy to Remote Linux Host"));
setUseDeploymentDataView();
+ addInitialStep(MakeInstallStep::stepId(), [](Target *target) {
+ const Project * const prj = target->project();
+ return prj->deploymentKnowledge() == DeploymentKnowledge::Bad
+ && prj->hasMakeInstallEquivalent();
+ });
addInitialStep(RemoteLinuxCheckForFreeDiskSpaceStep::stepId());
addInitialStep(RemoteLinuxKillAppStep::stepId());
addInitialStep(RsyncDeployStep::stepId(), [](Target *target) {
- auto device = DeviceKitInformation::device(target->kit()).staticCast<const LinuxDevice>();
+ auto device = DeviceKitAspect::device(target->kit()).staticCast<const LinuxDevice>();
return device && device->supportsRSync();
});
addInitialStep(GenericDirectUploadStep::stepId(), [](Target *target) {
- auto device = DeviceKitInformation::device(target->kit()).staticCast<const LinuxDevice>();
+ auto device = DeviceKitAspect::device(target->kit()).staticCast<const LinuxDevice>();
return device && !device->supportsRSync();
});
}
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp b/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp
index cfa23b3219..36d2d03e2d 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp
+++ b/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp
@@ -41,41 +41,21 @@ static bool displayAlreadySet(const QList<Utils::EnvironmentItem> &changes)
});
}
-enum BaseEnvironmentBase {
- CleanBaseEnvironment = 0,
- RemoteBaseEnvironment = 1
-};
-
-
RemoteLinuxEnvironmentAspect::RemoteLinuxEnvironmentAspect(ProjectExplorer::Target *target)
{
- addSupportedBaseEnvironment(CleanBaseEnvironment, tr("Clean Environment"));
- addPreferredBaseEnvironment(RemoteBaseEnvironment, tr("System Environment"));
+ addSupportedBaseEnvironment(tr("Clean Environment"), {});
+ addPreferredBaseEnvironment(tr("System Environment"), [this] { return m_remoteEnvironment; });
setConfigWidgetCreator([this, target] {
return new RemoteLinuxEnvironmentAspectWidget(this, target);
});
}
-Utils::Environment RemoteLinuxEnvironmentAspect::baseEnvironment() const
-{
- Utils::Environment env;
- if (baseEnvironmentBase() == static_cast<int>(RemoteBaseEnvironment))
- env = m_remoteEnvironment;
- return env;
-}
-
-Utils::Environment RemoteLinuxEnvironmentAspect::remoteEnvironment() const
-{
- return m_remoteEnvironment;
-}
-
void RemoteLinuxEnvironmentAspect::setRemoteEnvironment(const Utils::Environment &env)
{
if (env != m_remoteEnvironment) {
m_remoteEnvironment = env;
- if (baseEnvironmentBase() == static_cast<int>(RemoteBaseEnvironment))
- emit environmentChanged();
+ emit environmentChanged();
}
}
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentaspect.h b/src/plugins/remotelinux/remotelinuxenvironmentaspect.h
index 0ac83cd428..a6a2135970 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentaspect.h
+++ b/src/plugins/remotelinux/remotelinuxenvironmentaspect.h
@@ -38,9 +38,6 @@ class REMOTELINUX_EXPORT RemoteLinuxEnvironmentAspect : public ProjectExplorer::
public:
RemoteLinuxEnvironmentAspect(ProjectExplorer::Target *target);
- Utils::Environment baseEnvironment() const override;
-
- Utils::Environment remoteEnvironment() const;
void setRemoteEnvironment(const Utils::Environment &env);
QString userEnvironmentChangesAsString() const;
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp b/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp
index 4f06d741e7..0d94cf3ffa 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp
+++ b/src/plugins/remotelinux/remotelinuxenvironmentaspectwidget.cpp
@@ -25,11 +25,15 @@
#include "remotelinuxenvironmentaspectwidget.h"
+#include "linuxdevice.h"
#include "remotelinuxrunconfiguration.h"
#include "remotelinuxenvironmentreader.h"
-#include <projectexplorer/target.h>
+#include <coreplugin/icore.h>
+#include <projectexplorer/environmentwidget.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/target.h>
+#include <utils/qtcassert.h>
#include <QCoreApplication>
#include <QMessageBox>
@@ -50,7 +54,7 @@ RemoteLinuxEnvironmentAspectWidget::RemoteLinuxEnvironmentAspectWidget
(RemoteLinuxEnvironmentAspect *aspect, Target *target) :
EnvironmentAspectWidget(aspect, new QPushButton)
{
- IDevice::ConstPtr device = DeviceKitInformation::device(target->kit());
+ IDevice::ConstPtr device = DeviceKitAspect::device(target->kit());
deviceEnvReader = new RemoteLinuxEnvironmentReader(device, this);
connect(target, &ProjectExplorer::Target::kitChanged,
@@ -63,6 +67,20 @@ RemoteLinuxEnvironmentAspectWidget::RemoteLinuxEnvironmentAspectWidget
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentFinished);
connect(deviceEnvReader, &RemoteLinuxEnvironmentReader::error,
this, &RemoteLinuxEnvironmentAspectWidget::fetchEnvironmentError);
+
+ const EnvironmentWidget::OpenTerminalFunc openTerminalFunc
+ = [target](const Utils::Environment &env) {
+ IDevice::ConstPtr device = DeviceKitAspect::device(target->kit());
+ if (!device) {
+ QMessageBox::critical(Core::ICore::mainWindow(), tr("Cannot open terminal"),
+ tr("Cannot open remote terminal: Current kit has no device."));
+ return;
+ }
+ const auto linuxDevice = device.dynamicCast<const LinuxDevice>();
+ QTC_ASSERT(linuxDevice, return);
+ linuxDevice->openTerminal(env, QString());
+ };
+ envWidget()->setOpenTerminalFunc(openTerminalFunc);
}
RemoteLinuxEnvironmentAspect *RemoteLinuxEnvironmentAspectWidget::aspect() const
diff --git a/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp b/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp
index 0c93be020a..33543f6ee1 100644
--- a/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp
+++ b/src/plugins/remotelinux/remotelinuxenvironmentreader.cpp
@@ -27,7 +27,7 @@
#include <projectexplorer/devicesupport/deviceprocess.h>
#include <projectexplorer/devicesupport/idevice.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
using namespace ProjectExplorer;
diff --git a/src/plugins/remotelinux/remotelinuxkillappstep.cpp b/src/plugins/remotelinux/remotelinuxkillappstep.cpp
index c0c1298ad8..f6dd121e7c 100644
--- a/src/plugins/remotelinux/remotelinuxkillappstep.cpp
+++ b/src/plugins/remotelinux/remotelinuxkillappstep.cpp
@@ -27,7 +27,7 @@
#include "remotelinuxkillappservice.h"
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
@@ -44,15 +44,14 @@ RemoteLinuxKillAppStep::RemoteLinuxKillAppStep(BuildStepList *bsl, Core::Id id)
setWidgetExpandedByDefault(false);
}
-bool RemoteLinuxKillAppStep::initInternal(QString *error)
+CheckResult RemoteLinuxKillAppStep::initInternal()
{
- Q_UNUSED(error);
Target * const theTarget = target();
- QTC_ASSERT(theTarget, return false);
+ QTC_ASSERT(theTarget, return CheckResult::failure());
RunConfiguration * const rc = theTarget->activeRunConfiguration();
const QString remoteExe = rc ? rc->runnable().executable : QString();
m_service->setRemoteExecutable(remoteExe);
- return true;
+ return CheckResult::success();
}
AbstractRemoteLinuxDeployService *RemoteLinuxKillAppStep::deployService() const
diff --git a/src/plugins/remotelinux/remotelinuxkillappstep.h b/src/plugins/remotelinux/remotelinuxkillappstep.h
index e1f9b3f47e..183db57b2a 100644
--- a/src/plugins/remotelinux/remotelinuxkillappstep.h
+++ b/src/plugins/remotelinux/remotelinuxkillappstep.h
@@ -41,7 +41,7 @@ public:
static QString displayName();
private:
- bool initInternal(QString *error) override;
+ CheckResult initInternal() override;
AbstractRemoteLinuxDeployService *deployService() const override;
RemoteLinuxKillAppService * const m_service;
diff --git a/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp b/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
index 4d3439931b..bf27f6d03e 100644
--- a/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
+++ b/src/plugins/remotelinux/remotelinuxpackageinstaller.cpp
@@ -76,7 +76,7 @@ void AbstractRemoteLinuxPackageInstaller::installPackage(const IDevice::ConstPtr
QString cmdLine = installCommandLine(packageFilePath);
if (removePackageFile)
cmdLine += QLatin1String(" && (rm ") + packageFilePath + QLatin1String(" || :)");
- d->installer->run(cmdLine.toUtf8(), deviceConfig->sshParameters());
+ d->installer->run(cmdLine, deviceConfig->sshParameters());
d->isRunning = true;
}
@@ -86,7 +86,7 @@ void AbstractRemoteLinuxPackageInstaller::cancelInstallation()
if (!d->killProcess)
d->killProcess = new SshRemoteProcessRunner(this);
- d->killProcess->run(cancelInstallationCommandLine().toUtf8(), d->deviceConfig->sshParameters());
+ d->killProcess->run(cancelInstallationCommandLine(), d->deviceConfig->sshParameters());
setFinished();
}
diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp
index 25b8eb5e89..1f25666cbf 100644
--- a/src/plugins/remotelinux/remotelinuxplugin.cpp
+++ b/src/plugins/remotelinux/remotelinuxplugin.cpp
@@ -25,8 +25,8 @@
#include "remotelinuxplugin.h"
-#include "embeddedlinuxqtversionfactory.h"
-#include "genericlinuxdeviceconfigurationfactory.h"
+#include "embeddedlinuxqtversion.h"
+#include "linuxdevice.h"
#include "remotelinux_constants.h"
#include "remotelinuxqmltoolingsupport.h"
#include "remotelinuxcustomrunconfiguration.h"
@@ -35,6 +35,7 @@
#include "remotelinuxrunconfiguration.h"
#include "genericdirectuploadstep.h"
+#include "makeinstallstep.h"
#include "remotelinuxcheckforfreediskspacestep.h"
#include "remotelinuxdeployconfiguration.h"
#include "remotelinuxcustomcommanddeploymentstep.h"
@@ -67,7 +68,7 @@ public:
class RemoteLinuxPluginPrivate
{
public:
- GenericLinuxDeviceConfigurationFactory deviceConfigurationFactory;
+ LinuxDeviceFactory linuxDeviceFactory;
RemoteLinuxRunConfigurationFactory runConfigurationFactory;
RemoteLinuxCustomRunConfigurationFactory customRunConfigurationFactory;
RemoteLinuxDeployConfigurationFactory deployConfigurationFactory;
@@ -80,6 +81,7 @@ public:
GenericDeployStepFactory<RemoteLinuxCheckForFreeDiskSpaceStep>
checkForFreeDiskSpaceStepFactory;
GenericDeployStepFactory<RemoteLinuxKillAppStep> remoteLinuxKillAppStepFactory;
+ GenericDeployStepFactory<MakeInstallStep> makeInstallStepFactory;
EmbeddedLinuxQtVersionFactory embeddedLinuxQtVersionFactory;
};
@@ -103,7 +105,7 @@ bool RemoteLinuxPlugin::initialize(const QStringList &arguments, QString *errorM
dd = new RemoteLinuxPluginPrivate;
auto constraint = [](RunConfiguration *runConfig) {
- const Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(
+ const Core::Id devType = ProjectExplorer::DeviceTypeKitAspect::deviceTypeId(
runConfig->target()->kit());
if (devType != Constants::GenericLinuxOsType)
diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
index b39ebc7846..f636799af8 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
@@ -34,6 +34,7 @@
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtoutputformatter.h>
@@ -95,7 +96,7 @@ void RemoteLinuxRunConfiguration::updateTargetInformation()
QString localExecutable = bti.targetFilePath.toString();
DeployableFile depFile = target()->deploymentData().deployableForLocalFile(localExecutable);
- aspect<ExecutableAspect>()->setExecutable(FileName::fromString(depFile.remoteFilePath()));
+ aspect<ExecutableAspect>()->setExecutable(FilePath::fromString(depFile.remoteFilePath()));
aspect<SymbolFileAspect>()->setValue(localExecutable);
emit enabledChanged();
diff --git a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
index 64e1f5b2d3..5a5def6bb3 100644
--- a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
+++ b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp
@@ -60,7 +60,7 @@ void RemoteLinuxSignalOperation::run(const QString &command)
this, &RemoteLinuxSignalOperation::runnerProcessFinished);
connect(m_runner, &QSsh::SshRemoteProcessRunner::connectionError,
this, &RemoteLinuxSignalOperation::runnerConnectionError);
- m_runner->run(command.toLatin1(), m_sshParameters);
+ m_runner->run(command, m_sshParameters);
}
void RemoteLinuxSignalOperation::finish()
diff --git a/src/plugins/remotelinux/rsyncdeploystep.cpp b/src/plugins/remotelinux/rsyncdeploystep.cpp
index 8c04860c25..25dc0b28d5 100644
--- a/src/plugins/remotelinux/rsyncdeploystep.cpp
+++ b/src/plugins/remotelinux/rsyncdeploystep.cpp
@@ -51,6 +51,7 @@ public:
void setDeployableFiles(const QList<DeployableFile> &files) { m_deployableFiles = files; }
void setIgnoreMissingFiles(bool ignore) { m_ignoreMissingFiles = ignore; }
+ void setFlags(const QString &flags) { m_flags = flags; }
private:
bool isDeploymentNecessary() const override;
@@ -69,6 +70,7 @@ private:
mutable QList<DeployableFile> m_deployableFiles;
bool m_ignoreMissingFiles = false;
+ QString m_flags;
SshProcess m_rsync;
SshRemoteProcessPtr m_mkdir;
};
@@ -101,7 +103,7 @@ void RsyncDeployService::createRemoteDirectories()
remoteDirs.sort();
remoteDirs.removeDuplicates();
m_mkdir = connection()->createRemoteProcess("mkdir -p " + QtcProcess::Arguments
- ::createUnixArgs(remoteDirs).toString().toUtf8());
+ ::createUnixArgs(remoteDirs).toString());
connect(m_mkdir.get(), &SshRemoteProcess::done, this, [this](const QString &error) {
QString userError;
if (!error.isEmpty())
@@ -132,7 +134,7 @@ void RsyncDeployService::deployFiles()
setFinished();
}
});
- connect(&m_rsync, static_cast<void (QProcess::*)(int)>(&QProcess::finished), this, [this] {
+ connect(&m_rsync, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this] {
if (m_rsync.exitStatus() == QProcess::CrashExit) {
emit errorMessage(tr("rsync crashed."));
setFinished();
@@ -155,7 +157,7 @@ void RsyncDeployService::deployNextFile()
return;
}
const DeployableFile file = m_deployableFiles.takeFirst();
- const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*connection());
+ const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*connection(), m_flags);
const QStringList args = QStringList(cmdLine.options)
<< file.localFilePath().toString()
<< (cmdLine.remoteHostSpec + ':' + file.remoteFilePath());
@@ -180,11 +182,18 @@ class RsyncDeployStep::RsyncDeployStepPrivate
public:
Internal::RsyncDeployService deployService;
BaseBoolAspect *ignoreMissingFilesAspect;
+ BaseStringAspect *flagsAspect;
};
RsyncDeployStep::RsyncDeployStep(BuildStepList *bsl)
: AbstractRemoteLinuxDeployStep(bsl, stepId()), d(new RsyncDeployStepPrivate)
{
+ d->flagsAspect = addAspect<BaseStringAspect>();
+ d->flagsAspect->setDisplayStyle(BaseStringAspect::LineEditDisplay);
+ d->flagsAspect->setSettingsKey("RemoteLinux.RsyncDeployStep.Flags");
+ d->flagsAspect->setLabelText(tr("Flags:"));
+ d->flagsAspect->setValue(defaultFlags());
+
d->ignoreMissingFilesAspect = addAspect<BaseBoolAspect>();
d->ignoreMissingFilesAspect
->setSettingsKey("RemoteLinux.RsyncDeployStep.IgnoreMissingFiles");
@@ -199,11 +208,11 @@ RsyncDeployStep::~RsyncDeployStep()
delete d;
}
-bool RsyncDeployStep::initInternal(QString *error)
+CheckResult RsyncDeployStep::initInternal()
{
- d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
d->deployService.setIgnoreMissingFiles(d->ignoreMissingFilesAspect->value());
- return d->deployService.isDeploymentPossible(error);
+ d->deployService.setFlags(d->flagsAspect->value());
+ return d->deployService.isDeploymentPossible();
}
AbstractRemoteLinuxDeployService *RsyncDeployStep::deployService() const
@@ -211,6 +220,12 @@ AbstractRemoteLinuxDeployService *RsyncDeployStep::deployService() const
return &d->deployService;
}
+void RsyncDeployStep::doRun()
+{
+ d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
+ AbstractRemoteLinuxDeployStep::doRun();
+}
+
Core::Id RsyncDeployStep::stepId()
{
return "RemoteLinux.RsyncDeployStep";
@@ -221,13 +236,19 @@ QString RsyncDeployStep::displayName()
return tr("Deploy files via rsync");
}
-RsyncCommandLine RsyncDeployStep::rsyncCommand(const SshConnection &sshConnection)
+QString RsyncDeployStep::defaultFlags()
+{
+ return QString("-av");
+}
+
+RsyncCommandLine RsyncDeployStep::rsyncCommand(const SshConnection &sshConnection,
+ const QString &flags)
{
const QString sshCmdLine = QtcProcess::joinArgs(
QStringList{SshSettings::sshFilePath().toUserOutput()}
<< sshConnection.connectionOptions());
const SshConnectionParameters sshParams = sshConnection.connectionParameters();
- return RsyncCommandLine(QStringList{"-e", sshCmdLine, "-av"},
+ return RsyncCommandLine(QStringList{"-e", sshCmdLine, flags},
sshParams.userName() + '@' + sshParams.host());
}
diff --git a/src/plugins/remotelinux/rsyncdeploystep.h b/src/plugins/remotelinux/rsyncdeploystep.h
index ddc627e7dc..e71a57a11d 100644
--- a/src/plugins/remotelinux/rsyncdeploystep.h
+++ b/src/plugins/remotelinux/rsyncdeploystep.h
@@ -51,12 +51,15 @@ public:
static Core::Id stepId();
static QString displayName();
- static RsyncCommandLine rsyncCommand(const QSsh::SshConnection &sshConnection);
+ static QString defaultFlags();
+ static RsyncCommandLine rsyncCommand(const QSsh::SshConnection &sshConnection,
+ const QString &flags);
private:
AbstractRemoteLinuxDeployService *deployService() const override;
+ void doRun() override;
- bool initInternal(QString *error = nullptr) override;
+ CheckResult initInternal() override;
class RsyncDeployStepPrivate;
RsyncDeployStepPrivate * const d;
diff --git a/src/plugins/remotelinux/sshkeydeployer.cpp b/src/plugins/remotelinux/sshkeydeployer.cpp
index 7581a72018..2c73ffeff1 100644
--- a/src/plugins/remotelinux/sshkeydeployer.cpp
+++ b/src/plugins/remotelinux/sshkeydeployer.cpp
@@ -67,9 +67,10 @@ void SshKeyDeployer::deployPublicKey(const SshConnectionParameters &sshParams,
this, &SshKeyDeployer::handleConnectionFailure);
connect(&d->deployProcess, &SshRemoteProcessRunner::processClosed,
this, &SshKeyDeployer::handleKeyUploadFinished);
- const QByteArray command = "test -d .ssh "
+ const QString command = "test -d .ssh "
"|| mkdir .ssh && chmod 0700 .ssh && echo '"
- + reader.data() + "' >> .ssh/authorized_keys && chmod 0600 .ssh/authorized_keys";
+ + QString::fromLocal8Bit(reader.data())
+ + "' >> .ssh/authorized_keys && chmod 0600 .ssh/authorized_keys";
d->deployProcess.run(command, sshParams);
}
diff --git a/src/plugins/remotelinux/tarpackagecreationstep.cpp b/src/plugins/remotelinux/tarpackagecreationstep.cpp
index 49fead9a59..26ac446028 100644
--- a/src/plugins/remotelinux/tarpackagecreationstep.cpp
+++ b/src/plugins/remotelinux/tarpackagecreationstep.cpp
@@ -119,7 +119,7 @@ void TarPackageCreationStep::addNeededDeploymentFiles(
}
for (const QString &fileName : files) {
- const QString localFilePath = deployable.localFilePath().appendPath(fileName).toString();
+ const QString localFilePath = deployable.localFilePath().pathAppended(fileName).toString();
const QString remoteDir = deployable.remoteDirectory() + '/' + fileInfo.fileName();
diff --git a/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp b/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp
index 56068064ec..86a9d608fa 100644
--- a/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp
+++ b/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp
@@ -126,7 +126,7 @@ bool TypeSpecificDeviceConfigurationListModel::deviceMatches(IDevice::ConstPtr d
{
if (dev.isNull())
return false;
- Core::Id typeId = DeviceTypeKitInformation::deviceTypeId(target()->kit());
+ Core::Id typeId = DeviceTypeKitAspect::deviceTypeId(target()->kit());
return dev->type() == typeId;
}
diff --git a/src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp b/src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp
index ecc7eb3997..cf1c2face6 100644
--- a/src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp
+++ b/src/plugins/remotelinux/uploadandinstalltarpackagestep.cpp
@@ -69,7 +69,7 @@ UploadAndInstallTarPackageStep::UploadAndInstallTarPackageStep(BuildStepList *bs
setWidgetExpandedByDefault(false);
}
-bool UploadAndInstallTarPackageStep::initInternal(QString *error)
+CheckResult UploadAndInstallTarPackageStep::initInternal()
{
const TarPackageCreationStep *pStep = nullptr;
@@ -79,13 +79,11 @@ bool UploadAndInstallTarPackageStep::initInternal(QString *error)
if ((pStep = dynamic_cast<TarPackageCreationStep *>(step)))
break;
}
- if (!pStep) {
- if (error)
- *error = tr("No tarball creation step found.");
- return false;
- }
+ if (!pStep)
+ return CheckResult::failure(tr("No tarball creation step found."));
+
m_deployService->setPackageFilePath(pStep->packageFilePath());
- return m_deployService->isDeploymentPossible(error);
+ return m_deployService->isDeploymentPossible();
}
Core::Id UploadAndInstallTarPackageStep::stepId()
diff --git a/src/plugins/remotelinux/uploadandinstalltarpackagestep.h b/src/plugins/remotelinux/uploadandinstalltarpackagestep.h
index de1d2f487d..a613e7426f 100644
--- a/src/plugins/remotelinux/uploadandinstalltarpackagestep.h
+++ b/src/plugins/remotelinux/uploadandinstalltarpackagestep.h
@@ -55,7 +55,7 @@ class REMOTELINUX_EXPORT UploadAndInstallTarPackageStep : public AbstractRemoteL
public:
explicit UploadAndInstallTarPackageStep(ProjectExplorer::BuildStepList *bsl);
- bool initInternal(QString *error = nullptr) override;
+ CheckResult initInternal() override;
static Core::Id stepId();
static QString displayName();
diff --git a/src/plugins/resourceeditor/CMakeLists.txt b/src/plugins/resourceeditor/CMakeLists.txt
new file mode 100644
index 0000000000..e6d4003bf3
--- /dev/null
+++ b/src/plugins/resourceeditor/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_qtc_plugin(ResourceEditor
+ DEPENDS Qt5::Xml
+ DEFINES RESOURCE_LIBRARY
+ PLUGIN_DEPENDS Core ProjectExplorer
+ SOURCES
+ qrceditor/qrceditor.cpp qrceditor/qrceditor.h qrceditor/qrceditor.ui
+ qrceditor/resourcefile.cpp qrceditor/resourcefile_p.h
+ qrceditor/resourceview.cpp qrceditor/resourceview.h
+ qrceditor/undocommands.cpp qrceditor/undocommands_p.h
+ resource_global.h
+ resourceeditorconstants.h
+ resourceeditorfactory.cpp resourceeditorfactory.h
+ resourceeditorplugin.cpp resourceeditorplugin.h
+ resourceeditorw.cpp resourceeditorw.h
+ resourcenode.cpp resourcenode.h
+)
diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp
index 4f2032d28b..b4172173fa 100644
--- a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp
+++ b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp
@@ -813,7 +813,7 @@ bool ResourceModel::setData(const QModelIndex &index, const QVariant &value, int
return false;
const QDir baseDir = QFileInfo(fileName()).absoluteDir();
- Utils::FileName newFileName = Utils::FileName::fromUserInput(
+ Utils::FilePath newFileName = Utils::FilePath::fromUserInput(
baseDir.absoluteFilePath(value.toString()));
if (newFileName.isEmpty())
diff --git a/src/plugins/resourceeditor/resourceeditorplugin.cpp b/src/plugins/resourceeditor/resourceeditorplugin.cpp
index 4c7efeca47..7a5aedc434 100644
--- a/src/plugins/resourceeditor/resourceeditorplugin.cpp
+++ b/src/plugins/resourceeditor/resourceeditorplugin.cpp
@@ -216,9 +216,10 @@ void ResourceEditorPlugin::extensionsInitialized()
for (FileNode *file : toReplace) {
FolderNode *const pn = file->parentFolderNode();
QTC_ASSERT(pn, continue);
- const Utils::FileName path = file->filePath();
- pn->replaceSubtree(file, std::make_unique<ResourceTopLevelNode>(path, file->isGenerated(),
- QString(), pn));
+ const Utils::FilePath path = file->filePath();
+ auto topLevel = std::make_unique<ResourceTopLevelNode>(path, pn->filePath());
+ topLevel->setIsGenerated(file->isGenerated());
+ pn->replaceSubtree(file, std::move(topLevel));
}
});
}
@@ -240,7 +241,7 @@ void ResourceEditorPlugin::onRefresh()
void ResourceEditorPlugin::addPrefixContextMenu()
{
- auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::findCurrentNode());
+ auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::currentNode());
QTC_ASSERT(topLevel, return);
PrefixLangDialog dialog(tr("Add Prefix"), QString(), QString(), Core::ICore::mainWindow());
if (dialog.exec() != QDialog::Accepted)
@@ -253,7 +254,7 @@ void ResourceEditorPlugin::addPrefixContextMenu()
void ResourceEditorPlugin::removePrefixContextMenu()
{
- auto rfn = dynamic_cast<ResourceFolderNode *>(ProjectTree::findCurrentNode());
+ auto rfn = dynamic_cast<ResourceFolderNode *>(ProjectTree::currentNode());
QTC_ASSERT(rfn, return);
if (QMessageBox::question(Core::ICore::mainWindow(),
tr("Remove Prefix"),
@@ -266,7 +267,7 @@ void ResourceEditorPlugin::removePrefixContextMenu()
void ResourceEditorPlugin::removeNonExisting()
{
- auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::findCurrentNode());
+ auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::currentNode());
QTC_ASSERT(topLevel, return);
topLevel->removeNonExistingFiles();
}
@@ -278,7 +279,7 @@ void ResourceEditorPlugin::renameFileContextMenu()
void ResourceEditorPlugin::removeFileContextMenu()
{
- auto rfn = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::findCurrentNode());
+ auto rfn = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::currentNode());
QTC_ASSERT(rfn, return);
QString path = rfn->filePath().toString();
FolderNode *parent = rfn->parentFolderNode();
@@ -291,26 +292,26 @@ void ResourceEditorPlugin::removeFileContextMenu()
void ResourceEditorPlugin::openEditorContextMenu()
{
- Core::EditorManager::openEditor(ProjectTree::findCurrentNode()->filePath().toString());
+ Core::EditorManager::openEditor(ProjectTree::currentNode()->filePath().toString());
}
void ResourceEditorPlugin::copyPathContextMenu()
{
- auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::findCurrentNode());
+ auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::currentNode());
QTC_ASSERT(node, return);
QApplication::clipboard()->setText(QLatin1String(resourcePrefix) + node->qrcPath());
}
void ResourceEditorPlugin::copyUrlContextMenu()
{
- auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::findCurrentNode());
+ auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::currentNode());
QTC_ASSERT(node, return);
QApplication::clipboard()->setText(QLatin1String(urlPrefix) + node->qrcPath());
}
void ResourceEditorPlugin::renamePrefixContextMenu()
{
- auto node = dynamic_cast<ResourceFolderNode *>(ProjectTree::findCurrentNode());
+ auto node = dynamic_cast<ResourceFolderNode *>(ProjectTree::currentNode());
QTC_ASSERT(node, return);
PrefixLangDialog dialog(tr("Rename Prefix"), node->prefix(), node->lang(), Core::ICore::mainWindow());
@@ -325,7 +326,7 @@ void ResourceEditorPlugin::renamePrefixContextMenu()
void ResourceEditorPlugin::updateContextActions()
{
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
const bool isResourceNode = dynamic_cast<const ResourceTopLevelNode *>(node);
m_addPrefix->setEnabled(isResourceNode);
m_addPrefix->setVisible(isResourceNode);
diff --git a/src/plugins/resourceeditor/resourceeditorw.cpp b/src/plugins/resourceeditor/resourceeditorw.cpp
index 09a4001ff6..1dff313993 100644
--- a/src/plugins/resourceeditor/resourceeditorw.cpp
+++ b/src/plugins/resourceeditor/resourceeditorw.cpp
@@ -137,7 +137,7 @@ Core::IDocument::OpenResult ResourceEditorDocument::open(QString *errorString,
return openResult;
}
- setFilePath(FileName::fromString(fileName));
+ setFilePath(FilePath::fromString(fileName));
setBlockDirtyChanged(false);
m_model->setDirty(fileName != realFileName);
m_shouldAutoSave = false;
@@ -151,8 +151,8 @@ bool ResourceEditorDocument::save(QString *errorString, const QString &name, boo
if (debugResourceEditorW)
qDebug(">ResourceEditorW::save: %s", qPrintable(name));
- const FileName oldFileName = filePath();
- const FileName actualName = name.isEmpty() ? oldFileName : FileName::fromString(name);
+ const FilePath oldFileName = filePath();
+ const FilePath actualName = name.isEmpty() ? oldFileName : FilePath::fromString(name);
if (actualName.isEmpty())
return false;
@@ -208,7 +208,7 @@ bool ResourceEditorDocument::setContents(const QByteArray &contents)
return success;
}
-void ResourceEditorDocument::setFilePath(const FileName &newName)
+void ResourceEditorDocument::setFilePath(const FilePath &newName)
{
m_model->setFileName(newName.toString());
IDocument::setFilePath(newName);
diff --git a/src/plugins/resourceeditor/resourceeditorw.h b/src/plugins/resourceeditor/resourceeditorw.h
index 25bca62908..14c9c12394 100644
--- a/src/plugins/resourceeditor/resourceeditorw.h
+++ b/src/plugins/resourceeditor/resourceeditorw.h
@@ -61,7 +61,7 @@ public:
bool isModified() const override;
bool isSaveAsAllowed() const override;
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
- void setFilePath(const Utils::FileName &newName) override;
+ void setFilePath(const Utils::FilePath &newName) override;
void setBlockDirtyChanged(bool value);
RelativeResourceModel *model() const;
diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp
index 5276bb6929..baf214a2be 100644
--- a/src/plugins/resourceeditor/resourcenode.cpp
+++ b/src/plugins/resourceeditor/resourcenode.cpp
@@ -73,7 +73,7 @@ public:
FolderNode *parent = m_node->parentFolderNode();
QTC_ASSERT(parent, return false);
parent->replaceSubtree(m_node, std::make_unique<ResourceTopLevelNode>(
- m_node->filePath(), false, m_node->contents(), parent));
+ m_node->filePath(), parent->filePath(), m_node->contents()));
return true;
}
@@ -119,7 +119,7 @@ static bool hasPriority(const QStringList &files)
return false;
}
-static bool addFilesToResource(const FileName &resourceFile,
+static bool addFilesToResource(const FilePath &resourceFile,
const QStringList &filePaths,
QStringList *notAdded,
const QString &prefix,
@@ -157,13 +157,13 @@ class SimpleResourceFolderNode : public FolderNode
friend class ResourceEditor::ResourceTopLevelNode;
public:
SimpleResourceFolderNode(const QString &afolderName, const QString &displayName,
- const QString &prefix, const QString &lang, FileName absolutePath,
+ const QString &prefix, const QString &lang, FilePath absolutePath,
ResourceTopLevelNode *topLevel, ResourceFolderNode *prefixNode);
- QString displayName() const final;
bool supportsAction(ProjectAction, const Node *node) const final;
bool addFiles(const QStringList &filePaths, QStringList *notAdded) final;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) final;
+ bool canRenameFile(const QString &filePath, const QString &newFilePath) override;
bool renameFile(const QString &filePath, const QString &newFilePath) final;
QString prefix() const { return m_prefix; }
@@ -172,32 +172,23 @@ public:
private:
QString m_folderName;
- QString m_displayName;
QString m_prefix;
QString m_lang;
ResourceTopLevelNode *m_topLevelNode;
ResourceFolderNode *m_prefixNode;
};
-QString SimpleResourceFolderNode::displayName() const
-{
- if (!m_displayName.isEmpty())
- return m_displayName;
- return FolderNode::displayName();
-}
-
SimpleResourceFolderNode::SimpleResourceFolderNode(const QString &afolderName, const QString &displayName,
const QString &prefix, const QString &lang,
- FileName absolutePath, ResourceTopLevelNode *topLevel, ResourceFolderNode *prefixNode)
+ FilePath absolutePath, ResourceTopLevelNode *topLevel, ResourceFolderNode *prefixNode)
: FolderNode(absolutePath)
, m_folderName(afolderName)
- , m_displayName(displayName)
, m_prefix(prefix)
, m_lang(lang)
, m_topLevelNode(topLevel)
, m_prefixNode(prefixNode)
{
-
+ setDisplayName(displayName);
}
bool SimpleResourceFolderNode::supportsAction(ProjectAction action, const Node *) const
@@ -218,60 +209,31 @@ bool SimpleResourceFolderNode::addFiles(const QStringList &filePaths, QStringLis
bool SimpleResourceFolderNode::removeFiles(const QStringList &filePaths, QStringList *notRemoved)
{
- if (notRemoved)
- *notRemoved = filePaths;
- ResourceFile file(m_topLevelNode->filePath().toString());
- if (file.load() != IDocument::OpenResult::Success)
- return false;
- int index = file.indexOfPrefix(m_prefix, m_lang);
- if (index == -1)
- return false;
- for (int j = 0; j < file.fileCount(index); ++j) {
- const QString fileName = file.file(index, j);
- if (!filePaths.contains(fileName))
- continue;
- if (notRemoved)
- notRemoved->removeOne(fileName);
- file.removeFile(index, j);
- --j;
- }
- FileChangeBlocker changeGuard(m_topLevelNode->filePath().toString());
- file.save();
+ return prefixNode()->removeFiles(filePaths, notRemoved);
+}
- return true;
+bool SimpleResourceFolderNode::canRenameFile(const QString &filePath, const QString &newFilePath)
+{
+ return prefixNode()->canRenameFile(filePath, newFilePath);
}
bool SimpleResourceFolderNode::renameFile(const QString &filePath, const QString &newFilePath)
{
- ResourceFile file(m_topLevelNode->filePath().toString());
- if (file.load() != IDocument::OpenResult::Success)
- return false;
- int index = file.indexOfPrefix(m_prefix, m_lang);
- if (index == -1)
- return false;
-
- for (int j = 0; j < file.fileCount(index); ++j) {
- if (file.file(index, j) == filePath) {
- file.replaceFile(index, j, newFilePath);
- FileChangeBlocker changeGuard(m_topLevelNode->filePath().toString());
- file.save();
- return true;
- }
- }
-
- return false;
+ return prefixNode()->renameFile(filePath, newFilePath);
}
} // Internal
-ResourceTopLevelNode::ResourceTopLevelNode(const FileName &filePath, bool generated,
- const QString &contents, FolderNode *parent)
+ResourceTopLevelNode::ResourceTopLevelNode(const FilePath &filePath,
+ const FilePath &base,
+ const QString &contents)
: FolderNode(filePath)
{
- setIsGenerated(generated);
setIcon(FileIconProvider::icon(filePath.toString()));
setPriority(Node::DefaultFilePriority);
setListInProject(true);
+ setAddFileFilter("*.png; *.jpg; *.gif; *.svg; *.ico; *.qml; *.qml.ui");
+
if (!filePath.isEmpty()) {
QFileInfo fi = filePath.toFileInfo();
if (fi.isFile() && fi.isReadable()) {
@@ -282,7 +244,6 @@ ResourceTopLevelNode::ResourceTopLevelNode(const FileName &filePath, bool genera
m_contents = contents;
}
- FileName base = parent->filePath();
if (filePath.isChildOf(base))
setDisplayName(filePath.relativeChildPath(base).toUserOutput());
else
@@ -298,6 +259,17 @@ ResourceTopLevelNode::~ResourceTopLevelNode()
delete m_document;
}
+static void compressTree(FolderNode *n)
+{
+ if (const auto compressable = dynamic_cast<SimpleResourceFolderNode *>(n)) {
+ compressable->compress();
+ return;
+ }
+ const QList<FolderNode *> childFolders = n->folderNodes();
+ for (FolderNode * const c : childFolders)
+ compressTree(c);
+}
+
void ResourceTopLevelNode::addInternalNodes()
{
ResourceFile file(filePath().toString(), m_contents);
@@ -356,7 +328,7 @@ void ResourceTopLevelNode::addInternalNodes()
const QString absoluteFolderName
= filePath().toFileInfo().absoluteDir().absoluteFilePath(
currentPathList.join(QLatin1Char('/')));
- const FileName folderPath = FileName::fromString(absoluteFolderName);
+ const FilePath folderPath = FilePath::fromString(absoluteFolderName);
std::unique_ptr<FolderNode> newNode
= std::make_unique<SimpleResourceFolderNode>(folderName, pathElement,
prefix, lang, folderPath,
@@ -379,15 +351,11 @@ void ResourceTopLevelNode::addInternalNodes()
FolderNode *fn = folderNodes[folderId];
QTC_CHECK(fn);
if (fn)
- fn->addNode(std::make_unique<ResourceFileNode>(FileName::fromString(fileName),
+ fn->addNode(std::make_unique<ResourceFileNode>(FilePath::fromString(fileName),
qrcPath, displayName));
}
}
-}
-
-QString ResourceTopLevelNode::addFileFilter() const
-{
- return QLatin1String("*.png; *.jpg; *.gif; *.svg; *.ico; *.qml; *.qml.ui");
+ compressTree(this);
}
bool ResourceTopLevelNode::supportsAction(ProjectAction action, const Node *node) const
@@ -493,19 +461,14 @@ bool ResourceTopLevelNode::showInSimpleTree() const
return true;
}
-bool ResourceTopLevelNode::showWhenEmpty() const
-{
- return true;
-}
-
ResourceFolderNode::ResourceFolderNode(const QString &prefix, const QString &lang, ResourceTopLevelNode *parent)
- : FolderNode(FileName(parent->filePath()).appendPath(prefix)),
+ : FolderNode(parent->filePath().pathAppended(prefix)),
// TOOD Why add existing directory doesn't work
m_topLevelNode(parent),
m_prefix(prefix),
m_lang(lang)
{
-
+ setShowWhenEmpty(true);
}
ResourceFolderNode::~ResourceFolderNode() = default;
@@ -553,6 +516,7 @@ bool ResourceFolderNode::removeFiles(const QStringList &filePaths, QStringList *
file.removeFile(index, j);
--j;
}
+ FileChangeBlocker changeGuard(m_topLevelNode->filePath().toString());
file.save();
return true;
@@ -591,6 +555,7 @@ bool ResourceFolderNode::renameFile(const QString &filePath, const QString &newF
for (int j = 0; j < file.fileCount(index); ++j) {
if (file.file(index, j) == filePath) {
file.replaceFile(index, j, newFilePath);
+ FileChangeBlocker changeGuard(m_topLevelNode->filePath().toString());
file.save();
return true;
}
@@ -658,8 +623,8 @@ ResourceTopLevelNode *ResourceFolderNode::resourceNode() const
return m_topLevelNode;
}
-ResourceFileNode::ResourceFileNode(const FileName &filePath, const QString &qrcPath, const QString &displayName)
- : FileNode(filePath, FileNode::fileTypeForFileName(filePath), false)
+ResourceFileNode::ResourceFileNode(const FilePath &filePath, const QString &qrcPath, const QString &displayName)
+ : FileNode(filePath, FileNode::fileTypeForFileName(filePath))
, m_qrcPath(qrcPath)
, m_displayName(displayName)
{
diff --git a/src/plugins/resourceeditor/resourcenode.h b/src/plugins/resourceeditor/resourcenode.h
index 38175c322d..181172a7fe 100644
--- a/src/plugins/resourceeditor/resourcenode.h
+++ b/src/plugins/resourceeditor/resourcenode.h
@@ -34,14 +34,13 @@ namespace Internal { class ResourceFileWatcher; }
class RESOURCE_EXPORT ResourceTopLevelNode : public ProjectExplorer::FolderNode
{
public:
- ResourceTopLevelNode(const Utils::FileName &filePath, bool generated,
- const QString &contents, FolderNode *parent);
+ ResourceTopLevelNode(const Utils::FilePath &filePath,
+ const Utils::FilePath &basePath,
+ const QString &contents = {});
~ResourceTopLevelNode() override;
void addInternalNodes();
- QString addFileFilter() const override;
-
bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) override;
@@ -51,7 +50,6 @@ public:
AddNewInformation addNewInformation(const QStringList &files, Node *context) const override;
bool showInSimpleTree() const override;
- bool showWhenEmpty() const override;
bool removeNonExistingFiles();
QString contents() const { return m_contents; }
@@ -93,7 +91,7 @@ private:
class RESOURCE_EXPORT ResourceFileNode : public ProjectExplorer::FileNode
{
public:
- ResourceFileNode(const Utils::FileName &filePath, const QString &qrcPath, const QString &displayName);
+ ResourceFileNode(const Utils::FilePath &filePath, const QString &qrcPath, const QString &displayName);
QString displayName() const override;
QString qrcPath() const;
diff --git a/src/plugins/scxmleditor/CMakeLists.txt b/src/plugins/scxmleditor/CMakeLists.txt
new file mode 100644
index 0000000000..9a4925dfa2
--- /dev/null
+++ b/src/plugins/scxmleditor/CMakeLists.txt
@@ -0,0 +1,94 @@
+add_qtc_plugin(ScxmlEditor
+ INCLUDES common plugin_interface outputpane
+ PLUGIN_DEPENDS Core ProjectExplorer QtSupport TextEditor
+ SOURCES
+ common/colorpicker.cpp common/colorpicker.h common/colorpicker.ui
+ common/colorsettings.cpp common/colorsettings.h common/colorsettings.ui
+ common/colorthemedialog.cpp common/colorthemedialog.h common/colorthemedialog.ui
+ common/colorthemes.cpp common/colorthemes.h
+ common/colorthemeview.cpp common/colorthemeview.h
+ common/colortoolbutton.cpp common/colortoolbutton.h
+ common/common.qrc
+ common/dragshapebutton.cpp common/dragshapebutton.h
+ common/graphicsview.cpp common/graphicsview.h
+ common/magnifier.cpp common/magnifier.h common/magnifier.ui
+ common/mainwidget.cpp common/mainwidget.h
+ common/movableframe.cpp common/movableframe.h
+ common/navigator.cpp common/navigator.h
+ common/navigatorgraphicsview.cpp common/navigatorgraphicsview.h
+ common/navigatorslider.cpp common/navigatorslider.h common/navigatorslider.ui
+ common/search.cpp common/search.h common/search.ui
+ common/searchmodel.cpp common/searchmodel.h
+ common/shapegroupwidget.cpp common/shapegroupwidget.h
+ common/shapestoolbox.cpp common/shapestoolbox.h common/shapestoolbox.ui
+ common/sizegrip.cpp common/sizegrip.h
+ common/stateproperties.cpp common/stateproperties.h
+ common/stateview.cpp common/stateview.h common/stateview.ui
+ common/statistics.cpp common/statistics.h common/statistics.ui
+ common/statisticsdialog.cpp common/statisticsdialog.h common/statisticsdialog.ui
+ common/structure.cpp common/structure.h
+ common/structuremodel.cpp common/structuremodel.h
+ common/treeview.cpp common/treeview.h
+ outputpane/errorwidget.cpp outputpane/errorwidget.h
+ outputpane/outputpane.h
+ outputpane/outputtabwidget.cpp outputpane/outputtabwidget.h
+ outputpane/tableview.cpp outputpane/tableview.h
+ outputpane/warning.cpp outputpane/warning.h
+ outputpane/warningmodel.cpp outputpane/warningmodel.h
+ plugin_interface/actionhandler.cpp plugin_interface/actionhandler.h
+ plugin_interface/actionprovider.h
+ plugin_interface/attributeitemdelegate.cpp plugin_interface/attributeitemdelegate.h
+ plugin_interface/attributeitemmodel.cpp plugin_interface/attributeitemmodel.h
+ plugin_interface/baseitem.cpp plugin_interface/baseitem.h
+ plugin_interface/connectableitem.cpp plugin_interface/connectableitem.h
+ plugin_interface/cornergrabberitem.cpp plugin_interface/cornergrabberitem.h
+ plugin_interface/finalstateitem.cpp plugin_interface/finalstateitem.h
+ plugin_interface/genericscxmlplugin.cpp plugin_interface/genericscxmlplugin.h
+ plugin_interface/graphicsitemprovider.h
+ plugin_interface/graphicsscene.cpp plugin_interface/graphicsscene.h
+ plugin_interface/highlightitem.cpp plugin_interface/highlightitem.h
+ plugin_interface/historyitem.cpp plugin_interface/historyitem.h
+ plugin_interface/idwarningitem.cpp plugin_interface/idwarningitem.h
+ plugin_interface/imageprovider.cpp plugin_interface/imageprovider.h
+ plugin_interface/initialstateitem.cpp plugin_interface/initialstateitem.h
+ plugin_interface/initialwarningitem.cpp plugin_interface/initialwarningitem.h
+ plugin_interface/isceditor.h
+ plugin_interface/layoutitem.cpp plugin_interface/layoutitem.h
+ plugin_interface/mytypes.h
+ plugin_interface/parallelitem.cpp plugin_interface/parallelitem.h
+ plugin_interface/quicktransitionitem.cpp plugin_interface/quicktransitionitem.h
+ plugin_interface/scattributeitemdelegate.cpp plugin_interface/scattributeitemdelegate.h
+ plugin_interface/scattributeitemmodel.cpp plugin_interface/scattributeitemmodel.h
+ plugin_interface/sceneutils.cpp plugin_interface/sceneutils.h
+ plugin_interface/scgraphicsitemprovider.cpp plugin_interface/scgraphicsitemprovider.h
+ plugin_interface/scshapeprovider.cpp plugin_interface/scshapeprovider.h
+ plugin_interface/scutilsprovider.cpp plugin_interface/scutilsprovider.h
+ plugin_interface/scxmldocument.cpp plugin_interface/scxmldocument.h
+ plugin_interface/scxmlnamespace.cpp plugin_interface/scxmlnamespace.h
+ plugin_interface/scxmltag.cpp plugin_interface/scxmltag.h
+ plugin_interface/scxmltagutils.cpp plugin_interface/scxmltagutils.h
+ plugin_interface/scxmltypes.h
+ plugin_interface/scxmluifactory.cpp plugin_interface/scxmluifactory.h
+ plugin_interface/serializer.cpp plugin_interface/serializer.h
+ plugin_interface/shapeprovider.cpp plugin_interface/shapeprovider.h
+ plugin_interface/snapline.cpp plugin_interface/snapline.h
+ plugin_interface/stateitem.cpp plugin_interface/stateitem.h
+ plugin_interface/statewarningitem.cpp plugin_interface/statewarningitem.h
+ plugin_interface/tagtextitem.cpp plugin_interface/tagtextitem.h
+ plugin_interface/textitem.cpp plugin_interface/textitem.h
+ plugin_interface/transitionitem.cpp plugin_interface/transitionitem.h
+ plugin_interface/transitionwarningitem.cpp plugin_interface/transitionwarningitem.h
+ plugin_interface/undocommands.cpp plugin_interface/undocommands.h
+ plugin_interface/utilsprovider.cpp plugin_interface/utilsprovider.h
+ plugin_interface/warningitem.cpp plugin_interface/warningitem.h
+ plugin_interface/warningprovider.h
+ scxmlcontext.cpp scxmlcontext.h
+ scxmleditor_global.h
+ scxmleditorconstants.h
+ scxmleditordata.cpp scxmleditordata.h
+ scxmleditordocument.cpp scxmleditordocument.h
+ scxmleditorfactory.cpp scxmleditorfactory.h
+ scxmleditorplugin.cpp scxmleditorplugin.h
+ scxmleditorstack.cpp scxmleditorstack.h
+ scxmltexteditor.cpp scxmltexteditor.h
+)
diff --git a/src/plugins/scxmleditor/common/colorsettings.cpp b/src/plugins/scxmleditor/common/colorsettings.cpp
index cb3f1cee17..8b952c253b 100644
--- a/src/plugins/scxmleditor/common/colorsettings.cpp
+++ b/src/plugins/scxmleditor/common/colorsettings.cpp
@@ -39,7 +39,8 @@ ColorSettings::ColorSettings(QWidget *parent)
m_ui.setupUi(this);
m_ui.m_colorThemeView->setEnabled(false);
- connect(m_ui.m_comboColorThemes, static_cast<void (QComboBox::*)(const QString&)>(&QComboBox::currentIndexChanged), this, &ColorSettings::selectTheme);
+ connect(m_ui.m_comboColorThemes, QOverload<const QString &>::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);
diff --git a/src/plugins/scxmleditor/common/stateproperties.cpp b/src/plugins/scxmleditor/common/stateproperties.cpp
index 8a9d0aa3b2..b9797aeed3 100644
--- a/src/plugins/scxmleditor/common/stateproperties.cpp
+++ b/src/plugins/scxmleditor/common/stateproperties.cpp
@@ -50,7 +50,7 @@ StateProperties::StateProperties(QWidget *parent)
m_contentTimer.setInterval(500);
m_contentTimer.setSingleShot(true);
- connect(m_contentEdit, &QPlainTextEdit::textChanged, &m_contentTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ connect(m_contentEdit, &QPlainTextEdit::textChanged, &m_contentTimer, QOverload<>::of(&QTimer::start));
connect(&m_contentTimer, &QTimer::timeout, this, &StateProperties::timerTimeout);
}
diff --git a/src/plugins/scxmleditor/scxmleditordocument.cpp b/src/plugins/scxmleditor/scxmleditordocument.cpp
index d7c09b9e88..3f74d97a0c 100644
--- a/src/plugins/scxmleditor/scxmleditordocument.cpp
+++ b/src/plugins/scxmleditor/scxmleditordocument.cpp
@@ -74,15 +74,15 @@ Core::IDocument::OpenResult ScxmlEditorDocument::open(QString *errorString, cons
return OpenResult::ReadError;
}
- setFilePath(Utils::FileName::fromString(absfileName));
+ setFilePath(Utils::FilePath::fromString(absfileName));
return OpenResult::Success;
}
bool ScxmlEditorDocument::save(QString *errorString, const QString &name, bool autoSave)
{
- const FileName oldFileName = filePath();
- const FileName actualName = name.isEmpty() ? oldFileName : FileName::fromString(name);
+ const FilePath oldFileName = filePath();
+ const FilePath actualName = name.isEmpty() ? oldFileName : FilePath::fromString(name);
if (actualName.isEmpty())
return false;
bool dirty = m_designWidget->isDirty();
@@ -108,7 +108,7 @@ bool ScxmlEditorDocument::save(QString *errorString, const QString &name, bool a
return true;
}
-void ScxmlEditorDocument::setFilePath(const FileName &newName)
+void ScxmlEditorDocument::setFilePath(const FilePath &newName)
{
m_designWidget->setFileName(newName.toString());
IDocument::setFilePath(newName);
diff --git a/src/plugins/scxmleditor/scxmleditordocument.h b/src/plugins/scxmleditor/scxmleditordocument.h
index 2ccb98213d..537c7eb027 100644
--- a/src/plugins/scxmleditor/scxmleditordocument.h
+++ b/src/plugins/scxmleditor/scxmleditordocument.h
@@ -60,7 +60,7 @@ public:
Common::MainWidget *designWidget() const;
void syncXmlFromDesignWidget();
QString designWidgetContents() const;
- void setFilePath(const Utils::FileName&) override;
+ void setFilePath(const Utils::FilePath&) override;
signals:
void reloadRequested(QString *errorString, const QString &);
diff --git a/src/plugins/scxmleditor/scxmltexteditor.cpp b/src/plugins/scxmleditor/scxmltexteditor.cpp
index 0c86cad919..f6f3f08954 100644
--- a/src/plugins/scxmleditor/scxmltexteditor.cpp
+++ b/src/plugins/scxmleditor/scxmltexteditor.cpp
@@ -74,7 +74,7 @@ bool ScxmlTextEditor::open(QString *errorString, const QString &fileName, const
}
document->syncXmlFromDesignWidget();
- document->setFilePath(Utils::FileName::fromString(absfileName));
+ document->setFilePath(Utils::FilePath::fromString(absfileName));
return true;
}
diff --git a/src/plugins/serialterminal/CMakeLists.txt b/src/plugins/serialterminal/CMakeLists.txt
new file mode 100644
index 0000000000..79bbddb219
--- /dev/null
+++ b/src/plugins/serialterminal/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_qtc_plugin(SerialTerminal
+ CONDITION TARGET Qt5::SerialPort
+ DEPENDS Qt5::SerialPort
+ PLUGIN_DEPENDS Core TextEditor
+ SOURCES
+ consolelineedit.cpp consolelineedit.h
+ serialcontrol.cpp serialcontrol.h
+ serialdevicemodel.cpp serialdevicemodel.h
+ serialoutputpane.cpp serialoutputpane.h
+ serialterminalconstants.h
+ serialterminalplugin.cpp serialterminalplugin.h
+ serialterminalsettings.cpp serialterminalsettings.h
+)
diff --git a/src/plugins/serialterminal/serialoutputpane.cpp b/src/plugins/serialterminal/serialoutputpane.cpp
index cf3a9a2f14..e1eca5aec1 100644
--- a/src/plugins/serialterminal/serialoutputpane.cpp
+++ b/src/plugins/serialterminal/serialoutputpane.cpp
@@ -169,7 +169,7 @@ SerialOutputPane::SerialOutputPane(Settings &settings) :
updateLineEndingsComboBox();
inputLayout->addWidget(m_lineEndingsSelection);
- connect(m_lineEndingsSelection, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_lineEndingsSelection, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SerialOutputPane::defaultLineEndingChanged);
layout->addLayout(inputLayout);
@@ -305,7 +305,7 @@ void SerialOutputPane::createNewOutputWindow(SerialControl *rc)
static uint counter = 0;
Core::Id contextId = Core::Id(Constants::C_SERIAL_OUTPUT).withSuffix(counter++);
Core::Context context(contextId);
- Core::OutputWindow *ow = new Core::OutputWindow(context, m_tabWidget);
+ Core::OutputWindow *ow = new Core::OutputWindow(context, QString(), m_tabWidget);
using TextEditor::TextEditorSettings;
auto fontSettingsChanged = [ow] {
ow->setBaseFont(TextEditorSettings::fontSettings().font());
@@ -352,7 +352,6 @@ void SerialOutputPane::createToolButtons()
m_connectButton = new QToolButton;
m_connectButton->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR.icon());
m_connectButton->setToolTip(tr("Connect"));
- m_connectButton->setAutoRaise(true);
m_connectButton->setEnabled(false);
connect(m_connectButton, &QToolButton::clicked,
this, &SerialOutputPane::connectControl);
@@ -361,7 +360,6 @@ void SerialOutputPane::createToolButtons()
m_disconnectButton = new QToolButton;
m_disconnectButton->setIcon(Utils::Icons::STOP_SMALL_TOOLBAR.icon());
m_disconnectButton->setToolTip(tr("Disconnect"));
- m_disconnectButton->setAutoRaise(true);
m_disconnectButton->setEnabled(false);
connect(m_disconnectButton, &QToolButton::clicked,
@@ -371,7 +369,6 @@ void SerialOutputPane::createToolButtons()
m_resetButton = new QToolButton;
m_resetButton->setIcon(Utils::Icons::RELOAD.icon());
m_resetButton->setToolTip(tr("Reset Board"));
- m_resetButton->setAutoRaise(true);
m_resetButton->setEnabled(false);
connect(m_resetButton, &QToolButton::clicked,
@@ -381,7 +378,6 @@ void SerialOutputPane::createToolButtons()
m_newButton = new QToolButton;
m_newButton->setIcon(Utils::Icons::PLUS_TOOLBAR.icon());
m_newButton->setToolTip(tr("Add New Terminal"));
- m_newButton->setAutoRaise(true);
m_newButton->setEnabled(true);
connect(m_newButton, &QToolButton::clicked,
@@ -393,7 +389,7 @@ void SerialOutputPane::createToolButtons()
m_portsSelection->setModel(m_devicesModel);
updatePortsList();
connect(m_portsSelection, &ComboBox::opened, this, &SerialOutputPane::updatePortsList);
- connect(m_portsSelection, static_cast<void (ComboBox::*)(int)>(&ComboBox::currentIndexChanged),
+ connect(m_portsSelection, QOverload<int>::of(&ComboBox::currentIndexChanged),
this, &SerialOutputPane::activePortNameChanged);
// TODO: the ports are not updated with the box opened (if the user wait for it) -> add a timer?
@@ -402,7 +398,7 @@ void SerialOutputPane::createToolButtons()
m_baudRateSelection = new ComboBox;
m_baudRateSelection->setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_baudRateSelection->addItems(m_devicesModel->baudRates());
- connect(m_baudRateSelection, static_cast<void (ComboBox::*)(int)>(&ComboBox::currentIndexChanged),
+ connect(m_baudRateSelection, QOverload<int>::of(&ComboBox::currentIndexChanged),
this, &SerialOutputPane::activeBaudRateChanged);
if (m_settings.baudRate > 0)
diff --git a/src/plugins/silversearcher/CMakeLists.txt b/src/plugins/silversearcher/CMakeLists.txt
new file mode 100644
index 0000000000..bff78e573a
--- /dev/null
+++ b/src/plugins/silversearcher/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_qtc_plugin(SilverSearcher
+ PLUGIN_DEPENDS Core TextEditor
+ SOURCES
+ findinfilessilversearcher.cpp findinfilessilversearcher.h
+ silversearcheroutputparser.cpp silversearcheroutputparser.h
+ silversearcherplugin.cpp silversearcherplugin.h
+)
+
+extend_qtc_plugin(SilverSearcher CONDITION WITH_TESTS
+ SOURCES
+ outputparser_test.cpp outputparser_test.h
+)
diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp
index 5b22cc2cd4..f0d6fa7eae 100644
--- a/src/plugins/silversearcher/findinfilessilversearcher.cpp
+++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp
@@ -127,7 +127,7 @@ void runSilverSeacher(FutureInterfaceType &fi, FileFindParameters parameters)
if (!params.searchOptions.isEmpty())
arguments << params.searchOptions.split(' ');
- const FileName path = FileName::fromUserInput(FileUtils::normalizePathName(directory));
+ const FilePath path = FilePath::fromUserInput(FileUtils::normalizePathName(directory));
arguments << "--" << parameters.text << path.toString();
QProcess process;
@@ -190,7 +190,7 @@ QVariant FindInFilesSilverSearcher::parameters() const
{
SilverSearcherSearchOptions silverSearcherSearchOptions;
silverSearcherSearchOptions.searchOptions = m_searchOptionsLineEdit->text();
- return qVariantFromValue(silverSearcherSearchOptions);
+ return QVariant::fromValue(silverSearcherSearchOptions);
}
QString FindInFilesSilverSearcher::title() const
diff --git a/src/plugins/silversearcher/findinfilessilversearcher.h b/src/plugins/silversearcher/findinfilessilversearcher.h
index 8d0ebdd2c4..798b7f9fd9 100644
--- a/src/plugins/silversearcher/findinfilessilversearcher.h
+++ b/src/plugins/silversearcher/findinfilessilversearcher.h
@@ -61,7 +61,7 @@ public:
private:
QPointer<Core::IFindSupport> m_currentFindSupport;
- Utils::FileName m_directorySetting;
+ Utils::FilePath m_directorySetting;
QPointer<QWidget> m_widget;
QPointer<QLineEdit> m_searchOptionsLineEdit;
QString m_path;
diff --git a/src/plugins/silversearcher/silversearcherplugin.cpp b/src/plugins/silversearcher/silversearcherplugin.cpp
index 3d3ecca4e8..e6a090ffe9 100644
--- a/src/plugins/silversearcher/silversearcherplugin.cpp
+++ b/src/plugins/silversearcher/silversearcherplugin.cpp
@@ -45,7 +45,7 @@ void SilverSearcherPlugin::extensionsInitialized()
}
#ifdef WITH_TESTS
-QList<QObject *> SilverSearcherPlugin::createTestObjects() const
+QVector<QObject *> SilverSearcherPlugin::createTestObjects() const
{
return {new OutputParserTest};
}
diff --git a/src/plugins/silversearcher/silversearcherplugin.h b/src/plugins/silversearcher/silversearcherplugin.h
index 4ff3246dad..66e0d277bd 100644
--- a/src/plugins/silversearcher/silversearcherplugin.h
+++ b/src/plugins/silversearcher/silversearcherplugin.h
@@ -40,7 +40,7 @@ public:
void extensionsInitialized() override;
#ifdef WITH_TESTS
private:
- QList<QObject *> createTestObjects() const override;
+ QVector<QObject *> createTestObjects() const override;
#endif
};
diff --git a/src/plugins/studiowelcome/CMakeLists.txt b/src/plugins/studiowelcome/CMakeLists.txt
new file mode 100644
index 0000000000..30e5cc62af
--- /dev/null
+++ b/src/plugins/studiowelcome/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_qtc_plugin(StudioWelcome
+ DEPENDS Qt5::QuickWidgets
+ PLUGIN_DEPENDS Core ProjectExplorer QtSupport
+ DEFINES STUDIO_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/qml"
+ SOURCES
+ studiowelcomeplugin.cpp studiowelcomeplugin.h
+ studiowelcome_global.h
+ studiowelcome.qrc
+ "${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc"
+)
diff --git a/src/plugins/studiowelcome/StudioWelcome.json.in b/src/plugins/studiowelcome/StudioWelcome.json.in
new file mode 100644
index 0000000000..5a4173de12
--- /dev/null
+++ b/src/plugins/studiowelcome/StudioWelcome.json.in
@@ -0,0 +1,21 @@
+{
+ \"Name\" : \"StudioWelcome\",
+ \"Version\" : \"$$QTCREATOR_VERSION\",
+ \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
+ \"Revision\" : \"$$QTC_PLUGIN_REVISION\",
+ \"DisabledByDefault\" : 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.\"
+ ],
+ \"Category\" : \"Qt Quick\",
+ \"Description\" : \"Qt Design Studio Welcome Page.\",
+ \"Url\" : \"http://www.qt.io\",
+ $$dependencyList
+}
diff --git a/src/plugins/studiowelcome/images/mode_welcome_mask.png b/src/plugins/studiowelcome/images/mode_welcome_mask.png
new file mode 100644
index 0000000000..696af0c549
--- /dev/null
+++ b/src/plugins/studiowelcome/images/mode_welcome_mask.png
Binary files differ
diff --git a/src/plugins/studiowelcome/images/mode_welcome_mask@2x.png b/src/plugins/studiowelcome/images/mode_welcome_mask@2x.png
new file mode 100644
index 0000000000..060ada0cf5
--- /dev/null
+++ b/src/plugins/studiowelcome/images/mode_welcome_mask@2x.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Arc.qml b/src/plugins/studiowelcome/qml/splashscreen/Arc.qml
new file mode 100644
index 0000000000..2a63c1a7de
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Arc.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Shape {
+ id: root
+
+ //Antialiasing workaround
+ layer.enabled: true
+ layer.textureSize: Qt.size(width * 2, height * 2)
+ layer.smooth: true
+
+ implicitWidth: 100
+ implicitHeight: 100
+
+ property alias fillColor: path.fillColor
+ property alias strokeColor: path.strokeColor
+ property alias strokeWidth: path.strokeWidth
+ property alias capStyle: path.capStyle
+ property alias strokeStyle: path.strokeStyle
+ property alias fillGradient: path.fillGradient
+
+ property real begin: 0
+ property real end: 90
+
+ property real alpha: end - begin
+
+ function polarToCartesianX(centerX, centerY, radius, angleInDegrees) {
+ var angleInRadians = angleInDegrees * Math.PI / 180.0
+ var x = centerX + radius * Math.cos(angleInRadians)
+ return x
+ }
+
+ function polarToCartesianY(centerX, centerY, radius, angleInDegrees) {
+ var angleInRadians = angleInDegrees * Math.PI / 180.0
+ var y = centerY + radius * Math.sin(angleInRadians)
+ return y
+ }
+
+ ShapePath {
+ id: path
+
+ property real __xRadius: width / 2 - strokeWidth / 2
+ property real __yRadius: height / 2 - strokeWidth / 2
+
+ property real __Xcenter: width / 2
+ property real __Ycenter: height / 2
+ strokeColor: "#000000"
+
+ fillColor: "transparent"
+ strokeWidth: 1
+ capStyle: ShapePath.FlatCap
+
+ startX: root.polarToCartesianX(path.__Xcenter, path.__Ycenter,
+ path.__xRadius, root.begin - 180)
+ startY: root.polarToCartesianY(path.__Xcenter, path.__Ycenter,
+ path.__yRadius, root.begin - 180)
+
+ PathArc {
+ id: arc
+
+ x: root.polarToCartesianX(path.__Xcenter, path.__Ycenter,
+ path.__xRadius, root.end - 180)
+ y: root.polarToCartesianY(path.__Xcenter, path.__Ycenter,
+ path.__yRadius, root.end - 180)
+
+ radiusY: path.__yRadius
+ radiusX: path.__xRadius
+
+ useLargeArc: root.alpha > 180
+ }
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/ArcAnimation.qml b/src/plugins/studiowelcome/qml/splashscreen/ArcAnimation.qml
new file mode 100644
index 0000000000..08fae81a2c
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/ArcAnimation.qml
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Timeline 1.0
+
+Item {
+ id: arcItem
+ width: 549
+ height: 457
+ Arc {
+ id: arc
+ x: 401
+ y: 191
+ width: 52
+ height: 52
+ strokeColor: "#5d9dea"
+ end: 0
+ scale: 0.8
+ strokeWidth: 7
+ }
+
+ Arc {
+ id: arc1
+ x: 353
+ y: 203
+ width: 52
+ height: 52
+ rotation: -45
+ strokeWidth: 7
+ scale: 0.6
+ strokeColor: "#ea6d60"
+ end: 0
+ }
+
+ Arc {
+ id: arc2
+ x: 390
+ y: 226
+ width: 52
+ height: 52
+ rotation: 90
+ scale: 0.5
+ strokeWidth: 7
+ strokeColor: "#aa97f4"
+ end: 0
+ }
+
+ Timeline {
+ id: timeline
+ startFrame: 0
+ enabled: true
+ endFrame: 1000
+
+ KeyframeGroup {
+ target: arc
+ property: "end"
+
+ Keyframe {
+ value: 0
+ frame: 0
+ }
+
+ Keyframe {
+ value: 280
+ frame: 520
+ }
+
+ Keyframe {
+ value: 0
+ frame: 1000
+ }
+ }
+
+ KeyframeGroup {
+ target: arc1
+ property: "end"
+
+ Keyframe {
+ value: 0
+ frame: 0
+ }
+
+ Keyframe {
+ value: 320
+ frame: 690
+ }
+
+ Keyframe {
+ value: 0
+ frame: 1000
+ }
+ }
+
+ KeyframeGroup {
+ target: arc2
+ property: "end"
+
+ Keyframe {
+ value: 0
+ frame: 0
+ }
+
+ Keyframe {
+ value: 290
+ frame: 320
+ }
+
+ Keyframe {
+ value: 0
+ frame: 1000
+ }
+ }
+ }
+
+ PropertyAnimation {
+ id: propertyAnimation
+ target: timeline
+ property: "currentFrame"
+ running: true
+ loops: -1
+ duration: 2600
+ from: timeline.startFrame
+ to: timeline.endFrame
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Dof_Effect.qml b/src/plugins/studiowelcome/qml/splashscreen/Dof_Effect.qml
new file mode 100644
index 0000000000..010228b88b
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Dof_Effect.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtGraphicalEffects 1.0
+
+Item {
+ id: root
+ default property alias content: stack.children
+ property alias maskBlurRadius: maskedBlur.radius
+ property alias maskBlurSamples: maskedBlur.samples
+ property alias gradientStopPosition1: stop1.position
+ property alias gradientStopPosition2: stop2.position
+ property alias gradientStopPosition3: stop3.position
+ property alias gradientStopPosition4: stop4.position
+ property alias maskRotation: gradient.rotation
+
+ Row {
+ visible: true
+ id: stack
+ }
+
+ Item {
+ id: mask
+ width: stack.width
+ height: stack.height
+ visible: false
+
+ LinearGradient {
+ id: gradient
+ height: stack.height * 2
+ width: stack.width * 2
+ y: -stack.height / 2
+ x: -stack.width / 2
+ rotation: 0
+ gradient: Gradient {
+ GradientStop {
+ id: stop1
+ position: 0.2
+ color: "#ffffffff"
+ }
+ GradientStop {
+ id: stop2
+ position: 0.5
+ color: "#00ffffff"
+ }
+ GradientStop {
+ id: stop3
+ position: 0.8
+ color: "#00ffffff"
+ }
+ GradientStop {
+ id: stop4
+ position: 1.0
+ color: "#ffffffff"
+ }
+ }
+ start: Qt.point(stack.width / 2, 0)
+ end: Qt.point(stack.width + stack.width / 2, 100)
+ }
+ }
+
+ MaskedBlur {
+ id: maskedBlur
+ anchors.fill: stack
+ source: stack
+ maskSource: mask
+ radius: 32
+ samples: 16
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Image1.qml b/src/plugins/studiowelcome/qml/splashscreen/Image1.qml
new file mode 100644
index 0000000000..044a8eae84
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Image1.qml
@@ -0,0 +1,32 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Image {
+ id: slidersOn
+ scale: 0.5
+ source: "welcome_windows/splash_pngs/Slider_on.png"
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Image2.qml b/src/plugins/studiowelcome/qml/splashscreen/Image2.qml
new file mode 100644
index 0000000000..774723c23a
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Image2.qml
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Timeline 1.0
+
+Item {
+ width: 174
+ height: 200
+
+ Image {
+ id: image2
+ x: 93
+ y: 133
+ source: "welcome_windows/splash_pngs/ring_1_out.png"
+
+ Image {
+ id: image1
+ x: 13
+ y: 13
+ source: "welcome_windows/splash_pngs/ring_1_in.png"
+ }
+ }
+
+ Image {
+ id: image3
+ x: 13
+ y: 72
+ source: "welcome_windows/splash_pngs/ring_2.png"
+ }
+
+ Image {
+ id: image4
+ x: 73
+ y: 44
+ source: "welcome_windows/splash_pngs/ring_line_2.png"
+ }
+
+ Image {
+ id: image5
+ x: 103
+ y: 13
+ source: "welcome_windows/splash_pngs/ring_3.png"
+ }
+
+ Timeline {
+ id: timeline
+ startFrame: 0
+ enabled: true
+ endFrame: 1000
+
+ KeyframeGroup {
+ target: image1
+ property: "scale"
+
+ Keyframe {
+ value: 0.01
+ frame: 0
+ }
+
+ Keyframe {
+ value: 1
+ frame: 200
+ }
+ }
+
+ KeyframeGroup {
+ target: image2
+ property: "scale"
+
+ Keyframe {
+ value: 0.01
+ frame: 70
+ }
+
+ Keyframe {
+ value: 1
+ frame: 300
+ }
+ }
+
+ KeyframeGroup {
+ target: image3
+ property: "scale"
+
+ Keyframe {
+ value: 0.01
+ frame: 300
+ }
+
+ Keyframe {
+ value: 1
+ frame: 555
+ }
+ }
+
+ KeyframeGroup {
+ target: image5
+ property: "scale"
+
+ Keyframe {
+ value: 0.01
+ frame: 555
+ }
+
+ Keyframe {
+ value: 1
+ frame: 820
+ }
+ }
+ }
+
+ PropertyAnimation {
+ id: propertyAnimation
+ target: timeline
+ property: "currentFrame"
+ running: true
+ loops: -1
+ duration: 1000
+ from: timeline.startFrame
+ to: timeline.endFrame
+ }
+
+ Image {
+ id: image
+ x: 46
+ y: 105
+ source: "welcome_windows/splash_pngs/ring_line_1.png"
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml b/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml
new file mode 100644
index 0000000000..2b714a4784
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/NoShowCheckbox.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Timeline 1.0
+import QtQuick.Controls 2.12
+
+CheckBox {
+ id: do_not_show_checkBox
+ width: 268
+ height: 40
+ text: qsTr("Don't show this again")
+ spacing: 12
+
+
+ contentItem: Text {
+ text:do_not_show_checkBox.text
+ font.family: "titillium web"
+ color: "#ffffff"
+ font.pointSize: 24
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignLeft
+ leftPadding: do_not_show_checkBox.indicator.width + do_not_show_checkBox.spacing
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/RectangleMask.qml b/src/plugins/studiowelcome/qml/splashscreen/RectangleMask.qml
new file mode 100644
index 0000000000..d0652d84b0
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/RectangleMask.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Timeline 1.0
+
+Item {
+ width: 174
+ height: 200
+
+ Item {
+ id: rectangleMask
+ width: 0
+ height: 200
+ clip: true
+
+ Image {
+ id: image1
+ x: 0
+ y: 45
+ source: "welcome_windows/splash_pngs/Audio_Waves.png"
+ }
+
+ Timeline {
+ id: timeline
+ startFrame: 0
+ enabled: true
+ endFrame: 2000
+
+ KeyframeGroup {
+ target: rectangleMask
+ property: "width"
+
+ Keyframe {
+ value: 0
+ frame: 0
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.25, 0.10, 0.25, 1.00, 1, 1]
+ value: 175
+ frame: 997
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.00, 0.00, 0.58, 1.00, 1, 1]
+ value: 0
+ frame: 1998
+ }
+ }
+ }
+
+ PropertyAnimation {
+ id: propertyAnimation
+ target: timeline
+ property: "currentFrame"
+ running: true
+ loops: -1
+ duration: 2000
+ from: timeline.startFrame
+ to: timeline.endFrame
+ }
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Sequencer.qml b/src/plugins/studiowelcome/qml/splashscreen/Sequencer.qml
new file mode 100644
index 0000000000..8f3d8fc56a
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Sequencer.qml
@@ -0,0 +1,629 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Timeline 1.0
+
+Item {
+ id: blocks
+ anchors.right: parent.right
+ anchors.rightMargin: 175
+ anchors.left: parent.left
+ anchors.leftMargin: 0
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 77
+ anchors.top: parent.top
+ anchors.topMargin: 0
+
+ Image {
+ id: sequencer
+ width: 175
+ height: 77
+ clip: false
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/splash_pngs/Step_sequencer.png"
+
+ Image {
+ id: blue_seq_block2
+ x: 3
+ y: 16
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/blue_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: peach_seq_block
+ x: 49
+ y: 24
+ width: 10
+ height: 5
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/sequencer_images/peach_seq.png"
+ }
+
+ Image {
+ id: pink_seq_block
+ x: 26
+ y: 23
+ width: 10
+ height: 5
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/sequencer_images/pink_seq.png"
+ }
+
+ Image {
+ id: blue_seq_block
+ x: 83
+ y: 23
+ width: 10
+ height: 5
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/sequencer_images/blue_seq.png"
+ }
+
+ Image {
+ id: pink_seq_block1
+ x: 26
+ y: 16
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/pink_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: peach_seq_block1
+ x: 15
+ y: 31
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/peach_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: pink_seq_block2
+ x: 49
+ y: 16
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/pink_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: blue_seq_block3
+ x: 61
+ y: 29
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/blue_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: pink_seq_block3
+ x: 106
+ y: 23
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/pink_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: pink_seq_block4
+ x: 129
+ y: 16
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/pink_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: blue_seq_block4
+ x: 106
+ y: 16
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/blue_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: peach_seq_block2
+ x: 118
+ y: 30
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/peach_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: peach_seq_block3
+ x: 141
+ y: 30
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/peach_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+ }
+
+ Image {
+ id: blue_seq_block1
+ x: 3
+ y: 23
+ width: 10
+ height: 5
+ source: "welcome_windows/sequencer_images/blue_seq.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Sequencer_Bars {
+ id: seq_bars
+ x: -7
+ y: 39
+ width: 199
+ height: 69
+ }
+
+ Timeline {
+ id: timeline
+ enabled: true
+ startFrame: 0
+ endFrame: 1000
+
+ KeyframeGroup {
+ target: blue_seq_block2
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 52
+ value: 0
+ }
+
+ Keyframe {
+ frame: 53
+ value: 1
+ }
+
+ Keyframe {
+ frame: 300
+ value: 1
+ }
+
+ Keyframe {
+ frame: 301
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: blue_seq_block1
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 100
+ value: 0
+ }
+
+ Keyframe {
+ frame: 101
+ value: 1
+ }
+
+ Keyframe {
+ frame: 340
+ value: 1
+ }
+
+ Keyframe {
+ frame: 341
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: peach_seq_block1
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 175
+ value: 0
+ }
+
+ Keyframe {
+ frame: 176
+ value: 1
+ }
+
+ Keyframe {
+ frame: 432
+ value: 1
+ }
+
+ Keyframe {
+ frame: 435
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: pink_seq_block1
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 222
+ value: 0
+ }
+
+ Keyframe {
+ frame: 227
+ value: 1
+ }
+
+ Keyframe {
+ frame: 508
+ value: 1
+ }
+
+ Keyframe {
+ frame: 512
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: pink_seq_block
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 247
+ value: 0
+ }
+
+ Keyframe {
+ frame: 251
+ value: 1
+ }
+
+ Keyframe {
+ frame: 524
+ value: 1
+ }
+
+ Keyframe {
+ frame: 529
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: pink_seq_block2
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 286
+ value: 0
+ }
+
+ Keyframe {
+ frame: 290
+ value: 1
+ }
+
+ Keyframe {
+ frame: 575
+ value: 1
+ }
+
+ Keyframe {
+ frame: 580
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: peach_seq_block
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 352
+ value: 0
+ }
+
+ Keyframe {
+ frame: 357
+ value: 1
+ }
+
+ Keyframe {
+ frame: 647
+ value: 1
+ }
+
+ Keyframe {
+ frame: 652
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: blue_seq_block3
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 419
+ value: 0
+ }
+
+ Keyframe {
+ frame: 424
+ value: 1
+ }
+
+ Keyframe {
+ frame: 695
+ value: 1
+ }
+
+ Keyframe {
+ frame: 699
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: blue_seq_block
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 461
+ value: 0
+ }
+
+ Keyframe {
+ frame: 756
+ value: 1
+ }
+
+ Keyframe {
+ frame: 761
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: blue_seq_block4
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 502
+ value: 0
+ }
+
+ Keyframe {
+ frame: 508
+ value: 1
+ }
+
+ Keyframe {
+ frame: 799
+ value: 1
+ }
+
+ Keyframe {
+ frame: 804
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: pink_seq_block3
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 525
+ value: 0
+ }
+
+ Keyframe {
+ frame: 530
+ value: 1
+ }
+
+ Keyframe {
+ frame: 840
+ value: 1
+ }
+
+ Keyframe {
+ frame: 848
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: peach_seq_block2
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 661
+ value: 0
+ }
+
+ Keyframe {
+ frame: 667
+ value: 1
+ }
+
+ Keyframe {
+ frame: 901
+ value: 1
+ }
+
+ Keyframe {
+ frame: 906
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: pink_seq_block4
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 756
+ value: 0
+ }
+
+ Keyframe {
+ frame: 760
+ value: 1
+ }
+
+ Keyframe {
+ frame: 955
+ value: 1
+ }
+
+ Keyframe {
+ frame: 961
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: peach_seq_block3
+ property: "opacity"
+
+ Keyframe {
+ frame: 0
+ value: 0
+ }
+
+ Keyframe {
+ frame: 831
+ value: 0
+ }
+
+ Keyframe {
+ frame: 837
+ value: 1
+ }
+
+ Keyframe {
+ frame: 989
+ value: 1
+ }
+
+ Keyframe {
+ frame: 999
+ value: 0
+ }
+ }
+ }
+
+ PropertyAnimation {
+ id: propertyAnimation
+ target: timeline
+ property: "currentFrame"
+ running: true
+ duration: 1200
+ loops: -1
+ from: timeline.startFrame
+ to: timeline.endFrame
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Sequencer_Bars.qml b/src/plugins/studiowelcome/qml/splashscreen/Sequencer_Bars.qml
new file mode 100644
index 0000000000..477cd00b8c
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Sequencer_Bars.qml
@@ -0,0 +1,643 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Timeline 1.0
+
+Item {
+ id: item1
+ width: 200
+ height: 100
+
+ Rectangle {
+ id: mask_1
+ x: 0
+ y: 8
+ width: 7
+ height: 4
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_1
+ width: 72
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ source: "welcome_windows/sequencer_images/seq_bar_1.png"
+ }
+ }
+
+ Rectangle {
+ id: mask_2
+ x: 0
+ y: 13
+ width: 6
+ height: 6
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_2
+ width: 55
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ source: "welcome_windows/sequencer_images/seq_bar_2.png"
+ }
+ }
+
+ Rectangle {
+ id: mask_3
+ x: 0
+ y: 21
+ width: 50
+ height: 5
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_3
+ x: 8
+ y: 0
+ width: 36
+ height: 5
+ source: "welcome_windows/sequencer_images/seq_bar_3.png"
+ }
+ }
+
+ Rectangle {
+ id: mask_4
+ x: 0
+ y: 28
+ width: 99
+ height: 4
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_4
+ width: 79
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ source: "welcome_windows/sequencer_images/seq_bar_4.png"
+ }
+ }
+
+ Rectangle {
+ id: mask_5
+ x: 115
+ y: 8
+ width: 85
+ height: 4
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_5
+ width: 72
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ source: "welcome_windows/sequencer_images/seq_bar_5.png"
+ }
+ }
+
+ Rectangle {
+ id: mask_6
+ x: 115
+ y: 13
+ width: 69
+ height: 6
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_6
+ width: 45
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ source: "welcome_windows/sequencer_images/seq_bar_6.png"
+ }
+ }
+
+ Rectangle {
+ id: mask_7
+ x: 115
+ y: 21
+ width: 4
+ height: 5
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_7
+ width: 64
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ source: "welcome_windows/sequencer_images/seq_bar_7.png"
+ }
+ }
+
+ Timeline {
+ id: timeline
+ enabled: true
+ startFrame: 0
+ endFrame: 1000
+
+ KeyframeGroup {
+ target: mask_1
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 6
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.25, 0.46, 0.45, 0.94, 1, 1]
+ frame: 499
+ value: 87
+ }
+
+ Keyframe {
+ frame: 999
+ value: 6
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_1
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 4
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.25, 0.46, 0.45, 0.94, 1, 1]
+ frame: 499
+ value: 4
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_2
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 6
+ }
+
+ Keyframe {
+ frame: 151
+ value: 7
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.55, 0.08, 0.68, 0.53, 1, 1]
+ frame: 677
+ value: 64
+ }
+
+ Keyframe {
+ frame: 999
+ value: 6
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_2
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 6
+ }
+
+ Keyframe {
+ frame: 151
+ value: 6
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.55, 0.08, 0.68, 0.53, 1, 1]
+ frame: 677
+ value: 6
+ }
+
+ Keyframe {
+ frame: 999
+ value: 6
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_3
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 6
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.25, 0.25, 0.75, 0.75, 1, 1]
+ frame: 317
+ value: 47
+ }
+
+ Keyframe {
+ frame: 999
+ value: 6
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.17, 0.84, 0.44, 1.00, 1, 1]
+ frame: 544
+ value: 50
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_3
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 5
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.25, 0.25, 0.75, 0.75, 1, 1]
+ frame: 317
+ value: 5
+ }
+
+ Keyframe {
+ frame: 999
+ value: 5
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.17, 0.84, 0.44, 1.00, 1, 1]
+ frame: 544
+ value: 5
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_4
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 6
+ }
+
+ Keyframe {
+ frame: 243
+ value: 6
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.00, 0.00, 0.20, 1.00, 1, 1]
+ frame: 682
+ value: 92
+ }
+
+ Keyframe {
+ frame: 755
+ value: 90
+ }
+
+ Keyframe {
+ frame: 999
+ value: 6
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_4
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 4
+ }
+
+ Keyframe {
+ frame: 243
+ value: 4
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.00, 0.00, 0.20, 1.00, 1, 1]
+ frame: 682
+ value: 4
+ }
+
+ Keyframe {
+ frame: 755
+ value: 4
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_5
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 3
+ }
+
+ Keyframe {
+ frame: 182
+ value: 3
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.77, 0.00, 0.17, 1.00, 1, 1]
+ frame: 462
+ value: 85
+ }
+
+ Keyframe {
+ frame: 625
+ value: 85
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_5
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 4
+ }
+
+ Keyframe {
+ frame: 182
+ value: 4
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.77, 0.00, 0.17, 1.00, 1, 1]
+ frame: 462
+ value: 4
+ }
+
+ Keyframe {
+ frame: 625
+ value: 4
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_6
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 3
+ }
+
+ Keyframe {
+ frame: 364
+ value: 3
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.19, 1.00, 0.22, 1.00, 1, 1]
+ frame: 695
+ value: 54
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_6
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 6
+ }
+
+ Keyframe {
+ frame: 364
+ value: 6
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.19, 1.00, 0.22, 1.00, 1, 1]
+ frame: 695
+ value: 6
+ }
+
+ Keyframe {
+ frame: 999
+ value: 6
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_7
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 3
+ }
+
+ Keyframe {
+ frame: 444
+ value: 3
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.00, 0.00, 0.20, 1.00, 1, 1]
+ frame: 759
+ value: 77
+ }
+
+ Keyframe {
+ frame: 845
+ value: 77
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_7
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 5
+ }
+
+ Keyframe {
+ frame: 444
+ value: 5
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.00, 0.00, 0.20, 1.00, 1, 1]
+ frame: 759
+ value: 5
+ }
+
+ Keyframe {
+ frame: 845
+ value: 5
+ }
+
+ Keyframe {
+ frame: 999
+ value: 5
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_8
+ property: "width"
+ Keyframe {
+ frame: 0
+ value: 3
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.55, 0.06, 0.68, 0.19, 1, 1]
+ frame: 303
+ value: 85
+ }
+
+ Keyframe {
+ frame: 516
+ value: 85
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+
+ KeyframeGroup {
+ target: mask_8
+ property: "height"
+ Keyframe {
+ frame: 0
+ value: 4
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.55, 0.06, 0.68, 0.19, 1, 1]
+ frame: 303
+ value: 4
+ }
+
+ Keyframe {
+ frame: 516
+ value: 4
+ }
+
+ Keyframe {
+ frame: 999
+ value: 4
+ }
+ }
+ }
+
+ PropertyAnimation {
+ id: propertyAnimation
+ target: timeline
+ property: "currentFrame"
+ running: true
+ duration: 3400
+ loops: -1
+ from: timeline.startFrame
+ to: timeline.endFrame
+ }
+
+ Rectangle {
+ id: mask_8
+ x: 115
+ y: 28
+ width: 85
+ height: 4
+ color: "#00000000"
+ clip: true
+
+ Image {
+ id: bar_8
+ x: 5
+ y: 0
+ width: 72
+ height: 4
+ source: "welcome_windows/sequencer_images/seq_bar_8.png"
+ }
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/SlidersTogether.qml b/src/plugins/studiowelcome/qml/splashscreen/SlidersTogether.qml
new file mode 100644
index 0000000000..c05c6efce9
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/SlidersTogether.qml
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Timeline 1.0
+
+Item {
+ width: 174
+ height: 200
+
+ Item {
+ id: rectangleMask
+ x: -1
+ y: -2
+ width: 31
+ height: 49
+ clip: true
+
+ Item {
+ id: rectangle
+ x: 0
+ y: 0
+ width: 200
+ height: 200
+ clip: true
+
+ Image {
+ id: slidersTogether
+ scale: 0.5
+ source: "welcome_windows/splash_pngs/Sliders_together.png"
+ }
+ }
+ }
+
+ Timeline {
+ id: timeline
+ startFrame: 0
+ enabled: true
+ endFrame: 1000
+
+ KeyframeGroup {
+ target: rectangleMask
+ property: "width"
+
+ Keyframe {
+ value: 30
+ frame: 0
+ }
+
+ Keyframe {
+ easing.bezierCurve: [0.55, 0.06, 0.68, 0.19, 1, 1]
+ value: 106
+ frame: 740
+ }
+
+ Keyframe {
+ value: 0
+ frame: 1000
+ }
+ }
+
+ KeyframeGroup {
+ target: rectangleMask
+ property: "height"
+ Keyframe {
+ value: 49
+ frame: 505
+ }
+ }
+ }
+
+ PropertyAnimation {
+ id: propertyAnimation
+ target: timeline
+ property: "currentFrame"
+ running: true
+ loops: -1
+ duration: 1300
+ from: timeline.startFrame
+ to: timeline.endFrame
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Splash_Image25d.qml b/src/plugins/studiowelcome/qml/splashscreen/Splash_Image25d.qml
new file mode 100644
index 0000000000..3d54304195
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Splash_Image25d.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.3
+
+Rectangle {
+ id: splashBackground
+ width: 460
+ height: 480
+ color: "#11102d"
+
+ layer.enabled: true
+ layer.textureSize: Qt.size(width * 2, height * 2)
+ layer.smooth: true
+
+ Item {
+ id: composition
+ width: 460
+ height: 480
+
+ layer.enabled: true
+ layer.textureSize: Qt.size(width * 2, height * 2)
+ layer.smooth: true
+
+ Splash_Image2d_png {
+ x: 25
+ y: 15
+ antialiasing: false
+ scale: 1.4
+ transform: Matrix4x4 {
+ matrix: Qt.matrix4x4(1.12606, 0.06371, 0, 0, 0.26038, 0.90592,
+ 0, 0, 0.00000, 0.0000, 1.0, 0,
+ 0.00121, -0.00009, 0.0, 1)
+ }
+ }
+ }
+
+ Image {
+ id: highlight
+ x: -56
+ y: -19
+ width: 520
+ height: 506
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/highlight.png"
+ }
+
+ Image {
+ id: hand
+ x: 245
+ y: 227
+ width: 224
+ height: 264
+ visible: true
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/hand.png"
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Splash_Image2d_png.qml b/src/plugins/studiowelcome/qml/splashscreen/Splash_Image2d_png.qml
new file mode 100644
index 0000000000..5f07be1672
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Splash_Image2d_png.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: splashBackground
+ width: 460
+ height: 480
+ color: "#00ffffff"
+ visible: true
+
+ Image {
+ id: image
+ x: -228
+ y: -66
+ scale: 0.5
+ source: "welcome_windows/splash_pngs/UI_Background.png"
+ }
+
+ RectangleMask {
+ id: rectangleMask
+ x: 23
+ y: 156
+ width: 209
+ height: 199
+ scale: 0.5
+ }
+
+ Image1 {
+ id: sliderBackground
+ x: 155
+ y: 267
+ height: 86
+ }
+
+ SlidersTogether {
+ id: slidersTogether
+ x: 185
+ y: 295
+ }
+
+ Image {
+ id: slidersOff
+ x: 191
+ y: 316
+ scale: 0.5
+ source: "welcome_windows/splash_pngs/sliders_off.png"
+ }
+
+ Image2 {
+ id: rings
+ x: 84
+ y: 227
+ scale: 0.5
+ }
+
+ ArcAnimation {
+ id: arcAnimation
+ x: 9
+ y: 13
+ scale: 0.5
+ }
+
+ Sequencer {
+ id: sequencer
+ x: 152
+ y: 119
+ anchors.rightMargin: 119
+ anchors.bottomMargin: 264
+ anchors.leftMargin: 154
+ anchors.topMargin: 108
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml
new file mode 100644
index 0000000000..c00bde1ce8
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/Welcome_splash.qml
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Controls 2.3
+import StudioFonts 1.0
+import QtQuick.Layouts 1.0
+import projectmodel 1.0
+
+Image {
+ id: welcome_splash
+ width: 800
+ height: 480
+ source: "welcome_windows/welcome_1.png"
+
+ signal goNext
+ signal closeClicked
+
+ property alias doNotShowAgain: do_not_show_checkBox.checked
+ property bool loadingPlugins: true
+
+ Image {
+ id: logo
+ x: 14
+ y: 8
+ width: 76
+ height: 66
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/logo.png"
+ }
+
+ Text {
+ id: qt_design_studio
+ x: 13
+ y: 93
+ width: 250
+ height: 55
+ color: "#4cd265"
+ text: qsTr("Qt Design Studio")
+ font.pixelSize: 36
+ font.family: StudioFonts.titilliumWeb_light
+ }
+
+ Text {
+ id: software_for_ui
+ x: 15
+ y: 141
+ width: 250
+ height: 30
+ color: "#ffffff"
+ text: qsTr("Software for UI and UX Designers")
+ renderType: Text.QtRendering
+ font.pixelSize: 18
+ font.family: StudioFonts.titilliumWeb_light
+ }
+
+ Text {
+ id: copyright
+ x: 15
+ y: 183
+ width: 270
+ height: 24
+ color: "#ffffff"
+ text: qsTr("Copyright 2008 - 2019 The Qt Company")
+ font.pixelSize: 16
+ font.family: StudioFonts.titilliumWeb_light
+ }
+
+ Text {
+ id: all_rights_reserved
+ x: 15
+ y: 207
+ width: 250
+ height: 24
+ color: "#ffffff"
+ text: qsTr("All Rights Reserved")
+ font.pixelSize: 16
+ font.family: StudioFonts.titilliumWeb_light
+ }
+
+ Text {
+ id: marketing_1
+ x: 16
+ y: 302
+ width: 355
+ height: 31
+ color: "#ffffff"
+ text: qsTr("Multi-paradigm language for creating highly dynamic applications.")
+ wrapMode: Text.WordWrap
+ font.family: StudioFonts.titilliumWeb_light
+ font.pixelSize: 12
+ font.wordSpacing: 0
+ }
+
+ Text {
+ id: marketing_2
+ x: 16
+ y: 323
+ width: 311
+ height: 31
+ color: "#ffffff"
+ text: qsTr("Run your concepts and prototypes on your final hardware.")
+ wrapMode: Text.WordWrap
+ font.family: StudioFonts.titilliumWeb_light
+ font.pixelSize: 12
+ font.wordSpacing: 0
+ }
+
+ Text {
+ id: marketing_3
+ x: 16
+ y: 344
+ width: 311
+ height: 31
+ color: "#ffffff"
+ text: qsTr("Seamless integration between designer and developer.")
+ wrapMode: Text.WordWrap
+ font.family: StudioFonts.titilliumWeb_light
+ font.pixelSize: 12
+ font.wordSpacing: 0
+ }
+
+ Dof_Effect {
+ id: dof_Effect
+ x: 358
+ width: 442
+ height: 480
+ visible: true
+ maskBlurSamples: 64
+ maskBlurRadius: 32
+ gradientStopPosition4: 1.3
+ gradientStopPosition3: 0.9
+ gradientStopPosition2: 0.6
+ gradientStopPosition1: 0
+
+ Splash_Image25d {
+ id: animated_artwork
+ x: 358
+ y: 0
+ width: 442
+ height: 480
+ clip: true
+ }
+ }
+
+ Image {
+ id: close_window
+ x: 779
+ y: 5
+ width: 13
+ height: 13
+ fillMode: Image.PreserveAspectFit
+ source: "welcome_windows/close.png"
+ opacity: area.containsMouse ? 1 : 0.8
+ MouseArea {
+ id: area
+ hoverEnabled: true
+ anchors.fill: parent
+ anchors.margins: -10
+ onClicked: welcome_splash.closeClicked()
+ }
+ }
+
+ NoShowCheckbox {
+ id: do_not_show_checkBox
+ x: -47
+ y: 430
+ padding: 0
+ scale: 0.5
+ }
+
+
+ RowLayout {
+ x: 16
+ y: 254
+
+ visible: welcome_splash.loadingPlugins
+
+ Text {
+ id: text1
+ color: "#ffffff"
+ text: qsTr("%")
+ font.pixelSize: 12
+ RotationAnimator {
+ target: text1
+ from: 0
+ to: 360
+ duration: 1800
+ running: true
+ loops: -1
+ }
+ }
+
+ Text {
+ id: loading_progress
+ color: "#ffffff"
+ text: qsTr("Loading Plugins")
+ font.family: StudioFonts.titilliumWeb_light
+ font.pixelSize: 16
+ }
+
+ Text {
+ id: text2
+ color: "#ffffff"
+ text: qsTr("%")
+ font.pixelSize: 12
+ RotationAnimator {
+ target: text2
+ from: 0
+ to: 360
+ duration: 2000
+ running: true
+ loops: -1
+ }
+ }
+ }
+
+ Text {
+ id: all_rights_reserved1
+ x: 15
+ y: 75
+ color: "#ffffff"
+ text: qsTr("Community Edition")
+ font.pixelSize: 13
+ font.family: StudioFonts.titilliumWeb_light
+ visible: projectModel.communityVersion
+ ProjectModel {
+ id: projectModel
+ }
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/main.qml b/src/plugins/studiowelcome/qml/splashscreen/main.qml
new file mode 100644
index 0000000000..be88704784
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/main.qml
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ id: root
+ width: 800
+ height: 480
+
+ signal closeClicked
+ signal checkBoxToggled
+
+ property alias doNotShowAgain: welcome_splash.doNotShowAgain
+ property alias loadingPlugins: welcome_splash.loadingPlugins
+
+ Welcome_splash {
+ id: welcome_splash
+ x: 0
+ y: 0
+ antialiasing: true
+ onCloseClicked: root.closeClicked()
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_screens.qmlproject b/src/plugins/studiowelcome/qml/splashscreen/welcome_screens.qmlproject
new file mode 100644
index 0000000000..de393d88b0
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_screens.qmlproject
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QmlProject 1.1
+
+Project {
+ mainFile: "main.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ importPaths: [ "imports", "mockData", "../../../../share/3rdparty/studiofonts" ]
+
+ Environment {
+ QT_AUTO_SCREEN_SCALE_FACTOR: "1"
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/close.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/close.png
new file mode 100644
index 0000000000..940e1687fa
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/close.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/hand.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/hand.png
new file mode 100644
index 0000000000..73944a4bad
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/hand.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/highlight.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/highlight.png
new file mode 100644
index 0000000000..d9e6db2b05
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/highlight.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/logo.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/logo.png
new file mode 100644
index 0000000000..347beb789c
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/logo.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/blue_seq.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/blue_seq.png
new file mode 100644
index 0000000000..7697fc4747
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/blue_seq.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/peach_seq.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/peach_seq.png
new file mode 100644
index 0000000000..28fd238433
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/peach_seq.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/pink_seq.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/pink_seq.png
new file mode 100644
index 0000000000..714f1f79d4
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/pink_seq.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_1.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_1.png
new file mode 100644
index 0000000000..6ac5b5c43f
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_1.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_2.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_2.png
new file mode 100644
index 0000000000..eb942aadad
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_2.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_3.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_3.png
new file mode 100644
index 0000000000..b33feda2a2
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_3.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_4.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_4.png
new file mode 100644
index 0000000000..3e6a6ea817
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_4.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_5.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_5.png
new file mode 100644
index 0000000000..471f62da7d
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_5.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_6.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_6.png
new file mode 100644
index 0000000000..b6612b192b
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_6.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_7.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_7.png
new file mode 100644
index 0000000000..7bffeb9921
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_7.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_8.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_8.png
new file mode 100644
index 0000000000..0fe2a943db
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/sequencer_images/seq_bar_8.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Audio_Waves.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Audio_Waves.png
new file mode 100644
index 0000000000..177a13e6ef
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Audio_Waves.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Slider_on.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Slider_on.png
new file mode 100644
index 0000000000..326bb72d2e
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Slider_on.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Sliders_together.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Sliders_together.png
new file mode 100644
index 0000000000..870eb34e1e
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Sliders_together.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Step_sequencer.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Step_sequencer.png
new file mode 100644
index 0000000000..79e05d8ada
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/Step_sequencer.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/UI_Background.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/UI_Background.png
new file mode 100644
index 0000000000..edf9debd10
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/UI_Background.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_in.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_in.png
new file mode 100644
index 0000000000..0388a99ea0
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_in.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_out.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_out.png
new file mode 100644
index 0000000000..662fcb0fe8
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_1_out.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_2.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_2.png
new file mode 100644
index 0000000000..1bc54f8827
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_2.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_3.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_3.png
new file mode 100644
index 0000000000..df8c7b5c70
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_3.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_1.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_1.png
new file mode 100644
index 0000000000..022a6bc08d
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_1.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_2.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_2.png
new file mode 100644
index 0000000000..f857c92b74
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/ring_line_2.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/sliders_off.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/sliders_off.png
new file mode 100644
index 0000000000..9e8c2c7bdf
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/splash_pngs/sliders_off.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/welcome_1.png b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/welcome_1.png
new file mode 100644
index 0000000000..58b68511be
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/splashscreen/welcome_windows/welcome_1.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/AccountImage.qml b/src/plugins/studiowelcome/qml/welcomepage/AccountImage.qml
new file mode 100644
index 0000000000..719ff05546
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/AccountImage.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import welcome 1.0
+import StudioFonts 1.0
+
+Image {
+ id: account_icon
+
+ source: "images/" + (mouseArea.containsMouse ? "icon_hover.png" : "icon_default.png")
+
+ Text {
+ id: account
+ color: mouseArea.containsMouse ? Constants.textHoverColor
+ : Constants.textDefaultColor
+ text: qsTr("Account")
+ anchors.top: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.family: StudioFonts.titilliumWeb_regular
+ font.pixelSize: 16
+ renderType: Text.NativeRendering
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ anchors.margins: -25
+ hoverEnabled: true
+
+ onClicked: Qt.openUrlExternally("https://login.qt.io/login/")
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml b/src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml
new file mode 100644
index 0000000000..3f8ce9bc82
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+ListModel {
+ ListElement {
+ projectName: "ClusterTutorial"
+ qmlFileName: "Cluster_Art.ui.qml"
+ thumbnail: "images/tutorialclusterdemo_thumbnail.png"
+ displayName: "Cluster Tutorial"
+ }
+
+ ListElement {
+ projectName: "CoffeeMachine"
+ qmlFileName: "ApplicationFlowForm.ui.qml"
+ thumbnail: "images/coffeemachinedemo_thumbnail.png"
+ displayName: "Coffee Machine"
+ }
+
+ ListElement {
+ projectName: "SideMenu"
+ qmlFileName: "MainFile.ui.qml"
+ thumbnail: "images/sidemenu_demo.png"
+ displayName: "Side Menu"
+ }
+
+ ListElement {
+ projectName: "WebinarDemo"
+ qmlFileName: "MainApp.ui.qml"
+ thumbnail: "images/webinardemo_thumbnail.png"
+ displayName: "Webinar Demo"
+ }
+
+ ListElement {
+ projectName: "EBikeDesign"
+ qmlFileName: "Screen01.ui.qml"
+ thumbnail: "images/ebike_demo_thumbnail.png"
+ displayName: "E-Bike Design"
+ }
+
+ ListElement {
+ projectName: "ProgressBar"
+ qmlFileName: "ProgressBar.ui.qml"
+ thumbnail: "images/progressbar_demo.png"
+ displayName: "Progress Bar"
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml
new file mode 100644
index 0000000000..e160a1f70e
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Timeline 1.0
+import welcome 1.0
+import StudioFonts 1.0
+
+Item {
+ visible: true
+ width: 270
+ height: 175
+ property alias imageSource: image.source
+ property alias labelText: label.text
+
+ onVisibleChanged: {
+ animateOpacity.start()
+ animateScale.start()
+ }
+
+ NumberAnimation {
+ id: animateOpacity
+ property: "opacity"
+ from: 0
+ to: 1.0
+ duration: 400
+ }
+ NumberAnimation {
+ id: animateScale
+ property: "scale"
+ from: 0
+ to: 1.0
+ duration: 400
+ }
+
+ Rectangle {
+ id: rectangle
+ x: 0
+ y: 0
+ width: 270
+ height: 146
+
+ MouseArea {
+ x: 17
+ y: 12
+ height: 125
+ anchors.bottomMargin: -label.height
+ anchors.fill: parent
+ hoverEnabled: true
+ onHoveredChanged: {
+ if (saturationEffect.desaturation === 1)
+ saturationEffect.desaturation = 0
+ if (saturationEffect.desaturation === 0)
+ saturationEffect.desaturation = 1
+ if (saturationEffect.desaturation === 0)
+ rectangle.color = "#262728"
+ if (saturationEffect.desaturation === 1)
+ rectangle.color = "#404244"
+ if (saturationEffect.desaturation === 0)
+ label.color = "#686868"
+ if (saturationEffect.desaturation === 1)
+ label.color = Constants.textDefaultColor
+ }
+
+ onExited: {
+ saturationEffect.desaturation = 1
+ rectangle.color = "#262728"
+ label.color = "#686868"
+ }
+ }
+ }
+
+ SaturationEffect {
+ id: saturationEffect
+ x: 15
+ y: 10
+ width: 240
+ height: 125
+ desaturation: 0
+ antialiasing: true
+ Behavior on desaturation {
+ PropertyAnimation {
+ }
+ }
+
+ Image {
+ id: image
+ width: 240
+ height: 125
+ fillMode: Image.PreserveAspectFit
+ }
+ }
+
+ Timeline {
+ id: animation
+ startFrame: 0
+ enabled: true
+ endFrame: 1000
+
+ KeyframeGroup {
+ target: saturationEffect
+ property: "desaturation"
+
+ Keyframe {
+ frame: 0
+ value: 1
+ }
+
+ Keyframe {
+ frame: 1000
+ value: 0
+ }
+ }
+
+ KeyframeGroup {
+ target: label
+ property: "color"
+
+ Keyframe {
+ value: "#686868"
+ frame: 0
+ }
+
+ Keyframe {
+ value: Constants.textDefaultColor
+ frame: 1000
+ }
+ }
+
+ KeyframeGroup {
+ target: rectangle
+ property: "color"
+
+ Keyframe {
+ value: "#262728"
+ frame: 0
+ }
+
+ Keyframe {
+ value: "#404244"
+ frame: 1000
+ }
+ }
+ }
+
+ PropertyAnimation {
+ id: propertyAnimation
+ target: animation
+ property: "currentFrame"
+ running: false
+ duration: 1000
+ to: animation.endFrame
+ from: animation.startFrame
+ loops: 1
+ }
+
+ Text {
+ id: label
+ x: 1
+ y: 145
+ color: "#686868"
+
+ renderType: Text.NativeRendering
+ font.pixelSize: 14
+ font.family: StudioFonts.titilliumWeb_regular
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/MyButton.qml b/src/plugins/studiowelcome/qml/welcomepage/MyButton.qml
new file mode 100644
index 0000000000..304adc31c3
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/MyButton.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.3
+import welcome 1.0
+import StudioFonts 1.0
+
+Button {
+ id: button
+
+ property color hoverColor: Constants.textHoverColor
+ property color defaultColor: Constants.textDefaultColor
+ property color checkedColor: Constants.textDefaultColor
+
+ contentItem: Text {
+ id: textButton
+ text: button.text
+ color: checked ? button.checkedColor :
+ button.hovered ? button.hoverColor :
+ button.defaultColor
+ font.family: StudioFonts.titilliumWeb_regular
+ renderType: Text.NativeRendering
+ font.pixelSize: 18
+ }
+
+ background: Item {
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/MyTabButton.qml b/src/plugins/studiowelcome/qml/welcomepage/MyTabButton.qml
new file mode 100644
index 0000000000..420b3a2b67
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/MyTabButton.qml
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.9
+
+MyButton {
+ checkable: true
+ autoExclusive: true
+ defaultColor: "#686868"
+ hoverColor: "#79797C"
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml b/src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml
new file mode 100644
index 0000000000..6faf3a6554
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import welcome 1.0
+
+GridView {
+ id: root
+ cellHeight: 180
+ cellWidth: 285
+
+ clip: true
+
+ signal itemSelected(int index, variant item)
+
+ delegate: HoverOverDesaturate {
+ id: hoverOverDesaturate
+ imageSource: typeof(thumbnail) === "undefined" ? "images/thumbnail_test.png" : thumbnail;
+ labelText: displayName
+
+ SequentialAnimation {
+ id: animation
+ running: hoverOverDesaturate.visible
+
+ PropertyAction {
+ target: hoverOverDesaturate
+ property: "scale"
+ value: 0.0
+ }
+ PauseAnimation {
+ duration: model.index > 0 ? 100 * model.index : 0
+ }
+ NumberAnimation {
+ target: hoverOverDesaturate
+ property: "scale"
+ from: 0.0
+ to: 1.0
+ duration: 200
+ easing.type: Easing.InOutExpo
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.itemSelected(index, root.model.get(index))
+ }
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/SaturationEffect.qml b/src/plugins/studiowelcome/qml/welcomepage/SaturationEffect.qml
new file mode 100644
index 0000000000..4f85e681a4
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/SaturationEffect.qml
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtGraphicalEffects 1.0
+
+Item {
+ id: root
+
+ property real desaturation: 1.0
+ layer.enabled: true
+ layer.effect: Desaturate {
+ desaturation: root.desaturation
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/TutorialsModel.qml b/src/plugins/studiowelcome/qml/welcomepage/TutorialsModel.qml
new file mode 100644
index 0000000000..aa797b0752
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/TutorialsModel.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+ListModel {
+ ListElement {
+ displayName: "Learn to use Qt Design Studio (Part 1)"
+ thumbnail: "images/tutorial1.png"
+ url: "https://www.youtube.com/watch?v=aV6kFxH3Xws"
+ }
+
+ ListElement {
+ displayName: "Learn to use Qt Design Studio (Part 2)"
+ thumbnail: "images/tutorial2.png"
+ url: "https://www.youtube.com/watch?v=Z3uPoe-4UAw"
+ }
+
+ ListElement {
+ displayName: "Learn to use Qt Design Studio (Part 3)"
+ thumbnail: "images/tutorial3.png"
+ url: "https://www.youtube.com/watch?v=9AjvxoeqAKo"
+ }
+
+ ListElement {
+ displayName: "Learn to use Qt Design Studio (Part 4)"
+ thumbnail: "images/tutorial4.png"
+ url: "https://www.youtube.com/watch?v=8pJpdMwLaAg"
+ }
+
+ ListElement {
+ displayName: "Learn to use Qt Design Studio (Part 5)"
+ thumbnail: "images/tutorial5.png"
+ url: "https://www.youtube.com/watch?v=U91nAFReAoU"
+ }
+
+ ListElement {
+ displayName: "The Designer Tool Developers Love"
+ thumbnail: "images/webinar1.png"
+ url: "https://youtu.be/gU_tDbebAzM"
+ }
+
+ ListElement {
+ displayName: "From Photoshop to Prototype"
+ thumbnail: "images/webinar2.png"
+ url: "https://youtu.be/ZzbucmQPU44"
+ }
+
+ ListElement {
+ displayName: "Qt for Designers and Developers"
+ thumbnail: "images/designer_and_developers.png"
+ url: "https://www.youtube.com/watch?v=EgjCvZWEPWk"
+ }
+
+ ListElement {
+ displayName: "Qt Design Studio: 1.0 and Ready to Go!"
+ thumbnail: "images/ready_to_go.png"
+ url: "https://www.youtube.com/watch?v=i9ToZ_04kTk"
+ }
+
+ ListElement {
+ displayName: "QTWS - Designer and Developer Workflow"
+ thumbnail: "images/qtws_video_thumbnail.png"
+ url: "https://www.youtube.com/watch?v=4ug0EUdS2RM"
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/coffeemachinedemo_thumbnail.png b/src/plugins/studiowelcome/qml/welcomepage/images/coffeemachinedemo_thumbnail.png
new file mode 100644
index 0000000000..565b1d62b1
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/coffeemachinedemo_thumbnail.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/designer_and_developers.png b/src/plugins/studiowelcome/qml/welcomepage/images/designer_and_developers.png
new file mode 100644
index 0000000000..870a597282
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/designer_and_developers.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/ebike_demo_thumbnail.png b/src/plugins/studiowelcome/qml/welcomepage/images/ebike_demo_thumbnail.png
new file mode 100644
index 0000000000..67cf3b9bff
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/ebike_demo_thumbnail.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/icon_default.png b/src/plugins/studiowelcome/qml/welcomepage/images/icon_default.png
new file mode 100644
index 0000000000..82b852a408
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/icon_default.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/icon_hover.png b/src/plugins/studiowelcome/qml/welcomepage/images/icon_hover.png
new file mode 100644
index 0000000000..693fdaf7b5
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/icon_hover.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/progressbar_demo.png b/src/plugins/studiowelcome/qml/welcomepage/images/progressbar_demo.png
new file mode 100644
index 0000000000..b1af2d8f41
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/progressbar_demo.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/qtws_video_thumbnail.png b/src/plugins/studiowelcome/qml/welcomepage/images/qtws_video_thumbnail.png
new file mode 100644
index 0000000000..e24783aee0
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/qtws_video_thumbnail.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/ready_to_go.png b/src/plugins/studiowelcome/qml/welcomepage/images/ready_to_go.png
new file mode 100644
index 0000000000..af81a8a1d3
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/ready_to_go.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/sidemenu_demo.png b/src/plugins/studiowelcome/qml/welcomepage/images/sidemenu_demo.png
new file mode 100644
index 0000000000..b577ed4a0d
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/sidemenu_demo.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/thumbnail_test.png b/src/plugins/studiowelcome/qml/welcomepage/images/thumbnail_test.png
new file mode 100644
index 0000000000..3c4834e644
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/thumbnail_test.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/tutorial1.png b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial1.png
new file mode 100644
index 0000000000..6d8d8bbe61
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial1.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/tutorial2.png b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial2.png
new file mode 100644
index 0000000000..753e5d0937
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial2.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/tutorial3.png b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial3.png
new file mode 100644
index 0000000000..82c5e1cdd5
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial3.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/tutorial4.png b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial4.png
new file mode 100644
index 0000000000..1e1180fddb
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial4.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/tutorial5.png b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial5.png
new file mode 100644
index 0000000000..f0cefc0e6d
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/tutorial5.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/tutorialclusterdemo_thumbnail.png b/src/plugins/studiowelcome/qml/welcomepage/images/tutorialclusterdemo_thumbnail.png
new file mode 100644
index 0000000000..925a1247ca
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/tutorialclusterdemo_thumbnail.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/webinar1.png b/src/plugins/studiowelcome/qml/welcomepage/images/webinar1.png
new file mode 100644
index 0000000000..ba24ffc3bf
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/webinar1.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/webinar2.png b/src/plugins/studiowelcome/qml/welcomepage/images/webinar2.png
new file mode 100644
index 0000000000..325c7cdc33
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/webinar2.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/webinardemo_thumbnail.png b/src/plugins/studiowelcome/qml/welcomepage/images/webinardemo_thumbnail.png
new file mode 100644
index 0000000000..3cd777ab3f
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/images/webinardemo_thumbnail.png
Binary files differ
diff --git a/src/plugins/studiowelcome/qml/welcomepage/imports/welcome/Constants.qml b/src/plugins/studiowelcome/qml/welcomepage/imports/welcome/Constants.qml
new file mode 100644
index 0000000000..84f8da8d10
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/imports/welcome/Constants.qml
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** 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 Singleton
+
+import QtQuick 2.6
+import StudioFonts 1.0
+
+QtObject {
+ readonly property color backgroundColor: "#443224"
+
+ readonly property color textDefaultColor: "#b9b9ba"
+
+ readonly property color textHoverColor: "#ffffff"
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/imports/welcome/qmldir b/src/plugins/studiowelcome/qml/welcomepage/imports/welcome/qmldir
new file mode 100644
index 0000000000..616ac20353
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/imports/welcome/qmldir
@@ -0,0 +1 @@
+singleton Constants 1.0 Constants.qml
diff --git a/src/plugins/studiowelcome/qml/welcomepage/main.qml b/src/plugins/studiowelcome/qml/welcomepage/main.qml
new file mode 100644
index 0000000000..759ac45923
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/main.qml
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.10
+import QtQuick.Controls 2.4
+import QtQuick.Layouts 1.3
+import welcome 1.0
+import projectmodel 1.0
+import StudioFonts 1.0
+
+Item {
+ width: 1024
+ height: 786
+
+ Rectangle {
+ id: rectangle
+ anchors.fill: parent
+ visible: true
+ color: "#2d2e30"
+
+ StackLayout {
+ id: stackLayout
+ anchors.margins: 10
+ anchors.top: topLine.bottom
+ anchors.bottom: bottomLine.top
+ anchors.right: parent.right
+ anchors.left: parent.left
+
+ ScrollView{
+ ProjectsGrid {
+ model: ProjectModel {
+ id: projectModel
+ }
+ onItemSelected: projectModel.openProjectAt(index)
+ }
+ }
+
+ ScrollView {
+ ProjectsGrid {
+ model: ExamplesModel {}
+ onItemSelected: projectModel.openExample(item.projectName, item.qmlFileName)
+ }
+ }
+
+ ScrollView{
+ ProjectsGrid {
+ model: TutorialsModel {}
+ onItemSelected: Qt.openUrlExternally(item.url)
+ }
+ }
+ }
+ Rectangle {
+ id: topLine
+ height: 1
+ color: "#bababa"
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.top: parent.top
+ anchors.topMargin: 200
+ }
+
+ Rectangle {
+ id: bottomLine
+ height: 1
+ color: "#bababa"
+ anchors.left: topLine.left
+ anchors.right: topLine.right
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 60
+ }
+
+ Row {
+ x: 8
+ y: 160
+ spacing: 26
+
+ MyTabButton {
+ text: qsTr("Recent Projects")
+ bottomPadding: 6
+ topPadding: 6.8
+ checked: true
+ onClicked: stackLayout.currentIndex = 0
+ }
+
+ MyTabButton {
+ text: qsTr("Examples")
+ onClicked: stackLayout.currentIndex = 1
+ }
+
+ MyTabButton {
+ text: qsTr("Tutorials")
+ onClicked: stackLayout.currentIndex = 2
+ }
+ }
+
+ AccountImage {
+ id: account
+ x: 946
+ y: 29
+ anchors.right: parent.right
+ anchors.rightMargin: 40
+ }
+
+ GridLayout {
+ y: 78
+ anchors.horizontalCenter: parent.horizontalCenter
+ columnSpacing: 10
+ rows: 2
+ columns: 2
+
+ Text {
+ id: welcomeTo
+ color: Constants.textDefaultColor
+ text: qsTr("Welcome to")
+ renderType: Text.NativeRendering
+ font.pixelSize: 22
+ font.family: StudioFonts.titilliumWeb_regular
+ }
+
+ Text {
+ id: qtDesignStudio
+ color: "#4cd265"
+ text: qsTr("Qt Design Studio")
+ renderType: Text.NativeRendering
+ font.family: StudioFonts.titilliumWeb_regular
+ font.pixelSize: 22
+ }
+
+ MyButton {
+ text: qsTr("Create New")
+ onClicked: projectModel.createProject()
+ }
+
+ MyButton {
+ text: qsTr("Open Project")
+ onClicked: projectModel.openProject()
+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+ }
+ }
+
+ RowLayout {
+ y: 732
+ height: 28
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 26
+ spacing: 50
+
+ MyButton {
+ text: qsTr("Help")
+ onClicked: projectModel.showHelp()
+ }
+
+ MyButton {
+ text: qsTr("Community")
+ onClicked: Qt.openUrlExternally("https://forum.qt.io/")
+ }
+
+ MyButton {
+ text: qsTr("Blog")
+ onClicked: Qt.openUrlExternally("http://blog.qt.io/")
+ }
+ }
+
+ Text {
+ id: qtDesignStudio1
+ x: 891
+ y: 171
+ color: "#ffffff"
+ text: qsTr("Community Edition")
+ anchors.right: parent.right
+ anchors.rightMargin: 23
+ font.weight: Font.Light
+ font.pixelSize: 14
+ font.family: StudioFonts.titilliumWeb_regular
+ renderType: Text.NativeRendering
+ visible: projectModel.communityVersion
+ }
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml
new file mode 100644
index 0000000000..bca1783d42
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/ProjectModel.qml
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+ListModel {
+
+ property bool communityVersion: true
+ ListElement {
+ displayName: "Project 01"
+ prettyFilePath: "my_file_1"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 02"
+ prettyFilePath: "my_file_2"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 03"
+ prettyFilePath: "my_file_3"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 04"
+ prettyFilePath: "my_file_4"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 05"
+ prettyFilePath: "my_file_5"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 06"
+ prettyFilePath: "my_file_6"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 07"
+ prettyFilePath: "my_file_7"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 08"
+ filename: "my_file_8"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 09"
+ filename: "my_file_9"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 10"
+ prettyFilePath: "my_file_10"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 11"
+ filename: "my_file_11"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 12"
+ prettyFilePath: "my_file_12"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 13"
+ filename: "my_file_13"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 14"
+ prettyFilePath: "my_file_14"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 15"
+ filename: "my_file_15"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 16"
+ filename: "my_file_16"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 17"
+ filename: "my_file_17"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 18"
+ prettyFilePath: "my_file_18"
+ thumbnail: "images/thumbnail_test.png"
+ }
+}
diff --git a/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/qmldir b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/qmldir
new file mode 100644
index 0000000000..0d7bc345c2
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/mockData/projectmodel/qmldir
@@ -0,0 +1 @@
+ProjectModel 1.0 ProjectModel.qml
diff --git a/src/plugins/studiowelcome/qml/welcomepage/welcomepage.qmlproject b/src/plugins/studiowelcome/qml/welcomepage/welcomepage.qmlproject
new file mode 100644
index 0000000000..de393d88b0
--- /dev/null
+++ b/src/plugins/studiowelcome/qml/welcomepage/welcomepage.qmlproject
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QmlProject 1.1
+
+Project {
+ mainFile: "main.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ importPaths: [ "imports", "mockData", "../../../../share/3rdparty/studiofonts" ]
+
+ Environment {
+ QT_AUTO_SCREEN_SCALE_FACTOR: "1"
+ }
+}
diff --git a/src/plugins/studiowelcome/studiowelcome.pro b/src/plugins/studiowelcome/studiowelcome.pro
new file mode 100644
index 0000000000..183f955a49
--- /dev/null
+++ b/src/plugins/studiowelcome/studiowelcome.pro
@@ -0,0 +1,27 @@
+DEFINES += STUDIOWELCOME_LIBRARY
+
+QT += quick quickwidgets
+
+include(../../qtcreatorplugin.pri)
+
+## magic fix for unix builds
+RCC_DIR = .
+
+DEFINES += STUDIO_QML_PATH=\\\"$$PWD/qml/\\\"
+
+HEADERS += \
+ studiowelcome_global.h \
+ studiowelcomeplugin.h \
+
+SOURCES += \
+ studiowelcomeplugin.cpp
+
+OTHER_FILES += \
+ StudioWelcome.json.in
+
+RESOURCES += \
+ ../../share/3rdparty/studiofonts/studiofonts.qrc \
+ studiowelcome.qrc
+
+RESOURCES += \
+ $$files(qml/*)
diff --git a/src/plugins/studiowelcome/studiowelcome.qrc b/src/plugins/studiowelcome/studiowelcome.qrc
new file mode 100644
index 0000000000..59e410ba55
--- /dev/null
+++ b/src/plugins/studiowelcome/studiowelcome.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/studiowelcome">
+ <file>images/mode_welcome_mask.png</file>
+ <file>images/mode_welcome_mask@2x.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/studiowelcome/studiowelcome_dependencies.pri b/src/plugins/studiowelcome/studiowelcome_dependencies.pri
new file mode 100644
index 0000000000..51eb0d0256
--- /dev/null
+++ b/src/plugins/studiowelcome/studiowelcome_dependencies.pri
@@ -0,0 +1,10 @@
+QTC_PLUGIN_NAME = StudioWelcome
+QTC_LIB_DEPENDS += \
+ extensionsystem \
+ utils
+
+QTC_PLUGIN_DEPENDS += \
+ coreplugin \
+ projectexplorer \
+ qtsupport
+
diff --git a/src/plugins/studiowelcome/studiowelcome_global.h b/src/plugins/studiowelcome/studiowelcome_global.h
new file mode 100644
index 0000000000..6822c2a128
--- /dev/null
+++ b/src/plugins/studiowelcome/studiowelcome_global.h
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** 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 <QtGlobal>
+
+#if defined(STUDIOWELCOME_LIBRARY)
+# define STUDIOWELCOME_EXPORT Q_DECL_EXPORT
+#else
+# define STUDIOWELCOME_EXPORT Q_DECL_IMPORT
+#endif
diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
new file mode 100644
index 0000000000..508ab20b83
--- /dev/null
+++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** 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 "studiowelcomeplugin.h"
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/helpmanager.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/imode.h>
+#include <coreplugin/modemanager.h>
+
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectmanager.h>
+
+#include <utils/checkablemessagebox.h>
+#include <utils/icon.h>
+#include <utils/stringutils.h>
+#include <utils/theme/theme.h>
+
+#include <QAbstractListModel>
+#include <QApplication>
+#include <QDesktopServices>
+#include <QFontDatabase>
+#include <QFileInfo>
+#include <QPointer>
+#include <QQmlContext>
+#include <QQmlEngine>
+#include <QQuickItem>
+#include <QQuickView>
+#include <QQuickWidget>
+#include <QTimer>
+
+namespace StudioWelcome {
+namespace Internal {
+
+const char DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY[] = "StudioSplashScreen";
+
+QPointer<QQuickWidget> s_view = nullptr;
+
+class ProjectModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum { FilePathRole = Qt::UserRole+1, PrettyFilePathRole };
+
+ Q_PROPERTY(bool communityVersion MEMBER m_communityVersion NOTIFY communityVersionChanged)
+
+ explicit ProjectModel(QObject *parent = nullptr);
+
+ int rowCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ Q_INVOKABLE void createProject()
+ {
+ ProjectExplorer::ProjectExplorerPlugin::openNewProjectDialog();
+ }
+
+ Q_INVOKABLE void openProject()
+ {
+ ProjectExplorer::ProjectExplorerPlugin::openOpenProjectDialog();
+ }
+
+ Q_INVOKABLE void openProjectAt(int row)
+ {
+ const QString projectFile = data(index(row, 0),
+ ProjectModel::FilePathRole).toString();
+ ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
+ }
+
+ Q_INVOKABLE void showHelp()
+ {
+ QDesktopServices::openUrl(QUrl("qthelp://org.qt-project.qtcreator/doc/index.html"));
+ }
+
+ Q_INVOKABLE void openExample(const QString &example, const QString &formFile)
+ {
+ const QString projectFile = Core::ICore::resourcePath() + "/examples/" + example + "/" + example + ".qmlproject";
+ ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
+ const QString qmlFile = Core::ICore::resourcePath() + "/examples/" + example + "/" + formFile;
+ Core::EditorManager::openEditor(qmlFile);
+ }
+public slots:
+ void resetProjects();
+
+signals:
+ void communityVersionChanged();
+
+private:
+ bool m_communityVersion = false;
+};
+
+ProjectModel::ProjectModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+ connect(ProjectExplorer::ProjectExplorerPlugin::instance(),
+ &ProjectExplorer::ProjectExplorerPlugin::recentProjectsChanged,
+ this,
+ &ProjectModel::resetProjects);
+
+#ifdef LICENSECHECKER
+ if (!Utils::findOrDefault(ExtensionSystem::PluginManager::plugins(),
+ Utils::equal(&ExtensionSystem::PluginSpec::name, QString("LicenseChecker"))))
+ m_communityVersion = true;
+#endif
+}
+
+int ProjectModel::rowCount(const QModelIndex &) const
+{
+ return ProjectExplorer::ProjectExplorerPlugin::recentProjects().count();
+}
+
+QVariant ProjectModel::data(const QModelIndex &index, int role) const
+{
+ QPair<QString,QString> data =
+ ProjectExplorer::ProjectExplorerPlugin::recentProjects().at(index.row());
+ switch (role) {
+ case Qt::DisplayRole:
+ return data.second;
+ break;
+ case FilePathRole:
+ return data.first;
+ case PrettyFilePathRole:
+ return Utils::withTildeHomePath(data.first);
+ default:
+ return QVariant();
+ }
+
+ return QVariant();
+}
+
+QHash<int, QByteArray> ProjectModel::roleNames() const
+{
+ QHash<int, QByteArray> roleNames;
+ roleNames[Qt::DisplayRole] = "displayName";
+ roleNames[FilePathRole] = "filePath";
+ roleNames[PrettyFilePathRole] = "prettyFilePath";
+ return roleNames;
+}
+
+void ProjectModel::resetProjects()
+{
+ beginResetModel();
+ endResetModel();
+}
+
+class WelcomeMode : public Core::IMode
+{
+ Q_OBJECT
+public:
+ WelcomeMode();
+ ~WelcomeMode() override;
+
+private:
+
+ QQuickWidget *m_modeWidget = nullptr;
+};
+
+void StudioWelcomePlugin::closeSplashScreen()
+{
+ if (!s_view.isNull()) {
+ const bool doNotShowAgain = s_view->rootObject()->property("doNotShowAgain").toBool();
+ if (doNotShowAgain)
+ Utils::CheckableMessageBox::doNotAskAgain(Core::ICore::settings(),
+ DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY);
+
+ s_view->deleteLater();
+ }
+}
+
+StudioWelcomePlugin::~StudioWelcomePlugin()
+{
+ delete m_welcomeMode;
+}
+
+bool StudioWelcomePlugin::initialize(const QStringList &arguments, QString *errorString)
+{
+ Q_UNUSED(arguments);
+ Q_UNUSED(errorString);
+
+ qmlRegisterType<ProjectModel>("projectmodel", 1, 0, "ProjectModel");
+
+ m_welcomeMode = new WelcomeMode;
+
+ QFontDatabase fonts;
+ QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
+ QFont systemFont("Titillium Web", QApplication::font().pointSize());
+ QApplication::setFont(systemFont);
+
+ return true;
+}
+
+void StudioWelcomePlugin::extensionsInitialized()
+{
+ Core::ModeManager::activateMode(m_welcomeMode->id());
+ if (Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(),
+ DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) {
+ connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] (){
+ s_view = new QQuickWidget(Core::ICore::dialogParent());
+ s_view->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ s_view->setWindowFlag(Qt::SplashScreen, true);
+ s_view->setWindowModality(Qt::ApplicationModal);
+ s_view->engine()->addImportPath("qrc:/studiofonts");
+ #ifdef QT_DEBUG
+ s_view->engine()->addImportPath(QLatin1String(STUDIO_QML_PATH)
+ + "splashscreen/imports");
+ s_view->setSource(QUrl::fromLocalFile(QLatin1String(STUDIO_QML_PATH)
+ + "splashscreen/main.qml"));
+ #else
+ s_view->engine()->addImportPath("qrc:/qml/splashscreen/imports");
+ s_view->setSource(QUrl("qrc:/qml/splashscreen/main.qml"));
+ #endif
+
+ QTC_ASSERT(s_view->rootObject(),
+ qWarning() << "The StudioWelcomePlugin has a runtime depdendency on qt/qtquicktimeline.";
+ return);
+
+ connect(s_view->rootObject(), SIGNAL(closeClicked()), this, SLOT(closeSplashScreen()));
+
+ s_view->show();
+ s_view->raise();
+
+ QTimer::singleShot(15000, [](){
+ if (s_view)
+ s_view->close();
+ });
+ });
+ }
+}
+
+bool StudioWelcomePlugin::delayedInitialize()
+{
+ if (s_view.isNull())
+ return true;
+
+ QTC_ASSERT(s_view->rootObject() , return true);
+
+ s_view->rootObject()->setProperty("loadingPlugins", false);
+
+ QPointer<QQuickWidget> view = s_view;
+
+ connect(Core::ICore::mainWindow()->windowHandle(), &QWindow::visibleChanged, this, [view](){
+ if (!view.isNull()) {
+ view->close();
+ view->deleteLater();
+ }
+ });
+
+ return false;
+}
+
+WelcomeMode::WelcomeMode()
+{
+ setDisplayName(tr("Studio"));
+
+ const Utils::Icon FLAT({{":/studiowelcome/images/mode_welcome_mask.png",
+ Utils::Theme::IconsBaseColor}});
+ const Utils::Icon FLAT_ACTIVE({{":/studiowelcome/images/mode_welcome_mask.png",
+ Utils::Theme::IconsModeWelcomeActiveColor}});
+ setIcon(Utils::Icon::modeIcon(FLAT, FLAT, FLAT_ACTIVE));
+
+ setPriority(Core::Constants::P_MODE_WELCOME);
+ setId(Core::Constants::MODE_WELCOME);
+ setContextHelp("Qt Creator Manual");
+ setContext(Core::Context(Core::Constants::C_WELCOME_MODE));
+
+ m_modeWidget = new QQuickWidget;
+ m_modeWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ m_modeWidget->engine()->addImportPath("qrc:/studiofonts");
+#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
+
+ setWidget(m_modeWidget);
+
+ QStringList designStudioQchPathes = {Core::HelpManager::documentationPath()
+ + "/qtdesignstudio.qch",
+ Core::HelpManager::documentationPath() + "/qtquick.qch",
+ Core::HelpManager::documentationPath()
+ + "/qtquickcontrols.qch"};
+
+ Core::HelpManager::registerDocumentation(
+ Utils::filtered(designStudioQchPathes,
+ [](const QString &path) { return QFileInfo::exists(path); }));
+}
+
+WelcomeMode::~WelcomeMode()
+{
+ delete m_modeWidget;
+}
+
+} // namespace Internal
+} // namespace StudioWelcome
+
+#include "studiowelcomeplugin.moc"
diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.h b/src/plugins/studiowelcome/studiowelcomeplugin.h
new file mode 100644
index 0000000000..2250d7b1b6
--- /dev/null
+++ b/src/plugins/studiowelcome/studiowelcomeplugin.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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 <extensionsystem/iplugin.h>
+
+namespace StudioWelcome {
+namespace Internal {
+
+class StudioWelcomePlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "StudioWelcome.json")
+
+public slots:
+ void closeSplashScreen();
+
+public:
+ ~StudioWelcomePlugin() final;
+
+ bool initialize(const QStringList &arguments, QString *errorString) override;
+ void extensionsInitialized() override;
+ bool delayedInitialize() override;
+
+private:
+ class WelcomeMode *m_welcomeMode = nullptr;
+};
+
+} // namespace Internal
+} // namespace StudioWelcome
diff --git a/src/plugins/subversion/CMakeLists.txt b/src/plugins/subversion/CMakeLists.txt
new file mode 100644
index 0000000000..4dc5885f15
--- /dev/null
+++ b/src/plugins/subversion/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_qtc_plugin(Subversion
+ PLUGIN_DEPENDS Core DiffEditor TextEditor VcsBase
+ SOURCES
+ annotationhighlighter.cpp annotationhighlighter.h
+ settingspage.cpp settingspage.h settingspage.ui
+ subversionclient.cpp subversionclient.h
+ subversionconstants.h
+ subversioncontrol.cpp subversioncontrol.h
+ subversioneditor.cpp subversioneditor.h
+ subversionplugin.cpp subversionplugin.h
+ subversionsettings.cpp subversionsettings.h
+ subversionsubmiteditor.cpp subversionsubmiteditor.h
+)
diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp
index ef65246fc3..6982bb854b 100644
--- a/src/plugins/subversion/subversionclient.cpp
+++ b/src/plugins/subversion/subversionclient.cpp
@@ -150,7 +150,7 @@ QString SubversionClient::synchronousTopic(const QString &repository)
svnVersionBinary = svnVersionBinary.left(pos + 1);
svnVersionBinary.append(HostOsInfo::withExecutableSuffix("svnversion"));
const SynchronousProcessResponse result
- = vcsFullySynchronousExec(repository, FileName::fromString(svnVersionBinary), args);
+ = vcsFullySynchronousExec(repository, FilePath::fromString(svnVersionBinary), args);
if (result.result != SynchronousProcessResponse::Finished)
return QString();
diff --git a/src/plugins/subversion/subversionclient.h b/src/plugins/subversion/subversionclient.h
index 00ab1639ee..aa11695e9b 100644
--- a/src/plugins/subversion/subversionclient.h
+++ b/src/plugins/subversion/subversionclient.h
@@ -80,7 +80,7 @@ private:
SubversionDiffEditorController *findOrCreateDiffEditor(const QString &documentId, const QString &source,
const QString &title, const QString &workingDirectory) const;
- mutable Utils::FileName m_svnVersionBinary;
+ mutable Utils::FilePath m_svnVersionBinary;
mutable QString m_svnVersion;
};
diff --git a/src/plugins/subversion/subversioncontrol.cpp b/src/plugins/subversion/subversioncontrol.cpp
index 461bac97fd..0d4a024271 100644
--- a/src/plugins/subversion/subversioncontrol.cpp
+++ b/src/plugins/subversion/subversioncontrol.cpp
@@ -78,14 +78,14 @@ Core::Id SubversionControl::id() const
return Core::Id(VcsBase::Constants::VCS_ID_SUBVERSION);
}
-bool SubversionControl::isVcsFileOrDirectory(const Utils::FileName &fileName) const
+bool SubversionControl::isVcsFileOrDirectory(const Utils::FilePath &fileName) const
{
return m_plugin->isVcsDirectory(fileName);
}
bool SubversionControl::isConfigured() const
{
- const Utils::FileName binary = m_plugin->client()->vcsBinary();
+ const Utils::FilePath binary = m_plugin->client()->vcsBinary();
if (binary.isEmpty())
return false;
QFileInfo fi = binary.toFileInfo();
@@ -158,7 +158,7 @@ bool SubversionControl::vcsAnnotate(const QString &file, int line)
}
Core::ShellCommand *SubversionControl::createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs)
{
diff --git a/src/plugins/subversion/subversioncontrol.h b/src/plugins/subversion/subversioncontrol.h
index 9a8f9ff0e6..561decc2e9 100644
--- a/src/plugins/subversion/subversioncontrol.h
+++ b/src/plugins/subversion/subversioncontrol.h
@@ -40,7 +40,7 @@ public:
explicit SubversionControl(SubversionPlugin *plugin);
QString displayName() const final;
Core::Id id() const final;
- bool isVcsFileOrDirectory(const Utils::FileName &fileName) const final;
+ bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final;
bool managesDirectory(const QString &directory, QString *topLevel = nullptr) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
@@ -56,7 +56,7 @@ public:
bool vcsAnnotate(const QString &file, int line) final;
Core::ShellCommand *createInitialCheckoutCommand(const QString &url,
- const Utils::FileName &baseDirectory,
+ const Utils::FilePath &baseDirectory,
const QString &localName,
const QStringList &extraArgs) final;
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index e9a70d2f9a..21b30d878d 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -390,7 +390,7 @@ bool SubversionPlugin::initialize(const QStringList & /*arguments */, QString *e
return true;
}
-bool SubversionPlugin::isVcsDirectory(const FileName &fileName)
+bool SubversionPlugin::isVcsDirectory(const FilePath &fileName)
{
const QString baseName = fileName.fileName();
return fileName.toFileInfo().isDir()
diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h
index 67575fdb2d..a5b2dbd253 100644
--- a/src/plugins/subversion/subversionplugin.h
+++ b/src/plugins/subversion/subversionplugin.h
@@ -73,7 +73,7 @@ public:
bool initialize(const QStringList &arguments, QString *errorMessage) override;
- bool isVcsDirectory(const Utils::FileName &fileName);
+ bool isVcsDirectory(const Utils::FilePath &fileName);
SubversionClient *client() const;
diff --git a/src/plugins/tasklist/CMakeLists.txt b/src/plugins/tasklist/CMakeLists.txt
new file mode 100644
index 0000000000..b82d633ec4
--- /dev/null
+++ b/src/plugins/tasklist/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_plugin(TaskList
+ PLUGIN_DEPENDS Core ProjectExplorer
+ SOURCES
+ stopmonitoringhandler.cpp stopmonitoringhandler.h
+ taskfile.cpp taskfile.h
+ tasklistconstants.h
+ tasklistplugin.cpp tasklistplugin.h
+)
diff --git a/src/plugins/tasklist/taskfile.cpp b/src/plugins/tasklist/taskfile.cpp
index 3620616438..871cefe1ab 100644
--- a/src/plugins/tasklist/taskfile.cpp
+++ b/src/plugins/tasklist/taskfile.cpp
@@ -61,7 +61,7 @@ bool TaskFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
return load(errorString, filePath());
}
-bool TaskFile::load(QString *errorString, const Utils::FileName &fileName)
+bool TaskFile::load(QString *errorString, const Utils::FilePath &fileName)
{
setFilePath(fileName);
return TaskListPlugin::loadFile(errorString, fileName);
diff --git a/src/plugins/tasklist/taskfile.h b/src/plugins/tasklist/taskfile.h
index eaaf638829..22331f788e 100644
--- a/src/plugins/tasklist/taskfile.h
+++ b/src/plugins/tasklist/taskfile.h
@@ -40,7 +40,7 @@ public:
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override;
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
- bool load(QString *errorString, const Utils::FileName &fileName);
+ bool load(QString *errorString, const Utils::FilePath &fileName);
};
} // namespace Internal
diff --git a/src/plugins/tasklist/tasklistplugin.cpp b/src/plugins/tasklist/tasklistplugin.cpp
index 4c1d707309..b1d843355a 100644
--- a/src/plugins/tasklist/tasklistplugin.cpp
+++ b/src/plugins/tasklist/tasklistplugin.cpp
@@ -107,7 +107,7 @@ static QString unescape(const QString &input)
return result;
}
-static bool parseTaskFile(QString *errorString, const FileName &name)
+static bool parseTaskFile(QString *errorString, const FilePath &name)
{
QFile tf(name.toString());
if (!tf.open(QIODevice::ReadOnly)) {
@@ -116,7 +116,7 @@ static bool parseTaskFile(QString *errorString, const FileName &name)
return false;
}
- const FileName parentDir = name.parentDir();
+ const FilePath parentDir = name.parentDir();
while (!tf.atEnd()) {
QStringList chunks = parseRawLine(tf.readLine());
if (chunks.isEmpty())
@@ -149,12 +149,12 @@ static bool parseTaskFile(QString *errorString, const FileName &name)
file = QDir::fromNativeSeparators(file);
QFileInfo fi(file);
if (fi.isRelative())
- file = FileName(parentDir).appendPath(file).toString();
+ file = parentDir.pathAppended(file).toString();
}
description = unescape(description);
TaskHub::addTask(type, description, Constants::TASKLISTTASK_ID,
- FileName::fromUserInput(file), line);
+ FilePath::fromUserInput(file), line);
}
return true;
}
@@ -163,7 +163,7 @@ static bool parseTaskFile(QString *errorString, const FileName &name)
// TaskListPlugin
// --------------------------------------------------------------------------
-IDocument *TaskListPlugin::openTasks(const FileName &fileName)
+IDocument *TaskListPlugin::openTasks(const FilePath &fileName)
{
foreach (TaskFile *doc, d->m_openFiles) {
if (doc->filePath() == fileName)
@@ -210,7 +210,7 @@ bool TaskListPlugin::initialize(const QStringList &arguments, QString *errorMess
d->m_fileFactory.addMimeType(QLatin1String("text/x-tasklist"));
d->m_fileFactory.setOpener([this](const QString &fileName) {
- return openTasks(FileName::fromString(fileName));
+ return openTasks(FilePath::fromString(fileName));
});
connect(SessionManager::instance(), &SessionManager::sessionLoaded,
@@ -219,7 +219,7 @@ bool TaskListPlugin::initialize(const QStringList &arguments, QString *errorMess
return true;
}
-bool TaskListPlugin::loadFile(QString *errorString, const FileName &fileName)
+bool TaskListPlugin::loadFile(QString *errorString, const FilePath &fileName)
{
clearTasks();
@@ -248,7 +248,7 @@ void TaskListPlugin::clearTasks()
void TaskListPlugin::loadDataFromSession()
{
- const FileName fileName = FileName::fromString(
+ const FilePath fileName = FilePath::fromString(
SessionManager::value(QLatin1String(SESSION_FILE_KEY)).toString());
if (!fileName.isEmpty())
openTasks(fileName);
diff --git a/src/plugins/tasklist/tasklistplugin.h b/src/plugins/tasklist/tasklistplugin.h
index 4c78fcbfd0..6fcd6f3d7f 100644
--- a/src/plugins/tasklist/tasklistplugin.h
+++ b/src/plugins/tasklist/tasklistplugin.h
@@ -28,7 +28,7 @@
#include <coreplugin/idocumentfactory.h>
#include <extensionsystem/iplugin.h>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace TaskList {
namespace Internal {
@@ -45,12 +45,12 @@ public:
bool initialize(const QStringList &arguments, QString *errorMessage) override;
void extensionsInitialized() override {}
- static bool loadFile(QString *errorString, const Utils::FileName &fileName);
+ static bool loadFile(QString *errorString, const Utils::FilePath &fileName);
static void stopMonitoring();
static void clearTasks();
- Core::IDocument *openTasks(const Utils::FileName &fileName);
+ Core::IDocument *openTasks(const Utils::FilePath &fileName);
void loadDataFromSession();
diff --git a/src/plugins/texteditor/CMakeLists.txt b/src/plugins/texteditor/CMakeLists.txt
new file mode 100644
index 0000000000..23145ac72e
--- /dev/null
+++ b/src/plugins/texteditor/CMakeLists.txt
@@ -0,0 +1,108 @@
+add_qtc_plugin(TextEditor
+ DEPENDS Qt5::Concurrent Qt5::Network Qt5::PrintSupport Qt5::Xml
+ PUBLIC_DEPENDS KSyntaxHighlighting
+ PLUGIN_DEPENDS Core
+ SOURCES
+ autocompleter.cpp autocompleter.h
+ basefilefind.cpp basefilefind.h
+ basehoverhandler.cpp basehoverhandler.h
+ behaviorsettings.cpp behaviorsettings.h
+ behaviorsettingspage.cpp behaviorsettingspage.h behaviorsettingspage.ui
+ behaviorsettingswidget.cpp behaviorsettingswidget.h behaviorsettingswidget.ui
+ blockrange.h
+ circularclipboard.cpp circularclipboard.h
+ circularclipboardassist.cpp circularclipboardassist.h
+ codeassist/assistenums.h
+ codeassist/assistinterface.cpp codeassist/assistinterface.h
+ codeassist/assistproposalitem.cpp codeassist/assistproposalitem.h
+ codeassist/assistproposaliteminterface.h
+ codeassist/codeassistant.cpp codeassist/codeassistant.h
+ codeassist/completionassistprovider.cpp codeassist/completionassistprovider.h
+ codeassist/documentcontentcompletion.cpp codeassist/documentcontentcompletion.h
+ codeassist/functionhintproposal.cpp codeassist/functionhintproposal.h
+ codeassist/functionhintproposalwidget.cpp codeassist/functionhintproposalwidget.h
+ codeassist/genericproposal.cpp codeassist/genericproposal.h
+ codeassist/genericproposalmodel.cpp codeassist/genericproposalmodel.h
+ codeassist/genericproposalwidget.cpp codeassist/genericproposalwidget.h
+ codeassist/iassistprocessor.cpp codeassist/iassistprocessor.h
+ codeassist/iassistproposal.cpp codeassist/iassistproposal.h
+ codeassist/iassistproposalmodel.cpp codeassist/iassistproposalmodel.h
+ codeassist/iassistproposalwidget.cpp codeassist/iassistproposalwidget.h
+ codeassist/iassistprovider.cpp codeassist/iassistprovider.h
+ codeassist/ifunctionhintproposalmodel.cpp codeassist/ifunctionhintproposalmodel.h
+ codeassist/keywordscompletionassist.cpp codeassist/keywordscompletionassist.h
+ codeassist/runner.cpp codeassist/runner.h
+ codeassist/textdocumentmanipulator.cpp codeassist/textdocumentmanipulator.h
+ codeassist/textdocumentmanipulatorinterface.h
+ codecselector.cpp codecselector.h
+ codestyleeditor.cpp codestyleeditor.h
+ codestylepool.cpp codestylepool.h
+ codestyleselectorwidget.cpp codestyleselectorwidget.h codestyleselectorwidget.ui
+ colorpreviewhoverhandler.cpp colorpreviewhoverhandler.h
+ colorscheme.cpp colorscheme.h
+ colorschemeedit.cpp colorschemeedit.h colorschemeedit.ui
+ command.cpp command.h
+ commentssettings.cpp commentssettings.h
+ completionsettings.cpp completionsettings.h
+ completionsettingspage.cpp completionsettingspage.h completionsettingspage.ui
+ displaysettings.cpp displaysettings.h
+ displaysettingspage.cpp displaysettingspage.h displaysettingspage.ui
+ extraencodingsettings.cpp extraencodingsettings.h
+ findincurrentfile.cpp findincurrentfile.h
+ findinfiles.cpp findinfiles.h
+ findinopenfiles.cpp findinopenfiles.h
+ fontsettings.cpp fontsettings.h
+ fontsettingspage.cpp fontsettingspage.h fontsettingspage.ui
+ formattexteditor.cpp formattexteditor.h
+ highlighter.cpp highlighter.h
+ highlightersettings.cpp highlightersettings.h
+ highlightersettingspage.cpp highlightersettingspage.h highlightersettingspage.ui
+ icodestylepreferences.cpp icodestylepreferences.h
+ icodestylepreferencesfactory.cpp icodestylepreferencesfactory.h
+ indenter.h
+ ioutlinewidget.h
+ linenumberfilter.cpp linenumberfilter.h
+ marginsettings.cpp marginsettings.h
+ normalindenter.cpp normalindenter.h
+ outlinefactory.cpp outlinefactory.h
+ plaintexteditorfactory.cpp plaintexteditorfactory.h
+ quickfix.cpp quickfix.h
+ refactoringchanges.cpp refactoringchanges.h
+ refactoroverlay.cpp refactoroverlay.h
+ semantichighlighter.cpp semantichighlighter.h
+ simplecodestylepreferences.cpp simplecodestylepreferences.h
+ simplecodestylepreferenceswidget.cpp simplecodestylepreferenceswidget.h
+ snippets/reuse.h
+ snippets/snippet.cpp snippets/snippet.h
+ snippets/snippetassistcollector.cpp snippets/snippetassistcollector.h
+ snippets/snippeteditor.cpp snippets/snippeteditor.h
+ snippets/snippetprovider.cpp snippets/snippetprovider.h
+ snippets/snippetscollection.cpp snippets/snippetscollection.h
+ snippets/snippetssettings.cpp snippets/snippetssettings.h
+ snippets/snippetssettingspage.cpp snippets/snippetssettingspage.h snippets/snippetssettingspage.ui
+ storagesettings.cpp storagesettings.h
+ syntaxhighlighter.cpp syntaxhighlighter.h
+ tabsettings.cpp tabsettings.h
+ tabsettingswidget.cpp tabsettingswidget.h tabsettingswidget.ui
+ textdocument.cpp textdocument.h
+ textdocumentlayout.cpp textdocumentlayout.h
+ texteditor.cpp texteditor.h
+ texteditor.qrc
+ texteditor_global.h
+ texteditor_p.h
+ texteditoractionhandler.cpp texteditoractionhandler.h
+ texteditorconstants.cpp texteditorconstants.h
+ texteditoroptionspage.cpp texteditoroptionspage.h
+ texteditoroverlay.cpp texteditoroverlay.h
+ texteditorplugin.cpp texteditorplugin.h
+ texteditorsettings.cpp texteditorsettings.h
+ textindenter.cpp textindenter.h
+ textmark.cpp textmark.h
+ textstyles.h
+ typingsettings.cpp typingsettings.h
+)
+
+extend_qtc_plugin(TextEditor
+ CONDITION WITH_TESTS
+ SOURCES texteditor_test.cpp
+)
diff --git a/src/plugins/texteditor/autocompleter.cpp b/src/plugins/texteditor/autocompleter.cpp
index 8517c5c03d..ea50725639 100644
--- a/src/plugins/texteditor/autocompleter.cpp
+++ b/src/plugins/texteditor/autocompleter.cpp
@@ -37,7 +37,8 @@ AutoCompleter::AutoCompleter() :
m_autoInsertBrackets(true),
m_surroundWithBrackets(true),
m_autoInsertQuotes(true),
- m_surroundWithQuotes(true)
+ m_surroundWithQuotes(true),
+ m_overwriteClosingChars(false)
{}
AutoCompleter::~AutoCompleter() = default;
@@ -191,6 +192,9 @@ QString AutoCompleter::autoComplete(QTextCursor &cursor, const QString &textToIn
QTextDocument *doc = cursor.document();
const QChar lookAhead = doc->characterAt(cursor.selectionEnd());
+ if (m_overwriteClosingChars && (textToInsert == lookAhead))
+ skipChars = true;
+
int skippedChars = 0;
if (isQuote(textToInsert) && m_autoInsertQuotes
diff --git a/src/plugins/texteditor/autocompleter.h b/src/plugins/texteditor/autocompleter.h
index 4847f50476..128d875e0f 100644
--- a/src/plugins/texteditor/autocompleter.h
+++ b/src/plugins/texteditor/autocompleter.h
@@ -53,6 +53,9 @@ public:
void setSurroundWithQuotesEnabled(bool b) { m_surroundWithQuotes = b; }
bool isSurroundWithQuotesEnabled() const { return m_surroundWithQuotes; }
+ void setOverwriteClosingCharsEnabled(bool b) { m_overwriteClosingChars = b; }
+ bool isOverwriteClosingCharsEnabled() const { return m_overwriteClosingChars; }
+
void setTabSettings(const TabSettings &tabSettings) { m_tabSettings = tabSettings; }
const TabSettings &tabSettings() const { return m_tabSettings; }
@@ -103,6 +106,7 @@ private:
bool m_surroundWithBrackets;
bool m_autoInsertQuotes;
bool m_surroundWithQuotes;
+ bool m_overwriteClosingChars;
};
} // TextEditor
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index eb449251c1..f6c134e02c 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -272,7 +272,7 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags,
parameters.additionalParameters = additionalParameters();
parameters.searchEngineParameters = currentSearchEngine()->parameters();
parameters.searchEngineIndex = d->m_currentSearchEngineIndex;
- search->setUserData(qVariantFromValue(parameters));
+ search->setUserData(QVariant::fromValue(parameters));
connect(search, &SearchResult::activated, this, [this, search](const SearchResultItem &item) {
openEditor(search, item);
});
@@ -293,10 +293,6 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags,
void BaseFileFind::runSearch(SearchResult *search)
{
const FileFindParameters parameters = search->userData().value<FileFindParameters>();
- auto label = new CountingLabel;
- connect(search, &SearchResult::countChanged, label, &CountingLabel::updateCount);
- auto statusLabel = new CountingLabel;
- connect(search, &SearchResult::countChanged, statusLabel, &CountingLabel::updateCount);
SearchResultWindow::instance()->popup(IOutputPane::Flags(IOutputPane::ModeSwitch|IOutputPane::WithFocus));
auto watcher = new QFutureWatcher<FileSearchResultList>();
watcher->setPendingResultsLimit(1);
@@ -316,10 +312,13 @@ void BaseFileFind::runSearch(SearchResult *search)
search->finishSearch(watcher->isCanceled());
});
watcher->setFuture(executeSearch(parameters));
- FutureProgress *progress =
- ProgressManager::addTask(watcher->future(), tr("Searching"), Constants::TASK_SEARCH);
- progress->setWidget(label);
- progress->setStatusBarWidget(statusLabel);
+ FutureProgress *progress = ProgressManager::addTask(watcher->future(),
+ tr("Searching"),
+ Constants::TASK_SEARCH);
+ connect(search, &SearchResult::countChanged, progress, [progress](int c) {
+ progress->setSubtitle(BaseFileFind::tr("%n found.", nullptr, c));
+ });
+ progress->setSubtitleVisibleInStatusBar(true);
connect(progress, &FutureProgress::clicked, search, &SearchResult::popup);
}
@@ -498,12 +497,12 @@ QStringList BaseFileFind::replaceAll(const QString &text,
// Checking for files without write permissions
QHashIterator<QString, QList<SearchResultItem> > it(changes);
- QSet<QString> roFiles;
+ QSet<FilePath> roFiles;
while (it.hasNext()) {
it.next();
const QFileInfo fileInfo(it.key());
if (!fileInfo.isWritable())
- roFiles.insert(it.key());
+ roFiles.insert(FilePath::fromString(it.key()));
}
// Query the user for permissions
@@ -566,23 +565,5 @@ QFuture<FileSearchResultList> BaseFileFind::executeSearch(const FileFindParamete
namespace Internal {
-CountingLabel::CountingLabel()
-{
- setAlignment(Qt::AlignCenter);
- // ### TODO this setup should be done by style
- QFont f = font();
- f.setBold(true);
- f.setPointSizeF(StyleHelper::sidebarFontSize());
- setFont(f);
- setPalette(StyleHelper::sidebarFontPalette(palette()));
- setProperty("_q_custom_style_disabled", QVariant(true));
- updateCount(0);
-}
-
-void CountingLabel::updateCount(int count)
-{
- setText(BaseFileFind::tr("%n found.", nullptr, count));
-}
-
} // namespace Internal
} // namespace TextEditor
diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp
index 92dae73d59..dfe390d68f 100644
--- a/src/plugins/texteditor/basehoverhandler.cpp
+++ b/src/plugins/texteditor/basehoverhandler.cpp
@@ -162,7 +162,7 @@ void BaseHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoi
Utils::ToolTip::show(point,
m_toolTip,
editorWidget,
- qVariantFromValue(m_lastHelpItemIdentified));
+ QVariant::fromValue(m_lastHelpItemIdentified));
}
} // namespace TextEditor
diff --git a/src/plugins/texteditor/behaviorsettingswidget.cpp b/src/plugins/texteditor/behaviorsettingswidget.cpp
index 65bb8d5717..e528a23812 100644
--- a/src/plugins/texteditor/behaviorsettingswidget.cpp
+++ b/src/plugins/texteditor/behaviorsettingswidget.cpp
@@ -81,7 +81,7 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent)
d->m_codecs.prepend(QTextCodec::codecForLocale());
}
- auto currentIndexChanged = static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged);
+ auto currentIndexChanged = QOverload<int>::of(&QComboBox::currentIndexChanged);
connect(d->m_ui.autoIndent, &QAbstractButton::toggled,
this, &BehaviorSettingsWidget::slotTypingSettingsChanged);
connect(d->m_ui.smartBackspaceBehavior, currentIndexChanged,
diff --git a/src/plugins/texteditor/codeassist/assistproposalitem.h b/src/plugins/texteditor/codeassist/assistproposalitem.h
index bd61c02c8d..01668670ae 100644
--- a/src/plugins/texteditor/codeassist/assistproposalitem.h
+++ b/src/plugins/texteditor/codeassist/assistproposalitem.h
@@ -35,7 +35,6 @@
namespace TextEditor {
-
class TEXTEDITOR_EXPORT AssistProposalItem : public AssistProposalItemInterface
{
public:
diff --git a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
index 601dbd9c2b..893dc4aa0d 100644
--- a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
+++ b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
@@ -38,7 +38,6 @@ QT_END_NAMESPACE
namespace TextEditor {
-
class TEXTEDITOR_EXPORT AssistProposalItemInterface
{
public:
@@ -62,6 +61,8 @@ public:
virtual void apply(TextDocumentManipulatorInterface &manipulator, int basePosition) const = 0;
virtual QIcon icon() const = 0;
virtual QString detail() const = 0;
+ virtual bool isKeyword() const { return false; }
+ virtual Qt::TextFormat detailFormat() const { return Qt::AutoText; }
virtual bool isSnippet() const = 0;
virtual bool isValid() const = 0;
virtual quint64 hash() const = 0; // it is only for removing duplicates
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp
index b531f44c80..4f9605d1e3 100644
--- a/src/plugins/texteditor/codeassist/codeassistant.cpp
+++ b/src/plugins/texteditor/codeassist/codeassistant.cpp
@@ -40,6 +40,7 @@
#include <texteditor/completionsettings.h>
#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
+#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QKeyEvent>
@@ -431,22 +432,28 @@ void CodeAssistantPrivate::invalidateCurrentRequestData()
CompletionAssistProvider *CodeAssistantPrivate::identifyActivationSequence()
{
- CompletionAssistProvider *completionProvider = m_editorWidget->textDocument()->completionAssistProvider();
- if (!completionProvider)
- return nullptr;
-
- const int length = completionProvider->activationCharSequenceLength();
- if (length == 0)
- return nullptr;
- QString sequence = m_editorWidget->textAt(m_editorWidget->position() - length, length);
- // In pretty much all cases the sequence will have the appropriate length. Only in the
- // case of typing the very first characters in the document for providers that request a
- // length greater than 1 (currently only C++, which specifies 3), the sequence needs to
- // be prepended so it has the expected length.
- const int lengthDiff = length - sequence.length();
- for (int j = 0; j < lengthDiff; ++j)
- sequence.prepend(m_null);
- return completionProvider->isActivationCharSequence(sequence) ? completionProvider : nullptr;
+ auto checkActivationSequence = [this](CompletionAssistProvider *provider) {
+ if (!provider)
+ return false;
+ const int length = provider->activationCharSequenceLength();
+ if (!length)
+ return false;
+ QString sequence = m_editorWidget->textAt(m_editorWidget->position() - length, length);
+ // In pretty much all cases the sequence will have the appropriate length. Only in the
+ // case of typing the very first characters in the document for providers that request a
+ // length greater than 1 (currently only C++, which specifies 3), the sequence needs to
+ // be prepended so it has the expected length.
+ const int lengthDiff = length - sequence.length();
+ for (int j = 0; j < lengthDiff; ++j)
+ sequence.prepend(m_null);
+ return provider->isActivationCharSequence(sequence);
+ };
+
+ auto provider = {
+ m_editorWidget->textDocument()->completionAssistProvider(),
+ m_editorWidget->textDocument()->functionHintAssistProvider()
+ };
+ return Utils::findOrDefault(provider, checkActivationSequence);
}
void CodeAssistantPrivate::notifyChange()
diff --git a/src/plugins/texteditor/codeassist/documentcontentcompletion.h b/src/plugins/texteditor/codeassist/documentcontentcompletion.h
index 3d8c048cab..ec80140d5e 100644
--- a/src/plugins/texteditor/codeassist/documentcontentcompletion.h
+++ b/src/plugins/texteditor/codeassist/documentcontentcompletion.h
@@ -35,6 +35,8 @@ class AssistInterface;
class TEXTEDITOR_EXPORT DocumentContentCompletionProvider : public CompletionAssistProvider
{
+ Q_OBJECT
+
public:
DocumentContentCompletionProvider(
const QString &snippetGroup = QString(Constants::TEXT_SNIPPET_GROUP_ID));
diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp
index ec6168c0cb..b5d9b00340 100644
--- a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp
+++ b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp
@@ -214,8 +214,13 @@ bool GenericProposalModel::isPerfectMatch(const QString &prefix) const
if (match == PerfectMatchType::StartsWith)
return false;
- if (!hasFullMatch && match == PerfectMatchType::Full)
- hasFullMatch = true;
+ if (match == PerfectMatchType::Full) {
+ if (proposalItem(i)->isKeyword())
+ return true;
+
+ if (!hasFullMatch)
+ hasFullMatch = true;
+ }
}
return hasFullMatch;
@@ -257,6 +262,11 @@ QString GenericProposalModel::detail(int index) const
return m_currentItems.at(index)->detail();
}
+Qt::TextFormat GenericProposalModel::detailFormat(int index) const
+{
+ return m_currentItems.at(index)->detailFormat();
+}
+
void GenericProposalModel::removeDuplicates()
{
if (m_duplicatesRemoved)
diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.h b/src/plugins/texteditor/codeassist/genericproposalmodel.h
index 47e4f716fc..de84d60dbe 100644
--- a/src/plugins/texteditor/codeassist/genericproposalmodel.h
+++ b/src/plugins/texteditor/codeassist/genericproposalmodel.h
@@ -53,6 +53,7 @@ public:
virtual QIcon icon(int index) const;
virtual QString detail(int index) const;
+ virtual Qt::TextFormat detailFormat(int index) const;
virtual int persistentId(int index) const;
virtual bool containsDuplicates() const;
virtual void removeDuplicates();
diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp
index a821538a22..aad4096f81 100644
--- a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp
+++ b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp
@@ -70,6 +70,7 @@ public:
int rowCount(const QModelIndex &) const override;
QVariant data(const QModelIndex &index, int role) const override;
+ enum UserRoles{ FixItRole = Qt::UserRole, DetailTextFormatRole };
private:
GenericProposalModelPtr m_completionModel;
};
@@ -99,7 +100,9 @@ QVariant ModelAdapter::data(const QModelIndex &index, int role) const
return m_completionModel->icon(index.row());
} else if (role == Qt::WhatsThisRole) {
return m_completionModel->detail(index.row());
- } else if (role == Qt::UserRole) {
+ } else if (role == DetailTextFormatRole) {
+ return m_completionModel->detailFormat(index.row());
+ } else if (role == FixItRole) {
return m_completionModel->proposalItem(index.row())->requiresFixIts();
}
@@ -123,7 +126,6 @@ public:
// Limit horizontal width
m_label->setSizePolicy(QSizePolicy::Fixed, m_label->sizePolicy().verticalPolicy());
- m_label->setTextFormat(Qt::RichText);
m_label->setForegroundRole(QPalette::ToolTipText);
m_label->setBackgroundRole(QPalette::ToolTipBase);
}
@@ -133,6 +135,11 @@ public:
m_label->setText(text);
}
+ void setTextFormat(Qt::TextFormat format)
+ {
+ m_label->setTextFormat(format);
+ }
+
// Workaround QTCREATORBUG-11653
void calculateMaximumWidth()
{
@@ -189,7 +196,7 @@ public:
QStyledItemDelegate::paint(painter, option, index);
- if (m_parent->model()->data(index, Qt::UserRole).toBool()) {
+ if (m_parent->model()->data(index, ModelAdapter::FixItRole).toBool()) {
const QRect itemRect = m_parent->rectForIndex(index);
const QScrollBar *verticalScrollBar = m_parent->verticalScrollBar();
@@ -205,7 +212,7 @@ public:
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
QSize size(QStyledItemDelegate::sizeHint(option, index));
- if (m_parent->model()->data(index, Qt::UserRole).toBool())
+ if (m_parent->model()->data(index, ModelAdapter::FixItRole).toBool())
size.setWidth(size.width() + m_parent->rectForIndex(index).height() - 5);
return size;
}
@@ -313,6 +320,8 @@ void GenericProposalWidgetPrivate::maybeShowInfoTip()
m_infoFrame = new GenericProposalInfoFrame(m_completionListView);
m_infoFrame->move(m_completionListView->infoFramePos());
+ m_infoFrame->setTextFormat(
+ current.data(ModelAdapter::DetailTextFormatRole).value<Qt::TextFormat>());
m_infoFrame->setText(infoTip);
m_infoFrame->calculateMaximumWidth();
m_infoFrame->adjustSize();
@@ -395,7 +404,7 @@ void GenericProposalWidget::setModel(ProposalModelPtr model)
d->m_completionListView->setModel(new ModelAdapter(d->m_model, d->m_completionListView));
connect(d->m_completionListView->selectionModel(), &QItemSelectionModel::currentChanged,
- &d->m_infoTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
+ &d->m_infoTimer, QOverload<>::of(&QTimer::start));
}
void GenericProposalWidget::setDisplayRect(const QRect &rect)
diff --git a/src/plugins/texteditor/codeassist/iassistproposalmodel.h b/src/plugins/texteditor/codeassist/iassistproposalmodel.h
index 92a6658980..560aff1274 100644
--- a/src/plugins/texteditor/codeassist/iassistproposalmodel.h
+++ b/src/plugins/texteditor/codeassist/iassistproposalmodel.h
@@ -33,7 +33,6 @@ QT_FORWARD_DECLARE_CLASS(QString)
namespace TextEditor {
-
class TEXTEDITOR_EXPORT IAssistProposalModel
{
public:
diff --git a/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp
index 0328542549..b5458e0aa3 100644
--- a/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp
+++ b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp
@@ -25,6 +25,7 @@
#include "keywordscompletionassist.h"
+#include <coreplugin/coreconstants.h>
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/functionhintproposal.h>
@@ -34,7 +35,11 @@
#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditor.h>
+#include <QDir>
+#include <QFileInfo>
+
#include <utils/algorithm.h>
+#include <utils/utilsicons.h>
namespace TextEditor {
@@ -190,10 +195,14 @@ IAssistProposal *KeywordsCompletionAssistProcessor::perform(const AssistInterfac
if (interface->reason() == IdleEditor) {
QChar characterUnderCursor = interface->characterAt(interface->position());
- if (characterUnderCursor.isLetterOrNumber())
- return nullptr;
- if (interface->position() - startPosition < 3)
- return nullptr;
+ if (characterUnderCursor.isLetterOrNumber() || interface->position() - startPosition < 3) {
+ QList<AssistProposalItemInterface *> items;
+ if (m_dynamicCompletionFunction)
+ m_dynamicCompletionFunction(interface, &items, startPosition);
+ if (items.isEmpty())
+ return nullptr;
+ return new GenericProposal(startPosition, items);
+ }
}
// extract word
@@ -210,9 +219,15 @@ IAssistProposal *KeywordsCompletionAssistProcessor::perform(const AssistInterfac
FunctionHintProposalModelPtr model(new KeywordsFunctionHintModel(functionSymbols));
return new FunctionHintProposal(startPosition, model);
} else {
- QList<AssistProposalItemInterface *> items = m_snippetCollector.collect();
- items.append(generateProposalList(m_keywords.variables(), m_variableIcon));
- items.append(generateProposalList(m_keywords.functions(), m_functionIcon));
+ const int originalStartPos = startPosition;
+ QList<AssistProposalItemInterface *> items;
+ if (m_dynamicCompletionFunction)
+ m_dynamicCompletionFunction(interface, &items, startPosition);
+ if (startPosition == originalStartPos) {
+ items.append(m_snippetCollector.collect());
+ items.append(generateProposalList(m_keywords.variables(), m_variableIcon));
+ items.append(generateProposalList(m_keywords.functions(), m_functionIcon));
+ }
return new GenericProposal(startPosition, items);
}
}
@@ -227,6 +242,11 @@ void KeywordsCompletionAssistProcessor::setKeywords(const Keywords &keywords)
m_keywords = keywords;
}
+void KeywordsCompletionAssistProcessor::setDynamicCompletionFunction(DynamicCompletionFunction func)
+{
+ m_dynamicCompletionFunction = func;
+}
+
bool KeywordsCompletionAssistProcessor::isInComment(const AssistInterface *interface) const
{
QTextCursor tc(interface->textDocument());
@@ -252,6 +272,12 @@ KeywordsCompletionAssistProvider::KeywordsCompletionAssistProvider(const Keyword
, m_snippetGroup(snippetGroup)
{ }
+void KeywordsCompletionAssistProvider::setDynamicCompletionFunction(
+ const DynamicCompletionFunction &func)
+{
+ m_completionFunc = func;
+}
+
IAssistProvider::RunType KeywordsCompletionAssistProvider::runType() const
{
return Synchronous;
@@ -261,7 +287,66 @@ IAssistProcessor *KeywordsCompletionAssistProvider::createProcessor() const
{
auto processor = new KeywordsCompletionAssistProcessor(m_keyWords);
processor->setSnippetGroup(m_snippetGroup);
+ processor->setDynamicCompletionFunction(m_completionFunc);
return processor;
}
+void pathComplete(const AssistInterface *interface, QList<AssistProposalItemInterface *> *items,
+ int &startPosition)
+{
+ if (!items)
+ return;
+
+ if (interface->fileName().isEmpty())
+ return;
+
+ // For pragmatic reasons, we don't support spaces in file names here.
+ static const auto canOccurInFilePath = [](const QChar &c) {
+ return c.isLetterOrNumber() || c == '.' || c == '/' || c == "_" || c == '-';
+ };
+
+ int pos = interface->position();
+ QChar chr;
+ // Skip to the start of a name
+ do {
+ chr = interface->characterAt(--pos);
+ } while (canOccurInFilePath(chr));
+
+ const int startPos= ++pos;
+
+ if (interface->reason() == IdleEditor && interface->position() - startPos < 3)
+ return;
+
+ const QString word = interface->textAt(startPos, interface->position() - startPos);
+ QDir baseDir = QFileInfo(interface->fileName()).absoluteDir();
+ const int lastSlashPos = word.lastIndexOf(QLatin1Char('/'));
+
+ QString prefix = word;
+ if (lastSlashPos != -1) {
+ prefix = word.mid(lastSlashPos +1);
+ if (!baseDir.cd(word.left(lastSlashPos)))
+ return;
+ }
+
+ const QFileInfoList entryInfoList
+ = baseDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
+ for (const QFileInfo &entry : entryInfoList) {
+ const QString &fileName = entry.fileName();
+ if (fileName.startsWith(prefix)) {
+ AssistProposalItem *item = new AssistProposalItem;
+ if (entry.isDir()) {
+ item->setText(fileName + QLatin1String("/"));
+ item->setIcon(Utils::Icons::DIR.icon());
+ } else {
+ item->setText(fileName);
+ item->setIcon(Utils::Icons::UNKNOWN_FILE.icon());
+ }
+ *items << item;
+ }
+ }
+ if (!items->empty())
+ startPosition = startPos;
+}
+
+
} // namespace TextEditor
diff --git a/src/plugins/texteditor/codeassist/keywordscompletionassist.h b/src/plugins/texteditor/codeassist/keywordscompletionassist.h
index 6c042e0b05..b968a39e53 100644
--- a/src/plugins/texteditor/codeassist/keywordscompletionassist.h
+++ b/src/plugins/texteditor/codeassist/keywordscompletionassist.h
@@ -82,12 +82,17 @@ private:
QStringList m_functionSymbols;
};
+using DynamicCompletionFunction
+ = std::function<void (const AssistInterface *, QList<AssistProposalItemInterface *> *, int &)>;
+
class TEXTEDITOR_EXPORT KeywordsCompletionAssistProvider : public CompletionAssistProvider
{
public:
KeywordsCompletionAssistProvider(const Keywords &keyWords = Keywords(),
const QString &snippetGroup = QString(Constants::TEXT_SNIPPET_GROUP_ID));
+ void setDynamicCompletionFunction(const DynamicCompletionFunction &func);
+
// IAssistProvider interface
RunType runType() const override;
IAssistProcessor *createProcessor() const override;
@@ -95,6 +100,7 @@ public:
private:
Keywords m_keyWords;
QString m_snippetGroup;
+ DynamicCompletionFunction m_completionFunc;
};
class TEXTEDITOR_EXPORT KeywordsCompletionAssistProcessor : public IAssistProcessor
@@ -107,6 +113,8 @@ public:
void setSnippetGroup(const QString &id);
+ void setDynamicCompletionFunction(DynamicCompletionFunction func);
+
protected:
void setKeywords (const Keywords &keywords);
@@ -118,6 +126,11 @@ private:
const QIcon m_variableIcon;
const QIcon m_functionIcon;
Keywords m_keywords;
+ DynamicCompletionFunction m_dynamicCompletionFunction;
};
+TEXTEDITOR_EXPORT void pathComplete(const AssistInterface *interface,
+ QList<AssistProposalItemInterface *> *items,
+ int &startPosition);
+
} // TextEditor
diff --git a/src/plugins/texteditor/codestylepool.cpp b/src/plugins/texteditor/codestylepool.cpp
index e1dc23df11..7696fe0623 100644
--- a/src/plugins/texteditor/codestylepool.cpp
+++ b/src/plugins/texteditor/codestylepool.cpp
@@ -117,11 +117,9 @@ QString CodeStylePool::settingsDir() const
return customCodeStylesPath().append(suffix);
}
-Utils::FileName CodeStylePool::settingsPath(const QByteArray &id) const
+Utils::FilePath CodeStylePool::settingsPath(const QByteArray &id) const
{
- Utils::FileName path = Utils::FileName::fromString(settingsDir());
- path.appendPath(QString::fromUtf8(id + ".xml"));
- return path;
+ return Utils::FilePath::fromString(settingsDir()).pathAppended(QString::fromUtf8(id + ".xml"));
}
QList<ICodeStylePreferences *> CodeStylePool::codeStyles() const
@@ -220,11 +218,11 @@ void CodeStylePool::loadCustomCodeStyles()
const QString codeStyleFile = codeStyleFiles.at(i);
// filter out styles which id is the same as one of built-in styles
if (!d->m_idToCodeStyle.contains(QFileInfo(codeStyleFile).completeBaseName().toUtf8()))
- loadCodeStyle(Utils::FileName::fromString(dir.absoluteFilePath(codeStyleFile)));
+ loadCodeStyle(Utils::FilePath::fromString(dir.absoluteFilePath(codeStyleFile)));
}
}
-ICodeStylePreferences *CodeStylePool::importCodeStyle(const Utils::FileName &fileName)
+ICodeStylePreferences *CodeStylePool::importCodeStyle(const Utils::FilePath &fileName)
{
ICodeStylePreferences *codeStyle = loadCodeStyle(fileName);
if (codeStyle)
@@ -232,7 +230,7 @@ ICodeStylePreferences *CodeStylePool::importCodeStyle(const Utils::FileName &fil
return codeStyle;
}
-ICodeStylePreferences *CodeStylePool::loadCodeStyle(const Utils::FileName &fileName)
+ICodeStylePreferences *CodeStylePool::loadCodeStyle(const Utils::FilePath &fileName)
{
ICodeStylePreferences *codeStyle = nullptr;
Utils::PersistentSettingsReader reader;
@@ -282,7 +280,7 @@ void CodeStylePool::saveCodeStyle(ICodeStylePreferences *codeStyle) const
exportCodeStyle(settingsPath(codeStyle->id()), codeStyle);
}
-void CodeStylePool::exportCodeStyle(const Utils::FileName &fileName, ICodeStylePreferences *codeStyle) const
+void CodeStylePool::exportCodeStyle(const Utils::FilePath &fileName, ICodeStylePreferences *codeStyle) const
{
QVariantMap map;
codeStyle->toMap(QString(), &map);
diff --git a/src/plugins/texteditor/codestylepool.h b/src/plugins/texteditor/codestylepool.h
index 81c60a657c..150e57013a 100644
--- a/src/plugins/texteditor/codestylepool.h
+++ b/src/plugins/texteditor/codestylepool.h
@@ -29,7 +29,7 @@
#include <QObject>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace TextEditor {
class ICodeStylePreferences;
@@ -61,8 +61,8 @@ public:
void loadCustomCodeStyles();
- ICodeStylePreferences *importCodeStyle(const Utils::FileName &fileName);
- void exportCodeStyle(const Utils::FileName &fileName, ICodeStylePreferences *codeStyle) const;
+ ICodeStylePreferences *importCodeStyle(const Utils::FilePath &fileName);
+ void exportCodeStyle(const Utils::FilePath &fileName, ICodeStylePreferences *codeStyle) const;
signals:
void codeStyleAdded(ICodeStylePreferences *);
@@ -72,8 +72,8 @@ private:
void slotSaveCodeStyle();
QString settingsDir() const;
- Utils::FileName settingsPath(const QByteArray &id) const;
- ICodeStylePreferences *loadCodeStyle(const Utils::FileName &fileName);
+ Utils::FilePath settingsPath(const QByteArray &id) const;
+ ICodeStylePreferences *loadCodeStyle(const Utils::FilePath &fileName);
void saveCodeStyle(ICodeStylePreferences *codeStyle) const;
Internal::CodeStylePoolPrivate *d;
diff --git a/src/plugins/texteditor/codestyleselectorwidget.cpp b/src/plugins/texteditor/codestyleselectorwidget.cpp
index 26a11effdd..2d6f9dd2e0 100644
--- a/src/plugins/texteditor/codestyleselectorwidget.cpp
+++ b/src/plugins/texteditor/codestyleselectorwidget.cpp
@@ -162,7 +162,7 @@ CodeStyleSelectorWidget::CodeStyleSelectorWidget(ICodeStylePreferencesFactory *f
m_ui->importButton->setEnabled(false);
m_ui->exportButton->setEnabled(false);
- connect(m_ui->delegateComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_ui->delegateComboBox, QOverload<int>::of(&QComboBox::activated),
this, &CodeStyleSelectorWidget::slotComboBoxActivated);
connect(m_ui->copyButton, &QAbstractButton::clicked,
this, &CodeStyleSelectorWidget::slotCopyClicked);
@@ -326,8 +326,8 @@ void CodeStyleSelectorWidget::slotRemoveClicked()
void CodeStyleSelectorWidget::slotImportClicked()
{
- const Utils::FileName fileName =
- Utils::FileName::fromString(QFileDialog::getOpenFileName(this, tr("Import Code Style"), QString(),
+ const Utils::FilePath fileName =
+ Utils::FilePath::fromString(QFileDialog::getOpenFileName(this, tr("Import Code Style"), QString(),
tr("Code styles (*.xml);;All files (*)")));
if (!fileName.isEmpty()) {
CodeStylePool *codeStylePool = m_codeStyle->delegatingPool();
@@ -348,7 +348,7 @@ void CodeStyleSelectorWidget::slotExportClicked()
tr("Code styles (*.xml);;All files (*)"));
if (!fileName.isEmpty()) {
CodeStylePool *codeStylePool = m_codeStyle->delegatingPool();
- codeStylePool->exportCodeStyle(Utils::FileName::fromString(fileName), currentPreferences);
+ codeStylePool->exportCodeStyle(Utils::FilePath::fromString(fileName), currentPreferences);
}
}
diff --git a/src/plugins/texteditor/colorschemeedit.cpp b/src/plugins/texteditor/colorschemeedit.cpp
index 76fcf7b29b..ec316880bd 100644
--- a/src/plugins/texteditor/colorschemeedit.cpp
+++ b/src/plugins/texteditor/colorschemeedit.cpp
@@ -169,13 +169,13 @@ ColorSchemeEdit::ColorSchemeEdit(QWidget *parent) :
this, &ColorSchemeEdit::eraseBackColor);
connect(m_ui->eraseForegroundToolButton, &QAbstractButton::clicked,
this, &ColorSchemeEdit::eraseForeColor);
- connect(m_ui->foregroundSaturationSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_ui->foregroundSaturationSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeForeColor);
- connect(m_ui->foregroundLightnessSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_ui->foregroundLightnessSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeForeColor);
- connect(m_ui->backgroundSaturationSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_ui->backgroundSaturationSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeBackColor);
- connect(m_ui->backgroundLightnessSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_ui->backgroundLightnessSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeBackColor);
connect(m_ui->boldCheckBox, &QAbstractButton::toggled,
this, &ColorSchemeEdit::checkCheckBoxes);
@@ -185,7 +185,7 @@ ColorSchemeEdit::ColorSchemeEdit(QWidget *parent) :
this, &ColorSchemeEdit::changeUnderlineColor);
connect(m_ui->eraseUnderlineColorToolButton, &QToolButton::clicked,
this, &ColorSchemeEdit::eraseUnderlineColor);
- connect(m_ui->underlineComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->underlineComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ColorSchemeEdit::changeUnderlineStyle);
connect(m_ui->builtinSchemeLabel, &QLabel::linkActivated, this, &ColorSchemeEdit::copyScheme);
}
diff --git a/src/plugins/texteditor/completionsettings.cpp b/src/plugins/texteditor/completionsettings.cpp
index 61c9f203a8..aca84ef104 100644
--- a/src/plugins/texteditor/completionsettings.cpp
+++ b/src/plugins/texteditor/completionsettings.cpp
@@ -42,6 +42,7 @@ static const char animateAutoCompleteKey[] = "AnimateAutoComplete";
static const char highlightAutoCompleteKey[] = "HighlightAutoComplete";
static const char skipAutoCompleteKey[] = "SkipAutoComplete";
static const char autoRemoveKey[] = "AutoRemove";
+static const char overwriteClosingCharsKey[] = "OverwriteClosingChars";
using namespace TextEditor;
@@ -62,6 +63,7 @@ void CompletionSettings::toSettings(QSettings *s) const
s->setValue(highlightAutoCompleteKey, m_highlightAutoComplete);
s->setValue(skipAutoCompleteKey, m_skipAutoCompletedText);
s->setValue(autoRemoveKey, m_autoRemove);
+ s->setValue(overwriteClosingCharsKey, m_overwriteClosingChars);
s->endGroup();
}
@@ -98,6 +100,8 @@ void CompletionSettings::fromSettings(QSettings *s)
s->value(skipAutoCompleteKey, m_skipAutoCompletedText).toBool();
m_autoRemove =
s->value(autoRemoveKey, m_autoRemove).toBool();
+ m_overwriteClosingChars =
+ s->value(overwriteClosingCharsKey, m_overwriteClosingChars).toBool();
s->endGroup();
}
@@ -117,5 +121,6 @@ bool CompletionSettings::equals(const CompletionSettings &cs) const
&& m_highlightAutoComplete == cs.m_highlightAutoComplete
&& m_skipAutoCompletedText == cs.m_skipAutoCompletedText
&& m_autoRemove == cs.m_autoRemove
+ && m_overwriteClosingChars == cs.m_overwriteClosingChars
;
}
diff --git a/src/plugins/texteditor/completionsettings.h b/src/plugins/texteditor/completionsettings.h
index 9fa75e6152..c670c05443 100644
--- a/src/plugins/texteditor/completionsettings.h
+++ b/src/plugins/texteditor/completionsettings.h
@@ -70,6 +70,7 @@ public:
bool m_highlightAutoComplete = true;
bool m_skipAutoCompletedText = true;
bool m_autoRemove = true;
+ bool m_overwriteClosingChars = false;
};
inline bool operator==(const CompletionSettings &t1, const CompletionSettings &t2) { return t1.equals(t2); }
diff --git a/src/plugins/texteditor/completionsettingspage.cpp b/src/plugins/texteditor/completionsettingspage.cpp
index 8a9a82740c..6c5253ebc6 100644
--- a/src/plugins/texteditor/completionsettingspage.cpp
+++ b/src/plugins/texteditor/completionsettingspage.cpp
@@ -60,8 +60,7 @@ QWidget *CompletionSettingsPage::widget()
m_page = new Ui::CompletionSettingsPage;
m_page->setupUi(m_widget);
- connect(m_page->completionTrigger,
- static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_page->completionTrigger, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &CompletionSettingsPage::onCompletionTriggerChanged);
int caseSensitivityIndex = 0;
@@ -102,6 +101,7 @@ QWidget *CompletionSettingsPage::widget()
m_page->spaceAfterFunctionName->setChecked(m_completionSettings.m_spaceAfterFunctionName);
m_page->autoSplitStrings->setChecked(m_completionSettings.m_autoSplitStrings);
m_page->animateAutoComplete->setChecked(m_completionSettings.m_animateAutoComplete);
+ m_page->overwriteClosingChars->setChecked(m_completionSettings.m_overwriteClosingChars);
m_page->highlightAutoComplete->setChecked(m_completionSettings.m_highlightAutoComplete);
m_page->skipAutoComplete->setChecked(m_completionSettings.m_skipAutoCompletedText);
m_page->removeAutoComplete->setChecked(m_completionSettings.m_autoRemove);
@@ -181,6 +181,7 @@ void CompletionSettingsPage::settingsFromUi(CompletionSettings &completion, Comm
completion.m_spaceAfterFunctionName = m_page->spaceAfterFunctionName->isChecked();
completion.m_autoSplitStrings = m_page->autoSplitStrings->isChecked();
completion.m_animateAutoComplete = m_page->animateAutoComplete->isChecked();
+ completion.m_overwriteClosingChars = m_page->overwriteClosingChars->isChecked();
completion.m_highlightAutoComplete = m_page->highlightAutoComplete->isChecked();
completion.m_skipAutoCompletedText = m_page->skipAutoComplete->isChecked();
completion.m_autoRemove = m_page->removeAutoComplete->isChecked();
diff --git a/src/plugins/texteditor/completionsettingspage.ui b/src/plugins/texteditor/completionsettingspage.ui
index ce3ba046be..59e60cb70e 100644
--- a/src/plugins/texteditor/completionsettingspage.ui
+++ b/src/plugins/texteditor/completionsettingspage.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>551</width>
- <height>493</height>
+ <height>507</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@@ -303,6 +303,16 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
</item>
</layout>
</item>
+ <item row="3" column="1">
+ <widget class="QCheckBox" name="overwriteClosingChars">
+ <property name="toolTip">
+ <string>Automatically overwrite closing parentheses and quotes.</string>
+ </property>
+ <property name="text">
+ <string>Overwrite closing punctuation</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/texteditor/findincurrentfile.cpp b/src/plugins/texteditor/findincurrentfile.cpp
index 13cb63fa96..7c513d96bf 100644
--- a/src/plugins/texteditor/findincurrentfile.cpp
+++ b/src/plugins/texteditor/findincurrentfile.cpp
@@ -71,7 +71,7 @@ Utils::FileIterator *FindInCurrentFile::files(const QStringList &nameFilters,
QVariant FindInCurrentFile::additionalParameters() const
{
- return qVariantFromValue(m_currentDocument->filePath().toString());
+ return QVariant::fromValue(m_currentDocument->filePath().toString());
}
QString FindInCurrentFile::label() const
diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp
index 9c61d76922..4372dd0394 100644
--- a/src/plugins/texteditor/findinfiles.cpp
+++ b/src/plugins/texteditor/findinfiles.cpp
@@ -87,7 +87,7 @@ FileIterator *FindInFiles::files(const QStringList &nameFilters,
QVariant FindInFiles::additionalParameters() const
{
- return qVariantFromValue(path().toString());
+ return QVariant::fromValue(path().toString());
}
QString FindInFiles::label() const
@@ -151,7 +151,7 @@ QWidget *FindInFiles::createConfigWidget()
auto searchEngineLabel = new QLabel(tr("Search engine:"));
gridLayout->addWidget(searchEngineLabel, row, 0, Qt::AlignRight);
m_searchEngineCombo = new QComboBox;
- auto cc = static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged);
+ auto cc = QOverload<int>::of(&QComboBox::currentIndexChanged);
connect(m_searchEngineCombo, cc, this, &FindInFiles::searchEnginesSelectionChanged);
searchEngineLabel->setBuddy(m_searchEngineCombo);
gridLayout->addWidget(m_searchEngineCombo, row, 1);
@@ -203,7 +203,7 @@ QWidget *FindInFiles::createConfigWidget()
return m_configWidget;
}
-FileName FindInFiles::path() const
+FilePath FindInFiles::path() const
{
return m_directory->fileName();
}
@@ -222,17 +222,17 @@ void FindInFiles::readSettings(QSettings *settings)
settings->endGroup();
}
-void FindInFiles::setDirectory(const FileName &directory)
+void FindInFiles::setDirectory(const FilePath &directory)
{
m_directory->setFileName(directory);
}
-void FindInFiles::setBaseDirectory(const FileName &directory)
+void FindInFiles::setBaseDirectory(const FilePath &directory)
{
m_directory->setBaseFileName(directory);
}
-FileName FindInFiles::directory() const
+FilePath FindInFiles::directory() const
{
return m_directory->fileName();
}
@@ -242,7 +242,7 @@ void FindInFiles::findOnFileSystem(const QString &path)
QTC_ASSERT(m_instance, return);
const QFileInfo fi(path);
const QString folder = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath();
- m_instance->setDirectory(FileName::fromString(folder));
+ m_instance->setDirectory(FilePath::fromString(folder));
Find::openFindDialog(m_instance);
}
diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h
index f5df340ebd..54b1315096 100644
--- a/src/plugins/texteditor/findinfiles.h
+++ b/src/plugins/texteditor/findinfiles.h
@@ -56,9 +56,9 @@ public:
void readSettings(QSettings *settings) override;
bool isValid() const override;
- void setDirectory(const Utils::FileName &directory);
- void setBaseDirectory(const Utils::FileName &directory);
- Utils::FileName directory() const;
+ void setDirectory(const Utils::FilePath &directory);
+ void setBaseDirectory(const Utils::FilePath &directory);
+ Utils::FilePath directory() const;
static void findOnFileSystem(const QString &path);
static FindInFiles *instance();
@@ -77,7 +77,7 @@ protected:
private:
void setValid(bool valid);
void searchEnginesSelectionChanged(int index);
- Utils::FileName path() const;
+ Utils::FilePath path() const;
QPointer<QWidget> m_configWidget;
QPointer<Utils::PathChooser> m_directory;
diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp
index 36ee3ac6c6..6911c844a8 100644
--- a/src/plugins/texteditor/fontsettingspage.cpp
+++ b/src/plugins/texteditor/fontsettingspage.cpp
@@ -365,15 +365,14 @@ QWidget *FontSettingsPage::widget()
connect(d_ptr->m_ui->fontComboBox, &QFontComboBox::currentFontChanged,
this, &FontSettingsPage::fontSelected);
connect(d_ptr->m_ui->sizeComboBox,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
+ QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
this, &FontSettingsPage::fontSizeSelected);
- connect(d_ptr->m_ui->zoomSpinBox,
- static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(d_ptr->m_ui->zoomSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &FontSettingsPage::fontZoomChanged);
connect(d_ptr->m_ui->antialias, &QCheckBox::toggled,
this, &FontSettingsPage::antialiasChanged);
connect(d_ptr->m_ui->schemeComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &FontSettingsPage::colorSchemeSelected);
connect(d_ptr->m_ui->copyButton, &QPushButton::clicked,
this, &FontSettingsPage::openCopyColorSchemeDialog);
@@ -587,7 +586,7 @@ void FontSettingsPage::refreshColorSchemeList()
int selected = 0;
QStringList schemeList = styleDir.entryList();
- QString defaultScheme = Utils::FileName::fromString(FontSettings::defaultSchemeFileName()).fileName();
+ QString defaultScheme = Utils::FilePath::fromString(FontSettings::defaultSchemeFileName()).fileName();
if (schemeList.removeAll(defaultScheme))
schemeList.prepend(defaultScheme);
foreach (const QString &file, schemeList) {
diff --git a/src/plugins/texteditor/highlighter.cpp b/src/plugins/texteditor/highlighter.cpp
index ee958795ae..bbeff2a484 100644
--- a/src/plugins/texteditor/highlighter.cpp
+++ b/src/plugins/texteditor/highlighter.cpp
@@ -33,6 +33,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <utils/mimetypes/mimedatabase.h>
+#include <utils/qtcassert.h>
#include <DefinitionDownloader>
#include <Format>
@@ -119,13 +120,15 @@ Highlighter::Definition Highlighter::definitionForDocument(const TextDocument *d
Highlighter::Definition Highlighter::definitionForMimeType(const QString &mimeType)
{
+ if (mimeType.isEmpty())
+ return {};
const Definitions definitions = definitionsForMimeType(mimeType);
if (definitions.size() == 1)
return definitions.first();
return highlightRepository()->definitionForMimeType(mimeType);
}
-Highlighter::Definition Highlighter::definitionForFilePath(const Utils::FileName &fileName)
+Highlighter::Definition Highlighter::definitionForFilePath(const Utils::FilePath &fileName)
{
const Definitions definitions = definitionsForFileName(fileName);
if (definitions.size() == 1)
@@ -140,13 +143,23 @@ Highlighter::Definition Highlighter::definitionForName(const QString &name)
Highlighter::Definitions Highlighter::definitionsForDocument(const TextDocument *document)
{
- const Utils::MimeType mimeType = Utils::mimeTypeForName(document->mimeType());
- Definitions definitions;
- if (mimeType.isValid())
- definitions = Highlighter::definitionsForMimeType(mimeType.name());
- if (definitions.isEmpty())
- definitions = Highlighter::definitionsForFileName(document->filePath());
- return definitions;
+ QTC_ASSERT(document, return {});
+ const Utils::MimeType &mimeType = Utils::mimeTypeForName(document->mimeType());
+ if (mimeType.isValid()) {
+ if (mimeType.name() == "text/plain") {
+ // text/plain is the base mime type for all text types so ignore it and try matching the
+ // file name against the pattern and only if no definition can be found for the
+ // file name try matching the mime type
+ const Definitions &fileNameDefinitions = definitionsForFileName(document->filePath());
+ if (!fileNameDefinitions.isEmpty())
+ return fileNameDefinitions;
+ return definitionsForMimeType(mimeType.name());
+ }
+ const Definitions &mimeTypeDefinitions = definitionsForMimeType(mimeType.name());
+ if (!mimeTypeDefinitions.isEmpty())
+ return mimeTypeDefinitions;
+ }
+ return definitionsForFileName(document->filePath());
}
static Highlighter::Definition definitionForSetting(const QString &settingsKey,
@@ -171,7 +184,7 @@ Highlighter::Definitions Highlighter::definitionsForMimeType(const QString &mime
return definitions;
}
-Highlighter::Definitions Highlighter::definitionsForFileName(const Utils::FileName &fileName)
+Highlighter::Definitions Highlighter::definitionsForFileName(const Utils::FilePath &fileName)
{
Definitions definitions
= highlightRepository()->definitionsForFileName(fileName.fileName()).toList();
@@ -193,6 +206,7 @@ Highlighter::Definitions Highlighter::definitionsForFileName(const Utils::FileNa
void Highlighter::rememberDefintionForDocument(const Highlighter::Definition &definition,
const TextDocument *document)
{
+ QTC_ASSERT(document, return );
if (!definition.isValid())
return;
const QString &mimeType = document->mimeType();
@@ -229,7 +243,7 @@ void Highlighter::clearDefintionForDocumentCache()
settings->endGroup();
}
-void Highlighter::addCustomHighlighterPath(const Utils::FileName &path)
+void Highlighter::addCustomHighlighterPath(const Utils::FilePath &path)
{
highlightRepository()->addCustomSearchPath(path.toString());
}
diff --git a/src/plugins/texteditor/highlighter.h b/src/plugins/texteditor/highlighter.h
index 8777bf006f..33637070af 100644
--- a/src/plugins/texteditor/highlighter.h
+++ b/src/plugins/texteditor/highlighter.h
@@ -47,18 +47,18 @@ public:
static Definition definitionForDocument(const TextDocument *document);
static Definition definitionForMimeType(const QString &mimeType);
- static Definition definitionForFilePath(const Utils::FileName &fileName);
+ static Definition definitionForFilePath(const Utils::FilePath &fileName);
static Definition definitionForName(const QString &name);
static Definitions definitionsForDocument(const TextDocument *document);
static Definitions definitionsForMimeType(const QString &mimeType);
- static Definitions definitionsForFileName(const Utils::FileName &fileName);
+ static Definitions definitionsForFileName(const Utils::FilePath &fileName);
static void rememberDefintionForDocument(const Definition &definition,
const TextDocument *document);
static void clearDefintionForDocumentCache();
- static void addCustomHighlighterPath(const Utils::FileName &path);
+ static void addCustomHighlighterPath(const Utils::FilePath &path);
static void updateDefinitions(std::function<void()> callback = nullptr);
static void handleShutdown();
diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h
index 31dda46800..c377085d9a 100644
--- a/src/plugins/texteditor/indenter.h
+++ b/src/plugins/texteditor/indenter.h
@@ -33,7 +33,7 @@
#include <vector>
namespace Utils {
-class FileName;
+class FilePath;
}
namespace TextEditor {
@@ -74,7 +74,7 @@ public:
: m_doc(doc)
{}
- void setFileName(const Utils::FileName &fileName) { m_fileName = fileName; }
+ void setFileName(const Utils::FilePath &fileName) { m_fileName = fileName; }
virtual ~Indenter() = default;
@@ -137,7 +137,7 @@ public:
protected:
QTextDocument *m_doc;
- Utils::FileName m_fileName;
+ Utils::FilePath m_fileName;
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp
index 1d43972e68..76029cc6fd 100644
--- a/src/plugins/texteditor/refactoringchanges.cpp
+++ b/src/plugins/texteditor/refactoringchanges.cpp
@@ -312,8 +312,7 @@ bool RefactoringFile::apply()
{
// test file permissions
if (!QFileInfo(fileName()).isWritable()) {
- const QString &path = fileName();
- ReadOnlyFilesDialog roDialog(path, ICore::mainWindow());
+ ReadOnlyFilesDialog roDialog(FilePath::fromString(fileName()), ICore::mainWindow());
const QString &failDetailText = QApplication::translate("RefactoringFile::apply",
"Refactoring cannot be applied.");
roDialog.setShowFailWarning(true, failDetailText);
diff --git a/src/plugins/texteditor/refactoroverlay.cpp b/src/plugins/texteditor/refactoroverlay.cpp
index 65ef1dae0a..33a18f818f 100644
--- a/src/plugins/texteditor/refactoroverlay.cpp
+++ b/src/plugins/texteditor/refactoroverlay.cpp
@@ -81,8 +81,9 @@ void RefactorOverlay::paintMarker(const RefactorMarker& marker, QPainter *painte
icon = m_icon;
const qreal devicePixelRatio = painter->device()->devicePixelRatio();
- const QSize proposedIconSize = QSize(m_editor->fontMetrics().width(QLatin1Char(' ')) + 3,
- cursorRect.height()) * devicePixelRatio;
+ const QSize proposedIconSize =
+ QSize(m_editor->fontMetrics().horizontalAdvance(QLatin1Char(' ')) + 3,
+ cursorRect.height()) * devicePixelRatio;
const QSize actualIconSize = icon.actualSize(proposedIconSize) / devicePixelRatio;
const int y = cursorRect.top() + ((cursorRect.height() - actualIconSize.height()) / 2);
diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.cpp b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
index 32daaa503b..c90a13c976 100644
--- a/src/plugins/texteditor/snippets/snippetssettingspage.cpp
+++ b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
@@ -364,7 +364,7 @@ void SnippetsSettingsPagePrivate::configureUi(QWidget *w)
connect(m_model, &QAbstractItemModel::modelReset,
this, &SnippetsSettingsPagePrivate::markSnippetsCollection);
- connect(m_ui.groupCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui.groupCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SnippetsSettingsPagePrivate::loadSnippetGroup);
connect(m_ui.addButton, &QAbstractButton::clicked,
this, &SnippetsSettingsPagePrivate::addSnippet);
diff --git a/src/plugins/texteditor/tabsettingswidget.cpp b/src/plugins/texteditor/tabsettingswidget.cpp
index 08dd90e710..fd4ddb2989 100644
--- a/src/plugins/texteditor/tabsettingswidget.cpp
+++ b/src/plugins/texteditor/tabsettingswidget.cpp
@@ -38,8 +38,8 @@ TabSettingsWidget::TabSettingsWidget(QWidget *parent) :
ui->setupUi(this);
ui->codingStyleWarning->setVisible(false);
- auto comboIndexChanged = static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged);
- auto spinValueChanged = static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
+ auto comboIndexChanged = QOverload<int>::of(&QComboBox::currentIndexChanged);
+ auto spinValueChanged = QOverload<int>::of(&QSpinBox::valueChanged);
connect(ui->codingStyleWarning, &QLabel::linkActivated,
this, &TabSettingsWidget::codingStyleLinkActivated);
connect(ui->tabPolicy, comboIndexChanged,
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index 2bfb51439a..7bf7a2c371 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -100,6 +100,7 @@ public:
QTextDocument m_document;
SyntaxHighlighter *m_highlighter = nullptr;
CompletionAssistProvider *m_completionAssistProvider = nullptr;
+ CompletionAssistProvider *m_functionHintAssistProvider = nullptr;
IAssistProvider *m_quickFixProvider = nullptr;
QScopedPointer<Indenter> m_indenter;
@@ -299,7 +300,7 @@ TextDocument *TextDocument::currentTextDocument()
return qobject_cast<TextDocument *>(EditorManager::currentDocument());
}
-TextDocument *TextDocument::textDocumentForFileName(const Utils::FileName &fileName)
+TextDocument *TextDocument::textDocumentForFileName(const Utils::FilePath &fileName)
{
return qobject_cast<TextDocument *>(DocumentModel::documentForFilePath(fileName.toString()));
}
@@ -363,7 +364,7 @@ void TextDocument::setFontSettings(const FontSettings &fontSettings)
}
QAction *TextDocument::createDiffAgainstCurrentFileAction(
- QObject *parent, const std::function<Utils::FileName()> &filePath)
+ QObject *parent, const std::function<Utils::FilePath()> &filePath)
{
const auto diffAgainstCurrentFile = [filePath]() {
auto diffService = DiffService::instance();
@@ -394,6 +395,16 @@ CompletionAssistProvider *TextDocument::completionAssistProvider() const
return d->m_completionAssistProvider;
}
+void TextDocument::setFunctionHintAssistProvider(CompletionAssistProvider *provider)
+{
+ d->m_functionHintAssistProvider = provider;
+}
+
+CompletionAssistProvider *TextDocument::functionHintAssistProvider() const
+{
+ return d->m_functionHintAssistProvider;
+}
+
void TextDocument::setQuickFixAssistProvider(IAssistProvider *provider) const
{
d->m_quickFixProvider = provider;
@@ -593,7 +604,7 @@ bool TextDocument::save(QString *errorString, const QString &saveFileName, bool
// inform about the new filename
const QFileInfo fi(fName);
d->m_document.setModified(false); // also triggers update of the block revisions
- setFilePath(Utils::FileName::fromUserInput(fi.absoluteFilePath()));
+ setFilePath(Utils::FilePath::fromUserInput(fi.absoluteFilePath()));
emit changed();
return true;
}
@@ -613,11 +624,11 @@ bool TextDocument::shouldAutoSave() const
return d->m_autoSaveRevision != d->m_document.revision();
}
-void TextDocument::setFilePath(const Utils::FileName &newName)
+void TextDocument::setFilePath(const Utils::FilePath &newName)
{
if (newName == filePath())
return;
- IDocument::setFilePath(Utils::FileName::fromUserInput(newName.toFileInfo().absoluteFilePath()));
+ IDocument::setFilePath(Utils::FilePath::fromUserInput(newName.toFileInfo().absoluteFilePath()));
}
bool TextDocument::isFileReadOnly() const
@@ -714,7 +725,7 @@ Core::IDocument::OpenResult TextDocument::openImpl(QString *errorString, const Q
documentLayout->lastSaveRevision = d->m_autoSaveRevision = d->m_document.revision();
d->updateRevisions();
d->m_document.setModified(fileName != realFileName);
- setFilePath(Utils::FileName::fromUserInput(fi.absoluteFilePath()));
+ setFilePath(Utils::FilePath::fromUserInput(fi.absoluteFilePath()));
}
if (readResult == Utils::TextFileFormat::ReadIOError)
return OpenResult::ReadError;
diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h
index 9ea1751b11..a3b8678851 100644
--- a/src/plugins/texteditor/textdocument.h
+++ b/src/plugins/texteditor/textdocument.h
@@ -70,7 +70,7 @@ public:
static QMap<QString, QString> openedTextDocumentContents();
static QMap<QString, QTextCodec *> openedTextDocumentEncodings();
static TextDocument *currentTextDocument();
- static TextDocument *textDocumentForFileName(const Utils::FileName &fileName);
+ static TextDocument *textDocumentForFileName(const Utils::FilePath &fileName);
virtual QString plainText() const;
virtual QString textAt(int pos, int length) const;
@@ -116,7 +116,7 @@ public:
bool isSaveAsAllowed() const override;
void checkPermissions() override;
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
- void setFilePath(const Utils::FileName &newName) override;
+ void setFilePath(const Utils::FilePath &newName) override;
QString fallbackSaveAsPath() const override;
QString fallbackSaveAsFileName() const override;
@@ -141,6 +141,8 @@ public:
void setCompletionAssistProvider(CompletionAssistProvider *provider);
virtual CompletionAssistProvider *completionAssistProvider() const;
+ void setFunctionHintAssistProvider(CompletionAssistProvider *provider);
+ virtual CompletionAssistProvider *functionHintAssistProvider() const;
void setQuickFixAssistProvider(IAssistProvider *provider) const;
virtual IAssistProvider *quickFixAssistProvider() const;
@@ -148,7 +150,7 @@ public:
void setFontSettings(const TextEditor::FontSettings &fontSettings);
static QAction *createDiffAgainstCurrentFileAction(QObject *parent,
- const std::function<Utils::FileName()> &filePath);
+ const std::function<Utils::FilePath()> &filePath);
signals:
void aboutToOpen(const QString &fileName, const QString &realFileName);
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 59926e31ea..2250b6fb5b 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -106,6 +106,7 @@
#include <QScrollBar>
#include <QShortcut>
#include <QStyle>
+#include <QStyleFactory>
#include <QTextBlock>
#include <QTextCodec>
#include <QTextCursor>
@@ -1010,8 +1011,8 @@ void TextEditorWidgetPrivate::ctor(const QSharedPointer<TextDocument> &doc)
QObject::connect(q, &QPlainTextEdit::blockCountChanged,
this, &TextEditorWidgetPrivate::slotUpdateExtraAreaWidth);
- QObject::connect(q, &QPlainTextEdit::modificationChanged, m_extraArea,
- static_cast<void (QWidget::*)()>(&QWidget::update));
+ QObject::connect(q, &QPlainTextEdit::modificationChanged,
+ m_extraArea, QOverload<>::of(&QWidget::update));
QObject::connect(q, &QPlainTextEdit::cursorPositionChanged,
q, &TextEditorWidget::slotCursorPositionChanged);
@@ -1047,8 +1048,8 @@ void TextEditorWidgetPrivate::ctor(const QSharedPointer<TextDocument> &doc)
q->setFrameStyle(QFrame::NoFrame);
m_delayedUpdateTimer.setSingleShot(true);
- QObject::connect(&m_delayedUpdateTimer, &QTimer::timeout, q->viewport(),
- static_cast<void (QWidget::*)()>(&QWidget::update));
+ QObject::connect(&m_delayedUpdateTimer, &QTimer::timeout,
+ q->viewport(), QOverload<>::of(&QWidget::update));
m_moveLineUndoHack = false;
@@ -2011,19 +2012,22 @@ void TextEditorWidgetPrivate::moveLineUpDown(bool up)
bool shouldReindent = true;
if (m_commentDefinition.isValid()) {
- QString trimmedText(text.trimmed());
-
- if (m_commentDefinition.hasSingleLineStyle()) {
- if (trimmedText.startsWith(m_commentDefinition.singleLine))
- shouldReindent = false;
- }
- if (shouldReindent && m_commentDefinition.hasMultiLineStyle()) {
+ if (m_commentDefinition.hasMultiLineStyle()) {
// Don't have any single line comments; try multi line.
- if (trimmedText.startsWith(m_commentDefinition.multiLineStart)
- && trimmedText.endsWith(m_commentDefinition.multiLineEnd)) {
+ if (text.startsWith(m_commentDefinition.multiLineStart)
+ && text.endsWith(m_commentDefinition.multiLineEnd)) {
shouldReindent = false;
}
}
+ if (shouldReindent && m_commentDefinition.hasSingleLineStyle()) {
+ shouldReindent = false;
+ QTextBlock block = move.block();
+ while (block.isValid() && block.position() < end) {
+ if (!block.text().startsWith(m_commentDefinition.singleLine))
+ shouldReindent = true;
+ block = block.next();
+ }
+ }
}
if (shouldReindent) {
@@ -3470,7 +3474,7 @@ void TextEditorWidgetPrivate::setupDocumentSignals()
this, &TextEditorWidgetPrivate::slotUpdateBlockNotify);
QObject::connect(documentLayout, &TextDocumentLayout::updateExtraArea,
- m_extraArea, static_cast<void (QWidget::*)()>(&QWidget::update));
+ m_extraArea, QOverload<>::of(&QWidget::update));
QObject::connect(q, &TextEditorWidget::requestBlockUpdate,
documentLayout, &QPlainTextDocumentLayout::updateBlock);
@@ -3738,7 +3742,7 @@ QTextBlock TextEditorWidgetPrivate::foldedBlockAt(const QPoint &pos, QRect *box)
QRectF collapseRect(lineRect.right() + 12,
lineRect.top(),
- q->fontMetrics().width(replacement),
+ q->fontMetrics().horizontalAdvance(replacement),
lineRect.height());
if (collapseRect.contains(pos)) {
QTextBlock result = block;
@@ -4229,7 +4233,7 @@ void TextEditorWidgetPrivate::updateLineAnnotation(const PaintEventData &data,
const qreal itemOffset = q->fontMetrics().lineSpacing();
const qreal initialOffset = m_displaySettings.m_annotationAlignment == AnnotationAlignment::BetweenLines ? itemOffset / 2 : itemOffset * 2;
- const qreal minimalContentWidth = q->fontMetrics().width('X')
+ const qreal minimalContentWidth = q->fontMetrics().horizontalAdvance('X')
* m_displaySettings.m_minimalAnnotationContent;
qreal offset = initialOffset;
qreal x = 0;
@@ -4545,7 +4549,7 @@ void TextEditorWidgetPrivate::paintBlockSelection(const PaintEventData &data, QP
QString text = data.block.text();
const TabSettings tabSettings = m_document->tabSettings();
const qreal spacew = QFontMetricsF(q->font()).width(QLatin1Char(' '));
- const int cursorw = q->overwriteMode() ? QFontMetrics(q->font()).width(QLatin1Char(' '))
+ const int cursorw = q->overwriteMode() ? QFontMetrics(q->font()).horizontalAdvance(QLatin1Char(' '))
: q->cursorWidth();
int startOffset = 0;
@@ -4704,7 +4708,7 @@ void TextEditorWidgetPrivate::paintReplacement(PaintEventData &data, QPainter &p
QRectF collapseRect(lineRect.right() + 12,
lineRect.top(),
- q->fontMetrics().width(rectReplacement),
+ q->fontMetrics().horizontalAdvance(rectReplacement),
lineRect.height());
painter.setRenderHint(QPainter::Antialiasing, true);
painter.translate(.5, .5);
@@ -5100,7 +5104,7 @@ int TextEditorWidget::extraAreaWidth(int *markWidthPtr) const
fnt.setItalic(currentLineNumberFormat.font().italic());
const QFontMetrics linefm(fnt);
- space += linefm.width(QLatin1Char('9')) * lineNumberDigits();
+ space += linefm.horizontalAdvance(QLatin1Char('9')) * lineNumberDigits();
}
int markWidth = 0;
@@ -5360,7 +5364,19 @@ void TextEditorWidgetPrivate::drawFoldingMarker(QPainter *painter, const QPalett
if (hovered)
opt.palette.setBrush(QPalette::Window, pal.highlight());
- const char* const className = s->metaObject()->className();
+ const char *className = s->metaObject()->className();
+
+ // Do not use the windows folding marker since we cannot style them and the default hover color
+ // is a blue which does not guarantee an high contrast on all themes.
+ static QPointer<QStyle> fusionStyleOverwrite = nullptr;
+ if (!qstrcmp(className, "QWindowsVistaStyle")) {
+ if (fusionStyleOverwrite.isNull())
+ fusionStyleOverwrite = QStyleFactory::create("fusion");
+ if (!fusionStyleOverwrite.isNull()) {
+ s = fusionStyleOverwrite.data();
+ className = s->metaObject()->className();
+ }
+ }
if (!qstrcmp(className, "OxygenStyle")) {
const QStyle::PrimitiveElement direction = expanded ? QStyle::PE_IndicatorArrowDown
@@ -5819,6 +5835,11 @@ void TextEditorWidget::addHoverHandler(BaseHoverHandler *handler)
d->m_hoverHandlers.append(handler);
}
+void TextEditorWidget::removeHoverHandler(BaseHoverHandler *handler)
+{
+ d->m_hoverHandlers.removeAll(handler);
+}
+
void TextEditorWidget::extraAreaLeaveEvent(QEvent *)
{
d->extraAreaPreviousMarkTooltipRequestedLine = -1;
@@ -6636,7 +6657,7 @@ void TextEditorAnimator::init(const QTextCursor &cursor, const QFont &f, const Q
m_palette = pal;
m_text = cursor.selectedText();
QFontMetrics fm(m_font);
- m_size = QSizeF(fm.width(m_text), fm.height());
+ m_size = QSizeF(fm.horizontalAdvance(m_text), fm.height());
}
void TextEditorAnimator::draw(QPainter *p, const QPointF &pos)
@@ -6646,7 +6667,7 @@ void TextEditorAnimator::draw(QPainter *p, const QPointF &pos)
QFont f = m_font;
f.setPointSizeF(f.pointSizeF() * (1.0 + m_value/2));
QFontMetrics fm(f);
- int width = fm.width(m_text);
+ int width = fm.horizontalAdvance(m_text);
QRectF r((m_size.width()-width)/2, (m_size.height() - fm.height())/2, width, fm.height());
r.translate(pos);
p->fillRect(r, m_palette.base());
@@ -6664,7 +6685,7 @@ QRectF TextEditorAnimator::rect() const
QFont f = m_font;
f.setPointSizeF(f.pointSizeF() * (1.0 + m_value/2));
QFontMetrics fm(f);
- int width = fm.width(m_text);
+ int width = fm.horizontalAdvance(m_text);
return QRectF((m_size.width()-width)/2, (m_size.height() - fm.height())/2, width, fm.height());
}
@@ -7513,6 +7534,7 @@ void TextEditorWidget::setCompletionSettings(const CompletionSettings &completio
d->m_autoCompleter->setSurroundWithBracketsEnabled(completionSettings.m_surroundingAutoBrackets);
d->m_autoCompleter->setAutoInsertQuotesEnabled(completionSettings.m_autoInsertQuotes);
d->m_autoCompleter->setSurroundWithQuotesEnabled(completionSettings.m_surroundingAutoQuotes);
+ d->m_autoCompleter->setOverwriteClosingCharsEnabled(completionSettings.m_overwriteClosingChars);
d->m_animateAutoComplete = completionSettings.m_animateAutoComplete;
d->m_highlightAutoComplete = completionSettings.m_highlightAutoComplete;
d->m_skipAutoCompletedText = completionSettings.m_skipAutoCompletedText;
@@ -8277,11 +8299,7 @@ void TextEditorWidgetPrivate::updateTabStops()
// to be set as an int. A work around is to access directly the QTextOption.
qreal charWidth = QFontMetricsF(q->font()).width(QLatin1Char(' '));
QTextOption option = q->document()->defaultTextOption();
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
option.setTabStopDistance(charWidth * m_document->tabSettings().m_tabSize);
-#else
- option.setTabStop(charWidth * m_document->tabSettings().m_tabSize);
-#endif
q->document()->setDefaultTextOption(option);
}
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index 3d079bf77f..08b6738a5e 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -474,6 +474,9 @@ public:
Core::HighlightScrollBarController *highlightScrollBarController() const;
+ void addHoverHandler(BaseHoverHandler *handler);
+ void removeHoverHandler(BaseHoverHandler *handler);
+
signals:
void assistFinished(); // Used in tests.
void readOnlyChanged();
@@ -534,8 +537,6 @@ protected:
virtual void finalizeInitializationAfterDuplication(TextEditorWidget *) {}
static QTextCursor flippedCursor(const QTextCursor &cursor);
- void addHoverHandler(BaseHoverHandler *handler);
-
public:
QString selectedText() const;
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index 29231afb82..a0182a6f08 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -1,5 +1,5 @@
DEFINES += TEXTEDITOR_LIBRARY
-QT += gui-private network printsupport xml
+QT += network printsupport xml
CONFIG += exceptions
CONFIG += include_source_dir # For the highlighter autotest.
diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp
index 78cea2b828..bdc7e7a583 100644
--- a/src/plugins/texteditor/texteditorsettings.cpp
+++ b/src/plugins/texteditor/texteditorsettings.cpp
@@ -47,6 +47,7 @@
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
#include <utils/qtcassert.h>
#include <QApplication>
@@ -367,14 +368,27 @@ TextEditorSettings::TextEditorSettings()
new SnippetsSettingsPage(Constants::TEXT_EDITOR_SNIPPETS_SETTINGS, this);
d->m_completionSettingsPage = new CompletionSettingsPage(this);
+ auto updateGeneralMessagesFontSettings = []() {
+ Core::MessageManager::setFont(d->m_fontSettingsPage->fontSettings().font());
+ };
connect(d->m_fontSettingsPage, &FontSettingsPage::changed,
this, &TextEditorSettings::fontSettingsChanged);
+ connect(d->m_fontSettingsPage, &FontSettingsPage::changed,
+ this, updateGeneralMessagesFontSettings);
+ updateGeneralMessagesFontSettings();
connect(d->m_behaviorSettingsPage, &BehaviorSettingsPage::typingSettingsChanged,
this, &TextEditorSettings::typingSettingsChanged);
connect(d->m_behaviorSettingsPage, &BehaviorSettingsPage::storageSettingsChanged,
this, &TextEditorSettings::storageSettingsChanged);
+ auto updateGeneralMessagesBehaviorSettings = []() {
+ bool wheelZoom = d->m_behaviorSettingsPage->behaviorSettings().m_scrollWheelZooming;
+ Core::MessageManager::setWheelZoomEnabled(wheelZoom);
+ };
connect(d->m_behaviorSettingsPage, &BehaviorSettingsPage::behaviorSettingsChanged,
this, &TextEditorSettings::behaviorSettingsChanged);
+ connect(d->m_behaviorSettingsPage, &BehaviorSettingsPage::behaviorSettingsChanged,
+ this, updateGeneralMessagesBehaviorSettings);
+ updateGeneralMessagesBehaviorSettings();
connect(d->m_behaviorSettingsPage, &BehaviorSettingsPage::extraEncodingSettingsChanged,
this, &TextEditorSettings::extraEncodingSettingsChanged);
connect(d->m_displaySettingsPage, &DisplaySettingsPage::marginSettingsChanged,
diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp
index 49ce797f88..3493570487 100644
--- a/src/plugins/texteditor/textmark.cpp
+++ b/src/plugins/texteditor/textmark.cpp
@@ -58,7 +58,7 @@ private:
void documentRenamed(Core::IDocument *document, const QString &oldName, const QString &newName);
void allDocumentsRenamed(const QString &oldName, const QString &newName);
- QHash<Utils::FileName, QSet<TextMark *> > m_marks;
+ QHash<Utils::FilePath, QSet<TextMark *> > m_marks;
};
class AnnotationColors
@@ -78,7 +78,7 @@ private:
TextMarkRegistry *m_instance = nullptr;
-TextMark::TextMark(const FileName &fileName, int lineNumber, Id category, double widthFactor)
+TextMark::TextMark(const FilePath &fileName, int lineNumber, Id category, double widthFactor)
: m_fileName(fileName)
, m_lineNumber(lineNumber)
, m_visible(true)
@@ -100,12 +100,12 @@ TextMark::~TextMark()
m_baseTextDocument = nullptr;
}
-FileName TextMark::fileName() const
+FilePath TextMark::fileName() const
{
return m_fileName;
}
-void TextMark::updateFileName(const FileName &fileName)
+void TextMark::updateFileName(const FilePath &fileName)
{
if (fileName == m_fileName)
return;
@@ -182,7 +182,7 @@ TextMark::AnnotationRects TextMark::annotationRects(const QRectF &boundingRect,
if (drawIcon)
rects.iconRect.setWidth(rects.iconRect.height() * m_widthFactor);
rects.textRect = QRectF(rects.iconRect.right() + margin, boundingRect.top(),
- qreal(fm.width(rects.text)), boundingRect.height());
+ qreal(fm.horizontalAdvance(rects.text)), boundingRect.height());
rects.annotationRect.setRight(rects.textRect.right() + margin);
if (rects.annotationRect.right() > boundingRect.right()) {
rects.textRect.setRight(boundingRect.right() - margin);
@@ -398,8 +398,8 @@ void TextMarkRegistry::documentRenamed(IDocument *document, const
auto baseTextDocument = qobject_cast<TextDocument *>(document);
if (!baseTextDocument)
return;
- FileName oldFileName = FileName::fromString(oldName);
- FileName newFileName = FileName::fromString(newName);
+ FilePath oldFileName = FilePath::fromString(oldName);
+ FilePath newFileName = FilePath::fromString(newName);
if (!m_marks.contains(oldFileName))
return;
@@ -416,8 +416,8 @@ void TextMarkRegistry::documentRenamed(IDocument *document, const
void TextMarkRegistry::allDocumentsRenamed(const QString &oldName, const QString &newName)
{
- FileName oldFileName = FileName::fromString(oldName);
- FileName newFileName = FileName::fromString(newName);
+ FilePath oldFileName = FilePath::fromString(oldName);
+ FilePath newFileName = FilePath::fromString(newName);
if (!m_marks.contains(oldFileName))
return;
diff --git a/src/plugins/texteditor/textmark.h b/src/plugins/texteditor/textmark.h
index eeeb761eaf..2d049cbacc 100644
--- a/src/plugins/texteditor/textmark.h
+++ b/src/plugins/texteditor/textmark.h
@@ -50,7 +50,7 @@ class TextDocument;
class TEXTEDITOR_EXPORT TextMark
{
public:
- TextMark(const Utils::FileName &fileName,
+ TextMark(const Utils::FilePath &fileName,
int lineNumber,
Core::Id category,
double widthFactor = 1.0);
@@ -65,7 +65,7 @@ public:
HighPriority // shown on top.
};
- Utils::FileName fileName() const;
+ Utils::FilePath fileName() const;
int lineNumber() const;
virtual void paintIcon(QPainter *painter, const QRect &rect) const;
@@ -84,7 +84,7 @@ public:
AnnotationRects annotationRects(const QRectF &boundingRect, const QFontMetrics &fm,
const qreal fadeInOffset, const qreal fadeOutOffset) const;
/// called if the filename of the document changed
- virtual void updateFileName(const Utils::FileName &fileName);
+ virtual void updateFileName(const Utils::FilePath &fileName);
virtual void updateLineNumber(int lineNumber);
virtual void updateBlock(const QTextBlock &block);
virtual void move(int line);
@@ -131,7 +131,7 @@ private:
Q_DISABLE_COPY(TextMark)
TextDocument *m_baseTextDocument = nullptr;
- Utils::FileName m_fileName;
+ Utils::FilePath m_fileName;
int m_lineNumber = 0;
Priority m_priority = LowPriority;
QIcon m_icon;
diff --git a/src/plugins/todo/CMakeLists.txt b/src/plugins/todo/CMakeLists.txt
new file mode 100644
index 0000000000..6283407272
--- /dev/null
+++ b/src/plugins/todo/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_qtc_plugin(Todo
+ DEPENDS qmljs
+ PLUGIN_DEPENDS Core CppTools ProjectExplorer
+ SOURCES
+ constants.h
+ cpptodoitemsscanner.cpp cpptodoitemsscanner.h
+ keyword.cpp keyword.h
+ keyworddialog.cpp keyworddialog.h keyworddialog.ui
+ lineparser.cpp lineparser.h
+ optionsdialog.cpp optionsdialog.h optionsdialog.ui
+ optionspage.cpp optionspage.h
+ qmljstodoitemsscanner.cpp qmljstodoitemsscanner.h
+ settings.cpp settings.h
+ todoicons.cpp todoicons.h
+ todoitem.h
+ todoitemsmodel.cpp todoitemsmodel.h
+ todoitemsprovider.cpp todoitemsprovider.h
+ todoitemsscanner.cpp todoitemsscanner.h
+ todooutputpane.cpp todooutputpane.h
+ todooutputtreeview.cpp todooutputtreeview.h
+ todooutputtreeviewdelegate.cpp todooutputtreeviewdelegate.h
+ todoplugin.cpp todoplugin.h
+ todoplugin.qrc
+ todoprojectsettingswidget.cpp todoprojectsettingswidget.h todoprojectsettingswidget.ui
+)
diff --git a/src/plugins/todo/cpptodoitemsscanner.cpp b/src/plugins/todo/cpptodoitemsscanner.cpp
index 46b6f3d9a7..938f7922fc 100644
--- a/src/plugins/todo/cpptodoitemsscanner.cpp
+++ b/src/plugins/todo/cpptodoitemsscanner.cpp
@@ -60,7 +60,7 @@ void CppTodoItemsScanner::scannerParamsChanged()
QSet<QString> filesToBeUpdated;
foreach (const CppTools::ProjectInfo &info, modelManager->projectInfos())
filesToBeUpdated.unite(Utils::transform(info.project().data()->files(ProjectExplorer::Project::SourceFiles),
- &Utils::FileName::toString).toSet());
+ &Utils::FilePath::toString).toSet());
modelManager->updateSourceFiles(filesToBeUpdated);
}
diff --git a/src/plugins/todo/todoitem.h b/src/plugins/todo/todoitem.h
index be38f85ae7..f44cf0b42c 100644
--- a/src/plugins/todo/todoitem.h
+++ b/src/plugins/todo/todoitem.h
@@ -42,7 +42,7 @@ class TodoItem
{
public:
QString text;
- Utils::FileName file;
+ Utils::FilePath file;
int line = -1;
IconType iconType = IconType::Todo;
QColor color;
diff --git a/src/plugins/todo/todoitemsprovider.cpp b/src/plugins/todo/todoitemsprovider.cpp
index 99ca36fc23..c2f958bb4e 100644
--- a/src/plugins/todo/todoitemsprovider.cpp
+++ b/src/plugins/todo/todoitemsprovider.cpp
@@ -45,6 +45,7 @@
#include <QTimer>
using namespace ProjectExplorer;
+using namespace Utils;
namespace Todo {
namespace Internal {
@@ -90,7 +91,7 @@ void TodoItemsProvider::updateList()
// Show only items of the current file if any
if (m_settings.scanningScope == ScanningScopeCurrentFile) {
if (m_currentEditor)
- m_itemsList = m_itemsHash.value(m_currentEditor->document()->filePath().toString());
+ m_itemsList = m_itemsHash.value(m_currentEditor->document()->filePath());
// Show only items of the current sub-project
} else if (m_settings.scanningScope == ScanningScopeSubProject) {
if (m_startupProject)
@@ -121,21 +122,19 @@ void TodoItemsProvider::createScanners()
void TodoItemsProvider::setItemsListWithinStartupProject()
{
- QHashIterator<QString, QList<TodoItem> > it(m_itemsHash);
- const QSet<QString> fileNames
- = QSet<QString>::fromList(Utils::transform(m_startupProject->files(Project::SourceFiles),
- &Utils::FileName::toString));
+ QHashIterator<FilePath, QList<TodoItem> > it(m_itemsHash);
+ const auto filePaths = QSet<FilePath>::fromList(m_startupProject->files(Project::SourceFiles));
QVariantMap settings = m_startupProject->namedSettings(Constants::SETTINGS_NAME_KEY).toMap();
while (it.hasNext()) {
it.next();
- QString fileName = it.key();
- if (fileNames.contains(fileName)) {
+ const FilePath filePath = it.key();
+ if (filePaths.contains(filePath)) {
bool skip = false;
for (const QVariant &pattern : settings[Constants::EXCLUDES_LIST_KEY].toList()) {
QRegExp re(pattern.toString());
- if (re.indexIn(fileName) != -1) {
+ if (re.indexIn(filePath.toString()) != -1) {
skip = true;
break;
}
@@ -149,27 +148,24 @@ void TodoItemsProvider::setItemsListWithinStartupProject()
void TodoItemsProvider::setItemsListWithinSubproject()
{
// TODO prefer current editor as source of sub-project
- const Node *node = ProjectTree::findCurrentNode();
+ const Node *node = ProjectTree::currentNode();
if (node) {
ProjectNode *projectNode = node->parentProjectNode();
if (projectNode) {
// FIXME: The name doesn't match the implementation that lists all files.
- QSet<Utils::FileName> subprojectFileNames;
+ QSet<FilePath> subprojectFileNames;
projectNode->forEachGenericNode([&](Node *node) {
subprojectFileNames.insert(node->filePath());
});
// files must be both in the current subproject and the startup-project.
- const QSet<QString> fileNames
- = QSet<QString>::fromList(Utils::transform(m_startupProject->files(Project::SourceFiles),
- &Utils::FileName::toString));
- QHashIterator<QString, QList<TodoItem> > it(m_itemsHash);
+ const auto fileNames
+ = QSet<FilePath>::fromList(m_startupProject->files(Project::SourceFiles));
+ QHashIterator<FilePath, QList<TodoItem> > it(m_itemsHash);
while (it.hasNext()) {
it.next();
- if (subprojectFileNames.contains(Utils::FileName::fromString(it.key()))
- && fileNames.contains(it.key())) {
+ if (subprojectFileNames.contains(it.key()) && fileNames.contains(it.key()))
m_itemsList << it.value();
- }
}
}
}
@@ -178,7 +174,7 @@ void TodoItemsProvider::setItemsListWithinSubproject()
void TodoItemsProvider::itemsFetched(const QString &fileName, const QList<TodoItem> &items)
{
// Replace old items with new ones
- m_itemsHash.insert(fileName, items);
+ m_itemsHash.insert(FilePath::fromString(fileName), items);
m_shouldUpdateList = true;
}
diff --git a/src/plugins/todo/todoitemsprovider.h b/src/plugins/todo/todoitemsprovider.h
index 234025bfec..f2d1f33a10 100644
--- a/src/plugins/todo/todoitemsprovider.h
+++ b/src/plugins/todo/todoitemsprovider.h
@@ -60,7 +60,7 @@ private:
TodoItemsModel *m_itemsModel;
// All to-do items are stored here regardless current scanning scope
- QHash<QString, QList<TodoItem> > m_itemsHash;
+ QHash<Utils::FilePath, QList<TodoItem> > m_itemsHash;
// This list contains only those to-do items that are within current scanning scope
QList<TodoItem> m_itemsList;
diff --git a/src/plugins/todo/todoitemsscanner.cpp b/src/plugins/todo/todoitemsscanner.cpp
index 9b3a25dbfa..f9c57cccb7 100644
--- a/src/plugins/todo/todoitemsscanner.cpp
+++ b/src/plugins/todo/todoitemsscanner.cpp
@@ -54,7 +54,7 @@ void TodoItemsScanner::processCommentLine(const QString &fileName, const QString
for (int i = 0; i < newItemList.count(); ++i) {
newItemList[i].line = lineNumber;
- newItemList[i].file = Utils::FileName::fromString(fileName);
+ newItemList[i].file = Utils::FilePath::fromString(fileName);
}
outItemList << newItemList;
diff --git a/src/plugins/todo/todooutputpane.cpp b/src/plugins/todo/todooutputpane.cpp
index 0becced031..9f8a528124 100644
--- a/src/plugins/todo/todooutputpane.cpp
+++ b/src/plugins/todo/todooutputpane.cpp
@@ -91,7 +91,7 @@ int TodoOutputPane::priorityInStatusBar() const
void TodoOutputPane::clearContents()
{
- clearFilter();
+ clearKeywordFilter();
}
void TodoOutputPane::visibilityChanged(bool visible)
@@ -176,7 +176,7 @@ void TodoOutputPane::todoTreeViewClicked(const QModelIndex &index)
TodoItem item;
item.text = index.sibling(row, Constants::OUTPUT_COLUMN_TEXT).data().toString();
- item.file = Utils::FileName::fromUserInput(index.sibling(row, Constants::OUTPUT_COLUMN_FILE).data().toString());
+ item.file = Utils::FilePath::fromUserInput(index.sibling(row, Constants::OUTPUT_COLUMN_FILE).data().toString());
item.line = index.sibling(row, Constants::OUTPUT_COLUMN_LINE).data().toInt();
item.color = index.data(Qt::TextColorRole).value<QColor>();
item.iconType = static_cast<IconType>(index.sibling(row, Constants::OUTPUT_COLUMN_TEXT)
@@ -190,7 +190,7 @@ void TodoOutputPane::updateTodoCount()
emit setBadgeNumber(m_todoTreeView->model()->rowCount());
}
-void TodoOutputPane::updateFilter()
+void TodoOutputPane::updateKeywordFilter()
{
QStringList keywords;
for (const QToolButton *btn: qAsConst(m_filterButtons)) {
@@ -208,12 +208,12 @@ void TodoOutputPane::updateFilter()
updateTodoCount();
}
-void TodoOutputPane::clearFilter()
+void TodoOutputPane::clearKeywordFilter()
{
for (QToolButton *btn: qAsConst(m_filterButtons))
btn->setChecked(false);
- updateFilter();
+ updateKeywordFilter();
}
void TodoOutputPane::createTreeView()
@@ -271,7 +271,7 @@ void TodoOutputPane::createScopeButtons()
m_scopeButtons->addButton(m_wholeProjectButton);
m_scopeButtons->addButton(m_currentFileButton);
m_scopeButtons->addButton(m_subProjectButton);
- connect(m_scopeButtons, static_cast<void (QButtonGroup::*)(QAbstractButton *)>(&QButtonGroup::buttonClicked),
+ connect(m_scopeButtons, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
this, &TodoOutputPane::scopeButtonClicked);
m_spacer = new QWidget;
@@ -282,7 +282,7 @@ void TodoOutputPane::createScopeButtons()
QToolButton *button = createCheckableToolButton(keyword.name, tooltip.arg(keyword.name), toolBarIcon(keyword.iconType));
button->setProperty(Constants::FILTER_KEYWORD_NAME, keyword.name);
button->setToolButtonStyle(Qt::ToolButtonIconOnly);
- connect(button, &QToolButton::clicked, this, &TodoOutputPane::updateFilter);
+ connect(button, &QToolButton::clicked, this, &TodoOutputPane::updateKeywordFilter);
m_filterButtons.append(button);
}
diff --git a/src/plugins/todo/todooutputpane.h b/src/plugins/todo/todooutputpane.h
index 0c99d0a04a..78b0aff45d 100644
--- a/src/plugins/todo/todooutputpane.h
+++ b/src/plugins/todo/todooutputpane.h
@@ -80,8 +80,8 @@ private:
void scopeButtonClicked(QAbstractButton *button);
void todoTreeViewClicked(const QModelIndex &index);
void updateTodoCount();
- void updateFilter();
- void clearFilter();
+ void updateKeywordFilter();
+ void clearKeywordFilter();
void createTreeView();
void freeTreeView();
diff --git a/src/plugins/updateinfo/CMakeLists.txt b/src/plugins/updateinfo/CMakeLists.txt
new file mode 100644
index 0000000000..fe43e0be09
--- /dev/null
+++ b/src/plugins/updateinfo/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_plugin(UpdateInfo
+ DEPENDS Qt5::Xml
+ PLUGIN_DEPENDS Core
+ PLUGIN_JSON_IN UPDATEINFO_EXPERIMENTAL_STR=true
+ SOURCES
+ settingspage.cpp settingspage.h settingspage.ui
+ updateinfoplugin.cpp updateinfoplugin.h
+)
diff --git a/src/plugins/updateinfo/settingspage.cpp b/src/plugins/updateinfo/settingspage.cpp
index c142375383..82a9cf48de 100644
--- a/src/plugins/updateinfo/settingspage.cpp
+++ b/src/plugins/updateinfo/settingspage.cpp
@@ -73,7 +73,7 @@ QWidget *SettingsPage::widget()
connect(m_ui.m_checkNowButton, &QPushButton::clicked,
m_plugin, &UpdateInfoPlugin::startCheckForUpdates);
connect(m_ui.m_checkIntervalComboBox,
- static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SettingsPage::updateNextCheckDate);
connect(m_plugin, &UpdateInfoPlugin::lastCheckDateChanged,
this, &SettingsPage::updateLastCheckDate);
diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp
index 8f9e5da6fa..08e644bc5e 100644
--- a/src/plugins/updateinfo/updateinfoplugin.cpp
+++ b/src/plugins/updateinfo/updateinfoplugin.cpp
@@ -67,6 +67,7 @@ class UpdateInfoPluginPrivate
public:
QString m_maintenanceTool;
QPointer<ShellCommand> m_checkUpdatesCommand;
+ QPointer<FutureProgress> m_progress;
QString m_collectedOutput;
QTimer *m_checkUpdatesTimer = nullptr;
@@ -124,13 +125,19 @@ void UpdateInfoPlugin::startCheckForUpdates()
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert(QLatin1String("QT_LOGGING_RULES"), QLatin1String("*=false"));
d->m_checkUpdatesCommand = new ShellCommand(QString(), env);
+ 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::FileName(QFileInfo(d->m_maintenanceTool)), QStringList(QLatin1String("--checkupdates")),
+ d->m_checkUpdatesCommand->addJob(Utils::FilePath::fromFileInfo(d->m_maintenanceTool), {"--checkupdates"},
60 * 3, // 3 minutes timeout
/*workingDirectory=*/QString(),
[](int /*exitCode*/) { return Utils::SynchronousProcessResponse::Finished; });
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);
+ }
emit checkForUpdatesRunningChanged(true);
}
@@ -168,6 +175,8 @@ void UpdateInfoPlugin::checkForUpdatesFinished()
startUpdater();
} else {
emit newUpdatesAvailable(false);
+ if (d->m_progress)
+ d->m_progress->setSubtitle(tr("No updates found."));
}
}
diff --git a/src/plugins/valgrind/CMakeLists.txt b/src/plugins/valgrind/CMakeLists.txt
new file mode 100644
index 0000000000..fe8452d812
--- /dev/null
+++ b/src/plugins/valgrind/CMakeLists.txt
@@ -0,0 +1,63 @@
+add_qtc_plugin(Valgrind
+ DEPENDS CPlusPlus QtcSsh
+ 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
+ callgrind/callgrindfunction.cpp callgrind/callgrindfunction.h callgrind/callgrindfunction_p.h
+ callgrind/callgrindfunctioncall.cpp callgrind/callgrindfunctioncall.h
+ callgrind/callgrindfunctioncycle.cpp callgrind/callgrindfunctioncycle.h
+ callgrind/callgrindparsedata.cpp callgrind/callgrindparsedata.h
+ callgrind/callgrindparser.cpp callgrind/callgrindparser.h
+ callgrind/callgrindproxymodel.cpp callgrind/callgrindproxymodel.h
+ callgrind/callgrindstackbrowser.cpp callgrind/callgrindstackbrowser.h
+ callgrindcostdelegate.cpp callgrindcostdelegate.h
+ callgrindcostview.cpp callgrindcostview.h
+ callgrindengine.cpp callgrindengine.h
+ callgrindhelper.cpp callgrindhelper.h
+ callgrindnamedelegate.cpp callgrindnamedelegate.h
+ callgrindtextmark.cpp callgrindtextmark.h
+ callgrindtool.cpp callgrindtool.h
+ callgrindvisualisation.cpp callgrindvisualisation.h
+ memcheckerrorview.cpp memcheckerrorview.h
+ memchecktool.cpp memchecktool.h
+ suppressiondialog.cpp suppressiondialog.h
+ valgrind.qrc
+ valgrindconfigwidget.cpp valgrindconfigwidget.h valgrindconfigwidget.ui
+ valgrindengine.cpp valgrindengine.h
+ valgrindplugin.cpp valgrindplugin.h
+ valgrindrunner.cpp valgrindrunner.h
+ valgrindsettings.cpp valgrindsettings.h
+ xmlprotocol/announcethread.cpp xmlprotocol/announcethread.h
+ xmlprotocol/error.cpp xmlprotocol/error.h
+ xmlprotocol/errorlistmodel.cpp xmlprotocol/errorlistmodel.h
+ xmlprotocol/frame.cpp xmlprotocol/frame.h
+ xmlprotocol/modelhelpers.cpp xmlprotocol/modelhelpers.h
+ xmlprotocol/parser.cpp xmlprotocol/parser.h
+ xmlprotocol/stack.cpp xmlprotocol/stack.h
+ xmlprotocol/stackmodel.cpp xmlprotocol/stackmodel.h
+ xmlprotocol/status.cpp xmlprotocol/status.h
+ xmlprotocol/suppression.cpp xmlprotocol/suppression.h
+ xmlprotocol/threadedparser.cpp xmlprotocol/threadedparser.h
+)
+
+extend_qtc_plugin(Valgrind
+ CONDITION WIN32
+ DEFINES UNICODE _UNICODE
+)
+
+extend_qtc_plugin(Valgrind
+ CONDITION WITH_TESTS
+ SOURCES
+ valgrindmemcheckparsertest.cpp valgrindmemcheckparsertest.h
+ valgrindtestrunnertest.cpp valgrindtestrunnertest.h
+ DEFINES
+ PARSERTESTS_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/unit_testdata"
+ VALGRIND_FAKE_PATH="${PROJECT_SOURCE_DIR}/src/tools/valgrindfake"
+ TESTRUNNER_SRC_DIR="${PROJECT_SOURCE_DIR}/tests/auto/valgrind/memcheck/testapps"
+ TESTRUNNER_APP_DIR="${PROJECT_BINARY_DIR}/tests/auto/valgrind/memcheck/testapps"
+)
diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.h b/src/plugins/valgrind/callgrind/callgrindcontroller.h
index d3a6639e4e..2a5fd8d762 100644
--- a/src/plugins/valgrind/callgrind/callgrindcontroller.h
+++ b/src/plugins/valgrind/callgrind/callgrindcontroller.h
@@ -28,7 +28,7 @@
#include <ssh/sshremoteprocess.h>
#include <ssh/sshconnection.h>
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <QProcess>
diff --git a/src/plugins/valgrind/callgrind/callgrindparser.cpp b/src/plugins/valgrind/callgrind/callgrindparser.cpp
index 153fa866db..c80a30b99b 100644
--- a/src/plugins/valgrind/callgrind/callgrindparser.cpp
+++ b/src/plugins/valgrind/callgrind/callgrindparser.cpp
@@ -283,6 +283,10 @@ void Parser::Private::parseHeader(QIODevice *device)
while (!device->atEnd()) {
QByteArray line = device->readLine();
+ // last character will be ignored anyhow, but we might have CRLF; if so cut the last one
+ if (line.endsWith("\r\n"))
+ line.chop(1);
+
// now that we're done checking if we're done (heh) with the header, parse the address
// and cost column descriptions. speed is unimportant here.
if (line.startsWith('#')) {
@@ -352,8 +356,9 @@ Parser::Private::NamePair Parser::Private::parseName(const char *begin, const ch
void Parser::Private::dispatchLine(const QByteArray &line)
{
+ int lineEnding = line.endsWith("\r\n") ? 2 : 1;
const char *const begin = line.constData();
- const char *const end = begin + line.length() - 1; // we're not interested in the '\n'
+ const char *const end = begin + line.length() - lineEnding; // we're not interested in the '\n'
const char *current = begin;
// shortest possible line is "1 1" - a cost item line
diff --git a/src/plugins/valgrind/callgrindcostdelegate.cpp b/src/plugins/valgrind/callgrindcostdelegate.cpp
index 32fa1e9185..ff70a5f98b 100644
--- a/src/plugins/valgrind/callgrindcostdelegate.cpp
+++ b/src/plugins/valgrind/callgrindcostdelegate.cpp
@@ -154,7 +154,7 @@ QSize CostDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd
initStyleOption(&opt, index);
const QString text = d->displayText(index, opt.locale);
- const QSize size = QSize(option.fontMetrics.width(text),
+ const QSize size = QSize(option.fontMetrics.horizontalAdvance(text),
option.fontMetrics.height());
return size;
}
diff --git a/src/plugins/valgrind/callgrindtextmark.cpp b/src/plugins/valgrind/callgrindtextmark.cpp
index ab21688013..3ba65a3e00 100644
--- a/src/plugins/valgrind/callgrindtextmark.cpp
+++ b/src/plugins/valgrind/callgrindtextmark.cpp
@@ -42,7 +42,7 @@ using namespace Valgrind::Callgrind;
namespace Constants { const char CALLGRIND_TEXT_MARK_CATEGORY[] = "Callgrind.Textmark"; }
CallgrindTextMark::CallgrindTextMark(const QPersistentModelIndex &index,
- const FileName &fileName, int lineNumber)
+ const FilePath &fileName, int lineNumber)
: TextEditor::TextMark(fileName, lineNumber, Constants::CALLGRIND_TEXT_MARK_CATEGORY, 4.0)
, m_modelIndex(index)
{
diff --git a/src/plugins/valgrind/callgrindtextmark.h b/src/plugins/valgrind/callgrindtextmark.h
index abc710e993..e92f16ce23 100644
--- a/src/plugins/valgrind/callgrindtextmark.h
+++ b/src/plugins/valgrind/callgrindtextmark.h
@@ -45,7 +45,7 @@ public:
* \note The index parameter must refer to one of the DataModel cost columns
*/
explicit CallgrindTextMark(const QPersistentModelIndex &index,
- const Utils::FileName &fileName, int lineNumber);
+ const Utils::FilePath &fileName, int lineNumber);
const Valgrind::Callgrind::Function *function() const;
diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp
index b9a83bc42b..0bf4b2661e 100644
--- a/src/plugins/valgrind/callgrindtool.cpp
+++ b/src/plugins/valgrind/callgrindtool.cpp
@@ -106,13 +106,13 @@ const char CallgrindLocalActionId[] = "Callgrind.Local.Action";
const char CallgrindRemoteActionId[] = "Callgrind.Remote.Action";
const char CALLGRIND_RUN_MODE[] = "CallgrindTool.CallgrindRunMode";
-class CallgrindTool : public QObject
+class CallgrindToolPrivate : public QObject
{
Q_OBJECT
public:
- CallgrindTool();
- ~CallgrindTool() override;
+ CallgrindToolPrivate();
+ ~CallgrindToolPrivate() override;
void setupRunner(CallgrindToolRunner *runner);
@@ -218,10 +218,10 @@ public:
QString m_toggleCollectFunction;
bool m_toolBusy = false;
- Perspective m_perspective{"Callgrind.Perspective", tr("Callgrind")};
+ Perspective m_perspective{"Callgrind.Perspective", CallgrindTool::tr("Callgrind")};
};
-CallgrindTool::CallgrindTool()
+CallgrindToolPrivate::CallgrindToolPrivate()
{
setObjectName("CallgrindTool");
@@ -235,22 +235,22 @@ CallgrindTool::CallgrindTool()
m_proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
connect(&m_stackBrowser, &StackBrowser::currentChanged,
- this, &CallgrindTool::stackBrowserChanged);
+ this, &CallgrindToolPrivate::stackBrowserChanged);
connect(&m_updateTimer, &QTimer::timeout,
- this, &CallgrindTool::updateFilterString);
+ this, &CallgrindToolPrivate::updateFilterString);
connect(EditorManager::instance(), &EditorManager::editorOpened,
- this, &CallgrindTool::editorOpened);
+ this, &CallgrindToolPrivate::editorOpened);
m_startAction = Debugger::createStartAction();
m_stopAction = Debugger::createStopAction();
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
- QString toolTip = tr("Valgrind Function Profiler uses the "
+ QString toolTip = CallgrindTool::tr("Valgrind Function Profiler uses the "
"Callgrind tool to record function calls when a program runs.");
if (!Utils::HostOsInfo::isWindowsHost()) {
- auto action = new QAction(tr("Valgrind Function Profiler"), this);
+ auto action = new QAction(CallgrindTool::tr("Valgrind Function Profiler"), this);
action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, CallgrindLocalActionId),
Debugger::Constants::G_ANALYZER_TOOLS);
@@ -266,7 +266,7 @@ CallgrindTool::CallgrindTool()
});
}
- auto action = new QAction(tr("Valgrind Function Profiler (External Application)"), this);
+ auto action = new QAction(CallgrindTool::tr("Valgrind Function Profiler (External Application)"), this);
action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, CallgrindRemoteActionId),
Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
@@ -280,9 +280,9 @@ CallgrindTool::CallgrindTool()
if (dlg.exec() != QDialog::Accepted)
return;
m_perspective.select();
- auto runControl = new RunControl(runConfig, CALLGRIND_RUN_MODE);
- if (auto creator = RunControl::producer(runConfig, CALLGRIND_RUN_MODE))
- creator(runControl);
+ auto runControl = new RunControl(CALLGRIND_RUN_MODE);
+ runControl->setRunConfiguration(runConfig);
+ runControl->createMainWorker();
const auto runnable = dlg.runnable();
runControl->setRunnable(runnable);
runControl->setDisplayName(runnable.executable);
@@ -295,10 +295,10 @@ CallgrindTool::CallgrindTool()
Context analyzerContext = Context(Debugger::Constants::C_DEBUGMODE);
editorContextMenu->addSeparator(analyzerContext);
- auto action = new QAction(tr("Profile Costs of This Function and Its Callees"), this);
+ auto action = new QAction(CallgrindTool::tr("Profile Costs of This Function and Its Callees"), this);
action->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL.icon());
connect(action, &QAction::triggered, this,
- &CallgrindTool::handleShowCostsOfFunction);
+ &CallgrindToolPrivate::handleShowCostsOfFunction);
Command *cmd = ActionManager::registerAction(action, "Analyzer.Callgrind.ShowCostsOfFunction",
analyzerContext);
editorContextMenu->addAction(cmd);
@@ -314,51 +314,51 @@ CallgrindTool::CallgrindTool()
m_visualization = new Visualization;
m_visualization->setFrameStyle(QFrame::NoFrame);
m_visualization->setObjectName("Valgrind.CallgrindTool.Visualisation");
- m_visualization->setWindowTitle(tr("Visualization"));
+ m_visualization->setWindowTitle(CallgrindTool::tr("Visualization"));
m_visualization->setModel(&m_dataModel);
connect(m_visualization, &Visualization::functionActivated,
- this, &CallgrindTool::visualisationFunctionSelected);
+ this, &CallgrindToolPrivate::visualisationFunctionSelected);
m_callersView = new CostView;
m_callersView->setObjectName("Valgrind.CallgrindTool.CallersView");
- m_callersView->setWindowTitle(tr("Callers"));
+ m_callersView->setWindowTitle(CallgrindTool::tr("Callers"));
m_callersView->setSettings(coreSettings, "Valgrind.CallgrindTool.CallersView");
- m_callersView->sortByColumn(CallModel::CostColumn);
+ m_callersView->sortByColumn(CallModel::CostColumn, Qt::DescendingOrder);
m_callersView->setFrameStyle(QFrame::NoFrame);
// enable sorting
m_callersProxy.setSourceModel(&m_callersModel);
m_callersView->setModel(&m_callersProxy);
m_callersView->hideColumn(CallModel::CalleeColumn);
connect(m_callersView, &QAbstractItemView::activated,
- this, &CallgrindTool::callerFunctionSelected);
+ this, &CallgrindToolPrivate::callerFunctionSelected);
m_calleesView = new CostView;
m_calleesView->setObjectName("Valgrind.CallgrindTool.CalleesView");
- m_calleesView->setWindowTitle(tr("Callees"));
+ m_calleesView->setWindowTitle(CallgrindTool::tr("Callees"));
m_calleesView->setSettings(coreSettings, "Valgrind.CallgrindTool.CalleesView");
- m_calleesView->sortByColumn(CallModel::CostColumn);
+ m_calleesView->sortByColumn(CallModel::CostColumn, Qt::DescendingOrder);
m_calleesView->setFrameStyle(QFrame::NoFrame);
// enable sorting
m_calleesProxy.setSourceModel(&m_calleesModel);
m_calleesView->setModel(&m_calleesProxy);
m_calleesView->hideColumn(CallModel::CallerColumn);
connect(m_calleesView, &QAbstractItemView::activated,
- this, &CallgrindTool::calleeFunctionSelected);
+ this, &CallgrindToolPrivate::calleeFunctionSelected);
m_flatView = new CostView;
m_flatView->setObjectName("Valgrind.CallgrindTool.FlatView");
- m_flatView->setWindowTitle(tr("Functions"));
+ m_flatView->setWindowTitle(CallgrindTool::tr("Functions"));
m_flatView->setSettings(coreSettings, "Valgrind.CallgrindTool.FlatView");
- m_flatView->sortByColumn(DataModel::SelfCostColumn);
+ m_flatView->sortByColumn(DataModel::SelfCostColumn, Qt::DescendingOrder);
m_flatView->setFrameStyle(QFrame::NoFrame);
m_flatView->setAttribute(Qt::WA_MacShowFocusRect, false);
m_flatView->setModel(&m_proxyModel);
connect(m_flatView, &QAbstractItemView::activated,
- this, &CallgrindTool::dataFunctionSelected);
+ this, &CallgrindToolPrivate::dataFunctionSelected);
updateCostFormat();
- ValgrindGlobalSettings *settings = ValgrindPlugin::globalSettings();
+ ValgrindGlobalSettings *settings = ValgrindGlobalSettings::instance();
//
// Control Widget
@@ -367,15 +367,15 @@ CallgrindTool::CallgrindTool()
// load external log file
action = m_loadExternalLogFile = new QAction(this);
action->setIcon(Utils::Icons::OPENFILE_TOOLBAR.icon());
- action->setToolTip(tr("Load External Log File"));
- connect(action, &QAction::triggered, this, &CallgrindTool::loadExternalLogFile);
+ action->setToolTip(CallgrindTool::tr("Load External Log File"));
+ connect(action, &QAction::triggered, this, &CallgrindToolPrivate::loadExternalLogFile);
action = m_startKCachegrind = new QAction(this);
action->setEnabled(false);
const Utils::Icon kCachegrindIcon({{":/valgrind/images/kcachegrind.png",
Theme::IconsBaseColor}});
action->setIcon(kCachegrindIcon.icon());
- action->setToolTip(tr("Open results in KCachegrind."));
+ action->setToolTip(CallgrindTool::tr("Open results in KCachegrind."));
connect(action, &QAction::triggered, this, [this, settings] {
QProcess::startDetached(settings->kcachegrindExecutable(), { m_lastFileName });
});
@@ -384,30 +384,30 @@ CallgrindTool::CallgrindTool()
m_dumpAction = action = new QAction(this);
action->setDisabled(true);
action->setIcon(Utils::Icons::REDO.icon());
- //action->setText(tr("Dump"));
- action->setToolTip(tr("Request the dumping of profile information. This will update the Callgrind visualization."));
- connect(action, &QAction::triggered, this, &CallgrindTool::slotRequestDump);
+ //action->setText(CallgrindTool::tr("Dump"));
+ action->setToolTip(CallgrindTool::tr("Request the dumping of profile information. This will update the Callgrind visualization."));
+ connect(action, &QAction::triggered, this, &CallgrindToolPrivate::slotRequestDump);
// reset action
m_resetAction = action = new QAction(this);
action->setDisabled(true);
action->setIcon(Utils::Icons::RELOAD.icon());
- //action->setText(tr("Reset"));
- action->setToolTip(tr("Reset all event counters."));
- connect(action, &QAction::triggered, this, &CallgrindTool::resetRequested);
+ //action->setText(CallgrindTool::tr("Reset"));
+ action->setToolTip(CallgrindTool::tr("Reset all event counters."));
+ connect(action, &QAction::triggered, this, &CallgrindToolPrivate::resetRequested);
// pause action
m_pauseAction = action = new QAction(this);
action->setCheckable(true);
action->setIcon(Utils::Icons::INTERRUPT_SMALL_TOOLBAR.icon());
- //action->setText(tr("Ignore"));
- action->setToolTip(tr("Pause event logging. No events are counted which will speed up program execution during profiling."));
- connect(action, &QAction::toggled, this, &CallgrindTool::pauseToggled);
+ //action->setText(CallgrindTool::tr("Ignore"));
+ action->setToolTip(CallgrindTool::tr("Pause event logging. No events are counted which will speed up program execution during profiling."));
+ connect(action, &QAction::toggled, this, &CallgrindToolPrivate::pauseToggled);
// discard data action
m_discardAction = action = new QAction(this);
action->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
- action->setToolTip(tr("Discard Data"));
+ action->setToolTip(CallgrindTool::tr("Discard Data"));
connect(action, &QAction::triggered, this, [this](bool) {
clearTextMarks();
doClear(true);
@@ -418,21 +418,21 @@ CallgrindTool::CallgrindTool()
m_goBack = action = new QAction(this);
action->setDisabled(true);
action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
- action->setToolTip(tr("Go back one step in history. This will select the previously selected item."));
+ action->setToolTip(CallgrindTool::tr("Go back one step in history. This will select the previously selected item."));
connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goBack);
// go forward
m_goNext = action = new QAction(this);
action->setDisabled(true);
action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
- action->setToolTip(tr("Go forward one step in history."));
+ action->setToolTip(CallgrindTool::tr("Go forward one step in history."));
connect(action, &QAction::triggered, &m_stackBrowser, &StackBrowser::goNext);
// event selection
m_eventCombo = new QComboBox;
- m_eventCombo->setToolTip(tr("Selects which events from the profiling data are shown and visualized."));
- connect(m_eventCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &CallgrindTool::setCostEvent);
+ m_eventCombo->setToolTip(CallgrindTool::tr("Selects which events from the profiling data are shown and visualized."));
+ connect(m_eventCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &CallgrindToolPrivate::setCostEvent);
updateEventCombo();
m_perspective.addToolBarAction(m_startAction);
@@ -453,63 +453,63 @@ CallgrindTool::CallgrindTool()
auto group = new QActionGroup(this);
// Show costs as absolute numbers
- m_costAbsolute = new QAction(tr("Absolute Costs"), this);
- m_costAbsolute->setToolTip(tr("Show costs as absolute numbers."));
+ m_costAbsolute = new QAction(CallgrindTool::tr("Absolute Costs"), this);
+ m_costAbsolute->setToolTip(CallgrindTool::tr("Show costs as absolute numbers."));
m_costAbsolute->setCheckable(true);
m_costAbsolute->setChecked(true);
- connect(m_costAbsolute, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
+ connect(m_costAbsolute, &QAction::toggled, this, &CallgrindToolPrivate::updateCostFormat);
group->addAction(m_costAbsolute);
// Show costs in percentages
- m_costRelative = new QAction(tr("Relative Costs"), this);
- m_costRelative->setToolTip(tr("Show costs relative to total inclusive cost."));
+ m_costRelative = new QAction(CallgrindTool::tr("Relative Costs"), this);
+ m_costRelative->setToolTip(CallgrindTool::tr("Show costs relative to total inclusive cost."));
m_costRelative->setCheckable(true);
- connect(m_costRelative, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
+ connect(m_costRelative, &QAction::toggled, this, &CallgrindToolPrivate::updateCostFormat);
group->addAction(m_costRelative);
// Show costs relative to parent
- m_costRelativeToParent = new QAction(tr("Relative Costs to Parent"), this);
- m_costRelativeToParent->setToolTip(tr("Show costs relative to parent function's inclusive cost."));
+ m_costRelativeToParent = new QAction(CallgrindTool::tr("Relative Costs to Parent"), this);
+ m_costRelativeToParent->setToolTip(CallgrindTool::tr("Show costs relative to parent function's inclusive cost."));
m_costRelativeToParent->setCheckable(true);
- connect(m_costRelativeToParent, &QAction::toggled, this, &CallgrindTool::updateCostFormat);
+ connect(m_costRelativeToParent, &QAction::toggled, this, &CallgrindToolPrivate::updateCostFormat);
group->addAction(m_costRelativeToParent);
auto button = new QToolButton;
button->addActions(group->actions());
button->setPopupMode(QToolButton::InstantPopup);
button->setText("$");
- button->setToolTip(tr("Cost Format"));
+ button->setToolTip(CallgrindTool::tr("Cost Format"));
m_perspective.addToolBarWidget(button);
}
// Cycle detection
//action = new QAction("Cycle Detection", this); ///FIXME: icon
action = m_cycleDetection = new QAction("O", this); ///FIXME: icon
- action->setToolTip(tr("Enable cycle detection to properly handle recursive or circular function calls."));
+ action->setToolTip(CallgrindTool::tr("Enable cycle detection to properly handle recursive or circular function calls."));
action->setCheckable(true);
connect(action, &QAction::toggled, &m_dataModel, &DataModel::enableCycleDetection);
connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setDetectCycles);
// Shorter template signature
action = m_shortenTemplates = new QAction("<>", this);
- action->setToolTip(tr("Remove template parameter lists when displaying function names."));
+ action->setToolTip(CallgrindTool::tr("Remove template parameter lists when displaying function names."));
action->setCheckable(true);
connect(action, &QAction::toggled, &m_dataModel, &DataModel::setShortenTemplates);
connect(action, &QAction::toggled, settings, &ValgrindGlobalSettings::setShortenTemplates);
// Filtering
- action = m_filterProjectCosts = new QAction(tr("Show Project Costs Only"), this);
+ action = m_filterProjectCosts = new QAction(CallgrindTool::tr("Show Project Costs Only"), this);
action->setIcon(Utils::Icons::FILTER.icon());
- action->setToolTip(tr("Show only profiling info that originated from this project source."));
+ action->setToolTip(CallgrindTool::tr("Show only profiling info that originated from this project source."));
action->setCheckable(true);
- connect(action, &QAction::toggled, this, &CallgrindTool::handleFilterProjectCosts);
+ connect(action, &QAction::toggled, this, &CallgrindToolPrivate::handleFilterProjectCosts);
// Filter
///FIXME: find workaround for https://bugreports.qt.io/browse/QTCREATORBUG-3247
m_searchFilter = new QLineEdit;
- m_searchFilter->setPlaceholderText(tr("Filter..."));
+ m_searchFilter->setPlaceholderText(CallgrindTool::tr("Filter..."));
connect(m_searchFilter, &QLineEdit::textChanged,
- &m_updateTimer, static_cast<void(QTimer::*)()>(&QTimer::start));
+ &m_updateTimer, QOverload<>::of(&QTimer::start));
setCostFormat(settings->costFormat());
enableCycleDetection(settings->detectCycles());
@@ -526,10 +526,10 @@ CallgrindTool::CallgrindTool()
false, Qt::RightDockWidgetArea);
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
- this, &CallgrindTool::updateRunActions);
+ this, &CallgrindToolPrivate::updateRunActions);
}
-CallgrindTool::~CallgrindTool()
+CallgrindToolPrivate::~CallgrindToolPrivate()
{
qDeleteAll(m_textMarks);
delete m_flatView;
@@ -538,7 +538,7 @@ CallgrindTool::~CallgrindTool()
delete m_visualization;
}
-void CallgrindTool::doClear(bool clearParseData)
+void CallgrindToolPrivate::doClear(bool clearParseData)
{
if (clearParseData) // Crashed when done from destructor.
setParseData(nullptr);
@@ -552,7 +552,7 @@ void CallgrindTool::doClear(bool clearParseData)
m_proxyModel.setFilterFixedString(QString());
}
-void CallgrindTool::setBusyCursor(bool busy)
+void CallgrindToolPrivate::setBusyCursor(bool busy)
{
QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
m_flatView->setCursor(cursor);
@@ -561,7 +561,7 @@ void CallgrindTool::setBusyCursor(bool busy)
m_visualization->setCursor(cursor);
}
-void CallgrindTool::selectFunction(const Function *func)
+void CallgrindToolPrivate::selectFunction(const Function *func)
{
if (!func) {
m_flatView->clearSelection();
@@ -594,7 +594,7 @@ void CallgrindTool::selectFunction(const Function *func)
}
}
-void CallgrindTool::stackBrowserChanged()
+void CallgrindToolPrivate::stackBrowserChanged()
{
m_goBack->setEnabled(m_stackBrowser.hasPrevious());
m_goNext->setEnabled(m_stackBrowser.hasNext());
@@ -602,12 +602,12 @@ void CallgrindTool::stackBrowserChanged()
selectFunction(item);
}
-void CallgrindTool::updateFilterString()
+void CallgrindToolPrivate::updateFilterString()
{
m_proxyModel.setFilterFixedString(m_searchFilter->text());
}
-void CallgrindTool::setCostFormat(CostDelegate::CostFormat format)
+void CallgrindToolPrivate::setCostFormat(CostDelegate::CostFormat format)
{
switch (format) {
case CostDelegate::FormatAbsolute:
@@ -622,7 +622,7 @@ void CallgrindTool::setCostFormat(CostDelegate::CostFormat format)
}
}
-void CallgrindTool::setCostEvent(int index)
+void CallgrindToolPrivate::setCostEvent(int index)
{
// prevent assert in model, don't try to set event to -1
// happens when we clear the eventcombo
@@ -634,19 +634,19 @@ void CallgrindTool::setCostEvent(int index)
m_callersModel.setCostEvent(index);
}
-void CallgrindTool::enableCycleDetection(bool enabled)
+void CallgrindToolPrivate::enableCycleDetection(bool enabled)
{
m_cycleDetection->setChecked(enabled);
}
-void CallgrindTool::shortenTemplates(bool enabled)
+void CallgrindToolPrivate::shortenTemplates(bool enabled)
{
m_shortenTemplates->setChecked(enabled);
}
// Following functions can be called with actions=0 or widgets=0
// depending on initialization sequence (whether callgrind was current).
-CostDelegate::CostFormat CallgrindTool::costFormat() const
+CostDelegate::CostFormat CallgrindToolPrivate::costFormat() const
{
if (m_costRelativeToParent && m_costRelativeToParent->isChecked())
return CostDelegate::FormatRelativeToParent;
@@ -655,7 +655,7 @@ CostDelegate::CostFormat CallgrindTool::costFormat() const
return CostDelegate::FormatAbsolute;
}
-void CallgrindTool::updateCostFormat()
+void CallgrindToolPrivate::updateCostFormat()
{
const CostDelegate::CostFormat format = costFormat();
if (m_flatView)
@@ -664,11 +664,11 @@ void CallgrindTool::updateCostFormat()
m_calleesView->setCostFormat(format);
m_callersView->setCostFormat(format);
}
- if (ValgrindGlobalSettings *settings = ValgrindPlugin::globalSettings())
+ if (ValgrindGlobalSettings *settings = ValgrindGlobalSettings::instance())
settings->setCostFormat(format);
}
-void CallgrindTool::handleFilterProjectCosts()
+void CallgrindToolPrivate::handleFilterProjectCosts()
{
Project *pro = ProjectTree::currentProject();
@@ -680,7 +680,7 @@ void CallgrindTool::handleFilterProjectCosts()
}
}
-void CallgrindTool::dataFunctionSelected(const QModelIndex &index)
+void CallgrindToolPrivate::dataFunctionSelected(const QModelIndex &index)
{
auto func = index.data(DataModel::FunctionRole).value<const Function *>();
QTC_ASSERT(func, return);
@@ -688,7 +688,7 @@ void CallgrindTool::dataFunctionSelected(const QModelIndex &index)
selectFunction(func);
}
-void CallgrindTool::calleeFunctionSelected(const QModelIndex &index)
+void CallgrindToolPrivate::calleeFunctionSelected(const QModelIndex &index)
{
auto call = index.data(CallModel::FunctionCallRole).value<const FunctionCall *>();
QTC_ASSERT(call, return);
@@ -696,7 +696,7 @@ void CallgrindTool::calleeFunctionSelected(const QModelIndex &index)
selectFunction(call->callee());
}
-void CallgrindTool::callerFunctionSelected(const QModelIndex &index)
+void CallgrindToolPrivate::callerFunctionSelected(const QModelIndex &index)
{
auto call = index.data(CallModel::FunctionCallRole).value<const FunctionCall *>();
QTC_ASSERT(call, return);
@@ -704,7 +704,7 @@ void CallgrindTool::callerFunctionSelected(const QModelIndex &index)
selectFunction(call->caller());
}
-void CallgrindTool::visualisationFunctionSelected(const Function *function)
+void CallgrindToolPrivate::visualisationFunctionSelected(const Function *function)
{
if (function && function == m_visualization->function())
// up-navigation when the initial function was activated
@@ -713,7 +713,7 @@ void CallgrindTool::visualisationFunctionSelected(const Function *function)
selectFunction(function);
}
-void CallgrindTool::setParseData(ParseData *data)
+void CallgrindToolPrivate::setParseData(ParseData *data)
{
// we have new parse data, invalidate filters in the proxy model
m_visualization->setFunction(nullptr);
@@ -741,7 +741,7 @@ void CallgrindTool::setParseData(ParseData *data)
//setBusy(false);
}
-void CallgrindTool::updateEventCombo()
+void CallgrindToolPrivate::updateEventCombo()
{
QTC_ASSERT(m_eventCombo, return);
@@ -758,16 +758,16 @@ void CallgrindTool::updateEventCombo()
m_eventCombo->addItem(ParseData::prettyStringForEvent(event));
}
-void CallgrindTool::setupRunner(CallgrindToolRunner *toolRunner)
+void CallgrindToolPrivate::setupRunner(CallgrindToolRunner *toolRunner)
{
RunControl *runControl = toolRunner->runControl();
- connect(toolRunner, &CallgrindToolRunner::parserDataReady, this, &CallgrindTool::takeParserDataFromRunControl);
- connect(runControl, &RunControl::stopped, this, &CallgrindTool::engineFinished);
+ connect(toolRunner, &CallgrindToolRunner::parserDataReady, this, &CallgrindToolPrivate::takeParserDataFromRunControl);
+ connect(runControl, &RunControl::stopped, this, &CallgrindToolPrivate::engineFinished);
- connect(this, &CallgrindTool::dumpRequested, toolRunner, &CallgrindToolRunner::dump);
- connect(this, &CallgrindTool::resetRequested, toolRunner, &CallgrindToolRunner::reset);
- connect(this, &CallgrindTool::pauseToggled, toolRunner, &CallgrindToolRunner::setPaused);
+ connect(this, &CallgrindToolPrivate::dumpRequested, toolRunner, &CallgrindToolRunner::dump);
+ connect(this, &CallgrindToolPrivate::resetRequested, toolRunner, &CallgrindToolRunner::reset);
+ connect(this, &CallgrindToolPrivate::pauseToggled, toolRunner, &CallgrindToolRunner::setPaused);
connect(m_stopAction, &QAction::triggered, toolRunner, [runControl] { runControl->initiateStop(); });
@@ -781,8 +781,9 @@ void CallgrindTool::setupRunner(CallgrindToolRunner *toolRunner)
QTC_ASSERT(m_visualization, return);
// apply project settings
- if (auto settings = runControl->runConfiguration()
- ->currentSettings<ValgrindBaseSettings>(ANALYZER_VALGRIND_SETTINGS)) {
+ auto settings
+ = qobject_cast<ValgrindBaseSettings *>(runControl->settings(ANALYZER_VALGRIND_SETTINGS));
+ if (settings) {
m_visualization->setMinimumInclusiveCostRatio(settings->visualisationMinimumInclusiveCostRatio() / 100.0);
m_proxyModel.setMinimumInclusiveCostRatio(settings->minimumInclusiveCostRatio() / 100.0);
m_dataModel.setVerboseToolTipsEnabled(settings->enableEventToolTips());
@@ -799,28 +800,28 @@ void CallgrindTool::setupRunner(CallgrindToolRunner *toolRunner)
doClear(true);
}
-void CallgrindTool::updateRunActions()
+void CallgrindToolPrivate::updateRunActions()
{
if (m_toolBusy) {
m_startAction->setEnabled(false);
m_startKCachegrind->setEnabled(false);
- m_startAction->setToolTip(tr("A Valgrind Callgrind analysis is still in progress."));
+ m_startAction->setToolTip(CallgrindTool::tr("A Valgrind Callgrind analysis is still in progress."));
m_stopAction->setEnabled(true);
} else {
- QString whyNot = tr("Start a Valgrind Callgrind analysis.");
+ QString whyNot = CallgrindTool::tr("Start a Valgrind Callgrind analysis.");
bool canRun = ProjectExplorerPlugin::canRunStartupProject(CALLGRIND_RUN_MODE, &whyNot);
m_startAction->setToolTip(whyNot);
m_startAction->setEnabled(canRun);
m_stopAction->setEnabled(false);
}
}
-void CallgrindTool::clearTextMarks()
+void CallgrindToolPrivate::clearTextMarks()
{
qDeleteAll(m_textMarks);
m_textMarks.clear();
}
-void CallgrindTool::engineFinished()
+void CallgrindToolPrivate::engineFinished()
{
m_toolBusy = false;
updateRunActions();
@@ -834,51 +835,51 @@ void CallgrindTool::engineFinished()
if (data)
showParserResults(data);
else
- Debugger::showPermanentStatusMessage(tr("Profiling aborted."));
+ Debugger::showPermanentStatusMessage(CallgrindTool::tr("Profiling aborted."));
setBusyCursor(false);
}
-void CallgrindTool::showParserResults(const ParseData *data)
+void CallgrindToolPrivate::showParserResults(const ParseData *data)
{
QString msg;
if (data) {
// be careful, the list of events might be empty
if (data->events().isEmpty()) {
- msg = tr("Parsing finished, no data.");
+ msg = CallgrindTool::tr("Parsing finished, no data.");
} else {
const QString costStr = QString::fromLatin1("%1 %2")
.arg(QString::number(data->totalCost(0)), data->events().constFirst());
- msg = tr("Parsing finished, total cost of %1 reported.").arg(costStr);
+ msg = CallgrindTool::tr("Parsing finished, total cost of %1 reported.").arg(costStr);
}
} else {
- msg = tr("Parsing failed.");
+ msg = CallgrindTool::tr("Parsing failed.");
}
Debugger::showPermanentStatusMessage(msg);
}
-void CallgrindTool::editorOpened(IEditor *editor)
+void CallgrindToolPrivate::editorOpened(IEditor *editor)
{
if (auto widget = qobject_cast<TextEditorWidget *>(editor->widget())) {
connect(widget, &TextEditorWidget::markContextMenuRequested,
- this, &CallgrindTool::requestContextMenu);
+ this, &CallgrindToolPrivate::requestContextMenu);
}
}
-void CallgrindTool::requestContextMenu(TextEditorWidget *widget, int line, QMenu *menu)
+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) {
if (textMark->fileName() == widget->textDocument()->filePath() && textMark->lineNumber() == line) {
const Function *func = textMark->function();
- QAction *action = menu->addAction(tr("Select This Function in the Analyzer Output"));
+ QAction *action = menu->addAction(CallgrindTool::tr("Select This Function in the Analyzer Output"));
connect(action, &QAction::triggered, this, [this, func] { selectFunction(func); });
break;
}
}
}
-void CallgrindTool::handleShowCostsOfFunction()
+void CallgrindToolPrivate::handleShowCostsOfFunction()
{
CPlusPlus::Symbol *symbol = AnalyzerUtils::findSymbolUnderCursor();
if (!symbol)
@@ -894,32 +895,32 @@ void CallgrindTool::handleShowCostsOfFunction()
m_startAction->trigger();
}
-void CallgrindTool::slotRequestDump()
+void CallgrindToolPrivate::slotRequestDump()
{
//setBusy(true);
- m_visualization->setText(tr("Populating..."));
+ m_visualization->setText(CallgrindTool::tr("Populating..."));
emit dumpRequested();
}
-void CallgrindTool::loadExternalLogFile()
+void CallgrindToolPrivate::loadExternalLogFile()
{
const QString filePath = QFileDialog::getOpenFileName(
ICore::mainWindow(),
- tr("Open Callgrind Log File"),
+ CallgrindTool::tr("Open Callgrind Log File"),
QString(),
- tr("Callgrind Output (callgrind.out*);;All Files (*)"));
+ CallgrindTool::tr("Callgrind Output (callgrind.out*);;All Files (*)"));
if (filePath.isEmpty())
return;
QFile logFile(filePath);
if (!logFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QString msg = tr("Callgrind: Failed to open file for reading: %1").arg(filePath);
+ QString msg = CallgrindTool::tr("Callgrind: Failed to open file for reading: %1").arg(filePath);
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup();
return;
}
- Debugger::showPermanentStatusMessage(tr("Parsing Profile Data..."));
+ Debugger::showPermanentStatusMessage(CallgrindTool::tr("Parsing Profile Data..."));
QCoreApplication::processEvents();
Parser parser;
@@ -927,12 +928,12 @@ void CallgrindTool::loadExternalLogFile()
takeParserData(parser.takeData());
}
-void CallgrindTool::takeParserDataFromRunControl(CallgrindToolRunner *rc)
+void CallgrindToolPrivate::takeParserDataFromRunControl(CallgrindToolRunner *rc)
{
takeParserData(rc->takeParserData());
}
-void CallgrindTool::takeParserData(ParseData *data)
+void CallgrindToolPrivate::takeParserData(ParseData *data)
{
showParserResults(data);
@@ -944,14 +945,14 @@ void CallgrindTool::takeParserData(ParseData *data)
doClear(true);
setParseData(data);
- const QString kcachegrindExecutable = ValgrindPlugin::globalSettings()->kcachegrindExecutable();
+ const QString kcachegrindExecutable = ValgrindGlobalSettings::instance()->kcachegrindExecutable();
const bool kcachegrindExists = !Utils::Environment::systemEnvironment().searchInPath(
kcachegrindExecutable).isEmpty();
m_startKCachegrind->setEnabled(kcachegrindExists && !m_lastFileName.isEmpty());
createTextMarks();
}
-void CallgrindTool::createTextMarks()
+void CallgrindToolPrivate::createTextMarks()
{
QList<QString> locations;
for (int row = 0; row < m_dataModel.rowCount(); ++row) {
@@ -981,29 +982,29 @@ void CallgrindTool::createTextMarks()
continue;
locations << location;
- m_textMarks.append(new CallgrindTextMark(index, FileName::fromString(fileName), lineNumber));
+ m_textMarks.append(new CallgrindTextMark(index, FilePath::fromString(fileName), lineNumber));
}
}
-static CallgrindTool *theCallgrindTool;
+// CallgrindTool
+
+static CallgrindToolPrivate *dd = nullptr;
void setupCallgrindRunner(CallgrindToolRunner *toolRunner)
{
- theCallgrindTool->setupRunner(toolRunner);
+ dd->setupRunner(toolRunner);
}
-void initCallgrindTool()
+CallgrindTool::CallgrindTool()
{
- theCallgrindTool = new CallgrindTool;
-
+ dd = new CallgrindToolPrivate;
RunControl::registerWorker<CallgrindToolRunner>(CALLGRIND_RUN_MODE, {});
}
-void destroyCallgrindTool()
+CallgrindTool::~CallgrindTool()
{
- delete theCallgrindTool;
- theCallgrindTool = nullptr;
+ delete dd;
}
} // namespace Internal
diff --git a/src/plugins/valgrind/callgrindtool.h b/src/plugins/valgrind/callgrindtool.h
index 79af72ad28..4c4f6bbe86 100644
--- a/src/plugins/valgrind/callgrindtool.h
+++ b/src/plugins/valgrind/callgrindtool.h
@@ -25,11 +25,21 @@
#pragma once
+#include <QCoreApplication>
+
namespace Valgrind {
namespace Internal {
-void initCallgrindTool();
-void destroyCallgrindTool();
+class ValgrindGlobalSettings;
+
+class CallgrindTool : public QObject
+{
+ Q_OBJECT
+
+public:
+ CallgrindTool();
+ ~CallgrindTool() final;
+};
} // namespace Internal
} // namespace Valgrind
diff --git a/src/plugins/valgrind/callgrindvisualisation.cpp b/src/plugins/valgrind/callgrindvisualisation.cpp
index b96bdd71b8..f7ba16931c 100644
--- a/src/plugins/valgrind/callgrindvisualisation.cpp
+++ b/src/plugins/valgrind/callgrindvisualisation.cpp
@@ -139,7 +139,7 @@ void FunctionGraphicsTextItem::paint(QPainter *painter,
painter->save();
int textLeft = 0;
int textTop = 0;
- const int textWidth = painter->fontMetrics().width(m_staticText.text());
+ const int textWidth = painter->fontMetrics().horizontalAdvance(m_staticText.text());
textLeft = -textWidth/2;
textTop = (maxHeight - textHeight)/2;
painter->drawStaticText(textLeft, textTop, m_staticText);
diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp
index aaea6ba4d5..fee5c9a8d4 100644
--- a/src/plugins/valgrind/memchecktool.cpp
+++ b/src/plugins/valgrind/memchecktool.cpp
@@ -90,7 +90,6 @@
#include <QToolButton>
#include <QSortFilterProxyModel>
-#ifdef Q_OS_WIN
#include <QCheckBox>
#include <QComboBox>
#include <QLineEdit>
@@ -98,6 +97,8 @@
#include <QSpinBox>
#include <QStandardPaths>
#include <QVBoxLayout>
+
+#ifdef Q_OS_WIN
#include <QWinEventNotifier>
#include <utils/winutils.h>
@@ -170,7 +171,7 @@ public:
QString MemcheckToolRunner::progressTitle() const
{
- return tr("Analyzing Memory");
+ return MemcheckTool::tr("Analyzing Memory");
}
void MemcheckToolRunner::start()
@@ -382,13 +383,11 @@ static void initKindFilterAction(QAction *action, const QVariantList &kinds)
action->setData(kinds);
}
-class MemcheckTool : public QObject
+class MemcheckToolPrivate : public QObject
{
- Q_DECLARE_TR_FUNCTIONS(Valgrind::Internal::MemcheckTool)
-
public:
- MemcheckTool();
- ~MemcheckTool() override;
+ MemcheckToolPrivate();
+ ~MemcheckToolPrivate() override;
void setupRunner(MemcheckToolRunner *runTool);
void loadShowXmlLogFile(const QString &filePath, const QString &exitMsg);
@@ -437,10 +436,12 @@ private:
bool m_toolBusy = false;
QString m_exitMsg;
- Perspective m_perspective{"Memcheck.Perspective", tr("Memcheck")};
+ Perspective m_perspective{"Memcheck.Perspective", MemcheckTool::tr("Memcheck")};
};
-#ifdef Q_OS_WIN
+static MemcheckToolPrivate *dd = nullptr;
+
+
class HeobDialog : public QDialog
{
Q_DECLARE_TR_FUNCTIONS(HeobDialog)
@@ -473,12 +474,14 @@ private:
PathChooser *m_pathChooser = nullptr;
};
+#ifdef Q_OS_WIN
+
class HeobData : public QObject
{
Q_DECLARE_TR_FUNCTIONS(HeobData)
public:
- HeobData(MemcheckTool *mcTool, const QString &xmlPath, Kit *kit, bool attach);
+ HeobData(MemcheckToolPrivate *mcTool, const QString &xmlPath, Kit *kit, bool attach);
~HeobData() override;
bool createErrorPipe(DWORD heobPid);
@@ -496,7 +499,7 @@ private:
OVERLAPPED m_ov;
unsigned m_data[2];
QWinEventNotifier *m_processFinishedNotifier = nullptr;
- MemcheckTool *m_mcTool = nullptr;
+ MemcheckToolPrivate *m_mcTool = nullptr;
QString m_xmlPath;
Kit *m_kit = nullptr;
bool m_attach = false;
@@ -504,37 +507,37 @@ private:
};
#endif
-MemcheckTool::MemcheckTool()
+MemcheckToolPrivate::MemcheckToolPrivate()
{
- m_settings = ValgrindPlugin::globalSettings();
+ m_settings = ValgrindGlobalSettings::instance();
setObjectName("MemcheckTool");
- m_filterProjectAction = new QAction(tr("External Errors"), this);
+ m_filterProjectAction = new QAction(MemcheckTool::tr("External Errors"), this);
m_filterProjectAction->setToolTip(
- tr("Show issues originating outside currently opened projects."));
+ MemcheckTool::tr("Show issues originating outside currently opened projects."));
m_filterProjectAction->setCheckable(true);
- m_suppressionSeparator = new QAction(tr("Suppressions"), this);
+ m_suppressionSeparator = new QAction(MemcheckTool::tr("Suppressions"), this);
m_suppressionSeparator->setSeparator(true);
m_suppressionSeparator->setToolTip(
- tr("These suppression files were used in the last memory analyzer run."));
+ MemcheckTool::tr("These suppression files were used in the last memory analyzer run."));
- QAction *a = new QAction(tr("Definite Memory Leaks"), this);
+ QAction *a = new QAction(MemcheckTool::tr("Definite Memory Leaks"), this);
initKindFilterAction(a, {Leak_DefinitelyLost, Leak_IndirectlyLost});
m_errorFilterActions.append(a);
- a = new QAction(tr("Possible Memory Leaks"), this);
+ a = new QAction(MemcheckTool::tr("Possible Memory Leaks"), this);
initKindFilterAction(a, {Leak_PossiblyLost, Leak_StillReachable});
m_errorFilterActions.append(a);
- a = new QAction(tr("Use of Uninitialized Memory"), this);
+ a = new QAction(MemcheckTool::tr("Use of Uninitialized Memory"), this);
initKindFilterAction(a, {InvalidRead, InvalidWrite, InvalidJump, Overlap,
InvalidMemPool, UninitCondition, UninitValue,
SyscallParam, ClientCheck});
m_errorFilterActions.append(a);
- a = new QAction(tr("Invalid Calls to \"free()\""), this);
+ a = new QAction(MemcheckTool::tr("Invalid Calls to \"free()\""), this);
initKindFilterAction(a, { InvalidFree, MismatchedFree });
m_errorFilterActions.append(a);
@@ -552,12 +555,12 @@ MemcheckTool::MemcheckTool()
m_errorView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_errorView->setAutoScroll(false);
m_errorView->setObjectName("Valgrind.MemcheckTool.ErrorView");
- m_errorView->setWindowTitle(tr("Memory Issues"));
+ m_errorView->setWindowTitle(MemcheckTool::tr("Memory Issues"));
m_perspective.addWindow(m_errorView, Perspective::SplitVertical, nullptr);
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
- this, &MemcheckTool::maybeActiveRunConfigurationChanged);
+ this, &MemcheckToolPrivate::maybeActiveRunConfigurationChanged);
//
// The Control Widget.
@@ -570,15 +573,15 @@ MemcheckTool::MemcheckTool()
// Load external XML log file
auto action = new QAction(this);
action->setIcon(Icons::OPENFILE_TOOLBAR.icon());
- action->setToolTip(tr("Load External XML Log File"));
- connect(action, &QAction::triggered, this, &MemcheckTool::loadExternalXmlLogFile);
+ action->setToolTip(MemcheckTool::tr("Load External XML Log File"));
+ connect(action, &QAction::triggered, this, &MemcheckToolPrivate::loadExternalXmlLogFile);
m_loadExternalLogFile = action;
// Go to previous leak.
action = new QAction(this);
action->setDisabled(true);
action->setIcon(Icons::PREV_TOOLBAR.icon());
- action->setToolTip(tr("Go to previous leak."));
+ action->setToolTip(MemcheckTool::tr("Go to previous leak."));
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goBack);
m_goBack = action;
@@ -586,13 +589,13 @@ MemcheckTool::MemcheckTool()
action = new QAction(this);
action->setDisabled(true);
action->setIcon(Icons::NEXT_TOOLBAR.icon());
- action->setToolTip(tr("Go to next leak."));
+ action->setToolTip(MemcheckTool::tr("Go to next leak."));
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goNext);
m_goNext = action;
auto filterButton = new QToolButton;
filterButton->setIcon(Icons::FILTER.icon());
- filterButton->setText(tr("Error Filter"));
+ filterButton->setText(MemcheckTool::tr("Error Filter"));
filterButton->setPopupMode(QToolButton::InstantPopup);
filterButton->setProperty("noArrow", true);
@@ -602,15 +605,15 @@ MemcheckTool::MemcheckTool()
m_filterMenu->addSeparator();
m_filterMenu->addAction(m_filterProjectAction);
m_filterMenu->addAction(m_suppressionSeparator);
- connect(m_filterMenu, &QMenu::triggered, this, &MemcheckTool::updateErrorFilter);
+ connect(m_filterMenu, &QMenu::triggered, this, &MemcheckToolPrivate::updateErrorFilter);
filterButton->setMenu(m_filterMenu);
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
- QString toolTip = tr("Valgrind Analyze Memory uses the Memcheck tool to find memory leaks.");
+ QString toolTip = MemcheckTool::tr("Valgrind Analyze Memory uses the Memcheck tool to find memory leaks.");
if (!HostOsInfo::isWindowsHost()) {
action = new QAction(this);
- action->setText(tr("Valgrind Memory Analyzer"));
+ action->setText(MemcheckTool::tr("Valgrind Memory Analyzer"));
action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, "Memcheck.Local"),
Debugger::Constants::G_ANALYZER_TOOLS);
@@ -628,7 +631,7 @@ MemcheckTool::MemcheckTool()
action = new QAction(this);
action->setText(tr("Valgrind Memory Analyzer with GDB"));
- action->setToolTip(tr("Valgrind Analyze Memory with GDB uses the "
+ action->setToolTip(MemcheckTool::tr("Valgrind Analyze Memory with GDB uses the "
"Memcheck tool to find memory leaks.\nWhen a problem is detected, "
"the application is interrupted and can be debugged."));
menu->addAction(ActionManager::registerAction(action, "MemcheckWithGdb.Local"),
@@ -645,10 +648,10 @@ MemcheckTool::MemcheckTool()
action->setEnabled(m_startWithGdbAction->isEnabled());
});
} else {
- action = new QAction(tr("Heob"), this);
+ action = new QAction(MemcheckTool::tr("Heob"), this);
Core::Command *cmd = Core::ActionManager::registerAction(action, "Memcheck.Local");
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+H")));
- connect(action, &QAction::triggered, this, &MemcheckTool::heobAction);
+ connect(action, &QAction::triggered, this, &MemcheckToolPrivate::heobAction);
menu->addAction(cmd, Debugger::Constants::G_ANALYZER_TOOLS);
connect(m_startAction, &QAction::changed, action, [action, this] {
action->setEnabled(m_startAction->isEnabled());
@@ -671,9 +674,9 @@ MemcheckTool::MemcheckTool()
return;
TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID);
m_perspective.select();
- RunControl *rc = new RunControl(runConfig, MEMCHECK_RUN_MODE);
- if (auto creator = RunControl::producer(runConfig, MEMCHECK_RUN_MODE))
- creator(rc);
+ RunControl *rc = new RunControl(MEMCHECK_RUN_MODE);
+ rc->setRunConfiguration(runConfig);
+ rc->createMainWorker();
const auto runnable = dlg.runnable();
rc->setRunnable(runnable);
rc->setDisplayName(runnable.executable);
@@ -692,14 +695,13 @@ MemcheckTool::MemcheckTool()
maybeActiveRunConfigurationChanged();
}
-MemcheckTool::~MemcheckTool()
+MemcheckToolPrivate::~MemcheckToolPrivate()
{
delete m_errorView;
}
-void MemcheckTool::heobAction()
+void MemcheckToolPrivate::heobAction()
{
-#ifdef Q_OS_WIN
Runnable sr;
Abi abi;
bool hasLocalRc = false;
@@ -709,14 +711,14 @@ void MemcheckTool::heobAction()
if (RunConfiguration *rc = target->activeRunConfiguration()) {
kit = target->kit();
if (kit) {
- abi = ToolChainKitInformation::targetAbi(kit);
+ abi = ToolChainKitAspect::targetAbi(kit);
const Runnable runnable = rc->runnable();
sr = runnable;
const IDevice::ConstPtr device = sr.device;
hasLocalRc = device && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
if (!hasLocalRc)
- hasLocalRc = DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+ hasLocalRc = DeviceTypeKitAspect::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
}
}
}
@@ -808,6 +810,7 @@ void MemcheckTool::heobAction()
// process environment
QByteArray env;
void *envPtr = nullptr;
+ Q_UNUSED(envPtr);
if (!envStrings.isEmpty()) {
uint pos = 0;
for (const QString &par : envStrings) {
@@ -823,6 +826,7 @@ void MemcheckTool::heobAction()
envPtr = env.data();
}
+#ifdef Q_OS_WIN
// heob process
STARTUPINFO si;
PROCESS_INFORMATION pi;
@@ -855,20 +859,20 @@ void MemcheckTool::heobAction()
#endif
}
-void MemcheckTool::updateRunActions()
+void MemcheckToolPrivate::updateRunActions()
{
if (m_toolBusy) {
m_startAction->setEnabled(false);
- m_startAction->setToolTip(tr("A Valgrind Memcheck analysis is still in progress."));
+ m_startAction->setToolTip(MemcheckTool::tr("A Valgrind Memcheck analysis is still in progress."));
m_startWithGdbAction->setEnabled(false);
- m_startWithGdbAction->setToolTip(tr("A Valgrind Memcheck analysis is still in progress."));
+ m_startWithGdbAction->setToolTip(MemcheckTool::tr("A Valgrind Memcheck analysis is still in progress."));
m_stopAction->setEnabled(true);
} else {
- QString whyNot = tr("Start a Valgrind Memcheck analysis.");
+ QString whyNot = MemcheckTool::tr("Start a Valgrind Memcheck analysis.");
bool canRun = ProjectExplorerPlugin::canRunStartupProject(MEMCHECK_RUN_MODE, &whyNot);
m_startAction->setToolTip(whyNot);
m_startAction->setEnabled(canRun);
- whyNot = tr("Start a Valgrind Memcheck with GDB analysis.");
+ whyNot = MemcheckTool::tr("Start a Valgrind Memcheck with GDB analysis.");
canRun = ProjectExplorerPlugin::canRunStartupProject(MEMCHECK_WITH_GDB_RUN_MODE, &whyNot);
m_startWithGdbAction->setToolTip(whyNot);
m_startWithGdbAction->setEnabled(canRun);
@@ -876,13 +880,13 @@ void MemcheckTool::updateRunActions()
}
}
-void MemcheckTool::settingsDestroyed(QObject *settings)
+void MemcheckToolPrivate::settingsDestroyed(QObject *settings)
{
QTC_ASSERT(m_settings == settings, return);
- m_settings = ValgrindPlugin::globalSettings();
+ m_settings = ValgrindGlobalSettings::instance();
}
-void MemcheckTool::updateFromSettings()
+void MemcheckToolPrivate::updateFromSettings()
{
foreach (QAction *action, m_errorFilterActions) {
bool contained = true;
@@ -907,7 +911,7 @@ void MemcheckTool::updateFromSettings()
m_errorProxyModel.setFilterExternalIssues(m_settings->filterExternalIssues());
}
-void MemcheckTool::maybeActiveRunConfigurationChanged()
+void MemcheckToolPrivate::maybeActiveRunConfigurationChanged()
{
updateRunActions();
@@ -918,7 +922,7 @@ void MemcheckTool::maybeActiveRunConfigurationChanged()
settings = rc->currentSettings<ValgrindBaseSettings>(ANALYZER_VALGRIND_SETTINGS);
if (!settings) // fallback to global settings
- settings = ValgrindPlugin::globalSettings();
+ settings = ValgrindGlobalSettings::instance();
if (m_settings == settings)
return;
@@ -932,20 +936,24 @@ void MemcheckTool::maybeActiveRunConfigurationChanged()
// now make the new settings current, update and connect input widgets
m_settings = settings;
QTC_ASSERT(m_settings, return);
- connect(m_settings, &ValgrindBaseSettings::destroyed, this, &MemcheckTool::settingsDestroyed);
+ connect(m_settings, &ValgrindBaseSettings::destroyed,
+ this, &MemcheckToolPrivate::settingsDestroyed);
updateFromSettings();
}
-void MemcheckTool::setupRunner(MemcheckToolRunner *runTool)
+void MemcheckToolPrivate::setupRunner(MemcheckToolRunner *runTool)
{
RunControl *runControl = runTool->runControl();
m_errorModel.setRelevantFrameFinder(makeFrameFinder(transform(runControl->project()->files(Project::AllFiles),
- &FileName::toString)));
+ &FilePath::toString)));
- connect(runTool, &MemcheckToolRunner::parserError, this, &MemcheckTool::parserError);
- connect(runTool, &MemcheckToolRunner::internalParserError, this, &MemcheckTool::internalParserError);
- connect(runTool, &MemcheckToolRunner::stopped, this, &MemcheckTool::engineFinished);
+ connect(runTool, &MemcheckToolRunner::parserError,
+ this, &MemcheckToolPrivate::parserError);
+ connect(runTool, &MemcheckToolRunner::internalParserError,
+ this, &MemcheckToolPrivate::internalParserError);
+ connect(runTool, &MemcheckToolRunner::stopped,
+ this, &MemcheckToolPrivate::engineFinished);
m_stopAction->disconnect();
connect(m_stopAction, &QAction::triggered, runControl, &RunControl::initiateStop);
@@ -958,12 +966,12 @@ void MemcheckTool::setupRunner(MemcheckToolRunner *runTool)
m_loadExternalLogFile->setDisabled(true);
QString dir = runControl->project()->projectDirectory().toString() + '/';
- const QString name = FileName::fromString(runTool->executable()).fileName();
+ const QString name = FilePath::fromString(runTool->executable()).fileName();
m_errorView->setDefaultSuppressionFile(dir + name + ".supp");
foreach (const QString &file, runTool->suppressionFiles()) {
- QAction *action = m_filterMenu->addAction(FileName::fromString(file).fileName());
+ QAction *action = m_filterMenu->addAction(FilePath::fromString(file).fileName());
action->setToolTip(file);
connect(action, &QAction::triggered, this, [file] {
EditorManager::openEditorAt(file, 0);
@@ -972,7 +980,7 @@ void MemcheckTool::setupRunner(MemcheckToolRunner *runTool)
}
}
-void MemcheckTool::loadShowXmlLogFile(const QString &filePath, const QString &exitMsg)
+void MemcheckToolPrivate::loadShowXmlLogFile(const QString &filePath, const QString &exitMsg)
{
clearErrorView();
m_settings->setFilterExternalIssues(false);
@@ -984,13 +992,13 @@ void MemcheckTool::loadShowXmlLogFile(const QString &filePath, const QString &ex
loadXmlLogFile(filePath);
}
-void MemcheckTool::loadExternalXmlLogFile()
+void MemcheckToolPrivate::loadExternalXmlLogFile()
{
const QString filePath = QFileDialog::getOpenFileName(
ICore::mainWindow(),
- tr("Open Memcheck XML Log File"),
+ MemcheckTool::tr("Open Memcheck XML Log File"),
QString(),
- tr("XML Files (*.xml);;All Files (*)"));
+ MemcheckTool::tr("XML Files (*.xml);;All Files (*)"));
if (filePath.isEmpty())
return;
@@ -998,12 +1006,12 @@ void MemcheckTool::loadExternalXmlLogFile()
loadXmlLogFile(filePath);
}
-void MemcheckTool::loadXmlLogFile(const QString &filePath)
+void MemcheckToolPrivate::loadXmlLogFile(const QString &filePath)
{
auto logFile = new QFile(filePath);
if (!logFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
delete logFile;
- QString msg = tr("Memcheck: Failed to open file for reading: %1").arg(filePath);
+ QString msg = MemcheckTool::tr("Memcheck: Failed to open file for reading: %1").arg(filePath);
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup();
if (!m_exitMsg.isEmpty())
@@ -1015,34 +1023,38 @@ void MemcheckTool::loadXmlLogFile(const QString &filePath)
clearErrorView();
m_loadExternalLogFile->setDisabled(true);
- if (!m_settings || m_settings != ValgrindPlugin::globalSettings()) {
- m_settings = ValgrindPlugin::globalSettings();
+ if (!m_settings || m_settings != ValgrindGlobalSettings::instance()) {
+ m_settings = ValgrindGlobalSettings::instance();
m_errorView->settingsChanged(m_settings);
updateFromSettings();
}
auto parser = new ThreadedParser;
- connect(parser, &ThreadedParser::error, this, &MemcheckTool::parserError);
- connect(parser, &ThreadedParser::internalError, this, &MemcheckTool::internalParserError);
- connect(parser, &ThreadedParser::finished, this, &MemcheckTool::loadingExternalXmlLogFileFinished);
- connect(parser, &ThreadedParser::finished, parser, &ThreadedParser::deleteLater);
+ connect(parser, &ThreadedParser::error,
+ this, &MemcheckToolPrivate::parserError);
+ connect(parser, &ThreadedParser::internalError,
+ this, &MemcheckToolPrivate::internalParserError);
+ connect(parser, &ThreadedParser::finished,
+ this, &MemcheckToolPrivate::loadingExternalXmlLogFileFinished);
+ connect(parser, &ThreadedParser::finished,
+ parser, &ThreadedParser::deleteLater);
parser->parse(logFile); // ThreadedParser owns the file
}
-void MemcheckTool::parserError(const Error &error)
+void MemcheckToolPrivate::parserError(const Error &error)
{
m_errorModel.addError(error);
}
-void MemcheckTool::internalParserError(const QString &errorString)
+void MemcheckToolPrivate::internalParserError(const QString &errorString)
{
- QString msg = tr("Memcheck: Error occurred parsing Valgrind output: %1").arg(errorString);
+ QString msg = MemcheckTool::tr("Memcheck: Error occurred parsing Valgrind output: %1").arg(errorString);
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup();
}
-void MemcheckTool::clearErrorView()
+void MemcheckToolPrivate::clearErrorView()
{
QTC_ASSERT(m_errorView, return);
m_errorModel.clear();
@@ -1052,7 +1064,7 @@ void MemcheckTool::clearErrorView()
//QTC_ASSERT(filterMenu()->actions().last() == m_suppressionSeparator, qt_noop());
}
-void MemcheckTool::updateErrorFilter()
+void MemcheckToolPrivate::updateErrorFilter()
{
QTC_ASSERT(m_errorView, return);
QTC_ASSERT(m_settings, return);
@@ -1073,7 +1085,7 @@ void MemcheckTool::updateErrorFilter()
m_settings->setVisibleErrorKinds(errorKinds);
}
-int MemcheckTool::updateUiAfterFinishedHelper()
+int MemcheckToolPrivate::updateUiAfterFinishedHelper()
{
const int issuesFound = m_errorModel.rowCount();
m_goBack->setEnabled(issuesFound > 1);
@@ -1083,34 +1095,31 @@ int MemcheckTool::updateUiAfterFinishedHelper()
return issuesFound;
}
-void MemcheckTool::engineFinished()
+void MemcheckToolPrivate::engineFinished()
{
m_toolBusy = false;
updateRunActions();
const int issuesFound = updateUiAfterFinishedHelper();
Debugger::showPermanentStatusMessage(
- tr("Memory Analyzer Tool finished. %n issues were found.", nullptr, issuesFound));
+ MemcheckTool::tr("Memory Analyzer Tool finished. %n issues were found.", nullptr, issuesFound));
}
-void MemcheckTool::loadingExternalXmlLogFileFinished()
+void MemcheckToolPrivate::loadingExternalXmlLogFileFinished()
{
const int issuesFound = updateUiAfterFinishedHelper();
- QString statusMessage = tr("Log file processed. %n issues were found.", nullptr, issuesFound);
+ QString statusMessage = MemcheckTool::tr("Log file processed. %n issues were found.", nullptr, issuesFound);
if (!m_exitMsg.isEmpty())
statusMessage += ' ' + m_exitMsg;
Debugger::showPermanentStatusMessage(statusMessage);
}
-void MemcheckTool::setBusyCursor(bool busy)
+void MemcheckToolPrivate::setBusyCursor(bool busy)
{
QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
m_errorView->setCursor(cursor);
}
-
-static MemcheckTool *theMemcheckTool;
-
MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl)
: ValgrindToolRunner(runControl),
m_withGdb(runControl->runMode() == MEMCHECK_WITH_GDB_RUN_MODE),
@@ -1137,25 +1146,10 @@ MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl)
if (device()->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
addStartDependency(new LocalAddressFinder(runControl, &m_localServerAddress));
- theMemcheckTool->setupRunner(this);
-}
-
-void initMemcheckTool()
-{
- theMemcheckTool = new MemcheckTool;
-
- RunControl::registerWorker<MemcheckToolRunner>(MEMCHECK_RUN_MODE, {});
- RunControl::registerWorker<MemcheckToolRunner>(MEMCHECK_WITH_GDB_RUN_MODE, {});
-}
-
-void destroyMemcheckTool()
-{
- delete theMemcheckTool;
- theMemcheckTool = nullptr;
+ dd->setupRunner(this);
}
-#ifdef Q_OS_WIN
const char heobXmlC[] = "heob/Xml";
const char heobHandleExceptionC[] = "heob/HandleException";
const char heobPageProtectionC[] = "heob/PageProtection";
@@ -1168,11 +1162,6 @@ const char heobAttachC[] = "heob/Attach";
const char heobExtraArgsC[] = "heob/ExtraArgs";
const char heobPathC[] = "heob/Path";
-static QString upperHexNum(unsigned num)
-{
- return QString("%1").arg(num, 8, 16, QChar('0')).toUpper();
-}
-
HeobDialog::HeobDialog(QWidget *parent) :
QDialog(parent)
{
@@ -1215,7 +1204,7 @@ HeobDialog::HeobDialog(QWidget *parent) :
m_handleExceptionCombo->addItem(tr("On"));
m_handleExceptionCombo->addItem(tr("Only"));
m_handleExceptionCombo->setCurrentIndex(handleException);
- connect(m_handleExceptionCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_handleExceptionCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &HeobDialog::updateEnabled);
handleExceptionLayout->addWidget(m_handleExceptionCombo);
layout->addLayout(handleExceptionLayout);
@@ -1228,7 +1217,7 @@ HeobDialog::HeobDialog(QWidget *parent) :
m_pageProtectionCombo->addItem(tr("After"));
m_pageProtectionCombo->addItem(tr("Before"));
m_pageProtectionCombo->setCurrentIndex(pageProtection);
- connect(m_pageProtectionCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_pageProtectionCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &HeobDialog::updateEnabled);
pageProtectionLayout->addWidget(m_pageProtectionCombo);
layout->addLayout(pageProtectionLayout);
@@ -1252,7 +1241,7 @@ HeobDialog::HeobDialog(QWidget *parent) :
m_leakDetailCombo->addItem(tr("Fuzzy Detect Leak Types"));
m_leakDetailCombo->addItem(tr("Fuzzy Detect Leak Types (Show Reachable)"));
m_leakDetailCombo->setCurrentIndex(leakDetail);
- connect(m_leakDetailCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_leakDetailCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &HeobDialog::updateEnabled);
leakDetailLayout->addWidget(m_leakDetailCombo);
layout->addLayout(leakDetailLayout);
@@ -1422,7 +1411,13 @@ void HeobDialog::saveOptions()
settings->setValue(heobPathC, m_pathChooser->path());
}
-HeobData::HeobData(MemcheckTool *mcTool, const QString &xmlPath, Kit *kit, bool attach)
+#ifdef Q_OS_WIN
+static QString upperHexNum(unsigned num)
+{
+ return QString("%1").arg(num, 8, 16, QChar('0')).toUpper();
+}
+
+HeobData::HeobData(MemcheckToolPrivate *mcTool, const QString &xmlPath, Kit *kit, bool attach)
: m_ov(), m_data(), m_mcTool(mcTool), m_xmlPath(xmlPath), m_kit(kit), m_attach(attach)
{
}
@@ -1508,11 +1503,12 @@ void HeobData::processFinished()
DWORD didread;
if (GetOverlappedResult(m_errorPipe, &m_ov, &didread, TRUE) && didread == sizeof(m_data)) {
if (m_data[0] >= HEOB_PID_ATTACH) {
- m_runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto debugger = new DebuggerRunTool(m_runControl, m_kit);
+ m_runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ m_runControl->setKit(m_kit);
+ auto debugger = new DebuggerRunTool(m_runControl);
debugger->setAttachPid(ProcessHandle(m_data[1]));
debugger->setRunControlName(tr("Process %1").arg(m_data[1]));
- debugger->setInferiorDevice(DeviceKitInformation::device(m_kit));
+ debugger->setInferiorDevice(DeviceKitAspect::device(m_kit));
debugger->setStartMode(AttachExternal);
debugger->setCloseMode(DetachAtClose);
debugger->setContinueAfterAttach(true);
@@ -1635,6 +1631,19 @@ void HeobData::debugStopped()
}
#endif
+MemcheckTool::MemcheckTool()
+{
+ dd = new MemcheckToolPrivate;
+
+ RunControl::registerWorker<MemcheckToolRunner>(MEMCHECK_RUN_MODE, {});
+ RunControl::registerWorker<MemcheckToolRunner>(MEMCHECK_WITH_GDB_RUN_MODE, {});
+}
+
+MemcheckTool::~MemcheckTool()
+{
+ delete dd;
+}
+
} // namespace Internal
} // namespace Valgrind
diff --git a/src/plugins/valgrind/memchecktool.h b/src/plugins/valgrind/memchecktool.h
index 7fcef04d1e..e75bf9a1d6 100644
--- a/src/plugins/valgrind/memchecktool.h
+++ b/src/plugins/valgrind/memchecktool.h
@@ -26,11 +26,24 @@
#pragma once
+#include <QCoreApplication>
+
namespace Valgrind {
namespace Internal {
-void initMemcheckTool();
-void destroyMemcheckTool();
+class MemcheckToolRunner;
+
+class MemcheckTool : public QObject
+{
+ Q_OBJECT
+
+public:
+ MemcheckTool();
+ ~MemcheckTool() final;
+
+private:
+ class MemcheckToolPrivate *d = nullptr;
+};
} // namespace Internal
} // namespace Valgrind
diff --git a/src/plugins/valgrind/suppressiondialog.cpp b/src/plugins/valgrind/suppressiondialog.cpp
index 67b5612b3e..fbd2b21726 100644
--- a/src/plugins/valgrind/suppressiondialog.cpp
+++ b/src/plugins/valgrind/suppressiondialog.cpp
@@ -208,7 +208,7 @@ void SuppressionDialog::accept()
return;
// Add file to project if there is a project containing this file on the file system.
- if (!ProjectExplorer::SessionManager::projectForFile(Utils::FileName::fromString(path))) {
+ if (!ProjectExplorer::SessionManager::projectForFile(Utils::FilePath::fromString(path))) {
for (ProjectExplorer::Project *p : ProjectExplorer::SessionManager::projects()) {
if (path.startsWith(p->projectDirectory().toString())) {
p->rootProjectNode()->addFiles(QStringList() << path);
diff --git a/src/plugins/valgrind/valgrindconfigwidget.cpp b/src/plugins/valgrind/valgrindconfigwidget.cpp
index 7abb0e97d7..69a1560dfb 100644
--- a/src/plugins/valgrind/valgrindconfigwidget.cpp
+++ b/src/plugins/valgrind/valgrindconfigwidget.cpp
@@ -60,7 +60,7 @@ ValgrindConfigWidget::ValgrindConfigWidget(ValgrindBaseSettings *settings, bool
connect(m_ui->valgrindExeChooser, &Utils::PathChooser::rawPathChanged,
m_settings, &ValgrindBaseSettings::setValgrindExecutable);
- connect(m_ui->smcDetectionComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->smcDetectionComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
m_settings, &ValgrindBaseSettings::setSelfModifyingCodeDetection);
if (Utils::HostOsInfo::isWindowsHost()) {
@@ -102,12 +102,12 @@ ValgrindConfigWidget::ValgrindConfigWidget(ValgrindBaseSettings *settings, bool
connect(m_settings, &ValgrindBaseSettings::enableEventToolTipsChanged,
m_ui->enableEventToolTips, &QGroupBox::setChecked);
- connect(m_ui->minimumInclusiveCostRatio, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_ui->minimumInclusiveCostRatio, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
m_settings, &ValgrindBaseSettings::setMinimumInclusiveCostRatio);
connect(m_settings, &ValgrindBaseSettings::minimumInclusiveCostRatioChanged,
m_ui->minimumInclusiveCostRatio, &QDoubleSpinBox::setValue);
- connect(m_ui->visualisationMinimumInclusiveCostRatio, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+ connect(m_ui->visualisationMinimumInclusiveCostRatio, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
m_settings, &ValgrindBaseSettings::setVisualisationMinimumInclusiveCostRatio);
connect(m_settings, &ValgrindBaseSettings::visualisationMinimumInclusiveCostRatioChanged,
m_ui->visualisationMinimumInclusiveCostRatio, &QDoubleSpinBox::setValue);
@@ -121,12 +121,12 @@ ValgrindConfigWidget::ValgrindConfigWidget(ValgrindBaseSettings *settings, bool
connect(m_ui->addSuppression, &QPushButton::clicked, this, &ValgrindConfigWidget::slotAddSuppression);
connect(m_ui->removeSuppression, &QPushButton::clicked, this, &ValgrindConfigWidget::slotRemoveSuppression);
- connect(m_ui->numCallers, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
+ connect(m_ui->numCallers, QOverload<int>::of(&QSpinBox::valueChanged),
m_settings, &ValgrindBaseSettings::setNumCallers);
connect(m_settings, &ValgrindBaseSettings::numCallersChanged,
m_ui->numCallers, &QSpinBox::setValue);
- connect(m_ui->leakCheckOnFinish, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_ui->leakCheckOnFinish, QOverload<int>::of(&QComboBox::currentIndexChanged),
m_settings, &ValgrindBaseSettings::setLeakCheckOnFinish);
connect(m_settings, &ValgrindBaseSettings::leakCheckOnFinishChanged,
m_ui->leakCheckOnFinish, &QComboBox::setCurrentIndex);
@@ -191,7 +191,7 @@ void ValgrindConfigWidget::updateUi()
void ValgrindConfigWidget::slotAddSuppression()
{
- ValgrindGlobalSettings *conf = ValgrindPlugin::globalSettings();
+ ValgrindGlobalSettings *conf = ValgrindGlobalSettings::instance();
QTC_ASSERT(conf, return);
QStringList files = QFileDialog::getOpenFileNames(this,
tr("Valgrind Suppression Files"),
diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp
index 3aa2f78eac..547fa4a946 100644
--- a/src/plugins/valgrind/valgrindengine.cpp
+++ b/src/plugins/valgrind/valgrindengine.cpp
@@ -58,11 +58,11 @@ ValgrindToolRunner::ValgrindToolRunner(RunControl *runControl)
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
setSupportsReRunning(false);
- m_settings = runControl->runConfiguration()
- ->currentSettings<ValgrindBaseSettings>(ANALYZER_VALGRIND_SETTINGS);
+ m_settings =
+ qobject_cast<ValgrindBaseSettings *>(runControl->settings(ANALYZER_VALGRIND_SETTINGS));
if (!m_settings)
- m_settings = ValgrindPlugin::globalSettings();
+ m_settings = ValgrindGlobalSettings::instance();
}
void ValgrindToolRunner::start()
@@ -86,7 +86,7 @@ void ValgrindToolRunner::start()
m_runner.setDevice(device());
m_runner.setDebuggee(runnable());
- if (auto aspect = runControl()->runConfiguration()->aspect<TerminalAspect>())
+ if (auto aspect = runControl()->aspect<TerminalAspect>())
m_runner.setUseTerminal(aspect->useTerminal());
connect(&m_runner, &ValgrindRunner::processOutputReceived,
diff --git a/src/plugins/valgrind/valgrindengine.h b/src/plugins/valgrind/valgrindengine.h
index 8d3b300893..06c51583e7 100644
--- a/src/plugins/valgrind/valgrindengine.h
+++ b/src/plugins/valgrind/valgrindengine.h
@@ -26,7 +26,7 @@
#pragma once
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
#include <valgrind/valgrindrunner.h>
#include <valgrind/valgrindsettings.h>
diff --git a/src/plugins/valgrind/valgrindmemcheckparsertest.cpp b/src/plugins/valgrind/valgrindmemcheckparsertest.cpp
index ad2c3c8d2b..3bb2ba4ebf 100644
--- a/src/plugins/valgrind/valgrindmemcheckparsertest.cpp
+++ b/src/plugins/valgrind/valgrindmemcheckparsertest.cpp
@@ -111,6 +111,18 @@ static QString dataFile(const QString &file)
return QString(PARSERTESTS_DATA_DIR) + '/' + file;
}
+static QString extraDataFile(const QString &file)
+{
+ static QString prefix = QString::fromLocal8Bit(qgetenv("QTC_TEST_EXTRADATALOCATION"));
+ if (prefix.isEmpty())
+ return QString();
+
+ QFileInfo fi(QString(prefix + "/valgrind"), file);
+ if (fi.exists())
+ return fi.canonicalFilePath();
+ return QString();
+}
+
void ValgrindMemcheckParserTest::initTestCase()
{
m_server = new QTcpServer(this);
@@ -131,7 +143,7 @@ void ValgrindMemcheckParserTest::initTest(const QString &testfile, const QString
m_process->start(
fakeValgrind,
QStringList({QString("--xml-socket=127.0.0.1:%1").arg(m_server->serverPort()), "-i",
- dataFile(testfile)}) << otherArgs);
+ testfile}) << otherArgs);
QVERIFY(m_process->waitForStarted(5000));
QCOMPARE(m_process->state(), QProcess::Running);
@@ -155,9 +167,11 @@ void ValgrindMemcheckParserTest::cleanup()
void ValgrindMemcheckParserTest::testHelgrindSample1()
{
- QSKIP("testfile does not exist");
+ const QString file = extraDataFile("helgrind-output-sample1.xml");
+ if (file.isEmpty())
+ QSKIP("test file does not exist");
- initTest("helgrind-output-sample1.xml");
+ initTest(file);
QList<Error> expectedErrors;
{
@@ -251,7 +265,7 @@ void ValgrindMemcheckParserTest::testHelgrindSample1()
void ValgrindMemcheckParserTest::testMemcheckSample1()
{
- initTest("memcheck-output-sample1.xml");
+ initTest(dataFile("memcheck-output-sample1.xml"));
QList<Error> expectedErrors;
{
@@ -327,9 +341,11 @@ void ValgrindMemcheckParserTest::testMemcheckSample1()
void ValgrindMemcheckParserTest::testMemcheckSample2()
{
- QSKIP("testfile does not exist");
+ const QString file = extraDataFile("memcheck-output-sample2.xml");
+ if (file.isEmpty())
+ QSKIP("test file does not exist");
- initTest("memcheck-output-sample2.xml");
+ initTest(file);
Parser parser;
Recorder rec(&parser);
@@ -353,9 +369,11 @@ void ValgrindMemcheckParserTest::testMemcheckSample2()
void ValgrindMemcheckParserTest::testMemcheckSample3()
{
- QSKIP("testfile does not exist");
+ const QString file = extraDataFile("memcheck-output-sample3.xml");
+ if (file.isEmpty())
+ QSKIP("test file does not exist");
- initTest("memcheck-output-sample3.xml");
+ initTest(file);
Parser parser;
Recorder rec(&parser);
@@ -405,10 +423,12 @@ void ValgrindMemcheckParserTest::testMemcheckSample3()
void ValgrindMemcheckParserTest::testMemcheckCharm()
{
- QSKIP("testfile does not exist");
-
// a somewhat larger file, to make sure buffering and partial I/O works ok
- initTest("memcheck-output-untitled.xml");
+ const QString file = extraDataFile("memcheck-output-charm.xml");
+ if (file.isEmpty())
+ QSKIP("test file does not exist");
+
+ initTest(file);
Parser parser;
Recorder rec(&parser);
@@ -426,7 +446,7 @@ void ValgrindMemcheckParserTest::testMemcheckCharm()
void ValgrindMemcheckParserTest::testValgrindCrash()
{
- initTest("memcheck-output-sample1.xml", QStringList("--crash"));
+ initTest(dataFile("memcheck-output-sample1.xml"), QStringList("--crash"));
Parser parser;
parser.parse(m_socket);
@@ -441,7 +461,7 @@ void ValgrindMemcheckParserTest::testValgrindCrash()
void ValgrindMemcheckParserTest::testValgrindGarbage()
{
- initTest("memcheck-output-sample1.xml", QStringList("--garbage"));
+ initTest(dataFile("memcheck-output-sample1.xml"), QStringList("--garbage"));
Parser parser;
parser.parse(m_socket);
diff --git a/src/plugins/valgrind/valgrindplugin.cpp b/src/plugins/valgrind/valgrindplugin.cpp
index 9512054b4a..81ed429d3d 100644
--- a/src/plugins/valgrind/valgrindplugin.cpp
+++ b/src/plugins/valgrind/valgrindplugin.cpp
@@ -53,8 +53,6 @@ using namespace ProjectExplorer;
namespace Valgrind {
namespace Internal {
-static ValgrindGlobalSettings *theGlobalSettings = nullptr;
-
class ValgrindOptionsPage : public IOptionsPage
{
public:
@@ -71,13 +69,13 @@ public:
QWidget *widget() override
{
if (!m_widget)
- m_widget = new ValgrindConfigWidget(theGlobalSettings, true);
+ m_widget = new ValgrindConfigWidget(ValgrindGlobalSettings::instance(), true);
return m_widget;
}
void apply() override
{
- theGlobalSettings->writeSettings();
+ ValgrindGlobalSettings::instance()->writeSettings();
}
void finish() override
@@ -95,7 +93,7 @@ public:
ValgrindRunConfigurationAspect(Target *)
{
setProjectSettings(new ValgrindProjectSettings);
- setGlobalSettings(ValgrindPlugin::globalSettings());
+ setGlobalSettings(ValgrindGlobalSettings::instance());
setId(ANALYZER_VALGRIND_SETTINGS);
setDisplayName(QCoreApplication::translate("Valgrind::Internal::ValgrindRunConfigurationAspect",
"Valgrind Settings"));
@@ -105,16 +103,22 @@ public:
}
};
+class ValgrindPluginPrivate
+{
+public:
+ ValgrindGlobalSettings valgrindGlobalSettings; // Needs to come before the tools.
+ MemcheckTool memcheckTool;
+ CallgrindTool callgrindTool;
+};
+
ValgrindPlugin::~ValgrindPlugin()
{
- delete theGlobalSettings;
- theGlobalSettings = nullptr;
+ delete d;
}
bool ValgrindPlugin::initialize(const QStringList &, QString *)
{
- theGlobalSettings = new ValgrindGlobalSettings;
- theGlobalSettings->readSettings();
+ d = new ValgrindPluginPrivate;
new ValgrindOptionsPage(this);
@@ -123,27 +127,9 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
return true;
}
-void ValgrindPlugin::extensionsInitialized()
-{
- initMemcheckTool();
- initCallgrindTool();
-}
-
-ExtensionSystem::IPlugin::ShutdownFlag ValgrindPlugin::aboutToShutdown()
-{
- destroyCallgrindTool();
- destroyMemcheckTool();
- return SynchronousShutdown;
-}
-
-ValgrindGlobalSettings *ValgrindPlugin::globalSettings()
-{
- return theGlobalSettings;
-}
-
-QList<QObject *> ValgrindPlugin::createTestObjects() const
+QVector<QObject *> ValgrindPlugin::createTestObjects() const
{
- QList<QObject *> tests;
+ QVector<QObject *> tests;
#ifdef WITH_TESTS
tests << new Test::ValgrindMemcheckParserTest << new Test::ValgrindTestRunnerTest;
#endif
diff --git a/src/plugins/valgrind/valgrindplugin.h b/src/plugins/valgrind/valgrindplugin.h
index 5de834d58f..f05c249e45 100644
--- a/src/plugins/valgrind/valgrindplugin.h
+++ b/src/plugins/valgrind/valgrindplugin.h
@@ -32,8 +32,6 @@
namespace Valgrind {
namespace Internal {
-class ValgrindGlobalSettings;
-
class ValgrindPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -41,15 +39,15 @@ class ValgrindPlugin : public ExtensionSystem::IPlugin
public:
ValgrindPlugin() = default;
- ~ValgrindPlugin() override;
+ ~ValgrindPlugin() final;
- bool initialize(const QStringList &arguments, QString *errorString) override;
- void extensionsInitialized() override;
- ShutdownFlag aboutToShutdown() override;
+ bool initialize(const QStringList &arguments, QString *errorString) final;
+ void extensionsInitialized() final {}
- static ValgrindGlobalSettings *globalSettings();
private:
- QList<QObject *> createTestObjects() const override;
+ QVector<QObject *> createTestObjects() const override;
+
+ class ValgrindPluginPrivate *d = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp
index c5fdc115c6..827e2c2b4e 100644
--- a/src/plugins/valgrind/valgrindrunner.cpp
+++ b/src/plugins/valgrind/valgrindrunner.cpp
@@ -46,7 +46,7 @@ class ValgrindRunner::Private : public QObject
public:
Private(ValgrindRunner *owner) : q(owner) {}
- void run();
+ bool run();
void handleRemoteStderr(const QString &b);
void handleRemoteStdout(const QString &b);
@@ -80,8 +80,44 @@ public:
bool disableXml = false;
};
-void ValgrindRunner::Private::run()
+bool ValgrindRunner::Private::run()
{
+ QStringList arguments;
+
+ if (!localServerAddress.isNull()) {
+ if (!q->startServers())
+ return false;
+
+ arguments.append("--child-silent-after-fork=yes");
+
+ bool enableXml = !disableXml;
+
+ auto handleSocketParameter = [&enableXml, &arguments](const QString &prefix, const QTcpServer &tcpServer)
+ {
+ QHostAddress serverAddress = tcpServer.serverAddress();
+ if (serverAddress.protocol() != QAbstractSocket::IPv4Protocol) {
+ // Report will end up in the Application Output pane, i.e. not have
+ // clickable items, but that's better than nothing.
+ qWarning("Need IPv4 for valgrind");
+ enableXml = false;
+ } else {
+ arguments << QString("%1=%2:%3").arg(prefix).arg(serverAddress.toString())
+ .arg(tcpServer.serverPort());
+ }
+ };
+
+ handleSocketParameter("--xml-socket", xmlServer);
+ handleSocketParameter("--log-socket", logServer);
+
+ if (enableXml)
+ arguments << "--xml=yes";
+ }
+ arguments += m_valgrindArguments;
+
+ 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,
this, &ValgrindRunner::Private::closed);
connect(&m_valgrindProcess, &ApplicationLauncher::processStarted,
@@ -100,18 +136,17 @@ void ValgrindRunner::Private::run()
connect(&m_valgrindProcess, &ApplicationLauncher::remoteProcessStarted,
this, &ValgrindRunner::Private::remoteProcessStarted);
- QStringList fullArgs = m_valgrindArguments;
if (HostOsInfo::isMacHost())
// May be slower to start but without it we get no filenames for symbols.
- fullArgs << "--dsymutil=yes";
- fullArgs << m_debuggee.executable;
+ arguments << "--dsymutil=yes";
+ arguments << m_debuggee.executable;
Runnable valgrind;
valgrind.executable = m_valgrindExecutable;
valgrind.workingDirectory = m_debuggee.workingDirectory;
valgrind.environment = m_debuggee.environment;
valgrind.device = m_device;
- valgrind.commandLineArguments = QtcProcess::joinArgs(fullArgs, m_device->osType());
+ valgrind.commandLineArguments = QtcProcess::joinArgs(arguments, m_device->osType());
Utils::QtcProcess::addArgs(&valgrind.commandLineArguments, m_debuggee.commandLineArguments);
emit q->valgrindExecuted(QtcProcess::quoteArg(valgrind.executable) + ' '
+ valgrind.commandLineArguments);
@@ -120,6 +155,8 @@ void ValgrindRunner::Private::run()
m_valgrindProcess.start(valgrind);
else
m_valgrindProcess.start(valgrind, m_device);
+
+ return true;
}
void ValgrindRunner::Private::handleRemoteStderr(const QString &b)
@@ -164,7 +201,7 @@ void ValgrindRunner::Private::remoteProcessStarted()
// we pick the last one, first would be "bash -c ..."
" | awk '{print $1;}'" // get pid
"\""
- ).arg(proc, Utils::FileName::fromString(m_debuggee.executable).fileName());
+ ).arg(proc, Utils::FilePath::fromString(m_debuggee.executable).fileName());
// m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8());
connect(&m_findPID, &ApplicationLauncher::remoteStderr,
@@ -272,47 +309,9 @@ void ValgrindRunner::waitForFinished() const
loop.exec();
}
-static void handleSocketParameter(const QString &prefix, const QTcpServer &tcpServer,
- bool *useXml, QStringList *arguments)
-{
- QHostAddress serverAddress = tcpServer.serverAddress();
- if (serverAddress.protocol() != QAbstractSocket::IPv4Protocol) {
- // Report will end up in the Application Output pane, i.e. not have
- // clickable items, but that's better than nothing.
- qWarning("Need IPv4 for valgrind");
- *useXml = false;
- } else {
- *arguments << QString("%1=%2:%3").arg(prefix).arg(serverAddress.toString())
- .arg(tcpServer.serverPort());
- }
-}
-
bool ValgrindRunner::start()
{
- if (!d->localServerAddress.isNull()) {
- if (!startServers())
- return false;
-
- bool enableXml = !d->disableXml;
-
- QStringList arguments = {"--child-silent-after-fork=yes"};
-
- handleSocketParameter("--xml-socket", d->xmlServer, &enableXml, &arguments);
- handleSocketParameter("--log-socket", d->logServer, &enableXml, &arguments);
-
- if (enableXml)
- arguments << "--xml=yes";
-
- d->m_valgrindArguments = arguments + d->m_valgrindArguments;
- }
-
- d->m_valgrindProcess.setProcessChannelMode(d->channelMode);
- // consider appending our options last so they override any interfering user-supplied options
- // -q as suggested by valgrind manual
- d->m_valgrindExecutable = d->m_valgrindExecutable;
- d->run();
-
- return true;
+ return d->run();
}
void ValgrindRunner::processError(QProcess::ProcessError e)
diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h
index faeafd3a6c..8278c94291 100644
--- a/src/plugins/valgrind/valgrindrunner.h
+++ b/src/plugins/valgrind/valgrindrunner.h
@@ -26,7 +26,7 @@
#pragma once
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/outputformat.h>
diff --git a/src/plugins/valgrind/valgrindsettings.cpp b/src/plugins/valgrind/valgrindsettings.cpp
index 0b854bc651..0d63b23ea8 100644
--- a/src/plugins/valgrind/valgrindsettings.cpp
+++ b/src/plugins/valgrind/valgrindsettings.cpp
@@ -301,12 +301,20 @@ void ValgrindBaseSettings::setVisualisationMinimumInclusiveCostRatio(
//
//////////////////////////////////////////////////////////////////
+static ValgrindGlobalSettings *theGlobalSettings = nullptr;
+
ValgrindGlobalSettings::ValgrindGlobalSettings()
: ValgrindBaseSettings([this] { return new ValgrindConfigWidget(this, true); })
{
+ theGlobalSettings = this;
readSettings();
}
+ValgrindGlobalSettings *ValgrindGlobalSettings::instance()
+{
+ return theGlobalSettings;
+}
+
void ValgrindGlobalSettings::fromMap(const QVariantMap &map)
{
ValgrindBaseSettings::fromMap(map);
@@ -513,8 +521,8 @@ void ValgrindProjectSettings::toMap(QVariantMap &map) const
void ValgrindProjectSettings::addSuppressionFiles(const QStringList &suppressions)
{
- QStringList globalSuppressions = ValgrindPlugin::globalSettings()->suppressionFiles();
- foreach (const QString &s, suppressions) {
+ const QStringList globalSuppressions = ValgrindGlobalSettings::instance()->suppressionFiles();
+ for (const QString &s : suppressions) {
if (m_addedSuppressionFiles.contains(s))
continue;
m_disabledGlobalSuppressionFiles.removeAll(s);
@@ -525,8 +533,8 @@ void ValgrindProjectSettings::addSuppressionFiles(const QStringList &suppression
void ValgrindProjectSettings::removeSuppressionFiles(const QStringList &suppressions)
{
- QStringList globalSuppressions = ValgrindPlugin::globalSettings()->suppressionFiles();
- foreach (const QString &s, suppressions) {
+ const QStringList globalSuppressions = ValgrindGlobalSettings::instance()->suppressionFiles();
+ for (const QString &s : suppressions) {
m_addedSuppressionFiles.removeAll(s);
if (globalSuppressions.contains(s))
m_disabledGlobalSuppressionFiles.append(s);
@@ -535,8 +543,8 @@ void ValgrindProjectSettings::removeSuppressionFiles(const QStringList &suppress
QStringList ValgrindProjectSettings::suppressionFiles() const
{
- QStringList ret = ValgrindPlugin::globalSettings()->suppressionFiles();
- foreach (const QString &s, m_disabledGlobalSuppressionFiles)
+ QStringList ret = ValgrindGlobalSettings::instance()->suppressionFiles();
+ for (const QString &s : m_disabledGlobalSuppressionFiles)
ret.removeAll(s);
ret.append(m_addedSuppressionFiles);
return ret;
diff --git a/src/plugins/valgrind/valgrindsettings.h b/src/plugins/valgrind/valgrindsettings.h
index 0437b50733..eaeda4190f 100644
--- a/src/plugins/valgrind/valgrindsettings.h
+++ b/src/plugins/valgrind/valgrindsettings.h
@@ -187,6 +187,8 @@ class ValgrindGlobalSettings : public ValgrindBaseSettings
public:
ValgrindGlobalSettings();
+ static ValgrindGlobalSettings *instance();
+
void toMap(QVariantMap &map) const override;
void fromMap(const QVariantMap &map) override;
diff --git a/src/plugins/vcsbase/CMakeLists.txt b/src/plugins/vcsbase/CMakeLists.txt
new file mode 100644
index 0000000000..b6d234b4f2
--- /dev/null
+++ b/src/plugins/vcsbase/CMakeLists.txt
@@ -0,0 +1,39 @@
+add_qtc_plugin(VcsBase
+ PLUGIN_DEPENDS Core CppTools DiffEditor ProjectExplorer TextEditor
+ PLUGIN_RECOMMENDS CodePaster
+ SOURCES
+ baseannotationhighlighter.cpp baseannotationhighlighter.h
+ basevcseditorfactory.cpp basevcseditorfactory.h
+ basevcssubmiteditorfactory.cpp basevcssubmiteditorfactory.h
+ cleandialog.cpp cleandialog.h cleandialog.ui
+ commonsettingspage.cpp commonsettingspage.h commonsettingspage.ui
+ commonvcssettings.cpp commonvcssettings.h
+ diffandloghighlighter.cpp diffandloghighlighter.h
+ nicknamedialog.cpp nicknamedialog.h nicknamedialog.ui
+ submiteditorfile.cpp submiteditorfile.h
+ submiteditorwidget.cpp submiteditorwidget.h submiteditorwidget.ui
+ submitfieldwidget.cpp submitfieldwidget.h
+ submitfilemodel.cpp submitfilemodel.h
+ vcsbase.qrc
+ vcsbase_global.h
+ vcsbaseclient.cpp vcsbaseclient.h
+ vcsbaseclientsettings.cpp vcsbaseclientsettings.h
+ vcsbaseconstants.h
+ vcsbasediffeditorcontroller.cpp vcsbasediffeditorcontroller.h
+ vcsbaseeditor.cpp vcsbaseeditor.h
+ vcsbaseeditorconfig.cpp vcsbaseeditorconfig.h
+ vcsbaseoptionspage.cpp vcsbaseoptionspage.h
+ vcsbaseplugin.cpp vcsbaseplugin.h
+ vcsbasesubmiteditor.cpp vcsbasesubmiteditor.h
+ vcscommand.cpp vcscommand.h
+ vcsoutputwindow.cpp vcsoutputwindow.h
+ vcsplugin.cpp vcsplugin.h
+ wizard/vcscommandpage.cpp wizard/vcscommandpage.h
+ wizard/vcsconfigurationpage.cpp wizard/vcsconfigurationpage.h
+ wizard/vcsjsextension.cpp wizard/vcsjsextension.h
+)
+
+extend_qtc_plugin(VcsBase
+ CONDITION WITH_TESTS
+ DEFINES SRC_DIR="${IDE_SOURCE_TREE}"
+)
diff --git a/src/plugins/vcsbase/submiteditorfile.cpp b/src/plugins/vcsbase/submiteditorfile.cpp
index 9136118bf7..e7e5d01e15 100644
--- a/src/plugins/vcsbase/submiteditorfile.cpp
+++ b/src/plugins/vcsbase/submiteditorfile.cpp
@@ -68,7 +68,7 @@ Core::IDocument::OpenResult SubmitEditorFile::open(QString *errorString, const Q
if (!m_editor->setFileContents(text.toUtf8()))
return OpenResult::CannotHandle;
- setFilePath(FileName::fromString(fileName));
+ setFilePath(FilePath::fromString(fileName));
setModified(fileName != realFileName);
return OpenResult::Success;
}
@@ -93,7 +93,7 @@ void SubmitEditorFile::setModified(bool modified)
bool SubmitEditorFile::save(QString *errorString, const QString &fileName, bool autoSave)
{
- const FileName fName = fileName.isEmpty() ? filePath() : FileName::fromString(fileName);
+ const FilePath fName = fileName.isEmpty() ? filePath() : FilePath::fromString(fileName);
FileSaver saver(fName.toString(),
QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
saver.write(m_editor->fileContents());
@@ -101,7 +101,7 @@ bool SubmitEditorFile::save(QString *errorString, const QString &fileName, bool
return false;
if (autoSave)
return true;
- setFilePath(FileName::fromUserInput(fName.toFileInfo().absoluteFilePath()));
+ setFilePath(FilePath::fromUserInput(fName.toFileInfo().absoluteFilePath()));
setModified(false);
if (!errorString->isEmpty())
return false;
diff --git a/src/plugins/vcsbase/submitfieldwidget.cpp b/src/plugins/vcsbase/submitfieldwidget.cpp
index 000ba51426..b92579be43 100644
--- a/src/plugins/vcsbase/submitfieldwidget.cpp
+++ b/src/plugins/vcsbase/submitfieldwidget.cpp
@@ -286,7 +286,7 @@ void SubmitFieldWidget::createField(const QString &f)
if (d->completer)
fe.lineEdit->setCompleter(d->completer);
- connect(fe.combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(fe.combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SubmitFieldWidget::slotComboIndexChanged);
connect(fe.clearButton, &QAbstractButton::clicked,
this, &SubmitFieldWidget::slotRemove);
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index bda0b6379b..4e772f3b2c 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -110,7 +110,7 @@ VcsBaseClientSettings &VcsBaseClientImpl::settings() const
return *d->m_clientSettings;
}
-FileName VcsBaseClientImpl::vcsBinary() const
+FilePath VcsBaseClientImpl::vcsBinary() const
{
return settings().binaryPath();
}
@@ -178,7 +178,7 @@ QString VcsBaseClientImpl::stripLastNewline(const QString &in)
}
SynchronousProcessResponse
-VcsBaseClientImpl::vcsFullySynchronousExec(const QString &workingDir, const FileName &binary,
+VcsBaseClientImpl::vcsFullySynchronousExec(const QString &workingDir, const FilePath &binary,
const QStringList &args, unsigned flags,
int timeoutS, QTextCodec *codec) const
{
@@ -643,7 +643,7 @@ QString VcsBaseClient::vcsEditorTitle(const QString &vcsCmd, const QString &sour
{
return vcsBinary().toFileInfo().baseName() +
QLatin1Char(' ') + vcsCmd + QLatin1Char(' ') +
- FileName::fromString(sourceId).fileName();
+ FilePath::fromString(sourceId).fileName();
}
void VcsBaseClient::statusParser(const QString &text)
diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h
index 9f365af6df..0706d53861 100644
--- a/src/plugins/vcsbase/vcsbaseclient.h
+++ b/src/plugins/vcsbase/vcsbaseclient.h
@@ -64,7 +64,7 @@ public:
VcsBaseClientSettings &settings() const;
- virtual Utils::FileName vcsBinary() const;
+ virtual Utils::FilePath vcsBinary() const;
int vcsTimeoutS() const;
enum JobOutputBindMode {
@@ -105,7 +105,7 @@ public:
vcsFullySynchronousExec(const QString &workingDir, const QStringList &args,
unsigned flags = 0, int timeoutS = -1, QTextCodec *codec = nullptr) const;
Utils::SynchronousProcessResponse
- vcsFullySynchronousExec(const QString &workingDir, const Utils::FileName &binary, const QStringList &args,
+ vcsFullySynchronousExec(const QString &workingDir, const Utils::FilePath &binary, const QStringList &args,
unsigned flags = 0, int timeoutS = -1, QTextCodec *codec = nullptr) const;
diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.cpp b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
index 7d30181959..96571e5782 100644
--- a/src/plugins/vcsbase/vcsbaseclientsettings.cpp
+++ b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
@@ -175,7 +175,7 @@ public:
QHash<QString, SettingValue> m_valueHash;
QVariantHash m_defaultValueHash;
QString m_settingsGroup;
- mutable FileName m_binaryFullPath;
+ mutable FilePath m_binaryFullPath;
};
} // namespace Internal
@@ -351,11 +351,11 @@ QVariant::Type VcsBaseClientSettings::valueType(const QString &key) const
return QVariant::Invalid;
}
-FileName VcsBaseClientSettings::binaryPath() const
+FilePath VcsBaseClientSettings::binaryPath() const
{
if (d->m_binaryFullPath.isEmpty()) {
- const FileNameList searchPaths
- = Utils::transform(searchPathList(), [](const QString &s) { return FileName::fromString(s); });
+ const FilePathList searchPaths
+ = Utils::transform(searchPathList(), [](const QString &s) { return FilePath::fromString(s); });
d->m_binaryFullPath = Environment::systemEnvironment().searchInPath(
stringValue(binaryPathKey), searchPaths);
}
diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.h b/src/plugins/vcsbase/vcsbaseclientsettings.h
index 137d4391d8..e722a56564 100644
--- a/src/plugins/vcsbase/vcsbaseclientsettings.h
+++ b/src/plugins/vcsbase/vcsbaseclientsettings.h
@@ -35,7 +35,7 @@ QT_BEGIN_NAMESPACE
class QSettings;
QT_END_NAMESPACE
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace VcsBase {
namespace Internal { class VcsBaseClientSettingsPrivate; }
@@ -77,7 +77,7 @@ public:
void setValue(const QString &key, const QVariant &v);
QVariant::Type valueType(const QString &key) const;
- Utils::FileName binaryPath() const;
+ Utils::FilePath binaryPath() const;
QStringList searchPathList() const;
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 6fcfd09eae..c6b5ed8fbe 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -724,7 +724,7 @@ void VcsBaseEditorWidget::init()
case OtherContent:
break;
case LogOutput:
- connect(d->entriesComboBox(), static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(d->entriesComboBox(), QOverload<int>::of(&QComboBox::activated),
this, &VcsBaseEditorWidget::slotJumpToEntry);
connect(this, &QPlainTextEdit::textChanged,
this, &VcsBaseEditorWidget::slotPopulateLogBrowser);
@@ -737,7 +737,7 @@ void VcsBaseEditorWidget::init()
break;
case DiffOutput:
// Diff: set up diff file browsing
- connect(d->entriesComboBox(), static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(d->entriesComboBox(), QOverload<int>::of(&QComboBox::activated),
this, &VcsBaseEditorWidget::slotJumpToEntry);
connect(this, &QPlainTextEdit::textChanged,
this, &VcsBaseEditorWidget::slotPopulateDiffBrowser);
@@ -868,7 +868,7 @@ void VcsBaseEditorWidget::slotPopulateDiffBrowser()
lastFileName = file;
// ignore any headers
d->m_entrySections.push_back(d->m_entrySections.empty() ? 0 : lineNumber);
- entriesComboBox->addItem(FileName::fromString(file).fileName());
+ entriesComboBox->addItem(FilePath::fromString(file).fileName());
}
}
}
@@ -979,11 +979,11 @@ void VcsBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
// the user has "Open With" and choose the right diff editor so that
// fileNameFromDiffSpecification() works.
QAction *applyAction = menu->addAction(tr("Apply Chunk..."));
- applyAction->setData(qVariantFromValue(Internal::DiffChunkAction(chunk, false)));
+ applyAction->setData(QVariant::fromValue(Internal::DiffChunkAction(chunk, false)));
connect(applyAction, &QAction::triggered, this, &VcsBaseEditorWidget::slotApplyDiffChunk);
// Revert a chunk from a VCS diff, which might be linked to reloading the diff.
QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
- revertAction->setData(qVariantFromValue(Internal::DiffChunkAction(chunk, true)));
+ revertAction->setData(QVariant::fromValue(Internal::DiffChunkAction(chunk, true)));
connect(revertAction, &QAction::triggered, this, &VcsBaseEditorWidget::slotApplyDiffChunk);
// Custom diff actions
addDiffActions(menu, chunk);
diff --git a/src/plugins/vcsbase/vcsbaseeditorconfig.cpp b/src/plugins/vcsbase/vcsbaseeditorconfig.cpp
index f3f96e3b3f..ee40e2649a 100644
--- a/src/plugins/vcsbase/vcsbaseeditorconfig.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditorconfig.cpp
@@ -175,7 +175,7 @@ QComboBox *VcsBaseEditorConfig::addComboBox(const QStringList &options,
auto cb = new QComboBox;
foreach (const ComboBoxItem &item, items)
cb->addItem(item.displayText, item.value);
- connect(cb, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(cb, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &VcsBaseEditorConfig::argumentsChanged);
d->m_toolBar->addWidget(cb);
d->m_optionMappings.append(OptionMapping(options, cb));
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index 2d70846c34..298fdf61b3 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -791,7 +791,7 @@ void VcsBasePlugin::setProcessEnvironment(QProcessEnvironment *e,
// Run a process synchronously, returning Utils::SynchronousProcessResponse
// response struct and using the VcsBasePlugin flags as applicable
SynchronousProcessResponse VcsBasePlugin::runVcs(const QString &workingDir,
- const FileName &binary,
+ const FilePath &binary,
const QStringList &arguments,
int timeOutS,
unsigned flags,
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index 1bbe0c29b4..e1bfa15ded 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -41,7 +41,7 @@ class QTextCodec;
QT_END_NAMESPACE
namespace Utils {
-class FileName;
+class FilePath;
class SynchronousProcessResponse;
} // namespace Utils
@@ -170,7 +170,7 @@ public:
static QString source(Core::IDocument *document);
static Utils::SynchronousProcessResponse runVcs(const QString &workingDir,
- const Utils::FileName &binary,
+ const Utils::FilePath &binary,
const QStringList &arguments,
int timeOutS,
unsigned flags = 0,
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
index d66759cd17..3017ae03b9 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
@@ -569,7 +569,7 @@ VcsBaseSubmitEditor::PromptSubmitResult
const QString commitName = plugin->commitDisplayName();
mb.setWindowTitle(tr("Close %1 %2 Editor")
.arg(plugin->versionControl()->displayName(), commitName));
- mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question));
+ mb.setIcon(QMessageBox::Question);
QString message;
if (canCommit) {
message = tr("What do you want to do with these changes?");
@@ -741,7 +741,7 @@ void VcsBaseSubmitEditor::filterUntrackedFilesOfProject(const QString &repositor
const QDir repoDir(repositoryDirectory);
for (QStringList::iterator it = untrackedFiles->begin(); it != untrackedFiles->end(); ) {
const QString path = repoDir.absoluteFilePath(*it);
- if (ProjectExplorer::SessionManager::projectForFile(FileName::fromString(path)))
+ if (ProjectExplorer::SessionManager::projectForFile(FilePath::fromString(path)))
++it;
else
it = untrackedFiles->erase(it);
diff --git a/src/plugins/vcsbase/vcscommand.cpp b/src/plugins/vcsbase/vcscommand.cpp
index 6422eb2997..a659b13fec 100644
--- a/src/plugins/vcsbase/vcscommand.cpp
+++ b/src/plugins/vcsbase/vcscommand.cpp
@@ -77,7 +77,7 @@ const QProcessEnvironment VcsCommand::processEnvironment() const
return env;
}
-SynchronousProcessResponse VcsCommand::runCommand(const FileName &binary,
+SynchronousProcessResponse VcsCommand::runCommand(const FilePath &binary,
const QStringList &arguments, int timeoutS,
const QString &workingDirectory,
const ExitCodeInterpreter &interpreter)
diff --git a/src/plugins/vcsbase/vcscommand.h b/src/plugins/vcsbase/vcscommand.h
index bc7ad022e4..191b72b980 100644
--- a/src/plugins/vcsbase/vcscommand.h
+++ b/src/plugins/vcsbase/vcscommand.h
@@ -45,7 +45,7 @@ public:
const QProcessEnvironment processEnvironment() const override;
- Utils::SynchronousProcessResponse runCommand(const Utils::FileName &binary,
+ Utils::SynchronousProcessResponse runCommand(const Utils::FilePath &binary,
const QStringList &arguments, int timeoutS,
const QString &workDirectory = QString(),
const Utils::ExitCodeInterpreter &interpreter = Utils::defaultExitCodeInterpreter) override;
diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp
index 1207d0279a..07113e7fd9 100644
--- a/src/plugins/vcsbase/vcsoutputwindow.cpp
+++ b/src/plugins/vcsbase/vcsoutputwindow.cpp
@@ -33,24 +33,26 @@
#include <utils/fileutils.h>
#include <utils/outputformatter.h>
#include <utils/qtcprocess.h>
+#include <texteditor/behaviorsettings.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorsettings.h>
#include <utils/theme/theme.h>
-#include <QPlainTextEdit>
-#include <QTextCharFormat>
+#include <QAction>
#include <QContextMenuEvent>
-#include <QTextBlock>
+#include <QDir>
+#include <QFileInfo>
#include <QMenu>
-#include <QAction>
-#include <QTextBlockUserData>
-
+#include <QPlainTextEdit>
+#include <QPoint>
#include <QPointer>
-#include <QTextCodec>
-#include <QDir>
#include <QRegExp>
+#include <QTextBlock>
+#include <QTextBlockUserData>
+#include <QTextCharFormat>
+#include <QTextCodec>
#include <QTextStream>
#include <QTime>
-#include <QPoint>
-#include <QFileInfo>
using namespace Utils;
@@ -75,6 +77,8 @@ namespace Internal {
const char C_VCS_OUTPUT_PANE[] = "Vcs.OutputPane";
+const char zoomSettingsKey[] = "Vcs/OutputPane/Zoom";
+
// Store repository along with text blocks
class RepositoryUserData : public QTextBlockUserData
{
@@ -86,7 +90,7 @@ private:
const QString m_repository;
};
-// A plain text edit with a special context menu containing "Clear" and
+// A plain text edit with a special context menu containing "Clear"
// and functions to append specially formatted entries.
class OutputWindowPlainTextEdit : public Core::OutputWindow
{
@@ -94,27 +98,23 @@ public:
explicit OutputWindowPlainTextEdit(QWidget *parent = nullptr);
~OutputWindowPlainTextEdit() override;
- void appendLines(QString const& s, const QString &repository = QString());
- void appendLinesWithStyle(QString const& s, enum VcsOutputWindow::MessageStyle style, const QString &repository = QString());
+ void appendLines(const QString &s, const QString &repository = QString());
+ void appendLinesWithStyle(const QString &s, VcsOutputWindow::MessageStyle style,
+ const QString &repository = QString());
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
private:
- void setFormat(enum VcsOutputWindow::MessageStyle style);
+ void setFormat(VcsOutputWindow::MessageStyle style);
QString identifierUnderCursor(const QPoint &pos, QString *repository = nullptr) const;
Utils::OutputFormat m_format;
- const QTextCharFormat m_defaultFormat;
- QTextCharFormat m_errorFormat;
- QTextCharFormat m_warningFormat;
- QTextCharFormat m_commandFormat;
- QTextCharFormat m_messageFormat;
- OutputFormatter *m_formatter;
+ OutputFormatter *m_formatter = nullptr;
};
OutputWindowPlainTextEdit::OutputWindowPlainTextEdit(QWidget *parent) :
- Core::OutputWindow(Core::Context(C_VCS_OUTPUT_PANE), parent)
+ Core::OutputWindow(Core::Context(C_VCS_OUTPUT_PANE), zoomSettingsKey, parent)
{
setReadOnly(true);
setUndoRedoEnabled(false);
@@ -163,7 +163,7 @@ QString OutputWindowPlainTextEdit::identifierUnderCursor(const QPoint &widgetPos
// Retrieve repository if desired
if (repository)
if (QTextBlockUserData *data = cursor.block().userData())
- *repository = static_cast<const RepositoryUserData*>(data)->repository();
+ *repository = static_cast<const RepositoryUserData *>(data)->repository();
// Find first non-space character of word and find first non-space character past
const int startPos = firstWordCharacter(block, cursorPos);
int endPos = cursorPos;
@@ -182,7 +182,7 @@ void OutputWindowPlainTextEdit::contextMenuEvent(QContextMenuEvent *event)
// Check for a file, expand via repository if relative
QFileInfo fi(token);
if (!repository.isEmpty() && !fi.isFile() && fi.isRelative())
- fi = QFileInfo(repository + QLatin1Char('/') + token);
+ fi = QFileInfo(repository + '/' + token);
if (fi.isFile()) {
menu->addSeparator();
openAction = menu->addAction(VcsOutputWindow::tr("Open \"%1\"").
@@ -209,16 +209,16 @@ void OutputWindowPlainTextEdit::contextMenuEvent(QContextMenuEvent *event)
delete menu;
}
-void OutputWindowPlainTextEdit::appendLines(QString const& s, const QString &repository)
+void OutputWindowPlainTextEdit::appendLines(const QString &s, const QString &repository)
{
if (s.isEmpty())
return;
const int previousLineCount = document()->lineCount();
- const QChar newLine(QLatin1Char('\n'));
+ const QChar newLine('\n');
const QChar lastChar = s.at(s.size() - 1);
- const bool appendNewline = (lastChar != QLatin1Char('\r') && lastChar != newLine);
+ const bool appendNewline = (lastChar != '\r' && lastChar != newLine);
m_formatter->appendMessage(appendNewline ? s + newLine : s, m_format);
// Scroll down
@@ -232,20 +232,21 @@ void OutputWindowPlainTextEdit::appendLines(QString const& s, const QString &rep
}
}
-void OutputWindowPlainTextEdit::appendLinesWithStyle(QString const& s, enum VcsOutputWindow::MessageStyle style, const QString &repository)
+void OutputWindowPlainTextEdit::appendLinesWithStyle(const QString &s,
+ VcsOutputWindow::MessageStyle style,
+ const QString &repository)
{
setFormat(style);
if (style == VcsOutputWindow::Command) {
- const QString timeStamp = QTime::currentTime().toString(QLatin1String("\nHH:mm "));
+ const QString timeStamp = QTime::currentTime().toString("\nHH:mm ");
appendLines(timeStamp + s, repository);
- }
- else {
+ } else {
appendLines(s, repository);
}
}
-void OutputWindowPlainTextEdit::setFormat(enum VcsOutputWindow::MessageStyle style)
+void OutputWindowPlainTextEdit::setFormat(VcsOutputWindow::MessageStyle style)
{
m_formatter->setBoldFontEnabled(style == VcsOutputWindow::Command);
@@ -286,9 +287,23 @@ static VcsOutputWindowPrivate *d = nullptr;
VcsOutputWindow::VcsOutputWindow()
{
d = new VcsOutputWindowPrivate;
- d->passwordRegExp = QRegExp(QLatin1String("://([^@:]+):([^@]+)@"));
+ d->passwordRegExp = QRegExp("://([^@:]+):([^@]+)@");
Q_ASSERT(d->passwordRegExp.isValid());
m_instance = this;
+
+ auto updateBehaviorSettings = [] {
+ d->widget.setWheelZoomEnabled(
+ TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
+ };
+
+ updateBehaviorSettings();
+ setupContext(Internal::C_VCS_OUTPUT_PANE, &d->widget);
+
+ connect(this, &IOutputPane::zoomIn, &d->widget, &Core::OutputWindow::zoomIn);
+ connect(this, &IOutputPane::zoomOut, &d->widget, &Core::OutputWindow::zoomOut);
+ connect(this, &IOutputPane::resetZoom, &d->widget, &Core::OutputWindow::resetZoom);
+ connect(TextEditor::TextEditorSettings::instance(), &TextEditor::TextEditorSettings::behaviorSettingsChanged,
+ this, updateBehaviorSettings);
}
static QString filterPasswordFromUrls(const QString &input)
@@ -296,7 +311,7 @@ static QString filterPasswordFromUrls(const QString &input)
int pos = 0;
QString result = input;
while ((pos = d->passwordRegExp.indexIn(result, pos)) >= 0) {
- QString tmp = result.left(pos + 3) + d->passwordRegExp.cap(1) + QLatin1String(":***@");
+ QString tmp = result.left(pos + 3) + d->passwordRegExp.cap(1) + ":***@";
int newStart = tmp.count();
tmp += result.midRef(pos + d->passwordRegExp.matchedLength());
result = tmp;
@@ -318,11 +333,6 @@ QWidget *VcsOutputWindow::outputWidget(QWidget *parent)
return &d->widget;
}
-QList<QWidget *> VcsOutputWindow::toolBarWidgets() const
-{
- return {};
-}
-
QString VcsOutputWindow::displayName() const
{
return tr("Version Control");
@@ -397,7 +407,7 @@ void VcsOutputWindow::appendSilently(const QString &text)
append(text, None, true);
}
-void VcsOutputWindow::append(const QString &text, enum MessageStyle style, bool silently)
+void VcsOutputWindow::append(const QString &text, MessageStyle style, bool silently)
{
d->widget.appendLinesWithStyle(text, style, d->repository);
@@ -415,8 +425,7 @@ void VcsOutputWindow::appendWarning(const QString &text)
append(text, Warning, false);
}
-// Helper to format arguments for log windows hiding common password
-// options.
+// Helper to format arguments for log windows hiding common password options.
static inline QString formatArguments(const QStringList &args)
{
const char passwordOptionC[] = "--password";
@@ -429,12 +438,12 @@ static inline QString formatArguments(const QStringList &args)
const QString arg = filterPasswordFromUrls(args.at(i));
if (i)
str << ' ';
- if (arg.startsWith(QString::fromLatin1(passwordOptionC) + QLatin1Char('='))) {
+ if (arg.startsWith(QString::fromLatin1(passwordOptionC) + '=')) {
str << QtcProcess::quoteArg("--password=********");
continue;
}
str << QtcProcess::quoteArg(arg);
- if (arg == QLatin1String(passwordOptionC)) {
+ if (arg == passwordOptionC) {
str << ' ' << QtcProcess::quoteArg("********");
i++;
}
@@ -443,15 +452,15 @@ static inline QString formatArguments(const QStringList &args)
}
QString VcsOutputWindow::msgExecutionLogEntry(const QString &workingDir,
- const FileName &executable,
+ const FilePath &executable,
const QStringList &arguments)
{
const QString args = formatArguments(arguments);
const QString nativeExecutable = QtcProcess::quoteArg(executable.toUserOutput());
if (workingDir.isEmpty())
- return tr("Running: %1 %2").arg(nativeExecutable, args) + QLatin1Char('\n');
+ return tr("Running: %1 %2").arg(nativeExecutable, args) + '\n';
return tr("Running in %1: %2 %3").
- arg(QDir::toNativeSeparators(workingDir), nativeExecutable, args) + QLatin1Char('\n');
+ arg(QDir::toNativeSeparators(workingDir), nativeExecutable, args) + '\n';
}
void VcsOutputWindow::appendShellCommandLine(const QString &text)
@@ -460,7 +469,7 @@ void VcsOutputWindow::appendShellCommandLine(const QString &text)
}
void VcsOutputWindow::appendCommand(const QString &workingDirectory,
- const FileName &binary,
+ const FilePath &binary,
const QStringList &args)
{
appendShellCommandLine(msgExecutionLogEntry(workingDirectory, binary, args));
diff --git a/src/plugins/vcsbase/vcsoutputwindow.h b/src/plugins/vcsbase/vcsoutputwindow.h
index 1f78cd515f..d54b4e6306 100644
--- a/src/plugins/vcsbase/vcsoutputwindow.h
+++ b/src/plugins/vcsbase/vcsoutputwindow.h
@@ -29,7 +29,7 @@
#include <coreplugin/ioutputpane.h>
-namespace Utils { class FileName; }
+namespace Utils { class FilePath; }
namespace VcsBase {
namespace Internal { class VcsPlugin; }
@@ -41,7 +41,6 @@ class VCSBASE_EXPORT VcsOutputWindow : public Core::IOutputPane
public:
QWidget *outputWidget(QWidget *parent) override;
- QList<QWidget *> toolBarWidgets() const override;
QString displayName() const override;
int priorityInStatusBar() const override;
@@ -67,7 +66,7 @@ public:
// 'Executing <dir>: <cmd> <args>'. Hides well-known password option
// arguments.
static QString msgExecutionLogEntry(const QString &workingDir,
- const Utils::FileName &executable,
+ const Utils::FilePath &executable,
const QStringList &arguments);
enum MessageStyle {
@@ -89,7 +88,7 @@ public slots:
// Append text with a certain style (none by default),
// and maybe pop up (silent by default)
- static void append(const QString &text, enum MessageStyle style = None, bool silently = false);
+ static void append(const QString &text, MessageStyle style = None, bool silently = false);
// Silently append text, do not pop up.
static void appendSilently(const QString &text);
@@ -108,7 +107,7 @@ public slots:
// Append a standard-formatted entry for command execution
// (see msgExecutionLogEntry).
static void appendCommand(const QString &workingDirectory,
- const Utils::FileName &binary,
+ const Utils::FilePath &binary,
const QStringList &args);
// Append a blue message text and pop up.
diff --git a/src/plugins/vcsbase/vcsplugin.cpp b/src/plugins/vcsbase/vcsplugin.cpp
index 201f2a3b43..efb70f1696 100644
--- a/src/plugins/vcsbase/vcsplugin.cpp
+++ b/src/plugins/vcsbase/vcsplugin.cpp
@@ -98,7 +98,7 @@ bool VcsPlugin::initialize(const QStringList &arguments, QString *errorMessage)
JsonWizardFactory::registerPageFactory(new Internal::VcsConfigurationPageFactory);
JsonWizardFactory::registerPageFactory(new Internal::VcsCommandPageFactory);
- JsExpander::registerQObjectForJs(QLatin1String("Vcs"), new VcsJsExtension);
+ JsExpander::registerGlobalObject<VcsJsExtension>("Vcs");
Utils::MacroExpander *expander = Utils::globalMacroExpander();
expander->registerVariable(Constants::VAR_VCS_NAME,
diff --git a/src/plugins/vcsbase/wizard/vcscommandpage.cpp b/src/plugins/vcsbase/wizard/vcscommandpage.cpp
index 6ad605f586..f40138c1a3 100644
--- a/src/plugins/vcsbase/wizard/vcscommandpage.cpp
+++ b/src/plugins/vcsbase/wizard/vcscommandpage.cpp
@@ -287,7 +287,7 @@ void VcsCommandPage::delayedInitialize()
}
Core::ShellCommand *command
- = vc->createInitialCheckoutCommand(repo, FileName::fromString(base),
+ = vc->createInitialCheckoutCommand(repo, FilePath::fromString(base),
name, extraArgs);
foreach (const JobData &job, m_additionalJobs) {
@@ -310,7 +310,7 @@ void VcsCommandPage::delayedInitialize()
const QString dir = wiz->expander()->expand(job.workDirectory);
const int timeoutS = command->defaultTimeoutS() * job.timeOutFactor;
- command->addJob(FileName::fromUserInput(commandString), args, timeoutS, dir);
+ command->addJob(FilePath::fromUserInput(commandString), args, timeoutS, dir);
}
start(command);
diff --git a/src/plugins/welcome/CMakeLists.txt b/src/plugins/welcome/CMakeLists.txt
new file mode 100644
index 0000000000..4b07301581
--- /dev/null
+++ b/src/plugins/welcome/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_plugin(Welcome
+ DEPENDS
+ PLUGIN_DEPENDS Core
+ SOURCES
+ introductionwidget.cpp introductionwidget.h
+ welcome.qrc
+ welcomeplugin.cpp
+)
diff --git a/src/plugins/welcome/introductionwidget.cpp b/src/plugins/welcome/introductionwidget.cpp
index e931975f6f..82539fd996 100644
--- a/src/plugins/welcome/introductionwidget.cpp
+++ b/src/plugins/welcome/introductionwidget.cpp
@@ -52,9 +52,9 @@ void IntroductionWidget::askUserAboutIntroduction(QWidget *parent, QSettings *se
auto messageBox = new CheckableMessageBox(parent);
messageBox->setWindowTitle(tr("Take a UI Tour"));
messageBox->setText(
- tr("Do you want to take a quick UI tour? This shows where the most important user "
- "interface elements are, and how they are used, and will only take a minute. You can "
- "also take the tour later by selecting Help > UI Tour."));
+ tr("Would you like to take a quick UI tour? This tour highlights important user "
+ "interface elements and shows how they are used. To take the tour later, "
+ "select Help > UI Tour."));
messageBox->setCheckBoxVisible(true);
messageBox->setCheckBoxText(CheckableMessageBox::msgDoNotAskAgain());
messageBox->setChecked(true);
diff --git a/src/plugins/winrt/CMakeLists.txt b/src/plugins/winrt/CMakeLists.txt
new file mode 100644
index 0000000000..693b544612
--- /dev/null
+++ b/src/plugins/winrt/CMakeLists.txt
@@ -0,0 +1,16 @@
+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.pro b/src/plugins/winrt/winrt.pro
index 15b4a3bb98..1d6a7608fe 100644
--- a/src/plugins/winrt/winrt.pro
+++ b/src/plugins/winrt/winrt.pro
@@ -5,12 +5,10 @@ HEADERS += \
winrtdebugsupport.h \
winrtdeployconfiguration.h \
winrtdevice.h \
- winrtdevicefactory.h \
winrtpackagedeploymentstep.h \
winrtphoneqtversion.h \
winrtplugin.h \
winrtqtversion.h \
- winrtqtversionfactory.h \
winrtrunconfiguration.h \
winrtruncontrol.h \
winrtrunnerhelper.h
@@ -19,12 +17,10 @@ SOURCES += \
winrtdebugsupport.cpp \
winrtdeployconfiguration.cpp \
winrtdevice.cpp \
- winrtdevicefactory.cpp \
winrtpackagedeploymentstep.cpp \
winrtphoneqtversion.cpp \
winrtplugin.cpp \
winrtqtversion.cpp \
- winrtqtversionfactory.cpp \
winrtrunconfiguration.cpp \
winrtruncontrol.cpp \
winrtrunnerhelper.cpp
diff --git a/src/plugins/winrt/winrt.qbs b/src/plugins/winrt/winrt.qbs
index 9053161c5c..f511a9c31a 100644
--- a/src/plugins/winrt/winrt.qbs
+++ b/src/plugins/winrt/winrt.qbs
@@ -12,6 +12,7 @@ QtcPlugin {
Depends { name: "app_version_header" }
files: [
+ "winrt.qrc",
"winrtconstants.h",
"winrtdebugsupport.cpp",
"winrtdebugsupport.h",
@@ -19,8 +20,6 @@ QtcPlugin {
"winrtdeployconfiguration.h",
"winrtdevice.cpp",
"winrtdevice.h",
- "winrtdevicefactory.cpp",
- "winrtdevicefactory.h",
"winrtpackagedeploymentstep.cpp",
"winrtpackagedeploymentstep.h",
"winrtphoneqtversion.cpp",
@@ -29,8 +28,6 @@ QtcPlugin {
"winrtplugin.h",
"winrtqtversion.cpp",
"winrtqtversion.h",
- "winrtqtversionfactory.cpp",
- "winrtqtversionfactory.h",
"winrtrunconfiguration.cpp",
"winrtrunconfiguration.h",
"winrtruncontrol.cpp",
diff --git a/src/plugins/winrt/winrtdebugsupport.cpp b/src/plugins/winrt/winrtdebugsupport.cpp
index f7962c4ef0..d7f3e9a59b 100644
--- a/src/plugins/winrt/winrtdebugsupport.cpp
+++ b/src/plugins/winrt/winrtdebugsupport.cpp
@@ -75,7 +75,7 @@ WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl)
setQmlServer(qmlServer);
}
- setSymbolFile(runControl->runConfiguration()->buildTargetInfo().targetFilePath.toString());
+ setSymbolFile(runControl->buildTargetInfo().targetFilePath.toString());
QString errorMessage;
m_runner = new WinRtRunnerHelper(this, &errorMessage);
if (!errorMessage.isEmpty()) {
diff --git a/src/plugins/winrt/winrtdevice.cpp b/src/plugins/winrt/winrtdevice.cpp
index 5f6478a72f..9ceba3b323 100644
--- a/src/plugins/winrt/winrtdevice.cpp
+++ b/src/plugins/winrt/winrtdevice.cpp
@@ -25,23 +25,39 @@
#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 <QCoreApplication>
+#include <QIcon>
+#include <QLoggingCategory>
#include <QWizard>
+using QtSupport::BaseQtVersion;
+using QtSupport::QtVersionManager;
+
+
+using namespace Core;
using namespace ProjectExplorer;
+using namespace Utils;
namespace WinRt {
namespace Internal {
+Q_LOGGING_CATEGORY(winrtDeviceLog, "qtc.winrt.deviceParser", QtWarningMsg)
+
WinRtDevice::WinRtDevice()
{
Utils::PortList portList;
@@ -90,11 +106,6 @@ Utils::OsType WinRtDevice::osType() const
return Utils::OsTypeWindows;
}
-IDevice::Ptr WinRtDevice::clone() const
-{
- return IDevice::Ptr(new WinRtDevice(*this));
-}
-
QString WinRtDevice::displayNameForType(Core::Id type)
{
if (type == Constants::WINRT_DEVICE_TYPE_LOCAL)
@@ -109,5 +120,257 @@ QString WinRtDevice::displayNameForType(Core::Id type)
return QString();
}
+
+// Factory
+
+WinRtDeviceFactory::WinRtDeviceFactory(Core::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__;
+ MessageManager::write(tr("Running Windows Runtime device detection."));
+ const QString runnerFilePath = findRunnerFilePath();
+ if (runnerFilePath.isEmpty()) {
+ MessageManager::write(tr("No winrtrunner.exe found."));
+ return;
+ }
+
+ if (!m_process) {
+ qCDebug(winrtDeviceLog) << __FUNCTION__ << "Creating process";
+ m_process = new Utils::QtcProcess(this);
+ connect(m_process, &QProcess::errorOccurred, this, &WinRtDeviceFactory::onProcessError);
+ connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, &WinRtDeviceFactory::onProcessFinished);
+ }
+
+ const QString args = QStringLiteral("--list-devices");
+ m_process->setCommand(CommandLine(FilePath::fromString(runnerFilePath), args));
+ qCDebug(winrtDeviceLog) << __FUNCTION__ << "Starting process" << runnerFilePath
+ << "with arguments" << args;
+ MessageManager::write(runnerFilePath + QLatin1Char(' ') + args);
+ 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::write(tr("Error while executing winrtrunner: %1")
+ .arg(m_process->errorString()), MessageManager::Flash);
+}
+
+void WinRtDeviceFactory::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ qCDebug(winrtDeviceLog) << __FUNCTION__ << "Exit code:" << exitCode <<"\tExit status:"
+ << exitStatus;
+ if (exitStatus == QProcess::CrashExit) {
+ // already handled in onProcessError
+ return;
+ }
+
+ if (exitCode != 0) {
+ MessageManager::write(tr("winrtrunner returned with exit code %1.")
+ .arg(exitCode), MessageManager::Flash);
+ 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<BaseQtVersion *> winrtVersions
+ = QtVersionManager::sortVersions(
+ QtVersionManager::versions(BaseQtVersion::isValidPredicate([](const BaseQtVersion *v) {
+ return v->type() == QLatin1String(Constants::WINRT_WINRTQT)
+ || v->type() == QLatin1String(Constants::WINRT_WINPHONEQT);
+ })));
+ QString filePath;
+ BaseQtVersion *qt = nullptr;
+ for (BaseQtVersion *v : winrtVersions) {
+ if (!qt || qt->qtVersion() < v->qtVersion()) {
+ QFileInfo fi(v->binPath().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);
+ Core::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 Core::Id internalId = Core::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->setDisplayName(name);
+ deviceManager->addDevice(ProjectExplorer::IDevice::ConstPtr(device));
+ qCDebug(winrtDeviceLog) << __FUNCTION__ << "Added device" << name << "(internal name:"
+ << internalName << ")";
+ }
+ }
+ QString message = tr("Found %n Windows Runtime devices.", 0, numFound);
+ if (const int numNew = numFound - numSkipped) {
+ message += QLatin1Char(' ');
+ message += tr("%n of them are new.", 0, numNew);
+ }
+ MessageManager::write(message);
+}
+
} // Internal
} // WinRt
diff --git a/src/plugins/winrt/winrtdevice.h b/src/plugins/winrt/winrtdevice.h
index 96cca4dc38..f66c6c31ab 100644
--- a/src/plugins/winrt/winrtdevice.h
+++ b/src/plugins/winrt/winrtdevice.h
@@ -26,6 +26,9 @@
#pragma once
#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/devicesupport/idevicefactory.h>
+
+#include <utils/qtcprocess.h>
namespace WinRt {
namespace Internal {
@@ -44,7 +47,6 @@ public:
void fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
Utils::OsType osType() const override;
- ProjectExplorer::IDevice::Ptr clone() const override;
static QString displayNameForType(Core::Id type);
int deviceId() const { return m_deviceId; }
@@ -56,5 +58,26 @@ private:
int m_deviceId = -1;
};
+class WinRtDeviceFactory : public ProjectExplorer::IDeviceFactory
+{
+ Q_OBJECT
+public:
+ explicit WinRtDeviceFactory(Core::Id deviceType);
+
+ void autoDetect();
+ void onPrerequisitesLoaded();
+
+private:
+ void onProcessError();
+ void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
+
+ 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/winrtdevicefactory.cpp b/src/plugins/winrt/winrtdevicefactory.cpp
deleted file mode 100644
index 52b6dac69d..0000000000
--- a/src/plugins/winrt/winrtdevicefactory.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtdevicefactory.h"
-
-#include "winrtconstants.h"
-#include "winrtdevice.h"
-#include "winrtqtversion.h"
-
-#include <coreplugin/messagemanager.h>
-#include <projectexplorer/devicesupport/devicemanager.h>
-#include <qtsupport/qtversionmanager.h>
-
-#include <utils/qtcassert.h>
-
-#include <QFileInfo>
-#include <QIcon>
-#include <QLoggingCategory>
-
-using Core::MessageManager;
-using ProjectExplorer::DeviceManager;
-using ProjectExplorer::IDevice;
-using QtSupport::BaseQtVersion;
-using QtSupport::QtVersionManager;
-
-Q_LOGGING_CATEGORY(winrtDeviceLog, "qtc.winrt.deviceParser", QtWarningMsg)
-
-namespace WinRt {
-namespace Internal {
-
-WinRtDeviceFactory::WinRtDeviceFactory(Core::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__;
- MessageManager::write(tr("Running Windows Runtime device detection."));
- const QString runnerFilePath = findRunnerFilePath();
- if (runnerFilePath.isEmpty()) {
- MessageManager::write(tr("No winrtrunner.exe found."));
- return;
- }
-
- if (!m_process) {
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Creating process";
- m_process = new Utils::QtcProcess(this);
- connect(m_process, &QProcess::errorOccurred, this, &WinRtDeviceFactory::onProcessError);
- connect(m_process,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
- this, &WinRtDeviceFactory::onProcessFinished);
- }
-
- const QString args = QStringLiteral("--list-devices");
- m_process->setCommand(runnerFilePath, args);
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Starting process" << runnerFilePath
- << "with arguments" << args;
- MessageManager::write(runnerFilePath + QLatin1Char(' ') + args);
- 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::write(tr("Error while executing winrtrunner: %1")
- .arg(m_process->errorString()), MessageManager::Flash);
-}
-
-void WinRtDeviceFactory::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
-{
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Exit code:" << exitCode <<"\tExit status:"
- << exitStatus;
- if (exitStatus == QProcess::CrashExit) {
- // already handled in onProcessError
- return;
- }
-
- if (exitCode != 0) {
- MessageManager::write(tr("winrtrunner returned with exit code %1.")
- .arg(exitCode), MessageManager::Flash);
- 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<BaseQtVersion *> winrtVersions
- = QtVersionManager::sortVersions(
- QtVersionManager::versions(BaseQtVersion::isValidPredicate([](const BaseQtVersion *v) {
- return v->type() == QLatin1String(Constants::WINRT_WINRTQT)
- || v->type() == QLatin1String(Constants::WINRT_WINPHONEQT);
- })));
- QString filePath;
- BaseQtVersion *qt = nullptr;
- for (BaseQtVersion *v : winrtVersions) {
- if (!qt || qt->qtVersion() < v->qtVersion()) {
- QFileInfo fi(v->binPath().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);
- Core::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 Core::Id internalId = Core::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->setDisplayName(name);
- deviceManager->addDevice(ProjectExplorer::IDevice::ConstPtr(device));
- qCDebug(winrtDeviceLog) << __FUNCTION__ << "Added device" << name << "(internal name:"
- << internalName << ")";
- }
- }
- QString message = tr("Found %n Windows Runtime devices.", 0, numFound);
- if (const int numNew = numFound - numSkipped) {
- message += QLatin1Char(' ');
- message += tr("%n of them are new.", 0, numNew);
- }
- MessageManager::write(message);
-}
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtdevicefactory.h b/src/plugins/winrt/winrtdevicefactory.h
deleted file mode 100644
index 32a42a65c4..0000000000
--- a/src/plugins/winrt/winrtdevicefactory.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 <projectexplorer/devicesupport/idevicefactory.h>
-#include <utils/qtcprocess.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtDeviceFactory : public ProjectExplorer::IDeviceFactory
-{
- Q_OBJECT
-public:
- explicit WinRtDeviceFactory(Core::Id deviceType);
-
- void autoDetect();
- void onPrerequisitesLoaded();
-
-private:
- void onProcessError();
- void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
-
- 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
index 6798338227..357a306177 100644
--- a/src/plugins/winrt/winrtpackagedeploymentstep.cpp
+++ b/src/plugins/winrt/winrtpackagedeploymentstep.cpp
@@ -70,7 +70,7 @@ bool WinRtPackageDeploymentStep::init()
QTC_ASSERT(rc, return false);
const BuildTargetInfo bti = rc->buildTargetInfo();
- Utils::FileName appTargetFilePath = bti.targetFilePath;
+ Utils::FilePath appTargetFilePath = bti.targetFilePath;
m_targetFilePath = appTargetFilePath.toString();
if (m_targetFilePath.isEmpty()) {
@@ -87,7 +87,7 @@ bool WinRtPackageDeploymentStep::init()
if (!m_targetDirPath.endsWith(QLatin1Char('/')))
m_targetDirPath += QLatin1Char('/');
- const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
+ const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target()->kit());
if (!qt)
return false;
@@ -107,7 +107,7 @@ bool WinRtPackageDeploymentStep::init()
QDir::toNativeSeparators(qt->binPath().toString())));
return false;
}
- params->setCommand(windeployqtPath);
+ params->setCommand(Utils::FilePath::fromString(windeployqtPath));
params->setArguments(args);
params->setEnvironment(buildConfiguration()->environment());
@@ -116,7 +116,7 @@ bool WinRtPackageDeploymentStep::init()
void WinRtPackageDeploymentStep::doRun()
{
- const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
+ const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target()->kit());
if (!qt)
return;
@@ -248,7 +248,7 @@ QString WinRtPackageDeploymentStep::defaultWinDeployQtArguments() const
void WinRtPackageDeploymentStep::raiseError(const QString &errorMessage)
{
- ProjectExplorer::Task task = Task(Task::Error, errorMessage, Utils::FileName(), -1,
+ ProjectExplorer::Task task = Task(Task::Error, errorMessage, Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
emit addTask(task, 1);
emit addOutput(errorMessage, BuildStep::OutputFormat::ErrorMessage);
@@ -256,7 +256,7 @@ void WinRtPackageDeploymentStep::raiseError(const QString &errorMessage)
void WinRtPackageDeploymentStep::raiseWarning(const QString &warningMessage)
{
- ProjectExplorer::Task task = Task(Task::Warning, warningMessage, Utils::FileName(), -1,
+ ProjectExplorer::Task task = Task(Task::Warning, warningMessage, Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
emit addTask(task, 1);
emit addOutput(warningMessage, BuildStep::OutputFormat::NormalMessage);
diff --git a/src/plugins/winrt/winrtphoneqtversion.cpp b/src/plugins/winrt/winrtphoneqtversion.cpp
index e3e2aa65e5..dc696d41f6 100644
--- a/src/plugins/winrt/winrtphoneqtversion.cpp
+++ b/src/plugins/winrt/winrtphoneqtversion.cpp
@@ -35,30 +35,34 @@
namespace WinRt {
namespace Internal {
-WinRtPhoneQtVersion::WinRtPhoneQtVersion(const Utils::FileName &path, bool isAutodetected,
- const QString &autodetectionSource)
- : WinRtQtVersion(path, isAutodetected, autodetectionSource)
-{
-}
-
QString WinRtPhoneQtVersion::description() const
{
return tr("Windows Phone");
}
-QtSupport::BaseQtVersion *WinRtPhoneQtVersion::clone() const
+QSet<Core::Id> WinRtPhoneQtVersion::targetDeviceTypes() const
{
- return new WinRtPhoneQtVersion(*this);
+ return {Constants::WINRT_DEVICE_TYPE_PHONE, Constants::WINRT_DEVICE_TYPE_EMULATOR};
}
-QString WinRtPhoneQtVersion::type() const
+QSet<Core::Id> WinRtPhoneQtVersion::availableFeatures() const
{
- return QLatin1String(Constants::WINRT_WINPHONEQT);
+ QSet<Core::Id> features = QtSupport::BaseQtVersion::availableFeatures();
+ features.insert(QtSupport::Constants::FEATURE_MOBILE);
+ features.remove(QtSupport::Constants::FEATURE_QT_CONSOLE);
+ features.remove(Core::Id::versionedId(QtSupport::Constants::FEATURE_QT_QUICK_CONTROLS_PREFIX, 1));
+ features.remove(QtSupport::Constants::FEATURE_QT_WEBKIT);
+ return features;
}
-QSet<Core::Id> WinRtPhoneQtVersion::targetDeviceTypes() const
+// Factory
+
+WinRtPhoneQtVersionFactory::WinRtPhoneQtVersionFactory()
{
- return {Constants::WINRT_DEVICE_TYPE_PHONE, Constants::WINRT_DEVICE_TYPE_EMULATOR};
+ setQtVersionCreator([] { return new WinRtPhoneQtVersion; });
+ setSupportedType(Constants::WINRT_WINPHONEQT);
+ setRestrictionChecker([](const SetupData &setup) { return setup.platforms.contains("winphone"); });
+ setPriority(10);
}
} // Internal
diff --git a/src/plugins/winrt/winrtphoneqtversion.h b/src/plugins/winrt/winrtphoneqtversion.h
index bbb8bd9764..a8f7062ae7 100644
--- a/src/plugins/winrt/winrtphoneqtversion.h
+++ b/src/plugins/winrt/winrtphoneqtversion.h
@@ -30,18 +30,22 @@
namespace WinRt {
namespace Internal {
-class WinRtPhoneQtVersion : public WinRtQtVersion
+class WinRtPhoneQtVersion : public QtSupport::BaseQtVersion
{
Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtQtVersion)
public:
WinRtPhoneQtVersion() = default;
- WinRtPhoneQtVersion(const Utils::FileName &path, bool isAutodetected,
- const QString &autodetectionSource);
- QString description() const;
- BaseQtVersion *clone() const;
- QString type() const;
- QSet<Core::Id> targetDeviceTypes() const;
+ QSet<Core::Id> availableFeatures() const override;
+
+ QString description() const override;
+ QSet<Core::Id> targetDeviceTypes() const override;
+};
+
+class WinRtPhoneQtVersionFactory : public QtSupport::QtVersionFactory
+{
+public:
+ WinRtPhoneQtVersionFactory();
};
} // Internal
diff --git a/src/plugins/winrt/winrtplugin.cpp b/src/plugins/winrt/winrtplugin.cpp
index e2156b6d82..18293783dd 100644
--- a/src/plugins/winrt/winrtplugin.cpp
+++ b/src/plugins/winrt/winrtplugin.cpp
@@ -26,9 +26,9 @@
#include "winrtplugin.h"
#include "winrtconstants.h"
#include "winrtdevice.h"
-#include "winrtdevicefactory.h"
#include "winrtdeployconfiguration.h"
-#include "winrtqtversionfactory.h"
+#include "winrtqtversion.h"
+#include "winrtphoneqtversion.h"
#include "winrtrunconfiguration.h"
#include "winrtruncontrol.h"
#include "winrtdebugsupport.h"
@@ -43,11 +43,12 @@ using namespace ProjectExplorer;
namespace WinRt {
namespace Internal {
-class WinRtPluginRunData
+class WinRtPluginPrivate
{
public:
WinRtRunConfigurationFactory runConfigFactory;
WinRtQtVersionFactory qtVersionFactory;
+ WinRtPhoneQtVersionFactory phoneQtVersionFactory;
WinRtAppDeployConfigurationFactory appDeployConfigFactory;
WinRtPhoneDeployConfigurationFactory phoneDeployConfigFactory;
WinRtEmulatorDeployConfigurationFactory emulatorDeployFactory;
@@ -57,14 +58,9 @@ public:
WinRtDeviceFactory emulatorDeviceFactory{Constants::WINRT_DEVICE_TYPE_EMULATOR};
};
-WinRtPlugin::WinRtPlugin()
-{
- setObjectName(QLatin1String("WinRtPlugin"));
-}
-
WinRtPlugin::~WinRtPlugin()
{
- delete m_runData;
+ delete d;
}
bool WinRtPlugin::initialize(const QStringList &arguments, QString *errorMessage)
@@ -72,17 +68,17 @@ bool WinRtPlugin::initialize(const QStringList &arguments, QString *errorMessage
Q_UNUSED(arguments)
Q_UNUSED(errorMessage)
- m_runData = new WinRtPluginRunData;
+ d = new WinRtPluginPrivate;
auto runConstraint = [](RunConfiguration *runConfig) {
- IDevice::ConstPtr device = DeviceKitInformation::device(runConfig->target()->kit());
+ IDevice::ConstPtr device = DeviceKitAspect::device(runConfig->target()->kit());
if (!device)
return false;
return qobject_cast<WinRtRunConfiguration *>(runConfig) != nullptr;
};
auto debugConstraint = [](RunConfiguration *runConfig) {
- IDevice::ConstPtr device = DeviceKitInformation::device(runConfig->target()->kit());
+ IDevice::ConstPtr device = DeviceKitAspect::device(runConfig->target()->kit());
if (!device)
return false;
if (device->type() != Internal::Constants::WINRT_DEVICE_TYPE_LOCAL)
diff --git a/src/plugins/winrt/winrtplugin.h b/src/plugins/winrt/winrtplugin.h
index 66eff10c98..211fc7d83c 100644
--- a/src/plugins/winrt/winrtplugin.h
+++ b/src/plugins/winrt/winrtplugin.h
@@ -30,22 +30,19 @@
namespace WinRt {
namespace Internal {
-class WinRtPluginRunData;
-
class WinRtPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "WinRt.json")
public:
- WinRtPlugin();
~WinRtPlugin() final;
private:
bool initialize(const QStringList &arguments, QString *errorMessage) final;
void extensionsInitialized() final {}
- WinRtPluginRunData *m_runData = nullptr;
+ class WinRtPluginPrivate *d = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/winrt/winrtqtversion.cpp b/src/plugins/winrt/winrtqtversion.cpp
index 082eafd1e9..33d6a32bdc 100644
--- a/src/plugins/winrt/winrtqtversion.cpp
+++ b/src/plugins/winrt/winrtqtversion.cpp
@@ -33,23 +33,6 @@
namespace WinRt {
namespace Internal {
-WinRtQtVersion::WinRtQtVersion(const Utils::FileName &path, bool isAutodetected,
- const QString &autodetectionSource)
- : BaseQtVersion(path, isAutodetected, autodetectionSource)
-{
- setUnexpandedDisplayName(defaultUnexpandedDisplayName(path, false));
-}
-
-QtSupport::BaseQtVersion *WinRtQtVersion::clone() const
-{
- return new WinRtQtVersion(*this);
-}
-
-QString WinRtQtVersion::type() const
-{
- return QLatin1String(Constants::WINRT_WINRTQT);
-}
-
QString WinRtQtVersion::description() const
{
return tr("Windows Runtime");
@@ -65,14 +48,20 @@ QSet<Core::Id> WinRtQtVersion::availableFeatures() const
return features;
}
-QList<ProjectExplorer::Abi> WinRtQtVersion::detectQtAbis() const
+QSet<Core::Id> WinRtQtVersion::targetDeviceTypes() const
{
- return qtAbisFromLibrary(qtCorePaths());
+ return {Constants::WINRT_DEVICE_TYPE_LOCAL, Constants::WINRT_DEVICE_TYPE_EMULATOR};
}
-QSet<Core::Id> WinRtQtVersion::targetDeviceTypes() const
+
+// Factory
+
+WinRtQtVersionFactory::WinRtQtVersionFactory()
{
- return {Constants::WINRT_DEVICE_TYPE_LOCAL, Constants::WINRT_DEVICE_TYPE_EMULATOR};
+ setQtVersionCreator([] { return new WinRtQtVersion; });
+ setSupportedType(Constants::WINRT_WINRTQT);
+ setRestrictionChecker([](const SetupData &setup) { return setup.platforms.contains("winrt"); });
+ setPriority(10);
}
} // Internal
diff --git a/src/plugins/winrt/winrtqtversion.h b/src/plugins/winrt/winrtqtversion.h
index f3a4fc9d3b..40030e4e6c 100644
--- a/src/plugins/winrt/winrtqtversion.h
+++ b/src/plugins/winrt/winrtqtversion.h
@@ -26,6 +26,7 @@
#pragma once
#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtversionfactory.h>
namespace WinRt {
namespace Internal {
@@ -35,16 +36,17 @@ class WinRtQtVersion : public QtSupport::BaseQtVersion
Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtQtVersion)
public:
WinRtQtVersion() = default;
- WinRtQtVersion(const Utils::FileName &path, bool isAutodetected,
- const QString &autodetectionSource);
- BaseQtVersion *clone() const;
- QString type() const;
- QString description() const;
- QSet<Core::Id> availableFeatures() const;
- QList<ProjectExplorer::Abi> detectQtAbis() const;
+ QString description() const override;
+ QSet<Core::Id> availableFeatures() const override;
- QSet<Core::Id> targetDeviceTypes() const;
+ QSet<Core::Id> targetDeviceTypes() const override;
+};
+
+class WinRtQtVersionFactory : public QtSupport::QtVersionFactory
+{
+public:
+ WinRtQtVersionFactory();
};
} // Internal
diff --git a/src/plugins/winrt/winrtqtversionfactory.cpp b/src/plugins/winrt/winrtqtversionfactory.cpp
deleted file mode 100644
index 2daf2e3612..0000000000
--- a/src/plugins/winrt/winrtqtversionfactory.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "winrtqtversionfactory.h"
-
-#include "winrtconstants.h"
-#include "winrtphoneqtversion.h"
-
-#include <proparser/profileevaluator.h>
-
-#include <QFileInfo>
-
-namespace WinRt {
-namespace Internal {
-
-WinRtQtVersionFactory::WinRtQtVersionFactory(QObject *parent)
- : QtSupport::QtVersionFactory(parent)
-{
-}
-
-WinRtQtVersionFactory::~WinRtQtVersionFactory()
-{
-}
-
-bool WinRtQtVersionFactory::canRestore(const QString &type)
-{
- return type == QLatin1String(Constants::WINRT_WINRTQT)
- || type == QLatin1String(Constants::WINRT_WINPHONEQT);
-}
-
-QtSupport::BaseQtVersion *WinRtQtVersionFactory::restore(const QString &type,
- const QVariantMap &data)
-{
- if (!canRestore(type))
- return nullptr;
- WinRtQtVersion *v = nullptr;
- if (type == QLatin1String(Constants::WINRT_WINPHONEQT))
- v = new WinRtPhoneQtVersion;
- else
- v = new WinRtQtVersion;
- v->fromMap(data);
- return v;
-}
-
-int WinRtQtVersionFactory::priority() const
-{
- return 10;
-}
-
-QtSupport::BaseQtVersion *WinRtQtVersionFactory::create(const Utils::FileName &qmakePath,
- ProFileEvaluator *evaluator, bool isAutoDetected, const QString &autoDetectionSource)
-{
- QFileInfo fi = qmakePath.toFileInfo();
- if (!fi.exists() || !fi.isExecutable() || !fi.isFile())
- return nullptr;
-
- bool isWinRt = false;
- bool isPhone = false;
- foreach (const QString &value, evaluator->values(QLatin1String("QMAKE_PLATFORM"))) {
- if (value == QStringLiteral("winrt")) {
- isWinRt = true;
- } else if (value == QStringLiteral("winphone")) {
- isWinRt = true;
- isPhone = true;
- break;
- }
- }
-
- if (!isWinRt)
- return nullptr;
-
- return isPhone ? new WinRtPhoneQtVersion(qmakePath, isAutoDetected, autoDetectionSource)
- : new WinRtQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
-}
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtqtversionfactory.h b/src/plugins/winrt/winrtqtversionfactory.h
deleted file mode 100644
index 4a88ce40fa..0000000000
--- a/src/plugins/winrt/winrtqtversionfactory.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/qtversionfactory.h>
-
-namespace WinRt {
-namespace Internal {
-
-class WinRtQtVersionFactory : public QtSupport::QtVersionFactory
-{
-public:
- explicit WinRtQtVersionFactory(QObject *parent = nullptr);
- ~WinRtQtVersionFactory();
-
- bool canRestore(const QString &type);
- QtSupport::BaseQtVersion *restore(const QString &type, const QVariantMap &data);
-
- int priority() const;
- QtSupport::BaseQtVersion *create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator,
- bool isAutoDetected = false, const QString &autoDetectionSource = QString());
-};
-
-} // Internal
-} // WinRt
diff --git a/src/plugins/winrt/winrtrunconfiguration.cpp b/src/plugins/winrt/winrtrunconfiguration.cpp
index 09986bd95b..663ffdea91 100644
--- a/src/plugins/winrt/winrtrunconfiguration.cpp
+++ b/src/plugins/winrt/winrtrunconfiguration.cpp
@@ -71,7 +71,7 @@ WinRtRunConfiguration::WinRtRunConfiguration(Target *target, Core::Id id)
addAspect<UninstallAfterStopAspect>();
const QtSupport::BaseQtVersion *qt
- = QtSupport::QtKitInformation::qtVersion(target->kit());
+ = QtSupport::QtKitAspect::qtVersion(target->kit());
if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 12, 0)) {
addAspect<LoopbackExemptClientAspect>();
addAspect<LoopbackExemptServerAspect>();
diff --git a/src/plugins/winrt/winrtruncontrol.cpp b/src/plugins/winrt/winrtruncontrol.cpp
index d8faa0ab48..c5a365edef 100644
--- a/src/plugins/winrt/winrtruncontrol.cpp
+++ b/src/plugins/winrt/winrtruncontrol.cpp
@@ -41,7 +41,7 @@
#include <QTimer>
-using ProjectExplorer::DeviceKitInformation;
+using ProjectExplorer::DeviceKitAspect;
using ProjectExplorer::IDevice;
using ProjectExplorer::RunControl;
using Core::Id;
diff --git a/src/plugins/winrt/winrtruncontrol.h b/src/plugins/winrt/winrtruncontrol.h
index fe8e5176d9..6105525d15 100644
--- a/src/plugins/winrt/winrtruncontrol.h
+++ b/src/plugins/winrt/winrtruncontrol.h
@@ -27,7 +27,7 @@
#include "winrtdevice.h"
-#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <utils/qtcprocess.h>
namespace WinRt {
diff --git a/src/plugins/winrt/winrtrunnerhelper.cpp b/src/plugins/winrt/winrtrunnerhelper.cpp
index 1ddc49c005..3ab8461f32 100644
--- a/src/plugins/winrt/winrtrunnerhelper.cpp
+++ b/src/plugins/winrt/winrtrunnerhelper.cpp
@@ -29,12 +29,14 @@
#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/runconfiguration.h>
+#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
+
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/qtcprocess.h>
@@ -50,12 +52,11 @@ WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QStr
: QObject(runWorker)
, m_worker(runWorker)
{
- auto runConfiguration = runWorker->runControl()->runConfiguration();
+ auto runControl = runWorker->runControl();
- ProjectExplorer::Target *target = runConfiguration->target();
m_device = runWorker->device().dynamicCast<const WinRtDevice>();
- const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit());
+ const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(runControl->kit());
if (!qt) {
*errorMessage = tr("The current kit has no Qt version.");
return;
@@ -68,7 +69,7 @@ WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QStr
return;
}
- const BuildTargetInfo bti = target->applicationTargets().buildTargetInfo(runConfiguration->buildKey());
+ const BuildTargetInfo bti = runControl->buildTargetInfo();
m_executableFilePath = bti.targetFilePath.toString();
if (m_executableFilePath.isEmpty()) {
@@ -84,13 +85,13 @@ WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QStr
bool loopbackExemptClient = false;
bool loopbackExemptServer = false;
- if (auto aspect = runConfiguration->aspect<ArgumentsAspect>())
- m_arguments = aspect->arguments(runConfiguration->macroExpander());
- if (auto aspect = runConfiguration->aspect<UninstallAfterStopAspect>())
+ 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 = runConfiguration->aspect<LoopbackExemptClientAspect>())
+ if (auto aspect = runControl->aspect<LoopbackExemptClientAspect>())
loopbackExemptClient = aspect->value();
- if (auto aspect = runConfiguration->aspect<LoopbackExemptServerAspect>())
+ if (auto aspect = runControl->aspect<LoopbackExemptServerAspect>())
loopbackExemptServer = aspect->value();
if (loopbackExemptClient && loopbackExemptServer)
m_loopbackArguments = "--loopbackexempt clientserver";
@@ -99,7 +100,7 @@ WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QStr
else if (loopbackExemptServer)
m_loopbackArguments = "--loopbackexempt server";
- if (ProjectExplorer::BuildConfiguration *bc = target->activeBuildConfiguration())
+ if (BuildConfiguration *bc = runControl->target()->activeBuildConfiguration())
m_environment = bc->environment();
}
@@ -170,10 +171,10 @@ void WinRtRunnerHelper::onProcessError(QProcess::ProcessError processError)
void WinRtRunnerHelper::startWinRtRunner(const RunConf &conf)
{
using namespace Utils;
- QString runnerArgs;
+ CommandLine cmdLine(FilePath::fromString(m_runnerFilePath), {});
if (m_device) {
- QtcProcess::addArg(&runnerArgs, QStringLiteral("--device"));
- QtcProcess::addArg(&runnerArgs, QString::number(m_device->deviceId()));
+ cmdLine.addArg("--device");
+ cmdLine.addArg(QString::number(m_device->deviceId()));
}
QtcProcess *process = nullptr;
@@ -181,42 +182,41 @@ void WinRtRunnerHelper::startWinRtRunner(const RunConf &conf)
switch (conf) {
case Debug:
- QtcProcess::addArg(&runnerArgs, QStringLiteral("--debug"));
- QtcProcess::addArg(&runnerArgs, m_debuggerExecutable);
+ cmdLine.addArg("--debug");
+ cmdLine.addArg(m_debuggerExecutable);
if (!m_debuggerArguments.isEmpty()) {
- QtcProcess::addArg(&runnerArgs, QStringLiteral("--debugger-arguments"));
- QtcProcess::addArg(&runnerArgs, m_debuggerArguments);
+ cmdLine.addArg("--debugger-arguments");
+ cmdLine.addArg(m_debuggerArguments);
}
Q_FALLTHROUGH();
case Start:
- QtcProcess::addArgs(&runnerArgs, QStringLiteral("--start --stop --wait 0"));
+ 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:
- QtcProcess::addArgs(&runnerArgs, QStringLiteral("--stop"));
+ cmdLine.addArgs("--stop");
process = new QtcProcess(this);
break;
}
if (m_device->type() == Constants::WINRT_DEVICE_TYPE_LOCAL)
- QtcProcess::addArgs(&runnerArgs, QStringLiteral("--profile appx"));
+ cmdLine.addArgs("--profile appx");
else if (m_device->type() == Constants::WINRT_DEVICE_TYPE_PHONE ||
m_device->type() == Constants::WINRT_DEVICE_TYPE_EMULATOR)
- QtcProcess::addArgs(&runnerArgs, QStringLiteral("--profile appxphone"));
+ cmdLine.addArgs("--profile appxphone");
- QtcProcess::addArgs(&runnerArgs, m_loopbackArguments);
- QtcProcess::addArg(&runnerArgs, m_executableFilePath);
- QtcProcess::addArgs(&runnerArgs, m_arguments);
+ cmdLine.addArgs(m_loopbackArguments);
+ cmdLine.addArg(m_executableFilePath);
+ cmdLine.addArgs(m_arguments);
- appendMessage(QStringLiteral("winrtrunner ") + runnerArgs + QLatin1Char('\n'), NormalMessageFormat);
+ appendMessage("winrtrunner " + cmdLine.arguments() + '\n', NormalMessageFormat);
if (connectProcess) {
connect(process, &QProcess::started, this, &WinRtRunnerHelper::started);
- connect(process,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &WinRtRunnerHelper::onProcessFinished);
connect(process, &QProcess::errorOccurred, this, &WinRtRunnerHelper::onProcessError);
connect(process, &QProcess::readyReadStandardOutput, this, &WinRtRunnerHelper::onProcessReadyReadStdOut);
@@ -224,7 +224,7 @@ void WinRtRunnerHelper::startWinRtRunner(const RunConf &conf)
}
process->setUseCtrlCStub(true);
- process->setCommand(m_runnerFilePath, runnerArgs);
+ process->setCommand(cmdLine);
process->setEnvironment(m_environment);
process->setWorkingDirectory(QFileInfo(m_executableFilePath).absolutePath());
process->start();
diff --git a/src/share/3rdparty/CMakeLists.txt b/src/share/3rdparty/CMakeLists.txt
new file mode 100644
index 0000000000..ede2157426
--- /dev/null
+++ b/src/share/3rdparty/CMakeLists.txt
@@ -0,0 +1,13 @@
+install(
+ DIRECTORY fonts
+ DESTINATION "${IDE_DATA_PATH}"
+)
+
+add_custom_target(copy_fonts_to_builddir ALL VERBATIM)
+add_custom_command(TARGET copy_fonts_to_builddir POST_BUILD
+ COMMAND "${CMAKE_COMMAND}" -E copy_directory fonts
+ "${PROJECT_BINARY_DIR}/${IDE_DATA_PATH}/fonts"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ COMMENT Copy files into build directory
+ VERBATIM
+)
diff --git a/src/share/3rdparty/studiofonts/StudioFonts/StudioFonts.qml b/src/share/3rdparty/studiofonts/StudioFonts/StudioFonts.qml
new file mode 100644
index 0000000000..677dd7e0d1
--- /dev/null
+++ b/src/share/3rdparty/studiofonts/StudioFonts/StudioFonts.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** 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 Singleton
+
+import QtQuick 2.6
+
+QtObject {
+ property FontLoader fontLoader_regular: FontLoader {
+ id: fontLoader_regular
+ source: "../TitilliumWeb-Regular.ttf"
+ }
+
+ readonly property alias titilliumWeb_regular: fontLoader_regular.name
+
+ property FontLoader fontLoader_light: FontLoader {
+ id: fontLoader_light
+ source: "../TitilliumWeb-Light.ttf"
+ }
+
+ readonly property alias titilliumWeb_light: fontLoader_light.name
+}
diff --git a/src/share/3rdparty/studiofonts/StudioFonts/qmldir b/src/share/3rdparty/studiofonts/StudioFonts/qmldir
new file mode 100644
index 0000000000..7d39f37fcb
--- /dev/null
+++ b/src/share/3rdparty/studiofonts/StudioFonts/qmldir
@@ -0,0 +1 @@
+singleton StudioFonts 1.0 StudioFonts.qml
diff --git a/src/share/3rdparty/studiofonts/TitilliumWeb-Light.ttf b/src/share/3rdparty/studiofonts/TitilliumWeb-Light.ttf
new file mode 100644
index 0000000000..2685cbe55d
--- /dev/null
+++ b/src/share/3rdparty/studiofonts/TitilliumWeb-Light.ttf
Binary files differ
diff --git a/src/share/3rdparty/studiofonts/TitilliumWeb-Regular.ttf b/src/share/3rdparty/studiofonts/TitilliumWeb-Regular.ttf
new file mode 100644
index 0000000000..4fd6b7fba0
--- /dev/null
+++ b/src/share/3rdparty/studiofonts/TitilliumWeb-Regular.ttf
Binary files differ
diff --git a/src/share/3rdparty/studiofonts/TitilliumWeb.txt b/src/share/3rdparty/studiofonts/TitilliumWeb.txt
new file mode 100644
index 0000000000..cc2b593f34
--- /dev/null
+++ b/src/share/3rdparty/studiofonts/TitilliumWeb.txt
@@ -0,0 +1,8 @@
+Titillium is a free open source font and it is born inside the Accademia
+di Belle Arti di Urbino as a didactic project Course Type design of the
+Master of Visual Design Campi Visivi. It has 11 different weights and is
+well suited for headlines and body type.
+
+Titillium is used as the brand font for Qt.
+
+https://brand.qt.io/fonts/ \ No newline at end of file
diff --git a/src/share/3rdparty/studiofonts/studiofonts.qrc b/src/share/3rdparty/studiofonts/studiofonts.qrc
new file mode 100644
index 0000000000..0dfcd93232
--- /dev/null
+++ b/src/share/3rdparty/studiofonts/studiofonts.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="studiofonts">
+ <file>TitilliumWeb-Light.ttf</file>
+ <file>TitilliumWeb-Regular.ttf</file>
+ <file>StudioFonts/qmldir</file>
+ <file>StudioFonts/StudioFonts.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/share/CMakeLists.txt b/src/share/CMakeLists.txt
new file mode 100644
index 0000000000..57850ff783
--- /dev/null
+++ b/src/share/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(3rdparty)
+add_subdirectory(qtcreator)
diff --git a/src/share/qtcreator/CMakeLists.txt b/src/share/qtcreator/CMakeLists.txt
new file mode 100644
index 0000000000..054cb7404e
--- /dev/null
+++ b/src/share/qtcreator/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(externaltools)
diff --git a/src/share/qtcreator/externaltools/CMakeLists.txt b/src/share/qtcreator/externaltools/CMakeLists.txt
new file mode 100644
index 0000000000..bf9f216787
--- /dev/null
+++ b/src/share/qtcreator/externaltools/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(EXT_TOOLS_DIR "${IDE_DATA_PATH}/externaltools")
+
+install(FILES lrelease.xml lupdate.xml qmlscene.xml qmlviewer.xml
+ DESTINATION "${EXT_TOOLS_DIR}"
+)
+
+if (WIN32)
+ install(FILES notepad_win.xml DESTINATION "${EXT_TOOLS_DIR}")
+elseif (APPLE)
+ install(FILES vi_mac.xml DESTINATION "${EXT_TOOLS_DIR}")
+else()
+ install(FILES vi.xml DESTINATION "${EXT_TOOLS_DIR}")
+endif()
diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt
new file mode 100644
index 0000000000..eeaad66af2
--- /dev/null
+++ b/src/shared/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_subdirectory(designerintegrationv2)
+add_subdirectory(proparser)
+add_subdirectory(qtsingleapplication)
+add_subdirectory(qtlockedfile)
+add_subdirectory(help)
+add_subdirectory(registryaccess)
diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri
index 8c75b6cc82..980ad4bff6 100644
--- a/src/shared/clang/clang_installation.pri
+++ b/src/shared/clang/clang_installation.pri
@@ -141,15 +141,15 @@ win32: BIN_EXTENSION = .exe
isEmpty(LLVM_INSTALL_DIR) {
unix {
- llvm_config = $$system(which llvm-config-7)
+ llvm_config = $$system(which llvm-config-8)
}
isEmpty(llvm_config) {
llvm_config = llvm-config
}
} else {
- exists($$LLVM_INSTALL_DIR/bin/llvm-config-7$$BIN_EXTENSION) {
- llvm_config = $$system_quote($$LLVM_INSTALL_DIR/bin/llvm-config-7)
+ exists($$LLVM_INSTALL_DIR/bin/llvm-config-8$$BIN_EXTENSION) {
+ llvm_config = $$system_quote($$LLVM_INSTALL_DIR/bin/llvm-config-8)
} else {
llvm_config = $$system_quote($$LLVM_INSTALL_DIR/bin/llvm-config)
requires(exists($$llvm_config$$BIN_EXTENSION))
@@ -163,10 +163,10 @@ isEmpty(LLVM_VERSION) {
$$llvmWarningOrError(\
"Cannot determine clang version. Set LLVM_INSTALL_DIR to build the Clang Code Model",\
"LLVM_INSTALL_DIR does not contain a valid llvm-config, candidate: $$llvm_config")
-} else:!versionIsAtLeast($$LLVM_VERSION, 6, 0, 0): {
+} else:!versionIsAtLeast($$LLVM_VERSION, 8, 0, 0): {
# CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
$$llvmWarningOrError(\
- "LLVM/Clang version >= 6.0.0 required, version provided: $$LLVM_VERSION")
+ "LLVM/Clang version >= 8.0.0 required, version provided: $$LLVM_VERSION")
LLVM_VERSION =
} else {
# CLANG-UPGRADE-CHECK: Remove suppression if this warning is resolved.
@@ -176,7 +176,8 @@ isEmpty(LLVM_VERSION) {
GCC_MAJOR_VERSION = $$section(GCC_VERSION, ., 0, 0)
# GCC8 warns about memset/memcpy for types with copy ctor. Clang has some of these.
greaterThan(GCC_MAJOR_VERSION, 7):QMAKE_CXXFLAGS += -Wno-class-memaccess
- QMAKE_CXXFLAGS += -Wno-unused-parameter
+ # clang/Format/Format.h has intentional multiline comments
+ QMAKE_CXXFLAGS += -Wno-unused-parameter -Wno-comment
}
LLVM_LIBDIR = $$quote($$system($$llvm_config --libdir, lines))
@@ -196,19 +197,11 @@ isEmpty(LLVM_VERSION) {
CLANGFORMAT_MAIN_HEADER = $$LLVM_INCLUDEPATH/clang/Format/Format.h
exists($$CLANGFORMAT_MAIN_HEADER) {
- versionIsAtLeast($$LLVM_VERSION, 7, 0, 0): {
- CLANGFORMAT_LIBS=-lclangFormat -lclangToolingInclusions -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic
- ALL_CLANG_LIBS=-lclangFormat -lclangToolingInclusions -lclangTooling -lclangToolingCore \
- -lclangRewrite -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \
- -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \
- -lclangASTMatchers -lclangAST -lclangLex -lclangBasic
- } else:versionIsAtLeast($$LLVM_VERSION, 6, 0, 0): {
- CLANGFORMAT_LIBS=-lclangFormat -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic
- ALL_CLANG_LIBS=-lclangFormat -lclangTooling -lclangToolingCore \
- -lclangRewrite -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \
- -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \
- -lclangASTMatchers -lclangAST -lclangLex -lclangBasic
- }
+ CLANGFORMAT_LIBS=-lclangFormat -lclangToolingInclusions -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic
+ ALL_CLANG_LIBS=-lclangFormat -lclangToolingInclusions -lclangTooling -lclangToolingCore \
+ -lclangRewrite -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \
+ -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \
+ -lclangASTMatchers -lclangAST -lclangLex -lclangBasic
win32:CLANGFORMAT_LIBS += -lversion
}
win32:ALL_CLANG_LIBS += -lversion
@@ -232,12 +225,10 @@ isEmpty(LLVM_VERSION) {
!contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBCLANG_LIBS = -L$${LLVM_LIBDIR}
LIBCLANG_LIBS += $${CLANG_LIB}
- QTC_ENABLE_CLANG_LIBTOOLING=$$(QTC_ENABLE_CLANG_LIBTOOLING)
- !isEmpty(QTC_ENABLE_CLANG_LIBTOOLING) {
+ QTC_DISABLE_CLANG_REFACTORING=$$(QTC_DISABLE_CLANG_REFACTORING)
+ isEmpty(QTC_DISABLE_CLANG_REFACTORING) {
!contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBTOOLING_LIBS = -L$${LLVM_LIBDIR}
LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS
- } else {
- warning("Clang LibTooling is disabled. Set QTC_ENABLE_CLANG_LIBTOOLING to enable it.")
}
!isEmpty(CLANGFORMAT_LIBS) {
diff --git a/src/shared/designerintegrationv2/CMakeLists.txt b/src/shared/designerintegrationv2/CMakeLists.txt
new file mode 100644
index 0000000000..a3bdb4c50a
--- /dev/null
+++ b/src/shared/designerintegrationv2/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_library(designerintegrationv2 STATIC
+ formresizer.cpp formresizer.h
+ sizehandlerect.cpp sizehandlerect.h
+ widgethostconstants.h
+ widgethost.cpp widgethost.h
+)
+target_link_libraries(designerintegrationv2 PUBLIC Qt5::Designer)
+target_include_directories(designerintegrationv2 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/src/shared/help/CMakeLists.txt b/src/shared/help/CMakeLists.txt
new file mode 100644
index 0000000000..1058d6d3ad
--- /dev/null
+++ b/src/shared/help/CMakeLists.txt
@@ -0,0 +1,24 @@
+if (NOT TARGET Qt5::Help)
+ # Do not built without Qt5::Help being available
+ return()
+endif()
+
+set(PLUGIN_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/plugins")
+
+add_qtc_library(shared_help STATIC
+ DEPENDS Utils PUBLIC Qt5::Help Qt5::PrintSupport Qt5::Widgets
+ PUBLIC_INCLUDES
+ "${PLUGIN_SOURCE_DIR}/help"
+ "${PLUGIN_SOURCE_DIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}/shared_help_autogen/include"
+ "${CMAKE_CURRENT_BINARY_DIR}/"
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES
+ bookmarkdialog.ui
+ bookmarkmanager.cpp bookmarkmanager.h
+ contentwindow.cpp contentwindow.h
+ filternamedialog.cpp filternamedialog.h filternamedialog.ui
+ helpicons.h
+ indexwindow.cpp indexwindow.h
+ topicchooser.cpp topicchooser.h topicchooser.ui
+)
diff --git a/src/shared/help/bookmarkmanager.cpp b/src/shared/help/bookmarkmanager.cpp
index 979ca7c5bf..dc19b8e92a 100644
--- a/src/shared/help/bookmarkmanager.cpp
+++ b/src/shared/help/bookmarkmanager.cpp
@@ -96,7 +96,7 @@ BookmarkDialog::BookmarkDialog(BookmarkManager *manager, const QString &title,
this, &BookmarkDialog::itemChanged);
connect(ui.bookmarkFolders,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
+ QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
this, &BookmarkDialog::selectBookmarkFolder);
connect(ui.treeView, &TreeView::customContextMenuRequested,
diff --git a/src/shared/proparser/CMakeLists.txt b/src/shared/proparser/CMakeLists.txt
new file mode 100644
index 0000000000..d47141178a
--- /dev/null
+++ b/src/shared/proparser/CMakeLists.txt
@@ -0,0 +1,29 @@
+add_qtc_library(ProParser SHARED
+ DEPENDS Qt5::Core Utils
+ PUBLIC_DEFINES
+ QMAKE_BUILTIN_PRFS QMAKE_OVERRIDE_PRFS
+ PROPARSER_THREAD_SAFE PROEVALUATOR_CUMULATIVE PROEVALUATOR_DUAL_VFS
+ PROEVALUATOR_SETENV PROEVALUATOR_THREAD_SAFE
+ SOURCES
+ ioutils.cpp ioutils.h
+ profileevaluator.cpp profileevaluator.h
+ proitems.cpp proitems.h
+ proparser.qrc
+ prowriter.cpp prowriter.h
+ qmake_global.h
+ qmakebuiltins.cpp
+ qmakeevaluator.cpp qmakeevaluator.h qmakeevaluator_p.h
+ qmakeglobals.cpp qmakeglobals.h
+ qmakeparser.cpp qmakeparser.h
+ qmakevfs.cpp qmakevfs.h
+ registry.cpp registry_p.h
+ PROPERTIES
+ CXX_VISIBILITY_PRESET default
+ VISIBILITY_INLINES_HIDDEN OFF
+ WINDOWS_EXPORT_ALL_SYMBOLS ON
+)
+
+extend_qtc_target(ProParser
+ CONDITION WIN32
+ DEFINES _UNICODE UNICODE
+)
diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index 22f3ee5b4e..3b816f01cd 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -124,6 +124,11 @@ QStringList ProFileEvaluator::sourcesToFiles(const QVector<ProFileEvaluator::Sou
return result;
}
+QStringList ProFileEvaluator::featureRoots() const
+{
+ return d->m_featureRoots->paths;
+}
+
// VFS note: all search paths are assumed to be real.
QStringList ProFileEvaluator::absolutePathValues(
const QString &variable, const QString &baseDirectory) const
diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h
index a67d4b5a74..0251f8458c 100644
--- a/src/shared/proparser/profileevaluator.h
+++ b/src/shared/proparser/profileevaluator.h
@@ -89,6 +89,7 @@ public:
QHash<ProString, bool> *handled, QSet<QString> &directoriesWithWildcards) const;
QString propertyValue(const QString &val) const;
static QStringList sourcesToFiles(const QVector<SourceFile> &sources);
+ QStringList featureRoots() const;
private:
QMakeEvaluator *d;
diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp
index db4f386cae..5d7f6ddb6f 100644
--- a/src/shared/proparser/proitems.cpp
+++ b/src/shared/proparser/proitems.cpp
@@ -50,11 +50,6 @@ ProString::ProString() :
{
}
-ProString::ProString(const ProString &other) :
- m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(other.m_hash)
-{
-}
-
ProString::ProString(const ProString &other, OmitPreHashing) :
m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(0x80000000)
{
diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h
index a7566be220..3058b25c48 100644
--- a/src/shared/proparser/proitems.h
+++ b/src/shared/proparser/proitems.h
@@ -62,7 +62,6 @@ class ProFile;
class ProString {
public:
ProString();
- ProString(const ProString &other);
PROITEM_EXPLICIT ProString(const QString &str);
PROITEM_EXPLICIT ProString(const QStringRef &str);
PROITEM_EXPLICIT ProString(const char *str);
diff --git a/src/shared/proparser/prowriter.cpp b/src/shared/proparser/prowriter.cpp
index 668820ba43..282080013f 100644
--- a/src/shared/proparser/prowriter.cpp
+++ b/src/shared/proparser/prowriter.cpp
@@ -30,8 +30,8 @@
#include <utils/algorithm.h>
#include <QDir>
-#include <QRegExp>
#include <QPair>
+#include <QRegularExpression>
using namespace QmakeProjectManager::Internal;
@@ -178,7 +178,7 @@ QString ProWriter::compileScope(const QString &scope)
if (scope.isEmpty())
return QString();
QMakeParser parser(nullptr, nullptr, nullptr);
- ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), 0, QLatin1String("no-file"), 1);
+ ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), 0, "no-file", 1);
if (!includeFile)
return QString();
const QString result = includeFile->items();
@@ -321,13 +321,13 @@ void ProWriter::putVarValues(ProFile *profile, QStringList *lines, const QString
lines->erase(lines->begin() + lineNo + 1, lines->begin() + contInfo.lineNo);
// remove rest of the line
QString &line = (*lines)[lineNo];
- int eqs = line.indexOf(QLatin1Char('='));
+ int eqs = line.indexOf('=');
if (eqs >= 0) // If this is not true, we mess up the file a bit.
line.truncate(eqs + 1);
// put new values
for (const QString &v : values) {
- line += ((flags & MultiLine) ? QLatin1String(" \\\n") + effectiveContIndent(contInfo)
- : QString::fromLatin1(" ")) + v;
+ line += ((flags & MultiLine) ? QString(" \\\n") + effectiveContIndent(contInfo)
+ : QString(" ")) + v;
}
} else {
const ContinuationInfo contInfo = skipContLines(lines, lineNo, false);
@@ -354,13 +354,14 @@ void ProWriter::putVarValues(ProFile *profile, QStringList *lines, const QString
ContinuationInfo contInfo;
if (!scope.isEmpty()) {
if (scopeStart < 0) {
- added = QLatin1Char('\n') + scope + QLatin1String(" {");
+ added = '\n' + scope + " {";
} else {
- QRegExp rx(QLatin1String("(\\s*") + scope + QLatin1String("\\s*:\\s*)[^\\s{].*"));
- if (rx.exactMatch(lines->at(scopeStart))) {
- (*lines)[scopeStart].replace(0, rx.cap(1).length(),
- QString(scope + QLatin1String(" {\n")
- + continuationIndent));
+ // TODO use anchoredPattern() once Qt 5.12 is mandatory
+ const QRegularExpression rx("\\A(\\s*" + scope + "\\s*:\\s*)[^\\s{].*\\z");
+ const QRegularExpressionMatch match(rx.match(lines->at(scopeStart)));
+ if (match.hasMatch()) {
+ (*lines)[scopeStart].replace(0, match.captured(1).length(),
+ scope + " {\n" + continuationIndent);
contInfo = skipContLines(lines, scopeStart, false);
lNo = contInfo.lineNo;
scopeStart = -1;
@@ -374,26 +375,26 @@ void ProWriter::putVarValues(ProFile *profile, QStringList *lines, const QString
const QString &line = (*lines).at(lNo);
for (int i = 0; i < line.size(); i++)
// This is pretty sick, but qmake does pretty much the same ...
- if (line.at(i) == QLatin1Char('{')) {
+ if (line.at(i) == '{') {
++braces;
- } else if (line.at(i) == QLatin1Char('}')) {
+ } else if (line.at(i) == '}') {
if (!--braces)
break;
- } else if (line.at(i) == QLatin1Char('#')) {
+ } else if (line.at(i) == '#') {
break;
}
} while (braces && ++lNo < lines->size());
}
for (; lNo > scopeStart + 1 && lines->at(lNo - 1).isEmpty(); lNo--) ;
if (lNo != scopeStart + 1)
- added += QLatin1Char('\n');
- added += indent + var + QLatin1String((flags & AppendOperator) ? " +=" : " =");
+ added += '\n';
+ added += indent + var + ((flags & AppendOperator) ? " +=" : " =");
for (const QString &v : values) {
- added += ((flags & MultiLine) ? QLatin1String(" \\\n") + effectiveContIndent(contInfo)
- : QString::fromLatin1(" ")) + v;
+ added += ((flags & MultiLine) ? QString(" \\\n") + effectiveContIndent(contInfo)
+ : QString(" ")) + v;
}
if (!scope.isEmpty() && scopeStart < 0)
- added += QLatin1String("\n}");
+ added += "\n}";
lines->insert(lNo, added);
}
}
@@ -404,8 +405,8 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines, const QStringList
QStringList valuesToWrite;
QString prefixPwd;
QDir baseDir = QFileInfo(profile->fileName()).absoluteDir();
- if (profile->fileName().endsWith(QLatin1String(".pri")))
- prefixPwd = QLatin1String("$$PWD/");
+ if (profile->fileName().endsWith(".pri"))
+ prefixPwd = "$$PWD/";
for (const QString &v : values)
valuesToWrite << (prefixPwd + baseDir.relativeFilePath(v));
@@ -464,7 +465,7 @@ QList<int> ProWriter::removeVarValues(ProFile *profile, QStringList *lines,
int lineLen = line.length();
bool killed = false;
bool saved = false;
- int idx = line.indexOf(QLatin1Char('#'));
+ int idx = line.indexOf('#');
if (idx >= 0)
lineLen = idx;
QChar *chars = line.data();
@@ -475,30 +476,30 @@ QList<int> ProWriter::removeVarValues(ProFile *profile, QStringList *lines,
goto nextVar;
}
QChar c = chars[lineLen - 1];
- if (c != QLatin1Char(' ') && c != QLatin1Char('\t'))
+ if (c != ' ' && c != '\t')
break;
lineLen--;
}
{
int contCol = -1;
- if (chars[lineLen - 1] == QLatin1Char('\\'))
+ if (chars[lineLen - 1] == '\\')
contCol = --lineLen;
int colNo = 0;
if (first) {
- colNo = line.indexOf(QLatin1Char('=')) + 1;
+ colNo = line.indexOf('=') + 1;
first = false;
saved = true;
}
while (colNo < lineLen) {
QChar c = chars[colNo];
- if (c == QLatin1Char(' ') || c == QLatin1Char('\t')) {
+ if (c == ' ' || c == '\t') {
colNo++;
continue;
}
int varCol = colNo;
while (colNo < lineLen) {
QChar c = chars[colNo];
- if (c == QLatin1Char(' ') || c == QLatin1Char('\t'))
+ if (c == (' ') || c == ('\t'))
break;
colNo++;
}
@@ -517,7 +518,7 @@ QList<int> ProWriter::removeVarValues(ProFile *profile, QStringList *lines,
contCol -= len;
idx -= len;
if (idx >= 0)
- line.insert(idx, QLatin1String("# ") + fn + QLatin1Char(' '));
+ line.insert(idx, "# " + fn + ' ');
chars = line.data();
killed = true;
} else {
@@ -535,8 +536,7 @@ QList<int> ProWriter::removeVarValues(ProFile *profile, QStringList *lines,
QString &bline = (*lines)[pos.first];
bline.remove(pos.second, 1);
if (pos.second == bline.length())
- while (bline.endsWith(QLatin1Char(' '))
- || bline.endsWith(QLatin1Char('\t')))
+ while (bline.endsWith(' ') || bline.endsWith('\t'))
bline.chop(1);
}
contPos.clear();
@@ -572,7 +572,7 @@ QStringList ProWriter::removeFiles(ProFile *profile, QStringList *lines,
Utils::transform(removeVarValues(profile, lines, valuesToFind, vars),
[values](int i) { return values.at(i); });
- if (!profile->fileName().endsWith(QLatin1String(".pri")))
+ if (!profile->fileName().endsWith(".pri"))
return notYetChanged;
// If we didn't find them with a relative path to the .pro file
@@ -580,7 +580,7 @@ QStringList ProWriter::removeFiles(ProFile *profile, QStringList *lines,
valuesToFind.clear();
const QDir baseDir = QFileInfo(profile->fileName()).absoluteDir();
- const QString prefixPwd = QLatin1String("$$PWD/");
+ const QString prefixPwd = "$$PWD/";
for (const QString &absoluteFilePath : notYetChanged)
valuesToFind << (prefixPwd + baseDir.relativeFilePath(absoluteFilePath));
diff --git a/src/shared/proparser/prowriter.h b/src/shared/proparser/prowriter.h
index 7d3dca765d..31467c0e66 100644
--- a/src/shared/proparser/prowriter.h
+++ b/src/shared/proparser/prowriter.h
@@ -66,7 +66,7 @@ private:
static QString compileScope(const QString &scope);
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(ProWriter::PutFlags)
-
} // namespace Internal
} // namespace QmakeProjectManager
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmakeProjectManager::Internal::ProWriter::PutFlags)
diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp
index ea7e308cc5..916d4ab891 100644
--- a/src/shared/proparser/qmakebuiltins.cpp
+++ b/src/shared/proparser/qmakebuiltins.cpp
@@ -877,8 +877,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
ret += values(map(args.at(0)));
break;
case E_LIST: {
- QString tmp;
- tmp.sprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++);
+ const QString tmp = QString::asprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++);
ret = ProStringList(ProString(tmp));
ProStringList lst;
for (const ProString &arg : args)
diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp
index 01233fc46f..6e75847eb9 100644
--- a/src/shared/proparser/qmakeevaluator.cpp
+++ b/src/shared/proparser/qmakeevaluator.cpp
@@ -1702,7 +1702,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFunction(
if (m_valuemapStack.count() >= 100) {
evalError(fL1S("Ran into infinite recursion (depth > 100)."));
- vr = ReturnFalse;
+ vr = ReturnError;
} else {
m_valuemapStack.push(ProValueMap());
m_locationStack.push(m_current);
diff --git a/src/shared/proparser/qmakeparser.h b/src/shared/proparser/qmakeparser.h
index a0c1ca17f1..ab765c5d9b 100644
--- a/src/shared/proparser/qmakeparser.h
+++ b/src/shared/proparser/qmakeparser.h
@@ -107,7 +107,6 @@ private:
struct BlockScope {
BlockScope() : start(0), braceLevel(0), special(false), inBranch(false), nest(NestNone) {}
- BlockScope(const BlockScope &other) { *this = other; }
ushort *start; // Where this block started; store length here
int braceLevel; // Nesting of braces in scope
bool special; // Single-line conditionals inside loops, etc. cannot have else branches
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject 8cd4b8cec7ffda0b19b01129e96eda8d2fb75ec
+Subproject e0ac40e53c5fc16b675ea2ac63fb5f3a6cab3de
diff --git a/src/shared/qtlockedfile/CMakeLists.txt b/src/shared/qtlockedfile/CMakeLists.txt
new file mode 100644
index 0000000000..5386c7c962
--- /dev/null
+++ b/src/shared/qtlockedfile/CMakeLists.txt
@@ -0,0 +1,13 @@
+if (WIN32)
+ set(OS_SOURCES qtlockedfile_win.cpp)
+else()
+ set(OS_SOURCES qtlockedfile_unix.cpp)
+endif()
+
+add_library(shared_qtlockedfile STATIC ${OS_SOURCES} qtlockedfile.cpp qtlockedfile.h)
+target_link_libraries(shared_qtlockedfile Qt5::Core)
+target_include_directories(shared_qtlockedfile PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
+if (WIN32)
+ target_compile_definitions(shared_qtlockedfile PRIVATE
+ "QT_QTLOCKEDFILE_EXPORT=__declspec(dllexport)" _UNICODE UNICODE)
+endif()
diff --git a/src/shared/qtsingleapplication/CMakeLists.txt b/src/shared/qtsingleapplication/CMakeLists.txt
new file mode 100644
index 0000000000..b31f8f93ed
--- /dev/null
+++ b/src/shared/qtsingleapplication/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_library(shared_qtsingleapplication STATIC
+ qtsingleapplication.cpp qtsingleapplication.h
+ qtlocalpeer.cpp qtlocalpeer.h
+)
+target_link_libraries(shared_qtsingleapplication shared_qtlockedfile Qt5::Core Qt5::Network Qt5::Widgets)
+target_include_directories(shared_qtsingleapplication PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
+if (WIN32)
+ target_compile_definitions(shared_qtsingleapplication PRIVATE "QT_QTSINGLEAPPLICATION_EXPORT=__declspec(dllexport)")
+endif()
diff --git a/src/shared/registryaccess/CMakeLists.txt b/src/shared/registryaccess/CMakeLists.txt
new file mode 100644
index 0000000000..e289a0ba15
--- /dev/null
+++ b/src/shared/registryaccess/CMakeLists.txt
@@ -0,0 +1,8 @@
+if (WIN32)
+ add_library(registryaccess STATIC registryaccess.cpp registryaccess.h)
+ target_link_libraries(registryaccess PUBLIC advapi32 ole32 shell32 Qt5::Widgets)
+ target_compile_definitions(registryaccess PRIVATE _UNICODE UNICODE)
+ target_include_directories(registryaccess PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+else()
+ add_library(registryaccess INTERFACE)
+endif()
diff --git a/src/shared/registryaccess/registryaccess.h b/src/shared/registryaccess/registryaccess.h
index 2880aa6677..cfd945d35a 100644
--- a/src/shared/registryaccess/registryaccess.h
+++ b/src/shared/registryaccess/registryaccess.h
@@ -45,6 +45,7 @@ enum AccessMode {
static const char *debuggerApplicationFileC = "qtcdebugger";
static const WCHAR *debuggerRegistryKeyC = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
static const WCHAR *debuggerRegistryValueNameC = L"Debugger";
+static const WCHAR *autoRegistryValueNameC = L"Auto";
static inline QString wCharToQString(const WCHAR *w)
{
diff --git a/src/tools/3rdparty/CMakeLists.txt b/src/tools/3rdparty/CMakeLists.txt
new file mode 100644
index 0000000000..b82a82ceb0
--- /dev/null
+++ b/src/tools/3rdparty/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(cplusplus-keywordgen)
diff --git a/src/tools/3rdparty/cplusplus-keywordgen/CMakeLists.txt b/src/tools/3rdparty/cplusplus-keywordgen/CMakeLists.txt
new file mode 100644
index 0000000000..0ab12f5bf2
--- /dev/null
+++ b/src/tools/3rdparty/cplusplus-keywordgen/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_qtc_executable(cplusplus-keywordgen
+ DEPENDS CPlusPlus Utils
+ SOURCES cplusplus-keywordgen.cpp
+)
+
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
new file mode 100644
index 0000000000..4ec3202b0b
--- /dev/null
+++ b/src/tools/CMakeLists.txt
@@ -0,0 +1,48 @@
+add_subdirectory(3rdparty)
+add_subdirectory(buildoutputparser)
+if (NOT Clang_FOUND)
+ message(WARNING "Could not find Clang installation - disabling clangbackend.")
+else ()
+ add_subdirectory(clangbackend)
+ add_subdirectory(clangrefactoringbackend)
+ add_subdirectory(clangpchmanagerbackend)
+endif ()
+
+option(BUILD_CPLUSPLUS_TOOLS "Build CPlusPlus tools" OFF)
+
+function(add_qtc_cpp_tool name)
+ add_qtc_executable(${name}
+ DEFINES
+ PATH_PREPROCESSOR_CONFIG=\"${CMAKE_CURRENT_SOURCE_DIR}/pp-configuration.inc\"
+ ${ARGN}
+ DEPENDS CPlusPlus Utils Qt5::Widgets
+ INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/cplusplus-shared"
+ "${CMAKE_CURRENT_SOURCE_DIR}/${name}"
+ SOURCES
+ cplusplus-shared/utils.cpp
+ "${name}/${name}.cpp"
+ )
+endfunction()
+
+if (BUILD_CPLUSPLUS_TOOLS)
+ add_qtc_cpp_tool(cplusplus-ast2png "")
+ add_qtc_cpp_tool(cplusplus-frontend "")
+ add_qtc_cpp_tool(cplusplus-mkvisitor PATH_AST_H=\"${CMAKE_CURRENT_SOURCE_DIR}/../../libs/3rdparty/cplusplus/AST.h\")
+ add_qtc_cpp_tool(cplusplus-update-frontend PATH_CPP_FRONTEND=\"${CMAKE_CURRENT_SOURCE_DIR}/../../libs/3rdparty/cplusplus\" PATH_DUMPERS_FILE=\"${CMAKE_CURRENT_SOURCE_DIR}/../cplusplus-ast2png/dumpers.inc\")
+endif()
+
+if (APPLE)
+ add_subdirectory(iostool)
+endif()
+
+add_subdirectory(qml2puppet)
+# add_subdirectory(qtcdebugger) ## windows only
+# add_subdirectory(qtcrashhandler)
+add_subdirectory(qtcreatorcrashhandler)
+# add_subdirectory(qtcreatorwidgets) ## qbs does not build this either
+add_subdirectory(qtpromaker)
+# add_subdirectory(screenshotcropper) ## qbs does not build this either
+add_subdirectory(sdktool)
+add_subdirectory(valgrindfake)
+# add_subdirectory(wininterrupt) ## windows only
+# add_subdirectory(winrtdebughelper) ## windows only
diff --git a/src/tools/buildoutputparser/CMakeLists.txt b/src/tools/buildoutputparser/CMakeLists.txt
new file mode 100644
index 0000000000..ff55e888a3
--- /dev/null
+++ b/src/tools/buildoutputparser/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_qtc_executable(buildoutputparser
+ DEPENDS Utils ProjectExplorer QtSupport QmakeProjectManager
+ SOURCES
+ main.cpp
+ outputprocessor.cpp outputprocessor.h
+)
diff --git a/src/tools/clangbackend/CMakeLists.txt b/src/tools/clangbackend/CMakeLists.txt
new file mode 100644
index 0000000000..c0ad4e864d
--- /dev/null
+++ b/src/tools/clangbackend/CMakeLists.txt
@@ -0,0 +1,8 @@
+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/source/CMakeLists.txt b/src/tools/clangbackend/source/CMakeLists.txt
new file mode 100644
index 0000000000..fe0ab54deb
--- /dev/null
+++ b/src/tools/clangbackend/source/CMakeLists.txt
@@ -0,0 +1,66 @@
+add_qtc_library(clangbackend_lib STATIC
+ DEPENDS libclang Sqlite ClangSupport
+ PUBLIC_DEFINES CLANGSUPPORT_BUILD_LIB
+ PUBLIC_INCLUDES
+ ${CLANG_INCLUDE_DIRS}
+ 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/clangbackend_global.h b/src/tools/clangbackend/source/clangbackend_global.h
index bca0937d59..0e89673b96 100644
--- a/src/tools/clangbackend/source/clangbackend_global.h
+++ b/src/tools/clangbackend/source/clangbackend_global.h
@@ -36,29 +36,9 @@ enum class PreferredTranslationUnit
LastUninitialized,
};
-// CLANG-UPGRADE-CHECK: Remove IS_PRETTY_DECL_SUPPORTED once we require clang >= 7.0
-#if defined(CINDEX_VERSION_HAS_PRETTYDECL_BACKPORTED) || CINDEX_VERSION_MINOR >= 46
-# define IS_PRETTY_DECL_SUPPORTED
-#endif
-
-// CLANG-UPGRADE-CHECK: Remove IS_INVALIDDECL_SUPPORTED once we require clang >= 7.0
-#if defined(CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED) || CINDEX_VERSION_MINOR >= 46
-# define IS_INVALIDDECL_SUPPORTED
-#endif
-
-// CLANG-UPGRADE-CHECK: Remove IS_LIMITSKIPFUNCTIONBODIESTOPREAMBLE_SUPPORTED once we require clang >= 7.0
-#if defined(CINDEX_VERSION_HAS_LIMITSKIPFUNCTIONBODIESTOPREAMBLE_BACKPORTED) || CINDEX_VERSION_MINOR >= 46
-# define IS_LIMITSKIPFUNCTIONBODIESTOPREAMBLE_SUPPORTED
-#endif
-
// CLANG-UPGRADE-CHECK: Remove IS_SKIPWARNINGSFROMINCLUDEDFILES_SUPPORTED
#if defined(CINDEX_VERSION_HAS_SKIPWARNINGSFROMINCLUDEDFILES_BACKPORTED)
# define IS_SKIPWARNINGSFROMINCLUDEDFILES_SUPPORTED
#endif
-// CLANG-UPGRADE-CHECK: Remove IS_COMPLETION_FIXITS_BACKPORTED once we require clang >= 7.0
-#if defined(CINDEX_VERSION_HAS_COMPLETION_FIXITS_BACKPORTED) || CINDEX_VERSION_MINOR >= 49
-# define IS_COMPLETION_FIXITS_BACKPORTED
-#endif
-
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtooltipinfocollector.cpp b/src/tools/clangbackend/source/clangtooltipinfocollector.cpp
index beecf63bb6..0d001ca3d4 100644
--- a/src/tools/clangbackend/source/clangtooltipinfocollector.cpp
+++ b/src/tools/clangbackend/source/clangtooltipinfocollector.cpp
@@ -87,7 +87,6 @@ Utf8String displayName(const Cursor &cursor)
Utf8String textForFunctionLike(const Cursor &cursor)
{
-#ifdef IS_PRETTY_DECL_SUPPORTED
CXPrintingPolicy policy = clang_getCursorPrintingPolicy(cursor.cx());
clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_FullyQualifiedName, 1);
clang_PrintingPolicy_setProperty(policy, CXPrintingPolicy_TerseOutput, 1);
@@ -98,17 +97,6 @@ Utf8String textForFunctionLike(const Cursor &cursor)
clang_getCursorPrettyPrinted(cursor.cx(), policy));
clang_PrintingPolicy_dispose(policy);
return prettyPrinted;
-#else
- // Printing function declarations with displayName() is quite limited:
- // * result type is not included
- // * parameter names are not included
- // * templates in the result type are not included
- // * no full qualification of the function name
- return Utf8String(cursor.resultType().spelling())
- + Utf8StringLiteral(" ")
- + qualificationPrefix(cursor)
- + Utf8String(cursor.displayName());
-#endif
}
Utf8String textForEnumConstantDecl(const Cursor &cursor)
diff --git a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
index a45a898738..fdad057089 100644
--- a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
+++ b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
@@ -177,10 +177,8 @@ uint TranslationUnitUpdater::defaultParseOptions()
return CXTranslationUnit_CacheCompletionResults
| CXTranslationUnit_PrecompiledPreamble
| CXTranslationUnit_CreatePreambleOnFirstParse
-#ifdef IS_LIMITSKIPFUNCTIONBODIESTOPREAMBLE_SUPPORTED
| CXTranslationUnit_SkipFunctionBodies
| CXTranslationUnit_LimitSkipFunctionBodiesToPreamble
-#endif
#ifdef IS_SKIPWARNINGSFROMINCLUDEDFILES_SUPPORTED
| CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles
#endif
diff --git a/src/tools/clangbackend/source/codecompleter.cpp b/src/tools/clangbackend/source/codecompleter.cpp
index 0613adf146..2db3fbe0f1 100644
--- a/src/tools/clangbackend/source/codecompleter.cpp
+++ b/src/tools/clangbackend/source/codecompleter.cpp
@@ -130,7 +130,7 @@ static QString tweakName(const Utf8String &oldName)
if (!oldName.contains('>'))
return QString();
- QString fullName = QString(oldName).trimmed();
+ 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"))
@@ -197,9 +197,7 @@ ClangCodeCompleteResults CodeCompleter::completeHelper(uint line, uint column)
uint CodeCompleter::defaultOptions() const
{
uint options = CXCodeComplete_IncludeMacros
- #ifdef IS_COMPLETION_FIXITS_BACKPORTED
| CXCodeComplete_IncludeCompletionsWithFixIts
- #endif
| CXCodeComplete_IncludeCodePatterns;
if (TranslationUnitUpdater::defaultParseOptions()
diff --git a/src/tools/clangbackend/source/codecompleter.h b/src/tools/clangbackend/source/codecompleter.h
index 6bfe77c09d..473404f03e 100644
--- a/src/tools/clangbackend/source/codecompleter.h
+++ b/src/tools/clangbackend/source/codecompleter.h
@@ -39,7 +39,6 @@ class ClangCodeCompleteResults;
class CodeCompleter
{
public:
- CodeCompleter() = default;
CodeCompleter(const TranslationUnit &translationUnit,
const UnsavedFiles &unsavedFiles);
diff --git a/src/tools/clangbackend/source/codecompletionsextractor.cpp b/src/tools/clangbackend/source/codecompletionsextractor.cpp
index 065a589539..be36cae088 100644
--- a/src/tools/clangbackend/source/codecompletionsextractor.cpp
+++ b/src/tools/clangbackend/source/codecompletionsextractor.cpp
@@ -361,8 +361,8 @@ SourceRangeContainer toRangeContainer(const UnsavedFile &file, CXSourceRange cxS
QTC_ASSERT(startLine == endLine, return SourceRangeContainer(););
const Utf8String lineText = file.lineRange(startLine, endLine);
- startColumn = QString(lineText.mid(0, startColumn - 1)).size() + 1;
- endColumn = QString(lineText.mid(0, endColumn - 1)).size() + 1;
+ 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));
@@ -370,7 +370,6 @@ SourceRangeContainer toRangeContainer(const UnsavedFile &file, CXSourceRange cxS
void CodeCompletionsExtractor::extractRequiredFixIts()
{
-#ifdef IS_COMPLETION_FIXITS_BACKPORTED
unsigned fixItsNumber = clang_getCompletionNumFixIts(cxCodeCompleteResults,
cxCodeCompleteResultIndex);
@@ -386,7 +385,6 @@ void CodeCompletionsExtractor::extractRequiredFixIts()
currentCodeCompletion_.requiredFixIts.push_back(
FixItContainer(Utf8String(fixIt), toRangeContainer(unsavedFile, range)));
}
-#endif
}
void CodeCompletionsExtractor::adaptPriority()
diff --git a/src/tools/clangbackend/source/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp
index e76091a661..00fde42cc8 100644
--- a/src/tools/clangbackend/source/cursor.cpp
+++ b/src/tools/clangbackend/source/cursor.cpp
@@ -107,11 +107,7 @@ bool Cursor::isDeclaration() const
bool Cursor::isInvalidDeclaration() const
{
-#ifdef IS_INVALIDDECL_SUPPORTED
return clang_isInvalidDeclaration(m_cxCursor);
-#else
- return false;
-#endif
}
bool Cursor::isLocalVariable() const
diff --git a/src/tools/clangpchmanagerbackend/CMakeLists.txt b/src/tools/clangpchmanagerbackend/CMakeLists.txt
new file mode 100644
index 0000000000..513fd4a7a5
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_subdirectory(source)
+
+add_qtc_executable(clangpchmanagerbackend
+ DEPENDS
+ clangrefactoringbackend_lib clangpchmanagerbackend_lib
+ clangTooling libclang Sqlite ClangSupport clangToolingRefactor clangQuery clangIndex
+ SOURCES
+ clangpchmanagerbackendmain.cpp
+)
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
index b2a58b0d66..0ce49e829d 100644
--- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
+++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
@@ -95,23 +95,22 @@ public:
class ApplicationEnvironment final : public ClangBackEnd::Environment
{
public:
- ApplicationEnvironment(const QString &pchsPath)
- : m_pchBuildDirectoryPath(pchsPath)
+ ApplicationEnvironment(const QString &pchsPath, const QString &preIncludeSearchPath)
+ : m_pchBuildDirectoryPath(pchsPath.toStdString())
+ , m_preIncludeSearchPath(ClangBackEnd::FilePath{preIncludeSearchPath})
{
}
- QString pchBuildDirectory() const override
+ Utils::PathString pchBuildDirectory() const override { return m_pchBuildDirectoryPath; }
+ uint hardwareConcurrency() const override { return std::thread::hardware_concurrency(); }
+ ClangBackEnd::NativeFilePathView preIncludeSearchPath() const override
{
- return m_pchBuildDirectoryPath;
- }
-
- uint hardwareConcurrency() const override
- {
- return std::thread::hardware_concurrency();
+ return m_preIncludeSearchPath;
}
private:
- QString m_pchBuildDirectoryPath;
+ Utils::PathString m_pchBuildDirectoryPath;
+ ClangBackEnd::NativeFilePath m_preIncludeSearchPath;
};
QStringList processArguments(QCoreApplication &application)
@@ -123,6 +122,7 @@ QStringList processArguments(QCoreApplication &application)
parser.addPositionalArgument(QStringLiteral("connection"), QStringLiteral("Connection"));
parser.addPositionalArgument(QStringLiteral("databasepath"), QStringLiteral("Database path"));
parser.addPositionalArgument(QStringLiteral("pchspath"), QStringLiteral("PCHs path"));
+ parser.addPositionalArgument(QStringLiteral("resourcepath"), QStringLiteral("Resource path"));
parser.process(application);
@@ -172,9 +172,9 @@ struct Data // because we have a cycle dependency
{
using TaskScheduler = ClangBackEnd::TaskScheduler<PchCreatorManager, ClangBackEnd::PchTaskQueue::Task>;
- Data(const QString &databasePath, const QString &pchsPath)
+ Data(const QString &databasePath, const QString &pchsPath, const QString &preIncludeSearchPath)
: database{Utils::PathString{databasePath}, 100000ms}
- , environment{pchsPath}
+ , environment{pchsPath, preIncludeSearchPath}
{}
Sqlite::Database database;
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
@@ -182,7 +182,8 @@ struct Data // because we have a cycle dependency
ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher{filePathCache};
ApplicationEnvironment environment;
ProjectPartsStorage<> projectPartsStorage{database};
- ProjectPartsManager projectParts{projectPartsStorage};
+ PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
+ ProjectPartsManager projectParts{projectPartsStorage, preCompiledHeaderStorage};
GeneratedFiles generatedFiles;
PchCreatorManager pchCreatorManager{generatedFiles,
environment,
@@ -190,7 +191,6 @@ struct Data // because we have a cycle dependency
clangPchManagerServer,
includeWatcher,
buildDependencyStorage};
- PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
ClangBackEnd::ProgressCounter pchCreationProgressCounter{[&](int progress, int total) {
executeInLoop([&] {
clangPchManagerServer.setPchCreationProgress(progress, total);
@@ -205,7 +205,8 @@ struct Data // because we have a cycle dependency
projectTaskScheduler,
pchCreationProgressCounter,
preCompiledHeaderStorage,
- database};
+ database,
+ environment};
ClangBackEnd::PchTasksMerger pchTaskMerger{pchTaskQueue};
ClangBackEnd::BuildDependenciesStorage<> buildDependencyStorage{database};
ClangBackEnd::BuildDependencyCollector buildDependencyCollector{filePathCache,
@@ -215,7 +216,8 @@ struct Data // because we have a cycle dependency
[&](ClangBackEnd::FilePathView path) -> TimeStamp {
return QFileInfo(QString(path)).lastModified().toSecsSinceEpoch();
}};
- ClangBackEnd::ModifiedTimeChecker modifiedTimeChecker{getModifiedTime, filePathCache};
+ ClangBackEnd::ModifiedTimeChecker<ClangBackEnd::SourceEntries> modifiedTimeChecker{getModifiedTime,
+ filePathCache};
ClangBackEnd::BuildDependenciesProvider buildDependencyProvider{buildDependencyStorage,
modifiedTimeChecker,
buildDependencyCollector,
@@ -265,13 +267,16 @@ int main(int argc, char *argv[])
const QString connectionName = arguments[0];
const QString databasePath = arguments[1];
const QString pchsPath = arguments[2];
+ const QString preIncludeSearchPath = arguments[3] + "/indexer_preincludes";
- Data data{databasePath, pchsPath};
+ Data data{databasePath, pchsPath, preIncludeSearchPath};
data.includeWatcher.setNotifier(&data.clangPchManagerServer);
ConnectionServer<PchManagerServer, PchManagerClientProxy> connectionServer;
connectionServer.setServer(&data.clangPchManagerServer);
+ data.buildDependencyProvider.setEnsureAliveMessageIsSentCallback(
+ [&] { connectionServer.ensureAliveMessageIsSent(); });
connectionServer.start(connectionName);
return application.exec();
diff --git a/src/tools/clangpchmanagerbackend/source/CMakeLists.txt b/src/tools/clangpchmanagerbackend/source/CMakeLists.txt
new file mode 100644
index 0000000000..76973c6a21
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/CMakeLists.txt
@@ -0,0 +1,49 @@
+add_qtc_library(clangpchmanagerbackend_lib STATIC
+ DEPENDS clangrefactoringbackend_lib ClangSupport
+ PUBLIC_DEPENDS libclang
+ PUBLIC_DEFINES CLANGSUPPORT_BUILD_LIB
+ PUBLIC_INCLUDES
+ ${CLANG_INCLUDE_DIRS}
+ SOURCES
+ builddependenciesprovider.cpp builddependenciesprovider.h
+ builddependenciesproviderinterface.h
+ builddependenciesstorage.h
+ builddependenciesstorageinterface.h
+ builddependency.h
+ builddependencycollector.cpp builddependencycollector.h
+ builddependencygeneratorinterface.h
+ clangpchmanagerbackend_global.h
+ collectbuilddependencyaction.h
+ collectbuilddependencypreprocessorcallbacks.h
+ collectbuilddependencytoolaction.h
+ collectusedmacroactionfactory.h
+ collectusedmacrosaction.h
+ collectusedmacrosandsourcespreprocessorcallbacks.h
+ generatepchactionfactory.h
+ pchcreator.cpp pchcreator.h
+ pchcreatorinterface.h
+ pchmanagerserver.cpp pchmanagerserver.h
+ pchnotcreatederror.h
+ pchtask.h
+ pchtaskgenerator.cpp pchtaskgenerator.h
+ pchtaskgeneratorinterface.h
+ pchtaskqueue.cpp
+ pchtaskqueue.h
+ pchtaskqueueinterface.h
+ pchtasksmerger.cpp
+ pchtasksmerger.h
+ pchtasksmergerinterface.h
+ precompiledheaderstorage.h
+ precompiledheaderstorageinterface.h
+ processorinterface.h
+ processormanager.h
+ processormanagerinterface.h
+ projectpartsmanager.cpp projectpartsmanager.h
+ projectpartsmanagerinterface.h
+ queueinterface.h
+ taskscheduler.h
+ taskschedulerinterface.h
+ toolchainargumentscache.h
+ usedmacrofilter.h
+ usedmacrosandsourcescollector.cpp usedmacrosandsourcescollector.h
+)
diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp
index bf00f39098..c2e3b4a5f9 100644
--- a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp
+++ b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp
@@ -55,8 +55,10 @@ OutputContainer setUnion(InputContainer1 &&input1,
BuildDependency BuildDependenciesProvider::create(const ProjectPartContainer &projectPart)
{
- auto sourcesAndProjectPart = createSourceEntriesFromStorage(
- projectPart.sourcePathIds, projectPart.projectPartId);
+ m_ensureAliveMessageIsSentCallback();
+
+ auto sourcesAndProjectPart = createSourceEntriesFromStorage(projectPart.sourcePathIds,
+ projectPart.projectPartId);
if (!m_modifiedTimeChecker.isUpToDate(sourcesAndProjectPart.first)) {
BuildDependency buildDependency = m_generator.create(projectPart);
diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h
index 9700b83aa3..924e3e4f45 100644
--- a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h
+++ b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h
@@ -27,6 +27,8 @@
#include "builddependenciesproviderinterface.h"
+#include <modifiedtimecheckerinterface.h>
+
namespace Sqlite {
class TransactionInterface;
}
@@ -34,14 +36,13 @@ class TransactionInterface;
namespace ClangBackEnd {
class BuildDependenciesStorageInterface;
-class ModifiedTimeCheckerInterface;
class BuildDependencyGeneratorInterface;
class BuildDependenciesProvider : public BuildDependenciesProviderInterface
{
public:
BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage,
- ModifiedTimeCheckerInterface &modifiedTimeChecker,
+ ModifiedTimeCheckerInterface<> &modifiedTimeChecker,
BuildDependencyGeneratorInterface &buildDependenciesGenerator,
Sqlite::TransactionInterface &transactionBackend)
: m_storage(buildDependenciesStorage)
@@ -52,6 +53,11 @@ public:
BuildDependency create(const ProjectPartContainer &projectPart) override;
+ void setEnsureAliveMessageIsSentCallback(std::function<void()> &&callback)
+ {
+ m_ensureAliveMessageIsSentCallback = std::move(callback);
+ }
+
private:
BuildDependency createBuildDependencyFromStorage(SourceEntries &&includes) const;
UsedMacros createUsedMacrosFromStorage(const SourceEntries &includes) const;
@@ -61,9 +67,10 @@ private:
private:
BuildDependenciesStorageInterface &m_storage;
- ModifiedTimeCheckerInterface &m_modifiedTimeChecker;
+ ModifiedTimeCheckerInterface<> &m_modifiedTimeChecker;
BuildDependencyGeneratorInterface &m_generator;
Sqlite::TransactionInterface &m_transactionBackend;
+ std::function<void()> m_ensureAliveMessageIsSentCallback;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h b/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h
index e7269dd0f9..8c8c51a6cd 100644
--- a/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h
+++ b/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h
@@ -66,6 +66,12 @@ public:
}
}
+ FilePathIds fetchSources(ProjectPartId projectPartId) const override
+ {
+ return fetchProjectPartsFilesStatement.template values<FilePathId>(1024,
+ projectPartId.projectPathId);
+ }
+
void insertOrUpdateFileStatuses(const FileStatuses &fileStatuses) override
{
WriteStatement &statement = insertOrUpdateFileStatusesStatement;
@@ -246,6 +252,8 @@ public:
"CONFLICT(sourceId, projectPartId) DO UPDATE SET sourceType = ?003, "
"hasMissingIncludes = ?004",
database};
+ mutable ReadStatement fetchProjectPartsFilesStatement{
+ "SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? ORDER BY sourceId", database};
mutable ReadStatement fetchSourceDependenciesStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION "
"SELECT dependencySourceId FROM sourceDependencies, "
diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h b/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h
index a56e88b1f2..1166564b32 100644
--- a/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h
+++ b/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h
@@ -56,6 +56,7 @@ public:
virtual UsedMacros fetchUsedMacros(FilePathId sourceId) const = 0;
virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) = 0;
virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) = 0;
+ virtual FilePathIds fetchSources(ProjectPartId projectPartId) const = 0;
protected:
~BuildDependenciesStorageInterface() = default;
diff --git a/src/tools/clangpchmanagerbackend/source/builddependencycollector.cpp b/src/tools/clangpchmanagerbackend/source/builddependencycollector.cpp
index 1d08442c51..b2c6cf8f86 100644
--- a/src/tools/clangpchmanagerbackend/source/builddependencycollector.cpp
+++ b/src/tools/clangpchmanagerbackend/source/builddependencycollector.cpp
@@ -33,7 +33,7 @@
#include <utils/smallstring.h>
#include <algorithm>
-#include <iostream>
+
namespace ClangBackEnd {
namespace {
@@ -68,18 +68,26 @@ FilePaths generatedFilePaths(const V2::FileContainers &containers) {
BuildDependency BuildDependencyCollector::create(const ProjectPartContainer &projectPart)
{
- CommandLineBuilder<ProjectPartContainer, Utils::SmallStringVector>
- builder{projectPart, projectPart.toolChainArguments, InputFileType::Source};
+ if (projectPart.sourcePathIds.size()) {
+ CommandLineBuilder<ProjectPartContainer, Utils::SmallStringVector> builder{
+ projectPart,
+ projectPart.toolChainArguments,
+ InputFileType::Source,
+ {},
+ {},
+ {},
+ m_environment.preIncludeSearchPath()};
- addFiles(projectPart.sourcePathIds, std::move(builder.commandLine));
+ addFiles(projectPart.sourcePathIds, std::move(builder.commandLine));
- setExcludedFilePaths(m_filePathCache.filePaths(projectPart.headerPathIds +
- projectPart.sourcePathIds) +
- generatedFilePaths(m_generatedFiles.fileContainers()));
+ setExcludedFilePaths(
+ m_filePathCache.filePaths(projectPart.headerPathIds + projectPart.sourcePathIds)
+ + generatedFilePaths(m_generatedFiles.fileContainers()));
- addUnsavedFiles(m_generatedFiles.fileContainers());
+ addUnsavedFiles(m_generatedFiles.fileContainers());
- collect();
+ collect();
+ }
auto buildDependency = std::move(m_buildDependency);
@@ -121,8 +129,7 @@ void BuildDependencyCollector::collect()
auto action = std::make_unique<CollectBuildDependencyToolAction>(m_buildDependency,
m_filePathCache,
- m_excludedFilePaths,
- m_sourcesManager);
+ m_excludedFilePaths);
tool.run(action.get());
}
@@ -147,7 +154,7 @@ void BuildDependencyCollector::setExcludedFilePaths(ClangBackEnd::FilePaths &&ex
void BuildDependencyCollector::addFiles(const FilePathIds &filePathIds,
Utils::SmallStringVector &&arguments)
{
- m_clangTool.addFile(FilePath{m_environment.pchBuildDirectory().toStdString(), "dummy.cpp"},
+ m_clangTool.addFile(FilePath{m_environment.pchBuildDirectory(), "dummy.cpp"},
generateFakeFileContent(filePathIds),
std::move(arguments));
m_buildDependency.sourceFiles.insert(m_buildDependency.sourceFiles.end(),
diff --git a/src/tools/clangpchmanagerbackend/source/builddependencycollector.h b/src/tools/clangpchmanagerbackend/source/builddependencycollector.h
index f8aaa8f07c..084024c821 100644
--- a/src/tools/clangpchmanagerbackend/source/builddependencycollector.h
+++ b/src/tools/clangpchmanagerbackend/source/builddependencycollector.h
@@ -95,7 +95,6 @@ private:
BuildDependency m_buildDependency;
ClangBackEnd::FilePaths m_excludedFilePaths;
Utils::SmallStringVector m_directories;
- SourcesManager m_sourcesManager;
const FilePathCachingInterface &m_filePathCache;
const GeneratedFilesInterface &m_generatedFiles;
const Environment &m_environment;
diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
index 61bcedc262..6b79e2e71f 100644
--- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
+++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
@@ -12,7 +12,6 @@ HEADERS += \
$$PWD/pchmanagerserver.h \
$$PWD/clangpchmanagerbackend_global.h \
$$PWD/pchnotcreatederror.h \
- $$PWD/environment.h \
$$PWD/pchcreatorinterface.h \
$$PWD/projectpartsmanager.h \
$$PWD/projectpartsmanagerinterface.h \
@@ -29,8 +28,6 @@ HEADERS += \
$$PWD/builddependenciesprovider.h \
$$PWD/builddependenciesstorageinterface.h \
$$PWD/builddependency.h \
- $$PWD/modifiedtimecheckerinterface.h \
- $$PWD/sourceentry.h \
$$PWD/builddependenciesstorage.h \
$$PWD/builddependencygeneratorinterface.h \
$$PWD/usedmacrofilter.h \
@@ -40,8 +37,7 @@ HEADERS += \
$$PWD/pchtaskqueue.h \
$$PWD/generatepchactionfactory.h \
$$PWD/pchtaskgeneratorinterface.h \
- $$PWD/toolchainargumentscache.h \
- $$PWD/modifiedtimechecker.h
+ $$PWD/toolchainargumentscache.h
!isEmpty(LIBTOOLING_LIBS) {
SOURCES += \
diff --git a/src/tools/clangpchmanagerbackend/source/collectbuilddependencyaction.h b/src/tools/clangpchmanagerbackend/source/collectbuilddependencyaction.h
index fa1a10e79c..3e98dc2483 100644
--- a/src/tools/clangpchmanagerbackend/source/collectbuilddependencyaction.h
+++ b/src/tools/clangpchmanagerbackend/source/collectbuilddependencyaction.h
@@ -40,15 +40,13 @@ class CollectBuildDependencyAction final : public clang::PreprocessOnlyAction
{
public:
CollectBuildDependencyAction(BuildDependency &buildDependency,
- const FilePathCachingInterface &filePathCache,
- std::vector<uint> &excludedIncludeUID,
- std::vector<uint> &alreadyIncludedFileUIDs,
- SourcesManager &sourcesManager)
- : m_buildDependency(buildDependency),
- m_filePathCache(filePathCache),
- m_excludedIncludeUID(excludedIncludeUID),
- m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs),
- m_sourcesManager(sourcesManager)
+ const FilePathCachingInterface &filePathCache,
+ std::vector<uint> &excludedIncludeUID,
+ std::vector<uint> &alreadyIncludedFileUIDs)
+ : m_buildDependency(buildDependency)
+ , m_filePathCache(filePathCache)
+ , m_excludedIncludeUID(excludedIncludeUID)
+ , m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs)
{
}
@@ -66,7 +64,6 @@ public:
m_excludedIncludeUID,
m_alreadyIncludedFileUIDs,
compilerInstance.getSourceManager(),
- m_sourcesManager,
compilerInstance.getPreprocessorPtr());
preprocessor.addPPCallbacks(
@@ -88,7 +85,6 @@ private:
const FilePathCachingInterface &m_filePathCache;
std::vector<uint> &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs;
- SourcesManager &m_sourcesManager;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h
index f3b365d8d5..8583ff7a15 100644
--- a/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h
+++ b/src/tools/clangpchmanagerbackend/source/collectbuilddependencypreprocessorcallbacks.h
@@ -54,12 +54,10 @@ public:
const std::vector<uint> &excludedIncludeUID,
std::vector<uint> &alreadyIncludedFileUIDs,
clang::SourceManager &sourceManager,
- SourcesManager &sourcesManager,
std::shared_ptr<clang::Preprocessor> preprocessor)
: CollectUsedMacrosAndSourcesPreprocessorCallbacksBase(buildDependency.usedMacros,
filePathCache,
sourceManager,
- sourcesManager,
preprocessor,
buildDependency.sourceDependencies,
buildDependency.sourceFiles,
@@ -189,7 +187,6 @@ public:
{
filterOutHeaderGuards();
mergeUsedMacros();
- m_sourcesManager.updateModifiedTimeStamps();
filterOutIncludesWithMissingIncludes();
}
@@ -293,7 +290,7 @@ public:
entry.get().hasMissingIncludes = HasMissingIncludes::Yes;
}
- SourceDependencies sourceDependenciesSortedByDependendFilePathId() const
+ SourceDependencies sourceDependenciesSortedByDependentFilePathId() const
{
auto sourceDependencies = m_buildDependency.sourceDependencies;
std::sort(sourceDependencies.begin(), sourceDependencies.end(), [](auto first, auto second) {
@@ -309,7 +306,7 @@ public:
sortAndMakeUnique(m_containsMissingIncludes);
collectSourceWithMissingIncludes(m_containsMissingIncludes,
- sourceDependenciesSortedByDependendFilePathId());
+ sourceDependenciesSortedByDependentFilePathId());
removeSourceWithMissingIncludesFromSources();
}
diff --git a/src/tools/clangpchmanagerbackend/source/collectbuilddependencytoolaction.h b/src/tools/clangpchmanagerbackend/source/collectbuilddependencytoolaction.h
index 4f28d0f7c8..471291ee90 100644
--- a/src/tools/clangpchmanagerbackend/source/collectbuilddependencytoolaction.h
+++ b/src/tools/clangpchmanagerbackend/source/collectbuilddependencytoolaction.h
@@ -38,13 +38,11 @@ class CollectBuildDependencyToolAction final : public clang::tooling::FrontendAc
{
public:
CollectBuildDependencyToolAction(BuildDependency &buildDependency,
- const FilePathCachingInterface &filePathCache,
- const ClangBackEnd::FilePaths &excludedIncludes,
- SourcesManager &sourcesManager)
- : m_buildDependency(buildDependency),
- m_filePathCache(filePathCache),
- m_excludedFilePaths(excludedIncludes),
- m_sourcesManager(sourcesManager)
+ const FilePathCachingInterface &filePathCache,
+ const ClangBackEnd::FilePaths &excludedIncludes)
+ : m_buildDependency(buildDependency)
+ , m_filePathCache(filePathCache)
+ , m_excludedFilePaths(excludedIncludes)
{}
@@ -67,8 +65,7 @@ public:
return new CollectBuildDependencyAction(m_buildDependency,
m_filePathCache,
m_excludedIncludeUIDs,
- m_alreadyIncludedFileUIDs,
- m_sourcesManager);
+ m_alreadyIncludedFileUIDs);
}
std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
@@ -95,7 +92,6 @@ private:
BuildDependency &m_buildDependency;
const FilePathCachingInterface &m_filePathCache;
const ClangBackEnd::FilePaths &m_excludedFilePaths;
- SourcesManager &m_sourcesManager;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/collectusedmacroactionfactory.h b/src/tools/clangpchmanagerbackend/source/collectusedmacroactionfactory.h
index b3f1cc0029..423d5f8876 100644
--- a/src/tools/clangpchmanagerbackend/source/collectusedmacroactionfactory.h
+++ b/src/tools/clangpchmanagerbackend/source/collectusedmacroactionfactory.h
@@ -39,13 +39,11 @@ class CollectUsedMacrosToolActionFactory final : public clang::tooling::Frontend
public:
CollectUsedMacrosToolActionFactory(UsedMacros &usedMacros,
FilePathCachingInterface &filePathCache,
- SourcesManager &sourcesManager,
SourceDependencies &sourceDependencies,
FilePathIds &sourceFiles,
FileStatuses &fileStatuses)
: m_usedMacros(usedMacros),
m_filePathCache(filePathCache),
- m_sourcesManager(sourcesManager),
m_sourceDependencies(sourceDependencies),
m_sourceFiles(sourceFiles),
m_fileStatuses(fileStatuses)
@@ -67,7 +65,6 @@ public:
{
return new CollectUsedMacrosAction(m_usedMacros,
m_filePathCache,
- m_sourcesManager,
m_sourceDependencies,
m_sourceFiles,
m_fileStatuses);
@@ -76,7 +73,6 @@ public:
private:
UsedMacros &m_usedMacros;
FilePathCachingInterface &m_filePathCache;
- SourcesManager &m_sourcesManager;
SourceDependencies &m_sourceDependencies;
FilePathIds &m_sourceFiles;
FileStatuses &m_fileStatuses;
diff --git a/src/tools/clangpchmanagerbackend/source/collectusedmacrosaction.h b/src/tools/clangpchmanagerbackend/source/collectusedmacrosaction.h
index 4134d41d41..8f50e5a230 100644
--- a/src/tools/clangpchmanagerbackend/source/collectusedmacrosaction.h
+++ b/src/tools/clangpchmanagerbackend/source/collectusedmacrosaction.h
@@ -41,13 +41,11 @@ class CollectUsedMacrosAction final : public clang::PreprocessOnlyAction
public:
CollectUsedMacrosAction(UsedMacros &usedMacros,
FilePathCachingInterface &filePathCache,
- SourcesManager &sourcesManager,
SourceDependencies &sourceDependencies,
FilePathIds &sourceFiles,
FileStatuses &fileStatuses)
: m_usedMacros(usedMacros),
m_filePathCache(filePathCache),
- m_sourcesManager(sourcesManager),
m_sourceDependencies(sourceDependencies),
m_sourceFiles(sourceFiles),
m_fileStatuses(fileStatuses)
@@ -65,7 +63,6 @@ public:
m_usedMacros,
m_filePathCache,
compilerInstance.getSourceManager(),
- m_sourcesManager,
compilerInstance.getPreprocessorPtr(),
m_sourceDependencies,
m_sourceFiles,
@@ -87,7 +84,6 @@ public:
private:
UsedMacros &m_usedMacros;
FilePathCachingInterface &m_filePathCache;
- SourcesManager &m_sourcesManager;
SourceDependencies &m_sourceDependencies;
FilePathIds &m_sourceFiles;
FileStatuses &m_fileStatuses;
diff --git a/src/tools/clangpchmanagerbackend/source/collectusedmacrosandsourcespreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectusedmacrosandsourcespreprocessorcallbacks.h
index b8ea406df0..5dc630de18 100644
--- a/src/tools/clangpchmanagerbackend/source/collectusedmacrosandsourcespreprocessorcallbacks.h
+++ b/src/tools/clangpchmanagerbackend/source/collectusedmacrosandsourcespreprocessorcallbacks.h
@@ -54,17 +54,16 @@ public:
CollectUsedMacrosAndSourcesPreprocessorCallbacksBase(UsedMacros &usedMacros,
const FilePathCachingInterface &filePathCache,
const clang::SourceManager &sourceManager,
- SourcesManager &sourcesManager,
std::shared_ptr<clang::Preprocessor> preprocessor,
SourceDependencies &sourceDependencies,
FilePathIds &sourceFiles,
FileStatuses &fileStatuses)
- : SymbolsVisitorBase(filePathCache, &sourceManager, sourcesManager),
- m_usedMacros(usedMacros),
- m_preprocessor(preprocessor),
- m_sourceDependencies(sourceDependencies),
- m_sourceFiles(sourceFiles),
- m_fileStatuses(fileStatuses)
+ : SymbolsVisitorBase(filePathCache, &sourceManager, m_filePathIndices)
+ , m_usedMacros(usedMacros)
+ , m_preprocessor(preprocessor)
+ , m_sourceDependencies(sourceDependencies)
+ , m_sourceFiles(sourceFiles)
+ , m_fileStatuses(fileStatuses)
{}
void addSourceFile(const clang::FileEntry *fileEntry)
@@ -166,6 +165,7 @@ public:
private:
UsedMacros m_maybeUsedMacros;
+ FilePathIds m_filePathIndices;
UsedMacros &m_usedMacros;
std::shared_ptr<clang::Preprocessor> m_preprocessor;
SourceDependencies &m_sourceDependencies;
@@ -248,7 +248,6 @@ public:
{
filterOutHeaderGuards();
mergeUsedMacros();
- m_sourcesManager.updateModifiedTimeStamps();
}
private:
diff --git a/src/tools/clangpchmanagerbackend/source/environment.h b/src/tools/clangpchmanagerbackend/source/environment.h
deleted file mode 100644
index 7f575fe169..0000000000
--- a/src/tools/clangpchmanagerbackend/source/environment.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 <QString>
-
-namespace ClangBackEnd {
-
-class Environment
-{
-public:
- Environment() = default;
- Environment(const Environment &) = delete;
- Environment &operator=(const Environment &) = delete;
-
- virtual QString pchBuildDirectory() const = 0;
- virtual uint hardwareConcurrency() const = 0;
-
-protected:
- ~Environment() = default;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h b/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h
index 2b1f4d036d..c4a8cae028 100644
--- a/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h
+++ b/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h
@@ -46,8 +46,9 @@ public:
{
compilerInstance.getPreprocessorOpts().DisablePCHValidation = true;
compilerInstance.getPreprocessorOpts().AllowPCHWithCompilerErrors = true;
- compilerInstance.getLangOpts().DelayedTemplateParsing = true;
compilerInstance.getDiagnosticOpts().ErrorLimit = 0;
+ compilerInstance.getFrontendOpts().SkipFunctionBodies = true;
+ compilerInstance.getFrontendOpts().IncludeTimestamps = true;
std::unique_ptr<llvm::MemoryBuffer> Input = llvm::MemoryBuffer::getMemBuffer(m_fileContent);
compilerInstance.getPreprocessorOpts().addRemappedFile(m_filePath, Input.release());
diff --git a/src/tools/clangpchmanagerbackend/source/modifiedtimechecker.h b/src/tools/clangpchmanagerbackend/source/modifiedtimechecker.h
deleted file mode 100644
index d641de054c..0000000000
--- a/src/tools/clangpchmanagerbackend/source/modifiedtimechecker.h
+++ /dev/null
@@ -1,214 +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 "modifiedtimecheckerinterface.h"
-
-#include <filepathcachinginterface.h>
-
-#include <algorithm>
-#include <iterator>
-
-namespace ClangBackEnd {
-
-class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface
-{
-public:
- using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>;
- ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache)
- : m_getModifiedTime(getModifiedTime)
- , m_filePathCache(filePathCache)
- {}
-
- bool isUpToDate(const SourceEntries &sourceEntries) const
- {
- if (sourceEntries.empty())
- return false;
-
- updateCurrentSourceTimeStamps(sourceEntries);
-
- return compareEntries(sourceEntries);
- }
-
- void pathsChanged(const FilePathIds &filePathIds)
- {
- using SourceTimeStampReferences = std::vector<std::reference_wrapper<SourceTimeStamp>>;
-
- SourceTimeStampReferences timeStampsToUpdate;
- timeStampsToUpdate.reserve(filePathIds.size());
-
- std::set_intersection(m_currentSourceTimeStamps.begin(),
- m_currentSourceTimeStamps.end(),
- filePathIds.begin(),
- filePathIds.end(),
- std::back_inserter(timeStampsToUpdate));
-
- for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) {
- sourceTimeStamp.lastModified = m_getModifiedTime(
- m_filePathCache.filePath(sourceTimeStamp.sourceId));
- }
- }
-
-private:
- bool compareEntries(const SourceEntries &sourceEntries) const
- {
- class CompareSourceId
- {
- public:
- bool operator()(SourceTimeStamp first, SourceTimeStamp second) {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceEntry first, SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceTimeStamp first, SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceEntry first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
- };
-
- SourceTimeStamps currentSourceTimeStamp;
- currentSourceTimeStamp.reserve(sourceEntries.size());
- std::set_intersection(m_currentSourceTimeStamps.begin(),
- m_currentSourceTimeStamps.end(),
- sourceEntries.begin(),
- sourceEntries.end(),
- std::back_inserter(currentSourceTimeStamp),
- CompareSourceId{});
-
- class CompareTime
- {
- public:
- bool operator()(SourceTimeStamp first, SourceTimeStamp second)
- {
- return first.lastModified <= second.lastModified;
- }
-
- bool operator()(SourceEntry first, SourceEntry second)
- {
- return first.pchCreationTimeStamp <=
- second.pchCreationTimeStamp;
- }
-
- bool operator()(SourceTimeStamp first, SourceEntry second)
- {
- return first.lastModified <= second.pchCreationTimeStamp;
- }
-
- bool operator()(SourceEntry first, SourceTimeStamp second)
- {
- return first.pchCreationTimeStamp <= second.lastModified;
- }
- };
-
- return std::lexicographical_compare(currentSourceTimeStamp.begin(),
- currentSourceTimeStamp.end(),
- sourceEntries.begin(),
- sourceEntries.end(),
- CompareTime{});
- }
-
- void updateCurrentSourceTimeStamps(const SourceEntries &sourceEntries) const
- {
- SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries);
-
- for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) {
- newSourceTimeStamp.lastModified = m_getModifiedTime(
- m_filePathCache.filePath(newSourceTimeStamp.sourceId));
- }
-
- auto split = sourceTimeStamps.insert(sourceTimeStamps.end(),
- m_currentSourceTimeStamps.begin(),
- m_currentSourceTimeStamps.end());
- std::inplace_merge(sourceTimeStamps.begin(), split, sourceTimeStamps.end());
-
- m_currentSourceTimeStamps = sourceTimeStamps;
- }
-
- SourceTimeStamps newSourceTimeStamps(const SourceEntries &sourceEntries) const
- {
- SourceEntries newSourceEntries;
- newSourceEntries.reserve(sourceEntries.size());
-
- class CompareSourceId
- {
- public:
- bool operator()(SourceTimeStamp first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceEntry first, SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceTimeStamp first, SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceEntry first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
- };
-
- std::set_difference(sourceEntries.begin(),
- sourceEntries.end(),
- m_currentSourceTimeStamps.begin(),
- m_currentSourceTimeStamps.end(),
- std::back_inserter(newSourceEntries),
- CompareSourceId{});
-
- SourceTimeStamps newTimeStamps;
- newTimeStamps.reserve(newSourceEntries.size());
-
- std::transform(newSourceEntries.begin(),
- newSourceEntries.end(),
- std::back_inserter(newTimeStamps),
- [](SourceEntry entry) {
- return SourceTimeStamp{entry.sourceId, {}};
- });
-
- return newTimeStamps;
- }
-
-private:
- mutable SourceTimeStamps m_currentSourceTimeStamps;
- GetModifiedTime &m_getModifiedTime;
- FilePathCachingInterface &m_filePathCache;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h b/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h
deleted file mode 100644
index c0cae1cf4b..0000000000
--- a/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.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 "sourceentry.h"
-
-namespace ClangBackEnd {
-
-class ModifiedTimeCheckerInterface
-{
-public:
- ModifiedTimeCheckerInterface() = default;
- ModifiedTimeCheckerInterface(const ModifiedTimeCheckerInterface &) = delete;
- ModifiedTimeCheckerInterface &operator=(const ModifiedTimeCheckerInterface &) = delete;
-
- virtual bool isUpToDate(const SourceEntries &sourceEntries) const = 0;
-
-protected:
- ~ModifiedTimeCheckerInterface() = default;
-};
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
index 3f858b50ee..cd7b492868 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
@@ -104,25 +104,29 @@ Utils::SmallStringVector PchCreator::generateClangCompilerArguments(const PchTas
InputFileType::Header,
{},
pchOutputPath,
- pchTask.systemPchPath};
+ pchTask.systemPchPath,
+ pchTask.preIncludeSearchPath};
return builder.commandLine;
}
void PchCreator::generatePch(PchTask &&pchTask)
{
+ m_projectPartPch.projectPartId = pchTask.projectPartId();
m_projectPartPch.lastModified = QDateTime::currentSecsSinceEpoch();
+
+ if (pchTask.includes.empty())
+ return;
+
auto content = generatePchIncludeFileContent(pchTask.includes);
auto pchOutputPath = generatePchFilePath();
- FilePath headerFilePath{m_environment.pchBuildDirectory().toStdString(), "dummy.h"};
+ FilePath headerFilePath{m_environment.pchBuildDirectory(), "dummy.h"};
Utils::SmallStringVector commandLine = generateClangCompilerArguments(pchTask, pchOutputPath);
m_clangTool.addFile(std::move(headerFilePath), content.clone(), std::move(commandLine));
bool success = generatePch(NativeFilePath{headerFilePath}, content);
- m_projectPartPch.projectPartId = pchTask.projectPartId();
-
if (success) {
m_sources = pchTask.sources;
m_projectPartPch.pchPath = std::move(pchOutputPath);
@@ -168,17 +172,19 @@ void PchCreator::clear()
void PchCreator::doInMainThreadAfterFinished()
{
- FilePathIds existingSources;
- existingSources.reserve(m_sources.size());
- std::set_difference(m_sources.begin(),
- m_sources.end(),
- m_generatedFilePathIds.begin(),
- m_generatedFilePathIds.end(),
- std::back_inserter(existingSources));
- m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified,
- m_projectPartPch.projectPartId);
- m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingSources}});
- m_pchManagerClient.precompiledHeadersUpdated(ProjectPartPchs{m_projectPartPch});
+ if (m_projectPartPch.projectPartId.isValid()) {
+ FilePathIds existingSources;
+ existingSources.reserve(m_sources.size());
+ std::set_difference(m_sources.begin(),
+ m_sources.end(),
+ m_generatedFilePathIds.begin(),
+ m_generatedFilePathIds.end(),
+ std::back_inserter(existingSources));
+ m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified,
+ m_projectPartPch.projectPartId);
+ m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingSources}});
+ m_pchManagerClient.precompiledHeadersUpdated({m_projectPartPch.projectPartId});
+ }
}
const FilePathCaching &PchCreator::filePathCache()
diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
index c1c12121aa..9cce6ef469 100644
--- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
@@ -34,6 +34,7 @@
#include <updategeneratedfilesmessage.h>
#include <updateprojectpartsmessage.h>
+#include <utils/algorithm.h>
#include <utils/smallstring.h>
#include <QApplication>
@@ -57,18 +58,29 @@ void PchManagerServer::end()
QCoreApplication::exit();
}
+namespace {
+ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectParts)
+{
+ return Utils::transform<ProjectPartIds>(projectParts, [](const auto &projectPart) {
+ return projectPart.projectPartId;
+ });
+}
+} // namespace
+
void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
{
m_toolChainsArgumentsCache.update(message.projectsParts, message.toolChainArguments);
- ProjectPartContainers newProjectParts = m_projectPartsManager.update(message.takeProjectsParts());
+ auto upToDateProjectParts = m_projectPartsManager.update(message.takeProjectsParts());
if (m_generatedFiles.isValid()) {
- m_pchTaskGenerator.addProjectParts(std::move(newProjectParts),
+ m_pchTaskGenerator.addProjectParts(std::move(upToDateProjectParts.notUpToDate),
std::move(message.toolChainArguments));
} else {
- m_projectPartsManager.updateDeferred(newProjectParts);
+ m_projectPartsManager.updateDeferred(upToDateProjectParts.notUpToDate);
}
+
+ client()->precompiledHeadersUpdated(toProjectPartIds(upToDateProjectParts.upToDate));
}
void PchManagerServer::removeProjectParts(RemoveProjectPartsMessage &&message)
diff --git a/src/tools/clangpchmanagerbackend/source/pchtask.h b/src/tools/clangpchmanagerbackend/source/pchtask.h
index 7d8879fcbd..74b410831e 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtask.h
+++ b/src/tools/clangpchmanagerbackend/source/pchtask.h
@@ -94,8 +94,8 @@ public:
&& first.systemIncludeSearchPaths == second.systemIncludeSearchPaths
&& first.projectIncludeSearchPaths == second.projectIncludeSearchPaths
&& first.toolChainArguments == second.toolChainArguments
- && first.language == second.language
- && first.languageVersion == second.languageVersion
+ && first.preIncludeSearchPath == second.preIncludeSearchPath
+ && first.language == second.language && first.languageVersion == second.languageVersion
&& first.languageExtension == second.languageExtension;
}
@@ -110,6 +110,7 @@ public:
IncludeSearchPaths systemIncludeSearchPaths;
IncludeSearchPaths projectIncludeSearchPaths;
Utils::SmallStringVector toolChainArguments;
+ NativeFilePathView preIncludeSearchPath;
Utils::Language language = Utils::Language::Cxx;
Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98;
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None;
diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp
index 2abe3fa394..b9d6a48fe3 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp
@@ -25,11 +25,16 @@
#include "pchtaskqueue.h"
+#include <environment.h>
#include <pchcreatorinterface.h>
#include <precompiledheaderstorageinterface.h>
#include <progresscounter.h>
#include <sqlitetransaction.h>
+#include <utils/algorithm.h>
+
+#include <iostream>
+
namespace ClangBackEnd {
void PchTaskQueue::addPchTasks(PchTasks &&newPchTasks, PchTasks &destination)
@@ -42,12 +47,12 @@ void PchTaskQueue::addPchTasks(PchTasks &&newPchTasks, PchTasks &destination)
PchTasks mergedPchTasks;
mergedPchTasks.reserve(destination.size() + newPchTasks.size());
- std::set_union(std::make_move_iterator(newPchTasks.begin()),
- std::make_move_iterator(newPchTasks.end()),
- std::make_move_iterator(destination.begin()),
- std::make_move_iterator(destination.end()),
- std::back_inserter(mergedPchTasks),
- compare);
+ Utils::set_union(std::make_move_iterator(newPchTasks.begin()),
+ std::make_move_iterator(newPchTasks.end()),
+ std::make_move_iterator(destination.begin()),
+ std::make_move_iterator(destination.end()),
+ std::back_inserter(mergedPchTasks),
+ compare);
destination = std::move(mergedPchTasks);
@@ -142,16 +147,17 @@ std::vector<PchTaskQueue::Task> PchTaskQueue::createProjectTasks(PchTasks &&pchT
auto convert = [this](auto &&pchTask) {
return [pchTask = std::move(pchTask), this](PchCreatorInterface &pchCreator) mutable {
const auto projectPartId = pchTask.projectPartId();
- pchTask.systemPchPath = m_precompiledHeaderStorage.fetchSystemPrecompiledHeaderPath(
- projectPartId);
- pchCreator.generatePch(std::move(pchTask));
- const auto &projectPartPch = pchCreator.projectPartPch();
- if (projectPartPch.pchPath.empty()) {
- m_precompiledHeaderStorage.deleteProjectPrecompiledHeader(projectPartId);
- } else {
- m_precompiledHeaderStorage.insertProjectPrecompiledHeader(
- projectPartId, projectPartPch.pchPath, projectPartPch.lastModified);
- }
+ pchTask.systemPchPath = m_precompiledHeaderStorage.fetchSystemPrecompiledHeaderPath(
+ projectPartId);
+ pchTask.preIncludeSearchPath = m_environment.preIncludeSearchPath();
+ pchCreator.generatePch(std::move(pchTask));
+ const auto &projectPartPch = pchCreator.projectPartPch();
+ if (projectPartPch.pchPath.empty()) {
+ m_precompiledHeaderStorage.deleteProjectPrecompiledHeader(projectPartId);
+ } else {
+ m_precompiledHeaderStorage.insertProjectPrecompiledHeader(
+ projectPartId, projectPartPch.pchPath, projectPartPch.lastModified);
+ }
};
};
@@ -171,15 +177,15 @@ std::vector<PchTaskQueue::Task> PchTaskQueue::createSystemTasks(PchTasks &&pchTa
auto convert = [this](auto &&pchTask) {
return [pchTask = std::move(pchTask), this](PchCreatorInterface &pchCreator) mutable {
const auto projectPartIds = pchTask.projectPartIds;
- pchCreator.generatePch(std::move(pchTask));
- const auto &projectPartPch = pchCreator.projectPartPch();
- if (projectPartPch.pchPath.empty()) {
- m_precompiledHeaderStorage.deleteSystemPrecompiledHeaders(projectPartIds);
- } else {
- m_precompiledHeaderStorage.insertSystemPrecompiledHeaders(projectPartIds,
- projectPartPch.pchPath,
- projectPartPch.lastModified);
- }
+ pchTask.preIncludeSearchPath = m_environment.preIncludeSearchPath();
+ pchCreator.generatePch(std::move(pchTask));
+ const auto &projectPartPch = pchCreator.projectPartPch();
+ if (projectPartPch.pchPath.empty()) {
+ m_precompiledHeaderStorage.deleteSystemPrecompiledHeaders(projectPartIds);
+ } else {
+ m_precompiledHeaderStorage.insertSystemPrecompiledHeaders(
+ projectPartIds, projectPartPch.pchPath, projectPartPch.lastModified);
+ }
};
};
diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskqueue.h b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.h
index 2d6d76ee58..80d96b8e85 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtaskqueue.h
+++ b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.h
@@ -36,6 +36,7 @@ namespace ClangBackEnd {
class PchCreatorInterface;
class PrecompiledHeaderStorageInterface;
class ProgressCounter;
+class Environment;
class PchTaskQueue final : public PchTaskQueueInterface
{
@@ -46,12 +47,14 @@ public:
TaskSchedulerInterface<Task> &projectPchTaskScheduler,
ProgressCounter &progressCounter,
PrecompiledHeaderStorageInterface &precompiledHeaderStorage,
- Sqlite::TransactionInterface &transactionsInterface)
+ Sqlite::TransactionInterface &transactionsInterface,
+ const Environment &environment)
: m_systemPchTaskScheduler(systemPchTaskScheduler)
, m_projectPchTaskScheduler(projectPchTaskScheduler)
, m_precompiledHeaderStorage(precompiledHeaderStorage)
, m_transactionsInterface(transactionsInterface)
, m_progressCounter(progressCounter)
+ , m_environment(environment)
{}
void addSystemPchTasks(PchTasks &&pchTasks) override;
@@ -80,6 +83,7 @@ private:
PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
Sqlite::TransactionInterface &m_transactionsInterface;
ProgressCounter &m_progressCounter;
+ const Environment &m_environment;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp
index 7e850b8947..68a8e4a642 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp
@@ -27,6 +27,8 @@
#include "pchtaskqueueinterface.h"
+#include <utils/algorithm.h>
+
namespace ClangBackEnd {
void PchTasksMerger::mergeTasks(PchTaskSets &&taskSets,
@@ -48,11 +50,11 @@ Result merge(Container &&first, Container &&second)
Result result;
result.reserve(first.size() + second.size());
- std::set_union(std::make_move_iterator(first.begin()),
- std::make_move_iterator(first.end()),
- std::make_move_iterator(second.begin()),
- std::make_move_iterator(second.end()),
- std::back_inserter(result));
+ Utils::set_union(std::make_move_iterator(first.begin()),
+ std::make_move_iterator(first.end()),
+ std::make_move_iterator(second.begin()),
+ std::make_move_iterator(second.end()),
+ std::back_inserter(result));
return result;
}
diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h
index e1b2f8aa2e..5510376fd5 100644
--- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h
+++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h
@@ -25,6 +25,7 @@
#pragma once
+#include "pchpaths.h"
#include "precompiledheaderstorageinterface.h"
#include <sqlitetransaction.h>
@@ -77,6 +78,20 @@ public:
}
}
+ void deleteProjectPrecompiledHeaders(const ProjectPartIds &projectPartIds) override
+ {
+ try {
+ Sqlite::ImmediateTransaction transaction{database};
+
+ for (ProjectPartId projectPartId : projectPartIds)
+ deleteProjectPrecompiledHeaderStatement.write(projectPartId.projectPathId);
+
+ transaction.commit();
+ } catch (const Sqlite::StatementIsBusy) {
+ deleteProjectPrecompiledHeaders(projectPartIds);
+ }
+ }
+
void insertSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds,
Utils::SmallStringView pchPath,
long long pchBuildTime) override
@@ -128,9 +143,42 @@ public:
return FilePath("");
}
- Utils::optional<ProjectPartPch> fetchPrecompiledHeader(ProjectPartId projectPartId) const
+ FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const override
{
- return getPrecompiledHeader.template value<ProjectPartPch, 3>(projectPartId.projectPathId);
+ try {
+ Sqlite::DeferredTransaction transaction{database};
+
+ auto value = fetchPrecompiledHeaderStatement.template value<FilePath>(
+ projectPartId.projectPathId);
+
+ if (value)
+ return *value;
+
+ transaction.commit();
+ } catch (const Sqlite::StatementIsBusy) {
+ return fetchPrecompiledHeader(projectPartId);
+ }
+
+ return FilePath("");
+ }
+
+ PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const override
+ {
+ try {
+ Sqlite::DeferredTransaction transaction{database};
+
+ auto value = fetchPrecompiledHeadersStatement.template value<PchPaths, 2>(
+ projectPartId.projectPathId);
+
+ if (value)
+ return *value;
+
+ transaction.commit();
+ } catch (const Sqlite::StatementIsBusy) {
+ return fetchPrecompiledHeaders(projectPartId);
+ }
+
+ return {};
}
public:
@@ -138,7 +186,7 @@ public:
Database &database;
WriteStatement insertProjectPrecompiledHeaderStatement{
"INSERT INTO precompiledHeaders(projectPartId, projectPchPath, projectPchBuildTime) "
- "VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?001),?002,?003) "
+ "VALUES(?001,?002,?003) "
"ON CONFLICT (projectPartId) DO UPDATE SET projectPchPath=?002,projectPchBuildTime=?003",
database};
WriteStatement insertSystemPrecompiledHeaderStatement{
@@ -156,9 +204,12 @@ public:
database};
ReadStatement fetchSystemPrecompiledHeaderPathStatement{
"SELECT systemPchPath FROM precompiledHeaders WHERE projectPartId = ?", database};
- mutable ReadStatement getPrecompiledHeader{
- "SELECT projectPartId, ifnull(nullif(projectPchPath, ''), systemPchPath), "
- "projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?",
+ mutable ReadStatement fetchPrecompiledHeaderStatement{
+ "SELECT ifnull(nullif(projectPchPath, ''), systemPchPath) "
+ "FROM precompiledHeaders WHERE projectPartId = ?",
+ database};
+ mutable ReadStatement fetchPrecompiledHeadersStatement{
+ "SELECT projectPchPath, systemPchPath FROM precompiledHeaders WHERE projectPartId = ?",
database};
};
diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h
index e2a2b4a3b6..2ce880cd6a 100644
--- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h
+++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h
@@ -27,7 +27,7 @@
#include "projectpartpch.h"
-#include <filepath.h>
+#include <pchpaths.h>
#include <projectpartid.h>
#include <utils/smallstringvector.h>
@@ -47,14 +47,16 @@ public:
Utils::SmallStringView pchPath,
long long pchBuildTime)
= 0;
- virtual void deleteProjectPrecompiledHeader(ProjectPartId projectPartName) = 0;
+ virtual void deleteProjectPrecompiledHeader(ProjectPartId projectPartId) = 0;
+ virtual void deleteProjectPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0;
virtual void insertSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds,
Utils::SmallStringView pchPath,
long long pchBuildTime)
= 0;
virtual void deleteSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0;
virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0;
- virtual Utils::optional<ProjectPartPch> fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0;
+ virtual FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0;
+ virtual PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const = 0;
protected:
~PrecompiledHeaderStorageInterface() = default;
diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp
index ada99f44cd..191a13e16b 100644
--- a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp
+++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp
@@ -44,31 +44,35 @@ ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectsParts)
return ids;
}
-ProjectPartContainers ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
+ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
{
- auto updatedProjectParts = filterNewProjectParts(std::move(projectsParts), m_projectParts);
+ auto notUpToDateProjectParts = filterProjectParts(projectsParts, m_projectParts);
- if (updatedProjectParts.empty())
- return {};
+ if (notUpToDateProjectParts.empty())
+ return {std::move(projectsParts), {}};
auto persistentProjectParts = m_projectPartsStorage.fetchProjectParts(
- toProjectPartIds(updatedProjectParts));
+ toProjectPartIds(notUpToDateProjectParts));
if (persistentProjectParts.size() > 0) {
mergeProjectParts(persistentProjectParts);
- updatedProjectParts = filterNewProjectParts(std::move(updatedProjectParts),
- persistentProjectParts);
+ notUpToDateProjectParts = filterProjectParts(notUpToDateProjectParts, persistentProjectParts);
- if (updatedProjectParts.empty())
+ if (notUpToDateProjectParts.empty())
return {};
}
- m_projectPartsStorage.updateProjectParts(updatedProjectParts);
+ m_projectPartsStorage.updateProjectParts(notUpToDateProjectParts);
+ m_projectPartsStorage.resetIndexingTimeStamps(notUpToDateProjectParts);
+ m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders(
+ toProjectPartIds(notUpToDateProjectParts));
- mergeProjectParts(updatedProjectParts);
+ mergeProjectParts(notUpToDateProjectParts);
- return updatedProjectParts;
+ auto upToDateProjectParts = filterProjectParts(projectsParts, notUpToDateProjectParts);
+
+ return {upToDateProjectParts, notUpToDateProjectParts};
}
void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds)
@@ -173,8 +177,8 @@ ProjectPartContainers ProjectPartsManager::deferredUpdates()
return deferredProjectParts;
}
-ProjectPartContainers ProjectPartsManager::filterNewProjectParts(
- ProjectPartContainers &&projectsParts, const ProjectPartContainers &oldProjectParts)
+ProjectPartContainers ProjectPartsManager::filterProjectParts(
+ const ProjectPartContainers &projectsParts, const ProjectPartContainers &oldProjectParts)
{
ProjectPartContainers updatedProjectPartContainers;
updatedProjectPartContainers.reserve(projectsParts.size());
diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h
index 6583db25c6..35d9e41c1c 100644
--- a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h
+++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.h
@@ -27,6 +27,7 @@
#include "clangpchmanagerbackend_global.h"
+#include <precompiledheaderstorageinterface.h>
#include <projectpartsmanagerinterface.h>
#include <projectpartsstorageinterface.h>
@@ -35,27 +36,31 @@
namespace ClangBackEnd {
inline namespace Pch {
+
class ProjectPartsManager final : public ProjectPartsManagerInterface
{
public:
- ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage)
+ ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage,
+ PrecompiledHeaderStorageInterface &precompiledHeaderStorage)
: m_projectPartsStorage(projectPartsStorage)
+ , m_precompiledHeaderStorage(precompiledHeaderStorage)
{}
- ProjectPartContainers update(ProjectPartContainers &&projectsParts) override;
+ UpToDataProjectParts update(ProjectPartContainers &&projectsParts) override;
void remove(const ProjectPartIds &projectPartIds) override;
ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const override;
void updateDeferred(const ProjectPartContainers &projectsParts) override;
ProjectPartContainers deferredUpdates() override;
- static ProjectPartContainers filterNewProjectParts(ProjectPartContainers &&newProjectsParts,
- const ProjectPartContainers &oldProjectParts);
+ static ProjectPartContainers filterProjectParts(const ProjectPartContainers &newProjectsParts,
+ const ProjectPartContainers &oldProjectParts);
void mergeProjectParts(const ProjectPartContainers &projectsParts);
const ProjectPartContainers &projectParts() const;
private:
ProjectPartContainers m_projectParts;
ProjectPartsStorageInterface &m_projectPartsStorage;
+ PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
};
} // namespace Pch
diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h b/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h
index ee80173f8a..54bae58c1a 100644
--- a/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h
+++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanagerinterface.h
@@ -32,11 +32,18 @@ namespace ClangBackEnd {
class ProjectPartsManagerInterface
{
public:
+ class UpToDataProjectParts
+ {
+ public:
+ ProjectPartContainers upToDate;
+ ProjectPartContainers notUpToDate;
+ };
+
ProjectPartsManagerInterface() = default;
ProjectPartsManagerInterface(const ProjectPartsManagerInterface &) = delete;
ProjectPartsManagerInterface &operator=(const ProjectPartsManagerInterface &) = delete;
- virtual ProjectPartContainers update(ProjectPartContainers &&projectsParts) = 0;
+ virtual UpToDataProjectParts update(ProjectPartContainers &&projectsParts) = 0;
virtual void remove(const ProjectPartIds &projectPartIds) = 0;
virtual ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const = 0;
virtual void updateDeferred(const ProjectPartContainers &projectsParts) = 0;
diff --git a/src/tools/clangpchmanagerbackend/source/sourceentry.h b/src/tools/clangpchmanagerbackend/source/sourceentry.h
deleted file mode 100644
index 5c45db6bde..0000000000
--- a/src/tools/clangpchmanagerbackend/source/sourceentry.h
+++ /dev/null
@@ -1,151 +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 <filepathid.h>
-
-#include <vector>
-
-namespace ClangBackEnd {
-
-enum class SourceType : unsigned char {
- TopProjectInclude,
- TopSystemInclude,
- UserInclude,
- ProjectInclude,
- SystemInclude,
- Source
-};
-
-enum class HasMissingIncludes : unsigned char { No, Yes };
-
-class TimeStamp
-{
- using int64 = long long;
-public:
- TimeStamp() = default;
- TimeStamp(int64 value)
- : value(value)
- {}
-
- operator int64() const
- {
- return value;
- }
-
- int64 value = -1;
-};
-
-class SourceTimeStamp
-{
- using int64 = long long;
-public:
- SourceTimeStamp(int sourceId, int64 lastModified)
- : lastModified(lastModified)
- , sourceId(sourceId)
- {}
-
- SourceTimeStamp(FilePathId sourceId, TimeStamp lastModified)
- : lastModified(lastModified)
- , sourceId(sourceId)
- {}
-
- friend bool operator<(SourceTimeStamp first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
-
- friend bool operator<(SourceTimeStamp first, FilePathId second)
- {
- return first.sourceId < second;
- }
-
- friend bool operator<(FilePathId first, SourceTimeStamp second)
- {
- return first < second.sourceId;
- }
-
- friend bool operator==(SourceTimeStamp first, SourceTimeStamp second)
- {
- return first.sourceId == second.sourceId && first.lastModified == second.lastModified;
- }
-
- friend bool operator!=(SourceTimeStamp first, SourceTimeStamp second)
- {
- return !(first == second);
- }
-
-public:
- TimeStamp lastModified;
- FilePathId sourceId;
-};
-
-using SourceTimeStamps = std::vector<SourceTimeStamp>;
-
-class SourceEntry
-{
- using int64 = long long;
-
-public:
- SourceEntry(int sourceId,
- int64 pchCreationTimeStamp,
- int sourceType,
- int hasMissingIncludes)
- : pchCreationTimeStamp(pchCreationTimeStamp), sourceId(sourceId),
- sourceType(static_cast<SourceType>(sourceType)),
- hasMissingIncludes(
- static_cast<HasMissingIncludes>(hasMissingIncludes)) {}
-
- SourceEntry(FilePathId sourceId,
- SourceType sourceType,
- TimeStamp pchCreationTimeStamp,
- HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No)
- : pchCreationTimeStamp(pchCreationTimeStamp), sourceId(sourceId),
- sourceType(sourceType), hasMissingIncludes(hasMissingIncludes) {}
-
- friend bool operator<(SourceEntry first, SourceEntry second) {
- return first.sourceId < second.sourceId;
- }
-
- friend bool operator==(SourceEntry first, SourceEntry second)
- {
- return first.sourceId == second.sourceId && first.sourceType == second.sourceType
- && first.pchCreationTimeStamp == second.pchCreationTimeStamp;
- }
-
- friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); }
-
-public:
- TimeStamp pchCreationTimeStamp;
- FilePathId sourceId;
- SourceType sourceType = SourceType::UserInclude;
- HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No;
-};
-
-using SourceEntries = std::vector<SourceEntry>;
-using SourceEntryReference = std::reference_wrapper<SourceEntry>;
-using SourceEntryReferences = std::vector<SourceEntryReference>;
-} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/toolchainargumentscache.h b/src/tools/clangpchmanagerbackend/source/toolchainargumentscache.h
index ed5ab3b1fd..d4d8a6479f 100644
--- a/src/tools/clangpchmanagerbackend/source/toolchainargumentscache.h
+++ b/src/tools/clangpchmanagerbackend/source/toolchainargumentscache.h
@@ -27,6 +27,8 @@
#include <projectpartcontainer.h>
+#include <utils/algorithm.h>
+
#include <functional>
namespace ClangBackEnd {
@@ -48,11 +50,11 @@ struct ArgumentsEntry
ProjectPartIds mergedIds;
mergedIds.reserve(ids.size() + newIds.size());
- std::set_union(std::make_move_iterator(ids.begin()),
- std::make_move_iterator(ids.end()),
- std::make_move_iterator(newIds.begin()),
- std::make_move_iterator(newIds.end()),
- std::back_inserter(mergedIds));
+ Utils::set_union(std::make_move_iterator(ids.begin()),
+ std::make_move_iterator(ids.end()),
+ std::make_move_iterator(newIds.begin()),
+ std::make_move_iterator(newIds.end()),
+ std::back_inserter(mergedIds));
ids = std::move(mergedIds);
}
diff --git a/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.cpp b/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.cpp
index b26b2b801c..770d46f5e1 100644
--- a/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.cpp
+++ b/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.cpp
@@ -48,7 +48,6 @@ void UsedMacroAndSourcesCollector::collect()
auto action = std::make_unique<CollectUsedMacrosToolActionFactory>(
m_usedMacros,
m_filePathCache,
- m_sourcesManager,
m_sourceDependencies,
m_sourceFiles,
m_fileStatuses);
diff --git a/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.h b/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.h
index a5b5749c12..9b72201fbb 100644
--- a/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.h
+++ b/src/tools/clangpchmanagerbackend/source/usedmacrosandsourcescollector.h
@@ -74,7 +74,6 @@ public:
private:
ClangTool m_clangTool;
- SourcesManager m_sourcesManager;
UsedMacros m_usedMacros;
FilePathCachingInterface &m_filePathCache;
FilePathIds m_sourceFiles;
diff --git a/src/tools/clangrefactoringbackend/CMakeLists.txt b/src/tools/clangrefactoringbackend/CMakeLists.txt
new file mode 100644
index 0000000000..d161659e82
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_subdirectory(source)
+
+add_qtc_executable(clangrefactoringbackend
+ DEPENDS
+ clangrefactoringbackend_lib Sqlite
+ SOURCES
+ clangrefactoringbackendmain.cpp
+)
diff --git a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp
index 9579f760c9..aaef21b608 100644
--- a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp
+++ b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp
@@ -30,11 +30,12 @@
#include <QDir>
#include <connectionserver.h>
+#include <environment.h>
#include <executeinloop.h>
#include <filepathcaching.h>
#include <generatedfiles.h>
-#include <refactoringserver.h>
#include <refactoringclientproxy.h>
+#include <refactoringserver.h>
#include <symbolindexing.h>
#include <sqliteexception.h>
@@ -59,6 +60,8 @@ QStringList processArguments(QCoreApplication &application)
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument(QStringLiteral("connection"), QStringLiteral("Connection"));
+ parser.addPositionalArgument(QStringLiteral("databasepath"), QStringLiteral("Database path"));
+ parser.addPositionalArgument(QStringLiteral("resourcepath"), QStringLiteral("Resource path"));
parser.process(application);
@@ -85,12 +88,32 @@ public:
}
};
+class ApplicationEnvironment final : public ClangBackEnd::Environment
+{
+public:
+ ApplicationEnvironment(const QString &preIncludeSearchPath)
+ : m_preIncludeSearchPath(ClangBackEnd::FilePath{preIncludeSearchPath})
+ {}
+
+ Utils::PathString pchBuildDirectory() const override { return {}; }
+ uint hardwareConcurrency() const override { return std::thread::hardware_concurrency(); }
+ ClangBackEnd::NativeFilePathView preIncludeSearchPath() const override
+ {
+ return m_preIncludeSearchPath;
+ }
+
+private:
+ ClangBackEnd::NativeFilePath m_preIncludeSearchPath;
+};
+
struct Data // because we have a cycle dependency
{
- Data(const QString &databasePath)
- : database{Utils::PathString{databasePath}, 100000ms}
+ Data(const QString &databasePath, const QString &preIncludeSearchPath)
+ : environment{preIncludeSearchPath}
+ , database{Utils::PathString{databasePath}, 100000ms}
{}
+ ApplicationEnvironment environment;
Sqlite::Database database;
RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
FilePathCaching filePathCache{database};
@@ -103,7 +126,8 @@ struct Data // because we have a cycle dependency
executeInLoop([&] {
clangCodeModelServer.setProgress(progress, total);
});
- }};
+ },
+ environment};
};
#ifdef Q_OS_WIN
@@ -131,8 +155,9 @@ int main(int argc, char *argv[])
const QStringList arguments = processArguments(application);
const QString connectionName = arguments[0];
const QString databasePath = arguments[1];
+ const QString preIncludeSearchPath = arguments[2] + "/indexer_preincludes";
- Data data{databasePath};
+ Data data{databasePath, preIncludeSearchPath};
ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer;
connectionServer.setServer(&data.clangCodeModelServer);
diff --git a/src/tools/clangrefactoringbackend/source/CMakeLists.txt b/src/tools/clangrefactoringbackend/source/CMakeLists.txt
new file mode 100644
index 0000000000..d43472fd60
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/CMakeLists.txt
@@ -0,0 +1,54 @@
+add_qtc_library(clangrefactoringbackend_lib STATIC
+ PUBLIC_DEPENDS
+ Threads::Threads
+ LLVMCore libclang
+ clangAST clangASTMatchers clangBasic clangDynamicASTMatchers clangFrontend
+ clangHandleCXX clangIndex clangLex
+ clangSerialization clangTooling clangQuery
+ ClangSupport
+ PUBLIC_DEFINES CLANGSUPPORT_BUILD_LIB
+ PUBLIC_INCLUDES
+ ${CLANG_INCLUDE_DIRS}
+ "../../clangpchmanagerbackend/source"
+ SOURCES
+ clangquery.cpp clangquery.h
+ clangquerygatherer.cpp clangquerygatherer.h
+ clangrefactoringbackend_global.h
+ clangtool.cpp clangtool.h
+ collectmacrospreprocessorcallbacks.h
+ collectmacrossourcefilecallbacks.cpp collectmacrossourcefilecallbacks.h
+ collectsymbolsaction.cpp collectsymbolsaction.h
+ filestatus.h
+ filestatuscache.cpp filestatuscache.h
+ filestatuspreprocessorcallbacks.cpp filestatuspreprocessorcallbacks.h
+ findcursorusr.h
+ findlocationsofusrs.h
+ findusrforcursoraction.cpp findusrforcursoraction.h
+ indexdataconsumer.cpp indexdataconsumer.h
+ locationsourcefilecallbacks.cpp locationsourcefilecallbacks.h
+ macropreprocessorcallbacks.cpp macropreprocessorcallbacks.h
+ projectpartentry.h
+ refactoringcompilationdatabase.cpp refactoringcompilationdatabase.h
+ refactoringserver.cpp refactoringserver.h
+ sourcedependency.h
+ sourcelocationentry.h
+ sourcelocationsutils.h
+ sourcerangeextractor.cpp sourcerangeextractor.h
+ sourcerangefilter.cpp sourcerangefilter.h
+ sourcesmanager.h
+ symbolentry.h
+ symbolfinder.cpp symbolfinder.h
+ symbolindexer.cpp symbolindexer.h
+ symbolindexertask.h
+ symbolindexertaskqueue.h
+ symbolindexertaskqueueinterface.h
+ symbolindexing.cpp symbolindexing.h
+ symbolindexinginterface.h
+ symbollocationfinderaction.cpp symbollocationfinderaction.h
+ symbolscollector.cpp symbolscollector.h
+ symbolscollectorinterface.h
+ symbolstorage.h
+ symbolstorageinterface.h
+ symbolsvisitorbase.h
+ usedmacro.h
+)
diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri
index fcac51f226..e7e83da788 100644
--- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri
+++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri
@@ -2,6 +2,7 @@ INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/clangrefactoringbackend_global.h \
+ $$PWD/filestatuspreprocessorcallbacks.h \
$$PWD/sourcerangefilter.h \
$$PWD/symbolindexer.h \
$$PWD/symbolentry.h \
@@ -64,6 +65,7 @@ HEADERS += \
}
SOURCES += \
+ $$PWD/filestatuspreprocessorcallbacks.cpp \
$$PWD/sourcerangefilter.cpp \
$$PWD/symbolindexer.cpp \
$$PWD/filestatuscache.cpp
diff --git a/src/tools/clangrefactoringbackend/source/collectmacrospreprocessorcallbacks.h b/src/tools/clangrefactoringbackend/source/collectmacrospreprocessorcallbacks.h
index 1d16b0f5e1..b0d59607e2 100644
--- a/src/tools/clangrefactoringbackend/source/collectmacrospreprocessorcallbacks.h
+++ b/src/tools/clangrefactoringbackend/source/collectmacrospreprocessorcallbacks.h
@@ -56,18 +56,16 @@ public:
SourceDependencies &sourceDependencies,
FilePathCachingInterface &filePathCache,
const clang::SourceManager &sourceManager,
- std::shared_ptr<clang::Preprocessor> &&preprocessor,
- SourcesManager &sourcesManager)
+ std::shared_ptr<clang::Preprocessor> &&preprocessor)
: CollectUsedMacrosAndSourcesPreprocessorCallbacksBase(usedMacros,
filePathCache,
sourceManager,
- sourcesManager,
std::move(preprocessor),
sourceDependencies,
sourceFiles,
- fileStatuses),
- m_symbolEntries(symbolEntries),
- m_sourceLocationEntries(sourceLocationEntries)
+ fileStatuses)
+ , m_symbolEntries(symbolEntries)
+ , m_sourceLocationEntries(sourceLocationEntries)
{
}
@@ -88,17 +86,15 @@ public:
}
void InclusionDirective(clang::SourceLocation hashLocation,
- const clang::Token &/*includeToken*/,
+ const clang::Token & /*includeToken*/,
llvm::StringRef /*fileName*/,
bool /*isAngled*/,
clang::CharSourceRange /*fileNameRange*/,
const clang::FileEntry *file,
llvm::StringRef /*searchPath*/,
llvm::StringRef /*relativePath*/,
- const clang::Module * /*imported*/
-#if LLVM_VERSION_MAJOR >= 7
- , clang::SrcMgr::CharacteristicKind /*fileType*/
-#endif
+ const clang::Module * /*imported*/,
+ clang::SrcMgr::CharacteristicKind /*fileType*/
) override
{
if (!m_skipInclude && file)
@@ -174,7 +170,6 @@ public:
{
filterOutHeaderGuards();
mergeUsedMacros();
- m_sourcesManager.updateModifiedTimeStamps();
}
static const clang::MacroInfo *firstMacroInfo(const clang::MacroDirective *macroDirective)
diff --git a/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp
index d96fb05026..d360b727c4 100644
--- a/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp
+++ b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp
@@ -34,16 +34,15 @@ namespace ClangBackEnd {
bool CollectMacrosSourceFileCallbacks::handleBeginSource(clang::CompilerInstance &compilerInstance)
{
auto callbacks = std::make_unique<CollectMacrosPreprocessorCallbacks>(
- m_symbolEntries,
- m_sourceLocationEntries,
- m_sourceFiles,
- m_usedMacros,
- m_fileStatuses,
- m_sourceDependencies,
- m_filePathCache,
- compilerInstance.getSourceManager(),
- compilerInstance.getPreprocessorPtr(),
- m_sourcesManager);
+ m_symbolEntries,
+ m_sourceLocationEntries,
+ m_sourceFiles,
+ m_usedMacros,
+ m_fileStatuses,
+ m_sourceDependencies,
+ m_filePathCache,
+ compilerInstance.getSourceManager(),
+ compilerInstance.getPreprocessorPtr());
compilerInstance.getPreprocessorPtr()->addPPCallbacks(std::move(callbacks));
diff --git a/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h
index 2392238106..16ba5a4f53 100644
--- a/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h
+++ b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h
@@ -44,12 +44,10 @@ class CollectMacrosSourceFileCallbacks : public clang::tooling::SourceFileCallba
public:
CollectMacrosSourceFileCallbacks(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
- FilePathCachingInterface &filePathCache,
- SourcesManager &sourcesManager)
- : m_symbolEntries(symbolEntries),
- m_sourceLocationEntries(sourceLocationEntries),
- m_filePathCache(filePathCache),
- m_sourcesManager(sourcesManager)
+ FilePathCachingInterface &filePathCache)
+ : m_symbolEntries(symbolEntries)
+ , m_sourceLocationEntries(sourceLocationEntries)
+ , m_filePathCache(filePathCache)
{
}
@@ -96,7 +94,6 @@ private:
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathCachingInterface &m_filePathCache;
- SourcesManager &m_sourcesManager;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp
index 91c0dd28d8..301f50beae 100644
--- a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp
+++ b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp
@@ -33,8 +33,7 @@ std::unique_ptr<clang::ASTConsumer> CollectSymbolsAction::newASTConsumer(
clang::CompilerInstance &compilerInstance,
llvm::StringRef inFile)
{
- m_indexDataConsumer->setSourceManager(&compilerInstance.getSourceManager());
- return m_action.CreateASTConsumer(compilerInstance, inFile);
+ return clang::WrapperFrontendAction::CreateASTConsumer(compilerInstance, inFile);
}
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h
index 2074a25a6e..a38f1c4f87 100644
--- a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h
+++ b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h
@@ -26,8 +26,8 @@
#pragma once
#include "clangrefactoringbackend_global.h"
-#include "sourcelocationentry.h"
#include "indexdataconsumer.h"
+#include "sourcelocationentry.h"
#include "symbolentry.h"
#include <utils/smallstring.h>
@@ -37,53 +37,68 @@
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendAction.h>
#include <clang/Index/IndexingAction.h>
+#include <clang/Lex/PreprocessorOptions.h>
#include <mutex>
namespace ClangBackEnd {
-class CollectSymbolsAction
+class CollectSymbolsAction : public clang::WrapperFrontendAction
{
public:
CollectSymbolsAction(std::shared_ptr<IndexDataConsumer> indexDataConsumer)
- : m_action(indexDataConsumer, createIndexingOptions()),
- m_indexDataConsumer(indexDataConsumer.get())
+ : clang::WrapperFrontendAction(
+ clang::index::createIndexingAction(indexDataConsumer, createIndexingOptions(), nullptr))
+ , m_indexDataConsumer(indexDataConsumer)
{}
std::unique_ptr<clang::ASTConsumer> newASTConsumer(clang::CompilerInstance &compilerInstance,
llvm::StringRef inFile);
-private:
- class WrappedIndexAction final : public clang::WrapperFrontendAction
- {
- public:
- WrappedIndexAction(std::shared_ptr<clang::index::IndexDataConsumer> indexDataConsumer,
- clang::index::IndexingOptions indexingOptions)
- : clang::WrapperFrontendAction(
- clang::index::createIndexingAction(indexDataConsumer, indexingOptions, nullptr))
- {}
-
- std::unique_ptr<clang::ASTConsumer>
- CreateASTConsumer(clang::CompilerInstance &compilerInstance,
- llvm::StringRef inFile) override
- {
- return WrapperFrontendAction::CreateASTConsumer(compilerInstance, inFile);
- }
- };
-
- static
- clang::index::IndexingOptions createIndexingOptions()
+
+ static clang::index::IndexingOptions createIndexingOptions()
{
clang::index::IndexingOptions options;
options.SystemSymbolFilter = clang::index::IndexingOptions::SystemSymbolFilterKind::None;
options.IndexFunctionLocals = true;
+ options.IndexMacrosInPreprocessor = true;
return options;
}
+ bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
+ {
+ m_indexDataConsumer->setSourceManager(&compilerInstance.getSourceManager());
+ compilerInstance.getPreprocessorOpts().AllowPCHWithCompilerErrors = true;
+ compilerInstance.getDiagnosticOpts().ErrorLimit = 1;
+
+ return clang::WrapperFrontendAction::BeginInvocation(compilerInstance);
+ }
+
+ bool BeginSourceFileAction(clang::CompilerInstance &compilerInstance) override
+ {
+ compilerInstance.getPreprocessor().SetSuppressIncludeNotFoundError(true);
+
+ return clang::WrapperFrontendAction::BeginSourceFileAction(compilerInstance);
+ }
+
+ void EndSourceFileAction() override { clang::WrapperFrontendAction::EndSourceFileAction(); }
+
+ bool PrepareToExecuteAction(clang::CompilerInstance &instance) override
+ {
+ return clang::WrapperFrontendAction::PrepareToExecuteAction(instance);
+ }
+
+ void ExecuteAction() override { clang::WrapperFrontendAction::ExecuteAction(); }
+
+ std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &compilerInstance,
+ llvm::StringRef inFile) override
+ {
+ return WrapperFrontendAction::CreateASTConsumer(compilerInstance, inFile);
+ }
+
private:
- WrappedIndexAction m_action;
- IndexDataConsumer *m_indexDataConsumer;
+ std::shared_ptr<IndexDataConsumer> m_indexDataConsumer;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.cpp b/src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.cpp
new file mode 100644
index 0000000000..28efe39f9b
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 "filestatuspreprocessorcallbacks.h"
+
+namespace ClangBackEnd {
+
+void FileStatusPreprocessorCallbacks::FileChanged(clang::SourceLocation sourceLocation,
+ clang::PPCallbacks::FileChangeReason reason,
+ clang::SrcMgr::CharacteristicKind,
+ clang::FileID)
+{
+ if (reason == clang::PPCallbacks::EnterFile) {
+ const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(
+ m_sourceManager->getFileID(sourceLocation));
+ if (fileEntry)
+ addFileStatus(fileEntry);
+ }
+}
+
+void FileStatusPreprocessorCallbacks::addFileStatus(const clang::FileEntry *fileEntry)
+{
+ auto id = filePathId(fileEntry);
+
+ auto found = std::lower_bound(m_fileStatuses.begin(),
+ m_fileStatuses.end(),
+ id,
+ [](const auto &first, const auto &second) {
+ return first.filePathId < second;
+ });
+
+ if (found == m_fileStatuses.end() || found->filePathId != id) {
+ m_fileStatuses.emplace(found, id, fileEntry->getSize(), fileEntry->getModificationTime());
+ }
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.h b/src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.h
new file mode 100644
index 0000000000..ad7bc4f4d6
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/filestatuspreprocessorcallbacks.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 "filestatus.h"
+#include "symbolsvisitorbase.h"
+
+#include <filepathid.h>
+
+#include <clang/Lex/PPCallbacks.h>
+
+namespace ClangBackEnd {
+
+class FileStatusPreprocessorCallbacks final : public clang::PPCallbacks, public SymbolsVisitorBase
+{
+public:
+ FileStatusPreprocessorCallbacks(FileStatuses &fileStatuses,
+ const FilePathCachingInterface &filePathCache,
+ const clang::SourceManager *sourceManager,
+ FilePathIds &filePathIndices)
+ : SymbolsVisitorBase(filePathCache, sourceManager, filePathIndices)
+ , m_fileStatuses(fileStatuses)
+ {}
+
+ void FileChanged(clang::SourceLocation sourceLocation,
+ clang::PPCallbacks::FileChangeReason reason,
+ clang::SrcMgr::CharacteristicKind,
+ clang::FileID) override;
+
+ void addFileStatus(const clang::FileEntry *fileEntry);
+
+private:
+ FileStatuses &m_fileStatuses;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/findcursorusr.h b/src/tools/clangrefactoringbackend/source/findcursorusr.h
index 549086cd3a..06777d8611 100644
--- a/src/tools/clangrefactoringbackend/source/findcursorusr.h
+++ b/src/tools/clangrefactoringbackend/source/findcursorusr.h
@@ -25,6 +25,8 @@
#pragma once
+#include "clangrefactoringbackend_global.h"
+
#include <clang/AST/AST.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/RecursiveASTVisitor.h>
@@ -161,7 +163,7 @@ std::vector<const clang::NamedDecl *> namedDeclarationsAt(const clang::ASTContex
auto declarations = Context.getTranslationUnitDecl()->decls();
for (auto &currentDeclation : declarations) {
- const auto &fileLocation = currentDeclation->getLocStart();
+ const auto &fileLocation = currentDeclation->getBeginLoc();
const auto &fileName = sourceManager.getFilename(fileLocation);
if (fileName == currentFile) {
visitor.TraverseDecl(currentDeclation);
diff --git a/src/tools/clangrefactoringbackend/source/indexdataconsumer.cpp b/src/tools/clangrefactoringbackend/source/indexdataconsumer.cpp
index 86e5fb597c..1fa6043461 100644
--- a/src/tools/clangrefactoringbackend/source/indexdataconsumer.cpp
+++ b/src/tools/clangrefactoringbackend/source/indexdataconsumer.cpp
@@ -24,14 +24,18 @@
****************************************************************************/
#include "indexdataconsumer.h"
+#include "collectsymbolsaction.h"
+#include "filestatuspreprocessorcallbacks.h"
+#include <clang/AST/DeclVisitor.h>
#include <clang/Basic/SourceLocation.h>
#include <clang/Index/IndexSymbol.h>
-#include <clang/AST/Decl.h>
-#include <clang/AST/DeclVisitor.h>
+#include <clang/Index/IndexingAction.h>
#include <llvm/ADT/ArrayRef.h>
+#include <iostream>
+
namespace ClangBackEnd {
namespace {
@@ -113,23 +117,33 @@ bool isReference(clang::index::SymbolRoleSet symbolRoles)
return symbolRoles & (uint(SymbolRole::Reference) | uint(SymbolRole::Call));
}
-}
+} // namespace
bool IndexDataConsumer::skipSymbol(clang::FileID fileId, clang::index::SymbolRoleSet symbolRoles)
{
- bool alreadyParsed = isAlreadyParsed(fileId);
- bool isParsedDeclaration = alreadyParsed && isDeclaration(symbolRoles);
- bool isParsedReference = alreadyParsed && !dependentFilesAreModified() && isReference(symbolRoles);
+ return isAlreadyParsed(fileId, m_symbolSourcesManager)
+ && !m_symbolSourcesManager.dependentFilesModified();
+}
+
+bool IndexDataConsumer::isAlreadyParsed(clang::FileID fileId, SourcesManager &sourcesManager)
+{
+ const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(fileId);
+ if (!fileEntry)
+ return false;
+ return sourcesManager.alreadyParsed(filePathId(fileEntry), fileEntry->getModificationTime());
+}
- return isParsedDeclaration || isParsedReference;
+void IndexDataConsumer::setPreprocessor(std::shared_ptr<clang::Preprocessor> preprocessor)
+{
+ preprocessor->addPPCallbacks(std::make_unique<FileStatusPreprocessorCallbacks>(
+ m_fileStatuses, m_filePathCache, m_sourceManager, m_filePathIndices));
}
-bool IndexDataConsumer::handleDeclOccurence(
- const clang::Decl *declaration,
- clang::index::SymbolRoleSet symbolRoles,
- llvm::ArrayRef<clang::index::SymbolRelation> /*symbolRelations*/,
- clang::SourceLocation sourceLocation,
- IndexDataConsumer::ASTNodeInfo /*astNodeInfo*/)
+bool IndexDataConsumer::handleDeclOccurence(const clang::Decl *declaration,
+ clang::index::SymbolRoleSet symbolRoles,
+ llvm::ArrayRef<clang::index::SymbolRelation> /*symbolRelations*/,
+ clang::SourceLocation sourceLocation,
+ IndexDataConsumer::ASTNodeInfo /*astNodeInfo*/)
{
const auto *namedDeclaration = clang::dyn_cast<clang::NamedDecl>(declaration);
if (namedDeclaration) {
@@ -137,7 +151,6 @@ bool IndexDataConsumer::handleDeclOccurence(
return true;
if (skipSymbol(m_sourceManager->getFileID(sourceLocation), symbolRoles))
-
return true;
SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
@@ -165,4 +178,64 @@ bool IndexDataConsumer::handleDeclOccurence(
return true;
}
+namespace {
+
+SourceLocationKind macroSymbolType(clang::index::SymbolRoleSet roles)
+{
+ if (roles & static_cast<clang::index::SymbolRoleSet>(clang::index::SymbolRole::Definition))
+ return SourceLocationKind::MacroDefinition;
+
+ if (roles & static_cast<clang::index::SymbolRoleSet>(clang::index::SymbolRole::Undefinition))
+ return SourceLocationKind::MacroUndefinition;
+
+ if (roles & static_cast<clang::index::SymbolRoleSet>(clang::index::SymbolRole::Reference))
+ return SourceLocationKind::MacroUsage;
+
+ return SourceLocationKind::None;
+}
+
+} // namespace
+
+bool IndexDataConsumer::handleMacroOccurence(const clang::IdentifierInfo *identifierInfo,
+ const clang::MacroInfo *macroInfo,
+ clang::index::SymbolRoleSet roles,
+ clang::SourceLocation sourceLocation)
+{
+ if (macroInfo && sourceLocation.isFileID()
+ && !isAlreadyParsed(m_sourceManager->getFileID(sourceLocation), m_macroSourcesManager)
+ && !isInSystemHeader(sourceLocation)) {
+ FilePathId fileId = filePathId(sourceLocation);
+ if (fileId.isValid()) {
+ auto macroName = identifierInfo->getName();
+ SymbolIndex globalId = toSymbolIndex(macroInfo);
+
+ auto found = m_symbolEntries.find(globalId);
+ if (found == m_symbolEntries.end()) {
+ Utils::optional<Utils::PathString> usr = generateUSR(macroName, sourceLocation);
+ if (usr) {
+ m_symbolEntries.emplace(std::piecewise_construct,
+ std::forward_as_tuple(globalId),
+ std::forward_as_tuple(std::move(*usr),
+ macroName,
+ SymbolKind::Macro));
+ }
+ }
+
+ m_sourceLocationEntries.emplace_back(globalId,
+ fileId,
+ lineColum(sourceLocation),
+ macroSymbolType(roles));
+ }
+ }
+
+ return true;
+}
+
+void IndexDataConsumer::finish()
+{
+ m_macroSourcesManager.updateModifiedTimeStamps();
+ m_symbolSourcesManager.updateModifiedTimeStamps();
+ m_filePathIndices.clear();
+}
+
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/indexdataconsumer.h b/src/tools/clangrefactoringbackend/source/indexdataconsumer.h
index 6db595391c..730ca12b23 100644
--- a/src/tools/clangrefactoringbackend/source/indexdataconsumer.h
+++ b/src/tools/clangrefactoringbackend/source/indexdataconsumer.h
@@ -26,6 +26,7 @@
#pragma once
#include "clangrefactoringbackend_global.h"
+#include "filestatus.h"
#include "sourcelocationentry.h"
#include "symbolentry.h"
#include "symbolsvisitorbase.h"
@@ -42,28 +43,48 @@ class IndexDataConsumer : public clang::index::IndexDataConsumer,
public:
IndexDataConsumer(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
+ FileStatuses &fileStatuses,
FilePathCachingInterface &filePathCache,
- SourcesManager &sourcesManager)
- : SymbolsVisitorBase(filePathCache, nullptr, sourcesManager),
- m_symbolEntries(symbolEntries),
- m_sourceLocationEntries(sourceLocationEntries)
+ SourcesManager &symbolSourcesManager,
+ SourcesManager &macroSourcesManager)
+ : SymbolsVisitorBase(filePathCache, nullptr, m_filePathIndices)
+ , m_symbolEntries(symbolEntries)
+ , m_sourceLocationEntries(sourceLocationEntries)
+ , m_fileStatuses(fileStatuses)
+ , m_symbolSourcesManager(symbolSourcesManager)
+ , m_macroSourcesManager(macroSourcesManager)
+
{}
IndexDataConsumer(const IndexDataConsumer &) = delete;
IndexDataConsumer &operator=(const IndexDataConsumer &) = delete;
+ void setPreprocessor(std::shared_ptr<clang::Preprocessor> preprocessor) override;
+
bool handleDeclOccurence(const clang::Decl *declaration,
clang::index::SymbolRoleSet symbolRoles,
llvm::ArrayRef<clang::index::SymbolRelation> symbolRelations,
clang::SourceLocation sourceLocation,
ASTNodeInfo astNodeInfo) override;
+ bool handleMacroOccurence(const clang::IdentifierInfo *identifierInfo,
+ const clang::MacroInfo *macroInfo,
+ clang::index::SymbolRoleSet roles,
+ clang::SourceLocation sourceLocation) override;
+
+ void finish() override;
+
private:
bool skipSymbol(clang::FileID fileId, clang::index::SymbolRoleSet symbolRoles);
+ bool isAlreadyParsed(clang::FileID fileId, SourcesManager &sourcesManager);
private:
+ FilePathIds m_filePathIndices;
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
+ FileStatuses &m_fileStatuses;
+ SourcesManager &m_symbolSourcesManager;
+ SourcesManager &m_macroSourcesManager;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h b/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h
index b25e43e483..ad37c8a3e9 100644
--- a/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h
+++ b/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h
@@ -31,7 +31,6 @@
namespace ClangBackEnd {
-
class RefactoringCompilationDatabase : public clang::tooling::CompilationDatabase
{
public:
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
index e0315c6626..1ee61eb67c 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
+++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
@@ -29,6 +29,7 @@
#include "symbolindexertaskqueue.h"
#include <commandlinebuilder.h>
+#include <environment.h>
#include <chrono>
#include <iostream>
@@ -66,7 +67,9 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface,
- ProjectPartsStorageInterface &projectPartsStorage)
+ ProjectPartsStorageInterface &projectPartsStorage,
+ ModifiedTimeCheckerInterface<SourceTimeStamps> &modifiedTimeChecker,
+ const Environment &environment)
: m_symbolIndexerTaskQueue(symbolIndexerTaskQueue)
, m_symbolStorage(symbolStorage)
, m_buildDependencyStorage(buildDependenciesStorage)
@@ -76,6 +79,8 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
, m_fileStatusCache(fileStatusCache)
, m_transactionInterface(transactionInterface)
, m_projectPartsStorage(projectPartsStorage)
+ , m_modifiedTimeChecker(modifiedTimeChecker)
+ , m_environment(environment)
{
pathWatcher.setNotifier(this);
}
@@ -88,45 +93,59 @@ void SymbolIndexer::updateProjectParts(ProjectPartContainers &&projectParts)
void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
{
- Sqlite::DeferredTransaction transaction{m_transactionInterface};
-
ProjectPartId projectPartId = projectPart.projectPartId;
- const Utils::optional<ProjectPartPch> optionalProjectPartPch
- = m_precompiledHeaderStorage.fetchPrecompiledHeader(projectPartId);
-
- transaction.commit();
-
- using Builder = CommandLineBuilder<ProjectPartContainer, Utils::SmallStringVector>;
- Builder commandLineBuilder{projectPart,
- projectPart.toolChainArguments,
- InputFileType::Source,
- {},
- {},
- optionalProjectPartPch ? FilePathView{optionalProjectPartPch->pchPath}
- : FilePathView{}};
std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
for (FilePathId sourcePathId : projectPart.sourcePathIds) {
- auto indexing = [arguments = commandLineBuilder.commandLine,
- sourcePathId,
- this](SymbolsCollectorInterface &symbolsCollector) {
- symbolsCollector.setFile(sourcePathId, arguments);
-
- bool success = symbolsCollector.collectSymbols();
-
- if (success) {
- Sqlite::ImmediateTransaction transaction{m_transactionInterface};
-
- m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
- symbolsCollector.sourceLocations());
- transaction.commit();
- }
- };
-
- symbolIndexerTask.emplace_back(sourcePathId, projectPartId, std::move(indexing));
+ SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(
+ sourcePathId);
+
+ if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) {
+ auto indexing = [projectPart,
+ sourcePathId,
+ preIncludeSearchPath = m_environment.preIncludeSearchPath(),
+ this](SymbolsCollectorInterface &symbolsCollector) {
+ auto collect = [&](const FilePath &pchPath) {
+ using Builder = CommandLineBuilder<ProjectPartContainer, Utils::SmallStringVector>;
+ Builder commandLineBuilder{projectPart,
+ projectPart.toolChainArguments,
+ InputFileType::Source,
+ {},
+ {},
+ pchPath,
+ preIncludeSearchPath};
+ symbolsCollector.setFile(sourcePathId, commandLineBuilder.commandLine);
+
+ return symbolsCollector.collectSymbols();
+ };
+
+ auto store = [&] {
+ Sqlite::ImmediateTransaction transaction{m_transactionInterface};
+ m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
+ m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
+ symbolsCollector.sourceLocations());
+ transaction.commit();
+ };
+
+ const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders(
+ projectPart.projectPartId);
+
+ if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) {
+ store();
+ } else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) {
+ store();
+ } else if (collect({})) {
+ store();
+ }
+ };
+
+ symbolIndexerTask.emplace_back(sourcePathId, projectPartId, std::move(indexing));
+ }
}
+ m_pathWatcher.updateIdPaths(
+ {{projectPartId, m_buildDependencyStorage.fetchSources(projectPartId)}});
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries();
}
@@ -135,11 +154,13 @@ void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {}
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
{
+ FilePathIds dependentSourcePathIds = m_symbolStorage.fetchDependentSourceIds(filePathIds);
+
std::vector<SymbolIndexerTask> symbolIndexerTask;
- symbolIndexerTask.reserve(filePathIds.size());
+ symbolIndexerTask.reserve(dependentSourcePathIds.size());
- for (FilePathId filePathId : filePathIds)
- updateChangedPath(filePathId, symbolIndexerTask);
+ for (FilePathId dependentSourcePathId : dependentSourcePathIds)
+ updateChangedPath(dependentSourcePathId, symbolIndexerTask);
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries();
@@ -155,35 +176,54 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
optionalArtefact = m_projectPartsStorage.fetchProjectPartArtefact(filePathId);
if (!optionalArtefact)
return;
-
- const Utils::optional<ProjectPartPch> optionalProjectPartPch
- = m_precompiledHeaderStorage.fetchPrecompiledHeader(optionalArtefact->projectPartId);
transaction.commit();
- const ProjectPartArtefact &artefact = *optionalArtefact;
+ ProjectPartId projectPartId = optionalArtefact->projectPartId;
- auto pchPath = optionalProjectPartPch ? optionalProjectPartPch->pchPath : FilePath{};
+ SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId);
- CommandLineBuilder<ProjectPartArtefact, Utils::SmallStringVector>
- builder{artefact, artefact.toolChainArguments, InputFileType::Source, {}, {}, pchPath};
+ auto indexing = [optionalArtefact = std::move(optionalArtefact),
+ filePathId,
+ preIncludeSearchPath = m_environment.preIncludeSearchPath(),
+ this](SymbolsCollectorInterface &symbolsCollector) {
+ auto collect = [&](const FilePath &pchPath) {
+ const ProjectPartArtefact &artefact = *optionalArtefact;
- auto indexing = [arguments = builder.commandLine, filePathId, this](
- SymbolsCollectorInterface &symbolsCollector) {
- symbolsCollector.setFile(filePathId, arguments);
+ using Builder = CommandLineBuilder<ProjectPartArtefact, Utils::SmallStringVector>;
+ Builder builder{artefact,
+ artefact.toolChainArguments,
+ InputFileType::Source,
+ {},
+ {},
+ pchPath,
+ preIncludeSearchPath};
- bool success = symbolsCollector.collectSymbols();
+ symbolsCollector.setFile(filePathId, builder.commandLine);
- if (success) {
- Sqlite::ImmediateTransaction transaction{m_transactionInterface};
+ return symbolsCollector.collectSymbols();
+ };
+ auto store = [&] {
+ Sqlite::ImmediateTransaction transaction{m_transactionInterface};
+ m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
-
transaction.commit();
+ };
+
+ const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders(
+ optionalArtefact->projectPartId);
+
+ if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) {
+ store();
+ } else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) {
+ store();
+ } else if (collect({})) {
+ store();
}
};
- symbolIndexerTask.emplace_back(filePathId, optionalArtefact->projectPartId, std::move(indexing));
+ symbolIndexerTask.emplace_back(filePathId, projectPartId, std::move(indexing));
}
bool SymbolIndexer::compilerMacrosOrIncludeSearchPathsAreDifferent(
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.h b/src/tools/clangrefactoringbackend/source/symbolindexer.h
index c398c0f2bf..64b442bf33 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexer.h
+++ b/src/tools/clangrefactoringbackend/source/symbolindexer.h
@@ -32,6 +32,7 @@
#include "clangpathwatcher.h"
#include <filecontainerv2.h>
+#include <modifiedtimecheckerinterface.h>
#include <precompiledheaderstorageinterface.h>
#include <projectpartcontainer.h>
#include <projectpartsstorageinterface.h>
@@ -39,6 +40,7 @@
namespace ClangBackEnd {
class SymbolsCollectorInterface;
+class Environment;
class SymbolIndexer final : public ClangPathWatcherNotifier
{
@@ -51,7 +53,9 @@ public:
FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface,
- ProjectPartsStorageInterface &projectPartsStorage);
+ ProjectPartsStorageInterface &projectPartsStorage,
+ ModifiedTimeCheckerInterface<SourceTimeStamps> &modifiedTimeChecker,
+ const Environment &environment);
void updateProjectParts(ProjectPartContainers &&projectParts);
void updateProjectPart(ProjectPartContainer &&projectPart);
@@ -81,6 +85,8 @@ private:
FileStatusCache &m_fileStatusCache;
Sqlite::TransactionInterface &m_transactionInterface;
ProjectPartsStorageInterface &m_projectPartsStorage;
+ ModifiedTimeCheckerInterface<SourceTimeStamps> &m_modifiedTimeChecker;
+ const Environment &m_environment;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h
index 7ca3513284..1f15f2ffaa 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h
+++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h
@@ -30,6 +30,7 @@
#include <filepathid.h>
#include <progresscounter.h>
+#include <sqlitedatabase.h>
#include <taskschedulerinterface.h>
#include <utils/algorithm.h>
@@ -38,10 +39,6 @@
#include <functional>
#include <vector>
-namespace Sqlite {
-class TransactionInterface;
-}
-
namespace ClangBackEnd {
class SymbolsCollectorInterface;
@@ -53,9 +50,11 @@ public:
using Task = SymbolIndexerTask::Callable;
SymbolIndexerTaskQueue(TaskSchedulerInterface<Task> &symbolIndexerTaskScheduler,
- ProgressCounter &progressCounter)
- : m_symbolIndexerScheduler(symbolIndexerTaskScheduler),
- m_progressCounter(progressCounter)
+ ProgressCounter &progressCounter,
+ Sqlite::DatabaseInterface &database)
+ : m_symbolIndexerScheduler(symbolIndexerTaskScheduler)
+ , m_progressCounter(progressCounter)
+ , m_database(database)
{}
void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks)
@@ -94,12 +93,21 @@ public:
void processEntries()
{
- uint taskCount = m_symbolIndexerScheduler.slotUsage().free;
+ auto slotUsage = m_symbolIndexerScheduler.slotUsage();
+ uint taskCount = slotUsage.free;
auto newEnd = std::prev(m_tasks.end(), std::min<int>(int(taskCount), int(m_tasks.size())));
m_symbolIndexerScheduler.addTasks({std::make_move_iterator(newEnd),
std::make_move_iterator(m_tasks.end())});
m_tasks.erase(newEnd, m_tasks.end());
+
+ if (m_tasks.empty() && slotUsage.used == 0) {
+ try {
+ m_database.walCheckpointFull();
+ } catch (Sqlite::Exception &exception) {
+ exception.printWarning();
+ }
+ }
}
void syncTasks();
@@ -108,6 +116,7 @@ private:
std::vector<SymbolIndexerTask> m_tasks;
TaskSchedulerInterface<Task> &m_symbolIndexerScheduler;
ProgressCounter &m_progressCounter;
+ Sqlite::DatabaseInterface &m_database;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h
index c942059bad..5c391503bf 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexing.h
+++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h
@@ -38,13 +38,16 @@
#include <precompiledheaderstorage.h>
#include <projectpartsstorage.h>
-#include <refactoringdatabaseinitializer.h>
#include <filepathcachingfwd.h>
+#include <modifiedtimechecker.h>
+#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
+#include <QDateTime>
+#include <QFileInfo>
#include <QFileSystemWatcher>
#include <thread>
@@ -82,7 +85,8 @@ public:
SymbolIndexing(Sqlite::Database &database,
FilePathCachingInterface &filePathCache,
const GeneratedFiles &generatedFiles,
- ProgressCounter::SetProgressCallback &&setProgressCallback)
+ ProgressCounter::SetProgressCallback &&setProgressCallback,
+ const Environment &environment)
: m_filePathCache(filePathCache)
, m_buildDependencyStorage(database)
, m_precompiledHeaderStorage(database)
@@ -90,6 +94,18 @@ public:
, m_symbolStorage(database)
, m_collectorManger(generatedFiles, database)
, m_progressCounter(std::move(setProgressCallback))
+ , m_indexer(m_indexerQueue,
+ m_symbolStorage,
+ m_buildDependencyStorage,
+ m_precompiledHeaderStorage,
+ m_sourceWatcher,
+ m_filePathCache,
+ m_fileStatusCache,
+ m_symbolStorage.database,
+ m_projectPartsStorage,
+ m_modifiedTimeChecker,
+ environment)
+ , m_indexerQueue(m_indexerScheduler, m_progressCounter, database)
, m_indexerScheduler(m_collectorManger,
m_indexerQueue,
m_progressCounter,
@@ -130,16 +146,14 @@ private:
FileStatusCache m_fileStatusCache{m_filePathCache};
SymbolsCollectorManager m_collectorManger;
ProgressCounter m_progressCounter;
- SymbolIndexer m_indexer{m_indexerQueue,
- m_symbolStorage,
- m_buildDependencyStorage,
- m_precompiledHeaderStorage,
- m_sourceWatcher,
- m_filePathCache,
- m_fileStatusCache,
- m_symbolStorage.database,
- m_projectPartsStorage};
- SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler, m_progressCounter};
+ std::function<TimeStamp(FilePathView filePath)> getModifiedTime{
+ [&](ClangBackEnd::FilePathView path) -> TimeStamp {
+ return QFileInfo(QString(path)).lastModified().toSecsSinceEpoch();
+ }};
+ ModifiedTimeChecker<ClangBackEnd::SourceTimeStamps> m_modifiedTimeChecker{getModifiedTime,
+ m_filePathCache};
+ SymbolIndexer m_indexer;
+ SymbolIndexerTaskQueue m_indexerQueue;
SymbolIndexerTaskScheduler m_indexerScheduler;
};
diff --git a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp
index f8782b405b..eddcf683c7 100644
--- a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp
+++ b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp
@@ -93,7 +93,7 @@ std::unique_ptr<clang::ASTConsumer> SymbolLocationFinderAction::newASTConsumer()
consumer->setSourceLocations(&m_sourceLocations);
- return std::move(consumer);
+ return consumer;
}
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
index 188d6fd207..071837ac52 100644
--- a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
+++ b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
@@ -32,10 +32,14 @@
namespace ClangBackEnd {
SymbolsCollector::SymbolsCollector(Sqlite::Database &database)
- : m_filePathCache(database),
- m_indexDataConsumer(std::make_shared<IndexDataConsumer>(m_symbolEntries, m_sourceLocationEntries, m_filePathCache, m_sourcesManager)),
- m_collectSymbolsAction(m_indexDataConsumer),
- m_collectMacrosSourceFileCallbacks(m_symbolEntries, m_sourceLocationEntries, m_filePathCache, m_sourcesManager)
+ : m_filePathCache(database)
+ , m_indexDataConsumer(std::make_shared<IndexDataConsumer>(m_symbolEntries,
+ m_sourceLocationEntries,
+ m_fileStatuses,
+ m_filePathCache,
+ m_symbolSourcesManager,
+ m_macroSourcesManager))
+ , m_collectSymbolsAction(m_indexDataConsumer)
{
}
@@ -43,7 +47,6 @@ void SymbolsCollector::addFiles(const FilePathIds &filePathIds,
const Utils::SmallStringVector &arguments)
{
m_clangTool.addFiles(m_filePathCache.filePaths(filePathIds), arguments);
- m_collectMacrosSourceFileCallbacks.addSourceFiles(filePathIds);
}
void SymbolsCollector::setFile(FilePathId filePathId, const Utils::SmallStringVector &arguments)
@@ -58,90 +61,73 @@ void SymbolsCollector::setUnsavedFiles(const V2::FileContainers &unsavedFiles)
void SymbolsCollector::clear()
{
- m_indexDataConsumer->clear();
- m_collectMacrosSourceFileCallbacks.clear();
m_symbolEntries.clear();
m_sourceLocationEntries.clear();
+ m_fileStatuses.clear();
m_clangTool = ClangTool();
}
-template <typename Factory>
-std::unique_ptr<clang::tooling::FrontendActionFactory>
-newFrontendActionFactory(Factory *consumerFactory,
- clang::tooling::SourceFileCallbacks *sourceFileCallbacks)
+std::unique_ptr<clang::tooling::FrontendActionFactory> newFrontendActionFactory(CollectSymbolsAction *action)
{
class FrontendActionFactoryAdapter : public clang::tooling::FrontendActionFactory
{
public:
- explicit FrontendActionFactoryAdapter(Factory *consumerFactory,
- clang::tooling::SourceFileCallbacks *sourceFileCallbacks)
- : m_consumerFactory(consumerFactory),
- m_sourceFileCallbacks(sourceFileCallbacks)
+ explicit FrontendActionFactoryAdapter(CollectSymbolsAction *consumerFactory)
+ : m_action(consumerFactory)
{}
- clang::FrontendAction *create() override {
- return new ConsumerFactoryAdaptor(m_consumerFactory, m_sourceFileCallbacks);
- }
+ clang::FrontendAction *create() override { return new AdaptorAction(m_action); }
private:
- class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
+ class AdaptorAction : public clang::ASTFrontendAction
+ {
public:
- ConsumerFactoryAdaptor(Factory *consumerFactory,
- clang::tooling::SourceFileCallbacks *sourceFileCallbacks)
- : m_consumerFactory(consumerFactory),
- m_sourceFileCallbacks(sourceFileCallbacks)
+ AdaptorAction(CollectSymbolsAction *action)
+ : m_action(action)
{}
- std::unique_ptr<clang::ASTConsumer>
- CreateASTConsumer(clang::CompilerInstance &instance, StringRef inFile) override {
- return m_consumerFactory->newASTConsumer(instance, inFile);
+ std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &instance,
+ llvm::StringRef inFile) override
+ {
+ return m_action->newASTConsumer(instance, inFile);
}
- protected:
- bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
+ bool BeginInvocation(clang::CompilerInstance &instance) override
{
- compilerInstance.getLangOpts().DelayedTemplateParsing = false;
- compilerInstance.getPreprocessorOpts().AllowPCHWithCompilerErrors = true;
-
- return clang::ASTFrontendAction::BeginInvocation(compilerInstance);
+ return m_action->BeginInvocation(instance);
}
-
- bool BeginSourceFileAction(clang::CompilerInstance &compilerInstance) override
+ bool BeginSourceFileAction(clang::CompilerInstance &instance) override
{
- compilerInstance.getPreprocessor().SetSuppressIncludeNotFoundError(true);
-
- if (!clang::ASTFrontendAction::BeginSourceFileAction(compilerInstance))
- return false;
- if (m_sourceFileCallbacks)
- return m_sourceFileCallbacks->handleBeginSource(compilerInstance);
- return true;
+ return m_action->BeginSourceFileAction(instance);
}
- void EndSourceFileAction() override
+ bool PrepareToExecuteAction(clang::CompilerInstance &instance) override
{
- if (m_sourceFileCallbacks)
- m_sourceFileCallbacks->handleEndSource();
- clang::ASTFrontendAction::EndSourceFileAction();
+ return m_action->PrepareToExecuteAction(instance);
}
+ void ExecuteAction() override { m_action->ExecuteAction(); }
+ void EndSourceFileAction() override { m_action->EndSourceFileAction(); }
+
+ bool hasPCHSupport() const override { return m_action->hasPCHSupport(); }
+ bool hasASTFileSupport() const override { return m_action->hasASTFileSupport(); }
+ bool hasIRSupport() const override { return false; }
+ bool hasCodeCompletionSupport() const override { return false; }
private:
- Factory *m_consumerFactory;
- clang::tooling::SourceFileCallbacks *m_sourceFileCallbacks;
+ CollectSymbolsAction *m_action;
};
- Factory *m_consumerFactory;
- clang::tooling::SourceFileCallbacks *m_sourceFileCallbacks;
+ CollectSymbolsAction *m_action;
};
- return std::unique_ptr<clang::tooling::FrontendActionFactory>(
- new FrontendActionFactoryAdapter(consumerFactory, sourceFileCallbacks));
+ return std::unique_ptr<clang::tooling::FrontendActionFactory>(
+ new FrontendActionFactoryAdapter(action));
}
bool SymbolsCollector::collectSymbols()
{
auto tool = m_clangTool.createTool();
- auto actionFactory = ClangBackEnd::newFrontendActionFactory(&m_collectSymbolsAction,
- &m_collectMacrosSourceFileCallbacks);
+ auto actionFactory = ClangBackEnd::newFrontendActionFactory(&m_collectSymbolsAction);
return tool.run(actionFactory.get()) != 1;
}
@@ -160,24 +146,9 @@ const SourceLocationEntries &SymbolsCollector::sourceLocations() const
return m_sourceLocationEntries;
}
-const FilePathIds &SymbolsCollector::sourceFiles() const
-{
- return m_collectMacrosSourceFileCallbacks.sourceFiles();
-}
-
-const UsedMacros &SymbolsCollector::usedMacros() const
-{
- return m_collectMacrosSourceFileCallbacks.usedMacros();
-}
-
const FileStatuses &SymbolsCollector::fileStatuses() const
{
- return m_collectMacrosSourceFileCallbacks.fileStatuses();
-}
-
-const SourceDependencies &SymbolsCollector::sourceDependencies() const
-{
- return m_collectMacrosSourceFileCallbacks.sourceDependencies();
+ return m_fileStatuses;
}
bool SymbolsCollector::isUsed() const
diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.h b/src/tools/clangrefactoringbackend/source/symbolscollector.h
index b37647e969..cc7ca4396c 100644
--- a/src/tools/clangrefactoringbackend/source/symbolscollector.h
+++ b/src/tools/clangrefactoringbackend/source/symbolscollector.h
@@ -58,10 +58,7 @@ public:
const SymbolEntries &symbols() const override;
const SourceLocationEntries &sourceLocations() const override;
- const FilePathIds &sourceFiles() const override;
- const UsedMacros &usedMacros() const override;
const FileStatuses &fileStatuses() const override;
- const SourceDependencies &sourceDependencies() const override;
bool isUsed() const override;
void setIsUsed(bool isUsed) override;
@@ -71,10 +68,11 @@ private:
ClangTool m_clangTool;
SymbolEntries m_symbolEntries;
SourceLocationEntries m_sourceLocationEntries;
+ FileStatuses m_fileStatuses;
std::shared_ptr<IndexDataConsumer> m_indexDataConsumer;
CollectSymbolsAction m_collectSymbolsAction;
- CollectMacrosSourceFileCallbacks m_collectMacrosSourceFileCallbacks;
- SourcesManager m_sourcesManager;
+ SourcesManager m_symbolSourcesManager;
+ SourcesManager m_macroSourcesManager;
bool m_isUsed = false;
};
diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h
index 94b3142371..07b5de223c 100644
--- a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h
+++ b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h
@@ -48,10 +48,7 @@ public:
virtual const SymbolEntries &symbols() const = 0;
virtual const SourceLocationEntries &sourceLocations() const = 0;
- virtual const FilePathIds &sourceFiles() const = 0;
- virtual const UsedMacros &usedMacros() const = 0;
virtual const FileStatuses &fileStatuses() const = 0;
- virtual const SourceDependencies &sourceDependencies() const = 0;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h
index 9dffe48c96..3d7d4c9784 100644
--- a/src/tools/clangrefactoringbackend/source/symbolstorage.h
+++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h
@@ -41,7 +41,7 @@
namespace ClangBackEnd {
-template <typename DatabaseType>
+template<typename DatabaseType = Sqlite::Database>
class SymbolStorage final : public SymbolStorageInterface
{
using Database = DatabaseType;
@@ -70,6 +70,93 @@ public:
deleteNewLocationsTable();
}
+ void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) override
+ {
+ try {
+ Sqlite::ImmediateTransaction transaction{database};
+
+ for (FilePathId filePathId : filePathIds) {
+ inserOrUpdateIndexingTimesStampStatement.write(filePathId.filePathId,
+ indexingTimeStamp.value);
+ }
+
+ transaction.commit();
+ } catch (const Sqlite::StatementIsBusy &) {
+ insertOrUpdateIndexingTimeStamps(filePathIds, indexingTimeStamp);
+ }
+ }
+
+ void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) override
+ {
+ for (FileStatus fileStatus : fileStatuses) {
+ inserOrUpdateIndexingTimesStampStatement.write(fileStatus.filePathId.filePathId,
+ fileStatus.lastModified);
+ }
+ }
+
+ SourceTimeStamps fetchIndexingTimeStamps() const override
+ {
+ try {
+ Sqlite::DeferredTransaction transaction{database};
+
+ auto timeStamps = fetchIndexingTimeStampsStatement.template values<SourceTimeStamp, 2>(
+ 1024);
+
+ transaction.commit();
+
+ return timeStamps;
+ } catch (const Sqlite::StatementIsBusy &) {
+ return fetchIndexingTimeStamps();
+ }
+ }
+
+ SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const override
+ {
+ try {
+ Sqlite::DeferredTransaction transaction{database};
+
+ auto timeStamps = fetchIncludedIndexingTimeStampsStatement
+ .template values<SourceTimeStamp, 2>(1024, sourcePathId.filePathId);
+
+ transaction.commit();
+
+ return timeStamps;
+ } catch (const Sqlite::StatementIsBusy &) {
+ return fetchIncludedIndexingTimeStamps(sourcePathId);
+ }
+ }
+
+ FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const override
+ {
+ try {
+ FilePathIds dependentSourceIds;
+
+ Sqlite::DeferredTransaction transaction{database};
+
+ for (FilePathId sourcePathId : sourcePathIds) {
+ FilePathIds newDependentSourceIds;
+ newDependentSourceIds.reserve(dependentSourceIds.size() + 1024);
+
+ auto newIds = fetchDependentSourceIdsStatement
+ .template values<FilePathId>(1024, sourcePathId.filePathId);
+
+ std::set_union(dependentSourceIds.begin(),
+ dependentSourceIds.end(),
+ newIds.begin(),
+ newIds.end(),
+ std::back_inserter(newDependentSourceIds));
+
+ dependentSourceIds = std::move(newDependentSourceIds);
+ }
+
+ transaction.commit();
+
+ return dependentSourceIds;
+ } catch (const Sqlite::StatementIsBusy &) {
+ return fetchDependentSourceIds(sourcePathIds);
+ }
+ }
+
void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries)
{
WriteStatement &statement = insertSymbolsToNewSymbolsStatement;
@@ -191,6 +278,25 @@ public:
database};
WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", database};
WriteStatement deleteNewLocationsTableStatement{"DELETE FROM newLocations", database};
+ WriteStatement inserOrUpdateIndexingTimesStampStatement{
+ "INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON "
+ "CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002",
+ database};
+ mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{
+ "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
+ "dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
+ "sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, "
+ "indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId",
+ database};
+ mutable ReadStatement fetchIndexingTimeStampsStatement{
+ "SELECT sourceId, indexingTimeStamp FROM fileStatuses", database};
+ mutable ReadStatement fetchDependentSourceIdsStatement{
+ "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
+ "sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE "
+ "sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId "
+ "FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM "
+ "sourceDependencies) ORDER BY sourceId",
+ database};
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
index 1d04c4d168..d3c8035e8c 100644
--- a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
+++ b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
@@ -28,6 +28,9 @@
#include "sourcelocationentry.h"
#include "symbolentry.h"
+#include <filestatus.h>
+#include <sourceentry.h>
+
#include <compilermacro.h>
#include <sqlitetransaction.h>
@@ -45,6 +48,11 @@ public:
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations)
= 0;
+ virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0;
+ virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0;
+ virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0;
+ virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0;
+ virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0;
protected:
~SymbolStorageInterface() = default;
diff --git a/src/tools/clangrefactoringbackend/source/symbolsvisitorbase.h b/src/tools/clangrefactoringbackend/source/symbolsvisitorbase.h
index ff2142f40e..7b63cb223e 100644
--- a/src/tools/clangrefactoringbackend/source/symbolsvisitorbase.h
+++ b/src/tools/clangrefactoringbackend/source/symbolsvisitorbase.h
@@ -46,10 +46,10 @@ class SymbolsVisitorBase
public:
SymbolsVisitorBase(const FilePathCachingInterface &filePathCache,
const clang::SourceManager *sourceManager,
- SourcesManager &sourcesManager)
- : m_filePathCache(filePathCache),
- m_sourceManager(sourceManager),
- m_sourcesManager(sourcesManager)
+ FilePathIds &filePathIndices)
+ : m_filePathCache(filePathCache)
+ , m_sourceManager(sourceManager)
+ , m_filePathIndices(filePathIndices)
{}
FilePathId filePathId(clang::SourceLocation sourceLocation)
@@ -60,25 +60,6 @@ public:
return filePathId(fileEntry);
}
- bool dependentFilesAreModified()
- {
- return m_sourcesManager.dependentFilesModified();
- }
-
- bool isAlreadyParsed(clang::FileID fileId)
- {
- const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(fileId);
- if (!fileEntry)
- return false;
- return m_sourcesManager.alreadyParsed(filePathId(fileEntry),
- fileEntry->getModificationTime());
- }
-
- bool alreadyParsed(clang::SourceLocation sourceLocation)
- {
- return isAlreadyParsed(m_sourceManager->getFileID(sourceLocation));
- }
-
FilePathId filePathId(const clang::FileEntry *fileEntry)
{
if (fileEntry) {
@@ -156,22 +137,26 @@ public:
return isSystem(m_sourceManager->getSLocEntry(fileId).getFile().getFileCharacteristic());
}
+ bool isInSystemHeader(clang::SourceLocation sourceLocation) const
+ {
+ return m_sourceManager->isInSystemHeader(sourceLocation);
+ }
+
static
bool isSystem(clang::SrcMgr::CharacteristicKind kind)
{
return clang::SrcMgr::isSystem(kind);
}
- void clear()
- {
- m_filePathIndices.clear();
- }
+ const FilePathCachingInterface &filePathCache() const { return m_filePathCache; }
+ const clang::SourceManager *sourceManager() const { return m_sourceManager; }
protected:
- std::vector<FilePathId> m_filePathIndices;
const FilePathCachingInterface &m_filePathCache;
const clang::SourceManager *m_sourceManager = nullptr;
- SourcesManager &m_sourcesManager;
+
+private:
+ FilePathIds &m_filePathIndices;
};
} // namespace ClangBackend
diff --git a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
index 59aab237ec..ad69adae56 100644
--- a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
+++ b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
@@ -423,12 +423,11 @@ public:
static const char *const pretty[] = {"warning", "error", "fatal"};
- QString str;
- str.sprintf("%s:%d:%d: When parsing as %s: %s: ", fileName->chars(), line, column,
+ QString str = QString::asprintf("%s:%d:%d: When parsing as %s: %s: ", fileName->chars(), line, column,
parseModeToString(m_parseMode).toUtf8().constData(), pretty[level]);
m_errorString->append(str.toUtf8());
- str.vsprintf(format, ap);
+ str += QString::vasprintf(format, ap);
m_errorString->append(str.toUtf8());
m_errorString->append('\n');
}
diff --git a/src/tools/cplusplus-shared/utils.cpp b/src/tools/cplusplus-shared/utils.cpp
index 48178d7cf9..1373d5f6f9 100644
--- a/src/tools/cplusplus-shared/utils.cpp
+++ b/src/tools/cplusplus-shared/utils.cpp
@@ -94,7 +94,7 @@ SystemPreprocessor::SystemPreprocessor(bool verbose)
QMapIterator<QString, QString> i(m_knownCompilers);
while (i.hasNext()) {
i.next();
- const Utils::FileName executablePath
+ const Utils::FilePath executablePath
= Utils::Environment::systemEnvironment().searchInPath(i.key());
if (!executablePath.isEmpty()) {
m_compiler = i.key();
diff --git a/src/tools/iconlister/iconlister.cpp b/src/tools/iconlister/iconlister.cpp
index 509214cc25..522cd1891b 100644
--- a/src/tools/iconlister/iconlister.cpp
+++ b/src/tools/iconlister/iconlister.cpp
@@ -327,6 +327,8 @@ void IconLister::addProjectExplorerIcons()
""},
{QIcon(":/projectexplorer/images/fileoverlay_h.png"), "fileoverlay_h.png", prefix,
""},
+ {QIcon(":/projectexplorer/images/fileoverlay_py.png"), "fileoverlay_py.png", prefix,
+ ""},
{QIcon(":/projectexplorer/images/fileoverlay_unknown.png"), "fileoverlay_unknown.png", prefix,
""},
diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg
index 86fcbb48d0..cb6e4836af 100644
--- a/src/tools/icons/qtcreatoricons.svg
+++ b/src/tools/icons/qtcreatoricons.svg
@@ -14,7 +14,7 @@
height="600"
id="svg2"
version="1.1"
- inkscape:version="0.92.1 r15371"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="qtcreatoricons.svg">
<defs
id="defs4">
@@ -561,19 +561,11 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="4"
- inkscape:cx="407.31417"
- inkscape:cy="170.08332"
inkscape:document-units="px"
- inkscape:current-layer="g4718"
showgrid="true"
showguides="true"
inkscape:guide-bbox="true"
- inkscape:window-width="2880"
- inkscape:window-height="1503"
- inkscape:window-x="-13"
- inkscape:window-y="527"
- inkscape:window-maximized="1"
+ inkscape:window-maximized="0"
inkscape:snap-grids="true">
<inkscape:grid
type="xygrid"
@@ -612,7 +604,7 @@
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
- position="0,80"
+ position="232,80"
id="guide4545"
inkscape:locked="false" />
<sodipodi:guide
@@ -3453,6 +3445,207 @@
width="100%"
height="100%" />
</g>
+ <g
+ transform="translate(128)"
+ id="src/libs/utils/images/settings">
+ <use
+ transform="translate(1740,132)"
+ height="100%"
+ width="100%"
+ id="use4105"
+ xlink:href="#backgroundRect"
+ y="0"
+ x="0" />
+ <circle
+ style="fill:none;stroke:#000000;stroke-width:1.75"
+ id="path4133"
+ cx="1732"
+ cy="576"
+ r="3.5" />
+ <path
+ style="fill:#000000"
+ d="m 1733.25,579.5 -0.5,2.5 h -1.5 l -0.5,-2.5 z"
+ id="path4135"
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="5.25"
+ sodipodi:nodetypes="ccccc" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4135"
+ inkscape:transform-center-y="3.5355339"
+ id="use4137"
+ transform="rotate(45,1732,576)"
+ width="100%"
+ height="100%"
+ inkscape:transform-center-x="3.5355339" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4135"
+ id="use4139"
+ transform="rotate(90,1732,576)"
+ width="100%"
+ height="100%"
+ inkscape:transform-center-x="5.25" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4135"
+ inkscape:transform-center-y="-3.5355339"
+ id="use4141"
+ transform="rotate(135,1732,576)"
+ width="100%"
+ height="100%"
+ inkscape:transform-center-x="3.5355339" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4135"
+ inkscape:transform-center-y="-5.25"
+ id="use4143"
+ transform="rotate(-180,1732,576)"
+ width="100%"
+ height="100%" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4135"
+ inkscape:transform-center-y="-3.5355339"
+ id="use4145"
+ transform="rotate(-135,1732,576)"
+ width="100%"
+ height="100%"
+ inkscape:transform-center-x="-3.5355339" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4135"
+ id="use4147"
+ transform="rotate(-90,1732,576)"
+ width="100%"
+ height="100%"
+ inkscape:transform-center-x="-5.25" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4135"
+ inkscape:transform-center-y="3.5355339"
+ id="use4149"
+ transform="rotate(-45,1732,576)"
+ width="100%"
+ height="100%"
+ inkscape:transform-center-x="-3.5355339" />
+ </g>
+ <g
+ style="display:inline"
+ transform="translate(144)"
+ id="src/plugins/languageclient/images/languageclient">
+ <use
+ transform="translate(1740,132)"
+ height="100%"
+ width="100%"
+ id="use4105-8"
+ xlink:href="#backgroundRect"
+ y="0"
+ x="0" />
+ <ellipse
+ style="fill:none;stroke:#000000"
+ id="path4643-3"
+ cx="1729"
+ cy="580.5"
+ rx="3.5"
+ ry="2" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4643-3"
+ id="use4684-9"
+ width="100%"
+ height="100%"
+ transform="translate(0,-5)" />
+ <rect
+ style="fill:#ffffff"
+ id="rect4670-9"
+ width="8"
+ height="2.5"
+ x="1725"
+ y="578" />
+ <path
+ style="fill:none;stroke:#000000"
+ d="m 1725.5,575.5 v 5"
+ id="path4672-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4672-0"
+ id="use4686-9"
+ transform="translate(7)"
+ width="100%"
+ height="100%" />
+ <path
+ style="display:inline;fill:#000000"
+ d="m 1733,569 h 4 c 1,0 2,1 2,2 v 3 c 0,2.5 -1.5,2.5 -5.5,4 l 2,-2 h -2.5 c -1,0 -2,-1 -2,-2 v -3 c 0,-1 1,-2 2,-2 z"
+ id="path4639-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="display:inline;fill:none;stroke:#ffffff"
+ d="m 1734.25,570.75 -1.75,1.75 1.75,1.75"
+ id="path4676-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <use
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#path4676-1"
+ id="use4682-2"
+ transform="matrix(-1,0,0,1,3470,0)"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="display:inline"
+ transform="translate(160)"
+ id="src/libs/utils/images/toggleprogressdetails">
+ <use
+ style="display:inline"
+ transform="translate(1740,132)"
+ height="100%"
+ width="100%"
+ id="use4105-8-8"
+ xlink:href="#backgroundRect"
+ y="0"
+ x="0" />
+ <rect
+ style="display:inline;fill:#707070"
+ id="rect2566"
+ width="8"
+ height="2"
+ x="1726"
+ y="577" />
+ <rect
+ style="display:inline;fill:none;stroke:#000000"
+ id="rect2564"
+ width="13"
+ height="3"
+ x="1725.5"
+ y="576.5"
+ ry="1"
+ rx="1" />
+ <use
+ transform="matrix(1,0,0,-1,1529,1167)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#expandarrow"
+ id="use2507"
+ width="100%"
+ height="100%" />
+ </g>
</g>
<g
inkscape:groupmode="layer"
@@ -4963,7 +5156,7 @@
</g>
<g
style="display:inline"
- id="src/plugins/autotest/images/sort"
+ id="src/libs/utils/images/sort_alphabetically"
transform="translate(32,0)">
<rect
y="568"
@@ -6439,10 +6632,28 @@
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
- id="path4784-17"
+ id="expandarrow"
d="m 210,595 -2.5,2.5 -2.5,-2.5 z"
style="fill:#000000;fill-opacity:1;stroke:none" />
</g>
+ <g
+ id="src/libs/utils/images/pinned">
+ <use
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use5933-0-2-3"
+ width="100%"
+ height="100%"
+ transform="translate(361,148)" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path6750"
+ d="m 347,597.33936 0.60019,0.60645 3.49128,-3.49127 3.09695,3.09695 c 0.29088,-0.96173 0.20375,-2.0863 -0.1875,-3.07155 l 3.68179,-3.68179 0.55968,0.52841 0.75761,-0.75762 -4.51473,-4.51475 -0.80193,0.80194 0.53076,0.51509 -3.60205,3.60206 c -1.04768,-0.37523 -2.22553,-0.48941 -3.20237,-0.15625 l 3.0615,3.0615 z"
+ style="fill:#000000" />
+ </g>
</g>
<g
inkscape:groupmode="layer"
@@ -8914,6 +9125,30 @@
</g>
</g>
<g
+ transform="translate(111)"
+ id="src/plugins/projectexplorer/images/fileoverlay_py">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#transparentBackgroundRect"
+ id="use2479"
+ width="100%"
+ height="100%"
+ transform="translate(113,68)" />
+ <path
+ style="opacity:0.75;fill:#ffffff"
+ d="m 104,535.99991 c 0.5,-9e-5 1,-0.49991 1,-0.99991 v -1 c 1,0 1.58286,0 2.58286,0 -0.5,0.5 -0.2217,1 0.0332,1.22379 L 108.50001,536 h 0.74644 c 0.27171,0 0.55533,-0.30177 0.75356,-0.5 l 2.24999,-2.25 c 0.25054,-0.25054 0.75001,-0.85547 0.75001,-1.41406 V 530 c 0,-0.5 -0.5,-1 -1,-1 0,0 -8.49999,0 -9,0 -0.50001,0 -1,0.5 -1,1 v 5 c 0,0.5 0.49999,1 0.99999,1 0.5,0 0.5,0 1,-9e-5 z"
+ id="path5194-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="zsccscscssszzsszz" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0"
+ d="m 103.49859,532.5 v -2 c 1.02427,-0.0193 2.92783,-0.45188 3,1 0.0722,1.45188 -2,1 -3,1 z M 111.5,530 v 1.73815 c -0.36757,0.7971 -1.47164,1.64275 -3,3.26185 m 0,-5 v 1.97707 c 0.22805,0.82162 1.35083,0.8693 2,1.52293 m -7,-3.5 v 5"
+ style="fill:none;stroke:#1986a0;stroke-opacity:1"
+ id="path5210-3" />
+ </g>
+ <g
id="src/libs/utils/images/filesave">
<rect
style="display:inline;fill:#ffffff;fill-opacity:1"
diff --git a/src/tools/iostool/CMakeLists.txt b/src/tools/iostool/CMakeLists.txt
new file mode 100644
index 0000000000..d8bd23fe3f
--- /dev/null
+++ b/src/tools/iostool/CMakeLists.txt
@@ -0,0 +1,24 @@
+add_qtc_executable(iostool
+ DESTINATION ${IDE_LIBEXEC_PATH}/ios
+ DEPENDS
+ Qt5::Gui
+ Qt5::Xml
+ Qt5::Network
+ ${FWCoreFoundation}
+ ${FWCoreServices}
+ ${FWIOKit}
+ ${FWSecurity}
+ ${FWSystemConfiguration}
+ SOURCES
+ Info.plist
+ main.cpp
+ iosdevicemanager.cpp iosdevicemanager.h
+)
+
+if (TARGET iostool)
+ if (CMAKE_VERSION VERSION_LESS 3.13)
+ target_link_libraries(iostool "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/Info.plist")
+ else()
+ target_link_options(iostool PRIVATE "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/Info.plist")
+ endif()
+endif()
diff --git a/src/tools/iostool/main.cpp b/src/tools/iostool/main.cpp
index e99fe0dcb5..f62c0c6180 100644
--- a/src/tools/iostool/main.cpp
+++ b/src/tools/iostool/main.cpp
@@ -227,7 +227,7 @@ void Relayer::setClientSocket(QTcpSocket *clientSocket)
m_clientSocket = clientSocket;
if (m_clientSocket) {
connect(m_clientSocket,
- static_cast<void (QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
+ QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
this, &Relayer::handleClientHasError);
connect(m_clientSocket, &QAbstractSocket::disconnected,
this, [this](){server()->removeRelayConnection(this);});
diff --git a/src/tools/perfparser b/src/tools/perfparser
-Subproject 25ddba75f0767ef1150c3896fde5c50bc65147c
+Subproject 02b36dd2c5fe4d1cf2970bc396fa665b199463d
diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt
new file mode 100644
index 0000000000..8eda7bf132
--- /dev/null
+++ b/src/tools/qml2puppet/CMakeLists.txt
@@ -0,0 +1,136 @@
+set(SRCDIR "${CMAKE_SOURCE_DIR}/share/qtcreator/qml/qmlpuppet")
+
+set(DESTDIR "${IDE_LIBEXEC_PATH}")
+if (APPLE)
+ string(APPEND DESTDIR "/qmldesigner")
+endif()
+
+add_qtc_executable(qml2puppet
+ DEPENDS
+ Qt5::CorePrivate Qt5::Widgets Qt5::QmlPrivate
+ Qt5::QuickPrivate Qt5::Network Qt5::GuiPrivate
+ SOURCES
+ "${SRCDIR}/qml2puppet/qml2puppetmain.cpp"
+ "${SRCDIR}/qmlpuppet.qrc"
+ DESTINATION ${DESTDIR}
+)
+
+extend_qtc_executable(qml2puppet
+ SOURCES_PREFIX "${SRCDIR}/commands"
+ SOURCES
+ changeauxiliarycommand.cpp changeauxiliarycommand.h
+ changebindingscommand.cpp changebindingscommand.h
+ changefileurlcommand.cpp changefileurlcommand.h
+ changeidscommand.cpp changeidscommand.h
+ changenodesourcecommand.cpp changenodesourcecommand.h
+ changestatecommand.cpp changestatecommand.h
+ changevaluescommand.cpp changevaluescommand.h
+ childrenchangedcommand.cpp childrenchangedcommand.h
+ clearscenecommand.cpp clearscenecommand.h
+ completecomponentcommand.cpp completecomponentcommand.h
+ componentcompletedcommand.cpp componentcompletedcommand.h
+ createinstancescommand.cpp createinstancescommand.h
+ createscenecommand.cpp createscenecommand.h
+ debugoutputcommand.cpp debugoutputcommand.h
+ endpuppetcommand.cpp endpuppetcommand.h
+ informationchangedcommand.cpp informationchangedcommand.h
+ pixmapchangedcommand.cpp pixmapchangedcommand.h
+ puppetalivecommand.cpp puppetalivecommand.h
+ removeinstancescommand.cpp removeinstancescommand.h
+ removepropertiescommand.cpp removepropertiescommand.h
+ removesharedmemorycommand.cpp removesharedmemorycommand.h
+ reparentinstancescommand.cpp reparentinstancescommand.h
+ statepreviewimagechangedcommand.cpp statepreviewimagechangedcommand.h
+ synchronizecommand.cpp synchronizecommand.h
+ tokencommand.cpp tokencommand.h
+ valueschangedcommand.cpp
+)
+
+extend_qtc_executable(qml2puppet
+ SOURCES_PREFIX "${SRCDIR}/container"
+ SOURCES
+ addimportcontainer.cpp addimportcontainer.h
+ idcontainer.cpp idcontainer.h
+ imagecontainer.cpp imagecontainer.h
+ informationcontainer.cpp informationcontainer.h
+ instancecontainer.cpp instancecontainer.h
+ mockuptypecontainer.cpp mockuptypecontainer.h
+ propertyabstractcontainer.cpp propertyabstractcontainer.h
+ propertybindingcontainer.cpp propertybindingcontainer.h
+ propertyvaluecontainer.cpp propertyvaluecontainer.h
+ reparentcontainer.cpp reparentcontainer.h
+ sharedmemory.h
+)
+
+extend_qtc_executable(qml2puppet
+ CONDITION UNIX
+ SOURCES_PREFIX "${SRCDIR}/container"
+ SOURCES
+ sharedmemory_unix.cpp
+)
+extend_qtc_executable(qml2puppet
+ CONDITION UNIX AND (NOT APPLE)
+ DEPENDS rt
+)
+extend_qtc_executable(qml2puppet
+ CONDITION NOT UNIX
+ SOURCES_PREFIX "${SRCDIR}/container"
+ SOURCES
+ sharedmemory_qt.cpp
+)
+
+extend_qtc_executable(qml2puppet
+ SOURCES_PREFIX "${SRCDIR}/instances"
+ SOURCES
+ nodeinstanceclientproxy.cpp nodeinstanceclientproxy.h
+)
+
+extend_qtc_executable(qml2puppet
+ SOURCES_PREFIX "${SRCDIR}/interfaces"
+ SOURCES
+ commondefines.h
+ nodeinstanceclientinterface.h
+ nodeinstanceglobal.h
+ nodeinstanceserverinterface.cpp nodeinstanceserverinterface.h
+)
+
+extend_qtc_executable(qml2puppet
+ SOURCES_PREFIX "${SRCDIR}/qml2puppet/instances"
+ SOURCES
+ anchorchangesnodeinstance.cpp anchorchangesnodeinstance.h
+ behaviornodeinstance.cpp behaviornodeinstance.h
+ childrenchangeeventfilter.cpp childrenchangeeventfilter.h
+ componentnodeinstance.cpp componentnodeinstance.h
+ dummycontextobject.cpp dummycontextobject.h
+ dummynodeinstance.cpp dummynodeinstance.h
+ layoutnodeinstance.cpp layoutnodeinstance.h
+ nodeinstanceserver.cpp nodeinstanceserver.h
+ nodeinstancesignalspy.cpp nodeinstancesignalspy.h
+ objectnodeinstance.cpp objectnodeinstance.h
+ positionernodeinstance.cpp positionernodeinstance.h
+ qmlpropertychangesnodeinstance.cpp qmlpropertychangesnodeinstance.h
+ qmlstatenodeinstance.cpp qmlstatenodeinstance.h
+ qmltransitionnodeinstance.cpp qmltransitionnodeinstance.h
+ qt3dpresentationnodeinstance.cpp qt3dpresentationnodeinstance.h
+ qt5informationnodeinstanceserver.cpp qt5informationnodeinstanceserver.h
+ qt5nodeinstanceclientproxy.cpp qt5nodeinstanceclientproxy.h
+ qt5nodeinstanceserver.cpp qt5nodeinstanceserver.h
+ qt5previewnodeinstanceserver.cpp qt5previewnodeinstanceserver.h
+ qt5rendernodeinstanceserver.cpp qt5rendernodeinstanceserver.h
+ qt5testnodeinstanceserver.cpp qt5testnodeinstanceserver.h
+ quickitemnodeinstance.cpp quickitemnodeinstance.h
+ servernodeinstance.cpp servernodeinstance.h
+)
+
+extend_qtc_executable(qml2puppet
+ SOURCES_PREFIX "${SRCDIR}/types"
+ SOURCES
+ enumeration.cpp enumeration.h
+)
+
+extend_qtc_executable(qml2puppet
+ SOURCES_PREFIX "${SRCDIR}/qmlprivategate"
+ SOURCES
+ designersupportdelegate.h
+ qmlprivategate_56.cpp qmlprivategate.h
+)
diff --git a/src/tools/qtcdebugger/CMakeLists.txt b/src/tools/qtcdebugger/CMakeLists.txt
new file mode 100644
index 0000000000..22b1ca8e2d
--- /dev/null
+++ b/src/tools/qtcdebugger/CMakeLists.txt
@@ -0,0 +1,18 @@
+#
+# Copyright (C) YourCompany. All rights reserved.
+#
+# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
+# If you must edit, remove these two lines to avoid regeneration
+
+project(src.tools.qtcdebugger)
+
+
+add_library(${PROJECT_NAME} STATIC
+ main.cpp
+)
+
+target_link_libraries(${PROJECT_NAME}
+ PRIVATE
+ src
+)
+
diff --git a/src/tools/qtcdebugger/main.cpp b/src/tools/qtcdebugger/main.cpp
index 38507c8539..6beda7c1ec 100644
--- a/src/tools/qtcdebugger/main.cpp
+++ b/src/tools/qtcdebugger/main.cpp
@@ -419,6 +419,15 @@ static bool registerDebuggerKey(const WCHAR *key,
do {
if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, access, errorMessage))
break;
+
+ // Make sure to automatically open the qtcdebugger dialog on a crash
+ QString autoVal;
+ registryReadStringKey(handle, autoRegistryValueNameC, &autoVal, errorMessage);
+ if (autoVal != "1") {
+ if (!registryWriteStringKey(handle, autoRegistryValueNameC, "1", errorMessage))
+ break;
+ }
+
// Save old key, which might be missing
QString oldDebugger;
if (isRegistered(handle, call, errorMessage, &oldDebugger)) {
diff --git a/src/tools/qtcrashhandler/CMakeLists.txt b/src/tools/qtcrashhandler/CMakeLists.txt
new file mode 100644
index 0000000000..7868ec305d
--- /dev/null
+++ b/src/tools/qtcrashhandler/CMakeLists.txt
@@ -0,0 +1,7 @@
+#
+# Copyright (C) YourCompany. All rights reserved.
+#
+# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
+# If you must edit, remove these two lines to avoid regeneration
+
+
diff --git a/src/tools/qtcreatorcrashhandler/CMakeLists.txt b/src/tools/qtcreatorcrashhandler/CMakeLists.txt
new file mode 100644
index 0000000000..74dfd2199f
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/CMakeLists.txt
@@ -0,0 +1,11 @@
+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()
diff --git a/src/tools/qtcreatorcrashhandler/backtracecollector.cpp b/src/tools/qtcreatorcrashhandler/backtracecollector.cpp
index f4c49ba919..b3bc1939f7 100644
--- a/src/tools/qtcreatorcrashhandler/backtracecollector.cpp
+++ b/src/tools/qtcreatorcrashhandler/backtracecollector.cpp
@@ -49,10 +49,10 @@ public:
BacktraceCollector::BacktraceCollector(QObject *parent) :
QObject(parent), d(new BacktraceCollectorPrivate)
{
- connect(&d->debugger,
- static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ connect(&d->debugger, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &BacktraceCollector::onDebuggerFinished);
- connect(&d->debugger, &QProcess::errorOccurred, this, &BacktraceCollector::onDebuggerError);
+ connect(&d->debugger, &QProcess::errorOccurred,
+ this, &BacktraceCollector::onDebuggerError);
connect(&d->debugger, &QIODevice::readyRead,
this, &BacktraceCollector::onDebuggerOutputAvailable);
d->debugger.setProcessChannelMode(QProcess::MergedChannels);
diff --git a/src/tools/qtcreatorcrashhandler/crashhandler.cpp b/src/tools/qtcreatorcrashhandler/crashhandler.cpp
index c6df3c9ad9..89ff098420 100644
--- a/src/tools/qtcreatorcrashhandler/crashhandler.cpp
+++ b/src/tools/qtcreatorcrashhandler/crashhandler.cpp
@@ -94,7 +94,7 @@ public:
dialog(crashHandler, signalName, appName) {}
const pid_t pid;
- const Utils::FileName creatorInPath; // Backup debugger.
+ const Utils::FilePath creatorInPath; // Backup debugger.
BacktraceCollector backtraceCollector;
CrashHandlerDialog dialog;
diff --git a/src/tools/qtcreatorwidgets/CMakeLists.txt b/src/tools/qtcreatorwidgets/CMakeLists.txt
new file mode 100644
index 0000000000..80fd46c824
--- /dev/null
+++ b/src/tools/qtcreatorwidgets/CMakeLists.txt
@@ -0,0 +1,20 @@
+#
+# Copyright (C) YourCompany. All rights reserved.
+#
+# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
+# If you must edit, remove these two lines to avoid regeneration
+
+project(src.tools.qtcreatorwidgets)
+
+
+add_library(${PROJECT_NAME} STATIC
+ customwidget.h
+ customwidgets.cpp
+ customwidgets.h
+)
+
+target_link_libraries(${PROJECT_NAME}
+ PRIVATE
+ src.libs.utils
+)
+
diff --git a/src/tools/qtpromaker/CMakeLists.txt b/src/tools/qtpromaker/CMakeLists.txt
new file mode 100644
index 0000000000..5c81cdcd6b
--- /dev/null
+++ b/src/tools/qtpromaker/CMakeLists.txt
@@ -0,0 +1 @@
+add_qtc_executable(qtpromaker DEPENDS Qt5::Core SOURCES main.cpp)
diff --git a/src/tools/screenshotcropper/CMakeLists.txt b/src/tools/screenshotcropper/CMakeLists.txt
new file mode 100644
index 0000000000..c33a1311c8
--- /dev/null
+++ b/src/tools/screenshotcropper/CMakeLists.txt
@@ -0,0 +1,22 @@
+#
+# Copyright (C) YourCompany. All rights reserved.
+#
+# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
+# If you must edit, remove these two lines to avoid regeneration
+
+project(src.tools.screenshotcropper)
+
+
+add_library(${PROJECT_NAME} STATIC
+ cropimageview.cpp
+ cropimageview.h
+ main.cpp
+ screenshotcropperwindow.cpp
+ screenshotcropperwindow.h
+)
+
+target_link_libraries(${PROJECT_NAME}
+ PRIVATE
+ src.plugins.qtsupport
+)
+
diff --git a/src/tools/sdktool/CMakeLists.txt b/src/tools/sdktool/CMakeLists.txt
new file mode 100644
index 0000000000..3997c9763c
--- /dev/null
+++ b/src/tools/sdktool/CMakeLists.txt
@@ -0,0 +1,59 @@
+get_target_property(UtilsSourcesDir Utils SOURCES_DIR)
+
+add_qtc_executable(sdktool
+ DEFINES DATA_PATH=\"${IDE_DATA_PATH}\"
+ DEPENDS Qt5::Core app_version
+ INCLUDES "${UtilsSourcesDir}/../"
+ SOURCES
+ 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
+ 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
+)
+
+extend_qtc_target(sdktool
+ SOURCES_PREFIX "${UtilsSourcesDir}"
+ DEFINES QTCREATOR_UTILS_STATIC_LIB
+ SOURCES
+ environment.cpp environment.h
+ fileutils.cpp fileutils.h
+ hostosinfo.cpp hostosinfo.h
+ persistentsettings.cpp persistentsettings.h
+ qtcassert.cpp qtcassert.h
+ qtcprocess.cpp qtcprocess.h
+ savefile.cpp savefile.h
+ stringutils.cpp stringutils.h
+)
+
+extend_qtc_target(sdktool CONDITION APPLE
+ SOURCES_PREFIX "${UtilsSourcesDir}"
+ SOURCES
+ fileutils_mac.mm fileutils_mac.h
+ DEPENDS
+ ${FWFoundation}
+)
+
+extend_qtc_target(sdktool CONDITION WIN32
+ DEPENDS
+ user32 iphlpapi ws2_32 shell32
+ DEFINES
+ _UNICODE UNICODE
+ _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS
+)
diff --git a/src/tools/sdktool/addcmakeoperation.cpp b/src/tools/sdktool/addcmakeoperation.cpp
index 893b9c5b61..8a23fc42ca 100644
--- a/src/tools/sdktool/addcmakeoperation.cpp
+++ b/src/tools/sdktool/addcmakeoperation.cpp
@@ -157,7 +157,7 @@ bool AddCMakeOperation::test() const
if (!unchanged.isEmpty())
return false;
- // Make sure name stays unique:
+ // add 2nd cmake
map = addCMake(map, "{some-cm-id}", "name", "/tmp/test",
KeyValuePairList() << KeyValuePair("ExtraKey", QVariant("ExtraValue")));
if (map.value(COUNT).toInt() != 2
@@ -175,7 +175,7 @@ bool AddCMakeOperation::test() const
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() != "name2"
+ || cmData.value(DISPLAYNAME_KEY).toString() != "name"
|| cmData.value(AUTODETECTED_KEY).toBool() != true
|| cmData.value(PATH_KEY).toString() != "/tmp/test"
|| cmData.value("ExtraKey").toString() != "ExtraValue")
diff --git a/src/tools/sdktool/addkitoperation.cpp b/src/tools/sdktool/addkitoperation.cpp
index 0763c55e46..5eef6e7115 100644
--- a/src/tools/sdktool/addkitoperation.cpp
+++ b/src/tools/sdktool/addkitoperation.cpp
@@ -57,7 +57,7 @@ const char SDK[] = "PE.Profile.SDK";
const char ENV[] = "PE.Profile.Environment";
const char DATA[] = "PE.Profile.Data";
-// Standard KitInformation:
+// Standard KitAspects:
const char DEBUGGER[] = "Debugger.Information";
const char DEBUGGER_ENGINE[] = "EngineType";
const char DEBUGGER_BINARY[] = "Binary";
diff --git a/src/tools/sdktool/addqtoperation.cpp b/src/tools/sdktool/addqtoperation.cpp
index 30ece83c65..3297eb8dbf 100644
--- a/src/tools/sdktool/addqtoperation.cpp
+++ b/src/tools/sdktool/addqtoperation.cpp
@@ -231,7 +231,7 @@ bool AddQtOperation::test() const
if (!result.isEmpty())
return false;
- // Make sure name is unique:
+ // add 2nd Qt version:
map = addQt(map, QLatin1String("testId2"), QLatin1String("Test Qt Version"), QLatin1String("testType3"),
QLatin1String("/tmp/test/qmake2"),
KeyValuePairList() << KeyValuePair(QLatin1String("extraData"), QVariant(QLatin1String("extraValue"))),
@@ -251,7 +251,7 @@ bool AddQtOperation::test() const
|| !version1.contains(QLatin1String(ID))
|| version1.value(QLatin1String(ID)).toInt() != -1
|| !version1.contains(QLatin1String(DISPLAYNAME))
- || version1.value(QLatin1String(DISPLAYNAME)).toString() != QLatin1String("Test Qt Version2")
+ || version1.value(QLatin1String(DISPLAYNAME)).toString() != QLatin1String("Test Qt Version")
|| !version1.contains(QLatin1String(AUTODETECTED))
|| version1.value(QLatin1String(AUTODETECTED)).toBool() != true
|| !version1.contains(QLatin1String(AUTODETECTION_SOURCE))
diff --git a/src/tools/sdktool/addtoolchainoperation.cpp b/src/tools/sdktool/addtoolchainoperation.cpp
index 0f5359cff3..afcab9a5e2 100644
--- a/src/tools/sdktool/addtoolchainoperation.cpp
+++ b/src/tools/sdktool/addtoolchainoperation.cpp
@@ -199,7 +199,7 @@ bool AddToolChainOperation::test() const
if (!unchanged.isEmpty())
return false;
- // Make sure name stays unique:
+ // add 2nd tool chain:
map = addToolChain(map, "{some-tc-id}", "langId2", "name", "/tmp/test", "test-abi", "test-abi,test-abi2",
KeyValuePairList() << KeyValuePair("ExtraKey", QVariant("ExtraValue")));
if (map.value(COUNT).toInt() != 2
@@ -221,7 +221,7 @@ bool AddToolChainOperation::test() const
if (tcData.count() != 8
|| tcData.value(ID).toString() != "{some-tc-id}"
|| tcData.value(LANGUAGE_KEY_V2).toString() != "langId2"
- || tcData.value(DISPLAYNAME).toString() != "name2"
+ || tcData.value(DISPLAYNAME).toString() != "name"
|| tcData.value(AUTODETECTED).toBool() != true
|| tcData.value(PATH).toString() != "/tmp/test"
|| tcData.value(TARGET_ABI).toString() != "test-abi"
diff --git a/src/tools/sdktool/main.cpp b/src/tools/sdktool/main.cpp
index 444752a5a4..808a2652fa 100644
--- a/src/tools/sdktool/main.cpp
+++ b/src/tools/sdktool/main.cpp
@@ -116,7 +116,7 @@ int parseArguments(const QStringList &args, Settings *s,
// sdkpath
if (current.startsWith(QLatin1String("--sdkpath="))) {
- s->sdkPath = Utils::FileName::fromString(current.mid(10));
+ s->sdkPath = Utils::FilePath::fromString(current.mid(10));
continue;
}
if (current == QLatin1String("-s")) {
@@ -125,7 +125,7 @@ int parseArguments(const QStringList &args, Settings *s,
printHelp(operations);
return 1;
}
- s->sdkPath = Utils::FileName::fromString(next);
+ s->sdkPath = Utils::FilePath::fromString(next);
++i; // skip next;
continue;
}
diff --git a/src/tools/sdktool/operation.cpp b/src/tools/sdktool/operation.cpp
index 68bad3272d..a31e6ce271 100644
--- a/src/tools/sdktool/operation.cpp
+++ b/src/tools/sdktool/operation.cpp
@@ -87,7 +87,7 @@ QVariantMap Operation::load(const QString &file)
QVariantMap map;
// Read values from original file:
- Utils::FileName path = Settings::instance()->getPath(file);
+ Utils::FilePath path = Settings::instance()->getPath(file);
if (path.exists()) {
Utils::PersistentSettingsReader reader;
if (!reader.load(path))
@@ -100,14 +100,14 @@ QVariantMap Operation::load(const QString &file)
bool Operation::save(const QVariantMap &map, const QString &file) const
{
- Utils::FileName path = Settings::instance()->getPath(file);
+ Utils::FilePath path = Settings::instance()->getPath(file);
if (path.isEmpty()) {
std::cerr << "Error: No path found for " << qPrintable(file) << "." << std::endl;
return false;
}
- Utils::FileName dirName = path.parentDir();
+ Utils::FilePath dirName = path.parentDir();
QDir dir(dirName.toString());
if (!dir.exists() && !dir.mkpath(QLatin1String("."))) {
std::cerr << "Error: Could not create directory " << qPrintable(dirName.toString())
diff --git a/src/tools/sdktool/sdktool.pro b/src/tools/sdktool/sdktool.pro
index 098897f1e2..9869d50dc4 100644
--- a/src/tools/sdktool/sdktool.pro
+++ b/src/tools/sdktool/sdktool.pro
@@ -30,11 +30,14 @@ SOURCES += \
rmqtoperation.cpp \
rmtoolchainoperation.cpp \
settings.cpp \
+ $$UTILS/environment.cpp \
$$UTILS/fileutils.cpp \
$$UTILS/hostosinfo.cpp \
$$UTILS/persistentsettings.cpp \
$$UTILS/qtcassert.cpp \
+ $$UTILS/qtcprocess.cpp \
$$UTILS/savefile.cpp \
+ $$UTILS/stringutils.cpp
HEADERS += \
addabiflavor.h \
@@ -57,10 +60,12 @@ HEADERS += \
rmqtoperation.h \
rmtoolchainoperation.h \
settings.h \
+ $$UTILS/environment.h \
$$UTILS/fileutils.h \
$$UTILS/hostosinfo.h \
$$UTILS/persistentsettings.h \
$$UTILS/qtcassert.h \
+ $$UTILS/qtcprocess.h \
$$UTILS/savefile.h \
macos {
diff --git a/src/tools/sdktool/sdktool.qbs b/src/tools/sdktool/sdktool.qbs
index 67b1d8e3c3..c26db6ad3f 100644
--- a/src/tools/sdktool/sdktool.qbs
+++ b/src/tools/sdktool/sdktool.qbs
@@ -66,11 +66,14 @@ QtcTool {
name: "Utils"
prefix: libsDir + "/utils/"
files: [
+ "environment.cpp", "environment.h",
"fileutils.cpp", "fileutils.h",
"hostosinfo.cpp", "hostosinfo.h",
"persistentsettings.cpp", "persistentsettings.h",
"qtcassert.cpp", "qtcassert.h",
- "savefile.cpp", "savefile.h"
+ "qtcprocess.cpp", "qtcprocess.h",
+ "savefile.cpp", "savefile.h",
+ "stringutils.cpp"
]
}
Group {
diff --git a/src/tools/sdktool/settings.cpp b/src/tools/sdktool/settings.cpp
index e4c74cc19e..01f5120e16 100644
--- a/src/tools/sdktool/settings.cpp
+++ b/src/tools/sdktool/settings.cpp
@@ -47,30 +47,28 @@ Settings::Settings() :
m_instance = this;
// autodetect sdk dir:
- sdkPath = Utils::FileName::fromString(QCoreApplication::applicationDirPath());
- sdkPath.appendPath(QLatin1String(DATA_PATH));
- sdkPath = Utils::FileName::fromString(QDir::cleanPath(sdkPath.toString()));
- sdkPath.appendPath(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)
- + '/' + Core::Constants::IDE_ID);
+ sdkPath = Utils::FilePath::fromString(QCoreApplication::applicationDirPath())
+ .pathAppended(DATA_PATH);
+ sdkPath = Utils::FilePath::fromString(QDir::cleanPath(sdkPath.toString()))
+ .pathAppended(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR) + '/' + Core::Constants::IDE_ID);
}
-Utils::FileName Settings::getPath(const QString &file)
+Utils::FilePath Settings::getPath(const QString &file)
{
- Utils::FileName result = sdkPath;
+ Utils::FilePath result = sdkPath;
const QString lowerFile = file.toLower();
const QStringList identical
= QStringList({ "android", "cmaketools", "debuggers", "devices",
"profiles", "qtversions", "toolchains", "abi" });
if (lowerFile == "cmake")
- result.appendPath("cmaketools");
+ result = result.pathAppended("cmaketools");
else if (lowerFile == "kits")
- result.appendPath("profiles");
+ result = result.pathAppended("profiles");
else if (lowerFile == "qtversions")
- result.appendPath("qtversion");
+ result = result.pathAppended("qtversion");
else if (identical.contains(lowerFile))
- result.appendPath(lowerFile);
+ result = result.pathAppended(lowerFile);
else
- result.appendPath(file); // handle arbitrary file names not known yet
- result.appendString(".xml");
- return result;
+ result = result.pathAppended(file); // handle arbitrary file names not known yet
+ return result.stringAppended(".xml");
}
diff --git a/src/tools/sdktool/settings.h b/src/tools/sdktool/settings.h
index dbf3481c26..b2804e9907 100644
--- a/src/tools/sdktool/settings.h
+++ b/src/tools/sdktool/settings.h
@@ -37,11 +37,11 @@ public:
Settings();
static Settings *instance();
- Utils::FileName sdkPath;
+ Utils::FilePath sdkPath;
Operation *operation;
- Utils::FileName getPath(const QString &file);
+ Utils::FilePath getPath(const QString &file);
private:
static Settings *m_instance;
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
index 61a8d07cc5..688ff570af 100644
--- a/src/tools/tools.pro
+++ b/src/tools/tools.pro
@@ -11,7 +11,8 @@ SUBDIRS = qtpromaker \
isEmpty(QTC_SKIP_SDKTOOL): SUBDIRS += sdktool
-qtHaveModule(quick-private): SUBDIRS += qml2puppet
+QTC_DO_NOT_BUILD_QMLDESIGNER = $$(QTC_DO_NOT_BUILD_QMLDESIGNER)
+isEmpty(QTC_DO_NOT_BUILD_QMLDESIGNER):qtHaveModule(quick-private): SUBDIRS += qml2puppet
win32 {
SUBDIRS += qtcdebugger \
@@ -26,12 +27,10 @@ mac {
SUBDIRS += clangbackend
-QTC_ENABLE_CLANG_LIBTOOLING=$$(QTC_ENABLE_CLANG_LIBTOOLING)
-!isEmpty(QTC_ENABLE_CLANG_LIBTOOLING) {
+QTC_DISABLE_CLANG_REFACTORING=$$(QTC_DISABLE_CLANG_REFACTORING)
+isEmpty(QTC_DISABLE_CLANG_REFACTORING) {
SUBDIRS += clangrefactoringbackend
SUBDIRS += clangpchmanagerbackend
-} else {
- warning("Not building the clang refactoring backend and the pch manager backend.")
}
isEmpty(BUILD_CPLUSPLUS_TOOLS):BUILD_CPLUSPLUS_TOOLS=$$(BUILD_CPLUSPLUS_TOOLS)
@@ -80,7 +79,10 @@ exists(perfparser/perfparser.pro) {
cache(PERFPARSER_APP_INSTALLDIR)
}
-OTHER_FILES += tools.qbs
+OTHER_FILES += \
+ tools.qbs \
+ icons/exportapplicationicons.sh \
+ icons/exportdocumenttypeicons.sh
# delegate deployqt target
deployqt.CONFIG += recursive
diff --git a/src/tools/valgrindfake/CMakeLists.txt b/src/tools/valgrindfake/CMakeLists.txt
new file mode 100644
index 0000000000..93944f3913
--- /dev/null
+++ b/src/tools/valgrindfake/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_qtc_executable(valgrind-fake
+ DEPENDS Qt5::Network Qt5::Xml
+ SOURCES main.cpp outputgenerator.cpp outputgenerator.h
+)
+
diff --git a/src/tools/wininterrupt/CMakeLists.txt b/src/tools/wininterrupt/CMakeLists.txt
new file mode 100644
index 0000000000..704b417ff5
--- /dev/null
+++ b/src/tools/wininterrupt/CMakeLists.txt
@@ -0,0 +1,12 @@
+#
+# Copyright (C) YourCompany. All rights reserved.
+#
+# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
+# If you must edit, remove these two lines to avoid regeneration
+
+project(src.tools.wininterrupt)
+
+
+add_library(${PROJECT_NAME} INTERFACE
+)
+
diff --git a/src/tools/winrtdebughelper/CMakeLists.txt b/src/tools/winrtdebughelper/CMakeLists.txt
new file mode 100644
index 0000000000..0b19c9310c
--- /dev/null
+++ b/src/tools/winrtdebughelper/CMakeLists.txt
@@ -0,0 +1,13 @@
+#
+# Copyright (C) YourCompany. All rights reserved.
+#
+# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
+# If you must edit, remove these two lines to avoid regeneration
+
+project(src.tools.winrtdebughelper)
+
+
+add_library(${PROJECT_NAME} STATIC
+ winrtdebughelper.cpp
+)
+
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000000..dd56e8c35c
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_subdirectory(auto)
+# add_subdirectory(manual)
+# add_subdirectory(tools)
+add_subdirectory(unit)
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
new file mode 100644
index 0000000000..88f4e3b20b
--- /dev/null
+++ b/tests/auto/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_subdirectory(aggregation)
+add_subdirectory(algorithm)
+add_subdirectory(changeset)
+add_subdirectory(cplusplus)
+add_subdirectory(debugger)
+add_subdirectory(diff)
+add_subdirectory(environment)
+add_subdirectory(extensionsystem)
+add_subdirectory(externaltool)
+add_subdirectory(filesearch)
+add_subdirectory(json)
+add_subdirectory(languageserverprotocol)
+add_subdirectory(mapreduce)
+add_subdirectory(pointeralgorithm)
+add_subdirectory(profilewriter)
+add_subdirectory(qml)
+add_subdirectory(qtcprocess)
+add_subdirectory(runextensions)
+add_subdirectory(sdktool)
+add_subdirectory(ssh)
+add_subdirectory(toolchaincache)
+add_subdirectory(tracing)
+add_subdirectory(treeviewfind)
+add_subdirectory(utils)
+# add_subdirectory(valgrind)
diff --git a/tests/auto/aggregation/CMakeLists.txt b/tests/auto/aggregation/CMakeLists.txt
new file mode 100644
index 0000000000..1827d6b111
--- /dev/null
+++ b/tests/auto/aggregation/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_aggregation
+ DEPENDS Aggregation Qt5::Core
+ SOURCES tst_aggregate.cpp
+)
diff --git a/tests/auto/algorithm/CMakeLists.txt b/tests/auto/algorithm/CMakeLists.txt
new file mode 100644
index 0000000000..f856b34836
--- /dev/null
+++ b/tests/auto/algorithm/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_algorithm
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/libs"
+ SOURCES tst_algorithm.cpp
+)
diff --git a/tests/auto/changeset/CMakeLists.txt b/tests/auto/changeset/CMakeLists.txt
new file mode 100644
index 0000000000..50adbd176b
--- /dev/null
+++ b/tests/auto/changeset/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_changeset
+ DEPENDS Utils
+ SOURCES tst_changeset.cpp
+)
diff --git a/tests/auto/cplusplus/CMakeLists.txt b/tests/auto/cplusplus/CMakeLists.txt
new file mode 100644
index 0000000000..1c85a988cc
--- /dev/null
+++ b/tests/auto/cplusplus/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_subdirectory(ast)
+add_subdirectory(c99)
+add_subdirectory(checksymbols)
+add_subdirectory(codeformatter)
+add_subdirectory(cppselectionchanger)
+add_subdirectory(cxx11)
+add_subdirectory(fileiterationorder)
+add_subdirectory(findusages)
+add_subdirectory(lexer)
+add_subdirectory(lookup)
+add_subdirectory(misc)
+add_subdirectory(preprocessor)
+add_subdirectory(semantic)
+add_subdirectory(translationunit)
+add_subdirectory(typeprettyprinter)
diff --git a/tests/auto/cplusplus/ast/CMakeLists.txt b/tests/auto/cplusplus/ast/CMakeLists.txt
new file mode 100644
index 0000000000..5bfef72674
--- /dev/null
+++ b/tests/auto/cplusplus/ast/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_ast
+ DEPENDS CppTools
+ SOURCES tst_ast.cpp
+)
diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp
index 0cf9c7a560..e444a4b8e5 100644
--- a/tests/auto/cplusplus/ast/tst_ast.cpp
+++ b/tests/auto/cplusplus/ast/tst_ast.cpp
@@ -97,7 +97,7 @@ public:
{
++errorCount;
- qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' '<<QString().vsprintf(format, ap);
+ qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' ' << QString::vasprintf(format, ap);
}
};
diff --git a/tests/auto/cplusplus/c99/CMakeLists.txt b/tests/auto/cplusplus/c99/CMakeLists.txt
new file mode 100644
index 0000000000..836f4b5c55
--- /dev/null
+++ b/tests/auto/cplusplus/c99/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_c99
+ DEPENDS CppTools
+ SOURCES tst_c99.cpp
+)
diff --git a/tests/auto/cplusplus/c99/tst_c99.cpp b/tests/auto/cplusplus/c99/tst_c99.cpp
index df33671907..edcb5f955f 100644
--- a/tests/auto/cplusplus/c99/tst_c99.cpp
+++ b/tests/auto/cplusplus/c99/tst_c99.cpp
@@ -83,11 +83,10 @@ class tst_c99: public QObject
static const char *const pretty[] = {"warning", "error", "fatal"};
- QString str;
- str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]);
+ QString str = QString::asprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]);
errors->append(str.toUtf8());
- str.vsprintf(format, ap);
+ str += QString::vasprintf(format, ap);
errors->append(str.toUtf8());
errors->append('\n');
diff --git a/tests/auto/cplusplus/checksymbols/CMakeLists.txt b/tests/auto/cplusplus/checksymbols/CMakeLists.txt
new file mode 100644
index 0000000000..f889839ed2
--- /dev/null
+++ b/tests/auto/cplusplus/checksymbols/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_checksymbols
+ DEPENDS CppTools TextEditor
+ SOURCES tst_checksymbols.cpp
+)
diff --git a/tests/auto/cplusplus/codeformatter/CMakeLists.txt b/tests/auto/cplusplus/codeformatter/CMakeLists.txt
new file mode 100644
index 0000000000..9dfcc9346e
--- /dev/null
+++ b/tests/auto/cplusplus/codeformatter/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_codeformatter
+ DEPENDS CppTools
+ SOURCES tst_codeformatter.cpp
+)
diff --git a/tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt b/tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt
new file mode 100644
index 0000000000..6df9d4c2ba
--- /dev/null
+++ b/tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_cppselectionchangertest
+ DEPENDS CppTools
+ SOURCES tst_cppselectionchangertest.cpp
+)
diff --git a/tests/auto/cplusplus/cxx11/CMakeLists.txt b/tests/auto/cplusplus/cxx11/CMakeLists.txt
new file mode 100644
index 0000000000..b21ee16194
--- /dev/null
+++ b/tests/auto/cplusplus/cxx11/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_cxx11
+ DEPENDS CppTools
+ SOURCES tst_cxx11.cpp
+)
diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
index 108d93f18f..abef7cc1e1 100644
--- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
+++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
@@ -85,11 +85,10 @@ class tst_cxx11: public QObject
static const char *const pretty[] = {"warning", "error", "fatal"};
- QString str;
- str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]);
+ QString str = QString::asprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]);
errors->append(str.toUtf8());
- str.vsprintf(format, ap);
+ str += QString::vasprintf(format, ap);
errors->append(str.toUtf8());
errors->append('\n');
diff --git a/tests/auto/cplusplus/fileiterationorder/CMakeLists.txt b/tests/auto/cplusplus/fileiterationorder/CMakeLists.txt
new file mode 100644
index 0000000000..3f3d99d0e7
--- /dev/null
+++ b/tests/auto/cplusplus/fileiterationorder/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_fileiterationorder
+ DEPENDS CppTools
+ SOURCES tst_fileiterationorder.cpp
+)
diff --git a/tests/auto/cplusplus/findusages/CMakeLists.txt b/tests/auto/cplusplus/findusages/CMakeLists.txt
new file mode 100644
index 0000000000..5155c324e5
--- /dev/null
+++ b/tests/auto/cplusplus/findusages/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_findusages
+ DEPENDS CppTools Utils
+ SOURCES tst_findusages.cpp
+)
diff --git a/tests/auto/cplusplus/lexer/CMakeLists.txt b/tests/auto/cplusplus/lexer/CMakeLists.txt
new file mode 100644
index 0000000000..8cc0c55062
--- /dev/null
+++ b/tests/auto/cplusplus/lexer/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_lexer
+ DEPENDS CppTools
+ SOURCES tst_lexer.cpp
+)
diff --git a/tests/auto/cplusplus/lookup/CMakeLists.txt b/tests/auto/cplusplus/lookup/CMakeLists.txt
new file mode 100644
index 0000000000..4ca7f97e21
--- /dev/null
+++ b/tests/auto/cplusplus/lookup/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_lookup
+ DEPENDS CppTools
+ SOURCES tst_lookup.cpp
+)
diff --git a/tests/auto/cplusplus/misc/CMakeLists.txt b/tests/auto/cplusplus/misc/CMakeLists.txt
new file mode 100644
index 0000000000..260ec2ae12
--- /dev/null
+++ b/tests/auto/cplusplus/misc/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_misc
+ DEPENDS CppTools Utils
+ SOURCES tst_misc.cpp
+)
diff --git a/tests/auto/cplusplus/preprocessor/CMakeLists.txt b/tests/auto/cplusplus/preprocessor/CMakeLists.txt
new file mode 100644
index 0000000000..c473084bad
--- /dev/null
+++ b/tests/auto/cplusplus/preprocessor/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_preprocessor
+ DEPENDS CppTools
+ SOURCES tst_preprocessor.cpp
+)
diff --git a/tests/auto/cplusplus/semantic/CMakeLists.txt b/tests/auto/cplusplus/semantic/CMakeLists.txt
new file mode 100644
index 0000000000..6a358e9fff
--- /dev/null
+++ b/tests/auto/cplusplus/semantic/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_semantic
+ DEPENDS CppTools
+ SOURCES tst_semantic.cpp
+)
diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp
index 3904558efc..e13795154b 100644
--- a/tests/auto/cplusplus/semantic/tst_semantic.cpp
+++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp
@@ -120,7 +120,7 @@ public:
++errorCount;
#ifndef NO_PARSER_OR_SEMANTIC_ERROR_MESSAGES
- qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' '<<QString().vsprintf(format, ap);
+ qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' ' << QString::vasprintf(format, ap);
#else
Q_UNUSED(fileName);
Q_UNUSED(line);
diff --git a/tests/auto/cplusplus/translationunit/CMakeLists.txt b/tests/auto/cplusplus/translationunit/CMakeLists.txt
new file mode 100644
index 0000000000..5633d0f36b
--- /dev/null
+++ b/tests/auto/cplusplus/translationunit/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_translationunit
+ DEPENDS CppTools
+ SOURCES tst_translationunit.cpp
+)
diff --git a/tests/auto/cplusplus/translationunit/tst_translationunit.cpp b/tests/auto/cplusplus/translationunit/tst_translationunit.cpp
index 4a2159bf04..2c651676bc 100644
--- a/tests/auto/cplusplus/translationunit/tst_translationunit.cpp
+++ b/tests/auto/cplusplus/translationunit/tst_translationunit.cpp
@@ -133,7 +133,7 @@ private:
{
++errorCount;
qDebug() << fileName->chars() << ':' << line << ':' << column
- << ' ' << QString().vsprintf(format, ap);
+ << ' ' << QString::vasprintf(format, ap);
}
} m_diagnosticClient;
};
diff --git a/tests/auto/cplusplus/typeprettyprinter/CMakeLists.txt b/tests/auto/cplusplus/typeprettyprinter/CMakeLists.txt
new file mode 100644
index 0000000000..a6c0718114
--- /dev/null
+++ b/tests/auto/cplusplus/typeprettyprinter/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_cplusplus_typeprettyprinter
+ DEPENDS CppTools
+ SOURCES tst_typeprettyprinter.cpp
+)
diff --git a/tests/auto/debugger/CMakeLists.txt b/tests/auto/debugger/CMakeLists.txt
new file mode 100644
index 0000000000..b4e7da69dc
--- /dev/null
+++ b/tests/auto/debugger/CMakeLists.txt
@@ -0,0 +1,53 @@
+set(DEBUGGERDIR "${CMAKE_SOURCE_DIR}/src/plugins/debugger")
+
+add_qtc_test(tst_debugger_disassembler
+ INCLUDES "${DEBUGGERDIR}"
+ SOURCES
+ tst_disassembler.cpp
+ "${DEBUGGERDIR}/disassemblerlines.cpp" "${DEBUGGERDIR}/disassemblerlines.h"
+)
+
+if (WITH_DEBUGGER_DUMPERS)
+ add_qtc_test(tst_debugger_dumpers
+ DEPENDS Qt5::Network Utils
+ DEFINES DUMPERDIR="${CMAKE_SOURCE_DIR}/share/qtcreator/debugger"
+ INCLUDES
+ "${DEBUGGERDIR}"
+ SOURCES
+ "${DEBUGGERDIR}/debuggerprotocol.cpp" "${DEBUGGERDIR}/debuggerprotocol.h"
+ "${DEBUGGERDIR}/simplifytype.cpp" "${DEBUGGERDIR}/simplifytype.h"
+ "${DEBUGGERDIR}/watchdata.cpp" "${DEBUGGERDIR}/watchdata.h"
+ "${DEBUGGERDIR}/watchutils.cpp" "${DEBUGGERDIR}/watchutils.h"
+ tst_dumpers.cpp
+ )
+endif()
+
+add_qtc_test(tst_debugger_gdb
+ DEPENDS Qt5::Network Utils
+ INCLUDES "${DEBUGGERDIR}"
+ SOURCES
+ tst_gdb.cpp
+ "${DEBUGGERDIR}/debuggerprotocol.cpp" "${DEBUGGERDIR}/debuggerprotocol.h"
+)
+
+add_qtc_test(tst_debugger_namedemangler
+ INCLUDES "${DEBUGGERDIR}"
+ SOURCES
+ tst_namedemangler.cpp
+ "${DEBUGGERDIR}/namedemangler/globalparsestate.cpp" "${DEBUGGERDIR}/namedemangler/globalparsestate.h"
+ "${DEBUGGERDIR}/namedemangler/namedemangler.cpp" "${DEBUGGERDIR}/namedemangler/namedemangler.h"
+ "${DEBUGGERDIR}/namedemangler/parsetreenodes.cpp" "${DEBUGGERDIR}/namedemangler/parsetreenodes.h"
+)
+
+add_qtc_test(tst_debugger_offsets
+ DEPENDS Qt5::CorePrivate
+ INCLUDES "${DEBUGGERDIR}"
+ SOURCES tst_offsets.cpp
+)
+
+add_qtc_test(tst_debugger_simplifytypes
+ INCLUDES "${DEBUGGERDIR}"
+ SOURCES
+ tst_simplifytypes.cpp
+ "${DEBUGGERDIR}/simplifytype.cpp" "${DEBUGGERDIR}/simplifytype.h"
+)
diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp
index fac13979db..3b59a9cce8 100644
--- a/tests/auto/debugger/tst_dumpers.cpp
+++ b/tests/auto/debugger/tst_dumpers.cpp
@@ -90,10 +90,11 @@ static bool generateEnvironmentSettings(Utils::Environment &env,
// if Creator is launched within a session set up by setenv.cmd.
env.unset("ORIGINALPATH");
run.setEnvironment(env);
- const QString cmdPath = QString::fromLocal8Bit(qgetenv("COMSPEC"));
+ const Utils::FilePath cmdPath
+ = Utils::FilePath::fromString(QString::fromLocal8Bit(qgetenv("COMSPEC")));
// Windows SDK setup scripts require command line switches for environment expansion.
QString cmdArguments = " /E:ON /V:ON /c \"" + QDir::toNativeSeparators(saver.fileName()) + '"';
- run.setCommand(cmdPath, cmdArguments);
+ run.setCommand(Utils::CommandLine(cmdPath, cmdArguments));
run.start();
if (!run.waitForStarted()) {
@@ -3685,7 +3686,7 @@ void tst_Dumpers::dumper_data()
"QList<int> list;\n"
"list << 1 << 2 << 3;\n"
- "QVariant v3 = qVariantFromValue(list);\n"
+ "QVariant v3 = QVariant::fromValue(list);\n"
"unused(&list, &v3);\n\n")
+ CoreProfile()
diff --git a/tests/auto/diff/CMakeLists.txt b/tests/auto/diff/CMakeLists.txt
new file mode 100644
index 0000000000..61bd0b2845
--- /dev/null
+++ b/tests/auto/diff/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(differ)
diff --git a/tests/auto/diff/differ/CMakeLists.txt b/tests/auto/diff/differ/CMakeLists.txt
new file mode 100644
index 0000000000..59b675d4ce
--- /dev/null
+++ b/tests/auto/diff/differ/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_differ
+ DEPENDS Utils
+ SOURCES tst_differ.cpp
+)
diff --git a/tests/auto/environment/CMakeLists.txt b/tests/auto/environment/CMakeLists.txt
new file mode 100644
index 0000000000..c38dfe733e
--- /dev/null
+++ b/tests/auto/environment/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_environment
+ DEPENDS Utils
+ SOURCES tst_environment.cpp
+)
diff --git a/tests/auto/extensionsystem/CMakeLists.txt b/tests/auto/extensionsystem/CMakeLists.txt
new file mode 100644
index 0000000000..48d0b007d4
--- /dev/null
+++ b/tests/auto/extensionsystem/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(pluginmanager)
+add_subdirectory(pluginspec)
diff --git a/tests/auto/extensionsystem/pluginmanager/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/CMakeLists.txt
new file mode 100644
index 0000000000..26130c88ba
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_subdirectory(circularplugins)
+add_subdirectory(correctplugins1)
+
+add_qtc_test(tst_pluginmanager
+ DEFINES PLUGINMANAGER_TESTS_DIR="${CMAKE_CURRENT_BINARY_DIR}"
+ DEPENDS ExtensionSystem
+ SOURCES
+ tst_pluginmanager.cpp
+)
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/circularplugins/CMakeLists.txt
new file mode 100644
index 0000000000..bbf4a58ef9
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/CMakeLists.txt
@@ -0,0 +1,4 @@
+set(TEST_PLUGIN_PATH "${CMAKE_CURRENT_BINARY_DIR}")
+add_subdirectory(plugin1)
+add_subdirectory(plugin2)
+add_subdirectory(plugin3)
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/CMakeLists.txt
new file mode 100644
index 0000000000..0d3e8e3858
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin1/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_plugin(plugin1
+ DEPENDS ExtensionSystem
+ SOURCES
+ plugin1.cpp plugin1.h
+ PLUGIN_PATH "${TEST_PLUGIN_PATH}"
+ SKIP_INSTALL
+ )
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/CMakeLists.txt
new file mode 100644
index 0000000000..fd58e173c2
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin2/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_plugin(plugin2
+ DEPENDS ExtensionSystem
+ SOURCES
+ plugin2.cpp plugin2.h
+ PLUGIN_PATH "${TEST_PLUGIN_PATH}"
+ SKIP_INSTALL
+ )
diff --git a/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/CMakeLists.txt
new file mode 100644
index 0000000000..dec94785f1
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/circularplugins/plugin3/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_plugin(plugin3
+ DEPENDS ExtensionSystem
+ SOURCES
+ plugin3.cpp plugin3.h
+ PLUGIN_PATH "${TEST_PLUGIN_PATH}"
+ SKIP_INSTALL
+ )
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/correctplugins1/CMakeLists.txt
new file mode 100644
index 0000000000..bbf4a58ef9
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/CMakeLists.txt
@@ -0,0 +1,4 @@
+set(TEST_PLUGIN_PATH "${CMAKE_CURRENT_BINARY_DIR}")
+add_subdirectory(plugin1)
+add_subdirectory(plugin2)
+add_subdirectory(plugin3)
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/CMakeLists.txt
new file mode 100644
index 0000000000..6302992c2a
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin1/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_plugin(correct_plugin1
+ PLUGIN_NAME plugin1
+ DEPENDS ExtensionSystem
+ SOURCES
+ plugin1.cpp plugin1.h
+ PLUGIN_PATH "${TEST_PLUGIN_PATH}"
+ SKIP_INSTALL
+)
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/CMakeLists.txt
new file mode 100644
index 0000000000..075a08e58d
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin2/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_plugin(correct_plugin2
+ PLUGIN_NAME plugin2
+ DEPENDS ExtensionSystem
+ SOURCES
+ plugin2.cpp plugin2.h
+ PLUGIN_PATH "${TEST_PLUGIN_PATH}"
+ SKIP_INSTALL
+)
diff --git a/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/CMakeLists.txt b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/CMakeLists.txt
new file mode 100644
index 0000000000..2326ac08b4
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginmanager/correctplugins1/plugin3/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_plugin(correct_plugin3
+ PLUGIN_NAME plugin3
+ DEPENDS ExtensionSystem
+ SOURCES
+ plugin3.cpp plugin3.h
+ PLUGIN_PATH "${TEST_PLUGIN_PATH}"
+ SKIP_INSTALL
+)
diff --git a/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp b/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
index 14722c6d57..c3c144a16c 100644
--- a/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
+++ b/tests/auto/extensionsystem/pluginmanager/tst_pluginmanager.cpp
@@ -161,7 +161,7 @@ void tst_PluginManager::circularPlugins()
{
m_pm->setPluginPaths(QStringList() << pluginFolder(QLatin1String("circularplugins")));
m_pm->loadPlugins();
- QList<PluginSpec *> plugins = m_pm->plugins();
+ QVector<PluginSpec *> plugins = m_pm->plugins();
QCOMPARE(plugins.count(), 3);
foreach (PluginSpec *spec, plugins) {
if (spec->name() == "plugin1") {
diff --git a/tests/auto/extensionsystem/pluginspec/CMakeLists.txt b/tests/auto/extensionsystem/pluginspec/CMakeLists.txt
new file mode 100644
index 0000000000..8380467989
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginspec/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_subdirectory(testplugin)
+
+add_qtc_test(tst_pluginspec
+ DEFINES
+ PLUGIN_DIR="${CMAKE_CURRENT_BINARY_DIR}"
+ PLUGINSPEC_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ DEPENDS ExtensionSystem
+ SOURCES
+ tst_pluginspec.cpp
+)
diff --git a/tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt b/tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt
new file mode 100644
index 0000000000..df9fe19244
--- /dev/null
+++ b/tests/auto/extensionsystem/pluginspec/testplugin/CMakeLists.txt
@@ -0,0 +1,22 @@
+# TODO: unittest should be fixed
+if(APPLE)
+ set(plugin_output_name "libtest_debug")
+elseif(UNIX)
+ set(plugin_output_name "liblibtest")
+else()
+ set(plugin_output_name "testd4")
+endif()
+
+add_qtc_plugin(testplugin
+ DEPENDS ExtensionSystem
+ DEFINES MYPLUGIN_LIBRARY
+ SOURCES
+ testplugin.cpp testplugin.h
+ PLUGIN_PATH "${CMAKE_CURRENT_BINARY_DIR}"
+ PROPERTIES
+ OUTPUT_NAME ${plugin_output_name}
+ SKIP_INSTALL
+)
+
+# The empty string gets removed if I put it above
+set_target_properties(testplugin PROPERTIES PREFIX "")
diff --git a/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp b/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
index c846458615..8092bfa57e 100644
--- a/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
+++ b/tests/auto/extensionsystem/pluginspec/tst_pluginspec.cpp
@@ -245,7 +245,7 @@ void tst_PluginSpec::locationAndPath()
void tst_PluginSpec::resolveDependencies()
{
- QList<PluginSpec *> specs;
+ QVector<PluginSpec *> specs;
PluginSpec *spec1 = Internal::PluginManagerPrivate::createSpec();
specs.append(spec1);
Internal::PluginSpecPrivate *spec1Priv = Internal::PluginManagerPrivate::privateSpec(spec1);
@@ -291,7 +291,7 @@ void tst_PluginSpec::loadLibrary()
PluginSpec *ps = Internal::PluginManagerPrivate::createSpec();
Internal::PluginSpecPrivate *spec = Internal::PluginManagerPrivate::privateSpec(ps);
QVERIFY(spec->read(QLatin1String(PLUGIN_DIR) + QLatin1String("/testplugin/") + libraryName(QLatin1String("test"))));
- QVERIFY(spec->resolveDependencies(QList<PluginSpec *>()));
+ QVERIFY(spec->resolveDependencies(QVector<PluginSpec *>()));
QVERIFY2(spec->loadLibrary(), qPrintable(spec->errorString));
QVERIFY(spec->plugin != 0);
QVERIFY(QLatin1String(spec->plugin->metaObject()->className()) == QLatin1String("MyPlugin::MyPluginImpl"));
@@ -305,7 +305,7 @@ void tst_PluginSpec::initializePlugin()
{
Internal::PluginSpecPrivate spec(0);
QVERIFY(spec.read(QLatin1String(PLUGIN_DIR) + QLatin1String("/testplugin/") + libraryName(QLatin1String("test"))));
- QVERIFY(spec.resolveDependencies(QList<PluginSpec *>()));
+ QVERIFY(spec.resolveDependencies(QVector<PluginSpec *>()));
QVERIFY2(spec.loadLibrary(), qPrintable(spec.errorString));
bool isInitialized;
QMetaObject::invokeMethod(spec.plugin, "isInitialized",
@@ -323,7 +323,7 @@ void tst_PluginSpec::initializeExtensions()
{
Internal::PluginSpecPrivate spec(0);
QVERIFY(spec.read(QLatin1String(PLUGIN_DIR) + QLatin1String("/testplugin/") + libraryName(QLatin1String("test"))));
- QVERIFY(spec.resolveDependencies(QList<PluginSpec *>()));
+ QVERIFY(spec.resolveDependencies(QVector<PluginSpec *>()));
QVERIFY2(spec.loadLibrary(), qPrintable(spec.errorString));
bool isExtensionsInitialized;
QVERIFY(spec.initializePlugin());
diff --git a/tests/auto/externaltool/CMakeLists.txt b/tests/auto/externaltool/CMakeLists.txt
new file mode 100644
index 0000000000..64a6004150
--- /dev/null
+++ b/tests/auto/externaltool/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_test(tst_externaltooltest
+ DEPENDS Core app_version
+ SOURCES
+ tst_externaltooltest.cpp
+ "${CMAKE_SOURCE_DIR}/src/plugins/coreplugin/externaltool.cpp"
+ "${CMAKE_SOURCE_DIR}/src/plugins/coreplugin/externaltool.h"
+)
diff --git a/tests/auto/filesearch/CMakeLists.txt b/tests/auto/filesearch/CMakeLists.txt
new file mode 100644
index 0000000000..e61567e78a
--- /dev/null
+++ b/tests/auto/filesearch/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_qtc_test(tst_filesearch
+ DEPENDS Utils
+ SOURCES
+ tst_filesearch.cpp
+ tst_filesearch.qrc
+)
diff --git a/tests/auto/json/CMakeLists.txt b/tests/auto/json/CMakeLists.txt
new file mode 100644
index 0000000000..e03addf91d
--- /dev/null
+++ b/tests/auto/json/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_qtc_test(tst_json
+ DEPENDS Utils
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/shared/json"
+ SOURCES
+ tst_json.cpp
+ "${CMAKE_SOURCE_DIR}/src/shared/json/json.cpp"
+)
diff --git a/tests/auto/languageserverprotocol/CMakeLists.txt b/tests/auto/languageserverprotocol/CMakeLists.txt
new file mode 100644
index 0000000000..76664b67cb
--- /dev/null
+++ b/tests/auto/languageserverprotocol/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_languageserverprotocol
+ DEPENDS Utils LanguageServerProtocol
+ SOURCES tst_languageserverprotocol.cpp
+)
diff --git a/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp b/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp
index f4c94a36b9..daa013b744 100644
--- a/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp
+++ b/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp
@@ -595,7 +595,7 @@ void tst_LanguageServerProtocol::documentUri_data()
{
QTest::addColumn<DocumentUri>("uri");
QTest::addColumn<bool>("isValid");
- QTest::addColumn<Utils::FileName>("fileName");
+ QTest::addColumn<Utils::FilePath>("fileName");
QTest::addColumn<QString>("string");
// '/' (fs root) is part of the file path
@@ -605,18 +605,18 @@ void tst_LanguageServerProtocol::documentUri_data()
QTest::newRow("empty uri")
<< DocumentUri()
<< false
- << Utils::FileName()
+ << Utils::FilePath()
<< QString();
QTest::newRow("home dir")
- << DocumentUri::fromFileName(Utils::FileName::fromString(QDir::homePath()))
+ << DocumentUri::fromFileName(Utils::FilePath::fromString(QDir::homePath()))
<< true
- << Utils::FileName::fromUserInput(QDir::homePath())
+ << Utils::FilePath::fromUserInput(QDir::homePath())
<< QString(filePrefix + QDir::homePath());
const QString argv0 = QFileInfo(qApp->arguments().first()).absoluteFilePath();
- const auto argv0FileName = Utils::FileName::fromUserInput(argv0);
+ const auto argv0FileName = Utils::FilePath::fromUserInput(argv0);
QTest::newRow("argv0 file name")
<< DocumentUri::fromFileName(argv0FileName)
<< true
@@ -626,7 +626,7 @@ void tst_LanguageServerProtocol::documentUri_data()
QTest::newRow("http")
<< DocumentUri::fromProtocol("https://www.qt.io/")
<< true
- << Utils::FileName()
+ << Utils::FilePath()
<< "https://www.qt.io/";
// depending on the OS the resulting path is different (made suitable for the file system)
@@ -636,7 +636,7 @@ void tst_LanguageServerProtocol::documentUri_data()
QTest::newRow("percent encoding")
<< DocumentUri::fromProtocol(winUserPercent)
<< true
- << Utils::FileName::fromUserInput(winUser)
+ << Utils::FilePath::fromUserInput(winUser)
<< QString(filePrefix + QDir::fromNativeSeparators(winUser));
}
@@ -644,7 +644,7 @@ void tst_LanguageServerProtocol::documentUri()
{
QFETCH(DocumentUri, uri);
QFETCH(bool, isValid);
- QFETCH(Utils::FileName, fileName);
+ QFETCH(Utils::FilePath, fileName);
QFETCH(QString, string);
QCOMPARE(uri.isValid(), isValid);
diff --git a/tests/auto/mapreduce/CMakeLists.txt b/tests/auto/mapreduce/CMakeLists.txt
new file mode 100644
index 0000000000..5a57f3c676
--- /dev/null
+++ b/tests/auto/mapreduce/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_mapreduce
+ DEPENDS Utils
+ SOURCES tst_mapreduce.cpp
+)
diff --git a/tests/auto/pointeralgorithm/CMakeLists.txt b/tests/auto/pointeralgorithm/CMakeLists.txt
new file mode 100644
index 0000000000..52a8bbc499
--- /dev/null
+++ b/tests/auto/pointeralgorithm/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_pointeralgorithm
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/libs"
+ SOURCES tst_pointeralgorithm.cpp
+)
diff --git a/tests/auto/profilewriter/CMakeLists.txt b/tests/auto/profilewriter/CMakeLists.txt
new file mode 100644
index 0000000000..c929843c83
--- /dev/null
+++ b/tests/auto/profilewriter/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_qtc_test(tst_profilewriter
+ DEPENDS Utils ProParser
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/shared/proparser"
+ SOURCES tst_profilewriter.cpp
+)
diff --git a/tests/auto/qml/CMakeLists.txt b/tests/auto/qml/CMakeLists.txt
new file mode 100644
index 0000000000..61e6c1e0b5
--- /dev/null
+++ b/tests/auto/qml/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_subdirectory(codemodel)
+add_subdirectory(persistenttrie)
+add_subdirectory(qmldesigner)
+add_subdirectory(qmleditor)
+add_subdirectory(qmljssimplereader)
+add_subdirectory(qmlprojectmanager)
+add_subdirectory(qrcparser)
+add_subdirectory(reformatter)
diff --git a/tests/auto/qml/codemodel/CMakeLists.txt b/tests/auto/qml/codemodel/CMakeLists.txt
new file mode 100644
index 0000000000..94eae7af58
--- /dev/null
+++ b/tests/auto/qml/codemodel/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_subdirectory(check )
+add_subdirectory(dependencies )
+add_subdirectory(ecmascript7 )
+add_subdirectory(importscheck )
diff --git a/tests/auto/qml/codemodel/check/CMakeLists.txt b/tests/auto/qml/codemodel/check/CMakeLists.txt
new file mode 100644
index 0000000000..fdcd1334bd
--- /dev/null
+++ b/tests/auto/qml/codemodel/check/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_test(tst_qml_check
+ DEPENDS qmljs
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_check.cpp
+)
diff --git a/tests/auto/qml/codemodel/dependencies/CMakeLists.txt b/tests/auto/qml/codemodel/dependencies/CMakeLists.txt
new file mode 100644
index 0000000000..544e771873
--- /dev/null
+++ b/tests/auto/qml/codemodel/dependencies/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_qtc_test(tst_qml_dependencies
+ DEPENDS qmljs QmlJSTools ExtensionSystem Utils
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/plugins"
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_dependencies.cpp
+)
diff --git a/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
index 842cec7e4e..79ce9cec1b 100644
--- a/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
+++ b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
@@ -112,7 +112,7 @@ private:
void tst_Dependencies::initTestCase()
{
- m_path = QLatin1Literal(TESTSRCDIR "/samples");
+ m_path = QLatin1String(TESTSRCDIR "/samples");
m_basePaths.append(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath));
@@ -148,7 +148,7 @@ void tst_Dependencies::test()
QStringList paths(m_basePaths);
paths << m_path;
for (auto p: paths)
- lPaths.maybeInsert(Utils::FileName::fromString(p), Dialect::Qml);
+ lPaths.maybeInsert(Utils::FilePath::fromString(p), Dialect::Qml);
ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
ModelManagerInterface::instance(), false);
diff --git a/tests/auto/qml/codemodel/ecmascript7/CMakeLists.txt b/tests/auto/qml/codemodel/ecmascript7/CMakeLists.txt
new file mode 100644
index 0000000000..62a0ba588d
--- /dev/null
+++ b/tests/auto/qml/codemodel/ecmascript7/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_qtc_test(tst_qml_ecmascript7
+ DEPENDS qmljs QmlJSTools ExtensionSystem Utils
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/plugins"
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_ecmascript7.cpp
+)
diff --git a/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp b/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp
index fd6a54b59b..735daa04f7 100644
--- a/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp
+++ b/tests/auto/qml/codemodel/ecmascript7/tst_ecmascript7.cpp
@@ -124,7 +124,7 @@ private slots:
void test();
private:
- QList<QFileInfo> m_files;
+ QFileInfoList m_files;
QStringList m_basePaths;
};
@@ -134,13 +134,13 @@ void tst_Ecmascript::initTestCase()
QDirIterator it(sampledir, QDirIterator::Subdirectories);
- QStringList skipList = readSkipList(sampledir, QLatin1Literal("skip.txt"));
+ QStringList skipList = readSkipList(sampledir, QLatin1String("skip.txt"));
while (it.hasNext()) {
QString path = it.next();
if (skipList.contains(path))
continue;
QFileInfo f(path);
- if (f.isFile() && f.suffix() == QLatin1Literal("js"))
+ if (f.isFile() && f.suffix() == QLatin1String("js"))
m_files << f;
}
@@ -174,7 +174,7 @@ void tst_Ecmascript::test()
PathsAndLanguages lPaths;
QStringList paths(m_basePaths);
for (auto p: paths)
- lPaths.maybeInsert(Utils::FileName::fromString(p), Dialect::Qml);
+ lPaths.maybeInsert(Utils::FilePath::fromString(p), Dialect::Qml);
ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
ModelManagerInterface::instance(), false);
diff --git a/tests/auto/qml/codemodel/importscheck/CMakeLists.txt b/tests/auto/qml/codemodel/importscheck/CMakeLists.txt
new file mode 100644
index 0000000000..5f994a58ee
--- /dev/null
+++ b/tests/auto/qml/codemodel/importscheck/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_qtc_test(tst_qml_importscheck
+ DEPENDS qmljs QmlJSTools Utils CPlusPlus
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/plugins"
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_importscheck.cpp
+)
diff --git a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
index dcedd6df69..0c11438e12 100644
--- a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
+++ b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
@@ -67,7 +67,7 @@ void scanDir(const QString &dir)
{
QFutureInterface<void> result;
PathsAndLanguages paths;
- paths.maybeInsert(Utils::FileName::fromString(dir), Dialect::Qml);
+ paths.maybeInsert(Utils::FilePath::fromString(dir), Dialect::Qml);
ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), paths,
ModelManagerInterface::instance(), false);
ViewerContext vCtx = ViewerContext(QStringList(), QStringList(dir));
@@ -178,7 +178,7 @@ void tst_ImportCheck::test()
QFutureInterface<void> result;
PathsAndLanguages lPaths;
foreach (const QString &path, paths)
- lPaths.maybeInsert(Utils::FileName::fromString(path), Dialect::Qml);
+ lPaths.maybeInsert(Utils::FilePath::fromString(path), Dialect::Qml);
ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
ModelManagerInterface::instance(), false);
ViewerContext vCtx(QStringList(), paths);
diff --git a/tests/auto/qml/persistenttrie/CMakeLists.txt b/tests/auto/qml/persistenttrie/CMakeLists.txt
new file mode 100644
index 0000000000..2ab22d0919
--- /dev/null
+++ b/tests/auto/qml/persistenttrie/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_test(tst_qml_testtrie
+ DEPENDS qmljs
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_testtrie.cpp
+)
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 2f9a2f1b2c..c0da615d8b 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -9,13 +9,13 @@ SUBDIRS += \
qrcparser \
persistenttrie
-DO_NOT_BUILD_QMLDESIGNER = $$(DO_NOT_BUILD_QMLDESIGNER)
-isEmpty(DO_NOT_BUILD_QMLDESIGNER):qtHaveModule(quick-private) {
+QTC_DO_NOT_BUILD_QMLDESIGNER = $$(QTC_DO_NOT_BUILD_QMLDESIGNER)
+isEmpty(QTC_DO_NOT_BUILD_QMLDESIGNER):qtHaveModule(quick-private) {
SUBDIRS += qmldesigner
} else {
!qtHaveModule(quick-private) {
warning("QmlDesigner plugin has been disabled since the Qt Quick module is not available.")
} else {
- warning("QmlDesigner plugin has been disabled since DO_NOT_BUILD_QMLDESIGNER is set.")
+ warning("QmlDesigner plugin has been disabled since QTC_DO_NOT_BUILD_QMLDESIGNER is set.")
}
}
diff --git a/tests/auto/qml/qmldesigner/CMakeLists.txt b/tests/auto/qml/qmldesigner/CMakeLists.txt
new file mode 100644
index 0000000000..9d4ab11adc
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(coretests)
diff --git a/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt
new file mode 100644
index 0000000000..3e83f280af
--- /dev/null
+++ b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt
@@ -0,0 +1,20 @@
+# TODO: fix compiler errors
+return()
+
+add_qtc_test(tst_qml_testcore
+ DEPENDS qmljs Utils QmlEditorWidgets CPlusPlus Core QmlJSEditor
+ INCLUDES
+ "${CMAKE_SOURCE_DIR}/src/plugins/qmldesigner/designercore/include"
+ "${CMAKE_SOURCE_DIR}/src/plugins/qmldesigner/designercore"
+ "${CMAKE_SOURCE_DIR}/share/qtcreator/qml/qmlpuppet/interfaces"
+ "${CMAKE_SOURCE_DIR}/share/qtcreator/qml/qmlpuppet/types"
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES
+ ../data/testfiles.qrc
+ ../testview.cpp ../testview.h
+ testrewriterview.cpp testrewriterview.h
+ tst_testcore.cpp tst_testcore.h
+)
diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp
index 1a4eda3bcc..31ea4e5914 100644
--- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp
+++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp
@@ -185,7 +185,7 @@ void tst_TestCore::initTestCase()
QFutureInterface<void> result;
QmlJS::PathsAndLanguages lPaths;
- lPaths.maybeInsert(Utils::FileName::fromString(basePaths.first()), QmlJS::Dialect::Qml);
+ lPaths.maybeInsert(Utils::FilePath::fromString(basePaths.first()), QmlJS::Dialect::Qml);
QmlJS::ModelManagerInterface::importScan(result, QmlJS::ModelManagerInterface::workingCopy(),
lPaths, QmlJS::ModelManagerInterface::instance(), false);
@@ -1017,6 +1017,44 @@ void tst_TestCore::testRewriterUnicodeChars()
QCOMPARE(textEdit.toPlainText(), unicodeChar);
}
+void tst_TestCore::testRewriterTransactionAddingAfterReparenting()
+{
+ const QLatin1String qmlString("\n"
+ "import QtQuick 2.0\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());
+
+ QVERIFY(testRewriterView->errors().isEmpty());
+
+ ModelNode rootModelNode = testRewriterView->rootModelNode();
+ QVERIFY(rootModelNode.isValid());
+
+ {
+ /* Regression test
+ * If a node is not a direct child node of the root item we did get an exception when adding properties
+ * after the reparent */
+
+ RewriterTransaction transaction = testRewriterView->beginRewriterTransaction("TEST");
+ ModelNode rectangle = testRewriterView->createModelNode("QtQuick.Rectangle", 2, 0);
+ rootModelNode.nodeListProperty("data").reparentHere(rectangle);
+ ModelNode rectangle2 = testRewriterView->createModelNode("QtQuick.Rectangle", 2, 0);
+ rectangle.nodeListProperty("data").reparentHere(rectangle2);
+
+ rectangle2.variantProperty("width").setValue(100);
+ }
+}
+
void tst_TestCore::testRewriterForGradientMagic()
{
const QLatin1String qmlString("\n"
diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h
index 3f1eec576b..92f3b17161 100644
--- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h
+++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h
@@ -140,6 +140,7 @@ private slots:
void testRewriterImports();
void testRewriterChangeImports();
void testRewriterUnicodeChars();
+ void testRewriterTransactionAddingAfterReparenting();
//
// unit tests QmlModelNodeFacade/QmlModelState
diff --git a/tests/auto/qml/qmleditor/CMakeLists.txt b/tests/auto/qml/qmleditor/CMakeLists.txt
new file mode 100644
index 0000000000..93a723626e
--- /dev/null
+++ b/tests/auto/qml/qmleditor/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(qmlcodeformatter)
diff --git a/tests/auto/qml/qmleditor/qmlcodeformatter/CMakeLists.txt b/tests/auto/qml/qmleditor/qmlcodeformatter/CMakeLists.txt
new file mode 100644
index 0000000000..d8daee0578
--- /dev/null
+++ b/tests/auto/qml/qmleditor/qmlcodeformatter/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_test(tst_qml_qmlcodeformatter
+ DEPENDS qmljs QmlJSTools TextEditor
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_qmlcodeformatter.cpp
+)
diff --git a/tests/auto/qml/qmljssimplereader/CMakeLists.txt b/tests/auto/qml/qmljssimplereader/CMakeLists.txt
new file mode 100644
index 0000000000..4742047d7b
--- /dev/null
+++ b/tests/auto/qml/qmljssimplereader/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_test(tst_qml_qmljssimplereader
+ DEPENDS qmljs
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_qmljssimplereader.cpp
+)
diff --git a/tests/auto/qml/qmlprojectmanager/CMakeLists.txt b/tests/auto/qml/qmlprojectmanager/CMakeLists.txt
new file mode 100644
index 0000000000..f7c00d44bd
--- /dev/null
+++ b/tests/auto/qml/qmlprojectmanager/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(fileformat)
diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/CMakeLists.txt b/tests/auto/qml/qmlprojectmanager/fileformat/CMakeLists.txt
new file mode 100644
index 0000000000..5d7f7c79bf
--- /dev/null
+++ b/tests/auto/qml/qmlprojectmanager/fileformat/CMakeLists.txt
@@ -0,0 +1,15 @@
+get_target_property(QmlProjectManagerSources QmlProjectManager SOURCES)
+foreach(source IN LISTS QmlProjectManagerSources)
+ if (source MATCHES "fileformat")
+ list(APPEND fileformat_sources "${CMAKE_SOURCE_DIR}/src/plugins/qmlprojectmanager/${source}")
+ endif()
+endforeach()
+
+add_qtc_test(tst_qml_fileformat
+ DEPENDS qmljs Utils
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/plugins/qmlprojectmanager/fileformat"
+ DEFINES
+ QT_CREATOR
+ SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_fileformat.cpp ${fileformat_sources}
+)
diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
index bca2e8d7a8..fe61dd0ea5 100644
--- a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
+++ b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp
@@ -54,7 +54,7 @@ QString testDataDir = QLatin1String(SRCDIR "/data");
static QmlProjectItem *loadQmlProject(QString name, QString *error)
{
return QmlProjectFileFormat::parseProjectFile(
- Utils::FileName::fromString(testDataDir).appendPath(name).appendString(".qmlproject"), error);
+ Utils::FilePath::fromString(testDataDir).pathAppended(name + ".qmlproject"), error);
}
void tst_FileFormat::testFileFilter()
diff --git a/tests/auto/qml/qrcparser/CMakeLists.txt b/tests/auto/qml/qrcparser/CMakeLists.txt
new file mode 100644
index 0000000000..bcecb807e4
--- /dev/null
+++ b/tests/auto/qml/qrcparser/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_test(tst_qml_qrcparser
+ DEPENDS qmljs Utils
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_qrcparser.cpp
+)
diff --git a/tests/auto/qml/qrcparser/qrcparser.pro b/tests/auto/qml/qrcparser/qrcparser.pro
index 571c0a11a3..cb991a4e8f 100644
--- a/tests/auto/qml/qrcparser/qrcparser.pro
+++ b/tests/auto/qml/qrcparser/qrcparser.pro
@@ -1,5 +1,5 @@
#include(../shared/shared.pri)
-QTC_PLUGIN_DEPENDS += qmljstools
+QTC_LIB_DEPENDS += utils
include(../../qttest.pri)
#DEFINES+=CPLUSPLUS_BUILD_STATIC_LIB
include($$IDE_SOURCE_TREE/src/rpath.pri)
diff --git a/tests/auto/qml/qrcparser/qrcparser.qbs b/tests/auto/qml/qrcparser/qrcparser.qbs
index f08e32a063..432dca6d8b 100644
--- a/tests/auto/qml/qrcparser/qrcparser.qbs
+++ b/tests/auto/qml/qrcparser/qrcparser.qbs
@@ -1,9 +1,8 @@
import qbs
QtcAutotest {
- name: "QML qrc parser autotest"
- Depends { name: "QmlJS" }
- Depends { name: "QmlJSTools" }
+ name: "qrc parser autotest"
+ Depends { name: "Utils" }
files: "tst_qrcparser.cpp"
cpp.defines: base.concat(['TESTSRCDIR="' + path + '"'])
}
diff --git a/tests/auto/qml/qrcparser/tst_qrcparser.cpp b/tests/auto/qml/qrcparser/tst_qrcparser.cpp
index d8c3f03c36..10f3dfd10c 100644
--- a/tests/auto/qml/qrcparser/tst_qrcparser.cpp
+++ b/tests/auto/qml/qrcparser/tst_qrcparser.cpp
@@ -27,9 +27,9 @@
#include <QDebug>
#include <QLocale>
-#include <qmljs/qmljsqrcparser.h>
+#include <utils/qrcparser.h>
-using namespace QmlJS;
+using namespace Utils;
class tst_QrcParser: public QObject
{
diff --git a/tests/auto/qml/reformatter/CMakeLists.txt b/tests/auto/qml/reformatter/CMakeLists.txt
new file mode 100644
index 0000000000..a9119ccd93
--- /dev/null
+++ b/tests/auto/qml/reformatter/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_qtc_test(tst_qml_reformatter
+ DEPENDS qmljs
+ DEFINES
+ QT_CREATOR
+ QTCREATORDIR="${CMAKE_SOURCE_DIR}"
+ TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
+ SOURCES tst_reformatter.cpp
+)
diff --git a/tests/auto/qml/reformatter/comments.qml b/tests/auto/qml/reformatter/comments.qml
index 4ced7eb0e8..d2caa1b555 100644
--- a/tests/auto/qml/reformatter/comments.qml
+++ b/tests/auto/qml/reformatter/comments.qml
@@ -21,5 +21,13 @@ Item {
{
console.log("test")
}
+
+ var a = 1
+ if (a > 0) {
+ console.log("positive")
+ } // Final condition
+ else {
+ console.log("negative or zero")
+ }
}
}
diff --git a/tests/auto/qml/reformatter/enum.qml b/tests/auto/qml/reformatter/enum.qml
new file mode 100644
index 0000000000..769386494d
--- /dev/null
+++ b/tests/auto/qml/reformatter/enum.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Item {
+ enum Test {
+ A,
+ B
+ }
+
+ enum TestWithValues {
+ A = 11.1,
+ B,
+ C = 3
+ }
+}
diff --git a/tests/auto/qml/reformatter/jssyntax.js b/tests/auto/qml/reformatter/jssyntax.js
index 5ef1a2adcd..d651cd7822 100644
--- a/tests/auto/qml/reformatter/jssyntax.js
+++ b/tests/auto/qml/reformatter/jssyntax.js
@@ -1,6 +1,10 @@
var x
var y = 12
+var a_var = 1
+let a_let = 2
+const a_const = 3
+
function foo(a, b) {
x = 15
x += 4
@@ -28,6 +32,12 @@ while (true) {
for (var x in a) {
print(a[x])
}
+ for (let x in a) {
+ print(a[x])
+ }
+ for (const x in a) {
+ print(a[x])
+ }
do {
a = x
diff --git a/tests/auto/qml/reformatter/objectliteral.js b/tests/auto/qml/reformatter/objectliteral.js
index 37f6863374..d260712166 100644
--- a/tests/auto/qml/reformatter/objectliteral.js
+++ b/tests/auto/qml/reformatter/objectliteral.js
@@ -10,3 +10,5 @@ var x = {
},
"z": 12
}
+
+var empty_object = {}
diff --git a/tests/auto/qml/reformatter/qmlsingleton.qml b/tests/auto/qml/reformatter/qmlsingleton.qml
index d64f554097..05a08e7de4 100644
--- a/tests/auto/qml/reformatter/qmlsingleton.qml
+++ b/tests/auto/qml/reformatter/qmlsingleton.qml
@@ -2,5 +2,4 @@ pragma Singleton
import QtQuick 2.0
-Item {
-}
+Item {}
diff --git a/tests/auto/qml/reformatter/qmlsyntax.qml b/tests/auto/qml/reformatter/qmlsyntax.qml
index ded863106a..3e55503049 100644
--- a/tests/auto/qml/reformatter/qmlsyntax.qml
+++ b/tests/auto/qml/reformatter/qmlsyntax.qml
@@ -9,6 +9,8 @@ Text {
property int foo
property alias bar: x
property list<QtObject> pro
+ property Part.Particles particles
+ property list<Part.Particles> particlesList
default property int def
property var baz: Rectangle {
width: 20
@@ -45,4 +47,6 @@ Text {
function foo(a, b) {
x = a + 12 * b
}
+
+ value: Rectangle {}
}
diff --git a/tests/auto/qtcprocess/CMakeLists.txt b/tests/auto/qtcprocess/CMakeLists.txt
new file mode 100644
index 0000000000..16b9f4a9fa
--- /dev/null
+++ b/tests/auto/qtcprocess/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_qtcprocess
+ DEPENDS Utils
+ SOURCES tst_qtcprocess.cpp
+)
diff --git a/tests/auto/runextensions/CMakeLists.txt b/tests/auto/runextensions/CMakeLists.txt
new file mode 100644
index 0000000000..73455f7518
--- /dev/null
+++ b/tests/auto/runextensions/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_runextensions
+ DEPENDS Utils
+ SOURCES tst_runextensions.cpp
+)
diff --git a/tests/auto/sdktool/CMakeLists.txt b/tests/auto/sdktool/CMakeLists.txt
new file mode 100644
index 0000000000..65d83c00e3
--- /dev/null
+++ b/tests/auto/sdktool/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_qtc_test(tst_sdktool
+ DEPENDS Utils
+ DEFINES SDKTOOL_DIR="${IDE_LIBEXEC_PATH}"
+ SOURCES tst_sdktool.cpp
+)
diff --git a/tests/auto/sdktool/tst_sdktool.cpp b/tests/auto/sdktool/tst_sdktool.cpp
index 3a6eeca2f9..4cb4876dd8 100644
--- a/tests/auto/sdktool/tst_sdktool.cpp
+++ b/tests/auto/sdktool/tst_sdktool.cpp
@@ -43,7 +43,9 @@ void SdktoolTest::testSdktool()
process.start(rootDir.absoluteFilePath(QLatin1String("sdktool")),
QStringList() << QLatin1String("-test"));
process.waitForFinished();
- qDebug() << process.readAllStandardError();
+ QByteArray output = process.readAllStandardError();
+ for (auto line : output.split('\n'))
+ qDebug() << line;
QCOMPARE(process.exitCode(), 0);
}
diff --git a/tests/auto/ssh/CMakeLists.txt b/tests/auto/ssh/CMakeLists.txt
new file mode 100644
index 0000000000..590144d3bd
--- /dev/null
+++ b/tests/auto/ssh/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_ssh
+ DEPENDS Utils QtcSsh
+ SOURCES tst_ssh.cpp
+)
diff --git a/tests/auto/ssh/tst_ssh.cpp b/tests/auto/ssh/tst_ssh.cpp
index 22e7062fde..72260c2c9a 100644
--- a/tests/auto/ssh/tst_ssh.cpp
+++ b/tests/auto/ssh/tst_ssh.cpp
@@ -27,6 +27,7 @@
#include <ssh/sftptransfer.h>
#include <ssh/sshconnection.h>
#include <ssh/sshremoteprocessrunner.h>
+#include <ssh/sshsettings.h>
#include <utils/environment.h>
#include <utils/temporarydirectory.h>
@@ -171,8 +172,10 @@ void tst_Ssh::errorHandling()
connection.connectToHost();
loop.exec();
QVERIFY(timer.isActive());
- QCOMPARE(connection.state(), SshConnection::Unconnected);
- QVERIFY(!connection.errorString().isEmpty());
+ const bool expectConnected = !SshSettings::connectionSharingEnabled();
+ QCOMPARE(connection.state(), expectConnected ? SshConnection::Connected
+ : SshConnection::Unconnected);
+ QCOMPARE(connection.errorString().isEmpty(), expectConnected);
QVERIFY(!disconnected);
QVERIFY2(dataReceived.isEmpty(), qPrintable(dataReceived));
}
@@ -313,8 +316,7 @@ void tst_Ssh::remoteProcessInput()
SshConnection connection(params);
QVERIFY(waitForConnection(connection));
- SshRemoteProcessPtr catProcess
- = connection.createRemoteProcess(QString::fromLatin1("/bin/cat").toUtf8());
+ SshRemoteProcessPtr catProcess = connection.createRemoteProcess("/bin/cat");
QEventLoop loop;
connect(catProcess.get(), &SshRemoteProcess::started, &loop, &QEventLoop::quit);
connect(catProcess.get(), &SshRemoteProcess::done, &loop, &QEventLoop::quit);
@@ -375,7 +377,7 @@ void tst_Ssh::sftp()
};
FilesToTransfer filesToUpload;
std::srand(QDateTime::currentDateTime().toSecsSinceEpoch());
- for (int i = 0; i < 1000; ++i) {
+ 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()));
@@ -414,7 +416,7 @@ void tst_Ssh::sftp()
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
timer.setSingleShot(true);
- timer.setInterval((params.timeout + 5) * 1000);
+ timer.setInterval(30 * 1000);
timer.start();
upload->start();
loop.exec();
@@ -454,7 +456,7 @@ void tst_Ssh::sftp()
// Download the uploaded files to a different location
const QStringList allUploadedFileNames
= QDir(dirForFilesToUpload.path()).entryList(QDir::Files);
- QCOMPARE(allUploadedFileNames.size(), 1001);
+ QCOMPARE(allUploadedFileNames.size(), 101);
for (const QString &fileName : allUploadedFileNames) {
const QString localFilePath = dirForFilesToUpload.path() + '/' + fileName;
const QString remoteFilePath = getRemoteFilePath(fileName);
@@ -463,7 +465,7 @@ void tst_Ssh::sftp()
QVERIFY(downloadJob != SftpInvalidJob);
jobs << downloadJob;
}
- QCOMPARE(jobs.size(), 1001);
+ QCOMPARE(jobs.size(), 101);
loop.exec();
QVERIFY(!invalidFinishedSignal);
QVERIFY2(jobError.isEmpty(), qPrintable(jobError));
@@ -491,6 +493,7 @@ void tst_Ssh::sftp()
}
// 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);
diff --git a/tests/auto/toolchaincache/CMakeLists.txt b/tests/auto/toolchaincache/CMakeLists.txt
new file mode 100644
index 0000000000..5a2115f09b
--- /dev/null
+++ b/tests/auto/toolchaincache/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_qtc_test(tst_toolchaincache
+ DEPENDS ProjectExplorer Qt5::Gui
+ INCLUDES "${CMAKE_SOURCE_DIR}/src/libs"
+ SOURCES tst_toolchaincache.cpp
+)
diff --git a/tests/auto/toolchaincache/toolchaincache.pro b/tests/auto/toolchaincache/toolchaincache.pro
index 5dea077c20..cdb1ca0bb7 100644
--- a/tests/auto/toolchaincache/toolchaincache.pro
+++ b/tests/auto/toolchaincache/toolchaincache.pro
@@ -1,5 +1,3 @@
-QT -= gui
-
include(../qttest.pri)
SOURCES += \
diff --git a/tests/auto/toolchaincache/toolchaincache.qbs b/tests/auto/toolchaincache/toolchaincache.qbs
index c814441539..7f1a2adbf1 100644
--- a/tests/auto/toolchaincache/toolchaincache.qbs
+++ b/tests/auto/toolchaincache/toolchaincache.qbs
@@ -3,6 +3,7 @@ import qbs
QtcAutotest {
name: "ToolChainCache autotest"
Depends { name: "ProjectExplorer" }
+ Depends { name: "Qt.gui" } // For QIcon in Task
Group {
name: "Test sources"
files: "tst_toolchaincache.cpp"
diff --git a/tests/auto/tracing/CMakeLists.txt b/tests/auto/tracing/CMakeLists.txt
new file mode 100644
index 0000000000..5ad3ed915d
--- /dev/null
+++ b/tests/auto/tracing/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_subdirectory(flamegraph)
+add_subdirectory(flamegraphview)
+add_subdirectory(timelineabstractrenderer)
+add_subdirectory(timelineitemsrenderpass)
+add_subdirectory(timelinemodel)
+add_subdirectory(timelinemodelaggregator)
+add_subdirectory(timelinenotesmodel)
+add_subdirectory(timelinenotesrenderpass)
+add_subdirectory(timelineoverviewrenderer)
+add_subdirectory(timelinerenderer)
+add_subdirectory(timelinerenderpass)
+add_subdirectory(timelinerenderstate)
+add_subdirectory(timelineselectionrenderpass)
+add_subdirectory(timelinezoomcontrol)
diff --git a/tests/auto/tracing/flamegraph/CMakeLists.txt b/tests/auto/tracing/flamegraph/CMakeLists.txt
new file mode 100644
index 0000000000..eee7081aa2
--- /dev/null
+++ b/tests/auto/tracing/flamegraph/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_flamegraph
+ DEPENDS Tracing Qt5::Quick
+ SOURCES tst_flamegraph.cpp
+)
diff --git a/tests/auto/tracing/flamegraphview/CMakeLists.txt b/tests/auto/tracing/flamegraphview/CMakeLists.txt
new file mode 100644
index 0000000000..2a247c9ea1
--- /dev/null
+++ b/tests/auto/tracing/flamegraphview/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_qtc_test(tst_tracing_flamegraphview
+ DEPENDS Tracing Qt5::QuickWidgets Qt5::Quick Utils
+ SOURCES
+ tst_flamegraphview.cpp
+ flamegraphview.qrc
+)
diff --git a/tests/auto/tracing/timelineabstractrenderer/CMakeLists.txt b/tests/auto/tracing/timelineabstractrenderer/CMakeLists.txt
new file mode 100644
index 0000000000..5bf14c179c
--- /dev/null
+++ b/tests/auto/tracing/timelineabstractrenderer/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelineabstractrenderer
+ DEPENDS Tracing Qt5::Gui Qt5::Quick
+ SOURCES tst_timelineabstractrenderer.cpp
+)
diff --git a/tests/auto/tracing/timelineitemsrenderpass/CMakeLists.txt b/tests/auto/tracing/timelineitemsrenderpass/CMakeLists.txt
new file mode 100644
index 0000000000..056880e54c
--- /dev/null
+++ b/tests/auto/tracing/timelineitemsrenderpass/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelineitemsrenderpass
+ DEPENDS Tracing Qt5::Quick
+ SOURCES tst_timelineitemsrenderpass.cpp
+)
diff --git a/tests/auto/tracing/timelinemodel/CMakeLists.txt b/tests/auto/tracing/timelinemodel/CMakeLists.txt
new file mode 100644
index 0000000000..198f71e9b8
--- /dev/null
+++ b/tests/auto/tracing/timelinemodel/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinemodel
+ DEPENDS Tracing Qt5::Gui
+ SOURCES tst_timelinemodel.cpp
+)
diff --git a/tests/auto/tracing/timelinemodelaggregator/CMakeLists.txt b/tests/auto/tracing/timelinemodelaggregator/CMakeLists.txt
new file mode 100644
index 0000000000..7845c6ad51
--- /dev/null
+++ b/tests/auto/tracing/timelinemodelaggregator/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinemodelaggregator
+ DEPENDS Tracing Qt5::Gui
+ SOURCES tst_timelinemodelaggregator.cpp
+)
diff --git a/tests/auto/tracing/timelinenotesmodel/CMakeLists.txt b/tests/auto/tracing/timelinenotesmodel/CMakeLists.txt
new file mode 100644
index 0000000000..d59241ad98
--- /dev/null
+++ b/tests/auto/tracing/timelinenotesmodel/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinenotesmodel
+ DEPENDS Tracing Qt5::Gui
+ SOURCES tst_timelinenotesmodel.cpp
+)
diff --git a/tests/auto/tracing/timelinenotesrenderpass/CMakeLists.txt b/tests/auto/tracing/timelinenotesrenderpass/CMakeLists.txt
new file mode 100644
index 0000000000..4bed7af0d5
--- /dev/null
+++ b/tests/auto/tracing/timelinenotesrenderpass/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinenotesrenderpass
+ DEPENDS Tracing Qt5::Quick
+ SOURCES tst_timelinenotesrenderpass.cpp
+)
diff --git a/tests/auto/tracing/timelineoverviewrenderer/CMakeLists.txt b/tests/auto/tracing/timelineoverviewrenderer/CMakeLists.txt
new file mode 100644
index 0000000000..275765765d
--- /dev/null
+++ b/tests/auto/tracing/timelineoverviewrenderer/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelineoverviewrenderer
+ DEPENDS Tracing Qt5::Quick
+ SOURCES tst_timelineoverviewrenderer.cpp
+)
diff --git a/tests/auto/tracing/timelinerenderer/CMakeLists.txt b/tests/auto/tracing/timelinerenderer/CMakeLists.txt
new file mode 100644
index 0000000000..30e44a5cd2
--- /dev/null
+++ b/tests/auto/tracing/timelinerenderer/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinerenderer
+ DEPENDS Tracing Qt5::Gui Qt5::Quick
+ SOURCES tst_timelinerenderer.cpp
+)
diff --git a/tests/auto/tracing/timelinerenderpass/CMakeLists.txt b/tests/auto/tracing/timelinerenderpass/CMakeLists.txt
new file mode 100644
index 0000000000..3f0cd33f20
--- /dev/null
+++ b/tests/auto/tracing/timelinerenderpass/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinerenderpass
+ DEPENDS Tracing
+ SOURCES tst_timelinerenderpass.cpp
+)
diff --git a/tests/auto/tracing/timelinerenderstate/CMakeLists.txt b/tests/auto/tracing/timelinerenderstate/CMakeLists.txt
new file mode 100644
index 0000000000..53f0b67415
--- /dev/null
+++ b/tests/auto/tracing/timelinerenderstate/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinerenderstate
+ DEPENDS Tracing Qt5::Gui Qt5::Quick
+ SOURCES tst_timelinerenderstate.cpp
+)
diff --git a/tests/auto/tracing/timelineselectionrenderpass/CMakeLists.txt b/tests/auto/tracing/timelineselectionrenderpass/CMakeLists.txt
new file mode 100644
index 0000000000..a3e3c9af67
--- /dev/null
+++ b/tests/auto/tracing/timelineselectionrenderpass/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelineselectionrenderpass
+ DEPENDS Tracing Qt5::Quick
+ SOURCES tst_timelineselectionrenderpass.cpp
+)
diff --git a/tests/auto/tracing/timelinezoomcontrol/CMakeLists.txt b/tests/auto/tracing/timelinezoomcontrol/CMakeLists.txt
new file mode 100644
index 0000000000..1e5f7989e9
--- /dev/null
+++ b/tests/auto/tracing/timelinezoomcontrol/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_tracing_timelinezoomcontrol
+ DEPENDS Tracing Qt5::Gui
+ SOURCES tst_timelinezoomcontrol.cpp
+)
diff --git a/tests/auto/treeviewfind/CMakeLists.txt b/tests/auto/treeviewfind/CMakeLists.txt
new file mode 100644
index 0000000000..6ce09aa209
--- /dev/null
+++ b/tests/auto/treeviewfind/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_treeviewfind
+ DEPENDS Core
+ SOURCES tst_treeviewfind.cpp
+)
diff --git a/tests/auto/utils/CMakeLists.txt b/tests/auto/utils/CMakeLists.txt
new file mode 100644
index 0000000000..74f1d6f819
--- /dev/null
+++ b/tests/auto/utils/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_subdirectory(ansiescapecodehandler)
+add_subdirectory(fileutils)
+add_subdirectory(fuzzymatcher)
+add_subdirectory(settings)
+add_subdirectory(stringutils)
+add_subdirectory(templateengine)
+add_subdirectory(treemodel)
diff --git a/tests/auto/utils/ansiescapecodehandler/CMakeLists.txt b/tests/auto/utils/ansiescapecodehandler/CMakeLists.txt
new file mode 100644
index 0000000000..971849d8b2
--- /dev/null
+++ b/tests/auto/utils/ansiescapecodehandler/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_utils_ansiescapecodehandler
+ DEPENDS Utils
+ SOURCES tst_ansiescapecodehandler.cpp
+)
diff --git a/tests/auto/utils/fileutils/CMakeLists.txt b/tests/auto/utils/fileutils/CMakeLists.txt
new file mode 100644
index 0000000000..0f766bc999
--- /dev/null
+++ b/tests/auto/utils/fileutils/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_utils_fileutils
+ DEPENDS Utils
+ SOURCES tst_fileutils.cpp
+)
diff --git a/tests/auto/utils/fileutils/tst_fileutils.cpp b/tests/auto/utils/fileutils/tst_fileutils.cpp
index 2b588c533e..2102bd0f06 100644
--- a/tests/auto/utils/fileutils/tst_fileutils.cpp
+++ b/tests/auto/utils/fileutils/tst_fileutils.cpp
@@ -80,7 +80,7 @@ void tst_fileutils::parentDir()
QFETCH(QString, parentPath);
QFETCH(QString, expectFailMessage);
- FileName result = FileName::fromString(path).parentDir();
+ FilePath result = FilePath::fromString(path).parentDir();
if (!expectFailMessage.isEmpty())
QEXPECT_FAIL("", expectFailMessage.toUtf8().constData(), Continue);
QCOMPARE(result.toString(), parentPath);
@@ -120,7 +120,7 @@ void tst_fileutils::isChildOf()
QFETCH(QString, childPath);
QFETCH(bool, result);
- bool res = FileName::fromString(childPath).isChildOf(FileName::fromString(path));
+ bool res = FilePath::fromString(childPath).isChildOf(FilePath::fromString(path));
QCOMPARE(res, result);
}
@@ -161,7 +161,7 @@ void tst_fileutils::fileName()
QFETCH(QString, path);
QFETCH(int, components);
QFETCH(QString, result);
- QCOMPARE(FileName::fromString(path).fileName(components), result);
+ QCOMPARE(FilePath::fromString(path).fileName(components), result);
}
QTEST_APPLESS_MAIN(tst_fileutils)
diff --git a/tests/auto/utils/fuzzymatcher/CMakeLists.txt b/tests/auto/utils/fuzzymatcher/CMakeLists.txt
new file mode 100644
index 0000000000..fb5198fe08
--- /dev/null
+++ b/tests/auto/utils/fuzzymatcher/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_utils_fuzzymatcher
+ DEPENDS Utils
+ SOURCES tst_fuzzymatcher.cpp
+)
diff --git a/tests/auto/utils/settings/CMakeLists.txt b/tests/auto/utils/settings/CMakeLists.txt
new file mode 100644
index 0000000000..5bf072b08a
--- /dev/null
+++ b/tests/auto/utils/settings/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_utils_settings
+ DEPENDS Utils
+ SOURCES tst_settings.cpp
+)
diff --git a/tests/auto/utils/settings/tst_settings.cpp b/tests/auto/utils/settings/tst_settings.cpp
index 867f9bbe91..931c601a6e 100644
--- a/tests/auto/utils/settings/tst_settings.cpp
+++ b/tests/auto/utils/settings/tst_settings.cpp
@@ -70,18 +70,18 @@ public:
class BasicTestSettingsAccessor : public Utils::MergingSettingsAccessor
{
public:
- BasicTestSettingsAccessor(const Utils::FileName &baseName = Utils::FileName::fromString("/foo/bar"),
+ BasicTestSettingsAccessor(const Utils::FilePath &baseName = Utils::FilePath::fromString("/foo/bar"),
const QByteArray &id = QByteArray(TESTACCESSOR_DEFAULT_ID));
using Utils::MergingSettingsAccessor::addVersionUpgrader;
- QHash<Utils::FileName, QVariantMap> files() const { return m_files; }
- void addFile(const Utils::FileName &path, const QVariantMap &data) const { m_files.insert(path, data); }
- Utils::FileNameList fileNames() const { return m_files.keys(); }
- QVariantMap fileContents(const Utils::FileName &path) const { return m_files.value(path); }
+ QHash<Utils::FilePath, QVariantMap> files() const { return m_files; }
+ void addFile(const Utils::FilePath &path, const QVariantMap &data) const { m_files.insert(path, data); }
+ Utils::FilePathList fileNames() const { return m_files.keys(); }
+ QVariantMap fileContents(const Utils::FilePath &path) const { return m_files.value(path); }
protected:
- RestoreData readFile(const Utils::FileName &path) const override
+ RestoreData readFile(const Utils::FilePath &path) const override
{
if (!m_files.contains(path))
return RestoreData("File not found.", "File not found.", Issue::Type::ERROR);
@@ -108,7 +108,7 @@ protected:
return qMakePair(key, secondary);
}
- Utils::optional<Issue> writeFile(const Utils::FileName &path, const QVariantMap &data) const override
+ Utils::optional<Issue> writeFile(const Utils::FilePath &path, const QVariantMap &data) const override
{
if (data.isEmpty()) {
return Issue(QCoreApplication::translate("Utils::SettingsAccessor", "Failed to Write File"),
@@ -121,7 +121,7 @@ protected:
}
private:
- mutable QHash<Utils::FileName, QVariantMap> m_files;
+ mutable QHash<Utils::FilePath, QVariantMap> m_files;
};
// --------------------------------------------------------------------
@@ -137,10 +137,10 @@ public:
VersionedBackUpStrategy(accessor)
{ }
- FileNameList readFileCandidates(const Utils::FileName &baseFileName) const
+ FilePathList readFileCandidates(const Utils::FilePath &baseFileName) const
{
return Utils::filtered(static_cast<const BasicTestSettingsAccessor *>(accessor())->fileNames(),
- [&baseFileName](const Utils::FileName &f) {
+ [&baseFileName](const Utils::FilePath &f) {
return f.parentDir() == baseFileName.parentDir() && f.toString().startsWith(baseFileName.toString());
});
}
@@ -153,7 +153,7 @@ public:
class TestSettingsAccessor : public BasicTestSettingsAccessor
{
public:
- TestSettingsAccessor(const Utils::FileName &baseName = Utils::FileName::fromString("/foo/baz"),
+ TestSettingsAccessor(const Utils::FilePath &baseName = Utils::FilePath::fromString("/foo/baz"),
const QByteArray &id = QByteArray(TESTACCESSOR_DEFAULT_ID)) :
BasicTestSettingsAccessor(baseName, id)
{
@@ -166,7 +166,7 @@ public:
using Utils::MergingSettingsAccessor::upgradeSettings;
};
-BasicTestSettingsAccessor::BasicTestSettingsAccessor(const FileName &baseName, const QByteArray &id) :
+BasicTestSettingsAccessor::BasicTestSettingsAccessor(const FilePath &baseName, const QByteArray &id) :
Utils::MergingSettingsAccessor(std::make_unique<TestBackUpStrategy>(this),
"TestData", TESTACCESSOR_DN, TESTACCESSOR_APPLICATION_DN)
{
@@ -235,7 +235,7 @@ static QVariantMap versionedMap(int version, const QByteArray &id = QByteArray()
return result;
}
-static Utils::SettingsAccessor::RestoreData restoreData(const Utils::FileName &path,
+static Utils::SettingsAccessor::RestoreData restoreData(const Utils::FilePath &path,
const QVariantMap &data)
{
return Utils::SettingsAccessor::RestoreData(path, data);
@@ -244,7 +244,7 @@ static Utils::SettingsAccessor::RestoreData restoreData(const Utils::FileName &p
static Utils::SettingsAccessor::RestoreData restoreData(const QByteArray &path,
const QVariantMap &data)
{
- return restoreData(Utils::FileName::fromUtf8(path), data);
+ return restoreData(Utils::FilePath::fromUtf8(path), data);
}
void tst_SettingsAccessor::addVersionUpgrader()
@@ -365,7 +365,7 @@ void tst_SettingsAccessor::RestoreDataCompare_idMismatch()
void tst_SettingsAccessor::RestoreDataCompare_noId()
{
- const TestSettingsAccessor accessor(Utils::FileName::fromString("/foo/baz"), QByteArray());
+ const TestSettingsAccessor accessor(Utils::FilePath::fromString("/foo/baz"), QByteArray());
Utils::SettingsAccessor::RestoreData a = restoreData("/foo/bar", versionedMap(5, TESTACCESSOR_DEFAULT_ID));
Utils::SettingsAccessor::RestoreData b = restoreData("/foo/baz", versionedMap(6, "foo"));
@@ -667,7 +667,7 @@ void tst_SettingsAccessor::findIssues_nonDefaultPath()
void tst_SettingsAccessor::saveSettings()
{
- const Utils::FileName baseFile = Utils::FileName::fromString("/tmp/foo/saveSettings");
+ const Utils::FilePath baseFile = Utils::FilePath::fromString("/tmp/foo/saveSettings");
const TestSettingsAccessor accessor(baseFile);
const QVariantMap data = versionedMap(6, TESTACCESSOR_DEFAULT_ID);
@@ -691,7 +691,7 @@ void tst_SettingsAccessor::saveSettings()
void tst_SettingsAccessor::loadSettings()
{
const QVariantMap data = versionedMap(6, "loadSettings", generateExtraData());
- const Utils::FileName path = Utils::FileName::fromString("/tmp/foo/loadSettings");
+ const Utils::FilePath path = Utils::FilePath::fromString("/tmp/foo/loadSettings");
const TestSettingsAccessor accessor(path, "loadSettings");
accessor.addFile(path, data);
QCOMPARE(accessor.files().count(), 1); // Catch changes early:-)
@@ -719,17 +719,17 @@ void tst_SettingsAccessor::loadSettings()
void tst_SettingsAccessor::loadSettings_pickBest()
{
- const Utils::FileName path = Utils::FileName::fromString("/tmp/foo/loadSettings");
+ const Utils::FilePath path = Utils::FilePath::fromString("/tmp/foo/loadSettings");
const TestSettingsAccessor accessor(path, "loadSettings");
accessor.addFile(path, versionedMap(10, "loadSettings", generateExtraData())); // too new
const QVariantMap data = versionedMap(7, "loadSettings", generateExtraData());
- accessor.addFile(Utils::FileName::fromString("/tmp/foo/loadSettings.foo"), data); // pick this!
- accessor.addFile(Utils::FileName::fromString("/tmp/foo/loadSettings.foo1"),
+ accessor.addFile(Utils::FilePath::fromString("/tmp/foo/loadSettings.foo"), data); // pick this!
+ accessor.addFile(Utils::FilePath::fromString("/tmp/foo/loadSettings.foo1"),
versionedMap(8, "fooSettings", generateExtraData())); // wrong environment
- accessor.addFile(Utils::FileName::fromString("/tmp/foo/loadSettings.bar"),
+ accessor.addFile(Utils::FilePath::fromString("/tmp/foo/loadSettings.bar"),
versionedMap(6, "loadSettings", generateExtraData())); // too old
- accessor.addFile(Utils::FileName::fromString("/tmp/foo/loadSettings.baz"),
+ accessor.addFile(Utils::FilePath::fromString("/tmp/foo/loadSettings.baz"),
versionedMap(1, "loadSettings", generateExtraData())); // much too old
QCOMPARE(accessor.files().count(), 5); // Catch changes early:-)
diff --git a/tests/auto/utils/stringutils/CMakeLists.txt b/tests/auto/utils/stringutils/CMakeLists.txt
new file mode 100644
index 0000000000..9d77c71d86
--- /dev/null
+++ b/tests/auto/utils/stringutils/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_utils_stringutils
+ DEPENDS Utils
+ SOURCES tst_stringutils.cpp
+)
diff --git a/tests/auto/utils/stringutils/tst_stringutils.cpp b/tests/auto/utils/stringutils/tst_stringutils.cpp
index 8e51c89300..98e04185ab 100644
--- a/tests/auto/utils/stringutils/tst_stringutils.cpp
+++ b/tests/auto/utils/stringutils/tst_stringutils.cpp
@@ -68,6 +68,14 @@ public:
*ret = "bar";
return true;
}
+ if (name == "JS:with } inside") {
+ *ret = "yay";
+ return true;
+ }
+ if (name == "JS:literal%{") {
+ *ret = "hurray";
+ return true;
+ }
return false;
}
};
@@ -158,7 +166,9 @@ void tst_StringUtils::testMacroExpander_data()
{"%{hihi//./c}", "ccc"},
{"%{hihi/(.)(.)r/\\2\\1c}", "abc"}, // no escape for capture groups
{"%{hihi/b/c/d}", "c/dar"},
- {"%{hihi/a/e{\\}e}", "be{}er"}, // escape closing brace
+ {"%{hihi/a/e{\\}e}", "be{}er"}, // escape closing brace
+ {"%{JS:with \\} inside}", "yay"}, // escape closing brace also in JS:
+ {"%{JS:literal%\\{}", "hurray"},
{"%{slash/o\\/b/ol's c}", "fool's car"},
{"%{sl\\/sh/(.)(a)(.)/\\2\\1\\3as}", "salsash"}, // escape in variable name
{"%{JS:foo/b/c}", "%{JS:foo/b/c}"}, // No replacement for JS (all considered varName)
diff --git a/tests/auto/utils/templateengine/CMakeLists.txt b/tests/auto/utils/templateengine/CMakeLists.txt
new file mode 100644
index 0000000000..bb13af8817
--- /dev/null
+++ b/tests/auto/utils/templateengine/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_utils_templateengine
+ DEPENDS Utils
+ SOURCES tst_templateengine.cpp
+)
diff --git a/tests/auto/utils/treemodel/CMakeLists.txt b/tests/auto/utils/treemodel/CMakeLists.txt
new file mode 100644
index 0000000000..487afcefd7
--- /dev/null
+++ b/tests/auto/utils/treemodel/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_qtc_test(tst_utils_treemodel
+ DEPENDS Utils
+ SOURCES tst_treemodel.cpp
+)
diff --git a/tests/auto/valgrind/callgrind/modeltest.cpp b/tests/auto/valgrind/callgrind/modeltest.cpp
index c02b23bf6d..6197f632d6 100644
--- a/tests/auto/valgrind/callgrind/modeltest.cpp
+++ b/tests/auto/valgrind/callgrind/modeltest.cpp
@@ -85,7 +85,7 @@ ModelTestWidget::ModelTestWidget(CallgrindWidgetHandler *handler)
m_format->addItem("absolute", CostDelegate::FormatAbsolute);
m_format->addItem("relative", CostDelegate::FormatRelative);
m_format->addItem("rel. to parent", CostDelegate::FormatRelativeToParent);
- connect(m_format, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_format, QOverload<int>::of(&QComboBox::activated),
this, &ModelTestWidget::formatChanged);
h->addWidget(m_format);
diff --git a/tests/auto/valgrind/memcheck/memcheck.qbs b/tests/auto/valgrind/memcheck/memcheck.qbs
index c633a605a3..d695ba30a0 100644
--- a/tests/auto/valgrind/memcheck/memcheck.qbs
+++ b/tests/auto/valgrind/memcheck/memcheck.qbs
@@ -2,6 +2,7 @@ import qbs
Project {
name: "Memcheck autotests"
+ condition: !qbs.targetOS.contains("windows")
references: [
"testapps/testapps.qbs",
"modeldemo.qbs"
diff --git a/tests/auto/valgrind/valgrind.qbs b/tests/auto/valgrind/valgrind.qbs
index af50a1e889..23b7e2cdbb 100644
--- a/tests/auto/valgrind/valgrind.qbs
+++ b/tests/auto/valgrind/valgrind.qbs
@@ -2,7 +2,6 @@ import qbs
Project {
name: "Valgrind autotests"
- condition: !qbs.targetOS.contains("windows")
references: [
"callgrind/callgrind.qbs",
"memcheck/memcheck.qbs"
diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp
index 2beaffaaae..864e20d40a 100644
--- a/tests/manual/debugger/simple/simple_test_app.cpp
+++ b/tests/manual/debugger/simple/simple_test_app.cpp
@@ -276,8 +276,7 @@ void dummyStatement(...) {}
#if USE_AUTOBREAK
# ifdef Q_CC_MSVC
-# include <crtdbg.h>
-# define BREAK_HERE _CrtDbgReport(_CRT_WARN, NULL, NULL, "simple_test_app", NULL)
+# define BREAK_HERE DebugBreak();
# else
# define BREAK_HERE asm("int $3; mov %eax, %eax")
# endif
@@ -2511,7 +2510,6 @@ namespace qset {
namespace qsharedpointer {
-
class EmployeeData : public QSharedData
{
public:
@@ -4567,7 +4565,7 @@ namespace qvariant {
#if QT_VERSION > 0x050000
QList<int> list;
list << 1 << 2 << 3;
- QVariant variant = qVariantFromValue(list);
+ QVariant variant = QVariant::fromValue(list);
BREAK_HERE;
// Expand list variant variant.data.
// Check list <3 items> QList<int>.
@@ -5008,7 +5006,6 @@ QString fooxx()
namespace basic {
-
struct Empty {};
struct Data { Data() : a(42) {} int a; };
struct VEmpty {};
diff --git a/tests/manual/proparser/testreader.pro b/tests/manual/proparser/testreader.pro
index a7b7d74cd3..0e10613a1a 100644
--- a/tests/manual/proparser/testreader.pro
+++ b/tests/manual/proparser/testreader.pro
@@ -24,7 +24,8 @@ SOURCES += \
qmakebuiltins.cpp \
proitems.cpp \
qmakevfs.cpp \
- ioutils.cpp
+ ioutils.cpp \
+ registry.cpp
HEADERS += \
qmake_global.h \
@@ -35,7 +36,8 @@ HEADERS += \
profileevaluator.h \
proitems.h \
qmakevfs.h \
- ioutils.h
+ ioutils.h \
+ registry_p.h
RESOURCES += proparser.qrc
DEFINES += QMAKE_BUILTIN_PRFS
@@ -43,3 +45,5 @@ DEFINES += QMAKE_BUILTIN_PRFS
DEFINES += QT_NO_CAST_TO_ASCII QT_RESTRICTED_CAST_FROM_ASCII
DEFINES += QT_USE_FAST_OPERATOR_PLUS QT_USE_FAST_CONCATENATION
DEFINES += PROEVALUATOR_FULL PROEVALUATOR_CUMULATIVE PROEVALUATOR_INIT_PROPS
+
+win32: LIBS *= -ladvapi32
diff --git a/tests/system/objects.map b/tests/system/objects.map
index 276ae23b35..b1989cbe7a 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -76,10 +76,10 @@
:FormEditorStack.menuBar_QDesignerMenuBar {container=':*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack' name='menuBar' type='QDesignerMenuBar' visible='1'}
:FormEditorStack_qdesigner_internal::FormWindow {container=':*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack' type='qdesigner_internal::FormWindow' unnamed='1' visible='1'}
:FormEditorStack_qdesigner_internal::PropertyLineEdit {container=':*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack' type='qdesigner_internal::PropertyLineEdit' unnamed='1' visible='1'}
-:Git Repository Clone.Cancel_QPushButton {text='Cancel' type='QPushButton' visible='1' window=':New Text File_ProjectExplorer::JsonWizard'}
-:Git Repository Clone.Finish_QPushButton {text~='(Finish|Done)' type='QPushButton' visible='1' window=':New Text File_ProjectExplorer::JsonWizard'}
-:Git Repository Clone.Result._QLabel {type='QLabel' unnamed='1' visible='1' window=':New Text File_ProjectExplorer::JsonWizard'}
-:Git Repository Clone.logPlainTextEdit_QPlainTextEdit {type='QPlainTextEdit' unnamed='1' visible='1' window=':New Text File_ProjectExplorer::JsonWizard'}
+:Git Repository Clone.Cancel_QPushButton {text='Cancel' type='QPushButton' visible='1' window=':New_ProjectExplorer::JsonWizard'}
+:Git Repository Clone.Finish_QPushButton {text~='(Finish|Done)' type='QPushButton' visible='1' window=':New_ProjectExplorer::JsonWizard'}
+:Git Repository Clone.Result._QLabel {type='QLabel' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}
+:Git Repository Clone.logPlainTextEdit_QPlainTextEdit {type='QPlainTextEdit' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:Go to slot.OK_QPushButton {text='OK' type='QPushButton' unnamed='1' visible='1' window=':Go to slot_QDialog'}
:Go to slot.Select signal_QGroupBox {name='groupBox' title='Select signal' type='QGroupBox' visible='1' window=':Go to slot_QDialog'}
:Go to slot_QDialog {name='SelectSignalDialog' type='QDialog' visible='1' windowTitle='Go to slot'}
@@ -88,14 +88,14 @@
:Hits_QResultWidget {aboveWidget=':Hits_QLabel' type='QResultWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
: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 Text File_ProjectExplorer::JsonWizard'}
-:New Text File.Add to project:_QLabel {name='projectLabel' text='Add to project:' type='QLabel' visible='1' window=':New Text File_ProjectExplorer::JsonWizard'}
-:New Text File.nameLineEdit_Utils::FileNameValidatingLineEdit {name='nameLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1' window=':New Text File_ProjectExplorer::JsonWizard'}
-:New Text File_ProjectExplorer::JsonWizard {type='ProjectExplorer::JsonWizard' unnamed='1' visible='1'}
+:Minimal required Qt version:_QLabel {text='Minimal 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'}
:New.frame_QFrame {name='frame' type='QFrame' visible='1' window=':New_Core::Internal::NewDialog'}
:New.templateCategoryView_QTreeView {name='templateCategoryView' type='QTreeView' visible='1' window=':New_Core::Internal::NewDialog'}
:New_Core::Internal::NewDialog {name='Core__Internal__NewDialog' type='Core::Internal::NewDialog' visible='1' windowTitle?='New*'}
+:New_ProjectExplorer::JsonWizard {type='ProjectExplorer::JsonWizard' unnamed='1' visible='1'}
:Next_QPushButton {text~='(Next.*|Continue)' type='QPushButton' visible='1'}
:No valid kits found._QLabel {text?='*No valid kits found.*' type='QLabel' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:OpenDocuments_Widget {type='Core::Internal::OpenEditorsWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Open Documents'}
@@ -163,10 +163,6 @@
:Qt Creator_Utils::BuildDirectoryLineEdit {name='shadowBuildDirEditLineEdit' type='Utils::FancyLineEdit' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Utils::NavigationTreeView {type='Utils::NavigationTreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit {container=':Qt Creator_Utils::NavigationTreeView' type='QExpandingLineEdit' unnamed='1' visible='1'}
-:Qt Gui Application.Form file:_QLabel {name='formLabel' text='Form file:' type='QLabel' visible='1' window=':Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog'}
-:Qt Gui Application.Header file:_QLabel {name='headerLabel' text='Header file:' type='QLabel' visible='1' window=':Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog'}
-:Qt Gui Application.Source file:_QLabel {name='sourceLabel' text='Source file:' type='QLabel' visible='1' window=':Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog'}
-:Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog {type='QmakeProjectManager::Internal::GuiAppWizardDialog' unnamed='1' visible='1' windowTitle='Qt Widgets Application'}
:QtSupport__Internal__QtVersionManager.QLabel {container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' text?='Qt version *' type='QLabel' unnamed='1' visible='1'}
:QtSupport__Internal__QtVersionManager.errorLabel.QLabel {container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' name='errorLabel' type='QLabel' visible='1'}
:QtSupport__Internal__QtVersionManager.qmake_QLabel {container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' name='qmakePath' type='QLabel' visible='1'}
@@ -200,12 +196,12 @@
:Take a UI Tour_Utils::CheckableMessageBox {type='Utils::CheckableMessageBox' unnamed='1' visible='1' windowTitle='Take a UI Tour'}
:User Interface.languageBox_QComboBox {container=':Core__Internal__GeneralSettings.User Interface_QGroupBox' name='languageBox' type='QComboBox' visible='1'}
:Widget Box_qdesigner_internal::WidgetBoxTreeWidget {container=':*Qt Creator.Widget Box_QDockWidget' type='qdesigner_internal::WidgetBoxTreeWidget' unnamed='1' visible='1'}
-:Working Copy_Utils::BaseValidatingLineEdit {type='Utils::FancyLineEdit' unnamed='1' visible='1' window=':New Text File_ProjectExplorer::JsonWizard'}
+:Working Copy_Utils::BaseValidatingLineEdit {type='Utils::FancyLineEdit' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:WritePermissions_Core::Internal::ReadOnlyFilesDialog {name='Core__Internal__ReadOnlyFilesDialog' type='Core::ReadOnlyFilesDialog' visible='1' windowTitle='Files Without Write Permissions'}
:addToVersionControlComboBox_QComboBox {name='addToVersionControlComboBox' type='QComboBox' visible='1'}
-:formFileLineEdit_Utils::FileNameValidatingLineEdit {buddy=':Qt Gui Application.Form file:_QLabel' name='formFileLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1'}
+:formFileLineEdit_Utils::FileNameValidatingLineEdit {name='FormFileName' type='Utils::FancyLineEdit' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:frame.templateDescription_QTextBrowser {container=':New.frame_QFrame' name='templateDescription' type='QTextBrowser' visible='1'}
-:headerFileLineEdit_Utils::FileNameValidatingLineEdit {buddy=':Qt Gui Application.Header file:_QLabel' name='headerFileLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1'}
+:headerFileLineEdit_Utils::FileNameValidatingLineEdit {name='HdrFileName' type='Utils::FancyLineEdit' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:popupFrame_Proposal_QListView {container=':popupFrame_TextEditor::GenericProposalWidget' type='QListView' unnamed='1' visible='1'}
:popupFrame_TextEditor::GenericProposalWidget {name='m_popupFrame' type='TextEditor::GenericProposalWidget' visible='1'}
:projectComboBox_QComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='QComboBox' visible='1'}
@@ -222,7 +218,7 @@
:scrollArea.Edit build configuration:_QLabel {text='Edit build configuration:' type='QLabel' unnamed='1' visible='1'}
:scrollArea.Library not available_QLabel {name='qmlDebuggingWarningText' text?='Library not available*' type='QLabel' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:scrollArea.qmlDebuggingLibraryCheckBox_QCheckBox {name='qmlDebuggingLibraryCheckBox' type='QCheckBox' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:sourceFileLineEdit_Utils::FileNameValidatingLineEdit {buddy=':Qt Gui Application.Source file:_QLabel' name='sourceFileLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1'}
+:sourceFileLineEdit_Utils::FileNameValidatingLineEdit {name='SrcFileName' type='Utils::FancyLineEdit' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:splitter.Commit File(s)_VcsBase::QActionPushButton {text~='(Commit .+/.+ File.*)' type='VcsBase::QActionPushButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:splitter.Description_QGroupBox {container=':Qt Creator.splitter_QSplitter' name='descriptionBox' title='Description' type='QGroupBox' visible='1'}
:splitter.Files_QGroupBox {container=':Qt Creator.splitter_QSplitter' name='groupBox' title='Files' type='QGroupBox' visible='1'}
diff --git a/tests/system/shared/build_utils.py b/tests/system/shared/build_utils.py
index ee9037557f..b27000701e 100644
--- a/tests/system/shared/build_utils.py
+++ b/tests/system/shared/build_utils.py
@@ -166,7 +166,10 @@ def selectBuildConfig(wantedKit, configName, afterSwitchTo=ViewConstants.EDIT):
def verifyBuildConfig(currentTarget, configName, shouldBeDebug=False, enableShadowBuild=False, enableQmlDebug=False):
selectBuildConfig(currentTarget, configName, None)
ensureChecked(waitForObject(":scrollArea.Details_Utils::DetailsButton"))
- ensureChecked("{name='shadowBuildCheckBox' type='QCheckBox' visible='1'}", enableShadowBuild)
+ ensureChecked("{leftWidget={text='Shadow build:' type='QLabel' unnamed='1' visible='1' "
+ "window=':Qt Creator_Core::Internal::MainWindow'} "
+ "type='QCheckBox' unnamed='1' visible='1' "
+ "window=':Qt Creator_Core::Internal::MainWindow'}", enableShadowBuild)
buildCfCombo = waitForObject("{type='QComboBox' name='buildConfigurationComboBox' visible='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}")
if shouldBeDebug:
diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py
index 28c5398f66..77632241f3 100644
--- a/tests/system/shared/debugger.py
+++ b/tests/system/shared/debugger.py
@@ -255,7 +255,7 @@ def verifyBreakPoint(bpToVerify):
def __isWinFirewallRunning__():
if hasattr(__isWinFirewallRunning__, "fireWallState"):
return __isWinFirewallRunning__.fireWallState
- if not platform.system() in ('Microsoft' 'Windows'):
+ if platform.system() not in ('Microsoft' 'Windows'):
__isWinFirewallRunning__.fireWallState = False
return False
result = getOutputFromCmdline(["netsh", "firewall", "show", "state"])
diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py
index a4be7f14d1..a0eea63b82 100644
--- a/tests/system/shared/project.py
+++ b/tests/system/shared/project.py
@@ -53,17 +53,17 @@ def openQmakeProject(projectPath, targets=Targets.desktopTargetClasses(), fromWe
def openCmakeProject(projectPath, buildDir):
def additionalFunction():
- pChooser = waitForObject("{leftWidget={text='Default' type='QCheckBox' unnamed='1' "
+ pChooser = waitForObject("{leftWidget={text='Debug' type='QCheckBox' unnamed='1' "
"visible='1'} type='Utils::PathChooser' unnamed='1' visible='1'}")
lineEdit = getChildByClass(pChooser, "Utils::FancyLineEdit")
replaceEditorContent(lineEdit, buildDir)
- # disable all build configurations except "Default"
- configs = ['Debug', 'Release', 'Release with Debug Information', 'Minimum Size Release']
+ # disable all build configurations except "Debug"
+ configs = ['Release', 'Release with Debug Information', 'Minimum Size Release']
for checkbox in configs:
ensureChecked(waitForObject("{text='%s' type='QCheckBox' unnamed='1' visible='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}"
% checkbox), False)
- ensureChecked(waitForObject("{text='Default' type='QCheckBox' unnamed='1' visible='1' "
+ ensureChecked(waitForObject("{text='Debug' type='QCheckBox' unnamed='1' visible='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}"), True)
invokeMenuItem("File", "Open File or Project...")
@@ -216,7 +216,7 @@ def createProject_Qt_GUI(path, projectName, checks = True, addToVersionControl =
template = "Qt Widgets Application"
available = __createProjectOrFileSelectType__(" Application", template)
__createProjectSetNameAndPath__(path, projectName, checks)
- __selectQtVersionDesktop__(checks, available, True)
+ __handleBuildSystem__(None)
if checks:
exp_filename = "mainwindow"
@@ -234,6 +234,7 @@ def createProject_Qt_GUI(path, projectName, checks = True, addToVersionControl =
test.compare(findObject(":formFileLineEdit_Utils::FileNameValidatingLineEdit").text, ui_file)
clickButton(waitForObject(":Next_QPushButton"))
+ __selectQtVersionDesktop__(checks, available, True)
expectedFiles = []
if checks:
diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py
index 4b909c6e44..c5fa6792b0 100644
--- a/tests/system/shared/qtcreator.py
+++ b/tests/system/shared/qtcreator.py
@@ -292,7 +292,7 @@ def copySettingsToTmpDir(destination=None, omitFiles=[]):
if not os.path.exists(folder):
os.makedirs(folder)
for ff in f:
- if not ff in omitFiles:
+ if ff not in omitFiles:
shutil.copy(os.path.join(r, ff), currentPath)
if platform.system() in ('Linux', 'Darwin'):
substituteTildeWithinToolchains(tmpSettingsDir)
diff --git a/tests/system/suite_HELP/tst_HELP02/test.py b/tests/system/suite_HELP/tst_HELP02/test.py
index 988657cd3b..a1755679d7 100755
--- a/tests/system/suite_HELP/tst_HELP02/test.py
+++ b/tests/system/suite_HELP/tst_HELP02/test.py
@@ -38,7 +38,7 @@ def getQtCreatorVersionFromDialog():
return ""
def getQtCreatorVersionFromFile():
- qtCreatorPriFileName = "../../../../qtcreator.pri"
+ qtCreatorPriFileName = "../../../../qtcreator_ide_branding.pri"
# open file <qtCreatorPriFileName> and read version
fileText = readFile(qtCreatorPriFileName)
chk = re.search("(?<=QTCREATOR_DISPLAY_VERSION =)\s\d+.\d+.\d+\S*", fileText)
diff --git a/tests/system/suite_debugger/tst_qml_locals/test.py b/tests/system/suite_debugger/tst_qml_locals/test.py
index 0430c306c9..f85a2d3b23 100644
--- a/tests/system/suite_debugger/tst_qml_locals/test.py
+++ b/tests/system/suite_debugger/tst_qml_locals/test.py
@@ -122,7 +122,8 @@ def fetchItems(index, valIndex, treeView):
tree.setName(name)
tree.setValue(value)
for row in range(model.rowCount(index)):
- tree.addChild(fetchItems(model.index(row, 0, index), model.index(row, 1, index), treeView))
+ tree.addChild(fetchItems(model.index(row, 0, index),
+ model.index(row, 2, index), treeView))
return tree
def checkForEmptyRows(items, isRootCheck=True):
diff --git a/tests/system/suite_editors/tst_edit_externally/test.py b/tests/system/suite_editors/tst_edit_externally/test.py
index ec6fcd9203..9c2ea61d2c 100644
--- a/tests/system/suite_editors/tst_edit_externally/test.py
+++ b/tests/system/suite_editors/tst_edit_externally/test.py
@@ -47,7 +47,8 @@ def main():
mBox = ("{text?='The file * has been changed on disk. Do you want to reload it?' "
"type='QMessageBox' unnamed='1' visible='1'}")
- popupText = "The file <i>%s</i> has been changed on disk. Do you want to reload it?"
+ 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>")
formerContent = None
for i, currentFile in enumerate(files):
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 194d90aa9c..e3bee3b2a4 100644
--- a/tests/system/suite_general/tst_create_proj_wizard/test.py
+++ b/tests/system/suite_general/tst_create_proj_wizard/test.py
@@ -61,7 +61,7 @@ def main():
for template in dumpItems(templatesView.model(), templatesView.rootIndex()):
template = template.replace(".", "\\.")
# skip non-configurable
- if not template in ["Qt Quick UI Prototype", "Auto Test Project", # FIXME
+ if template not in ["Qt Quick UI Prototype", "Auto Test Project", # FIXME
"Qt for Python - Empty", "Qt for Python - Window"]:
availableProjectTypes.append({category:template})
safeClickButton("Cancel")
diff --git a/tests/system/suite_general/tst_default_settings/test.py b/tests/system/suite_general/tst_default_settings/test.py
index 928f890b2a..3270f619e5 100644
--- a/tests/system/suite_general/tst_default_settings/test.py
+++ b/tests/system/suite_general/tst_default_settings/test.py
@@ -121,14 +121,8 @@ def __compFunc__(it, foundComp, foundCompNames):
pathLineEdit = findObject(":Path.Utils_BaseValidatingLineEdit")
foundComp.append(str(pathLineEdit.text))
except:
- objectString = ("{buddy={container=':qt_tabwidget_stackedwidget_QWidget'"
- " text='Initialization:' type='QLabel' unnamed='1' visible='1'}"
- " type='%s' unnamed='1' visible='1'}")
- try:
- foundText = findObject(objectString % "QLabel").text
- except:
- foundText = findObject(objectString % "QComboBox").currentText
- foundComp.append({it:str(foundText)})
+ varsBatCombo = waitForObjectExists("{name='varsBatCombo' type='QComboBox' visible='1'}")
+ foundComp.append({it:str(varsBatCombo.currentText)})
foundCompNames.append(it)
diff --git a/tests/system/suite_general/tst_rename_file/test.py b/tests/system/suite_general/tst_rename_file/test.py
index ed13ee9a8e..3f0907759a 100644
--- a/tests/system/suite_general/tst_rename_file/test.py
+++ b/tests/system/suite_general/tst_rename_file/test.py
@@ -114,11 +114,11 @@ def renameFile(projectDir, proFile, branch, oldname, newname):
"Comparing content of file before and after renaming")
test.verify(waitFor("newname in safeReadFile(proFile)", 2000),
"Verify that new filename '%s' was added to pro-file." % newname)
- if not oldname in newname:
- test.verify(not oldname in readFile(proFile),
+ if oldname not in newname:
+ test.verify(oldname not in readFile(proFile),
"Verify that old filename '%s' was removed from pro-file." % oldname)
if not (oldname.lower() == newname.lower() and platform.system() in ('Windows', 'Microsoft')):
- test.verify(not oldname in os.listdir(projectDir),
+ test.verify(oldname not in os.listdir(projectDir),
"Verify that file with old name does not exist: %s" % oldFilePath)
def safeReadFile(filename):
diff --git a/tests/system/suite_tools/tst_git_clone/test.py b/tests/system/suite_tools/tst_git_clone/test.py
index dbafe77690..476c1be365 100644
--- a/tests/system/suite_tools/tst_git_clone/test.py
+++ b/tests/system/suite_tools/tst_git_clone/test.py
@@ -55,7 +55,7 @@ def verifyCloneLog(targetDir, canceled):
if canceled:
test.warning("Could not find resultLabel",
"Cloning might have failed before clicking 'Cancel'")
- return object.exists(":New Text File_ProjectExplorer::JsonWizard")
+ return object.exists(":New_ProjectExplorer::JsonWizard")
else:
test.fail("Could not find resultLabel")
return True
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
new file mode 100644
index 0000000000..eb072a2d92
--- /dev/null
+++ b/tests/unit/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(echoserver)
+add_subdirectory(unittest)
diff --git a/tests/unit/echoserver/CMakeLists.txt b/tests/unit/echoserver/CMakeLists.txt
new file mode 100644
index 0000000000..ce3065be8b
--- /dev/null
+++ b/tests/unit/echoserver/CMakeLists.txt
@@ -0,0 +1,8 @@
+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
+)
diff --git a/tests/unit/mockup/coreplugin/icore.h b/tests/unit/mockup/coreplugin/icore.h
index 579fbc3b56..8cf88f7037 100644
--- a/tests/unit/mockup/coreplugin/icore.h
+++ b/tests/unit/mockup/coreplugin/icore.h
@@ -12,5 +12,10 @@ inline static QString cacheResourcePath()
return QDir::tempPath();
}
+inline static QString resourcePath()
+{
+ return QDir::tempPath();
+}
+
} // namespace ICore
} // namespace Core
diff --git a/tests/unit/mockup/projectexplorer/project.h b/tests/unit/mockup/projectexplorer/project.h
index cca7e49127..c69eb6e47b 100644
--- a/tests/unit/mockup/projectexplorer/project.h
+++ b/tests/unit/mockup/projectexplorer/project.h
@@ -39,8 +39,14 @@ public:
Utils::FileName projectDirectory() const { return {}; }
- Utils::FileName rootProjectDirectory() const { return {}; }
+ Utils::FileName rootProjectDirectory() const { return rootProjectDirectoryPath; }
Target *activeTarget() const { return {}; }
+
+ QVariant namedSettings(const QString &name) const { return settings.at(name); }
+ void setNamedSettings(const QString &name, const QVariant &value) { settings[name] = value; }
+
+ Utils::FileName rootProjectDirectoryPath;
+ mutable std::map<QString, QVariant> settings;
};
} // namespace ProjectExplorer
diff --git a/tests/unit/mockup/projectexplorer/toolchain.h b/tests/unit/mockup/projectexplorer/toolchain.h
index 7e3f4af097..925b0a2ae8 100644
--- a/tests/unit/mockup/projectexplorer/toolchain.h
+++ b/tests/unit/mockup/projectexplorer/toolchain.h
@@ -38,11 +38,13 @@ namespace ProjectExplorer {
class ToolChain
{
public:
+ ToolChain() = default;
Core::Id typeId() const { return Core::Id(); }
Abi targetAbi() const { return Abi(); }
- using BuiltInHeaderPathsRunner = std::function<HeaderPaths(const QStringList &cxxflags, const QString &sysRoot)>;
+ using BuiltInHeaderPathsRunner = std::function<HeaderPaths(
+ const QStringList &cxxflags, const QString &sysRoot, const QString &originalTargetTriple)>;
virtual BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const { return BuiltInHeaderPathsRunner(); }
class MacroInspectionReport
@@ -58,4 +60,13 @@ public:
virtual QStringList extraCodeModelFlags() const { return QStringList(); }
};
+class ConcreteToolChain : public ToolChain
+{
+public:
+ MacroInspectionRunner createMacroInspectionRunner() const override
+ {
+ return MacroInspectionRunner();
+ }
+};
+
} // namespace ProjectExplorer
diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt
new file mode 100644
index 0000000000..0aed2a8995
--- /dev/null
+++ b/tests/unit/unittest/CMakeLists.txt
@@ -0,0 +1,413 @@
+find_package(Googletest MODULE)
+find_package(GoogleBenchmark MODULE)
+
+if (NOT Googletest_FOUND)
+ message(STATUS "Googletest was not found. Please set GOOGLETEST_DIR (CMake or Environment) variable.")
+ message(STATUS "Have a look at cmake/FindGoogletest.cmake file for more details.")
+ message(STATUS "unittest module will be skipped.")
+ return()
+endif()
+
+add_qtc_test(unittest GTEST
+ INCLUDES
+ BEFORE "../mockup"
+ DEPENDS
+ Qt5::Core Qt5::Network Qt5::Widgets
+ Qt5::Xml Qt5::Concurrent Qt5::Qml Qt5::Gui
+ Googletest
+ clangrefactoringbackend_lib clangbackend_lib clangpchmanagerbackend_lib
+ CPlusPlus Sqlite Utils
+ DEFINES
+ QT_NO_CAST_TO_ASCII QT_RESTRICTED_CAST_FROM_ASCII
+ QT_USE_FAST_OPERATOR_PLUS QT_USE_FAST_CONCATENATION
+ UNIT_TESTS
+ DONT_CHECK_MESSAGE_COUNTER
+ QTC_RESOURCE_DIR="${CMAKE_SOURCE_DIR}/share/qtcreator"
+ TESTDATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data"
+ ECHOSERVER="$<TARGET_FILE_DIR:echo>/echo"
+ CPPTOOLS_JSON="${CMAKE_CURRENT_BINARY_DIR}/CppTools.json"
+ SOURCES
+ builddependenciesprovider-test.cpp
+ builddependenciesstorage-test.cpp
+ changedfilepathcompressor-test.cpp
+ clangpathwatcher-test.cpp
+ clangqueryexamplehighlightmarker-test.cpp
+ clangqueryhighlightmarker-test.cpp
+ clientserverinprocess-test.cpp
+ clientserveroutsideprocess-test.cpp
+ commandlinebuilder-test.cpp
+ compare-operators.h
+ compilationdatabaseutils-test.cpp
+ compileroptionsbuilder-test.cpp
+ conditionally-disabled-tests.h
+ cppprojectfilecategorizer-test.cpp
+ cppprojectinfogenerator-test.cpp
+ cppprojectpartchooser-test.cpp
+ dummyclangipcclient.h
+ dynamicastmatcherdiagnosticcontainer-matcher.h
+ eventspy.cpp eventspy.h
+ fakeprocess.cpp fakeprocess.h
+ filepathcache-test.cpp
+ filepathstoragesqlitestatementfactory-test.cpp
+ filepathstorage-test.cpp
+ filepath-test.cpp
+ filepathview-test.cpp
+ filestatuscache-test.cpp
+ filesystem-utilities.h
+ generatedfiles-test.cpp
+ googletest.h
+ google-using-declarations.h
+ gtest-creator-printing.cpp gtest-creator-printing.h
+ gtest-llvm-printing.h
+ gtest-qt-printing.cpp gtest-qt-printing.h
+ headerpathfilter-test.cpp
+ highlightingresultreporter-test.cpp
+ lineprefixer-test.cpp
+ locatorfilter-test.cpp
+ matchingtext-test.cpp
+ mimedatabase-utilities.cpp mimedatabase-utilities.h
+ mockbuilddependenciesprovider.h
+ mockbuilddependenciesstorage.h
+ mockbuilddependencygenerator.h
+ mockclangcodemodelclient.h
+ mockclangcodemodelserver.h
+ mockclangpathwatcher.h
+ mockclangpathwatchernotifier.h
+ mockcppmodelmanager.h
+ mockeditormanager.h
+ mockfilepathcaching.h
+ mockfilepathstorage.h
+ mockfutureinterface.h
+ mockgeneratedfiles.h
+ mockmodifiedtimechecker.h
+ mockmutex.h
+ mockpchcreator.h
+ mockpchmanagerclient.h
+ mockpchmanagernotifier.h
+ mockpchmanagerserver.h
+ mockpchtaskgenerator.h
+ mockpchtaskqueue.h
+ mockpchtasksmerger.h
+ mockprecompiledheaderstorage.h
+ mockprocessor.h
+ mockprocessormanager.h
+ mockprogressmanager.h
+ mockprojectpartprovider.h
+ mockprojectpartqueue.h
+ mockprojectpartsmanager.h
+ mockprojectpartsstorage.h
+ mockqfilesystemwatcher.h
+ mockqueue.h
+ mocksearch.h
+ mocksearchhandle.h
+ mocksearchresult.h
+ mocksqlitedatabase.h
+ mocksqlitereadstatement.cpp
+ mocksqlitereadstatement.h
+ mocksqlitestatement.h
+ mocksqlitetransactionbackend.h
+ mocksqlitewritestatement.h
+ mocksymbolindexertaskqueue.h
+ mocksymbolindexing.h
+ mocksymbolquery.h
+ mocksymbolscollector.h
+ mocksymbolstorage.h
+ mocksyntaxhighligher.h
+ mocktaskscheduler.h
+ mocktimer.cpp mocktimer.h
+ modifiedtimechecker-test.cpp
+ nativefilepath-test.cpp
+ nativefilepathview-test.cpp
+ pchmanagerclientserverinprocess-test.cpp
+ pchmanagerclient-test.cpp
+ pchmanagerserver-test.cpp
+ pchtaskgenerator-test.cpp
+ pchtaskqueue-test.cpp
+ pchtasksmerger-test.cpp
+ precompiledheaderstorage-test.cpp
+ processcreator-test.cpp
+ processevents-utilities.cpp processevents-utilities.h
+ processormanager-test.cpp
+ progresscounter-test.cpp
+ projectpartartefact-test.cpp
+ projectpartsmanager-test.cpp
+ projectpartsstorage-test.cpp
+ projectupdater-test.cpp
+ readandwritemessageblock-test.cpp
+ refactoringdatabaseinitializer-test.cpp
+ refactoringprojectupdater-test.cpp
+ rundocumentparse-utility.h
+ sizedarray-test.cpp
+ smallstring-test.cpp
+ sourcerangecontainer-matcher.h
+ sourcerangefilter-test.cpp
+ sourcesmanager-test.cpp
+ spydummy.cpp spydummy.h
+ sqliteindex-test.cpp
+ sqliteteststatement.h
+ sqlitetransaction-test.cpp
+ stringcache-test.cpp
+ symbolindexertaskqueue-test.cpp
+ symbolindexer-test.cpp
+ symbolquery-test.cpp
+ symbolsfindfilter-test.cpp
+ symbolstorage-test.cpp
+ taskscheduler-test.cpp
+ testenvironment.h
+ tokenprocessor-test.cpp
+ toolchainargumentscache-test.cpp
+ unittests-main.cpp
+ unittest-utility-functions.h
+ usedmacrofilter-test.cpp
+ utf8-test.cpp
+)
+
+# Do not work on the source directory data
+add_custom_command(TARGET unittest POST_BUILD
+ COMMAND "${CMAKE_COMMAND}" -E copy_directory
+ "${CMAKE_CURRENT_SOURCE_DIR}/data"
+ "${CMAKE_CURRENT_BINARY_DIR}/data"
+)
+
+# create fake CppTools.json for the mime type definitions
+file(READ "${CMAKE_SOURCE_DIR}/src/plugins/cpptools/CppTools.json.in" plugin_json_in)
+string(REPLACE "\\\"" "\"" plugin_json_in ${plugin_json_in})
+string(REPLACE "\\'" "'" plugin_json_in ${plugin_json_in})
+string(REPLACE "$$QTCREATOR_VERSION" "${IDE_VERSION}" plugin_json_in ${plugin_json_in})
+string(REPLACE "$$QTCREATOR_COMPAT_VERSION" "${IDE_VERSION_COMPAT}" plugin_json_in ${plugin_json_in})
+string(REPLACE "$$QTCREATOR_COPYRIGHT_YEAR" "${IDE_COPYRIGHT_YEAR}" plugin_json_in ${plugin_json_in})
+string(REPLACE "$$dependencyList" "\"Dependencies\" : []" plugin_json_in ${plugin_json_in})
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CppTools.json" ${plugin_json_in}})
+
+if (TARGET libclang)
+ target_sources(unittest PRIVATE
+ 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
+ createtablesqlstatementbuilder-test.cpp
+ cursor-test.cpp
+ diagnosticset-test.cpp
+ diagnostic-test.cpp
+ fixit-test.cpp
+ senddocumenttracker-test.cpp
+ skippedsourceranges-test.cpp
+ sourcelocation-test.cpp
+ sourcerange-test.cpp
+ sqlitecolumn-test.cpp
+ sqlitedatabasebackend-test.cpp
+ sqlitedatabase-test.cpp
+ sqlitestatement-test.cpp
+ sqlitetable-test.cpp
+ sqlstatementbuilder-test.cpp
+ token-test.cpp
+ translationunitupdater-test.cpp
+ unsavedfiles-test.cpp
+ unsavedfile-test.cpp
+ utf8positionfromlinecolumn-test.cpp
+ chunksreportedmonitor.h
+ clangasyncjob-base.h
+ clangcompareoperators.h
+ diagnosticcontainer-matcher.h
+ )
+ target_include_directories(unittest PRIVATE "${CLANG_INCLUDE_DIRS}")
+ target_link_libraries(unittest PRIVATE libclang)
+endif()
+
+if (TARGET clangTooling)
+ target_compile_definitions(unittest PRIVATE CLANG_UNIT_TESTS)
+ target_sources(unittest PRIVATE
+ gtest-llvm-printing.cpp
+ clangquerygatherer-test.cpp
+ clangqueryprojectfindfilter-test.cpp
+ clangquery-test.cpp
+ gtest-clang-printing.cpp gtest-clang-printing.h
+ pchcreator-test.cpp
+ refactoringclientserverinprocess-test.cpp
+ refactoringclient-test.cpp
+ refactoringcompilationdatabase-test.cpp
+ refactoringengine-test.cpp
+ refactoringserver-test.cpp
+ sourcerangeextractor-test.cpp
+ symbolindexing-test.cpp
+ symbolscollector-test.cpp
+ symbolfinder-test.cpp
+ testclangtool.cpp testclangtool.h
+ usedmacrocollector-test.cpp
+ builddependencycollector-test.cpp
+ mockrefactoringclient.h
+ mockrefactoringserver.h
+ )
+ target_link_libraries(unittest
+ PRIVATE clangTooling clangIndex clangQuery clangToolingRefactor)
+endif()
+
+if (TARGET clangFormat)
+ target_sources(unittest PRIVATE
+ clangformat-test.cpp
+ )
+ target_link_libraries(unittest PRIVATE clangFormat)
+endif()
+
+if (TARGET GoogleBenchmark)
+ target_sources(unittest PRIVATE
+ smallstring-benchmark.cpp
+ )
+ target_link_libraries(unittest PRIVATE GoogleBenchmark)
+endif()
+
+finalize_qtc_gtest(unittest)
+
+# Path needs to be before CppTools
+target_include_directories(unittest
+ PRIVATE
+ BEFORE $<TARGET_PROPERTY:clangrefactoringbackend_lib,INTERFACE_INCLUDE_DIRECTORIES>
+ BEFORE $<TARGET_PROPERTY:ClangRefactoring,INTERFACE_INCLUDE_DIRECTORIES>
+)
+
+get_target_property(ClangSupportSources ClangSupport SOURCES)
+get_target_property(ClangSupportSourcesDir ClangSupport SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${ClangSupportSourcesDir}"
+ SOURCES ${ClangSupportSources}
+ DEFINES
+ $<TARGET_PROPERTY:ClangSupport,INTERFACE_COMPILE_DEFINITIONS>
+ CLANGSUPPORT_BUILD_LIB
+ INCLUDES
+ $<TARGET_PROPERTY:ClangSupport,INTERFACE_INCLUDE_DIRECTORIES>
+)
+
+get_target_property(ClangCodeModelSourcesDir ClangCodeModel SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${ClangCodeModelSourcesDir}"
+ 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
+)
+
+get_target_property(CompilationDatabasePMSourcesDir CompilationDatabaseProjectManager SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${CompilationDatabasePMSourcesDir}"
+ SOURCES
+ compilationdatabaseutils.cpp compilationdatabaseutils.h
+)
+
+get_target_property(CoreSourcesDir Core SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${CoreSourcesDir}"
+ DEFINES CORE_STATIC_LIBRARY
+ SOURCES
+ coreicons.cpp coreicons.h
+ id.cpp id.h
+ find/ifindfilter.cpp find/ifindfilter.h
+ locator/ilocatorfilter.cpp locator/ilocatorfilter.h
+)
+
+get_target_property(CppToolsSourcesDir CppTools SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${CppToolsSourcesDir}"
+ DEFINES CPPTOOLS_STATIC_LIBRARY
+ SOURCES
+ cppprojectfile.cpp cppprojectfile.h
+ senddocumenttracker.cpp senddocumenttracker.h
+ projectpart.cpp projectpart.h
+ compileroptionsbuilder.cpp compileroptionsbuilder.h
+ cppprojectfilecategorizer.cpp cppprojectfilecategorizer.h
+ projectinfo.cpp projectinfo.h
+ cppprojectinfogenerator.cpp cppprojectinfogenerator.cpp
+ cppprojectpartchooser.cpp cppprojectpartchooser.h
+ headerpathfilter.cpp headerpathfilter.h
+)
+
+get_target_property(ProjectExplorerSourcesDir ProjectExplorer SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${ProjectExplorerSourcesDir}"
+ DEFINES PROJECTEXPLORER_STATIC_LIBRARY
+ SOURCES
+ projectmacro.cpp projectmacro.h
+)
+
+get_target_property(ClangRefactoringSourcesDir ClangRefactoring SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${ClangRefactoringSourcesDir}"
+ SOURCES
+ clangqueryexamplehighlighter.cpp clangqueryexamplehighlighter.h
+ clangqueryexamplehighlightmarker.h
+ clangqueryhighlighter.cpp clangqueryhighlighter.h
+ clangqueryhighlightmarker.h
+ clangqueryprojectsfindfilter.cpp clangqueryprojectsfindfilter.h
+ projectpartutilities.cpp projectpartutilities.h
+ refactoringclient.cpp refactoringclient.h
+ refactoringconnectionclient.cpp refactoringconnectionclient.h
+ refactoringengine.cpp refactoringengine.h
+ refactoringprojectupdater.cpp refactoringprojectupdater.h
+ searchinterface.h
+ searchhandle.cpp searchhandle.h
+ symbolsfindfilter.cpp symbolsfindfilter.h
+ symbolqueryinterface.h
+ symbol.h
+ projectpartproviderinterface.h
+ editormanagerinterface.h
+ locatorfilter.cpp locatorfilter.h
+)
+
+get_target_property(ClangPchManagerSourcesDir ClangPchManager SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${ClangPchManagerSourcesDir}"
+ DEFINES CLANGPCHMANAGER_STATIC_LIB
+ SOURCES
+ pchmanagerclient.h pchmanagerclient.cpp
+ pchmanagernotifierinterface.h pchmanagernotifierinterface.cpp
+ pchmanagerconnectionclient.h pchmanagerconnectionclient.cpp
+ clangpchmanager_global.h
+ projectupdater.h projectupdater.cpp
+ pchmanagerprojectupdater.h pchmanagerprojectupdater.cpp
+ progressmanager.h
+ progressmanagerinterface.h
+)
+
+get_target_property(ClangFormatSourcesDir ClangFormat SOURCES_DIR)
+extend_qtc_target(unittest
+ SOURCES_PREFIX "${ClangFormatSourcesDir}"
+ DEFINES CLANGPCHMANAGER_STATIC_LIB
+ SOURCES
+ clangformatconstants.h
+ clangformatbaseindenter.cpp clangformatbaseindenter.h
+)
diff --git a/tests/unit/unittest/builddependenciesprovider-test.cpp b/tests/unit/unittest/builddependenciesprovider-test.cpp
index 772a435a58..9983e42d8d 100644
--- a/tests/unit/unittest/builddependenciesprovider-test.cpp
+++ b/tests/unit/unittest/builddependenciesprovider-test.cpp
@@ -56,9 +56,17 @@ MATCHER_P(HasSourceId, sourceId, std::string(negation ? "hasn't" : "has")
class BuildDependenciesProvider : public testing::Test
{
protected:
+ BuildDependenciesProvider()
+ {
+ provider.setEnsureAliveMessageIsSentCallback(
+ mockEnsureAliveMessageIsSentCallback.AsStdFunction());
+ }
+
+protected:
+ NiceMock<MockFunction<void()>> mockEnsureAliveMessageIsSentCallback;
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
- NiceMock<MockModifiedTimeChecker> mockModifiedTimeChecker;
+ NiceMock<MockSourceEntriesModifiedTimeChecker> mockModifiedTimeChecker;
NiceMock<MockBuildDependencyGenerator> mockBuildDependenciesGenerator;
ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage,
mockModifiedTimeChecker,
@@ -209,4 +217,11 @@ TEST_F(BuildDependenciesProvider, FetchUsedMacrosFromStorageIfDependSourcesAreUp
ASSERT_THAT(buildDependency.usedMacros, ElementsAre(UsedMacro{"YI", 1}, UsedMacro{"ER", 2}, UsedMacro{"LIANG", 2}, UsedMacro{"SAN", 10}));
}
+
+TEST_F(BuildDependenciesProvider, CallEnsureAliveMessageIsSentCallback)
+{
+ EXPECT_CALL(mockEnsureAliveMessageIsSentCallback, Call());
+
+ provider.create(projectPart1);
+}
}
diff --git a/tests/unit/unittest/builddependenciesstorage-test.cpp b/tests/unit/unittest/builddependenciesstorage-test.cpp
index aa82370485..052ed452f0 100644
--- a/tests/unit/unittest/builddependenciesstorage-test.cpp
+++ b/tests/unit/unittest/builddependenciesstorage-test.cpp
@@ -70,6 +70,7 @@ protected:
MockSqliteWriteStatement &updatePchCreationTimeStampStatement = storage.updatePchCreationTimeStampStatement;
MockSqliteWriteStatement &deleteAllProjectPartsFilesWithProjectPartNameStatement
= storage.deleteAllProjectPartsFilesWithProjectPartNameStatement;
+ MockSqliteReadStatement &fetchProjectPartsFilesStatement = storage.fetchProjectPartsFilesStatement;
};
TEST_F(BuildDependenciesStorage, ConvertStringsToJson)
@@ -232,5 +233,13 @@ TEST_F(BuildDependenciesStorage, FetchUsedMacros)
ASSERT_THAT(usedMacros, result);
}
-}
+TEST_F(BuildDependenciesStorage, FetchSources)
+{
+ ClangBackEnd::FilePathIds result{3, 5, 7};
+ EXPECT_CALL(fetchProjectPartsFilesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result));
+ auto sources = storage.fetchSources(22);
+
+ ASSERT_THAT(sources, result);
+}
+} // namespace
diff --git a/tests/unit/unittest/builddependencycollector-test.cpp b/tests/unit/unittest/builddependencycollector-test.cpp
index 6c2153fe0c..0d1b9650dc 100644
--- a/tests/unit/unittest/builddependencycollector-test.cpp
+++ b/tests/unit/unittest/builddependencycollector-test.cpp
@@ -737,10 +737,16 @@ TEST_F(BuildDependencyCollector, Create)
1,
{},
{},
- {{TESTDATA_DIR "/builddependencycollector/system", 1, IncludeSearchPathType::System}},
+ {{TESTDATA_DIR "/builddependencycollector/system",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::System}},
{
- {TESTDATA_DIR "/builddependencycollector/project", 1, IncludeSearchPathType::User},
- {TESTDATA_DIR "/builddependencycollector/external", 2, IncludeSearchPathType::User},
+ {TESTDATA_DIR "/builddependencycollector/project",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::User},
+ {TESTDATA_DIR "/builddependencycollector/external",
+ 2,
+ ClangBackEnd::IncludeSearchPathType::User},
},
{
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
@@ -771,6 +777,7 @@ TEST_F(BuildDependencyCollector, Create)
"/builddependencycollector/external/indirect_external2.h"),
fileStatus(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
fileStatus(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
+ fileStatus(TESTDATA_DIR "/preincludes/system1.h"),
fileStatus(TESTDATA_DIR "/builddependencycollector/system/indirect_system.h"),
fileStatus(TESTDATA_DIR
"/builddependencycollector/system/indirect_system2.h"),
@@ -804,7 +811,7 @@ TEST_F(BuildDependencyCollector, Create)
HasSource(id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
SourceType::TopProjectInclude),
HasSource(id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
- SourceType::TopSystemInclude),
+ SourceType::SystemInclude),
HasSource(id(TESTDATA_DIR "/builddependencycollector/system/indirect_system.h"),
SourceType::SystemInclude),
HasSource(id(TESTDATA_DIR
@@ -813,7 +820,8 @@ TEST_F(BuildDependencyCollector, Create)
HasSource(id(TESTDATA_DIR "/builddependencycollector/project/macros.h"),
SourceType::UserInclude),
HasSource(id(TESTDATA_DIR "/builddependencycollector/project/generated_file.h"),
- SourceType::UserInclude))),
+ SourceType::UserInclude),
+ HasSource(id(TESTDATA_DIR "/preincludes/system1.h"), SourceType::TopSystemInclude))),
Field(&BuildDependency::usedMacros,
UnorderedElementsAre(
UsedMacro{"IFDEF", id(TESTDATA_DIR "/builddependencycollector/project/macros.h")},
@@ -830,6 +838,7 @@ TEST_F(BuildDependencyCollector, Create)
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
+ id(TESTDATA_DIR "/preincludes/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/indirect_system.h"),
id(TESTDATA_DIR "/builddependencycollector/system/indirect_system2.h"),
id(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
@@ -854,6 +863,8 @@ TEST_F(BuildDependencyCollector, Create)
id(TESTDATA_DIR
"/builddependencycollector/external/external2.h")),
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
+ id(TESTDATA_DIR "/preincludes/system1.h")),
+ SourceDependency(id(TESTDATA_DIR "/preincludes/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system1.h")),
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
id(TESTDATA_DIR "/builddependencycollector/project/macros.h")),
@@ -888,10 +899,16 @@ TEST_F(BuildDependencyCollector, Clear)
1,
{},
{},
- {{TESTDATA_DIR "/builddependencycollector/system", 1, IncludeSearchPathType::System}},
+ {{TESTDATA_DIR "/builddependencycollector/system",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::System}},
{
- {TESTDATA_DIR "/builddependencycollector/project", 1, IncludeSearchPathType::User},
- {TESTDATA_DIR "/builddependencycollector/external", 2, IncludeSearchPathType::User},
+ {TESTDATA_DIR "/builddependencycollector/project",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::User},
+ {TESTDATA_DIR "/builddependencycollector/external",
+ 2,
+ ClangBackEnd::IncludeSearchPathType::User},
},
{
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
@@ -899,14 +916,76 @@ TEST_F(BuildDependencyCollector, Clear)
id(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
id(TESTDATA_DIR "/builddependencycollector/project/macros.h"),
},
- {},
+ {id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp")},
Utils::Language::Cxx,
Utils::LanguageVersion::CXX11,
Utils::LanguageExtension::None};
collector.create(projectPart);
+ ClangBackEnd::ProjectPartContainer emptyProjectPart{
+ 1,
+ {},
+ {},
+ {{TESTDATA_DIR "/builddependencycollector/system",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::System}},
+ {
+ {TESTDATA_DIR "/builddependencycollector/project",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::User},
+ {TESTDATA_DIR "/builddependencycollector/external",
+ 2,
+ ClangBackEnd::IncludeSearchPathType::User},
+ },
+ {
+ id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
+ id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
+ id(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
+ id(TESTDATA_DIR "/builddependencycollector/project/macros.h"),
+ },
+ {},
+ Utils::Language::Cxx,
+ Utils::LanguageVersion::CXX11,
+ Utils::LanguageExtension::None};
- auto buildDependency = collector.create(projectPart);
+ auto buildDependency = collector.create(emptyProjectPart);
ASSERT_THAT(buildDependency.sources, IsEmpty());
}
+
+TEST_F(BuildDependencyCollector, PreIncludes)
+{
+ using ClangBackEnd::IncludeSearchPathType;
+ ClangBackEnd::BuildDependencyCollector collector{filePathCache, generatedFiles, environment};
+ ClangBackEnd::ProjectPartContainer projectPart{
+ 1,
+ {},
+ {},
+ {{TESTDATA_DIR "/builddependencycollector/system",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::System}},
+ {
+ {TESTDATA_DIR "/builddependencycollector/project",
+ 1,
+ ClangBackEnd::IncludeSearchPathType::User},
+ {TESTDATA_DIR "/builddependencycollector/external",
+ 2,
+ ClangBackEnd::IncludeSearchPathType::User},
+ },
+ {
+ id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
+ id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
+ id(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
+ id(TESTDATA_DIR "/builddependencycollector/project/macros.h"),
+ },
+ {id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp")},
+ Utils::Language::Cxx,
+ Utils::LanguageVersion::CXX11,
+ Utils::LanguageExtension::None};
+
+ auto buildDependency = collector.create(projectPart);
+
+ ASSERT_THAT(buildDependency.sources,
+ Contains(HasSource(id(TESTDATA_DIR "/preincludes/system1.h"),
+ SourceType::TopSystemInclude)));
+}
} // namespace
diff --git a/tests/unit/unittest/clangdocument-test.cpp b/tests/unit/unittest/clangdocument-test.cpp
index 26a4ab1bfd..4978f41fd7 100644
--- a/tests/unit/unittest/clangdocument-test.cpp
+++ b/tests/unit/unittest/clangdocument-test.cpp
@@ -201,7 +201,7 @@ TEST_F(DocumentSlowTest, NeedsReparseAfterChangeOfMainFile)
ASSERT_TRUE(document.isDirty());
}
-TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependendFile)
+TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependentFile)
{
document.parse();
@@ -210,7 +210,7 @@ TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependendFile)
ASSERT_FALSE(document.isDirty());
}
-TEST_F(DocumentSlowTest, NeedsReparsingForDependendFile)
+TEST_F(DocumentSlowTest, NeedsReparsingForDependentFile)
{
document.parse();
diff --git a/tests/unit/unittest/clangfollowsymbol-test.cpp b/tests/unit/unittest/clangfollowsymbol-test.cpp
index 628aa07618..e836cc83c6 100644
--- a/tests/unit/unittest/clangfollowsymbol-test.cpp
+++ b/tests/unit/unittest/clangfollowsymbol-test.cpp
@@ -24,7 +24,7 @@
****************************************************************************/
#include "googletest.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <clangsupport_global.h>
#include <clangfollowsymboljob.h>
@@ -113,7 +113,7 @@ public:
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{unsavedFiles};
Utf8StringVector compilationArguments{
- TestEnvironment::addPlatformArguments({Utf8StringLiteral("-std=c++14")})};
+ UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++14")})};
Document document = {sourceFilePath, compilationArguments, {}, documents};
Document headerDocument = {headerFilePath, compilationArguments, {}, documents};
QVector<Utf8String> deps{sourceFilePath, cursorPath};
diff --git a/tests/unit/unittest/clangformat-test.cpp b/tests/unit/unittest/clangformat-test.cpp
index 44217b9876..172afb64c8 100644
--- a/tests/unit/unittest/clangformat-test.cpp
+++ b/tests/unit/unittest/clangformat-test.cpp
@@ -65,9 +65,9 @@ class ClangFormat : public ::testing::Test
protected:
void SetUp() final
{
- indenter.setFileName(Utils::FileName::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
+ indenter.setFileName(Utils::FilePath::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
extendedIndenter.setFileName(
- Utils::FileName::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
+ Utils::FilePath::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
}
void insertLines(const std::vector<QString> &lines)
diff --git a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp
index 5ff87f6059..3981980902 100644
--- a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp
+++ b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp
@@ -37,6 +37,7 @@
#include <cpptools/compileroptionsbuilder.h>
#include <cpptools/projectpart.h>
+#include <projectexplorer/project.h>
namespace {
@@ -53,11 +54,62 @@ using testing::ByMove;
using CppTools::CompilerOptionsBuilder;
using ClangBackEnd::V2::FileContainer;
+std::vector<Utils::SmallStringVector> createCommandLines(
+ const std::vector<CppTools::ProjectPart::Ptr> &projectParts)
+{
+ using Filter = ClangRefactoring::ClangQueryProjectsFindFilter;
+
+ std::vector<Utils::SmallStringVector> commandLines;
+
+ for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) {
+ for (const CppTools::ProjectFile &projectFile : projectPart->files) {
+ Utils::SmallStringVector commandLine = Filter::compilerArguments(projectPart.data(),
+ projectFile.kind);
+ commandLine.emplace_back(projectFile.path);
+ commandLines.push_back(commandLine);
+ }
+ }
+
+ return commandLines;
+}
+
class ClangQueryProjectFindFilter : public ::testing::Test
{
protected:
- void SetUp();
- std::unique_ptr<ClangRefactoring::SearchHandle> createSearchHandle();
+ void SetUp()
+ {
+ projectsParts = createProjectParts();
+ commandLines = createCommandLines(projectsParts);
+
+ findFilter.setProjectParts(projectsParts);
+ findFilter.setUnsavedContent({unsavedContent.clone()});
+
+ ON_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), findDeclQueryText))
+ .WillByDefault(Return(ByMove(createSearchHandle())));
+ }
+ std::unique_ptr<ClangRefactoring::SearchHandle> createSearchHandle()
+ {
+ auto handle = std::make_unique<NiceMock<MockSearchHandle>>();
+ handle->setRefactoringServer(&mockRefactoringServer);
+
+ return handle;
+ }
+
+ std::vector<CppTools::ProjectPart::Ptr> createProjectParts()
+ {
+ auto projectPart1 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
+ projectPart1->project = &project;
+ projectPart1->files.append({"/path/to/file1.h", CppTools::ProjectFile::CXXHeader});
+ projectPart1->files.append({"/path/to/file1.cpp", CppTools::ProjectFile::CXXSource});
+
+ auto projectPart2 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
+ projectPart2->project = &project;
+ projectPart2->files.append({"/path/to/file2.cpp", CppTools::ProjectFile::CXXSource});
+ projectPart2->files.append({"/path/to/unsaved.cpp", CppTools::ProjectFile::CXXSource});
+ projectPart2->files.append({"/path/to/cheader.h", CppTools::ProjectFile::CHeader});
+
+ return {projectPart1, projectPart2};
+ }
protected:
NiceMock<MockRefactoringServer> mockRefactoringServer;
@@ -73,6 +125,7 @@ protected:
ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"},
"void f();",
{}};
+ ProjectExplorer::Project project;
};
TEST_F(ClangQueryProjectFindFilter, SupportedFindFlags)
@@ -175,60 +228,4 @@ TEST_F(ClangQueryProjectFindFilter, CallingRequestSourceRangesAndDiagnostics)
findFilter.requestSourceRangesAndDiagnostics(QString(queryText), QString(exampleContent));
}
-std::vector<CppTools::ProjectPart::Ptr> createProjectParts()
-{
- auto projectPart1 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
- projectPart1->files.append({"/path/to/file1.h", CppTools::ProjectFile::CXXHeader});
- projectPart1->files.append({"/path/to/file1.cpp", CppTools::ProjectFile::CXXSource});
-
- auto projectPart2 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
- projectPart2->files.append({"/path/to/file2.cpp", CppTools::ProjectFile::CXXSource});
- projectPart2->files.append({"/path/to/unsaved.cpp", CppTools::ProjectFile::CXXSource});
- projectPart2->files.append({"/path/to/cheader.h", CppTools::ProjectFile::CHeader});
-
-
- return {projectPart1, projectPart2};
-}
-
-std::vector<Utils::SmallStringVector>
-createCommandLines(const std::vector<CppTools::ProjectPart::Ptr> &projectParts)
-{
- using Filter = ClangRefactoring::ClangQueryProjectsFindFilter;
-
- std::vector<Utils::SmallStringVector> commandLines;
-
- for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) {
- for (const CppTools::ProjectFile &projectFile : projectPart->files) {
- Utils::SmallStringVector commandLine = Filter::compilerArguments(projectPart.data(),
- projectFile.kind);
- commandLine.emplace_back(projectFile.path);
- commandLines.push_back(commandLine);
- }
- }
-
- return commandLines;
-}
-
-void ClangQueryProjectFindFilter::SetUp()
-{
- projectsParts = createProjectParts();
- commandLines = createCommandLines(projectsParts);
-
- findFilter.setProjectParts(projectsParts);
- findFilter.setUnsavedContent({unsavedContent.clone()});
-
-
- ON_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), findDeclQueryText))
- .WillByDefault(Return(ByMove(createSearchHandle())));
-
-}
-
-std::unique_ptr<ClangRefactoring::SearchHandle> ClangQueryProjectFindFilter::createSearchHandle()
-{
- auto handle = std::make_unique<NiceMock<MockSearchHandle>>();
- handle->setRefactoringServer(&mockRefactoringServer);
-
- return handle;
-}
-
}
diff --git a/tests/unit/unittest/clangreferencescollector-test.cpp b/tests/unit/unittest/clangreferencescollector-test.cpp
index acf7c42ac3..bb04d8c8d1 100644
--- a/tests/unit/unittest/clangreferencescollector-test.cpp
+++ b/tests/unit/unittest/clangreferencescollector-test.cpp
@@ -24,7 +24,7 @@
****************************************************************************/
#include "googletest.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <clangsupport_global.h>
#include <clangreferencescollector.h>
@@ -59,7 +59,7 @@ struct Data {
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{unsavedFiles};
Document document{Utf8StringLiteral(TESTDATA_DIR"/references.cpp"),
- TestEnvironment::addPlatformArguments({Utf8StringLiteral("-std=c++14")}),
+ UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++14")}),
{},
documents};
};
diff --git a/tests/unit/unittest/clangtooltipinfo-test.cpp b/tests/unit/unittest/clangtooltipinfo-test.cpp
index 807618deef..fb630e2aa3 100644
--- a/tests/unit/unittest/clangtooltipinfo-test.cpp
+++ b/tests/unit/unittest/clangtooltipinfo-test.cpp
@@ -153,7 +153,7 @@ TEST_F(ToolTipInfo, MemberVariable)
ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("int"))));
}
-TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(MemberFunctionCall_QualifiedName))
+TEST_F(ToolTipInfo, MemberFunctionCall_QualifiedName)
{
const ::ToolTipInfo actual = tooltip(21, 9);
@@ -161,7 +161,7 @@ TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(MemberFunctionCall_Qualifi
}
// ChangeLog: Show extra specifiers. For functions e.g.: virtual, inline, explicit, const, volatile
-TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(MemberFunctionCall_ExtraSpecifiers))
+TEST_F(ToolTipInfo, MemberFunctionCall_ExtraSpecifiers)
{
const ::ToolTipInfo actual = tooltip(22, 9);
@@ -199,7 +199,7 @@ TEST_F(ToolTipInfo, MemberFunctionCall_qdocCategory)
}
// TODO: Show the template parameter type, too: "template<typename T>...)"
-TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(TemplateFunctionCall))
+TEST_F(ToolTipInfo, TemplateFunctionCall)
{
const ::ToolTipInfo actual = tooltip(30, 5);
@@ -548,7 +548,7 @@ TEST_F(ToolTipInfo, Function_qdocIdCandidatesAreQualified)
Utf8StringLiteral("f")));
}
-TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(Function_HasParameterName))
+TEST_F(ToolTipInfo, Function_HasParameterName)
{
const ::ToolTipInfo actual = tooltip(167, 5);
@@ -621,21 +621,21 @@ TEST_F(ToolTipInfo, AutoTypeClassTemplateType)
ASSERT_THAT(actual.text, Utf8StringLiteral("Zii<int>"));
}
-TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(Function_DefaultConstructor))
+TEST_F(ToolTipInfo, Function_DefaultConstructor)
{
const ::ToolTipInfo actual = tooltip(193, 5);
ASSERT_THAT(actual.text, Utf8StringLiteral("inline constexpr Con::Con() noexcept"));
}
-TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(Function_ExplicitDefaultConstructor))
+TEST_F(ToolTipInfo, Function_ExplicitDefaultConstructor)
{
const ::ToolTipInfo actual = tooltip(194, 5);
ASSERT_THAT(actual.text, Utf8StringLiteral("ExplicitCon::ExplicitCon() noexcept = default"));
}
-TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(Function_CustomConstructor))
+TEST_F(ToolTipInfo, Function_CustomConstructor)
{
const ::ToolTipInfo actual = tooltip(195, 5);
diff --git a/tests/unit/unittest/clangupdateannotationsjob-test.cpp b/tests/unit/unittest/clangupdateannotationsjob-test.cpp
index 0bcd5a67c0..79623619c1 100644
--- a/tests/unit/unittest/clangupdateannotationsjob-test.cpp
+++ b/tests/unit/unittest/clangupdateannotationsjob-test.cpp
@@ -97,16 +97,16 @@ TEST_F(UpdateAnnotationsJobSlowTest, DontSendAnnotationsIfDocumentRevisionChange
ASSERT_TRUE(waitUntilJobFinished(job));
}
-TEST_F(UpdateAnnotationsJobSlowTest, UpdatesDependendFilePaths)
+TEST_F(UpdateAnnotationsJobSlowTest, UpdatesDependentFilePaths)
{
- const QSet<Utf8String> dependendOnFilesBefore = document.dependedFilePaths();
+ const QSet<Utf8String> dependentOnFilesBefore = document.dependedFilePaths();
job.setContext(jobContext);
job.prepareAsyncRun();
job.runAsync();
ASSERT_TRUE(waitUntilJobFinished(job));
- ASSERT_THAT(dependendOnFilesBefore, Not(document.dependedFilePaths()));
+ ASSERT_THAT(dependentOnFilesBefore, Not(document.dependedFilePaths()));
}
TEST_F(UpdateAnnotationsJobSlowTest, UpdatesUnresolvedFilePaths)
diff --git a/tests/unit/unittest/codecompletionsextractor-test.cpp b/tests/unit/unittest/codecompletionsextractor-test.cpp
index ae7559ce78..509dfd49dc 100644
--- a/tests/unit/unittest/codecompletionsextractor-test.cpp
+++ b/tests/unit/unittest/codecompletionsextractor-test.cpp
@@ -24,7 +24,7 @@
****************************************************************************/
#include "googletest.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <clangcodecompleteresults.h>
#include <clangdocument.h>
@@ -148,7 +148,7 @@ protected:
protected:
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{unsavedFiles};
- Utf8StringVector compilationArguments{TestEnvironment::addPlatformArguments()};
+ 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};
diff --git a/tests/unit/unittest/commandlinebuilder-test.cpp b/tests/unit/unittest/commandlinebuilder-test.cpp
index 8979cebca8..c5765037dc 100644
--- a/tests/unit/unittest/commandlinebuilder-test.cpp
+++ b/tests/unit/unittest/commandlinebuilder-test.cpp
@@ -36,6 +36,7 @@ namespace {
template<typename ProjectInfo>
using Builder = ClangBackEnd::CommandLineBuilder<ProjectInfo>;
+using ClangBackEnd::FilePath;
using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::InputFileType;
@@ -48,10 +49,7 @@ template <>
class CommandLineBuilder<ClangBackEnd::PchTask> : public testing::Test
{
public:
- CommandLineBuilder()
- {
- cppProjectInfo.language = Utils::Language::Cxx;
- }
+ CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; }
public:
ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}};
@@ -62,10 +60,7 @@ template <>
class CommandLineBuilder<ClangBackEnd::ProjectPartContainer> : public testing::Test
{
public:
- CommandLineBuilder()
- {
- cppProjectInfo.language = Utils::Language::Cxx;
- }
+ CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; }
public:
ClangBackEnd::ProjectPartContainer emptyProjectInfo{0,
@@ -94,10 +89,7 @@ template <>
class CommandLineBuilder<ClangBackEnd::ProjectPartArtefact> : public testing::Test
{
public:
- CommandLineBuilder()
- {
- cppProjectInfo.language = Utils::Language::Cxx;
- }
+ CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; }
public:
ClangBackEnd::ProjectPartArtefact emptyProjectInfo{{},
@@ -502,7 +494,13 @@ TYPED_TEST(CommandLineBuilder, IncludesOrder)
{"/system/foo", 3, IncludeSearchPathType::Framework},
{"/builtin/bar", 2, IncludeSearchPathType::BuiltIn},
{"/builtin/foo", 1, IncludeSearchPathType::BuiltIn}};
- Builder<TypeParam> builder{this->emptyProjectInfo, {}, InputFileType::Header, "/source/file.cpp"};
+ Builder<TypeParam> builder{this->emptyProjectInfo,
+ {},
+ InputFileType::Header,
+ "/source/file.cpp",
+ {},
+ {},
+ ClangBackEnd::NativeFilePath{FilePath{"/resource/path"}}};
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
@@ -513,6 +511,8 @@ TYPED_TEST(CommandLineBuilder, IncludesOrder)
"-std=c++11",
"-nostdinc",
"-nostdinc++",
+ "-isystem",
+ toNativePath("/resource/path"),
"-I",
toNativePath("/include/foo"),
"-I",
@@ -598,6 +598,19 @@ TYPED_TEST(CommandLineBuilder, OutputFile)
toNativePath("/source/file.cpp")));
}
+TYPED_TEST(CommandLineBuilder, PreIncludeSearchPath)
+{
+ Builder<TypeParam> builder{this->emptyProjectInfo,
+ {},
+ {},
+ {},
+ {},
+ {},
+ ClangBackEnd::NativeFilePath{FilePath{"/resource/path"}}};
+
+ ASSERT_THAT(builder.commandLine, Contains(toNativePath("/resource/path")));
+}
+
TYPED_TEST(CommandLineBuilder, IncludePchPath)
{
Builder<TypeParam> builder{this->emptyProjectInfo,
diff --git a/tests/unit/unittest/compilationdatabaseutils-test.cpp b/tests/unit/unittest/compilationdatabaseutils-test.cpp
index 252ab2ffd6..cae74fa807 100644
--- a/tests/unit/unittest/compilationdatabaseutils-test.cpp
+++ b/tests/unit/unittest/compilationdatabaseutils-test.cpp
@@ -29,26 +29,35 @@
#include <projectexplorer/headerpath.h>
#include <projectexplorer/projectmacro.h>
#include <utils/fileutils.h>
+#include <utils/hostosinfo.h>
using namespace ProjectExplorer;
using namespace CompilationDatabaseProjectManager;
+using namespace CompilationDatabaseProjectManager::Internal;
namespace {
class CompilationDatabaseUtils : public ::testing::Test
{
protected:
+ QStringList splitCommandLine(const QString &commandLine)
+ {
+ QSet<QString> flagsCache;
+ return CompilationDatabaseProjectManager::Internal::splitCommandLine(commandLine, flagsCache);
+ }
+
HeaderPaths headerPaths;
Macros macros;
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::Unclassified;
QStringList flags;
QString fileName;
QString workingDir;
+ QString sysRoot;
};
TEST_F(CompilationDatabaseUtils, FilterEmptyFlags)
{
- filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
+ filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind, sysRoot);
ASSERT_THAT(flags.isEmpty(), true);
}
@@ -62,77 +71,89 @@ TEST_F(CompilationDatabaseUtils, FilterFromFilename)
TEST_F(CompilationDatabaseUtils, FilterArguments)
{
+ using Utils::HostOsInfo;
+ const char winPath1[] = "C:\\Qt\\5.9.2\\mingw53_32\\include";
+ const char otherPath1[] = "/Qt/5.9.2/mingw53_32/include";
+ const char winPath2[] = "C:\\Qt\\5.9.2\\mingw53_32\\include\\QtWidgets";
+ const char otherPath2[] = "/Qt/5.9.2/mingw53_32/include/QtWidgets";
fileName = "compileroptionsbuilder.cpp";
workingDir = "C:/build-qtcreator-MinGW_32bit-Debug";
- flags = filterFromFileName(QStringList {
- "clang++",
- "-c",
- "-m32",
- "-target",
- "i686-w64-mingw32",
- "-std=gnu++14",
- "-fcxx-exceptions",
- "-fexceptions",
- "-DUNICODE",
- "-DRELATIVE_PLUGIN_PATH=\"../lib/qtcreator/plugins\"",
- "-DQT_CREATOR",
- "-fPIC",
- "-I",
- "C:\\Qt\\5.9.2\\mingw53_32\\include",
- "-I",
- "C:\\Qt\\5.9.2\\mingw53_32\\include\\QtWidgets",
- "-x",
- "c++",
- "C:\\qt-creator\\src\\plugins\\cpptools\\compileroptionsbuilder.cpp"
- }, "compileroptionsbuilder");
-
- filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
-
- ASSERT_THAT(flags, Eq(QStringList{"-m32",
- "-target",
- "i686-w64-mingw32",
- "-std=gnu++14",
- "-fcxx-exceptions",
- "-fexceptions"}));
- ASSERT_THAT(headerPaths, Eq(HeaderPaths{
- {"C:\\Qt\\5.9.2\\mingw53_32\\include", HeaderPathType::User},
- {"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtWidgets", HeaderPathType::User}
- }));
- ASSERT_THAT(macros, Eq(Macros{
- {"UNICODE", "1"},
- {"RELATIVE_PLUGIN_PATH", "\"../lib/qtcreator/plugins\""},
- {"QT_CREATOR", "1"}
- }));
+ flags = filterFromFileName(
+ QStringList{"clang++",
+ "-c",
+ "-m32",
+ "-target",
+ "i686-w64-mingw32",
+ "-std=gnu++14",
+ "-fcxx-exceptions",
+ "-fexceptions",
+ "-DUNICODE",
+ "-DRELATIVE_PLUGIN_PATH=\"../lib/qtcreator/plugins\"",
+ "-DQT_CREATOR",
+ "-fPIC",
+ "-I",
+ QString::fromUtf8(HostOsInfo::isWindowsHost() ? winPath1 : otherPath1),
+ "-I",
+ QString::fromUtf8(HostOsInfo::isWindowsHost() ? winPath2 : otherPath2),
+ "-x",
+ "c++",
+ QString("--sysroot=") + (HostOsInfo::isWindowsHost()
+ ? "C:\\sysroot\\embedded" : "/opt/sysroot/embedded"),
+ "C:\\qt-creator\\src\\plugins\\cpptools\\compileroptionsbuilder.cpp"},
+ "compileroptionsbuilder");
+
+ filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind, sysRoot);
+
+ ASSERT_THAT(flags,
+ Eq(QStringList{"-m32",
+ "-target",
+ "i686-w64-mingw32",
+ "-std=gnu++14",
+ "-fcxx-exceptions",
+ "-fexceptions"}));
+ ASSERT_THAT(headerPaths,
+ Eq(HeaderPaths{{QString::fromUtf8(HostOsInfo::isWindowsHost() ? winPath1 : otherPath1),
+ HeaderPathType::User},
+ {QString::fromUtf8(HostOsInfo::isWindowsHost() ? winPath2 : otherPath2),
+ HeaderPathType::User}}));
+ ASSERT_THAT(macros,
+ Eq(Macros{{"UNICODE", "1"},
+ {"RELATIVE_PLUGIN_PATH", "\"../lib/qtcreator/plugins\""},
+ {"QT_CREATOR", "1"}}));
ASSERT_THAT(fileKind, CppTools::ProjectFile::Kind::CXXSource);
+ ASSERT_THAT(sysRoot, HostOsInfo::isWindowsHost() ? QString("C:\\sysroot\\embedded")
+ : QString("/opt/sysroot/embedded"));
}
-static QString kCmakeCommand = "C:\\PROGRA~2\\MICROS~2\\2017\\COMMUN~1\\VC\\Tools\\MSVC\\1415~1.267\\bin\\HostX64\\x64\\cl.exe "
- "/nologo "
- "/TP "
- "-DUNICODE "
- "-D_HAS_EXCEPTIONS=0 "
- "-Itools\\clang\\lib\\Sema "
- "/DWIN32 "
- "/D_WINDOWS "
- "/Zc:inline "
- "/Zc:strictStrings "
- "/Oi "
- "/Zc:rvalueCast "
- "/W4 "
- "-wd4141 "
- "-wd4146 "
- "/MDd "
- "/Zi "
- "/Ob0 "
- "/Od "
- "/RTC1 "
- "/EHs-c- "
- "/GR "
- "/Fotools\\clang\\lib\\Sema\\CMakeFiles\\clangSema.dir\\SemaCodeComplete.cpp.obj "
- "/FdTARGET_COMPILE_PDB "
- "/FS "
- "-c "
- "C:\\qt_llvm\\tools\\clang\\lib\\Sema\\SemaCodeComplete.cpp";
+static QString kCmakeCommand
+ = "C:\\PROGRA~2\\MICROS~2\\2017\\COMMUN~1\\VC\\Tools\\MSVC\\1415~1.267\\bin\\HostX64\\x64\\cl."
+ "exe "
+ "/nologo "
+ "/TP "
+ "-DUNICODE "
+ "-D_HAS_EXCEPTIONS=0 "
+ "-Itools\\clang\\lib\\Sema "
+ "/DWIN32 "
+ "/D_WINDOWS "
+ "/Zc:inline "
+ "/Zc:strictStrings "
+ "/Oi "
+ "/Zc:rvalueCast "
+ "/W4 "
+ "-wd4141 "
+ "-wd4146 "
+ "/MDd "
+ "/Zi "
+ "/Ob0 "
+ "/Od "
+ "/RTC1 "
+ "/EHs-c- "
+ "/GR "
+ "/Fotools\\clang\\lib\\Sema\\CMakeFiles\\clangSema.dir\\SemaCodeComplete.cpp.obj "
+ "/FdTARGET_COMPILE_PDB "
+ "/FS "
+ "-c "
+ "C:\\qt_llvm\\tools\\clang\\lib\\Sema\\SemaCodeComplete.cpp";
TEST_F(CompilationDatabaseUtils, SplitFlags)
{
@@ -155,21 +176,14 @@ TEST_F(CompilationDatabaseUtils, FilterCommand)
workingDir = "C:/build-qt_llvm-msvc2017_64bit-Debug";
flags = filterFromFileName(splitCommandLine(kCmakeCommand), "SemaCodeComplete");
- filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
-
- ASSERT_THAT(flags, Eq(QStringList{"/Zc:inline",
- "/Zc:strictStrings",
- "/Zc:rvalueCast",
- "/Zi"}));
- ASSERT_THAT(headerPaths, Eq(HeaderPaths{
- {"tools\\clang\\lib\\Sema", HeaderPathType::User}
- }));
- ASSERT_THAT(macros, Eq(Macros{
- {"UNICODE", "1"},
- {"_HAS_EXCEPTIONS", "0"},
- {"WIN32", "1"},
- {"_WINDOWS", "1"}
- }));
+ filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind, sysRoot);
+
+ ASSERT_THAT(flags, Eq(QStringList{"/Zc:inline", "/Zc:strictStrings", "/Zc:rvalueCast", "/Zi"}));
+ ASSERT_THAT(headerPaths,
+ Eq(HeaderPaths{{"C:/build-qt_llvm-msvc2017_64bit-Debug/tools\\clang\\lib\\Sema",
+ HeaderPathType::User}}));
+ ASSERT_THAT(macros,
+ Eq(Macros{{"UNICODE", "1"}, {"_HAS_EXCEPTIONS", "0"}, {"WIN32", "1"}, {"_WINDOWS", "1"}}));
ASSERT_THAT(fileKind, CppTools::ProjectFile::Kind::CXXSource);
}
@@ -178,7 +192,7 @@ TEST_F(CompilationDatabaseUtils, FileKindDifferentFromExtension)
fileName = "foo.c";
flags = QStringList{"-xc++"};
- filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
+ filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind, sysRoot);
ASSERT_THAT(fileKind, CppTools::ProjectFile::Kind::CXXSource);
}
@@ -186,9 +200,9 @@ TEST_F(CompilationDatabaseUtils, FileKindDifferentFromExtension)
TEST_F(CompilationDatabaseUtils, FileKindDifferentFromExtension2)
{
fileName = "foo.cpp";
- flags = QStringList{"-x", "c"};
+ flags = QStringList{"-x", "c"};
- filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
+ filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind, sysRoot);
ASSERT_THAT(fileKind, CppTools::ProjectFile::Kind::CSource);
}
@@ -197,9 +211,9 @@ TEST_F(CompilationDatabaseUtils, SkipOutputFiles)
{
flags = filterFromFileName(QStringList{"-o", "foo.o"}, "foo");
- filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
+ filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind, sysRoot);
ASSERT_THAT(flags.isEmpty(), true);
}
-}
+} // namespace
diff --git a/tests/unit/unittest/conditionally-disabled-tests.h b/tests/unit/unittest/conditionally-disabled-tests.h
index 0b6f279975..c88a844b96 100644
--- a/tests/unit/unittest/conditionally-disabled-tests.h
+++ b/tests/unit/unittest/conditionally-disabled-tests.h
@@ -39,15 +39,3 @@
#else
# define DISABLED_ON_NON_WINDOWS(x) x
#endif
-
-#ifdef IS_PRETTY_DECL_SUPPORTED
-# define DISABLED_WITHOUT_PRETTYDECL_PATCH(x) x
-#else
-# define DISABLED_WITHOUT_PRETTYDECL_PATCH(x) DISABLED_##x
-#endif
-
-#ifdef IS_INVALIDDECL_SUPPORTED
-# define DISABLED_WITHOUT_INVALIDDECL_PATCH(x) x
-#else
-# define DISABLED_WITHOUT_INVALIDDECL_PATCH(x) DISABLED_##x
-#endif
diff --git a/tests/unit/unittest/cppprojectinfogenerator-test.cpp b/tests/unit/unittest/cppprojectinfogenerator-test.cpp
index 9d39b8eada..7db9f0e439 100644
--- a/tests/unit/unittest/cppprojectinfogenerator-test.cpp
+++ b/tests/unit/unittest/cppprojectinfogenerator-test.cpp
@@ -164,8 +164,11 @@ void ProjectInfoGenerator::SetUp()
ProjectInfo ProjectInfoGenerator::generate()
{
QFutureInterface<void> fi;
+ ProjectExplorer::ConcreteToolChain aToolChain;
projectUpdateInfo.rawProjectParts += rawProjectPart;
+ projectUpdateInfo.cxxToolChain = &aToolChain;
+ projectUpdateInfo.cToolChain = &aToolChain;
::ProjectInfoGenerator generator(fi, projectUpdateInfo);
return generator.generate();
diff --git a/tests/unit/unittest/cursor-test.cpp b/tests/unit/unittest/cursor-test.cpp
index e55668d420..2fa4bff709 100644
--- a/tests/unit/unittest/cursor-test.cpp
+++ b/tests/unit/unittest/cursor-test.cpp
@@ -26,7 +26,7 @@
#include "googletest.h"
#include "clangcompareoperators.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <clangdocument.h>
#include <clangdocuments.h>
@@ -63,7 +63,7 @@ struct Data {
ClangBackEnd::Documents documents{unsavedFiles};
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp")};
Document document{filePath,
- TestEnvironment::addPlatformArguments({Utf8StringLiteral("-std=c++11")}),
+ UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++11")}),
{},
documents};
TranslationUnit translationUnit{filePath,
diff --git a/tests/unit/unittest/data/preincludes/system1.h b/tests/unit/unittest/data/preincludes/system1.h
new file mode 100644
index 0000000000..005a65916e
--- /dev/null
+++ b/tests/unit/unittest/data/preincludes/system1.h
@@ -0,0 +1 @@
+#include_next <system1.h>
diff --git a/tests/unit/unittest/diagnostic-test.cpp b/tests/unit/unittest/diagnostic-test.cpp
index fac44162cd..3ab382c46b 100644
--- a/tests/unit/unittest/diagnostic-test.cpp
+++ b/tests/unit/unittest/diagnostic-test.cpp
@@ -23,10 +23,10 @@
**
****************************************************************************/
-#include "googletest.h"
#include "diagnosticcontainer-matcher.h"
+#include "googletest.h"
#include "rundocumentparse-utility.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <diagnostic.h>
#include <diagnosticcontainer.h>
@@ -87,7 +87,7 @@ protected:
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{unsavedFiles};
Document document{Utf8StringLiteral(TESTDATA_DIR"/diagnostic_diagnostic.cpp"),
- TestEnvironment::addPlatformArguments({Utf8StringLiteral("-std=c++11")}),
+ UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++11")}),
{},
documents};
UnitTest::RunDocumentParse _1{document};
diff --git a/tests/unit/unittest/diagnosticset-test.cpp b/tests/unit/unittest/diagnosticset-test.cpp
index f37d00e13f..b59325e0e7 100644
--- a/tests/unit/unittest/diagnosticset-test.cpp
+++ b/tests/unit/unittest/diagnosticset-test.cpp
@@ -23,9 +23,9 @@
**
****************************************************************************/
-#include "googletest.h"
#include "diagnosticcontainer-matcher.h"
-#include "testenvironment.h"
+#include "googletest.h"
+#include "unittest-utility-functions.h"
#include <clangsupport_global.h>
#include <clangdocument.h>
@@ -64,7 +64,7 @@ protected:
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{unsavedFiles};
Utf8StringVector compilationArguments{
- TestEnvironment::addPlatformArguments({Utf8StringLiteral("-pedantic")})};
+ UnitTest::addPlatformArguments({Utf8StringLiteral("-pedantic")})};
Document document{Utf8StringLiteral(TESTDATA_DIR "/diagnostic_diagnosticset.cpp"),
compilationArguments,
{},
diff --git a/tests/unit/unittest/filesystem-utilities.h b/tests/unit/unittest/filesystem-utilities.h
index fa75f06ad1..7238cfab75 100644
--- a/tests/unit/unittest/filesystem-utilities.h
+++ b/tests/unit/unittest/filesystem-utilities.h
@@ -29,6 +29,9 @@
#include <nativefilepath.h>
+#include <QCoreApplication>
+#include <QDir>
+
template<std::size_t Size>
ClangBackEnd::NativeFilePath toNativePath(const char (&text)[Size])
{
@@ -50,3 +53,9 @@ inline Utils::PathString toNativePath(Utils::SmallStringView 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/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 3cb7e45def..7ac4a676e3 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -39,27 +39,28 @@
#include <clangpathwatcher.h>
#include <clangrefactoringmessages.h>
#include <clangreferencescollector.h>
-#include <filestatus.h>
#include <filepath.h>
#include <filepathcaching.h>
+#include <filepathview.h>
+#include <filestatus.h>
#include <fulltokeninfo.h>
#include <includesearchpath.h>
#include <nativefilepath.h>
+#include <pchpaths.h>
#include <pchtask.h>
#include <precompiledheadersupdatedmessage.h>
#include <projectpartartefact.h>
-#include <projectpartid.h>
+#include <projectpartentry.h>
+#include <projectpartpch.h>
#include <sourcedependency.h>
#include <sourcelocationentry.h>
#include <sourcelocationscontainer.h>
-#include <tokenprocessor.h>
-#include <filepathview.h>
+#include <symbol.h>
#include <symbolentry.h>
#include <symbolindexertaskqueue.h>
-#include <symbol.h>
-#include <tooltipinfo.h>
+#include <tokenprocessor.h>
#include <toolchainargumentscache.h>
-#include <projectpartentry.h>
+#include <tooltipinfo.h>
#include <usedmacro.h>
#include <cpptools/usages.h>
@@ -193,6 +194,8 @@ const char * toText(Utils::Language language)
return "C";
case Language::Cxx:
return "Cxx";
+ case Language::None:
+ return "None";
}
return "";
@@ -228,6 +231,8 @@ const char * toText(Utils::LanguageVersion languageVersion)
return "CXX2a";
case LanguageVersion::CXX98:
return "CXX98";
+ case LanguageVersion::None:
+ return "None";
}
return "";
@@ -714,18 +719,14 @@ std::ostream &operator<<(std::ostream &out, const NativeFilePath &filePath)
std::ostream &operator<<(std::ostream &out, const PrecompiledHeadersUpdatedMessage &message)
{
- out << "("
- << message.projectPartPchs
- << ")";
+ out << "(" << message.projectPartIds << ")";
return out;
}
std::ostream &operator<<(std::ostream &out, const ProjectPartPch &projectPartPch)
{
- out << "("
- << projectPartPch.projectPartId << ", "
- << projectPartPch.pchPath << ", "
+ out << "(" << projectPartPch.projectPartId << ", " << projectPartPch.pchPath << ", "
<< projectPartPch.lastModified << ")";
return out;
@@ -1226,6 +1227,16 @@ std::ostream &operator<<(std::ostream &out, const SourceEntry &entry)
<< typeToString(entry.hasMissingIncludes) << ")";
}
+std::ostream &operator<<(std::ostream &out, const SourceTimeStamp &sourceTimeStamp)
+{
+ return out << "(" << sourceTimeStamp.sourceId << ", " << sourceTimeStamp.timeStamp << ")";
+}
+
+std::ostream &operator<<(std::ostream &out, const TimeStamp &timeStamp)
+{
+ return out << timeStamp.value;
+}
+
const char *typeToString(IncludeSearchPathType type)
{
switch (type) {
@@ -1275,6 +1286,10 @@ std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId)
return out << projectPathId.projectPathId;
}
+std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths)
+{
+ return out << "(" << pchPaths.projectPchPath << ", " << pchPaths.systemPchPath << ")";
+}
void PrintTo(const FilePath &filePath, ::std::ostream *os)
{
*os << filePath;
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 9e2c5632f5..b874fc90e4 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -49,7 +49,7 @@ std::ostream &operator<<(std::ostream &out, const CompileCommand &command);
} // namespace clang
namespace Core {
-class LocatorFilterEntry;
+struct LocatorFilterEntry;
std::ostream &operator<<(std::ostream &out, const LocatorFilterEntry &entry);
@@ -165,7 +165,7 @@ class UpdateProjectPartsMessage;
class DocumentsChangedMessage;
class DocumentVisibilityChangedMessage;
class FilePath;
-template <char WindowsSlash>
+template<char WindowsSlash>
class AbstractFilePathView;
using FilePathView = AbstractFilePathView<'/'>;
using NativeFilePathView = AbstractFilePathView<'\\'>;
@@ -190,6 +190,8 @@ class PchTask;
class PchTaskSet;
class BuildDependency;
class SourceEntry;
+class SourceTimeStamp;
+class TimeStamp;
class FilePathCaching;
struct SlotUsage;
class IncludeSearchPath;
@@ -197,6 +199,7 @@ enum class IncludeSearchPathType : unsigned char;
struct ArgumentsEntry;
class ProjectPartContainer;
class ProjectPartId;
+class PchPaths;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -281,12 +284,15 @@ std::ostream &operator<<(std::ostream &out, const PchTask &task);
std::ostream &operator<<(std::ostream &out, const PchTaskSet &taskSet);
std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency);
std::ostream &operator<<(std::ostream &out, const SourceEntry &entry);
+std::ostream &operator<<(std::ostream &out, const SourceTimeStamp &sourceTimeStamp);
+std::ostream &operator<<(std::ostream &out, const TimeStamp &timeStamp);
std::ostream &operator<<(std::ostream &out, const SlotUsage &slotUsage);
std::ostream &operator<<(std::ostream &out, const IncludeSearchPathType &pathType);
std::ostream &operator<<(std::ostream &out, const IncludeSearchPath &path);
std::ostream &operator<<(std::ostream &out, const ArgumentsEntry &entry);
std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container);
std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId);
+std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths);
void PrintTo(const FilePath &filePath, ::std::ostream *os);
void PrintTo(const FilePathView &filePathView, ::std::ostream *os);
diff --git a/tests/unit/unittest/headerpathfilter-test.cpp b/tests/unit/unittest/headerpathfilter-test.cpp
index 9a75399443..79091e0a0b 100644
--- a/tests/unit/unittest/headerpathfilter-test.cpp
+++ b/tests/unit/unittest/headerpathfilter-test.cpp
@@ -26,6 +26,7 @@
#include "googletest.h"
#include <cpptools/headerpathfilter.h>
+#include <projectexplorer/project.h>
namespace {
@@ -37,7 +38,7 @@ MATCHER_P(HasBuiltIn,
std::string(negation ? "isn't " : "is ")
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::BuiltIn}))
{
- return arg.path == path && arg.type == HeaderPathType::BuiltIn;
+ return arg.path == QString::fromUtf8(path) && arg.type == HeaderPathType::BuiltIn;
}
MATCHER_P(HasSystem,
@@ -45,7 +46,7 @@ MATCHER_P(HasSystem,
std::string(negation ? "isn't " : "is ")
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::System}))
{
- return arg.path == path && arg.type == HeaderPathType::System;
+ return arg.path == QString::fromUtf8(path) && arg.type == HeaderPathType::System;
}
MATCHER_P(HasFramework,
@@ -53,7 +54,7 @@ MATCHER_P(HasFramework,
std::string(negation ? "isn't " : "is ")
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::Framework}))
{
- return arg.path == path && arg.type == HeaderPathType::Framework;
+ return arg.path == QString::fromUtf8(path) && arg.type == HeaderPathType::Framework;
}
MATCHER_P(HasUser,
@@ -61,7 +62,7 @@ MATCHER_P(HasUser,
std::string(negation ? "isn't " : "is ")
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::User}))
{
- return arg.path == path && arg.type == HeaderPathType::User;
+ return arg.path == QString::fromUtf8(path) && arg.type == HeaderPathType::User;
}
class HeaderPathFilter : public testing::Test
@@ -80,9 +81,11 @@ protected:
HeaderPath{"/project/user_path", HeaderPathType::User}};
projectPart.headerPaths = headerPaths;
+ projectPart.project = &project;
}
protected:
+ ProjectExplorer::Project project;
CppTools::ProjectPart projectPart;
CppTools::HeaderPathFilter filter{
projectPart, CppTools::UseTweakedHeaderPaths::No, {}, {}, "/project", "/build"};
@@ -100,7 +103,8 @@ TEST_F(HeaderPathFilter, System)
filter.process();
ASSERT_THAT(filter.systemHeaderPaths,
- ElementsAre(HasSystem("/system_path"),
+ ElementsAre(HasSystem("/project/.pre_includes"),
+ HasSystem("/system_path"),
HasFramework("/framework_path"),
HasUser("/outside_project_user_path"),
HasUser("/buildb/user_path"),
@@ -137,7 +141,8 @@ TEST_F(HeaderPathFilter, DontAddInvalidPath)
AllOf(Field(&CppTools::HeaderPathFilter::builtInHeaderPaths,
ElementsAre(HasBuiltIn("/builtin_path"))),
Field(&CppTools::HeaderPathFilter::systemHeaderPaths,
- ElementsAre(HasSystem("/system_path"),
+ ElementsAre(HasSystem("/project/.pre_includes"),
+ HasSystem("/system_path"),
HasFramework("/framework_path"),
HasUser("/outside_project_user_path"),
HasUser("/buildb/user_path"),
diff --git a/tests/unit/unittest/highlightingresultreporter-test.cpp b/tests/unit/unittest/highlightingresultreporter-test.cpp
index dfe8dfbd2e..dd2001e02f 100644
--- a/tests/unit/unittest/highlightingresultreporter-test.cpp
+++ b/tests/unit/unittest/highlightingresultreporter-test.cpp
@@ -24,7 +24,7 @@
****************************************************************************/
#include "googletest.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <chunksreportedmonitor.h>
#include <clangdocument.h>
@@ -51,7 +51,7 @@ struct Data {
UnsavedFiles unsavedFiles;
Documents documents{unsavedFiles};
Document document{Utf8StringLiteral(TESTDATA_DIR "/highlightingmarks.cpp"),
- TestEnvironment::addPlatformArguments({Utf8StringLiteral("-std=c++14")}),
+ UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++14")}),
Utf8StringVector(),
documents};
};
diff --git a/tests/unit/unittest/matchingtext-test.cpp b/tests/unit/unittest/matchingtext-test.cpp
index 081e356764..b49731d3e6 100644
--- a/tests/unit/unittest/matchingtext-test.cpp
+++ b/tests/unit/unittest/matchingtext-test.cpp
@@ -221,6 +221,41 @@ TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotInTheMiddle)
ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{"));
}
+TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotAfterControlFlow_WhileAndFriends)
+{
+ const Document document("while (true) @");
+
+ ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{"));
+}
+
+TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotAfterControlFlow_DoAndFriends)
+{
+ const Document document("do @");
+
+ ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{"));
+}
+
+TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_InvalidCode_UnbalancedParens)
+{
+ const Document document(") @");
+
+ ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{"));
+}
+
+TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_InvalidCode_UnbalancedParens2)
+{
+ const Document document("while true) @");
+
+ ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{"));
+}
+
+TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_InvalidCode_OnlyBalancedParens)
+{
+ const Document document("() @");
+
+ ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{"));
+}
+
TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeNamedNamespace)
{
const Document document("namespace X @");
diff --git a/tests/unit/unittest/mockbuilddependenciesstorage.h b/tests/unit/unittest/mockbuilddependenciesstorage.h
index 46c201de55..a4d34e481d 100644
--- a/tests/unit/unittest/mockbuilddependenciesstorage.h
+++ b/tests/unit/unittest/mockbuilddependenciesstorage.h
@@ -51,5 +51,7 @@ public:
ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName));
MOCK_METHOD2(updatePchCreationTimeStamp,
void(long long pchCreationTimeStamp, ClangBackEnd::ProjectPartId projectPartId));
+ MOCK_CONST_METHOD1(fetchSources,
+ ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId));
};
diff --git a/tests/unit/unittest/mockmodifiedtimechecker.h b/tests/unit/unittest/mockmodifiedtimechecker.h
index 5f0559f682..bf101988b1 100644
--- a/tests/unit/unittest/mockmodifiedtimechecker.h
+++ b/tests/unit/unittest/mockmodifiedtimechecker.h
@@ -29,9 +29,17 @@
#include <modifiedtimecheckerinterface.h>
-class MockModifiedTimeChecker : public ClangBackEnd::ModifiedTimeCheckerInterface
+class MockSourceEntriesModifiedTimeChecker
+ : public ClangBackEnd::ModifiedTimeCheckerInterface<ClangBackEnd::SourceEntries>
{
public:
MOCK_CONST_METHOD1(isUpToDate,
bool (const ClangBackEnd::SourceEntries &sourceEntries));
};
+
+class MockSourceTimeStampsModifiedTimeChecker
+ : public ClangBackEnd::ModifiedTimeCheckerInterface<ClangBackEnd::SourceTimeStamps>
+{
+public:
+ MOCK_CONST_METHOD1(isUpToDate, bool(const ClangBackEnd::SourceTimeStamps &sourceTimeStamps));
+};
diff --git a/tests/unit/unittest/mockpchmanagernotifier.h b/tests/unit/unittest/mockpchmanagernotifier.h
index 600b37bd2e..8db9a63c40 100644
--- a/tests/unit/unittest/mockpchmanagernotifier.h
+++ b/tests/unit/unittest/mockpchmanagernotifier.h
@@ -36,9 +36,6 @@ public:
: ClangPchManager::PchManagerNotifierInterface(pchManagerClient)
{}
- MOCK_METHOD3(precompiledHeaderUpdated,
- void(ClangBackEnd::ProjectPartId projectPartId,
- const QString &pchFilePath,
- long long lastModified));
+ MOCK_METHOD1(precompiledHeaderUpdated, void(ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD1(precompiledHeaderRemoved, void(ClangBackEnd::ProjectPartId projectPartId));
};
diff --git a/tests/unit/unittest/mockprecompiledheaderstorage.h b/tests/unit/unittest/mockprecompiledheaderstorage.h
index 31c38affda..84caea55be 100644
--- a/tests/unit/unittest/mockprecompiledheaderstorage.h
+++ b/tests/unit/unittest/mockprecompiledheaderstorage.h
@@ -37,6 +37,8 @@ public:
Utils::SmallStringView pchPath,
long long pchBuildTime));
MOCK_METHOD1(deleteProjectPrecompiledHeader, void(ClangBackEnd::ProjectPartId projectPartId));
+ MOCK_METHOD1(deleteProjectPrecompiledHeaders,
+ void(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_METHOD3(insertSystemPrecompiledHeaders,
void(const ClangBackEnd::ProjectPartIds &projectPartIds,
Utils::SmallStringView pchPath,
@@ -45,7 +47,8 @@ public:
void(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_METHOD1(fetchSystemPrecompiledHeaderPath,
ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId));
- MOCK_CONST_METHOD1(
- fetchPrecompiledHeader,
- Utils::optional<ClangBackEnd::ProjectPartPch>(ClangBackEnd::ProjectPartId projectPartId));
+ MOCK_CONST_METHOD1(fetchPrecompiledHeader,
+ ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId));
+ MOCK_CONST_METHOD1(fetchPrecompiledHeaders,
+ ClangBackEnd::PchPaths(ClangBackEnd::ProjectPartId projectPartId));
};
diff --git a/tests/unit/unittest/mockprojectpartsmanager.h b/tests/unit/unittest/mockprojectpartsmanager.h
index b2cab59060..613faf7dfc 100644
--- a/tests/unit/unittest/mockprojectpartsmanager.h
+++ b/tests/unit/unittest/mockprojectpartsmanager.h
@@ -33,7 +33,7 @@ class MockProjectPartsManager : public ClangBackEnd::ProjectPartsManagerInterfac
{
public:
MOCK_METHOD1(update,
- ClangBackEnd::ProjectPartContainers(
+ ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts(
const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD1(remove, void(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_CONST_METHOD1(
@@ -42,7 +42,8 @@ public:
MOCK_METHOD1(updateDeferred, void(const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD0(deferredUpdates, ClangBackEnd::ProjectPartContainers());
- ClangBackEnd::ProjectPartContainers update(ClangBackEnd::ProjectPartContainers &&projectsParts) override
+ ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts update(
+ ClangBackEnd::ProjectPartContainers &&projectsParts) override
{
return update(projectsParts);
}
diff --git a/tests/unit/unittest/mockprojectpartsstorage.h b/tests/unit/unittest/mockprojectpartsstorage.h
index 114a7fab0e..e8dcbc94b2 100644
--- a/tests/unit/unittest/mockprojectpartsstorage.h
+++ b/tests/unit/unittest/mockprojectpartsstorage.h
@@ -56,5 +56,7 @@ public:
MOCK_CONST_METHOD1(fetchProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact>(
ClangBackEnd::ProjectPartId projectPartId));
+ MOCK_METHOD1(resetIndexingTimeStamps,
+ void(const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD0(transactionBackend, Sqlite::TransactionInterface &());
};
diff --git a/tests/unit/unittest/mocksqlitedatabase.h b/tests/unit/unittest/mocksqlitedatabase.h
index 5bef2ba8c5..05f6f4e958 100644
--- a/tests/unit/unittest/mocksqlitedatabase.h
+++ b/tests/unit/unittest/mocksqlitedatabase.h
@@ -31,12 +31,13 @@
#include "mocksqlitetransactionbackend.h"
#include "mocksqlitewritestatement.h"
+#include <sqlitedatabaseinterface.h>
#include <sqlitetable.h>
#include <sqlitetransaction.h>
#include <utils/smallstringview.h>
-class MockSqliteDatabase : public MockSqliteTransactionBackend
+class MockSqliteDatabase : public MockSqliteTransactionBackend, public Sqlite::DatabaseInterface
{
public:
using ReadStatement = NiceMock<MockSqliteReadStatement>;
@@ -56,5 +57,7 @@ public:
MOCK_METHOD1(setIsInitialized,
void (bool));
+
+ MOCK_METHOD0(walCheckpointFull, void());
};
diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp
index c12d40b9ea..b0df1ab75d 100644
--- a/tests/unit/unittest/mocksqlitereadstatement.cpp
+++ b/tests/unit/unittest/mocksqlitereadstatement.cpp
@@ -200,9 +200,15 @@ MockSqliteReadStatement::value<ClangBackEnd::ProjectPartPch, 3>(const int &proje
return valueReturnProjectPartPch(projectPartId);
}
-template <>
-Utils::optional<Utils::SmallString>
-MockSqliteReadStatement::value<Utils::SmallString>(const int &sourceId)
+template<>
+Utils::optional<ClangBackEnd::PchPaths> MockSqliteReadStatement::value<ClangBackEnd::PchPaths, 2>(
+ const int &projectPartId)
+{
+ return valueReturnPchPaths(projectPartId);
+}
+
+template<>
+Utils::optional<Utils::SmallString> MockSqliteReadStatement::value<Utils::SmallString>(const int &sourceId)
{
return valueReturnSmallString(sourceId);
}
@@ -222,6 +228,19 @@ SourceEntries MockSqliteReadStatement::values<SourceEntry, 4>(std::size_t reserv
return valuesReturnSourceEntries(reserveSize, filePathId, projectPartId);
}
+template<>
+SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize)
+{
+ return valuesReturnSourceTimeStamps(reserveSize);
+}
+
+template<>
+SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize,
+ const int &sourcePathId)
+{
+ return valuesReturnSourceTimeStamps(reserveSize, sourcePathId);
+}
+
template <>
Utils::optional<Sources::SourceNameAndDirectoryId>
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int &id)
diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h
index e3ab740b6e..d952c90dec 100644
--- a/tests/unit/unittest/mocksqlitereadstatement.h
+++ b/tests/unit/unittest/mocksqlitereadstatement.h
@@ -30,6 +30,7 @@
#include <sourcelocations.h>
#include <filepathstoragesources.h>
+#include <pchpaths.h>
#include <projectpartartefact.h>
#include <projectpartcontainer.h>
#include <projectpartpch.h>
@@ -50,6 +51,8 @@
using ClangBackEnd::FilePathIds;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry;
+using ClangBackEnd::SourceTimeStamp;
+using ClangBackEnd::SourceTimeStamps;
using ClangRefactoring::SourceLocation;
using ClangRefactoring::SourceLocations;
using std::int64_t;
@@ -118,11 +121,11 @@ public:
MOCK_METHOD1(valueReturnProjectPartContainer,
Utils::optional<ClangBackEnd::ProjectPartContainer>(int));
MOCK_METHOD1(valuesReturnProjectPartContainers, ClangBackEnd::ProjectPartContainers(std::size_t));
- MOCK_METHOD1(valueReturnProjectPartPch,
- Utils::optional<ClangBackEnd::ProjectPartPch>(int));
+ MOCK_METHOD1(valueReturnProjectPartPch, Utils::optional<ClangBackEnd::ProjectPartPch>(int));
- MOCK_METHOD3(valuesReturnSymbols,
- Symbols(std::size_t, int, Utils::SmallStringView));
+ MOCK_METHOD1(valueReturnPchPaths, Utils::optional<ClangBackEnd::PchPaths>(int));
+
+ MOCK_METHOD3(valuesReturnSymbols, Symbols(std::size_t, int, Utils::SmallStringView));
MOCK_METHOD4(valuesReturnSymbols,
Symbols(std::size_t, int, int, Utils::SmallStringView));
@@ -136,6 +139,9 @@ public:
MOCK_METHOD1(valueReturnProjectPartId,
Utils::optional<ClangBackEnd::ProjectPartId>(Utils::SmallStringView));
+ MOCK_METHOD1(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t));
+ MOCK_METHOD2(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t, int sourcePathId));
+
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryType>
@@ -263,6 +269,10 @@ Utils::optional<ClangBackEnd::ProjectPartContainer>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartContainer, 8>(const int &);
template<>
+Utils::optional<ClangBackEnd::PchPaths> MockSqliteReadStatement::value<ClangBackEnd::PchPaths, 2>(
+ const int &);
+
+template<>
ClangBackEnd::ProjectPartContainers MockSqliteReadStatement::values<ClangBackEnd::ProjectPartContainer,
8>(std::size_t reserveSize);
@@ -283,6 +293,13 @@ SourceEntries MockSqliteReadStatement::values<SourceEntry, 4>(std::size_t reserv
const int &,
const int &);
+template<>
+SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize);
+
+template<>
+SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t reserveSize,
+ const int &sourcePathId);
+
template <>
Utils::optional<Sources::SourceNameAndDirectoryId>
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int&);
diff --git a/tests/unit/unittest/mocksymbolstorage.h b/tests/unit/unittest/mocksymbolstorage.h
index a174389735..7b77868e8a 100644
--- a/tests/unit/unittest/mocksymbolstorage.h
+++ b/tests/unit/unittest/mocksymbolstorage.h
@@ -37,4 +37,11 @@ public:
MOCK_METHOD2(addSymbolsAndSourceLocations,
void(const ClangBackEnd::SymbolEntries &symbolEentries,
const ClangBackEnd::SourceLocationEntries &sourceLocations));
+ MOCK_METHOD2(insertOrUpdateIndexingTimeStamps,
+ void(const FilePathIds &filePathIds, ClangBackEnd::TimeStamp indexingTimeStamp));
+ MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &));
+ MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps());
+ MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps,
+ ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId));
+ MOCK_CONST_METHOD1(fetchDependentSourceIds, FilePathIds(const FilePathIds &sourcePathIds));
};
diff --git a/tests/unit/unittest/modifiedtimechecker-test.cpp b/tests/unit/unittest/modifiedtimechecker-test.cpp
index 8e0c881b38..ff0c3c66d8 100644
--- a/tests/unit/unittest/modifiedtimechecker-test.cpp
+++ b/tests/unit/unittest/modifiedtimechecker-test.cpp
@@ -57,7 +57,7 @@ protected:
ClangBackEnd::FilePathCaching filePathCache{database};
decltype(getModifiedTimeCallback.AsStdFunction()) callback = getModifiedTimeCallback
.AsStdFunction();
- ClangBackEnd::ModifiedTimeChecker checker{callback, filePathCache};
+ ClangBackEnd::ModifiedTimeChecker<> checker{callback, filePathCache};
SourceEntries upToDateEntries = {{id("/path1"), SourceType::UserInclude, 100},
{id("/path2"), SourceType::SystemInclude, 30}};
SourceEntries notUpToDateEntries = {{id("/path1"), SourceType::UserInclude, 50},
diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp
index b057795a3a..0cf84a983d 100644
--- a/tests/unit/unittest/pchcreator-test.cpp
+++ b/tests/unit/unittest/pchcreator-test.cpp
@@ -27,6 +27,7 @@
#include "fakeprocess.h"
#include "filesystem-utilities.h"
+#include "testenvironment.h"
#include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h"
@@ -79,7 +80,11 @@ MATCHER_P2(HasIdAndType,
class PchCreator: public ::testing::Test
{
protected:
- PchCreator() { creator.setUnsavedFiles({generatedFile}); }
+ PchCreator()
+ {
+ creator.setUnsavedFiles({generatedFile});
+ pchTask1.preIncludeSearchPath = testEnvironment.preIncludeSearchPath();
+ }
ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path)
{
@@ -121,6 +126,7 @@ protected:
{TESTDATA_DIR "/builddependencycollector/external", 1, IncludeSearchPathType::System}},
{{TESTDATA_DIR "/builddependencycollector/project", 1, IncludeSearchPathType::User}},
};
+ TestEnvironment testEnvironment;
};
using PchCreatorSlowTest = PchCreator;
using PchCreatorVerySlowTest = PchCreator;
@@ -148,6 +154,8 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath(TESTDATA_DIR "/builddependencycollector/project"),
"-isystem",
@@ -173,6 +181,8 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArgumentsWithSystemPch)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath(TESTDATA_DIR "/builddependencycollector/project"),
"-isystem",
@@ -193,8 +203,8 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchsSendToPchManagerClient)
EXPECT_CALL(mockPchManagerClient,
precompiledHeadersUpdated(
- Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartPchs,
- ElementsAre(Eq(creator.projectPartPch())))));
+ Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
+ ElementsAre(Eq(creator.projectPartPch().projectPartId)))));
creator.doInMainThreadAfterFinished();
}
@@ -239,6 +249,15 @@ TEST_F(PchCreatorVerySlowTest, PchCreationTimeStampsAreUpdated)
creator.doInMainThreadAfterFinished();
}
+TEST_F(PchCreator, DoNothingInTheMainThreadIfGenerateWasNotCalled)
+{
+ EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(_, _)).Times(0);
+ EXPECT_CALL(mockClangPathWatcher, updateIdPaths(_)).Times(0);
+ EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(_)).Times(0);
+
+ creator.doInMainThreadAfterFinished();
+}
+
TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForPchTask)
{
creator.generatePch(std::move(pchTask1));
@@ -296,6 +315,36 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask
Field(&ProjectPartPch::lastModified, Gt(0))));
}
+TEST_F(PchCreatorSlowTest, NoIncludes)
+{
+ pchTask1.includes = {};
+
+ creator.generatePch(std::move(pchTask1));
+
+ ASSERT_THAT(creator.projectPartPch(),
+ AllOf(Field(&ProjectPartPch::projectPartId, Eq(pchTask1.projectPartId())),
+ Field(&ProjectPartPch::pchPath, IsEmpty()),
+ Field(&ProjectPartPch::lastModified, Gt(0))));
+}
+
+TEST_F(PchCreatorSlowTest, NoIncludesInTheMainThreadCalls)
+{
+ pchTask1.includes = {};
+ creator.generatePch(std::move(pchTask1));
+
+ EXPECT_CALL(mockPchManagerClient,
+ precompiledHeadersUpdated(
+ Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
+ ElementsAre(Eq(creator.projectPartPch().projectPartId)))));
+ EXPECT_CALL(mockClangPathWatcher,
+ updateIdPaths(
+ ElementsAre(AllOf(Field(&ClangBackEnd::IdPaths::id, 1),
+ Field(&ClangBackEnd::IdPaths::filePathIds, IsEmpty())))));
+ EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(Gt(0), Eq(1)));
+
+ creator.doInMainThreadAfterFinished();
+}
+
TEST_F(PchCreatorVerySlowTest, GeneratedFile)
{
creator.clear();
diff --git a/tests/unit/unittest/pchmanagerclient-test.cpp b/tests/unit/unittest/pchmanagerclient-test.cpp
index 6c74143e4d..18a61d7038 100644
--- a/tests/unit/unittest/pchmanagerclient-test.cpp
+++ b/tests/unit/unittest/pchmanagerclient-test.cpp
@@ -65,11 +65,9 @@ protected:
filePathCache,
mockProjectPartsStorage};
ClangBackEnd::ProjectPartId projectPartId{1};
- ClangBackEnd::FilePath pchFilePath{"/path/to/pch"};
- PrecompiledHeadersUpdatedMessage message{{{projectPartId, pchFilePath.clone(), 1}}};
+ PrecompiledHeadersUpdatedMessage message{{projectPartId}};
ClangBackEnd::ProjectPartId projectPartId2{2};
- ClangBackEnd::FilePath pchFilePath2{"/path/to/pch2"};
- PrecompiledHeadersUpdatedMessage message2{{{projectPartId2, pchFilePath2.clone(), 1}}};
+ PrecompiledHeadersUpdatedMessage message2{{projectPartId2}};
};
TEST_F(PchManagerClient, NotifierAttached)
@@ -93,8 +91,7 @@ TEST_F(PchManagerClient, NotifierDetached)
TEST_F(PchManagerClient, Update)
{
- EXPECT_CALL(mockPchManagerNotifier,
- precompiledHeaderUpdated(projectPartId, pchFilePath.toQString(), Eq(1)));
+ EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderUpdated(projectPartId));
client.precompiledHeadersUpdated(message.clone());
}
@@ -106,58 +103,6 @@ TEST_F(PchManagerClient, Remove)
projectUpdater.removeProjectParts({projectPartId, projectPartId});
}
-TEST_F(PchManagerClient, GetNoProjectPartPchForWrongProjectPartId)
-{
- auto optional = client.projectPartPch(23);
-
- ASSERT_FALSE(optional);
-}
-
-TEST_F(PchManagerClient, GetProjectPartPchForProjectPartId)
-{
- client.precompiledHeadersUpdated(std::move(message));
-
- auto optional = client.projectPartPch(projectPartId);
-
- ASSERT_TRUE(optional);
-}
-
-TEST_F(PchManagerClient, ProjectPartPchRemoved)
-{
- client.precompiledHeadersUpdated(std::move(message));
-
- client.precompiledHeaderRemoved(projectPartId);
-
- ASSERT_FALSE(client.projectPartPch(projectPartId));
-}
-
-TEST_F(PchManagerClient, ProjectPartPchHasNoDublicateEntries)
-{
- client.precompiledHeadersUpdated(message.clone());
- client.precompiledHeadersUpdated(message2.clone());
-
- client.precompiledHeadersUpdated(message.clone());
-
- ASSERT_THAT(client.projectPartPchs(), SizeIs(2));
-}
-
-TEST_F(PchManagerClient, ProjectPartPchForProjectPartIdLastModified)
-{
- client.precompiledHeadersUpdated(std::move(message));
-
- ASSERT_THAT(client.projectPartPch(projectPartId)->lastModified, 1);
-}
-
-TEST_F(PchManagerClient, ProjectPartPchForProjectPartIdIsUpdated)
-{
- client.precompiledHeadersUpdated(message.clone());
- PrecompiledHeadersUpdatedMessage updateMessage{{{projectPartId, pchFilePath.clone(), 42}}};
-
- client.precompiledHeadersUpdated(updateMessage.clone());
-
- ASSERT_THAT(client.projectPartPch(projectPartId)->lastModified, 42);
-}
-
TEST_F(PchManagerClient, SetPchCreationProgress)
{
EXPECT_CALL(mockPchCreationProgressManager, setProgress(10, 20));
diff --git a/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp
index e55b71f860..194f52afd3 100644
--- a/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp
+++ b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp
@@ -148,7 +148,7 @@ TEST_F(PchManagerClientServerInProcess, SendRemoveGeneratedFilesMessage)
TEST_F(PchManagerClientServerInProcess, SendPrecompiledHeaderUpdatedMessage)
{
- PrecompiledHeadersUpdatedMessage message{{{1, "/path/to/pch", 1}}};
+ PrecompiledHeadersUpdatedMessage message{1};
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(message));
diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp
index 502b51bc8c..47b7d987ab 100644
--- a/tests/unit/unittest/pchmanagerserver-test.cpp
+++ b/tests/unit/unittest/pchmanagerserver-test.cpp
@@ -48,6 +48,7 @@ using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::FileContainers;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartContainers;
+using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
class PchManagerServer : public ::testing::Test
{
@@ -55,7 +56,8 @@ class PchManagerServer : public ::testing::Test
{
server.setClient(&mockPchManagerClient);
- ON_CALL(mockProjectPartsManager, update(projectParts)).WillByDefault(Return(projectParts));
+ ON_CALL(mockProjectPartsManager, update(projectParts))
+ .WillByDefault(Return(UpToDataProjectParts{{}, projectParts}));
ON_CALL(mockGeneratedFiles, isValid()).WillByDefault(Return(true));
}
@@ -107,7 +109,8 @@ protected:
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2};
- std::vector<ProjectPartContainer> projectParts2{projectPart2};
+ std::vector<ProjectPartContainer> projectParts1{projectPart1};
+ std::vector<ProjectPartContainer> projectParts2{projectPart2};
FileContainer generatedFile{{"/path/to/", "file"}, "content", {}};
ClangBackEnd::UpdateProjectPartsMessage updateProjectPartsMessage{
Utils::clone(projectParts), {"toolChainArgument"}};
@@ -120,7 +123,7 @@ TEST_F(PchManagerServer, FilterProjectPartsAndSendThemToQueue)
InSequence s;
EXPECT_CALL(mockProjectPartsManager, update(updateProjectPartsMessage.projectsParts))
- .WillOnce(Return(projectParts2));
+ .WillOnce(Return(UpToDataProjectParts{{}, projectParts2}));
EXPECT_CALL(
mockPchTaskGenerator, addProjectParts(Eq(projectParts2), ElementsAre("toolChainArgument")));
@@ -219,7 +222,7 @@ TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid)
InSequence s;
EXPECT_CALL(mockProjectPartsManager, update(ElementsAre(projectPart1)))
- .WillOnce(Return(ProjectPartContainers{projectPart1}));
+ .WillOnce(Return(UpToDataProjectParts{{}, ProjectPartContainers{projectPart1}}));
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(false));
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
EXPECT_CALL(mockProjectPartsManager, updateDeferred(ElementsAre(projectPart1)));
@@ -233,7 +236,7 @@ TEST_F(PchManagerServer, GeneratePchIfGeneratedFilesAreValid)
InSequence s;
EXPECT_CALL(mockProjectPartsManager, update(ElementsAre(projectPart1)))
- .WillOnce(Return(ProjectPartContainers{projectPart1}));
+ .WillOnce(Return(UpToDataProjectParts{{}, ProjectPartContainers{projectPart1}}));
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(true));
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _));
EXPECT_CALL(mockProjectPartsManager, updateDeferred(_)).Times(0);
@@ -276,4 +279,19 @@ TEST_F(PchManagerServer, AfterUpdatingGeneratedFilesAreStillInvalidSoNoPchsGener
server.updateGeneratedFiles(updateGeneratedFilesMessage.clone());
}
+TEST_F(PchManagerServer, SentUpToDateProjectPartIdsToClient)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockProjectPartsManager, update(updateProjectPartsMessage.projectsParts))
+ .WillOnce(Return(UpToDataProjectParts{projectParts1, projectParts2}));
+ EXPECT_CALL(mockPchTaskGenerator,
+ addProjectParts(Eq(projectParts2), ElementsAre("toolChainArgument")));
+ EXPECT_CALL(mockPchManagerClient,
+ precompiledHeadersUpdated(
+ Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
+ ElementsAre(Eq(projectPart1.projectPartId)))));
+
+ server.updateProjectParts(updateProjectPartsMessage.clone());
}
+} // namespace
diff --git a/tests/unit/unittest/pchtaskqueue-test.cpp b/tests/unit/unittest/pchtaskqueue-test.cpp
index 3e0bba1bc8..1754cea562 100644
--- a/tests/unit/unittest/pchtaskqueue-test.cpp
+++ b/tests/unit/unittest/pchtaskqueue-test.cpp
@@ -29,6 +29,7 @@
#include "mockprecompiledheaderstorage.h"
#include "mocksqlitetransactionbackend.h"
#include "mocktaskscheduler.h"
+#include "testenvironment.h"
#include <pchtaskqueue.h>
#include <progresscounter.h>
@@ -50,11 +51,13 @@ protected:
MockSqliteTransactionBackend mockSqliteTransactionBackend;
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
+ TestEnvironment testEnvironment;
ClangBackEnd::PchTaskQueue queue{mockSytemPchTaskScheduler,
mockProjectPchTaskScheduler,
progressCounter,
mockPrecompiledHeaderStorage,
- mockSqliteTransactionBackend};
+ mockSqliteTransactionBackend,
+ testEnvironment};
IncludeSearchPaths systemIncludeSearchPaths{
{"/includes", 1, IncludeSearchPathType::BuiltIn},
{"/other/includes", 2, IncludeSearchPathType::System}};
@@ -297,6 +300,7 @@ TEST_F(PchTaskQueue, CreateProjectTaskFromPchTask)
auto tasks = queue.createProjectTasks({projectTask1});
auto projectTask = projectTask1;
projectTask.systemPchPath = "/path/to/pch";
+ projectTask.preIncludeSearchPath = testEnvironment.preIncludeSearchPath();
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq(1)))
.WillOnce(Return(ClangBackEnd::FilePath{"/path/to/pch"}));
@@ -316,6 +320,7 @@ TEST_F(PchTaskQueue, DeleteProjectPchEntryInDatabaseIfNoPchIsGenerated)
auto tasks = queue.createProjectTasks({projectTask1});
auto projectTask = projectTask1;
projectTask.systemPchPath = "/path/to/pch";
+ projectTask.preIncludeSearchPath = testEnvironment.preIncludeSearchPath();
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq(1)))
.WillOnce(Return(ClangBackEnd::FilePath{"/path/to/pch"}));
@@ -339,8 +344,10 @@ TEST_F(PchTaskQueue, CreateSystemTaskFromPchTask)
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{{}, "/path/to/pch", 99};
auto tasks = queue.createSystemTasks({systemTask4});
+ auto systemTask = systemTask4;
+ systemTask.preIncludeSearchPath = testEnvironment.preIncludeSearchPath();
- EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask4)));
+ EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockPrecompiledHeaderStorage,
insertSystemPrecompiledHeaders(UnorderedElementsAre(1, 3), Eq("/path/to/pch"), 99));
@@ -354,12 +361,15 @@ TEST_F(PchTaskQueue, DeleteSystemPchEntryInDatabaseIfNoPchIsGenerated)
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{{}, "", 0};
auto tasks = queue.createSystemTasks({systemTask4});
+ auto systemTask = systemTask4;
+ systemTask.preIncludeSearchPath = testEnvironment.preIncludeSearchPath();
- EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask4)));
+ EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteSystemPrecompiledHeaders(UnorderedElementsAre(1, 3)));
tasks.front()(mockPchCreator);
}
+
} // namespace
diff --git a/tests/unit/unittest/precompiledheaderstorage-test.cpp b/tests/unit/unittest/precompiledheaderstorage-test.cpp
index 13fca71fdc..9fb161d0eb 100644
--- a/tests/unit/unittest/precompiledheaderstorage-test.cpp
+++ b/tests/unit/unittest/precompiledheaderstorage-test.cpp
@@ -47,7 +47,8 @@ protected:
MockSqliteWriteStatement &insertSystemPrecompiledHeaderStatement = storage.insertSystemPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteSystemPrecompiledHeaderStatement = storage.deleteSystemPrecompiledHeaderStatement;
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement;
- MockSqliteReadStatement &getPrecompiledHeader = storage.getPrecompiledHeader;
+ MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement;
+ MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement;
};
TEST_F(PrecompiledHeaderStorage, UseTransaction)
@@ -112,6 +113,31 @@ TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeaderStatementIsBusy)
storage.deleteProjectPrecompiledHeader(1);
}
+TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeaders)
+{
+ InSequence s;
+
+ EXPECT_CALL(database, immediateBegin());
+ EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<int>(1)));
+ EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<int>(2)));
+ EXPECT_CALL(database, commit());
+
+ storage.deleteProjectPrecompiledHeaders({1, 2});
+}
+
+TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeadersStatementIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
+ EXPECT_CALL(database, immediateBegin());
+ EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<int>(1)));
+ EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<int>(2)));
+ EXPECT_CALL(database, commit());
+
+ storage.deleteProjectPrecompiledHeaders({1, 2});
+}
+
TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeaders)
{
InSequence s;
@@ -225,18 +251,88 @@ TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsNullOptional
TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCallsValueInStatement)
{
- EXPECT_CALL(getPrecompiledHeader, valueReturnProjectPartPch(Eq(25)));
+ EXPECT_CALL(database, deferredBegin());
+ EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25)));
+ EXPECT_CALL(database, commit());
+
+ storage.fetchPrecompiledHeader(25);
+}
+
+TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(database, deferredBegin());
+ EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(database, rollback());
+ EXPECT_CALL(database, deferredBegin());
+ EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25)));
+ EXPECT_CALL(database, commit());
storage.fetchPrecompiledHeader(25);
}
TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeader)
{
- ClangBackEnd::ProjectPartPch pch{{}, "/path/to/pch", 131};
- EXPECT_CALL(getPrecompiledHeader, valueReturnProjectPartPch(Eq(25))).WillRepeatedly(Return(pch));
+ ClangBackEnd::FilePath pchFilePath{"/path/to/pch"};
+ ON_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25)))
+ .WillByDefault(Return(pchFilePath));
+
+ auto path = storage.fetchPrecompiledHeader(25);
+
+ ASSERT_THAT(path, Eq(pchFilePath));
+}
+
+TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeader)
+{
+ auto path = storage.fetchPrecompiledHeader(25);
+
+ ASSERT_THAT(path, IsEmpty());
+}
+
+TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCalls)
+{
+ EXPECT_CALL(database, deferredBegin());
+ EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25)));
+ EXPECT_CALL(database, commit());
+
+ storage.fetchPrecompiledHeaders(25);
+}
+
+TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeadersIsBusy)
+{
+ InSequence s;
- auto precompiledHeader = storage.fetchPrecompiledHeader(25);
+ EXPECT_CALL(database, deferredBegin());
+ EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(database, rollback());
+ EXPECT_CALL(database, deferredBegin());
+ EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25)));
+ EXPECT_CALL(database, commit());
- ASSERT_THAT(precompiledHeader.value(), Eq(pch));
+ storage.fetchPrecompiledHeaders(25);
}
+
+TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaders)
+{
+ ClangBackEnd::PchPaths pchFilePaths{"/project/pch", "/system/pch"};
+ ON_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25)))
+ .WillByDefault(Return(pchFilePaths));
+
+ auto paths = storage.fetchPrecompiledHeaders(25);
+
+ ASSERT_THAT(paths, Eq(pchFilePaths));
}
+
+TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeaders)
+{
+ auto paths = storage.fetchPrecompiledHeaders(25);
+
+ ASSERT_THAT(paths,
+ AllOf(Field(&ClangBackEnd::PchPaths::projectPchPath, IsEmpty()),
+ Field(&ClangBackEnd::PchPaths::systemPchPath, IsEmpty())));
+}
+
+} // namespace
diff --git a/tests/unit/unittest/projectpartsmanager-test.cpp b/tests/unit/unittest/projectpartsmanager-test.cpp
index b2b2fbc263..d86543e9c2 100644
--- a/tests/unit/unittest/projectpartsmanager-test.cpp
+++ b/tests/unit/unittest/projectpartsmanager-test.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "googletest.h"
+#include "mockprecompiledheaderstorage.h"
#include "mockprojectpartsstorage.h"
#include <projectpartsmanager.h>
@@ -35,12 +36,19 @@ namespace {
using ClangBackEnd::FilePathId;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartContainers;
+using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
class ProjectPartsManager : public testing::Test
{
protected:
+ ProjectPartsManager()
+ {
+ projectPartContainerWithoutPrecompiledHeader1.hasPrecompiledHeader = false;
+ }
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
- ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage};
+ NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage;
+
+ ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage, mockPrecompiledHeaderStorage};
FilePathId firstHeader{1};
FilePathId secondHeader{2};
FilePathId firstSource{11};
@@ -68,6 +76,27 @@ protected:
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
+ ProjectPartContainer nullProjectPartContainer1{1,
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ Utils::Language::C,
+ Utils::LanguageVersion::C89,
+ Utils::LanguageExtension::None};
+ ProjectPartContainer projectPartContainerWithoutPrecompiledHeader1{
+ 1,
+ {"-DUNIX", "-O2"},
+ {{"DEFINE", "1", 1}},
+ {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
+ {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
+ {firstHeader, secondHeader},
+ {firstSource, secondSource},
+ Utils::Language::C,
+ Utils::LanguageVersion::C11,
+ Utils::LanguageExtension::All};
ProjectPartContainer projectPartContainer2{
2,
{"-DUNIX", "-O2"},
@@ -83,16 +112,20 @@ protected:
TEST_F(ProjectPartsManager, GetNoProjectPartsForAddingEmptyProjectParts)
{
- auto updatedProjectParts = manager.update({});
+ auto projectParts = manager.update({});
- ASSERT_THAT(updatedProjectParts, IsEmpty());
+ ASSERT_THAT(projectParts,
+ AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
+ Field(&UpToDataProjectParts::notUpToDate, IsEmpty())));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPart)
{
- auto updatedProjectParts = manager.update({projectPartContainer1});
+ auto projectParts = manager.update({projectPartContainer1});
- ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1));
+ ASSERT_THAT(projectParts,
+ AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
+ Field(&UpToDataProjectParts::notUpToDate, ElementsAre(projectPartContainer1))));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithProjectPartAlreadyInTheDatabase)
@@ -100,9 +133,11 @@ TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithProjectPartAlr
ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
.WillByDefault(Return(ProjectPartContainers{projectPartContainer1}));
- auto updatedProjectParts = manager.update({projectPartContainer1, projectPartContainer2});
+ auto projectParts = manager.update({projectPartContainer1, projectPartContainer2});
- ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer2));
+ ASSERT_THAT(projectParts,
+ AllOf(Field(&UpToDataProjectParts::upToDate, ElementsAre(projectPartContainer1)),
+ Field(&UpToDataProjectParts::notUpToDate, ElementsAre(projectPartContainer2))));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithOlderProjectPartAlreadyInTheDatabase)
@@ -110,9 +145,12 @@ TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithOlderProjectPa
ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
.WillByDefault(Return(ProjectPartContainers{projectPartContainer1}));
- auto updatedProjectParts = manager.update({updatedProjectPartContainer1, projectPartContainer2});
+ auto projectParts = manager.update({updatedProjectPartContainer1, projectPartContainer2});
- ASSERT_THAT(updatedProjectParts, ElementsAre(updatedProjectPartContainer1, projectPartContainer2));
+ ASSERT_THAT(projectParts,
+ AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
+ Field(&UpToDataProjectParts::notUpToDate,
+ ElementsAre(updatedProjectPartContainer1, projectPartContainer2))));
}
TEST_F(ProjectPartsManager, ProjectPartAdded)
@@ -156,9 +194,11 @@ TEST_F(ProjectPartsManager, DoNotUpdateNotNewProjectPart)
{
manager.update({projectPartContainer1});
- auto updatedProjectParts = manager.update({projectPartContainer1});
+ auto projectParts = manager.update({projectPartContainer1});
- ASSERT_THAT(updatedProjectParts, IsEmpty());
+ ASSERT_THAT(projectParts,
+ AllOf(Field(&UpToDataProjectParts::upToDate, ElementsAre(projectPartContainer1)),
+ Field(&UpToDataProjectParts::notUpToDate, IsEmpty())));
}
TEST_F(ProjectPartsManager, NoDuplicateProjectPartAfterUpdatingWithNotNewProjectPart)
@@ -188,8 +228,8 @@ TEST_F(ProjectPartsManager, MergeProjectMultipleTimesParts)
TEST_F(ProjectPartsManager, GetNewProjectParts)
{
- auto newProjectParts = manager.filterNewProjectParts({projectPartContainer1, projectPartContainer2},
- {projectPartContainer2});
+ auto newProjectParts = manager.filterProjectParts({projectPartContainer1, projectPartContainer2},
+ {projectPartContainer2});
ASSERT_THAT(newProjectParts, ElementsAre(projectPartContainer1));
}
@@ -198,9 +238,12 @@ TEST_F(ProjectPartsManager, GetUpdatedProjectPart)
{
manager.update({projectPartContainer1, projectPartContainer2});
- auto updatedProjectParts = manager.update({updatedProjectPartContainer1});
+ auto projectParts = manager.update({updatedProjectPartContainer1});
- ASSERT_THAT(updatedProjectParts, ElementsAre(updatedProjectPartContainer1));
+ ASSERT_THAT(projectParts,
+ AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
+ Field(&UpToDataProjectParts::notUpToDate,
+ ElementsAre(updatedProjectPartContainer1))));
}
TEST_F(ProjectPartsManager, ProjectPartIsReplacedWithUpdatedProjectPart)
@@ -252,14 +295,14 @@ TEST_F(ProjectPartsManager, UpdateDeferred)
TEST_F(ProjectPartsManager, NotUpdateDeferred)
{
- auto projectPartContainers = manager.update({projectPartContainer1, projectPartContainer2});
+ manager.update({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(manager.deferredUpdates(), IsEmpty());
}
TEST_F(ProjectPartsManager, UpdateDeferredCleansDeferredUpdates)
{
- auto projectPartContainers = manager.update({projectPartContainer1, projectPartContainer2});
+ manager.update({projectPartContainer1, projectPartContainer2});
manager.updateDeferred({projectPartContainer1});
manager.deferredUpdates();
@@ -272,6 +315,9 @@ TEST_F(ProjectPartsManager, UpdateCallsIfNewProjectPartIsAdded)
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectParts(ElementsAre(Eq(projectPartContainer1.projectPartId))));
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1)));
+ EXPECT_CALL(mockPrecompiledHeaderStorage,
+ deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
+ EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)));
manager.update({projectPartContainer1});
}
@@ -296,12 +342,38 @@ TEST_F(ProjectPartsManager, UpdateCallsNotFetchProjectPartsInStorageIfNoNewerPro
manager.update({projectPartContainer1});
}
+TEST_F(ProjectPartsManager, UpdateCallsNotDeleteProjectPrecompiledHeadersIfNoNewerProjectPartsExists)
+{
+ manager.update({projectPartContainer1});
+
+ EXPECT_CALL(mockPrecompiledHeaderStorage,
+ deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)))
+ .Times(0);
+
+ manager.update({projectPartContainer1});
+}
+
+TEST_F(ProjectPartsManager, UpdateCallsNotResetIndexingTimeStampsIfNoNewerProjectPartsExists)
+{
+ manager.update({projectPartContainer1});
+
+ EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)))
+ .Times(0);
+
+ manager.update({projectPartContainer1});
+}
+
TEST_F(ProjectPartsManager, UpdateCallsIfOldProjectPartIsAdded)
{
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectParts(ElementsAre(Eq(projectPartContainer1.projectPartId))))
.WillRepeatedly(Return(ProjectPartContainers{projectPartContainer1}));
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1))).Times(0);
+ EXPECT_CALL(mockPrecompiledHeaderStorage,
+ deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)))
+ .Times(0);
+ EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)))
+ .Times(0);
manager.update({projectPartContainer1});
}
@@ -315,7 +387,35 @@ TEST_F(ProjectPartsManager, UpdateCallsIfUpdatedProjectPartIsAdded)
.WillRepeatedly(Return(ProjectPartContainers{projectPartContainer1}));
EXPECT_CALL(mockProjectPartsStorage,
updateProjectParts(ElementsAre(updatedProjectPartContainer1)));
+ EXPECT_CALL(mockPrecompiledHeaderStorage,
+ deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
+ EXPECT_CALL(mockProjectPartsStorage,
+ resetIndexingTimeStamps(ElementsAre(updatedProjectPartContainer1)));
manager.update({updatedProjectPartContainer1});
}
+
+TEST_F(ProjectPartsManager,
+ GetProjectPartForAddingProjectPartWithProjectPartAlreadyInTheDatabaseButNoPrecompiledHeader)
+{
+ ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
+ .WillByDefault(Return(ProjectPartContainers{projectPartContainerWithoutPrecompiledHeader1}));
+
+ auto projectParts = manager.update({projectPartContainer1});
+
+ ASSERT_THAT(projectParts,
+ AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
+ Field(&UpToDataProjectParts::notUpToDate, ElementsAre(projectPartContainer1))));
+}
+
+TEST_F(ProjectPartsManager, ProjectPartAddedWithProjectPartAlreadyInTheDatabaseButWithoutEntries)
+{
+ ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
+ .WillByDefault(Return(ProjectPartContainers{nullProjectPartContainer1}));
+
+ manager.update({projectPartContainer1});
+
+ ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1));
+}
+
} // namespace
diff --git a/tests/unit/unittest/projectpartsstorage-test.cpp b/tests/unit/unittest/projectpartsstorage-test.cpp
index ad78b0b833..3c13f33ad6 100644
--- a/tests/unit/unittest/projectpartsstorage-test.cpp
+++ b/tests/unit/unittest/projectpartsstorage-test.cpp
@@ -27,12 +27,13 @@
#include "mocksqlitedatabase.h"
+#include <builddependenciesstorage.h>
#include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
-
+#include <symbolstorage.h>
namespace {
using ClangBackEnd::FilePathId;
@@ -103,6 +104,8 @@ protected:
MockSqliteWriteStatement &insertProjectPartsSourcesStatement = storage.insertProjectPartsSourcesStatement;
MockSqliteReadStatement &fetchProjectPartsHeadersByIdStatement = storage.fetchProjectPartsHeadersByIdStatement;
MockSqliteReadStatement &fetchProjectPartsSourcesByIdStatement = storage.fetchProjectPartsSourcesByIdStatement;
+ MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderPathStatement;
+ MockSqliteWriteStatement &resetDependentIndexingTimeStampsStatement = storage.resetDependentIndexingTimeStampsStatement;
IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn},
{"/other/includes", 2, IncludeSearchPathType::System}};
IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User},
@@ -252,7 +255,13 @@ TEST_F(ProjectPartsStorage, FetchProjectPartsByIds)
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(1)));
+ EXPECT_CALL(fetchProjectPartsHeadersByIdStatement, valuesReturnFilePathIds(1024, Eq(1)));
+ EXPECT_CALL(fetchProjectPartsSourcesByIdStatement, valuesReturnFilePathIds(1024, Eq(1)));
+ EXPECT_CALL(fetchProjectPrecompiledHeaderPathStatement, valueReturnSmallString(Eq(1)));
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(2)));
+ EXPECT_CALL(fetchProjectPartsHeadersByIdStatement, valuesReturnFilePathIds(1024, Eq(2)));
+ EXPECT_CALL(fetchProjectPartsSourcesByIdStatement, valuesReturnFilePathIds(1024, Eq(2)));
+ EXPECT_CALL(fetchProjectPrecompiledHeaderPathStatement, valueReturnSmallString(Eq(2)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectParts({1, 2});
@@ -275,6 +284,36 @@ TEST_F(ProjectPartsStorage, FetchProjectPartsByIdsIsBusy)
storage.fetchProjectParts({1, 2});
}
+TEST_F(ProjectPartsStorage, FetchProjectPartsByIdsHasPrecompiledNullOptional)
+{
+ ON_CALL(fetchProjectPrecompiledHeaderPathStatement, valueReturnSmallString(Eq(1)))
+ .WillByDefault(Return(Utils::optional<Utils::SmallString>{}));
+
+ auto projectParts = storage.fetchProjectParts({1});
+
+ ASSERT_FALSE(projectParts.front().hasPrecompiledHeader);
+}
+
+TEST_F(ProjectPartsStorage, FetchProjectPartsByIdsHasPrecompiledEmptyString)
+{
+ ON_CALL(fetchProjectPrecompiledHeaderPathStatement, valueReturnSmallString(Eq(1)))
+ .WillByDefault(Return(Utils::optional<Utils::SmallString>{""}));
+
+ auto projectParts = storage.fetchProjectParts({1});
+
+ ASSERT_FALSE(projectParts.front().hasPrecompiledHeader);
+}
+
+TEST_F(ProjectPartsStorage, FetchProjectPartsByIdsHasPrecompiledStringWithContent)
+{
+ ON_CALL(fetchProjectPrecompiledHeaderPathStatement, valueReturnSmallString(Eq(1)))
+ .WillByDefault(Return(Utils::optional<Utils::SmallString>{"/some/path"}));
+
+ auto projectParts = storage.fetchProjectParts({1});
+
+ ASSERT_TRUE(projectParts.front().hasPrecompiledHeader);
+}
+
TEST_F(ProjectPartsStorage, FetchProjectPartsByIdsHasMissingId)
{
auto projectParts = storage.fetchProjectParts({1, 2, 3});
@@ -302,7 +341,7 @@ TEST_F(ProjectPartsStorage, UpdateProjectParts)
TypedEq<Utils::SmallStringView>(R"([["FOO","1",1]])"),
TypedEq<Utils::SmallStringView>(R"([["/include",1,3]])"),
TypedEq<Utils::SmallStringView>(R"([["/home/yi",2,1]])"),
- 1,
+ 2,
35,
2));
EXPECT_CALL(deleteProjectPartsHeadersByIdStatement, write(TypedEq<int>(1)));
@@ -317,8 +356,8 @@ TEST_F(ProjectPartsStorage, UpdateProjectParts)
TypedEq<Utils::SmallStringView>(R"([["BAR","2",1]])"),
TypedEq<Utils::SmallStringView>(R"([["/usr/include",1,3]])"),
TypedEq<Utils::SmallStringView>(R"([["/home/er",2,1]])"),
- 0,
- 2,
+ 1,
+ 3,
1));
EXPECT_CALL(deleteProjectPartsHeadersByIdStatement, write(TypedEq<int>(2)));
EXPECT_CALL(insertProjectPartsHeadersStatement, write(TypedEq<int>(2), TypedEq<int>(5)));
@@ -343,7 +382,7 @@ TEST_F(ProjectPartsStorage, UpdateProjectPartsIsBusy)
TypedEq<Utils::SmallStringView>(R"([["FOO","1",1]])"),
TypedEq<Utils::SmallStringView>(R"([["/include",1,3]])"),
TypedEq<Utils::SmallStringView>(R"([["/home/yi",2,1]])"),
- 1,
+ 2,
35,
2));
EXPECT_CALL(mockDatabase, commit());
@@ -387,6 +426,35 @@ TEST_F(ProjectPartsStorage, FetchProjectPartArtefactByProjectPartIdReturnArtefac
ASSERT_THAT(result, Eq(artefact));
}
+TEST_F(ProjectPartsStorage, ResetDependentIndexingTimeStamps)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, immediateBegin());
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(3)));
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(4)));
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(7)));
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(8)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.resetIndexingTimeStamps({projectPart1, projectPart2});
+}
+
+TEST_F(ProjectPartsStorage, ResetDependentIndexingTimeStampsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, immediateBegin());
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(3)));
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(4)));
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(7)));
+ EXPECT_CALL(resetDependentIndexingTimeStampsStatement, write(TypedEq<int>(8)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.resetIndexingTimeStamps({projectPart1, projectPart2});
+}
+
class ProjectPartsStorageSlow : public testing::Test, public Data
{
using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>;
@@ -395,6 +463,8 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
Storage storage{database};
+ ClangBackEnd::SymbolStorage<> symbolStorage{database};
+ ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
};
TEST_F(ProjectPartsStorageSlow, FetchProjectPartName)
@@ -432,4 +502,26 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
ASSERT_THAT(projectParts, ElementsAre(projectPart1, projectPart2));
}
+
+TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps)
+{
+ symbolStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34);
+ buildDependenciesStorage.insertOrUpdateSourceDependencies(
+ {{3, 1}, {4, 1}, {1, 2}, {7, 5}, {8, 6}, {6, 5}, {9, 10}});
+
+ storage.resetIndexingTimeStamps({projectPart1, projectPart2});
+
+ ASSERT_THAT(symbolStorage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 0},
+ SourceTimeStamp{2, 0},
+ SourceTimeStamp{3, 0},
+ SourceTimeStamp{4, 0},
+ SourceTimeStamp{5, 0},
+ SourceTimeStamp{6, 0},
+ SourceTimeStamp{7, 0},
+ SourceTimeStamp{8, 0},
+ SourceTimeStamp{9, 34},
+ SourceTimeStamp{10, 34}));
+}
+
} // namespace
diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp
index 028a6161c9..ea1c14dc35 100644
--- a/tests/unit/unittest/projectupdater-test.cpp
+++ b/tests/unit/unittest/projectupdater-test.cpp
@@ -46,9 +46,10 @@
#include <updategeneratedfilesmessage.h>
#include <updateprojectpartsmessage.h>
-#include <projectexplorer/projectexplorerconstants.h>
#include <cpptools/compileroptionsbuilder.h>
#include <cpptools/projectpart.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
@@ -85,6 +86,8 @@ protected:
void SetUp() override
{
+ project.rootProjectDirectoryPath = Utils::FilePath::fromString("project");
+ projectPart.project = &project;
projectPart.files.push_back(header1ProjectFile);
projectPart.files.push_back(header2ProjectFile);
projectPart.files.push_back(source1ProjectFile);
@@ -94,6 +97,7 @@ protected:
projectPart.projectMacros = {{"FOO", "2"}, {"BAR", "1"}};
projectPartId = projectPartsStorage.fetchProjectPartId(Utils::SmallString{projectPart.id()});
+ projectPart2.project = &project;
projectPart2.files.push_back(header2ProjectFile);
projectPart2.files.push_back(header1ProjectFile);
projectPart2.files.push_back(source2ProjectFile);
@@ -115,7 +119,8 @@ protected:
expectedContainer = {projectPartId,
arguments.clone(),
Utils::clone(compilerMacros),
- {{CLANG_RESOURCE_DIR, 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
+ {{"project/.pre_includes", 1, ClangBackEnd::IncludeSearchPathType::System},
+ {CLANG_RESOURCE_DIR, 2, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{},
{filePathId(headerPaths[1])},
{filePathIds(sourcePaths)},
@@ -125,7 +130,8 @@ protected:
expectedContainer2 = {projectPartId2,
arguments2.clone(),
Utils::clone(compilerMacros),
- {{CLANG_RESOURCE_DIR, 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
+ {{"project/.pre_includes", 1, ClangBackEnd::IncludeSearchPathType::System},
+ {CLANG_RESOURCE_DIR, 2, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{},
{filePathId(headerPaths[1])},
{filePathIds(sourcePaths)},
@@ -159,6 +165,7 @@ protected:
CppTools::ProjectFile cannotBuildSourceProjectFile{QString("/cannot/build"),
CppTools::ProjectFile::CXXSource};
CppTools::ProjectFile nonActiveProjectFile{QString("/foo"), CppTools::ProjectFile::CXXSource, false};
+ ProjectExplorer::Project project;
CppTools::ProjectPart projectPart;
CppTools::ProjectPart projectPart2;
CppTools::ProjectPart nonBuildingProjectPart;
@@ -269,6 +276,7 @@ TEST_F(ProjectUpdater, CallStorageInsideTransaction)
{
InSequence s;
CppTools::ProjectPart projectPart;
+ projectPart.project = &project;
projectPart.displayName = "project";
Utils::SmallString projectPartName = projectPart.id();
MockSqliteTransactionBackend mockSqliteTransactionBackend;
@@ -302,9 +310,18 @@ TEST_F(ProjectUpdater, CreateSortedCompilerMacros)
CompilerMacro{"DEFINE", "1", 3}));
}
+TEST_F(ProjectUpdater, FilterCompilerMacros)
+{
+ auto paths = updater.createCompilerMacros(
+ {{"DEFINE", "1"}, {"QT_TESTCASE_BUILDDIR", "2"}, {"BAR", "1"}});
+
+ ASSERT_THAT(paths, ElementsAre(CompilerMacro{"BAR", "1", 1}, CompilerMacro{"DEFINE", "1", 3}));
+}
+
TEST_F(ProjectUpdater, CreateSortedIncludeSearchPaths)
{
CppTools::ProjectPart projectPart;
+ projectPart.project = &project;
ProjectExplorer::HeaderPath includePath{"/to/path1", ProjectExplorer::HeaderPathType::User};
ProjectExplorer::HeaderPath includePath2{"/to/path2", ProjectExplorer::HeaderPathType::User};
ProjectExplorer::HeaderPath invalidPath;
@@ -317,13 +334,15 @@ TEST_F(ProjectUpdater, CreateSortedIncludeSearchPaths)
auto paths = updater.createIncludeSearchPaths(projectPart);
- ASSERT_THAT(paths.system,
- ElementsAre(Eq(IncludeSearchPath{systemPath.path, 1, IncludeSearchPathType::System}),
- Eq(IncludeSearchPath{builtInPath.path, 4, IncludeSearchPathType::BuiltIn}),
- Eq(IncludeSearchPath{frameworkPath.path, 2, IncludeSearchPathType::Framework}),
- Eq(IncludeSearchPath{CLANG_RESOURCE_DIR,
- 3,
- ClangBackEnd::IncludeSearchPathType::BuiltIn})));
+ ASSERT_THAT(
+ paths.system,
+ ElementsAre(Eq(IncludeSearchPath{systemPath.path, 2, IncludeSearchPathType::System}),
+ Eq(IncludeSearchPath{builtInPath.path, 5, IncludeSearchPathType::BuiltIn}),
+ Eq(IncludeSearchPath{frameworkPath.path, 3, IncludeSearchPathType::Framework}),
+ Eq(IncludeSearchPath{"project/.pre_includes", 1, IncludeSearchPathType::System}),
+ Eq(IncludeSearchPath{CLANG_RESOURCE_DIR,
+ 4,
+ ClangBackEnd::IncludeSearchPathType::BuiltIn})));
ASSERT_THAT(paths.project,
ElementsAre(Eq(IncludeSearchPath{includePath.path, 2, IncludeSearchPathType::User}),
Eq(IncludeSearchPath{includePath2.path, 1, IncludeSearchPathType::User})));
@@ -339,7 +358,10 @@ TEST_F(ProjectUpdater, ToolChainArguments)
auto arguments = updater.toolChainArguments(&projectPart);
ASSERT_THAT(arguments,
- ElementsAre("-m32", "-fPIC", "--target=target", "extraflags", "-include", "config.h"));
+ ElementsAre(QString{"-m32"},
+ QString{"extraflags"},
+ QString{"-include"},
+ QString{"config.h"}));
}
TEST_F(ProjectUpdater, ToolChainArgumentsMSVC)
@@ -352,61 +374,61 @@ TEST_F(ProjectUpdater, ToolChainArgumentsMSVC)
auto arguments = updater.toolChainArguments(&projectPart);
ASSERT_THAT(arguments,
- ElementsAre("-m32",
- "--target=target",
- "extraflags",
- "-U__clang__",
- "-U__clang_major__",
- "-U__clang_minor__",
- "-U__clang_patchlevel__",
- "-U__clang_version__",
- "-U__cpp_aggregate_bases",
- "-U__cpp_aggregate_nsdmi",
- "-U__cpp_alias_templates",
- "-U__cpp_aligned_new",
- "-U__cpp_attributes",
- "-U__cpp_binary_literals",
- "-U__cpp_capture_star_this",
- "-U__cpp_constexpr",
- "-U__cpp_decltype",
- "-U__cpp_decltype_auto",
- "-U__cpp_deduction_guides",
- "-U__cpp_delegating_constructors",
- "-U__cpp_digit_separators",
- "-U__cpp_enumerator_attributes",
- "-U__cpp_exceptions",
- "-U__cpp_fold_expressions",
- "-U__cpp_generic_lambdas",
- "-U__cpp_guaranteed_copy_elision",
- "-U__cpp_hex_float",
- "-U__cpp_if_constexpr",
- "-U__cpp_inheriting_constructors",
- "-U__cpp_init_captures",
- "-U__cpp_initializer_lists",
- "-U__cpp_inline_variables",
- "-U__cpp_lambdas",
- "-U__cpp_namespace_attributes",
- "-U__cpp_nested_namespace_definitions",
- "-U__cpp_noexcept_function_type",
- "-U__cpp_nontype_template_args",
- "-U__cpp_nontype_template_parameter_auto",
- "-U__cpp_nsdmi",
- "-U__cpp_range_based_for",
- "-U__cpp_raw_strings",
- "-U__cpp_ref_qualifiers",
- "-U__cpp_return_type_deduction",
- "-U__cpp_rtti",
- "-U__cpp_rvalue_references",
- "-U__cpp_static_assert",
- "-U__cpp_structured_bindings",
- "-U__cpp_template_auto",
- "-U__cpp_threadsafe_static_init",
- "-U__cpp_unicode_characters",
- "-U__cpp_unicode_literals",
- "-U__cpp_user_defined_literals",
- "-U__cpp_variable_templates",
- "-U__cpp_variadic_templates",
- "-U__cpp_variadic_using"));
+ ElementsAre(QString{"-m32"},
+ QString{"extraflags"},
+ QString{"-U__clang__"},
+ QString{"-U__clang_major__"},
+ QString{"-U__clang_minor__"},
+ QString{"-U__clang_patchlevel__"},
+ QString{"-U__clang_version__"},
+ QString{"-U__cpp_aggregate_bases"},
+ QString{"-U__cpp_aggregate_nsdmi"},
+ QString{"-U__cpp_alias_templates"},
+ QString{"-U__cpp_aligned_new"},
+ QString{"-U__cpp_attributes"},
+ QString{"-U__cpp_binary_literals"},
+ QString{"-U__cpp_capture_star_this"},
+ QString{"-U__cpp_constexpr"},
+ QString{"-U__cpp_decltype"},
+ QString{"-U__cpp_decltype_auto"},
+ QString{"-U__cpp_deduction_guides"},
+ QString{"-U__cpp_delegating_constructors"},
+ QString{"-U__cpp_digit_separators"},
+ QString{"-U__cpp_enumerator_attributes"},
+ QString{"-U__cpp_exceptions"},
+ QString{"-U__cpp_fold_expressions"},
+ QString{"-U__cpp_generic_lambdas"},
+ QString{"-U__cpp_guaranteed_copy_elision"},
+ QString{"-U__cpp_hex_float"},
+ QString{"-U__cpp_if_constexpr"},
+ QString{"-U__cpp_impl_destroying_delete"},
+ QString{"-U__cpp_inheriting_constructors"},
+ QString{"-U__cpp_init_captures"},
+ QString{"-U__cpp_initializer_lists"},
+ QString{"-U__cpp_inline_variables"},
+ QString{"-U__cpp_lambdas"},
+ QString{"-U__cpp_namespace_attributes"},
+ QString{"-U__cpp_nested_namespace_definitions"},
+ QString{"-U__cpp_noexcept_function_type"},
+ QString{"-U__cpp_nontype_template_args"},
+ QString{"-U__cpp_nontype_template_parameter_auto"},
+ QString{"-U__cpp_nsdmi"},
+ QString{"-U__cpp_range_based_for"},
+ QString{"-U__cpp_raw_strings"},
+ QString{"-U__cpp_ref_qualifiers"},
+ QString{"-U__cpp_return_type_deduction"},
+ QString{"-U__cpp_rtti"},
+ QString{"-U__cpp_rvalue_references"},
+ QString{"-U__cpp_static_assert"},
+ QString{"-U__cpp_structured_bindings"},
+ QString{"-U__cpp_template_auto"},
+ QString{"-U__cpp_threadsafe_static_init"},
+ QString{"-U__cpp_unicode_characters"},
+ QString{"-U__cpp_unicode_literals"},
+ QString{"-U__cpp_user_defined_literals"},
+ QString{"-U__cpp_variable_templates"},
+ QString{"-U__cpp_variadic_templates"},
+ QString{"-U__cpp_variadic_using"}));
}
TEST_F(ProjectUpdater, FetchProjectPartName)
@@ -415,7 +437,7 @@ TEST_F(ProjectUpdater, FetchProjectPartName)
auto projectPartName = updater.fetchProjectPartName(1);
- ASSERT_THAT(projectPartName, Eq(" projectb"));
+ ASSERT_THAT(projectPartName, Eq(QString{" projectb"}));
}
// test for update many time and get the same id
diff --git a/tests/unit/unittest/refactoringclient-test.cpp b/tests/unit/unittest/refactoringclient-test.cpp
index 37b6e2a744..00a390dd14 100644
--- a/tests/unit/unittest/refactoringclient-test.cpp
+++ b/tests/unit/unittest/refactoringclient-test.cpp
@@ -38,6 +38,7 @@
#include <cpptools/compileroptionsbuilder.h>
#include <cpptools/projectpart.h>
+#include <projectexplorer/project.h>
#include <utils/smallstringvector.h>
@@ -63,7 +64,26 @@ using Utils::SmallStringVector;
class RefactoringClient : public ::testing::Test
{
- void SetUp();
+ void SetUp()
+ {
+ using Filter = ClangRefactoring::ClangQueryProjectsFindFilter;
+
+ client.setRefactoringEngine(&engine);
+
+ projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
+ projectPart->project = &project;
+ projectPart->files.push_back(projectFile);
+
+ commandLine = Filter::compilerArguments(projectPart.data(), projectFile.kind);
+
+ client.setSearchHandle(&mockSearchHandle);
+ client.setExpectedResultCount(1);
+
+ ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{1})))
+ .WillByDefault(Return(FilePath(PathString("/path/to/file"))));
+ ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{42})))
+ .WillByDefault(Return(clangBackEndFilePath));
+ }
protected:
NiceMock<MockFilePathCaching> mockFilePathCaching;
@@ -81,9 +101,10 @@ protected:
QTextDocument textDocument{fileContent};
QTextCursor cursor{&textDocument};
QString qStringFilePath{QStringLiteral("/home/user/file.cpp")};
- Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)};
+ Utils::FilePath filePath{Utils::FilePath::fromString(qStringFilePath)};
ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath};
SmallStringVector commandLine;
+ ProjectExplorer::Project project;
CppTools::ProjectPart::Ptr projectPart;
CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource};
SourceLocationsForRenamingMessage renameMessage{"symbol",
@@ -228,25 +249,4 @@ TEST_F(RefactoringClient, SetProgress)
client.progress({ClangBackEnd::ProgressType::Indexing, 10, 20});
}
-
-void RefactoringClient::SetUp()
-{
- using Filter = ClangRefactoring::ClangQueryProjectsFindFilter;
-
- client.setRefactoringEngine(&engine);
-
- projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
- projectPart->files.push_back(projectFile);
-
- commandLine = Filter::compilerArguments(projectPart.data(), projectFile.kind);
-
- client.setSearchHandle(&mockSearchHandle);
- client.setExpectedResultCount(1);
-
- ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{1})))
- .WillByDefault(Return(FilePath(PathString("/path/to/file"))));
- ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{42})))
- .WillByDefault(Return(clangBackEndFilePath));
-}
-
}
diff --git a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
index 4865e2ebff..7177060311 100644
--- a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
+++ b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
@@ -131,7 +131,7 @@ TEST_F(RefactoringDatabaseInitializer, AddFileStatusesTable)
mockDatabase,
execute(Eq(
"CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, "
- "lastModified INTEGER)")));
+ "lastModified INTEGER, indexingTimeStamp INTEGER)")));
initializer.createFileStatusesTable();
}
@@ -140,8 +140,19 @@ TEST_F(RefactoringDatabaseInitializer, AddSourceDependenciesTable)
{
InSequence s;
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, "
+ "dependencySourceId INTEGER)")));
+ EXPECT_CALL(
+ mockDatabase,
+ execute(
+ Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON "
+ "sourceDependencies(sourceId, dependencySourceId)")));
+ EXPECT_CALL(
+ mockDatabase,
+ execute(
+ Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_dependencySourceId_sourceId ON "
+ "sourceDependencies(dependencySourceId, sourceId)")));
initializer.createSourceDependenciesTable();
}
@@ -189,40 +200,88 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
EXPECT_CALL(mockDatabase, isInitialized()).WillOnce(Return(false));
EXPECT_CALL(mockDatabase, exclusiveBegin());
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT, symbolKind INTEGER, signature TEXT)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_symbolKind_symbolName ON symbols(symbolKind, symbolName)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER, locationKind INTEGER)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_locations_sourceId_line_column ON locations(sourceId, line, column)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_locationKind ON locations(sourceId, locationKind)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, directoryId INTEGER, sourceName TEXT)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_sources_directoryId_sourceName ON sources(directoryId, sourceName)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS directories(directoryId INTEGER PRIMARY KEY, directoryPath TEXT)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_directories_directoryPath ON directories(directoryPath)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr "
+ "TEXT, symbolName TEXT, symbolKind INTEGER, signature TEXT)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_symbolKind_symbolName ON "
+ "symbols(symbolKind, symbolName)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, "
+ "column INTEGER, sourceId INTEGER, locationKind INTEGER)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_locations_sourceId_line_column "
+ "ON locations(sourceId, line, column)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_locationKind ON "
+ "locations(sourceId, locationKind)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, "
+ "directoryId INTEGER, sourceName TEXT)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_sources_directoryId_sourceName "
+ "ON sources(directoryId, sourceName)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS directories(directoryId INTEGER PRIMARY "
+ "KEY, directoryPath TEXT)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_directories_directoryPath ON "
+ "directories(directoryPath)")));
EXPECT_CALL(mockDatabase,
execute(
Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY "
"KEY, projectPartName TEXT, toolChainArguments TEXT, compilerMacros "
"TEXT, systemIncludeSearchPaths TEXT, projectIncludeSearchPaths TEXT, "
"language INTEGER, languageVersion INTEGER, languageExtension INTEGER)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectParts_projectPartName ON projectParts(projectPartName)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectParts_projectPartName "
+ "ON projectParts(projectPartName)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsFiles(projectPartId INTEGER, "
"sourceId INTEGER, sourceType INTEGER, pchCreationTimeStamp INTEGER, "
"hasMissingIncludes INTEGER)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectPartsFiles_sourceId_projectPartId ON projectPartsFiles(sourceId, projectPartId)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_projectPartsFiles_projectPartId ON projectPartsFiles(projectPartId)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS usedMacros(usedMacroId INTEGER PRIMARY KEY, sourceId INTEGER, macroName TEXT)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_sourceId_macroName ON usedMacros(sourceId, macroName)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_macroName ON usedMacros(macroName)")));
+ EXPECT_CALL(
+ mockDatabase,
+ execute(
+ Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectPartsFiles_sourceId_projectPartId "
+ "ON projectPartsFiles(sourceId, projectPartId)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_projectPartsFiles_projectPartId ON "
+ "projectPartsFiles(projectPartId)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS usedMacros(usedMacroId INTEGER PRIMARY KEY, "
+ "sourceId INTEGER, macroName TEXT)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_sourceId_macroName ON "
+ "usedMacros(sourceId, macroName)")));
+ EXPECT_CALL(
+ mockDatabase,
+ execute(
+ Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_macroName ON usedMacros(macroName)")));
EXPECT_CALL(
mockDatabase,
execute(Eq(
"CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, "
- "lastModified INTEGER)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)")));
- EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, projectPchPath TEXT, projectPchBuildTime INTEGER, systemPchPath TEXT, systemPchBuildTime INTEGER)")));
+ "lastModified INTEGER, indexingTimeStamp INTEGER)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, "
+ "dependencySourceId INTEGER)")));
+ EXPECT_CALL(
+ mockDatabase,
+ execute(
+ Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON "
+ "sourceDependencies(sourceId, dependencySourceId)")));
+ EXPECT_CALL(
+ mockDatabase,
+ execute(
+ Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_dependencySourceId_sourceId ON "
+ "sourceDependencies(dependencySourceId, sourceId)")));
+ EXPECT_CALL(mockDatabase,
+ execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER "
+ "PRIMARY KEY, projectPchPath TEXT, projectPchBuildTime INTEGER, "
+ "systemPchPath TEXT, systemPchBuildTime INTEGER)")));
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsHeaders(projectPartId INTEGER, "
"sourceId INTEGER)")));
@@ -271,7 +330,7 @@ TEST_F(RefactoringDatabaseInitializer, DontCreateIfAlreadyInitialized)
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_usedMacros_macroName ON usedMacros(macroName)"))).Times(0);
EXPECT_CALL(mockDatabase,
execute(Eq("CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, "
- "size INTEGER, lastModified INTEGER, isInPrecompiledHeader INTEGER)")))
+ "size INTEGER, lastModified INTEGER, indexingTimeStamp INTEGER)")))
.Times(0);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)"))).Times(0);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)"))).Times(0);
diff --git a/tests/unit/unittest/refactoringengine-test.cpp b/tests/unit/unittest/refactoringengine-test.cpp
index 747c930090..3cf5961dd1 100644
--- a/tests/unit/unittest/refactoringengine-test.cpp
+++ b/tests/unit/unittest/refactoringengine-test.cpp
@@ -36,6 +36,7 @@
#include <cpptools/compileroptionsbuilder.h>
#include <cpptools/projectpart.h>
+#include <projectexplorer/project.h>
#include <utils/smallstringvector.h>
@@ -56,7 +57,17 @@ using Utils::SmallStringVector;
class RefactoringEngine : public ::testing::Test
{
protected:
- void SetUp();
+ void SetUp()
+ {
+ projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
+ projectPart->project = &project;
+ projectPart->files.push_back(projectFile);
+
+ CompilerOptionsBuilder optionsBuilder(*projectPart);
+ commandLine = Utils::SmallStringVector(
+ optionsBuilder.build(projectFile.kind, CppTools::UsePrecompiledHeaders::No));
+ commandLine.push_back(qStringFilePath);
+ }
protected:
NiceMock<MockFilePathCaching> mockFilePathCaching;
@@ -71,9 +82,10 @@ protected:
QTextDocument textDocument{fileContent};
QTextCursor cursor{&textDocument};
QString qStringFilePath{QStringLiteral("/home/user/file.cpp")};
- Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)};
+ Utils::FilePath filePath{Utils::FilePath::fromString(qStringFilePath)};
ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath};
SmallStringVector commandLine;
+ ProjectExplorer::Project project;
CppTools::ProjectPart::Ptr projectPart;
CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource};
};
@@ -143,17 +155,5 @@ TEST_F(RefactoringEngine, ServerIsUsableForUsableEngine)
ASSERT_TRUE(mockRefactoringServer.isAvailable());
}
-
-void RefactoringEngine::SetUp()
-{
- projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
- projectPart->files.push_back(projectFile);
-
- CompilerOptionsBuilder optionsBuilder(*projectPart);
- commandLine = Utils::SmallStringVector(
- optionsBuilder.build(projectFile.kind, CppTools::UsePrecompiledHeaders::No));
- commandLine.push_back(qStringFilePath);
-}
-
}
diff --git a/tests/unit/unittest/refactoringprojectupdater-test.cpp b/tests/unit/unittest/refactoringprojectupdater-test.cpp
index 028edc0f7f..6913d1a16f 100644
--- a/tests/unit/unittest/refactoringprojectupdater-test.cpp
+++ b/tests/unit/unittest/refactoringprojectupdater-test.cpp
@@ -41,6 +41,8 @@
#include <refactoringprojectupdater.h>
+#include <projectexplorer/project.h>
+
#include <memory>
namespace {
@@ -64,6 +66,7 @@ protected:
ProjectPart::Ptr createProjectPart(const char *name)
{
ProjectPart::Ptr projectPart{new ProjectPart};
+ projectPart->project = &project;
projectPart->displayName = QString::fromUtf8(name, std::strlen(name));
projectPartId = projectPart->id();
return projectPart;
@@ -80,6 +83,7 @@ protected:
ClangPchManager::PchManagerClient pchManagerClient{mockPchCreationProgressManager,
mockDependencyCreationProgressManager};
MockCppModelManager mockCppModelManager;
+ ProjectExplorer::Project project;
ClangRefactoring::RefactoringProjectUpdater updater{mockRefactoringServer,
pchManagerClient,
mockCppModelManager,
@@ -97,7 +101,7 @@ TEST_F(RefactoringProjectUpdater, DontUpdateProjectPartIfNoProjectPartExistsForI
EXPECT_CALL(mockCppModelManager, projectPartForId(Eq(QString("project1"))));
EXPECT_CALL(mockRefactoringServer, updateProjectParts(_)).Times(0);
- pchManagerClient.precompiledHeadersUpdated({{{3, "/path/to/pch", 12}}});
+ pchManagerClient.precompiledHeadersUpdated({3});
}
TEST_F(RefactoringProjectUpdater, UpdateProjectPart)
@@ -114,7 +118,7 @@ TEST_F(RefactoringProjectUpdater, UpdateProjectPart)
updateProjectParts(Field(&UpdateProjectPartsMessage::projectsParts,
ElementsAre(IsProjectPartContainer(3)))));
- pchManagerClient.precompiledHeadersUpdated({{{3, "/path/to/pch", 12}}});
+ pchManagerClient.precompiledHeadersUpdated({3});
}
TEST_F(RefactoringProjectUpdater, RemoveProjectPart)
diff --git a/tests/unit/unittest/skippedsourceranges-test.cpp b/tests/unit/unittest/skippedsourceranges-test.cpp
index 083f795ec9..fd95dc4779 100644
--- a/tests/unit/unittest/skippedsourceranges-test.cpp
+++ b/tests/unit/unittest/skippedsourceranges-test.cpp
@@ -24,7 +24,7 @@
****************************************************************************/
#include "googletest.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <cursor.h>
#include <clangdocument.h>
@@ -89,7 +89,7 @@ struct Data {
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{unsavedFiles};
Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/skippedsourceranges.cpp");
- Utf8StringVector compilationArguments{TestEnvironment::addPlatformArguments(
+ Utf8StringVector compilationArguments{UnitTest::addPlatformArguments(
{Utf8StringLiteral("-std=c++11"), {}, Utf8StringLiteral("-DBLAH")})};
Document document{filePath, compilationArguments, {}, documents};
TranslationUnit translationUnit{filePath,
diff --git a/tests/unit/unittest/sourcerange-test.cpp b/tests/unit/unittest/sourcerange-test.cpp
index c66b9854db..1b2b44a8f9 100644
--- a/tests/unit/unittest/sourcerange-test.cpp
+++ b/tests/unit/unittest/sourcerange-test.cpp
@@ -25,7 +25,7 @@
#include "googletest.h"
#include "rundocumentparse-utility.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <clangtranslationunit.h>
#include <diagnostic.h>
@@ -75,7 +75,7 @@ struct Data {
ClangBackEnd::Documents documents{unsavedFiles};
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/diagnostic_source_range.cpp")};
Document document{filePath,
- {TestEnvironment::addPlatformArguments({Utf8StringLiteral("-pedantic")})},
+ {UnitTest::addPlatformArguments({Utf8StringLiteral("-pedantic")})},
{},
documents};
UnitTest::RunDocumentParse _1{document};
diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp
index edfcb286ad..2db11dc5fb 100644
--- a/tests/unit/unittest/symbolindexer-test.cpp
+++ b/tests/unit/unittest/symbolindexer-test.cpp
@@ -28,11 +28,13 @@
#include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h"
#include "mockfilepathcaching.h"
+#include "mockmodifiedtimechecker.h"
#include "mockprecompiledheaderstorage.h"
#include "mockprojectpartsstorage.h"
#include "mocksqlitetransactionbackend.h"
#include "mocksymbolscollector.h"
#include "mocksymbolstorage.h"
+#include "testenvironment.h"
#include <filepathcaching.h>
#include <filestatuscache.h>
@@ -113,7 +115,12 @@ protected:
.WillByDefault(Return(artefact));
ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1));
ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true));
-
+ ON_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
+ .WillByDefault(Return(sourceFileIds));
+ ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0])))
+ .WillByDefault(Return(FilePathIds{sourceFileIds[0]}));
+ ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(main1PathId)))
+ .WillByDefault(Return(FilePathIds{main1PathId}));
mockCollector.setIsUsed(false);
generatedFiles.update(unsaved);
@@ -230,8 +237,12 @@ protected:
Utils::Language::Cxx,
Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None};
+ ClangBackEnd::SourceTimeStamps dependentSourceTimeStamps1{{1, 32}};
+ ClangBackEnd::SourceTimeStamps dependentSourceTimeStamps2{{2, 35}};
+ ClangBackEnd::FileStatuses fileStatuses1{{1, 0, 32}};
+ ClangBackEnd::FileStatuses fileStatuses2{{2, 0, 35}};
Utils::optional<ClangBackEnd::ProjectPartArtefact > nullArtefact;
- ClangBackEnd::ProjectPartPch projectPartPch{74, "/path/to/pch", 4};
+ ClangBackEnd::PchPaths pchPaths{"/project/pch", "/system/pch"};
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockSymbolStorage> mockSymbolStorage;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
@@ -243,6 +254,8 @@ protected:
Manager collectorManger{generatedFiles};
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
+ NiceMock<MockSourceTimeStampsModifiedTimeChecker> mockModifiedTimeChecker;
+ TestEnvironment testEnvironment;
ClangBackEnd::SymbolIndexer indexer{indexerQueue,
mockSymbolStorage,
mockBuildDependenciesStorage,
@@ -251,8 +264,11 @@ protected:
filePathCache,
fileStatusCache,
mockSqliteTransactionBackend,
- mockProjectPartsStorage};
- SymbolIndexerTaskQueue indexerQueue{indexerScheduler, progressCounter};
+ mockProjectPartsStorage,
+ mockModifiedTimeChecker,
+ testEnvironment};
+ NiceMock<MockSqliteDatabase> mockSqliteDatabase;
+ SymbolIndexerTaskQueue indexerQueue{indexerScheduler, progressCounter, mockSqliteDatabase};
Scheduler indexerScheduler{collectorManger,
indexerQueue,
progressCounter,
@@ -278,6 +294,8 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -294,8 +312,8 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInCollector)
{
- ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId)))
- .WillByDefault(Return(projectPartPch));
+ ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)))
+ .WillByDefault(Return(pchPaths));
EXPECT_CALL(mockCollector,
setFile(main1PathId,
@@ -310,6 +328,8 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInColl
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -323,7 +343,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInColl
"-Xclang",
"-include-pch",
"-Xclang",
- toNativePath("/path/to/pch"))));
+ toNativePath("/project/pch"))));
indexer.updateProjectParts({projectPart1});
}
@@ -346,6 +366,8 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithoutPrecompiledHeaderInC
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -384,7 +406,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEv
TEST_F(SymbolIndexer, UpdateProjectPartsCallscollectSymbolsInCollector)
{
- EXPECT_CALL(mockCollector, collectSymbols()).Times(2);;
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(2);
indexer.updateProjectParts({projectPart1, projectPart2});
}
@@ -421,9 +443,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder)
{
InSequence s;
- EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
- EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId)));
- EXPECT_CALL(mockSqliteTransactionBackend, commit());
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)));
EXPECT_CALL(mockCollector,
setFile(main1PathId,
ElementsAre("clang++",
@@ -437,6 +457,8 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder)
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -455,13 +477,258 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder)
indexer.updateProjectParts({projectPart1});
}
-TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingSymbols)
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasNoError)
{
InSequence s;
- EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
- EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId)));
- EXPECT_CALL(mockSqliteTransactionBackend, commit());
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectPch)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer,
+ UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectAndSystemPch)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasOnlyError)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(main1PathId,
ElementsAre("clang++",
@@ -475,6 +742,39 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -486,9 +786,153 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
- EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
- EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsSystemPchPathsAndHasErrorWithProjectPch)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{{}, "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsNoPchPathsAndHasErrors)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId)));
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps)
+{
+ InSequence s;
+ ProjectPartContainer projectPart{1,
+ {"-Wno-pragma-once-outside-header"},
+ {{"BAR", "1", 1}, {"FOO", "1", 2}},
+ Utils::clone(systemIncludeSearchPaths),
+ Utils::clone(projectIncludeSearchPaths),
+ {header1PathId},
+ {main1PathId, main2PathId},
+ Utils::Language::Cxx,
+ Utils::LanguageVersion::CXX14,
+ Utils::LanguageExtension::None};
+
+ EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId)))
+ .WillOnce(Return(dependentSourceTimeStamps1));
+ EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1));
+ EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId)))
+ .WillOnce(Return(dependentSourceTimeStamps2));
+ EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps2));
+ EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1));
+ EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
+ EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses2));
+ EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
+
+ indexer.updateProjectParts({projectPart});
+}
+
+TEST_F(SymbolIndexer, DependentSourceAreNotUpToDate)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillOnce(Return(false));
+ EXPECT_CALL(mockCollector, setFile(main1PathId, _));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer, DependentSourceAreUpToDate)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillOnce(Return(true));
+ EXPECT_CALL(mockCollector, setFile(main1PathId, _)).Times(0);
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+
+ indexer.updateProjectParts({projectPart1});
+}
+
+TEST_F(SymbolIndexer, SourcesAreWatched)
+{
+ using ClangBackEnd::IdPaths;
+ InSequence s;
+ FilePathIds sourcePathIds{4, 6, 8};
+
+ EXPECT_CALL(mockBuildDependenciesStorage, fetchSources(projectPart1.projectPartId))
+ .WillOnce(Return(sourcePathIds));
+ EXPECT_CALL(mockPathWatcher,
+ updateIdPaths(ElementsAre(AllOf(Field(&IdPaths::id, projectPart1.projectPartId),
+ Field(&IdPaths::filePathIds, sourcePathIds)))));
indexer.updateProjectParts({projectPart1});
}
@@ -505,7 +949,9 @@ TEST_F(SymbolIndexer, CallSetNotifier)
filePathCache,
fileStatusCache,
mockSqliteTransactionBackend,
- mockProjectPartsStorage};
+ mockProjectPartsStorage,
+ mockModifiedTimeChecker,
+ testEnvironment};
}
TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
@@ -516,6 +962,54 @@ TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
indexer.pathsChanged(sourceFileIds);
}
+TEST_F(SymbolIndexer, PathChangedCallsFetchSourcePathIds)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
+ .WillOnce(Return(FilePathIds{2, 6, 5}));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{2}));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{6}));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{5}));
+
+ indexer.pathsChanged(sourceFileIds);
+}
+
+TEST_F(SymbolIndexer, PathChangedFetchIncludedIndexingTimeStamps)
+{
+ InSequence s;
+ ProjectPartContainer projectPart{1,
+ {"-Wno-pragma-once-outside-header"},
+ {{"BAR", "1", 1}, {"FOO", "1", 2}},
+ Utils::clone(systemIncludeSearchPaths),
+ Utils::clone(projectIncludeSearchPaths),
+ {header1PathId},
+ {main1PathId, main2PathId},
+ Utils::Language::Cxx,
+ Utils::LanguageVersion::CXX14,
+ Utils::LanguageExtension::None};
+
+ EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillOnce(Return(FilePathIds{1, 2}));
+ EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(1)))
+ .WillOnce(Return(dependentSourceTimeStamps1));
+ EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(2)))
+ .WillOnce(Return(dependentSourceTimeStamps2));
+ EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses1));
+ EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
+ EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses2));
+ EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
+
+ indexer.pathsChanged({1, 3});
+}
+
+TEST_F(SymbolIndexer, PathChangedFetchesDependentSourceIdsFromStorage)
+{
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]));
+ EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1]));
+
+ indexer.pathsChanged(sourceFileIds);
+}
+
TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
{
InSequence s;
@@ -524,8 +1018,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
- EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId)));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)));
EXPECT_CALL(mockCollector,
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
@@ -539,6 +1033,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -564,8 +1060,8 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]))
.WillOnce(Return(nullArtefact));
- EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(_)).Times(0);
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(_)).Times(0);
EXPECT_CALL(mockCollector, setFile(_, _)).Times(0);
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
@@ -575,18 +1071,271 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
indexer.pathsChanged({sourceFileIds[0]});
}
-TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSymbols)
+TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasNoError)
{
InSequence s;
- EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
- EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId)));
- EXPECT_CALL(mockSqliteTransactionBackend, commit());
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
- setFile(Eq(sourceFileIds[0]),
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+
+ indexer.pathsChanged({sourceFileIds[0]});
+}
+
+TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectPch)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockProjectPartsStorage,
+ fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
+ .WillOnce(Return(artefact));
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+
+ indexer.pathsChanged({sourceFileIds[0]});
+}
+
+TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectAndSystemPch)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockProjectPartsStorage,
+ fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
+ .WillOnce(Return(artefact));
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+
+ indexer.pathsChanged({sourceFileIds[0]});
+}
+
+TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasOnlyError)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockProjectPartsStorage,
+ fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
+ .WillOnce(Return(artefact));
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/project/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
@@ -598,6 +1347,39 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSy
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -609,9 +1391,92 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSy
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
- EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
- EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
+
+ indexer.pathsChanged({sourceFileIds[0]});
+}
+
+TEST_F(SymbolIndexer, PathsChangedCallsGetsSystemPchPathsAndHasErrorWithProjectPch)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockProjectPartsStorage,
+ fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
+ .WillOnce(Return(artefact));
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
+ .WillOnce(Return(ClangBackEnd::PchPaths{{}, "/system/pch"}));
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"),
+ "-Xclang",
+ "-include-pch",
+ "-Xclang",
+ toNativePath("/system/pch"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
+
+ indexer.pathsChanged({sourceFileIds[0]});
+}
+
+TEST_F(SymbolIndexer, PathsChangedCallsGetsNoPchPathsAndHasErrors)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockProjectPartsStorage,
+ fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
+ .WillOnce(Return(artefact));
+ EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)));
+ EXPECT_CALL(mockCollector,
+ setFile(sourceFileIds[0],
+ ElementsAre("clang++",
+ "-w",
+ "-DFOO",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"))));
+ EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
+ EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+ EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
@@ -620,8 +1485,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
{
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillByDefault(Return(artefact));
- ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId)))
- .WillByDefault(Return(projectPartPch));
+ ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
+ .WillByDefault(Return(pchPaths));
std::vector<SymbolIndexerTask> symbolIndexerTask;
EXPECT_CALL(mockCollector,
@@ -637,6 +1502,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -650,7 +1517,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
"-Xclang",
"-include-pch",
"-Xclang",
- toNativePath("/path/to/pch"))));
+ toNativePath("/project/pch"))));
indexer.pathsChanged({sourceFileIds[0]});
}
@@ -674,6 +1541,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
@@ -797,6 +1666,7 @@ TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache)
auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp");
auto oldLastModified = fileStatusCache.lastModifiedTime(sourceId);
touchFile(sourceId);
+ ON_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillByDefault(Return(FilePathIds{sourceId}));
indexer.pathsChanged({sourceId});
@@ -889,4 +1759,68 @@ TEST_F(SymbolIndexer, DISABLED_UpToDateFilesAreNotParsedInUpdateProjectParts)
indexer.updateProjectParts({projectPart1});
}
+TEST_F(SymbolIndexer, MultipleSourceFiles)
+{
+ ProjectPartContainer projectPart{0,
+ {},
+ {{"BAR", "1", 1}, {"FOO", "1", 2}},
+ Utils::clone(systemIncludeSearchPaths),
+ Utils::clone(projectIncludeSearchPaths),
+ {header1PathId, header2PathId},
+ {main1PathId, main2PathId},
+ Utils::Language::Cxx,
+ Utils::LanguageVersion::CXX14,
+ Utils::LanguageExtension::None};
+
+ EXPECT_CALL(mockCollector,
+ setFile(main1PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"))));
+ EXPECT_CALL(mockCollector,
+ setFile(main2PathId,
+ ElementsAre("clang++",
+ "-w",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++14",
+ "-nostdinc",
+ "-nostdinc++",
+ "-DBAR=1",
+ "-DFOO=1",
+ "-isystem",
+ toNativePath(TESTDATA_DIR "/preincludes"),
+ "-I",
+ toNativePath("/project/includes"),
+ "-I",
+ toNativePath("/other/project/includes"),
+ "-isystem",
+ toNativePath(TESTDATA_DIR),
+ "-isystem",
+ toNativePath("/other/includes"),
+ "-isystem",
+ toNativePath("/includes"))));
+
+ indexer.updateProjectParts({projectPart});
}
+} // namespace
diff --git a/tests/unit/unittest/symbolindexertaskqueue-test.cpp b/tests/unit/unittest/symbolindexertaskqueue-test.cpp
index 2932310eb0..1364091161 100644
--- a/tests/unit/unittest/symbolindexertaskqueue-test.cpp
+++ b/tests/unit/unittest/symbolindexertaskqueue-test.cpp
@@ -25,6 +25,7 @@
#include "googletest.h"
+#include "mocksqlitedatabase.h"
#include "mocktaskscheduler.h"
#include <symbolindexertaskqueue.h>
@@ -54,7 +55,8 @@ protected:
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
NiceMock<MockTaskScheduler<Callable>> mockTaskScheduler;
- ClangBackEnd::SymbolIndexerTaskQueue queue{mockTaskScheduler, progressCounter};
+ NiceMock<MockSqliteDatabase> mockSqliteDatabase;
+ ClangBackEnd::SymbolIndexerTaskQueue queue{mockTaskScheduler, progressCounter, mockSqliteDatabase};
};
TEST_F(SymbolIndexerTaskQueue, AddTasks)
@@ -208,4 +210,35 @@ TEST_F(SymbolIndexerTaskQueue, ProcessTasksRemovesProcessedTasks)
ASSERT_THAT(queue.tasks(), SizeIs(1));
}
+
+TEST_F(SymbolIndexerTaskQueue,
+ ProcessTasksWritesBackTheDatabaseLogIfTheQueueIsEmptyAndTheIndexerHasNothingToDo)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
+ EXPECT_CALL(mockSqliteDatabase, walCheckpointFull());
+
+ queue.processEntries();
+}
+
+TEST_F(SymbolIndexerTaskQueue, ProcessTasksDoesNotWritesBackTheDatabaseLogIfTheIndexerHasSomethingToDo)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{1, 1}));
+ EXPECT_CALL(mockSqliteDatabase, walCheckpointFull()).Times(0);
+
+ queue.processEntries();
+}
+
+TEST_F(SymbolIndexerTaskQueue, HandleExeptionInWalCheckPoint)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
+ EXPECT_CALL(mockSqliteDatabase, walCheckpointFull()).WillOnce(Throw(Sqlite::DatabaseIsBusy{""}));
+
+ queue.processEntries();
}
+} // namespace
diff --git a/tests/unit/unittest/symbolindexing-test.cpp b/tests/unit/unittest/symbolindexing-test.cpp
index 6e094951f3..67411efd37 100644
--- a/tests/unit/unittest/symbolindexing-test.cpp
+++ b/tests/unit/unittest/symbolindexing-test.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "googletest.h"
+#include "testenvironment.h"
#include <symbolindexing.h>
#include <symbolquery.h>
@@ -85,7 +86,12 @@ protected:
ClangBackEnd::GeneratedFiles generatedFiles;
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProjectPartsStorage<Sqlite::Database> projectPartStorage{database};
- ClangBackEnd::SymbolIndexing indexing{database, filePathCache, generatedFiles, mockSetProgressCallback.AsStdFunction()};
+ TestEnvironment testEnvironment;
+ ClangBackEnd::SymbolIndexing indexing{database,
+ filePathCache,
+ generatedFiles,
+ mockSetProgressCallback.AsStdFunction(),
+ testEnvironment};
StatementFactory queryFactory{database};
Query query{queryFactory};
PathString main1Path = TESTDATA_DIR "/symbolindexing_main1.cpp";
diff --git a/tests/unit/unittest/symbolscollector-test.cpp b/tests/unit/unittest/symbolscollector-test.cpp
index 48e4420dc1..f0080a5d2c 100644
--- a/tests/unit/unittest/symbolscollector-test.cpp
+++ b/tests/unit/unittest/symbolscollector-test.cpp
@@ -271,56 +271,6 @@ TEST_F(SymbolsCollector, DISABLED_ON_WINDOWS(CollectInUnsavedFile))
Contains(HasSymbolName("function")));
}
-TEST_F(SymbolsCollector, SourceFiles)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
-
- collector.collectSymbols();
-
- ASSERT_THAT(collector.sourceFiles(),
- UnorderedElementsAre(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"),
- filePathId(TESTDATA_DIR "/symbolscollector/header1.h"),
- filePathId(TESTDATA_DIR "/symbolscollector/header2.h")));
-}
-
-TEST_F(SymbolsCollector, MainFileInSourceFiles)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
-
- ASSERT_THAT(collector.sourceFiles(),
- ElementsAre(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp")));
-}
-
-TEST_F(SymbolsCollector, ResetMainFileInSourceFiles)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
-
- ASSERT_THAT(collector.sourceFiles(),
- ElementsAre(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp")));
-}
-
-TEST_F(SymbolsCollector, DontDuplicateSourceFiles)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
- collector.collectSymbols();
-
- collector.collectSymbols();
-
- ASSERT_THAT(collector.sourceFiles(),
- UnorderedElementsAre(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"),
- filePathId(TESTDATA_DIR "/symbolscollector/header1.h"),
- filePathId(TESTDATA_DIR "/symbolscollector/header2.h")));
-}
-
-TEST_F(SymbolsCollector, ClearSourceFiles)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
-
- collector.clear();
-
- ASSERT_THAT(collector.sourceFiles(), IsEmpty());
-}
-
TEST_F(SymbolsCollector, ClearSymbols)
{
collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
@@ -351,27 +301,6 @@ TEST_F(SymbolsCollector, ClearFileStatus)
ASSERT_THAT(collector.fileStatuses(), IsEmpty());
}
-TEST_F(SymbolsCollector, ClearUsedMacros)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/defines.h"), {"cc"});
- collector.collectSymbols();
-
- collector.clear();
-
- ASSERT_THAT(collector.usedMacros(), IsEmpty());
-}
-
-TEST_F(SymbolsCollector, ClearSourceDependencies)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main2.cpp"),
- {"cc", "-I" TESTDATA_DIR});
- collector.collectSymbols();
-
- collector.clear();
-
- ASSERT_THAT(collector.sourceDependencies(), IsEmpty());
-}
-
TEST_F(SymbolsCollector, DontCollectSymbolsAfterFilesAreCleared)
{
collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
@@ -382,16 +311,6 @@ TEST_F(SymbolsCollector, DontCollectSymbolsAfterFilesAreCleared)
ASSERT_THAT(collector.symbols(), IsEmpty());
}
-TEST_F(SymbolsCollector, DontCollectSourceFilesAfterFilesAreCleared)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
-
- collector.clear();
- collector.collectSymbols();
-
- ASSERT_THAT(collector.sourceFiles(), IsEmpty());
-}
-
TEST_F(SymbolsCollector, DontCollectFileStatusAfterFilesAreCleared)
{
collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
@@ -402,82 +321,6 @@ TEST_F(SymbolsCollector, DontCollectFileStatusAfterFilesAreCleared)
ASSERT_THAT(collector.fileStatuses(), IsEmpty());
}
-TEST_F(SymbolsCollector, DontCollectUsedMacrosAfterFilesAreCleared)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
-
- collector.clear();
- collector.collectSymbols();
-
- ASSERT_THAT(collector.usedMacros(), IsEmpty());
-}
-
-TEST_F(SymbolsCollector, DontCollectSourceDependenciesAfterFilesAreCleared)
-{
- collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/main.cpp"), {"cc"});
-
- collector.clear();
- collector.collectSymbols();
-
- ASSERT_THAT(collector.sourceDependencies(), IsEmpty());
-}
-
-TEST_F(SymbolsCollector, CollectUsedMacrosWithExternalDefine)
-{
- auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
- collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
-
- collector.collectSymbols();
-
- ASSERT_THAT(collector.usedMacros(),
- ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
- Eq(UsedMacro{"IF_DEFINE", fileId}),
- Eq(UsedMacro{"__clang__", fileId}),
- Eq(UsedMacro{"CLASS_EXPORT", fileId}),
- Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
- Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
- Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
-}
-
-TEST_F(SymbolsCollector, CollectUsedMacrosWithoutExternalDefine)
-{
- auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
- collector.setFile(fileId, {"cc"});
-
- collector.collectSymbols();
-
- ASSERT_THAT(collector.usedMacros(),
- ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
- Eq(UsedMacro{"IF_DEFINE", fileId}),
- Eq(UsedMacro{"__clang__", fileId}),
- Eq(UsedMacro{"CLASS_EXPORT", fileId}),
- Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
- Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
- Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
-}
-
-TEST_F(SymbolsCollector, DontCollectHeaderGuards)
-{
- auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
- collector.setFile(fileId, {"cc"});
-
- collector.collectSymbols();
-
- ASSERT_THAT(collector.usedMacros(),
- Not(Contains(Eq(UsedMacro{"SYMBOLSCOLLECTOR_DEFINES_H", fileId}))));
-}
-
-TEST_F(SymbolsCollector, DISABLED_DontCollectDynamicLibraryExports)
-{
- auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
- collector.setFile(fileId, {"cc"});
-
- collector.collectSymbols();
-
- ASSERT_THAT(collector.usedMacros(),
- Not(Contains(Eq(UsedMacro{"CLASS_EXPORT", fileId}))));
-}
-
TEST_F(SymbolsCollector, CollectMacroDefinitionSourceLocation)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
@@ -489,7 +332,7 @@ TEST_F(SymbolsCollector, CollectMacroDefinitionSourceLocation)
Contains(IsSourceLocationEntry(symbolId("IF_NOT_DEFINE"), fileId, 4, 9, SourceLocationKind::MacroDefinition)));
}
-TEST_F(SymbolsCollector, CollectMacroUsageInIfNotDefSourceLocation)
+TEST_F(SymbolsCollector, DISABLED_CollectMacroUsageInIfNotDefSourceLocation)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
@@ -500,7 +343,7 @@ TEST_F(SymbolsCollector, CollectMacroUsageInIfNotDefSourceLocation)
Contains(IsSourceLocationEntry(symbolId("IF_NOT_DEFINE"), fileId, 6, 9, SourceLocationKind::MacroUsage)));
}
-TEST_F(SymbolsCollector, CollectSecondMacroUsageInIfNotDefSourceLocation)
+TEST_F(SymbolsCollector, DISABLED_CollectSecondMacroUsageInIfNotDefSourceLocation)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
@@ -511,7 +354,7 @@ TEST_F(SymbolsCollector, CollectSecondMacroUsageInIfNotDefSourceLocation)
Contains(IsSourceLocationEntry(symbolId("IF_NOT_DEFINE"), fileId, 9, 9, SourceLocationKind::MacroUsage)));
}
-TEST_F(SymbolsCollector, CollectMacroUsageCompilerArgumentSourceLocation)
+TEST_F(SymbolsCollector, DISABLED_CollectMacroUsageCompilerArgumentSourceLocation)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
@@ -522,7 +365,7 @@ TEST_F(SymbolsCollector, CollectMacroUsageCompilerArgumentSourceLocation)
Contains(IsSourceLocationEntry(symbolId("COMPILER_ARGUMENT"), fileId, 12, 9, SourceLocationKind::MacroUsage)));
}
-TEST_F(SymbolsCollector, CollectMacroUsageInIfDefSourceLocation)
+TEST_F(SymbolsCollector, DISABLED_CollectMacroUsageInIfDefSourceLocation)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
@@ -533,7 +376,7 @@ TEST_F(SymbolsCollector, CollectMacroUsageInIfDefSourceLocation)
Contains(IsSourceLocationEntry(symbolId("IF_DEFINE"), fileId, 17, 8, SourceLocationKind::MacroUsage)));
}
-TEST_F(SymbolsCollector, CollectMacroUsageInDefinedSourceLocation)
+TEST_F(SymbolsCollector, DISABLED_CollectMacroUsageInDefinedSourceLocation)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
@@ -566,7 +409,7 @@ TEST_F(SymbolsCollector, CollectMacroUsageUndefSourceLocation)
Contains(IsSourceLocationEntry(symbolId("UN_DEFINE"), fileId, 34, 8, SourceLocationKind::MacroUndefinition)));
}
-TEST_F(SymbolsCollector, CollectMacroUsageBuiltInSourceLocation)
+TEST_F(SymbolsCollector, DISABLED_CollectMacroUsageBuiltInSourceLocation)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
@@ -588,7 +431,7 @@ TEST_F(SymbolsCollector, CollectMacroDefinitionSymbols)
Contains(AllOf(HasSymbolName("IF_NOT_DEFINE"), HasSymbolKind(SymbolKind::Macro))));
}
-TEST_F(SymbolsCollector, CollectMacroBuiltInSymbols)
+TEST_F(SymbolsCollector, DISABLED_CollectMacroBuiltInSymbols)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc"});
@@ -599,7 +442,7 @@ TEST_F(SymbolsCollector, CollectMacroBuiltInSymbols)
Contains(AllOf(HasSymbolName("__clang__"), HasSymbolKind(SymbolKind::Macro))));
}
-TEST_F(SymbolsCollector, CollectMacroCompilerArgumentSymbols)
+TEST_F(SymbolsCollector, DISABLED_CollectMacroCompilerArgumentSymbols)
{
auto fileId = filePathId(TESTDATA_DIR "/symbolscollector/defines.h");
collector.setFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
@@ -623,23 +466,6 @@ TEST_F(SymbolsCollector, CollectFileStatuses)
fileStatus(TESTDATA_DIR "/symbolscollector/header2.h")));
}
-TEST_F(SymbolsCollector, CollectSourceDependencies)
-{
- auto mainFileId = filePathId(TESTDATA_DIR "/symbolscollector/main2.cpp");
- auto header1FileId = filePathId(TESTDATA_DIR "/symbolscollector/header1.h");
- auto header2FileId = filePathId(TESTDATA_DIR "/symbolscollector/header2.h");
- auto header3FileId = filePathId(TESTDATA_DIR "/symbolscollector/header3.h");
- collector.setFile(mainFileId, {"cc", "-I" TESTDATA_DIR});
-
- collector.collectSymbols();
-
- ASSERT_THAT(collector.sourceDependencies(),
- UnorderedElementsAre(SourceDependency(mainFileId, header1FileId),
- SourceDependency(mainFileId, header3FileId),
- SourceDependency(header3FileId, header2FileId),
- SourceDependency(header1FileId, header2FileId)));
-}
-
TEST_F(SymbolsCollector, IsClassSymbol)
{
collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/symbolkind.cpp"), {"cc"});
@@ -770,13 +596,13 @@ TEST_F(SymbolsCollector, DontIndexUnmodifiedHeaderFilesAtSecondRun)
collector.collectSymbols();
ASSERT_THAT(collector.symbols(),
- AllOf(
- Contains(HasSymbolName("HeaderFunctionReferenceInMainFile")),
- Not(Contains(HasSymbolName("MemberReference"))),
- Not(Contains(HasSymbolName("HeaderFunctionReference"))),
- Not(Contains(HasSymbolName("HeaderFunction"))),
- Not(Contains(HasSymbolName("Class"))),
- Not(Contains(HasSymbolName("Member")))));
+ AllOf(Contains(HasSymbolName("HeaderFunctionReferenceInMainFile")),
+ Not(Contains(HasSymbolName("MemberReference"))),
+ Not(Contains(HasSymbolName("HeaderFunctionReference"))),
+ Not(Contains(HasSymbolName("HeaderFunction"))),
+ Not(Contains(HasSymbolName("Class"))),
+ Not(Contains(HasSymbolName("Member"))),
+ Not(Contains(HasSymbolName("HEADER_DEFINE")))));
}
TEST_F(SymbolsCollector, DontIndexUnmodifiedHeaderFilesAtTouchHeader)
@@ -792,13 +618,14 @@ TEST_F(SymbolsCollector, DontIndexUnmodifiedHeaderFilesAtTouchHeader)
collector.collectSymbols();
ASSERT_THAT(collector.symbols(),
- AllOf(
- Contains(HasSymbolName("HeaderFunctionReferenceInMainFile")),
- Not(Contains(HasSymbolName("MemberReference"))),
- Not(Contains(HasSymbolName("HeaderFunctionReference"))),
- Not(Contains(HasSymbolName("HeaderFunction"))),
- Not(Contains(HasSymbolName("Class"))),
- Not(Contains(HasSymbolName("Member")))));
+ AllOf(Contains(HasSymbolName("TouchHeaderFunction")),
+ Contains(HasSymbolName("HeaderFunctionReferenceInMainFile")),
+ Not(Contains(HasSymbolName("MemberReference"))),
+ Not(Contains(HasSymbolName("HeaderFunctionReference"))),
+ Not(Contains(HasSymbolName("HeaderFunction"))),
+ Not(Contains(HasSymbolName("Class"))),
+ Not(Contains(HasSymbolName("Member"))),
+ Not(Contains(HasSymbolName("HEADER_DEFINE")))));
}
TEST_F(SymbolsCollector, DontIndexSystemIncudes)
diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp
index 059b1a3c0f..a29b7f92aa 100644
--- a/tests/unit/unittest/symbolstorage-test.cpp
+++ b/tests/unit/unittest/symbolstorage-test.cpp
@@ -28,17 +28,22 @@
#include "mockfilepathcaching.h"
#include "mocksqlitedatabase.h"
-#include <symbolstorage.h>
+#include <builddependenciesstorage.h>
+#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
+#include <sqlitereadstatement.h>
+#include <sqlitewritestatement.h>
+#include <symbolstorage.h>
#include <utils/optional.h>
namespace {
-
using ClangBackEnd::FilePathCachingInterface;
+using ClangBackEnd::FilePathId;
using ClangBackEnd::SourceLocationEntries;
using ClangBackEnd::SourceLocationEntry;
using ClangBackEnd::SourceLocationKind;
+using ClangBackEnd::SourceTimeStamp;
using ClangBackEnd::SymbolEntries;
using ClangBackEnd::SymbolEntry;
using ClangBackEnd::SymbolIndex;
@@ -64,6 +69,10 @@ protected:
MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = storage.insertNewLocationsInLocationsStatement;
MockSqliteWriteStatement &deleteNewSymbolsTableStatement = storage.deleteNewSymbolsTableStatement;
MockSqliteWriteStatement &deleteNewLocationsTableStatement = storage.deleteNewLocationsTableStatement;
+ MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement;
+ MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement;
+ MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement;
+ MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement;
SymbolEntries symbolEntries{{1, {"functionUSR", "function", SymbolKind::Function}},
{2, {"function2USR", "function2", SymbolKind::Function}}};
SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SourceLocationKind::Declaration},
@@ -183,5 +192,145 @@ TEST_F(SymbolStorage, AddTablesInConstructor)
Storage storage{mockDatabase};
}
+TEST_F(SymbolStorage, FetchIndexingTimeStampsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, rollback());
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.fetchIndexingTimeStamps();
+}
+
+TEST_F(SymbolStorage, InsertIndexingTimeStamp)
+{
+ ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}};
+
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(37)));
+
+ storage.insertOrUpdateIndexingTimeStamps(fileStatuses);
+}
+
+TEST_F(SymbolStorage, InsertIndexingTimeStampsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, immediateBegin());
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
+ EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(34)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
+}
+
+TEST_F(SymbolStorage, FetchIncludedIndexingTimeStampsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
+ valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, rollback());
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
+ valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.fetchIncludedIndexingTimeStamps(1);
+}
+
+TEST_F(SymbolStorage, FetchDependentSourceIdsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy{""}));
+ EXPECT_CALL(mockDatabase, rollback());
+ EXPECT_CALL(mockDatabase, deferredBegin());
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)));
+ EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(7)));
+ EXPECT_CALL(mockDatabase, commit());
+
+ storage.fetchDependentSourceIds({3, 2, 7});
+}
+
+class SymbolStorageSlow : public testing::Test
+{
+protected:
+ Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
+ ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
+ ClangBackEnd::SymbolStorage<> storage{database};
+ ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
+};
+
+TEST_F(SymbolStorageSlow, InsertIndexingTimeStamps)
+{
+ storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34}));
+}
+
+TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamps)
+{
+ storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
+
+ storage.insertOrUpdateIndexingTimeStamps({1}, 37);
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34}));
}
+TEST_F(SymbolStorageSlow, InsertIndexingTimeStamp)
+{
+ storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}});
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
+}
+
+TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamp)
+{
+ storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}});
+
+ storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}});
+
+ ASSERT_THAT(storage.fetchIndexingTimeStamps(),
+ ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
+}
+
+TEST_F(SymbolStorageSlow, FetchIncludedIndexingTimeStamps)
+{
+ storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34);
+ buildDependenciesStorage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}});
+
+ auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1);
+
+ ASSERT_THAT(timeStamps,
+ ElementsAre(SourceTimeStamp{1, 34},
+ SourceTimeStamp{2, 34},
+ SourceTimeStamp{3, 34},
+ SourceTimeStamp{4, 34}));
+}
+
+TEST_F(SymbolStorageSlow, FetchDependentSourceIds)
+{
+ buildDependenciesStorage.insertOrUpdateSourceDependencies(
+ {{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}});
+
+ auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7});
+
+ ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7}));
+}
+} // namespace
diff --git a/tests/unit/unittest/testenvironment.h b/tests/unit/unittest/testenvironment.h
index a9529c58d5..1e6c7da862 100644
--- a/tests/unit/unittest/testenvironment.h
+++ b/tests/unit/unittest/testenvironment.h
@@ -27,36 +27,24 @@
#include <environment.h>
-#include <utf8string.h>
-#include <utils/hostosinfo.h>
+#include <filepath.h>
#include <QTemporaryDir>
-#include <QVector>
class TestEnvironment final : public ClangBackEnd::Environment
{
public:
- TestEnvironment() {
- temporaryDirectory.setAutoRemove(true);
- }
- QString pchBuildDirectory() const override
- {
- return temporaryDirectory.path();
- }
-
- uint hardwareConcurrency() const
- {
- return 2;
- }
+ TestEnvironment() { temporaryDirectory.setAutoRemove(true); }
- static QVector<Utf8String> addPlatformArguments(std::initializer_list<Utf8String> arguments = {})
+ Utils::PathString pchBuildDirectory() const override { return temporaryDirectory.path(); }
+ uint hardwareConcurrency() const { return 2; }
+ ClangBackEnd::NativeFilePathView preIncludeSearchPath() const override
{
- QVector<Utf8String> result{arguments};
- if (Utils::HostOsInfo::isWindowsHost())
- result.append(Utf8StringLiteral("-fno-delayed-template-parsing"));
- return result;
+ return includeSearchPath;
}
private:
QTemporaryDir temporaryDirectory;
+ ClangBackEnd::NativeFilePath includeSearchPath{
+ ClangBackEnd::FilePath{TESTDATA_DIR "/preincludes"}};
};
diff --git a/tests/unit/unittest/token-test.cpp b/tests/unit/unittest/token-test.cpp
index 3f7c39ea5f..f5f8a36e3a 100644
--- a/tests/unit/unittest/token-test.cpp
+++ b/tests/unit/unittest/token-test.cpp
@@ -25,7 +25,7 @@
#include "googletest.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <clangdocument.h>
#include <clangdocuments.h>
@@ -55,7 +55,7 @@ struct Data {
ClangBackEnd::Documents documents{unsavedFiles};
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/token.cpp")};
Utf8StringVector compilationArguments{
- TestEnvironment::addPlatformArguments({Utf8StringLiteral("-std=c++11")})};
+ UnitTest::addPlatformArguments({Utf8StringLiteral("-std=c++11")})};
Document document{filePath, compilationArguments, {}, documents};
TranslationUnit translationUnit{filePath,
filePath,
diff --git a/tests/unit/unittest/tokenprocessor-test.cpp b/tests/unit/unittest/tokenprocessor-test.cpp
index 8d79bc95cb..285c6d3446 100644
--- a/tests/unit/unittest/tokenprocessor-test.cpp
+++ b/tests/unit/unittest/tokenprocessor-test.cpp
@@ -24,7 +24,7 @@
****************************************************************************/
#include "googletest.h"
-#include "testenvironment.h"
+#include "unittest-utility-functions.h"
#include <clangdocument.h>
#include <clangdocuments.h>
@@ -128,7 +128,7 @@ struct Data {
ClangBackEnd::Documents documents{unsavedFiles};
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/highlightingmarks.cpp")};
Document document{filePath,
- TestEnvironment::addPlatformArguments(
+ UnitTest::addPlatformArguments(
{Utf8StringLiteral("-std=c++14"),
Utf8StringLiteral("-I" TESTDATA_DIR)}),
{},
@@ -1552,14 +1552,14 @@ TEST_F(TokenProcessor, NamespaceTypeSpelling)
ASSERT_THAT(container.extraInfo.semanticParentTypeSpelling, Utf8StringLiteral("NFoo::NBar::NTest"));
}
-TEST_F(TokenProcessor, DISABLED_WITHOUT_INVALIDDECL_PATCH(TypeNameOfInvalidDeclarationIsInvalid))
+TEST_F(TokenProcessor, TypeNameOfInvalidDeclarationIsInvalid)
{
const auto infos = translationUnit.tokenInfosInRange(sourceRange(594, 14));
ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Invalid));
}
-TEST_F(TokenProcessor, DISABLED_WITHOUT_INVALIDDECL_PATCH(VariableNameOfInvalidDeclarationIsInvalid))
+TEST_F(TokenProcessor, VariableNameOfInvalidDeclarationIsInvalid)
{
const auto infos = translationUnit.tokenInfosInRange(sourceRange(594, 14));
diff --git a/tests/unit/unittest/translationunitupdater-test.cpp b/tests/unit/unittest/translationunitupdater-test.cpp
index b491018956..eecc06b8a7 100644
--- a/tests/unit/unittest/translationunitupdater-test.cpp
+++ b/tests/unit/unittest/translationunitupdater-test.cpp
@@ -113,7 +113,7 @@ TEST_F(TranslationUnitUpdaterSlowTest, NotUpdatingParseTimePointForReparseOnly)
ASSERT_FALSE(result.hasParsed());
}
-TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependendOnFilesOnParse)
+TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependentOnFilesOnParse)
{
::TranslationUnitUpdater updater = createUpdater(createInput());
diff --git a/tests/unit/unittest/unittest-utility-functions.h b/tests/unit/unittest/unittest-utility-functions.h
index 6d68c1adfc..5102769e78 100644
--- a/tests/unit/unittest/unittest-utility-functions.h
+++ b/tests/unit/unittest/unittest-utility-functions.h
@@ -25,10 +25,12 @@
#pragma once
+#include <utils/hostosinfo.h>
#include <utils/smallstring.h>
-
#include <utils/temporarydirectory.h>
+#include <utf8stringvector.h>
+
inline
bool operator==(const QString &first, const char *second)
{
@@ -42,4 +44,12 @@ 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.pro b/tests/unit/unittest/unittest.pro
index 4fbba5b413..63980ab055 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -26,6 +26,9 @@ msvc: QMAKE_CXXFLAGS_WARN_ON -= -w34100 # 'unreferenced formal parameter' in MAT
win32:DEFINES += ECHOSERVER=\"R\\\"xxx($$OUT_PWD/../echo)xxx\\\"\"
unix: DEFINES += ECHOSERVER=\"R\\\"xxx($$OUT_PWD/../echoserver/echo)xxx\\\"\"
+RELATIVE_DATA_PATH = ../../../share/qtcreator
+DEFINES += $$shell_quote(RELATIVE_DATA_PATH=\"$$RELATIVE_DATA_PATH\")
+
linux {
QMAKE_LFLAGS_RELEASE = #disable optimization
QMAKE_LFLAGS += -fno-merge-debug-strings -fuse-ld=gold
@@ -33,7 +36,7 @@ CONFIG(release, debug|release):QMAKE_LFLAGS += -Wl,--strip-debug
}
gcc:!clang: QMAKE_CXXFLAGS += -Wno-noexcept-type
-msvc: QMAKE_CXXFLAGS += /bigobj
+msvc: QMAKE_CXXFLAGS += /bigobj /wd4267 /wd4141 /wd4146
# create fake CppTools.json for the mime type definitions
dependencyList = "\"Dependencies\" : []"