diff --git a/dist/changes-4.12.0.md b/dist/changes-4.12.0.md index 136428ef568..bcc86dee14e 100644 --- a/dist/changes-4.12.0.md +++ b/dist/changes-4.12.0.md @@ -104,6 +104,7 @@ Projects ### Qbs +* Updated included Qbs version to 1.16.0 * Changed to use separate Qbs executable instead of direcly linking to Qbs (QTCREATORBUG-20622) * Added option for default install root (QTCREATORBUG-12983) @@ -139,6 +140,7 @@ Analyzer ### Clang * Improved filtering +* Added `Analyze Current File` to `Tools` menu and editor context menu * Added context menu item that opens help on diagnostics ### CppCheck @@ -161,6 +163,7 @@ Qt Quick Designer * Added locking and pinning of animation curves (QDS-550, QDS-551) * Added support for annotations (QDS-39) * Fixed dragging of keyframes in curve editor (QDS-1405) +* Fixed crash when selecting icon (QTCREATORBUG-23773) Version Control Systems ----------------------- @@ -181,6 +184,7 @@ Test Integration ### Google Test * Added support for internal logging (QTCREATORBUG-23354) +* Added support for `GTEST_SKIP` (QTCREATORBUG-23736) Platforms --------- @@ -202,6 +206,8 @@ Platforms * Added option to automatically download and install required Android tools (QTCREATORBUG-23285) * Added option to register multiple NDKs (QTCREATORBUG-23286) * Added automatic selection of correct NDK for Qt version (QTCREATORBUG-23583) +* Added option to download and use [OpenSSL for Android](https://github.com/KDAB/android_openssl) + (QTBUG-80625) * Added support for Android 11 with API level 30 * Improved examples browser to only show items tagged with `android` (QTBUG-80716) * Improved manifest editor (QTCREATORBUG-23283) @@ -222,6 +228,10 @@ Platforms * Added support for J-Link and EBlink GDB servers * Added support for KEIL uVision v5.x debugger +### MCU + +* Added auto-registration of documentation (UL-1685) + Credits for these changes go to: -------------------------------- Aleksei German @@ -243,6 +253,7 @@ Eike Ziller Fawzi Mohamed Federico Guerinoni Filippo Cucchetto +Friedemann Kleint Halfdan Ingvarsson Hannes Domani Henning Gruendl @@ -266,6 +277,7 @@ Nikolai Kosjar Nikolay Panov Oliver Wolff Orgad Shaneh +Richard Weickelt Robert Löhning Sergey Morozov Tasuku Suzuki @@ -276,6 +288,8 @@ Tim Jenssen Tobias Hunger Topi Reinio Ulf Hermann +Unseon Ryu +Venugopal Shivashankar Vikas Pachdha Ville Voutilainen Volodymyr Samokhatko diff --git a/doc/qtcreator/images/creator-gs-01.png b/doc/qtcreator/images/creator-gs-01.png deleted file mode 100644 index c67a633aa52..00000000000 Binary files a/doc/qtcreator/images/creator-gs-01.png and /dev/null differ diff --git a/doc/qtcreator/images/creator-gs-02.png b/doc/qtcreator/images/creator-gs-02.png deleted file mode 100644 index b8b4bd93ae0..00000000000 Binary files a/doc/qtcreator/images/creator-gs-02.png and /dev/null differ diff --git a/doc/qtcreator/images/creator-gs-03.png b/doc/qtcreator/images/creator-gs-03.png deleted file mode 100644 index f97d38b1d55..00000000000 Binary files a/doc/qtcreator/images/creator-gs-03.png and /dev/null differ diff --git a/doc/qtcreator/images/creator-gs-04.png b/doc/qtcreator/images/creator-gs-04.png deleted file mode 100644 index b99158debd6..00000000000 Binary files a/doc/qtcreator/images/creator-gs-04.png and /dev/null differ diff --git a/doc/qtcreator/images/creator_advanceduse.png b/doc/qtcreator/images/creator_advanceduse.png index 3c07f77d6f4..c3ec46c38ec 100644 Binary files a/doc/qtcreator/images/creator_advanceduse.png and b/doc/qtcreator/images/creator_advanceduse.png differ diff --git a/doc/qtcreator/images/creator_advanceduse.svg b/doc/qtcreator/images/creator_advanceduse.svg new file mode 100644 index 00000000000..7a7b77186b4 --- /dev/null +++ b/doc/qtcreator/images/creator_advanceduse.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/doc/qtcreator/images/creator_buildingrunning.png b/doc/qtcreator/images/creator_buildingrunning.png index 7f51e328e87..a52c4b392f6 100644 Binary files a/doc/qtcreator/images/creator_buildingrunning.png and b/doc/qtcreator/images/creator_buildingrunning.png differ diff --git a/doc/qtcreator/images/creator_buildingrunning.svg b/doc/qtcreator/images/creator_buildingrunning.svg new file mode 100644 index 00000000000..3d4808cdb58 --- /dev/null +++ b/doc/qtcreator/images/creator_buildingrunning.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + 1 + 2 + 3 + + + + + + + + + + + + 1 + 2 + 3 + + + diff --git a/doc/qtcreator/images/creator_coding.png b/doc/qtcreator/images/creator_coding.png index 7ddc31ad1c2..9597fe831fc 100644 Binary files a/doc/qtcreator/images/creator_coding.png and b/doc/qtcreator/images/creator_coding.png differ diff --git a/doc/qtcreator/images/creator_coding.svg b/doc/qtcreator/images/creator_coding.svg new file mode 100644 index 00000000000..39149cdf397 --- /dev/null +++ b/doc/qtcreator/images/creator_coding.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +// main.cpp +#include <QApplication> +#include <QTableView> +#include "mymodel.h" +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QTableView tableView; + MyModel myModel; +} + diff --git a/doc/qtcreator/images/creator_designinguserinterface.png b/doc/qtcreator/images/creator_designinguserinterface.png index ba6e86de4cc..85162a52cea 100644 Binary files a/doc/qtcreator/images/creator_designinguserinterface.png and b/doc/qtcreator/images/creator_designinguserinterface.png differ diff --git a/doc/qtcreator/images/creator_designinguserinterface.svg b/doc/qtcreator/images/creator_designinguserinterface.svg new file mode 100644 index 00000000000..b3aff292403 --- /dev/null +++ b/doc/qtcreator/images/creator_designinguserinterface.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + +1 +2 +3 + + + ON + + + + + + + + + + + + + + diff --git a/doc/qtcreator/images/creator_gettinghelp.png b/doc/qtcreator/images/creator_gettinghelp.png index a9b51e3297c..c3ae18b392a 100644 Binary files a/doc/qtcreator/images/creator_gettinghelp.png and b/doc/qtcreator/images/creator_gettinghelp.png differ diff --git a/doc/qtcreator/images/creator_gettinghelp.svg b/doc/qtcreator/images/creator_gettinghelp.svg new file mode 100644 index 00000000000..6663ed53eb9 --- /dev/null +++ b/doc/qtcreator/images/creator_gettinghelp.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + +? + diff --git a/doc/qtcreator/images/creator_gettingstarted.png b/doc/qtcreator/images/creator_gettingstarted.png index 85eb15c4e00..e6177959ad6 100644 Binary files a/doc/qtcreator/images/creator_gettingstarted.png and b/doc/qtcreator/images/creator_gettingstarted.png differ diff --git a/doc/qtcreator/images/creator_gettingstarted.svg b/doc/qtcreator/images/creator_gettingstarted.svg new file mode 100644 index 00000000000..779ae13947f --- /dev/null +++ b/doc/qtcreator/images/creator_gettingstarted.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/doc/qtcreator/images/creator_managingprojects.png b/doc/qtcreator/images/creator_managingprojects.png index 016a4cd4281..dfb2ebe67d0 100644 Binary files a/doc/qtcreator/images/creator_managingprojects.png and b/doc/qtcreator/images/creator_managingprojects.png differ diff --git a/doc/qtcreator/images/creator_managingprojects.svg b/doc/qtcreator/images/creator_managingprojects.svg new file mode 100644 index 00000000000..fb934268a09 --- /dev/null +++ b/doc/qtcreator/images/creator_managingprojects.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + +C++ +qml + + + + + diff --git a/doc/qtcreator/images/creator_publishing.png b/doc/qtcreator/images/creator_publishing.png index 8066ffddc1f..b7e79a9bc3a 100644 Binary files a/doc/qtcreator/images/creator_publishing.png and b/doc/qtcreator/images/creator_publishing.png differ diff --git a/doc/qtcreator/images/creator_publishing.svg b/doc/qtcreator/images/creator_publishing.svg new file mode 100644 index 00000000000..4954f8930c2 --- /dev/null +++ b/doc/qtcreator/images/creator_publishing.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + 3 + + + diff --git a/doc/qtcreator/images/creator_testing.png b/doc/qtcreator/images/creator_testing.png index 194fd94beba..395f898cddf 100644 Binary files a/doc/qtcreator/images/creator_testing.png and b/doc/qtcreator/images/creator_testing.png differ diff --git a/doc/qtcreator/images/creator_testing.svg b/doc/qtcreator/images/creator_testing.svg new file mode 100644 index 00000000000..14e75f3489f --- /dev/null +++ b/doc/qtcreator/images/creator_testing.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + diff --git a/doc/qtcreator/images/qtcreator-gdb-extended-options.png b/doc/qtcreator/images/qtcreator-gdb-extended-options.png new file mode 100644 index 00000000000..10e22f235c1 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-gdb-extended-options.png differ diff --git a/doc/qtcreator/images/qtcreator-gdb-options.png b/doc/qtcreator/images/qtcreator-gdb-options.png new file mode 100644 index 00000000000..d8f3f59be02 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-gdb-options.png differ diff --git a/doc/qtcreator/images/qtcreator-new-qt-quick-project-wizard.png b/doc/qtcreator/images/qtcreator-new-qt-quick-project-wizard.png index 49562a64ea5..a2a5bf396fc 100644 Binary files a/doc/qtcreator/images/qtcreator-new-qt-quick-project-wizard.png and b/doc/qtcreator/images/qtcreator-new-qt-quick-project-wizard.png differ diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc index 1a1f36d4918..78ac325ab46 100644 --- a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc +++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc @@ -390,6 +390,93 @@ \endlist + \section3 Specifying GDB Settings + + To specify settings for managing the GDB process, select \uicontrol Tools > + \uicontrol Options > \uicontrol Debugger > \uicontrol GDB. + + \image qtcreator-gdb-options.png "GDB options" + + To specify a timeout for terminating non-responsive GDB processes, set the + number of seconds to wait in the \uicontrol {GDB timeout} field. The default + value of 20 seconds should be sufficient for most applications, but if + loading big libraries or listing source files takes much longer than + that on slow machines, you should increase the value. + + To compress several steps into one step for less noisy debugging when + stepping into code, select the \uicontrol {Skip known frames when stepping} + check box. For example, the atomic reference counting code is skipped, and + a single \e {Step Into} for a signal emission ends up directly in the slot + connected to it. + + To display a message box as soon as your application receives a signal, such + as SIGSEGV, during debugging, select the \uicontrol {Show a message box when + receiving a signal} check box. + + GDB allows setting breakpoints on source lines for which no code was + generated. In such situations, the breakpoint is shifted to the next + source code line for which the code was actually generated. To reflect + such temporary changes by moving the breakpoint markers in the source + code editor, select the \uicontrol {Adjust breakpoint locations} check box. + + To specify whether the dynamic or the static type of objects will be + displayed, select the \uicontrol {Use dynamic object type for display} + check box. Keep in mind that choosing the dynamic type might be slower. + + To allow reading the user's default .gdbinit file on debugger startup, + select the \uicontrol {Load .gdbinit file on startup} check box. + + To use the default GDB pretty printers installed in your system + or linked to the libraries your application uses, select the + \uicontrol {Load system GDB pretty printers} check box. + + By default, GDB shows AT&T style disassembly. To switch to the Intel style, + select the \uicontrol {Use Intel style disassembly} check box. + + To execute GDB commands after GDB has been started, but before the debugged + program is started or attached, and before the debugging helpers are + initialized, enter them in the \uicontrol {Additional Startup Commands} + field. + + To execute GDB commands after GDB has successfully attached to remote + targets, enter them in the \uicontrol {Additional Attach Commands} field. + You can add commands to further set up the target here, such as + \c {monitor reset} or \c {load}. + + To execute simple Python commands, prefix them with \c python. To execute + sequences of Python commands spanning multiple lines, prepend the block + with \c python on a separate line, and append \c end on a separate line. + To execute arbitrary Python scripts, use + \c {python execfile('/path/to/script.py')}. + + \section3 Specifying Extended GDB Settings + + To specify extended settings for GBD, select \uicontrol Tools > + \uicontrol Options > \uicontrol Debugger > \uicontrol {GDB Extended}. + The settings give access to advanced or experimental functions of GDB. + Enabling them may negatively impact your debugging experience, so use + them with care. + + \image qtcreator-gdb-extended-options.png "GDB Extended options" + + To use asynchronous mode to control the inferior, select the + respective check box. + + To add common paths to locations of debug information, such as + \c {/usr/src/debug}, when starting GDB, select the + \uicontrol {Use common locations for debug information} check box. + + To stop when \c qWarning, \c qFatal, or \c abort is called, select the + respective check box. + + To enable stepping backwards, select the \uicontrol {Enable reverse + debugging} check box. This feature is very slow and unstable on the + GDB side. It exhibits unpredictable behavior when going backwards over + system calls and is very likely to destroy your debugging session. + + To keep debugging all children after a fork, select the + \uicontrol {Debug all child processes} check box. + \section3 Using CDB In remote mode, the local CDB process talks to a CDB process that runs on diff --git a/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc b/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc index 02eee1e2b04..1407cf33581 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-getting-started.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -39,8 +39,8 @@ \table \row - \li \inlineimage creator-gs-01.png - \li \inlineimage creator-gs-02.png + \li \inlineimage creator_gettingstarted.png + \li \inlineimage creator_designinguserinterface.png \li \inlineimage creator_advanceduse.png \row \li \b {\l{IDE Overview}} @@ -60,8 +60,8 @@ control systems. For an overview of the options you have, go to \l{Configuring Qt Creator}. \row - \li \inlineimage creator-gs-03.png - \li \inlineimage creator-gs-04.png + \li \inlineimage creator_buildingrunning.png + \li \inlineimage creator_gettinghelp.png \li \row \li \b {\l{Building and Running an Example}} diff --git a/doc/qtcreator/src/overview/creator-only/creator-tutorials.qdoc b/doc/qtcreator/src/overview/creator-only/creator-tutorials.qdoc index 003422fef43..ec2ba4fdf95 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-tutorials.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-tutorials.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -37,7 +37,7 @@ \title Tutorials - \image creator-gs-04.png + \image creator_gettinghelp.png You can use \QC to create applications for several platforms by using several technologies. The tutorials in this manual explain how to create diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc index d20710d3074..c830180c901 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc @@ -98,15 +98,9 @@ \list - \li Applications + \li Application (Qt Quick) \list - - \li Qt Widgets Application - - Use \QD forms to design a Qt widget based user interface for the - desktop and C++ to implement the application logic - \li Qt Quick Application - Empty Create an empty Qt Quick application that uses Qt Quick 2 types. @@ -121,10 +115,25 @@ {Qt Quick Controls} to implement a scrollable list (requires Qt 5.9 or later) or a set of pages with a stack-based or swipe-based navigation model (requires Qt 5.7 or later). + \endlist + + \li Application (Qt) + + \list + + \li Qt Widgets Application + + Use \QD forms to design a Qt widget based user interface for the + desktop and C++ to implement the application logic \li Qt Console Application Use a single main.cpp file + \endlist + + \li Application (Qt for Python) + + \list \li Qt for Python Application - Empty, Window, Window (UI file), or Qt Quick Application (Empty) @@ -135,14 +144,18 @@ a widget-based UI. Alternatively, you can create an empty Qt Quick Application. - \li MCU Support Application + \endlist - Creates an application that uses a subset of QML and - Qt Quick Controls (as supported by Qt for MCUs) that - you can deploy, run, and debug on MCU boards. For more - information, see \l {Connecting MCUs}. + \li Application (Qt for MCU) - \endlist + \list + \li MCU Support Application + + Creates an application that uses a subset of QML and + Qt Quick Controls (as supported by Qt for MCUs) that + you can deploy, run, and debug on MCU boards. For more + information, see \l {Connecting MCUs}. + \endlist \li Libraries diff --git a/doc/qtcreator/src/webassembly/creator-webassembly.qdoc b/doc/qtcreator/src/webassembly/creator-webassembly.qdoc index 083f8b7d40b..7de593b5815 100644 --- a/doc/qtcreator/src/webassembly/creator-webassembly.qdoc +++ b/doc/qtcreator/src/webassembly/creator-webassembly.qdoc @@ -54,7 +54,7 @@ \list \li Qt for WebAssembly 5.13.1, or later - \li On Windows: \l{http://mingw.org/}{MinGW} 7.3.0, or later + \li On Windows: \l{http://wiki.qt.io/MinGW}{MinGW} 7.3.0, or later \li \l{https://emscripten.org/docs/introducing_emscripten/index.html} {emscripten} tool chain for compiling to WebAssembly \li \c sed stream editor @@ -74,9 +74,13 @@ Windows, \MinGW (found in \uicontrol {Developer and Designer Tools}). \li Check out \c emsdk and install and activate \c emscripten, as instructed in \l {Qt for WebAssembly}. + \note Do not use the \c{--embedded} option for activating the + \c emscripten version in the \c emsdk, because \QC + expects to find the \c{.emscripten} file describing the toolchain in + your home directory. \li On Windows, you have to download and install \c sed, as instructed in \l{http://gnuwin32.sourceforge.net/packages/sed.htm} - {sed for Windows}, and add its location to the system PATH. + {sed for Windows}. \li In \QC, select \uicontrol Help > \uicontrol {About Plugins} > \uicontrol {Device Support} > \uicontrol {WebAssembly} to enable the plugin. diff --git a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h index 9f25e2abb4b..332b6006c39 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h +++ b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h @@ -43,7 +43,8 @@ public: SelectionModeToggle, CameraToggle, OrientationToggle, - EditLightToggle + EditLightToggle, + ShowGrid }; explicit View3DActionCommand(Type type, bool enable); diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 3910b36fd7f..db8d4fb4eab 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -24,7 +24,6 @@ ****************************************************************************/ import QtQuick 2.12 -import QtQuick.Window 2.12 import QtQuick3D 1.15 import QtQuick.Controls 2.0 import QtGraphicalEffects 1.0 @@ -40,11 +39,18 @@ Item { property View3D editView: null property string sceneId - property alias showEditLight: btnEditViewLight.toggled - property alias usePerspective: btnPerspective.toggled - property alias globalOrientation: btnLocalGlobal.toggled + property bool showEditLight: false + property bool showGrid: true + property bool usePerspective: true + property bool globalOrientation: false property alias contentItem: contentItem + enum SelectionMode { Item, Group } + enum TransformMode { Move, Rotate, Scale } + + property int selectionMode: EditView3D.SelectionMode.Item + property int transformMode: EditView3D.TransformMode.Move + property Node selectedNode: null // This is non-null only in single selection case property var selectedNodes: [] // All selected nodes @@ -53,16 +59,18 @@ Item { property var selectionBoxes: [] property rect viewPortRect: Qt.rect(0, 0, 1000, 1000) - property bool showButtons: false - signal selectionChanged(var selectedNodes) signal commitObjectProperty(var object, var propName) signal changeObjectProperty(var object, var propName) signal notifyActiveSceneChange() - onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective) - onShowEditLightChanged: _generalHelper.storeToolState(sceneId,"showEditLight", showEditLight) + onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective) + onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight) onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) + onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid); + onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode); + onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode); + onActiveSceneChanged: updateActiveScene() function createEditView() @@ -72,11 +80,13 @@ Item { editView = component.createObject(viewRect, {"usePerspective": usePerspective, "showSceneLight": showEditLight, + "showGrid": showGrid, "importScene": activeScene, "cameraZoomFactor": cameraControl._zoomFactor, "z": 1}); editView.usePerspective = Qt.binding(function() {return usePerspective;}); editView.showSceneLight = Qt.binding(function() {return showEditLight;}); + editView.showGrid = Qt.binding(function() {return showGrid;}); editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;}); selectionBoxes.length = 0; @@ -148,41 +158,31 @@ Item { showEditLight = toolStates.showEditLight; else if (resetToDefault) showEditLight = false; + + if ("showGrid" in toolStates) + showGrid = toolStates.showGrid; + else if (resetToDefault) + showGrid = true; + if ("usePerspective" in toolStates) usePerspective = toolStates.usePerspective; else if (resetToDefault) - usePerspective = false; + usePerspective = true; + if ("globalOrientation" in toolStates) globalOrientation = toolStates.globalOrientation; else if (resetToDefault) globalOrientation = false; - var groupIndex; - var group; - var i; + if ("selectionMode" in toolStates) + selectionMode = toolStates.selectionMode; + else if (resetToDefault) + selectionMode = EditView3D.SelectionMode.Item; - if ("groupSelect" in toolStates) { - groupIndex = toolStates.groupSelect; - group = toolbarButtons.buttonGroups["groupSelect"]; - for (i = 0; i < group.length; ++i) - group[i].selected = (i === groupIndex); - _generalHelper.storeToolState(sceneId, "groupSelect", groupIndex) - } else if (resetToDefault) { - btnSelectItem.selected = true; - btnSelectGroup.selected = false; - } - - if ("groupTransform" in toolStates) { - groupIndex = toolStates.groupTransform; - group = toolbarButtons.buttonGroups["groupTransform"]; - for (i = 0; i < group.length; ++i) - group[i].selected = (i === groupIndex); - _generalHelper.storeToolState(sceneId, "groupTransform", groupIndex) - } else if (resetToDefault) { - btnRotate.selected = false; - btnScale.selected = false; - btnMove.selected = true; - } + if ("transformMode" in toolStates) + transformMode = toolStates.transformMode; + else if (resetToDefault) + selectionMode = EditView3D.TransformMode.Move; if ("editCamState" in toolStates) cameraControl.restoreCameraState(toolStates.editCamState); @@ -193,25 +193,11 @@ Item { function storeCurrentToolStates() { _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight) + _generalHelper.storeToolState(sceneId, "showGrid", showGrid) _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective) _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) - - var group = toolbarButtons.buttonGroups["groupSelect"]; - var i; - for (i = 0; i < group.length; ++i) { - if (group[i].selected) { - _generalHelper.storeToolState(sceneId, "groupSelect", i) - break; - } - } - - group = toolbarButtons.buttonGroups["groupTransform"]; - for (i = 0; i < group.length; ++i) { - if (group[i].selected) { - _generalHelper.storeToolState(sceneId, "groupTransform", i) - break; - } - } + _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode); + _generalHelper.storeToolState(sceneId, "transformMode", transformMode); cameraControl.storeCameraState(0); } @@ -259,7 +245,7 @@ Item { function handleObjectClicked(object, multi) { var theObject = object; - if (btnSelectGroup.selected) { + if (selectionMode === EditView3D.SelectionMode.Group) { while (theObject && theObject !== activeScene && theObject.parent !== activeScene) theObject = theObject.parent; } @@ -434,7 +420,7 @@ Item { highlightOnHover: true targetNode: viewRoot.selectedNode globalOrientation: viewRoot.globalOrientation - visible: viewRoot.selectedNode && btnMove.selected + visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Move view3D: overlayView dragHelper: gizmoDragHelper @@ -447,7 +433,7 @@ Item { scale: autoScale.getScale(Qt.vector3d(5, 5, 5)) highlightOnHover: true targetNode: viewRoot.selectedNode - visible: viewRoot.selectedNode && btnScale.selected + visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Scale view3D: overlayView dragHelper: gizmoDragHelper @@ -461,7 +447,7 @@ Item { highlightOnHover: true targetNode: viewRoot.selectedNode globalOrientation: viewRoot.globalOrientation - visible: viewRoot.selectedNode && btnRotate.selected + visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Rotate view3D: overlayView dragHelper: gizmoDragHelper @@ -522,7 +508,6 @@ Item { Rectangle { id: viewRect anchors.fill: parent - focus: true gradient: Gradient { GradientStop { position: 1.0; color: "#222222" } @@ -626,107 +611,6 @@ Item { } } - Rectangle { // toolbar - id: toolbar - color: "#9F000000" - width: 35 - height: toolbarButtons.height - visible: viewRoot.showButtons - - Column { - id: toolbarButtons - anchors.horizontalCenter: parent.horizontalCenter - spacing: 5 - padding: 5 - - // Button groups must be defined in parent object of buttons - property var buttonGroups: { - "groupSelect": [btnSelectGroup, btnSelectItem], - "groupTransform": [btnMove, btnRotate, btnScale] - } - - ToolBarButton { - id: btnSelectItem - selected: true - tooltip: qsTr("Select Item") - shortcut: "Q" - currentShortcut: selected ? "" : shortcut - tool: "item_selection" - buttonGroup: "groupSelect" - sceneId: viewRoot.sceneId - } - - ToolBarButton { - id: btnSelectGroup - tooltip: qsTr("Select Group") - shortcut: "Q" - currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut - tool: "group_selection" - buttonGroup: "groupSelect" - sceneId: viewRoot.sceneId - } - - Rectangle { // separator - width: 25 - height: 1 - color: "#f1f1f1" - anchors.horizontalCenter: parent.horizontalCenter - } - - ToolBarButton { - id: btnMove - selected: true - tooltip: qsTr("Move current selection") - shortcut: "W" - currentShortcut: shortcut - tool: "move" - buttonGroup: "groupTransform" - sceneId: viewRoot.sceneId - } - - ToolBarButton { - id: btnRotate - tooltip: qsTr("Rotate current selection") - shortcut: "E" - currentShortcut: shortcut - tool: "rotate" - buttonGroup: "groupTransform" - sceneId: viewRoot.sceneId - } - - ToolBarButton { - id: btnScale - tooltip: qsTr("Scale current selection") - shortcut: "R" - currentShortcut: shortcut - tool: "scale" - buttonGroup: "groupTransform" - sceneId: viewRoot.sceneId - } - - Rectangle { // separator - width: 25 - height: 1 - color: "#f1f1f1" - anchors.horizontalCenter: parent.horizontalCenter - } - - ToolBarButton { - id: btnFit - tooltip: qsTr("Fit camera to current selection") - shortcut: "F" - currentShortcut: shortcut - tool: "fit" - togglable: false - - onSelectedChanged: { - if (selected) - viewRoot.fitToView(); - } - } - } - } - AxisHelper { anchors.right: parent.right anchors.top: parent.top @@ -735,41 +619,5 @@ Item { editCameraCtrl: cameraControl selectedNode : viewRoot.selectedNodes.length ? selectionBoxes[0].model : null } - - Rectangle { // top controls bar - color: "#aa000000" - width: 290 - height: btnPerspective.height + 10 - anchors.top: parent.top - anchors.right: parent.right - anchors.rightMargin: 100 - visible: viewRoot.showButtons - - Row { - padding: 5 - anchors.fill: parent - ToggleButton { - id: btnPerspective - width: 105 - tooltip: qsTr("Toggle Perspective / Orthographic Projection") - states: [{iconId: "ortho", text: qsTr("Orthographic")}, {iconId: "persp", text: qsTr("Perspective")}] - } - - ToggleButton { - id: btnLocalGlobal - width: 65 - tooltip: qsTr("Toggle Global / Local Orientation") - states: [{iconId: "local", text: qsTr("Local")}, {iconId: "global", text: qsTr("Global")}] - } - - ToggleButton { - id: btnEditViewLight - width: 110 - toggleBackground: true - tooltip: qsTr("Toggle Edit Light") - states: [{iconId: "edit_light_off", text: qsTr("Edit Light Off")}, {iconId: "edit_light_on", text: qsTr("Edit Light On")}] - } - } - } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml new file mode 100644 index 00000000000..b16b27406d9 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick3D 1.15 + +Item { + id: viewRoot + width: 1024 + height: 1024 + visible: true + + property alias view3D: view3D + property alias camPos: viewCamera.position + + function setSceneToBox() + { + selectionBox.targetNode = view3D.importScene; + } + + function fitAndHideBox() : bool + { + cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true); + if (cameraControl._zoomFactor < 0.1) { + view3D.importScene.scale = view3D.importScene.scale.times(10); + return false; + } + if (cameraControl._zoomFactor > 100) { + view3D.importScene.scale = view3D.importScene.scale.times(0.1); + return false; + } + + selectionBox.visible = false; + return true + } + + View3D { + id: view3D + camera: viewCamera + environment: sceneEnv + + SceneEnvironment { + id: sceneEnv + antialiasingMode: SceneEnvironment.MSAA + antialiasingQuality: SceneEnvironment.VeryHigh + } + + PerspectiveCamera { + id: viewCamera + position: Qt.vector3d(-200, 200, 200) + eulerRotation: Qt.vector3d(-45, -45, 0) + } + + DirectionalLight { + rotation: viewCamera.rotation + } + + SelectionBox { + id: selectionBox + view3D: view3D + geometryName: "SB" + } + + EditCameraController { + id: cameraControl + camera: view3D.camera + view3d: view3D + } + } +} diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SceneView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/SceneView3D.qml index 72608d20b8f..7a376179d82 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/SceneView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/SceneView3D.qml @@ -23,7 +23,6 @@ ** ****************************************************************************/ -import QtQuick 2.12 import QtQuick3D 1.15 View3D { @@ -31,7 +30,8 @@ View3D { anchors.fill: parent property bool usePerspective: false - property bool showSceneLight: false + property alias showSceneLight: sceneLight.visible + property alias showGrid: helperGrid.visible property alias sceneHelpers: sceneHelpers property alias perspectiveCamera: scenePerspectiveCamera property alias orthoCamera: sceneOrthoCamera @@ -62,7 +62,6 @@ View3D { PointLight { id: sceneLight - visible: showSceneLight position: usePerspective ? scenePerspectiveCamera.position : sceneOrthoCamera.position quadraticFade: 0 diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index 8fe5395a6a5..f99d219c5c5 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -200,7 +200,7 @@ QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defau camera->setPosition(lookAt + newLookVector); - float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / 700.), 100.f) : oldZoom; + float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / 900.), 100.f) : oldZoom; float cameraZoomFactor = zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false); return QVector4D(lookAt, cameraZoomFactor); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp new file mode 100644 index 00000000000..034a809b16f --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "iconrenderer.h" +#include "../editor3d/selectionboxgeometry.h" +#include "../editor3d/generalhelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef QUICK3D_MODULE +#include +#include +#endif + +#include + +IconRenderer::IconRenderer(int size, const QString &filePath, const QString &source) + : QObject(nullptr) + , m_size(size) + , m_filePath(filePath) + , m_source(source) +{ +} + +void IconRenderer::setupRender() +{ + DesignerSupport::activateDesignerMode(); + DesignerSupport::activateDesignerWindowManager(); + + 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); + + QQmlComponent component(m_quickView->engine()); + component.loadUrl(QUrl::fromLocalFile(m_source)); + QObject *iconItem = component.create(); + + if (iconItem) { + QQuickItem *containerItem = nullptr; + bool is3D = false; +#ifdef QUICK3D_MODULE + if (auto scene = qobject_cast(iconItem)) { + qmlRegisterType("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry"); + QQmlComponent component(m_quickView->engine()); + component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/IconRenderer3D.qml")); + containerItem = qobject_cast(component.create()); + DesignerSupport::setRootItem(m_quickView, containerItem); + + auto helper = new QmlDesigner::Internal::GeneralHelper(); + m_quickView->engine()->rootContext()->setContextProperty("_generalHelper", helper); + + m_contentItem = QQmlProperty::read(containerItem, "view3D").value(); + auto view3D = qobject_cast(m_contentItem); + view3D->setImportScene(scene); + is3D = true; + } else +#endif + if (auto scene = qobject_cast(iconItem)) { + m_contentItem = scene; + containerItem = new QQuickItem(); + containerItem->setSize(QSizeF(1024, 1024)); + DesignerSupport::setRootItem(m_quickView, containerItem); + m_contentItem->setParentItem(containerItem); + } + + if (containerItem && m_contentItem) { + m_contentItem->setSize(QSizeF(m_size, m_size)); + if (m_contentItem->width() > containerItem->width()) + containerItem->setWidth(m_contentItem->width()); + if (m_contentItem->height() > containerItem->height()) + containerItem->setHeight(m_contentItem->height()); + + QTimer::singleShot(0, this, [this, containerItem, is3D]() { + m_designerSupport.refFromEffectItem(m_quickView->rootObject(), false); + QQuickDesignerSupportItems::disableNativeTextRendering(m_quickView->rootObject()); + +#ifdef QUICK3D_MODULE + if (is3D) { + // Render once to make sure scene is up to date before we set up the selection box + render({}); + QMetaObject::invokeMethod(containerItem, "setSceneToBox"); + bool success = false; + int tries = 0; + while (!success && tries < 10) { + ++tries; + render({}); + QMetaObject::invokeMethod(containerItem, "fitAndHideBox", + Q_RETURN_ARG(bool, success)); + } + } +#else + Q_UNUSED(is3D) +#endif + QFileInfo fi(m_filePath); + + // Render regular size image + render(fi.absoluteFilePath()); + + // Render @2x image + m_contentItem->setSize(QSizeF(m_size * 2, m_size * 2)); + + QString saveFile; + saveFile = fi.absolutePath() + '/' + fi.completeBaseName() + "@2x"; + if (!fi.suffix().isEmpty()) + saveFile += '.' + fi.suffix(); + + fi.absoluteDir().mkpath("."); + + render(saveFile); + + // Allow little time for file operations to finish + QTimer::singleShot(1000, qGuiApp, &QGuiApplication::quit); + }); + } else { + qGuiApp->quit(); + } + } else { + qGuiApp->quit(); + } +} + +void IconRenderer::render(const QString &fileName) +{ + std::function updateNodesRecursive; + updateNodesRecursive = [&updateNodesRecursive](QQuickItem *item) { + const auto childItems = item->childItems(); + for (QQuickItem *childItem : childItems) + updateNodesRecursive(childItem); + DesignerSupport::updateDirtyNode(item); + }; + updateNodesRecursive(m_quickView->rootObject()); + + QRect rect(QPoint(), m_contentItem->size().toSize()); + QImage renderImage = m_designerSupport.renderImageForItem(m_quickView->rootObject(), + rect, rect.size()); + if (!fileName.isEmpty()) { + QFileInfo fi(fileName); + if (fi.suffix().isEmpty()) + renderImage.save(fileName, "PNG"); + else + renderImage.save(fileName); + } +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h new file mode 100644 index 00000000000..f7bab0f6fc6 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QQuickView; +class QQuickItem; +QT_END_NAMESPACE + +class IconRenderer : public QObject +{ + Q_OBJECT + +public: + explicit IconRenderer(int size, const QString &filePath, const QString &source); + + void setupRender(); + +private: + void render(const QString &fileName); + + int m_size = 16; + QString m_filePath; + QString m_source; + QQuickView *m_quickView = nullptr; + QQuickItem *m_contentItem = nullptr; + DesignerSupport m_designerSupport; +}; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri new file mode 100644 index 00000000000..59d5b12cee1 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri @@ -0,0 +1,3 @@ +HEADERS += $$PWD/iconrenderer.h + +SOURCES += $$PWD/iconrenderer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp index 2d2edeee4a6..1c6601784b8 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp @@ -653,7 +653,6 @@ QObject *ObjectNodeInstance::createPrimitive(const QString &typeName, int majorN || typeName == "QtQuick.Controls/Drawer" || typeName == "QtQuick.Controls/Dialog" || typeName == "QtQuick.Controls/Menu" - || typeName == "QtQuick.Controls/Pane" || typeName == "QtQuick.Controls/ToolTip") polishTypeName = "QtQuick/Item"; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 253147de020..4331e35ddc8 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -745,7 +745,7 @@ QObject *Qt5InformationNodeInstanceServer::find3DSceneRoot(const ServerNodeInsta view = qobject_cast(parentInstance.internalObject()); int nodeCount = countChildNodes(view); if (nodeCount == 1) - return checkInstance.internalObject(); + return childNode; else return view->scene(); } else if (parentInstance.isSubclassOf("QQuick3DNode")) { @@ -1045,24 +1045,26 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm if (firstSceneRoot && sceneRoot == firstSceneRoot && instance.isSubclassOf("QQuick3DNode")) object = instance.internalObject(); - auto instanceIsModelOrComponent = [&]() -> bool { - bool retval = instance.isSubclassOf("QQuick3DModel"); + auto isSelectableAsRoot = [&]() -> bool { #ifdef QUICK3D_MODULE - if (!retval) { - // Node is a component if it has node children that have no instances - auto node = qobject_cast(object); - if (node) { - const auto childItems = node->childItems(); - for (const auto &childItem : childItems) { - if (qobject_cast(childItem) && !hasInstanceForObject(childItem)) - return true; - } + if (qobject_cast(object) + || qobject_cast(object) + || qobject_cast(object)) { + return true; + } + // Node is a component if it has node children that have no instances + auto node = qobject_cast(object); + if (node) { + const auto childItems = node->childItems(); + for (const auto &childItem : childItems) { + if (qobject_cast(childItem) && !hasInstanceForObject(childItem)) + return true; } } #endif - return retval; + return false; }; - if (object && (firstSceneRoot != object || instanceIsModelOrComponent())) + if (object && (firstSceneRoot != object || isSelectableAsRoot())) selectedObjs << objectToVariant(object); } } @@ -1162,19 +1164,19 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c switch (command.type()) { case View3DActionCommand::MoveTool: - updatedState.insert("groupTransform", 0); + updatedState.insert("transformMode", 0); break; case View3DActionCommand::RotateTool: - updatedState.insert("groupTransform", 1); + updatedState.insert("transformMode", 1); break; case View3DActionCommand::ScaleTool: - updatedState.insert("groupTransform", 2); + updatedState.insert("transformMode", 2); break; case View3DActionCommand::FitToView: QMetaObject::invokeMethod(m_editView3DRootItem, "fitToView"); break; case View3DActionCommand::SelectionModeToggle: - updatedState.insert("groupSelect", command.isEnabled() ? 0 : 1); + updatedState.insert("selectionMode", command.isEnabled() ? 1 : 0); break; case View3DActionCommand::CameraToggle: updatedState.insert("usePerspective", command.isEnabled()); @@ -1187,6 +1189,9 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c case View3DActionCommand::EditLightToggle: updatedState.insert("showEditLight", command.isEnabled()); break; + case View3DActionCommand::ShowGrid: + updatedState.insert("showGrid", command.isEnabled()); + break; default: break; } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri index d0bab57ca1a..b8013102767 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri @@ -13,6 +13,7 @@ include (../container/container.pri) include (../interfaces/interfaces.pri) include (../types/types.pri) include (../qmlprivategate/qmlprivategate.pri) +include (iconrenderer/iconrenderer.pri) SOURCES += $$PWD/qml2puppetmain.cpp RESOURCES += $$PWD/../qmlpuppet.qrc diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp index 70f403512fa..ee2f5bac599 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp @@ -32,6 +32,7 @@ #include #include +#include "iconrenderer/iconrenderer.h" #include #include @@ -52,11 +53,13 @@ int internalMain(QGuiApplication *application) QCoreApplication::setApplicationVersion("1.0.0"); if (application->arguments().count() < 2 - || (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() < 3)) { + || (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() < 3) + || (application->arguments().at(1) == "--rendericon" && application->arguments().count() < 5)) { qDebug() << "Usage:\n"; qDebug() << "--test"; qDebug() << "--version"; qDebug() << "--readcapturedstream [control stream file]"; + qDebug() << "--rendericon "; return -1; } @@ -108,7 +111,16 @@ int internalMain(QGuiApplication *application) return -1; } + if (application->arguments().at(1) == "--rendericon") { + int size = application->arguments().at(2).toInt(); + QString iconFileName = application->arguments().at(3); + QString iconSource = application->arguments().at(4); + IconRenderer *iconRenderer = new IconRenderer(size, iconFileName, iconSource); + iconRenderer->setupRender(); + + return application->exec(); + } #ifdef ENABLE_QT_BREAKPAD const QString libexecPath = QCoreApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH; diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index 0585896fedb..81f28c13ed3 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -7,6 +7,7 @@ mockfiles/SwipeView.qml mockfiles/GenericBackend.qml mockfiles/Dialog.qml + mockfiles/IconRenderer3D.qml mockfiles/EditView3D.qml mockfiles/EditCameraController.qml mockfiles/Arrow.qml diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml index 0fa2b331a8c..3cd5d90399f 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml @@ -40,7 +40,7 @@ Column { ColorEditor { caption: qsTr("Color") backendValue: backendValues.color - supportGradient: true + supportGradient: backendValues.gradient.isAvailable } diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index 6c723bba443..e505a9e4c5e 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -35,6 +35,7 @@ #include #include +#include using namespace LanguageUtils; using namespace QmlJS::AST; @@ -385,8 +386,10 @@ Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &im if (!importFound) { for (const QString &dir : qAsConst(m_applicationDirectories)) { + QDirIterator it(dir, QStringList { "*.qmltypes" }, QDir::Files); + // This adds the types to the C++ types, to be found below if applicable. - if (QFile::exists(dir + "/app.qmltypes")) + if (it.hasNext()) importLibrary(doc, dir, &import); } } diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index a7f2b3d3ae7..25cd5f02d0e 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -781,13 +782,17 @@ static bool findNewQmlApplicationInPath(const QString &path, default: break; } - const QDir dir(path); - const QLatin1String appQmltypes("app.qmltypes"); - QFile appQmltypesFile(dir.filePath(appQmltypes)); - if (!appQmltypesFile.exists()) + QString qmltypesFile; + + QDir dir(path); + QDirIterator it(path, QStringList { "*.qmltypes" }, QDir::Files); + + if (!it.hasNext()) return false; - LibraryInfo libraryInfo = LibraryInfo(QmlDirParser::TypeInfo(appQmltypes)); + qmltypesFile = it.next(); + + LibraryInfo libraryInfo = LibraryInfo(QmlDirParser::TypeInfo(qmltypesFile)); const QString libraryPath = dir.absolutePath(); newLibraries->insert(libraryPath); modelManager->updateLibraryInfo(path, libraryInfo); diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp index d74b4663fab..7ba665dc94b 100644 --- a/src/libs/qmljs/qmljsplugindumper.cpp +++ b/src/libs/qmljs/qmljsplugindumper.cpp @@ -36,17 +36,12 @@ #include #include +#include #include using namespace LanguageUtils; using namespace QmlJS; -static const QStringList qmltypesFileNames = { - QLatin1String("plugins.qmltypes"), - QLatin1String("app.qmltypes"), - QLatin1String("lib.qmltypes") -}; - PluginDumper::PluginDumper(ModelManagerInterface *modelManager) : QObject(modelManager) , m_modelManager(modelManager) @@ -152,9 +147,12 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString & plugin.importVersion = importVersion; // add default qmltypes file if it exists - for (const QString &qmltypesFileName : qmltypesFileNames) { - const QString defaultQmltypesPath = makeAbsolute(qmltypesFileName, canonicalLibraryPath); - if (!plugin.typeInfoPaths.contains(defaultQmltypesPath) && QFile::exists(defaultQmltypesPath)) + QDirIterator it(canonicalLibraryPath, QStringList { "*.qmltypes" }, QDir::Files); + + while (it.hasNext()) { + const QString defaultQmltypesPath = makeAbsolute(it.next(), canonicalLibraryPath); + + if (!plugin.typeInfoPaths.contains(defaultQmltypesPath)) plugin.typeInfoPaths += defaultQmltypesPath; } @@ -405,11 +403,10 @@ QString PluginDumper::buildQmltypesPath(const QString &name) const if (path.isEmpty()) return QString(); - for (const QString &qmltypesFileName : qmltypesFileNames) { - const QString filename = path + QLatin1Char('/') + qmltypesFileName; - if (QFile::exists(filename)) - return filename; - } + QDirIterator it(path, QStringList { "*.qmltypes" }, QDir::Files); + + if (it.hasNext()) + return it.next(); return QString(); } diff --git a/src/plugins/android/androidsdkmanagerwidget.cpp b/src/plugins/android/androidsdkmanagerwidget.cpp index b098078f0b2..631b7dd385a 100644 --- a/src/plugins/android/androidsdkmanagerwidget.cpp +++ b/src/plugins/android/androidsdkmanagerwidget.cpp @@ -444,6 +444,9 @@ void AndroidSdkManagerWidget::switchView(AndroidSdkManagerWidget::View view) else emit updatingSdk(); + if (m_currentView == LicenseWorkflow) + emit licenseWorkflowStarted(); + m_ui->operationProgress->setValue(0); m_ui->viewStack->setCurrentWidget(m_currentView == PackageListing ? m_ui->packagesStack : m_ui->outputStack); diff --git a/src/plugins/android/androidsdkmanagerwidget.h b/src/plugins/android/androidsdkmanagerwidget.h index 7ef83d31f43..eadb61e7eb3 100644 --- a/src/plugins/android/androidsdkmanagerwidget.h +++ b/src/plugins/android/androidsdkmanagerwidget.h @@ -86,6 +86,7 @@ public: signals: void updatingSdk(); void updatingSdkFinished(); + void licenseWorkflowStarted(); private: void onApplyButton(); diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index d7c136fd7b1..28b3ad3c5f4 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -428,6 +428,9 @@ AndroidSettingsWidget::AndroidSettingsWidget() m_ui->SDKLocationPathChooser->setEnabled(true); m_ui->managerTabWidget->tabBar()->setEnabled(true); }); + connect(m_sdkManagerWidget, &AndroidSdkManagerWidget::licenseWorkflowStarted, [this]() { + m_ui->scrollArea->ensureWidgetVisible(m_ui->managerTabWidget); + }); QMap javaValidationPoints; javaValidationPoints[JavaPathExistsRow] = tr("JDK path exists."); @@ -1020,7 +1023,13 @@ AndroidSettingsPage::AndroidSettingsPage() setId(Constants::ANDROID_SETTINGS_ID); setDisplayName(AndroidSettingsWidget::tr("Android")); setCategory(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY); - setWidgetCreator([] { return new AndroidSettingsWidget; }); + setWidgetCreator([] { + auto widget = new AndroidSettingsWidget; + QPalette pal = widget->palette(); + pal.setColor(QPalette::Window, Utils::creatorTheme()->color(Utils::Theme::BackgroundColorNormal)); + widget->setPalette(pal); + return widget; + }); } } // namespace Internal diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui index 1bd69e556ae..56eba59b99d 100644 --- a/src/plugins/android/androidsettingswidget.ui +++ b/src/plugins/android/androidsettingswidget.ui @@ -27,267 +27,32 @@ 4 - - - - 0 - 0 - + + + QFrame::NoFrame - - Java Settings + + QFrame::Plain - - - - - - 0 - 0 - - - - - - - - Open JDK download URL in the system's browser. - - - - - - - - 0 - 0 - - - - JDK location: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - - - - - - - Android Settings - - - - - - - 0 - 0 - - - - Android SDK location: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Automatically download Android SDK Tools to selected location. - - - - - - - - - - Open Android SDK download URL in the system's browser. - - - - - - - Open Android NDK download URL in the system's browser. - - - - - - - - - - - - - - - - Android NDK list: - - - - - - - QAbstractScrollArea::AdjustToContents - - - QListView::Adjust - - - 0 - - - false - - - - - - - - - true - - - - 0 - 0 - - - - Add the selected custom NDK. The toolchains and debuggers will be created automatically. - - - Add... - - - - - - - false - - - - 0 - 0 - - - - Remove the selected NDK if it has been added manually. - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - Android OpenSSL settings - - - - - - - 0 - 0 - - - - OpenSSL .pri location: - - - - - - - Select the path of the prebuilt OpenSSL binaries. - - - - - - - Automatically download OpenSSL prebuilt libraries. If the automatic download fails, the download URL will be opened in the system's browser for manual download. - - - - - - - - - - - - - - - - - 0 - 0 - - - - Automatically create kits for Android tool chains - - - true - - - - - - + 0 - - - AVD Manager - - + + true + + + + + 0 + 0 + 1123 + 818 + + + + false + + 0 @@ -301,155 +66,433 @@ 0 - + + + + 0 + 0 + + + + Java Settings + + + + + + + 0 + 0 + + + + + + + + Open JDK download URL in the system's browser. + + + + + + + + 0 + 0 + + + + JDK location: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + + + + Android Settings + + + + + + + 0 + 0 + + + + Android SDK location: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Automatically download Android SDK Tools to selected location. + + + + + + + + + + Open Android SDK download URL in the system's browser. + + + + + + + Open Android NDK download URL in the system's browser. + + + + + + + + + + + + + + + + Android NDK list: + + + + + + + QAbstractScrollArea::AdjustToContents + + + QListView::Adjust + + + 0 + + + false + + + + + + + + + true + + + + 0 + 0 + + + + Add the selected custom NDK. The toolchains and debuggers will be created automatically. + + + Add... + + + + + + + false + + + + 0 + 0 + + + + Remove the selected NDK if it has been added manually. + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Android OpenSSL settings + + + + + + + 0 + 0 + + + + OpenSSL .pri location: + + + + + + + Select the path of the prebuilt OpenSSL binaries. + + + + + + + Automatically download OpenSSL prebuilt libraries. If the automatic download fails, the download URL will be opened in the system's browser for manual download. + + + + + + + + + + + + + + - + 0 0 - - QAbstractItemView::SingleSelection + + Automatically create kits for Android tool chains - - QAbstractItemView::SelectRows + + true - - Qt::ElideMiddle - - - false - - - false - - - - - - System/data partition size: + + + 0 + + + + AVD Manager + + + + 0 - - - - - - - 0 - 0 - + + 0 - - Mb + + 0 - - 99999 + + 0 - - 1024 - - - - - - - false - - - - 0 - 0 - - - - Start... - - - - - - - Refresh List - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 0 - 8 - - - - - - - - - 0 - 0 - - - - Add... - - - - - - - false - - - - 0 - 0 - - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Native AVD Manager... - - - - + + + + + 0 + 0 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + Qt::ElideMiddle + + + false + + + false + + + + + + + + + System/data partition size: + + + + + + + + 0 + 0 + + + + Mb + + + 99999 + + + 1024 + + + + + + + false + + + + 0 + 0 + + + + Start... + + + + + + + Refresh List + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 0 + 8 + + + + + + + + + 0 + 0 + + + + Add... + + + + + + + false + + + + 0 + 0 + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Native AVD Manager... + + + + + + + + + + SDK Manager + + + - - - SDK Manager - - diff --git a/src/plugins/autotest/autotestunittests.cpp b/src/plugins/autotest/autotestunittests.cpp index 812dd1fd557..9a70fb2fdce 100644 --- a/src/plugins/autotest/autotestunittests.cpp +++ b/src/plugins/autotest/autotestunittests.cpp @@ -245,6 +245,7 @@ void AutoTestUnitTests::testCodeParserBoostTest() QSKIP("This test needs boost - set BOOST_INCLUDE_DIR (or have it installed)"); QFETCH(QString, projectFilePath); + QFETCH(QString, extension); CppTools::Tests::ProjectOpenerAndCloser projectManager; CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true); QVERIFY(projectInfo.isValid()); @@ -256,14 +257,23 @@ void AutoTestUnitTests::testCodeParserBoostTest() QCOMPARE(m_model->boostTestNamesCount(), 5); - QMultiMap 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 + QString basePath; + if (auto project = projectInfo.project()) + basePath = project->projectFilePath().toFileInfo().absolutePath(); + QVERIFY(!basePath.isEmpty()); - QMultiMap foundNamesAndSets = m_model->boostTestSuitesAndTests(); + QMap expectedSuitesAndTests; + + auto pathConstructor = [basePath, extension](const QString &name, const QString &subPath) { + return QString(name + '|' + basePath + subPath + extension); + }; + expectedSuitesAndTests.insert(pathConstructor("Master Test Suite", "/tests/deco/deco"), 2); // decorators w/o suite + expectedSuitesAndTests.insert(pathConstructor("Master Test Suite", "/tests/fix/fix"), 2); // fixtures + expectedSuitesAndTests.insert(pathConstructor("Master Test Suite", "/tests/params/params"), 3); // functions + expectedSuitesAndTests.insert(pathConstructor("Suite1", "/tests/deco/deco"), 4); + expectedSuitesAndTests.insert(pathConstructor("SuiteOuter", "/tests/deco/deco"), 5); // 2 sub suites + 3 tests + + QMap foundNamesAndSets = m_model->boostTestSuitesAndTests(); QCOMPARE(expectedSuitesAndTests.size(), foundNamesAndSets.size()); for (const QString &name : expectedSuitesAndTests.keys()) QCOMPARE(expectedSuitesAndTests.values(name), foundNamesAndSets.values(name)); @@ -279,10 +289,11 @@ void AutoTestUnitTests::testCodeParserBoostTest() void AutoTestUnitTests::testCodeParserBoostTest_data() { QTest::addColumn("projectFilePath"); + QTest::addColumn("extension"); QTest::newRow("simpleBoostTest") - << QString(m_tmpDir->path() + "/simple_boost/simple_boost.pro"); + << QString(m_tmpDir->path() + "/simple_boost/simple_boost.pro") << QString(".pro"); QTest::newRow("simpleBoostTestQbs") - << QString(m_tmpDir->path() + "/simple_boost/simple_boost.qbs"); + << QString(m_tmpDir->path() + "/simple_boost/simple_boost.qbs") << QString(".qbs"); } } // namespace Internal diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index 00bfafcadc7..c4d7510b505 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -611,13 +611,13 @@ int TestTreeModel::boostTestNamesCount() const return rootNode ? rootNode->childCount() : 0; } -QMultiMap TestTreeModel::boostTestSuitesAndTests() const +QMap TestTreeModel::boostTestSuitesAndTests() const { - QMultiMap result; + QMap result; if (TestTreeItem *rootNode = boostTestRootNode()) { rootNode->forFirstLevelChildren([&result](TestTreeItem *child) { - result.insert(child->name(), child->childCount()); + result.insert(child->name() + '|' + child->proFile(), child->childCount()); }); } return result; diff --git a/src/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h index ec84b43b0f7..7d64db73f06 100644 --- a/src/plugins/autotest/testtreemodel.h +++ b/src/plugins/autotest/testtreemodel.h @@ -76,7 +76,7 @@ public: int gtestNamesCount() const; QMultiMap gtestNamesAndSets() const; int boostTestNamesCount() const; - QMultiMap boostTestSuitesAndTests() const; + QMap boostTestSuitesAndTests() const; #endif void markAllForRemoval(); diff --git a/src/plugins/clangtools/CMakeLists.txt b/src/plugins/clangtools/CMakeLists.txt index 88b25830d7e..9831046b5f7 100644 --- a/src/plugins/clangtools/CMakeLists.txt +++ b/src/plugins/clangtools/CMakeLists.txt @@ -8,6 +8,7 @@ add_qtc_plugin(ClangTools CONDITION TARGET libclang AND TARGET yaml-cpp DEPENDS ClangSupport libclang yaml-cpp PLUGIN_DEPENDS Core Debugger CppTools ${TST_COMPONENT} + PLUGIN_RECOMMENDS CppEditor INCLUDES ${CLANG_INCLUDE_DIRS} SOURCES clangfileinfo.h diff --git a/src/plugins/clangtools/clangtools.qbs b/src/plugins/clangtools/clangtools.qbs index d25707c562d..07ec6201b12 100644 --- a/src/plugins/clangtools/clangtools.qbs +++ b/src/plugins/clangtools/clangtools.qbs @@ -18,6 +18,10 @@ QtcPlugin { Depends { name: "Qt.widgets" } + pluginRecommends: [ + "CppEditor" + ] + pluginTestDepends: [ "QbsProjectManager", "QmakeProjectManager", diff --git a/src/plugins/clangtools/clangtools_dependencies.pri b/src/plugins/clangtools/clangtools_dependencies.pri index 943ca179360..eaaaf295154 100644 --- a/src/plugins/clangtools/clangtools_dependencies.pri +++ b/src/plugins/clangtools/clangtools_dependencies.pri @@ -9,6 +9,8 @@ isEmpty(EXTERNAL_YAML_CPP_FOUND): QTC_LIB_DEPENDS += yaml-cpp QTC_PLUGIN_DEPENDS += \ debugger \ cpptools +QTC_PLUGIN_RECOMMENDS += \ + cppeditor QTC_TEST_DEPENDS += \ qbsprojectmanager \ qmakeprojectmanager diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp index 6d9e8b8aa55..eb1d73663ed 100644 --- a/src/plugins/clangtools/clangtoolsplugin.cpp +++ b/src/plugins/clangtools/clangtoolsplugin.cpp @@ -48,6 +48,8 @@ #include #include +#include + #include #include #include @@ -95,8 +97,16 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt d = new ClangToolsPluginPrivate; ActionManager::registerAction(d->clangTool.startAction(), Constants::RUN_ON_PROJECT); - ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(), - Constants::RUN_ON_CURRENT_FILE); + Command *cmd = ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(), + Constants::RUN_ON_CURRENT_FILE); + ActionContainer *mtoolscpp = ActionManager::actionContainer(CppTools::Constants::M_TOOLS_CPP); + if (mtoolscpp) + mtoolscpp->addAction(cmd); + + Core::ActionContainer *mcontext = Core::ActionManager::actionContainer( + CppEditor::Constants::M_CONTEXT); + if (mcontext) + mcontext->addAction(cmd, CppEditor::Constants::G_CONTEXT_FIRST); // TODO auto panelFactory = m_projectPanelFactoryInstance = new ProjectPanelFactory; panelFactory->setPriority(100); diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h index 4df974e1262..a6f3f9609f2 100644 --- a/src/plugins/cppeditor/cppeditorconstants.h +++ b/src/plugins/cppeditor/cppeditorconstants.h @@ -29,6 +29,7 @@ namespace CppEditor { namespace Constants { const char M_CONTEXT[] = "CppEditor.ContextMenu"; +const char G_CONTEXT_FIRST[] = "CppEditor.GFirst"; const char CPPEDITOR_ID[] = "CppEditor.C++Editor"; const char CPPEDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "C++ Editor"); const char SWITCH_DECLARATION_DEFINITION[] = "CppEditor.SwitchDeclarationDefinition"; diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index bb86ee5be78..1376843080b 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -174,6 +174,7 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err Context context(Constants::CPPEDITOR_ID); ActionContainer *contextMenu = ActionManager::createMenu(Constants::M_CONTEXT); + contextMenu->insertGroup(Core::Constants::G_DEFAULT_ONE, Constants::G_CONTEXT_FIRST); Command *cmd; ActionContainer *cppToolsMenu = ActionManager::actionContainer(CppTools::Constants::M_TOOLS_CPP); @@ -181,12 +182,12 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err cmd = ActionManager::command(CppTools::Constants::SWITCH_HEADER_SOURCE); cmd->setTouchBarText(tr("Header/Source", "text on macOS touch bar")); - contextMenu->addAction(cmd); + contextMenu->addAction(cmd, Constants::G_CONTEXT_FIRST); touchBar->addAction(cmd, Core::Constants::G_TOUCHBAR_NAVIGATION); cmd = ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR); cmd->setTouchBarText(tr("Follow", "text on macOS touch bar")); - contextMenu->addAction(cmd); + contextMenu->addAction(cmd, Constants::G_CONTEXT_FIRST); cppToolsMenu->addAction(cmd); touchBar->addAction(cmd, Core::Constants::G_TOUCHBAR_NAVIGATION); @@ -204,7 +205,7 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err cmd->setTouchBarText(tr("Decl/Def", "text on macOS touch bar")); connect(switchDeclarationDefinition, &QAction::triggered, this, &CppEditorPlugin::switchDeclarationDefinition); - contextMenu->addAction(cmd); + contextMenu->addAction(cmd, Constants::G_CONTEXT_FIRST); cppToolsMenu->addAction(cmd); touchBar->addAction(cmd, Core::Constants::G_TOUCHBAR_NAVIGATION); @@ -223,21 +224,21 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err cppToolsMenu->addAction(cmd); cmd = ActionManager::command(TextEditor::Constants::FIND_USAGES); - contextMenu->addAction(cmd); + contextMenu->addAction(cmd, Constants::G_CONTEXT_FIRST); cppToolsMenu->addAction(cmd); d->m_openTypeHierarchyAction = new QAction(tr("Open Type Hierarchy"), this); cmd = ActionManager::registerAction(d->m_openTypeHierarchyAction, Constants::OPEN_TYPE_HIERARCHY, context); cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? tr("Meta+Shift+T") : tr("Ctrl+Shift+T"))); connect(d->m_openTypeHierarchyAction, &QAction::triggered, this, &CppEditorPlugin::openTypeHierarchy); - contextMenu->addAction(cmd); + contextMenu->addAction(cmd, Constants::G_CONTEXT_FIRST); cppToolsMenu->addAction(cmd); d->m_openIncludeHierarchyAction = new QAction(tr("Open Include Hierarchy"), this); cmd = ActionManager::registerAction(d->m_openIncludeHierarchyAction, Constants::OPEN_INCLUDE_HIERARCHY, context); cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? tr("Meta+Shift+I") : tr("Ctrl+Shift+I"))); connect(d->m_openIncludeHierarchyAction, &QAction::triggered, this, &CppEditorPlugin::openIncludeHierarchy); - contextMenu->addAction(cmd); + contextMenu->addAction(cmd, Constants::G_CONTEXT_FIRST); cppToolsMenu->addAction(cmd); // Refactoring sub-menu @@ -256,19 +257,19 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err cppToolsMenu->addAction(cmd); // Update context in global context - cppToolsMenu->addSeparator(); + cppToolsMenu->addSeparator(Core::Constants::G_DEFAULT_THREE); d->m_reparseExternallyChangedFiles = new QAction(tr("Reparse Externally Changed Files"), this); cmd = ActionManager::registerAction(d->m_reparseExternallyChangedFiles, Constants::UPDATE_CODEMODEL); CppTools::CppModelManager *cppModelManager = CppTools::CppModelManager::instance(); connect(d->m_reparseExternallyChangedFiles, &QAction::triggered, cppModelManager, &CppTools::CppModelManager::updateModifiedSourceFiles); - cppToolsMenu->addAction(cmd); + cppToolsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE); - cppToolsMenu->addSeparator(); + cppToolsMenu->addSeparator(Core::Constants::G_DEFAULT_THREE); QAction *inspectCppCodeModel = new QAction(tr("Inspect C++ Code Model..."), this); cmd = ActionManager::registerAction(inspectCppCodeModel, Constants::INSPECT_CPP_CODEMODEL); cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? tr("Meta+Shift+F12") : tr("Ctrl+Shift+F12"))); connect(inspectCppCodeModel, &QAction::triggered, d, &CppEditorPluginPrivate::inspectCppCodeModel); - cppToolsMenu->addAction(cmd); + cppToolsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE); contextMenu->addSeparator(context); diff --git a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp index 9f0b648dc6d..5e94dee80cd 100644 --- a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp +++ b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp @@ -352,7 +352,8 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor data.insert(QLatin1String(CPP_CXXCOMPILERNAME), cxxCompilerName); } - if (tcC && tcCxx && cFileInfo.absolutePath() != cxxFileInfo.absolutePath()) { + if (tcC && tcCxx && !cCompilerPath.isEmpty() && !cxxCompilerPath.isEmpty() + && cFileInfo.absolutePath() != cxxFileInfo.absolutePath()) { Core::MessageManager::write(tr("C and C++ compiler paths differ. C compiler may not work."), Core::MessageManager::ModeSwitch); } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3d.qrc b/src/plugins/qmldesigner/components/edit3d/edit3d.qrc index c0456890cd5..69e7113f023 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3d.qrc +++ b/src/plugins/qmldesigner/components/edit3d/edit3d.qrc @@ -8,6 +8,10 @@ images/edit_light_off@2x.png images/edit_light_on.png images/edit_light_on@2x.png + images/grid_off.png + images/grid_off@2x.png + images/grid_on.png + images/grid_on@2x.png images/fit_selected.png images/fit_selected@2x.png images/move_off.png diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index d06e1b299cf..c8e1e222e54 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -101,12 +101,13 @@ void Edit3DView::renderImage3DChanged(const QImage &img) void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) { - const QString sceneKey = QStringLiteral("sceneInstanceId"); - const QString selectKey = QStringLiteral("groupSelect"); - const QString transformKey = QStringLiteral("groupTransform"); + const QString sceneKey = QStringLiteral("sceneInstanceId"); + const QString selectKey = QStringLiteral("selectionMode"); + const QString transformKey = QStringLiteral("transformMode"); const QString perspectiveKey = QStringLiteral("usePerspective"); const QString orientationKey = QStringLiteral("globalOrientation"); - const QString editLightKey = QStringLiteral("showEditLight"); + const QString editLightKey = QStringLiteral("showEditLight"); + const QString gridKey = QStringLiteral("showGrid"); if (sceneState.contains(sceneKey)) { qint32 newActiveScene = sceneState[sceneKey].value(); @@ -115,7 +116,7 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) } if (sceneState.contains(selectKey)) - m_selectionModeAction->action()->setChecked(sceneState[selectKey].toInt() == 0); + m_selectionModeAction->action()->setChecked(sceneState[selectKey].toInt() == 1); else m_selectionModeAction->action()->setChecked(false); @@ -135,14 +136,21 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) m_cameraModeAction->action()->setChecked(sceneState[perspectiveKey].toBool()); else m_cameraModeAction->action()->setChecked(false); + if (sceneState.contains(orientationKey)) m_orientationModeAction->action()->setChecked(sceneState[orientationKey].toBool()); else m_orientationModeAction->action()->setChecked(false); + if (sceneState.contains(editLightKey)) m_editLightAction->action()->setChecked(sceneState[editLightKey].toBool()); else m_editLightAction->action()->setChecked(false); + + if (sceneState.contains(gridKey)) + m_showGridAction->action()->setChecked(sceneState[gridKey].toBool()); + else + m_showGridAction->action()->setChecked(false); } void Edit3DView::modelAttached(Model *model) @@ -247,6 +255,12 @@ void Edit3DView::createEdit3DActions() QKeySequence(Qt::Key_U), true, false, Icons::EDIT3D_LIGHT_OFF.icon(), Icons::EDIT3D_LIGHT_ON.icon()); + m_showGridAction = new Edit3DAction( + QmlDesigner::Constants::EDIT3D_EDIT_SHOW_GRID, View3DActionCommand::ShowGrid, + QCoreApplication::translate("ShowGridAction", "Toggle grid visibility"), + QKeySequence(Qt::Key_G), true, true, Icons::EDIT3D_GRID_OFF.icon(), + Icons::EDIT3D_GRID_ON.icon()); + SelectionContextOperation resetTrigger = [this](const SelectionContext &) { setCurrentStateNode(rootModelNode()); resetPuppet(); @@ -270,6 +284,7 @@ void Edit3DView::createEdit3DActions() m_leftActions << m_cameraModeAction; m_leftActions << m_orientationModeAction; m_leftActions << m_editLightAction; + m_leftActions << m_showGridAction; m_rightActions << m_resetAction; } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index 5835c89b325..d1646470b75 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -87,6 +87,7 @@ private: Edit3DAction *m_cameraModeAction = nullptr; Edit3DAction *m_orientationModeAction = nullptr; Edit3DAction *m_editLightAction = nullptr; + Edit3DAction *m_showGridAction = nullptr; Edit3DAction *m_resetAction = nullptr; }; diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_off.png b/src/plugins/qmldesigner/components/edit3d/images/grid_off.png new file mode 100644 index 00000000000..4c355f70a89 Binary files /dev/null and b/src/plugins/qmldesigner/components/edit3d/images/grid_off.png differ diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_off@2x.png b/src/plugins/qmldesigner/components/edit3d/images/grid_off@2x.png new file mode 100644 index 00000000000..88db6b9badd Binary files /dev/null and b/src/plugins/qmldesigner/components/edit3d/images/grid_off@2x.png differ diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_on.png b/src/plugins/qmldesigner/components/edit3d/images/grid_on.png new file mode 100644 index 00000000000..4c355f70a89 Binary files /dev/null and b/src/plugins/qmldesigner/components/edit3d/images/grid_on.png differ diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_on@2x.png b/src/plugins/qmldesigner/components/edit3d/images/grid_on@2x.png new file mode 100644 index 00000000000..88db6b9badd Binary files /dev/null and b/src/plugins/qmldesigner/components/edit3d/images/grid_on@2x.png differ diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp index b50322b4bb2..37f3acd4aa4 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp @@ -28,6 +28,7 @@ #include "rewriterview.h" #include "model.h" +#include "puppetcreator.h" #include #include @@ -84,44 +85,14 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles, parseFiles(inputFiles, options, extToImportOptionsMap); if (!isCancelled()) { - // Don't allow cancel anymore as existing asset overwrites are not trivially recoverable. - // Also, on Windows at least you can't delete a subdirectory of a watched directory, - // so complete rollback is no longer possible in any case. - emit importNearlyFinished(); - - copyImportedFiles(); - - auto doc = QmlDesignerPlugin::instance()->currentDesignDocument(); - Model *model = doc ? doc->currentModel() : nullptr; - if (model && !m_importFiles.isEmpty()) { - const QString progressTitle = tr("Updating data model."); + // Wait for icon generation processes to finish + if (m_qmlPuppetProcesses.isEmpty()) { + finalizeQuick3DImport(); + } else { + m_qmlPuppetCount = m_qmlPuppetProcesses.size(); + const QString progressTitle = tr("Generating icons."); addInfo(progressTitle); notifyProgress(0, progressTitle); - - // Trigger underlying qmljs snapshot update by making a non-change to the doc - model->rewriterView()->textModifier()->replace(0, 0, {}); - - // There is a inbuilt delay before rewriter change actually updates the data model, - // so we need to wait for a moment to allow the change to take effect. - // Otherwise subsequent subcomponent manager update won't detect new imports properly. - QTimer *timer = new QTimer(parent()); - static int counter; - counter = 0; - timer->callOnTimeout([this, timer, progressTitle, doc]() { - if (!isCancelled()) { - notifyProgress(++counter * 10, progressTitle); - if (counter >= 10) { - doc->updateSubcomponentManager(); - timer->stop(); - notifyFinished(); - } - } else { - timer->stop(); - } - }); - timer->start(100); - } else { - notifyFinished(); } } #else @@ -208,6 +179,26 @@ QHash ItemLibraryAssetImporter::supportedExtensions() cons #endif } +void ItemLibraryAssetImporter::processFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + Q_UNUSED(exitCode) + Q_UNUSED(exitStatus) + + auto process = qobject_cast(sender()); + if (process) { + m_qmlPuppetProcesses.remove(process); + process->deleteLater(); + const QString progressTitle = tr("Generating icons."); + if (m_qmlPuppetProcesses.isEmpty()) { + notifyProgress(100, progressTitle); + finalizeQuick3DImport(); + } else { + notifyProgress(int(100. * (1. - double(m_qmlPuppetCount) / double(m_qmlPuppetProcesses.size()))), + progressTitle); + } + } +} + void ItemLibraryAssetImporter::notifyFinished() { m_isImporting = false; @@ -224,6 +215,9 @@ void ItemLibraryAssetImporter::reset() m_tempDir = new QTemporaryDir; m_importFiles.clear(); m_overwrittenImports.clear(); + qDeleteAll(m_qmlPuppetProcesses); + m_qmlPuppetProcesses.clear(); + m_qmlPuppetCount = 0; #endif } @@ -307,6 +301,14 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar return; } + QHash assetFiles; + const int outDirPathSize = outDir.path().size(); + auto insertAsset = [&](const QString &filePath) { + QString targetPath = filePath.mid(outDirPathSize); + targetPath.prepend(targetDirPath); + assetFiles.insert(filePath, targetPath); + }; + // Generate qmldir file if importer doesn't already make one QString qmldirFileName = outDir.absoluteFilePath(QStringLiteral("qmldir")); if (!QFileInfo(qmldirFileName).exists()) { @@ -349,8 +351,6 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar int nlIdx = content.lastIndexOf('\n', braceIdx); QByteArray rootItem = content.mid(nlIdx, braceIdx - nlIdx).trimmed(); if (rootItem == "Node") { // a 3D object - QFile::copy(":/ItemLibrary/images/item-3D_model-icon.png", iconFileName); - QFile::copy(":/ItemLibrary/images/item-3D_model-icon@2x.png", iconFileName2x); // create hints file with proper hints QFile file(outDir.path() + '/' + fi.baseName() + ".hints"); file.open(QIODevice::WriteOnly | QIODevice::Text); @@ -359,9 +359,14 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar out << "canBeDroppedInFormEditor: false" << endl; out << "canBeDroppedInView3D: true" << endl; file.close(); - } else { - QFile::copy(":/ItemLibrary/images/item-default-icon.png", iconFileName); - QFile::copy(":/ItemLibrary/images/item-default-icon@2x.png", iconFileName2x); + } + QString outIconSource = QString::fromUtf8(content); + if (generateComponentIcon(24, iconFileName, qmlIt.filePath())) { + // Since icon is generated by external process, the file won't be + // ready for asset gathering below, so assume its generation succeeds + // and add it now. + insertAsset(iconFileName); + insertAsset(iconFileName2x); } } } @@ -375,15 +380,10 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar } // Gather all generated files - const int outDirPathSize = outDir.path().size(); QDirIterator dirIt(outDir.path(), QDir::Files, QDirIterator::Subdirectories); - QHash assetFiles; while (dirIt.hasNext()) { dirIt.next(); - const QString filePath = dirIt.filePath(); - QString targetPath = filePath.mid(outDirPathSize); - targetPath.prepend(targetDirPath); - assetFiles.insert(filePath, targetPath); + insertAsset(dirIt.filePath()); } // Copy the original asset into a subdirectory @@ -428,10 +428,12 @@ void ItemLibraryAssetImporter::copyImportedFiles() // by filesystem watchers. QHash::const_iterator it = assetFiles.begin(); while (it != assetFiles.end()) { - QDir targetDir = QFileInfo(it.value()).dir(); - if (!targetDir.exists()) - targetDir.mkpath(QStringLiteral(".")); - QFile::copy(it.key(), it.value()); + if (QFileInfo(it.key()).exists()) { + QDir targetDir = QFileInfo(it.value()).dir(); + if (!targetDir.exists()) + targetDir.mkpath("."); + QFile::copy(it.key(), it.value()); + } ++it; } notifyProgress((100 * ++counter) / m_importFiles.size(), progressTitle); @@ -461,6 +463,79 @@ bool ItemLibraryAssetImporter::confirmAssetOverwrite(const QString &assetName) QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes; } +bool ItemLibraryAssetImporter::generateComponentIcon(int size, const QString &iconFile, + const QString &iconSource) +{ + auto doc = QmlDesignerPlugin::instance()->currentDesignDocument(); + Model *model = doc ? doc->currentModel() : nullptr; + + if (model) { + PuppetCreator puppetCreator(doc->currentTarget(), model); + puppetCreator.createQml2PuppetExecutableIfMissing(); + QStringList puppetArgs; + puppetArgs << "--rendericon" << QString::number(size) << iconFile << iconSource; + QProcess *process = puppetCreator.createPuppetProcess( + "custom", {}, this, "", SLOT(processFinished(int, QProcess::ExitStatus)), puppetArgs); + + if (process->waitForStarted(5000)) { + connect(process, QOverload::of(&QProcess::finished), + process, &QProcess::deleteLater); + m_qmlPuppetProcesses << process; + return true; + } else { + delete process; + } + } + return false; +} + +void ItemLibraryAssetImporter::finalizeQuick3DImport() +{ +#ifdef IMPORT_QUICK3D_ASSETS + if (!isCancelled()) { + // Don't allow cancel anymore as existing asset overwrites are not trivially recoverable. + // Also, on Windows at least you can't delete a subdirectory of a watched directory, + // so complete rollback is no longer possible in any case. + emit importNearlyFinished(); + + copyImportedFiles(); + + auto doc = QmlDesignerPlugin::instance()->currentDesignDocument(); + Model *model = doc ? doc->currentModel() : nullptr; + if (model && !m_importFiles.isEmpty()) { + const QString progressTitle = tr("Updating data model."); + addInfo(progressTitle); + notifyProgress(0, progressTitle); + + // Trigger underlying qmljs snapshot update by making a non-change to the doc + model->rewriterView()->textModifier()->replace(0, 0, {}); + + // There is an inbuilt delay before rewriter change actually updates the data model, + // so we need to wait for a moment to allow the change to take effect. + // Otherwise subsequent subcomponent manager update won't detect new imports properly. + QTimer *timer = new QTimer(parent()); + static int counter; + counter = 0; + timer->callOnTimeout([this, timer, progressTitle, doc]() { + if (!isCancelled()) { + notifyProgress(++counter * 10, progressTitle); + if (counter >= 10) { + doc->updateSubcomponentManager(); + timer->stop(); + notifyFinished(); + } + } else { + timer->stop(); + } + }); + timer->start(100); + } else { + notifyFinished(); + } + } +#endif +} + bool ItemLibraryAssetImporter::isCancelled() const { keepUiAlive(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h index 67b36c6e72b..4bdccad6af9 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "import.h" @@ -72,6 +73,9 @@ signals: void importNearlyFinished() const; void importFinished(); +private slots: + void processFinished(int exitCode, QProcess::ExitStatus exitStatus); + private: void notifyFinished(); void reset(); @@ -83,6 +87,8 @@ private: void notifyProgress(int value, const QString &text) const; void keepUiAlive() const; bool confirmAssetOverwrite(const QString &assetName); + bool generateComponentIcon(int size, const QString &iconFile, const QString &iconSource); + void finalizeQuick3DImport(); #ifdef IMPORT_QUICK3D_ASSETS QScopedPointer m_quick3DAssetImporter; @@ -93,5 +99,7 @@ private: bool m_cancelled = false; QString m_importPath; QTemporaryDir *m_tempDir = nullptr; + QSet m_qmlPuppetProcesses; + int m_qmlPuppetCount = 0; }; } // QmlDesigner diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.cpp index c18a486fda8..5a60dd1eb78 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.cpp @@ -39,7 +39,6 @@ ItemLibrarySectionModel::ItemLibrarySectionModel(QObject *parent) : ItemLibrarySectionModel::~ItemLibrarySectionModel() { - clearItems(); } int ItemLibrarySectionModel::rowCount(const QModelIndex &) const @@ -73,12 +72,6 @@ QHash ItemLibrarySectionModel::roleNames() const return m_roleNames; } -void ItemLibrarySectionModel::clearItems() -{ - beginResetModel(); - endResetModel(); -} - void ItemLibrarySectionModel::addItem(ItemLibraryItem *element) { m_itemList.append(element); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.h index 6d543b5afae..6e1771a52f0 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarysectionmodel.h @@ -45,8 +45,6 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash roleNames() const override; - void clearItems(); - void addItem(ItemLibraryItem *item); const QList &items() const; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp index 90c0a2f28f1..cad7189698c 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp @@ -98,15 +98,14 @@ void ItemLibraryView::setResourcePath(const QString &resourcePath) void ItemLibraryView::documentMessagesChanged(const QList &errors, const QList &) { if (m_hasErrors && errors.isEmpty()) - /* For some reason we have to call update from the event loop */ - QTimer::singleShot(0, m_widget, &ItemLibraryWidget::updateModel); + updateImports(); m_hasErrors = !errors.isEmpty(); } void ItemLibraryView::updateImports() { - m_widget->updateModel(); + m_widget->delayedUpdateModel(); } } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 69d431582a0..378f1e897ae 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -293,7 +293,11 @@ void ItemLibraryWidget::setSearchFilter(const QString &searchFilter) void ItemLibraryWidget::delayedUpdateModel() { - m_compressionTimer.start(); + static bool disableTimer = DesignerSettings::getValue(DesignerSettingsKey::DISABLE_ITEM_LIBRARY_UPDATE_TIMER).toBool(); + if (disableTimer) + updateModel(); + else + m_compressionTimer.start(); } void ItemLibraryWidget::setModel(Model *model) diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index b7dd9d10820..2bb6b5aded8 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -551,20 +551,46 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i NodeAbstractProperty targetProperty; bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); - if (foundTarget) { - const QString imageFileName = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); - const QmlItemNode newQmlItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imageFileName, QPointF(), targetProperty); + ModelNode targetNode(modelNodeForIndex(rowModelIndex)); - if (newQmlItemNode.isValid()) { - QList newModelNodeList; - newModelNodeList.append(newQmlItemNode); + const QString imageSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); // absolute path + const QString imageFileName = imageSource.mid(imageSource.lastIndexOf('/') + 1); + ModelNode newModelNode; - moveNodesInteractive(targetProperty, newModelNodeList, targetRowNumber); + if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")) { + // if dropping an image on a default material, create a texture instead of image + m_view->executeInTransaction("QmlItemNode::createQmlItemNode", [&] { + // create a texture item lib + ItemLibraryEntry itemLibraryEntry; + itemLibraryEntry.setName("Texture"); + itemLibraryEntry.setType("QtQuick3D.Texture", 1, 0); + + // set texture source + PropertyName prop = "source"; + QString type = "QUrl"; + QVariant val = imageFileName; + itemLibraryEntry.addProperty(prop, type, val); + + // create a texture + newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, targetProperty, false); + + // set the texture to parent material's diffuseMap property + // TODO: allow the user to choose which map property to set the texture for + targetNode.bindingProperty("diffuseMap").setExpression(newModelNode.validId()); + }); + } else if (targetNode.isSubclassOf("QtQuick3D.Texture")) { + // if dropping an image on a texture, set the texture source + targetNode.variantProperty("source").setValue(imageFileName); + } else { + // create an image + newModelNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imageSource , QPointF(), targetProperty); } - if (newQmlItemNode.isValid()) - m_view->selectModelNode(newQmlItemNode.modelNode()); + if (newModelNode.isValid()) { + moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber); + m_view->setSelectedModelNode(newModelNode); + } } } diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp index 3ec61f9cabb..515b73ed2cb 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp @@ -265,7 +265,8 @@ bool PropertyEditorValue::isTranslated() const bool PropertyEditorValue::isAvailable() const { - const QList mcuProperties = {"layer", "opacity", "rotation", "scale", "transformOrigin", "smooth", "antialiasing", "border"}; + const QList mcuProperties = {"layer", "opacity", "rotation", "scale", "gradient", + "transformOrigin", "smooth", "antialiasing", "border"}; const QList list = name().split('.'); const QByteArray pureName = list.first(); diff --git a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h index 65f3e96aa08..aae262686ae 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h @@ -94,13 +94,11 @@ public: const Position &position, QmlVisualNode parentQmlItemNode); - - - static QmlObjectNode createQmlObjectNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, const Position &position, - NodeAbstractProperty parentproperty); + NodeAbstractProperty parentProperty, + bool createInTransaction = true); static QmlVisualNode createQml3DNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp index 70cf975df76..0688ebde6e6 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp @@ -179,7 +179,8 @@ QProcess *PuppetCreator::createPuppetProcess(const QString &puppetMode, const QString &socketToken, QObject *handlerObject, const char *outputSlot, - const char *finishSlot) const + const char *finishSlot, + const QStringList &customOptions) const { return puppetProcess(qml2PuppetPath(m_availablePuppetType), qmlPuppetDirectory(m_availablePuppetType), @@ -187,7 +188,8 @@ QProcess *PuppetCreator::createPuppetProcess(const QString &puppetMode, socketToken, handlerObject, outputSlot, - finishSlot); + finishSlot, + customOptions); } @@ -197,7 +199,8 @@ QProcess *PuppetCreator::puppetProcess(const QString &puppetPath, const QString &socketToken, QObject *handlerObject, const char *outputSlot, - const char *finishSlot) const + const char *finishSlot, + const QStringList &customOptions) const { auto puppetProcess = new QProcess; puppetProcess->setObjectName(puppetMode); @@ -230,7 +233,14 @@ QProcess *PuppetCreator::puppetProcess(const QString &puppetPath, if (forceFreeType) forceFreeTypeOption = "-platform windows:fontengine=freetype"; - puppetProcess->start(puppetPath, {socketToken, puppetMode, "-graphicssystem raster", forceFreeTypeOption }); + if (puppetMode == "custom") { + QStringList args = customOptions; + args << "-graphicssystem raster"; + args << forceFreeTypeOption; + puppetProcess->start(puppetPath, args); + } else { + puppetProcess->start(puppetPath, {socketToken, puppetMode, "-graphicssystem raster", forceFreeTypeOption }); + } #ifndef QMLDESIGNER_TEST QString debugPuppet = m_designerSettings.value(DesignerSettingsKey:: diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.h b/src/plugins/qmldesigner/designercore/instances/puppetcreator.h index d11a798a319..bafea8fa3e6 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.h +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.h @@ -57,7 +57,8 @@ public: const QString &socketToken, QObject *handlerObject, const char *outputSlot, - const char *finishSlot) const; + const char *finishSlot, + const QStringList &customOptions = {}) const; void setQrcMappingString(const QString qrcMapping); @@ -87,7 +88,8 @@ protected: const QString &socketToken, QObject *handlerObject, const char *outputSlot, - const char *finishSlot) const; + const char *finishSlot, + const QStringList &customOptions) const; QProcessEnvironment processEnvironment() const; diff --git a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp index abd64928527..7b3059247f3 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp @@ -225,6 +225,10 @@ QDataStream& operator<<(QDataStream& stream, const ItemLibraryEntry &itemLibrary QDataStream& operator>>(QDataStream& stream, ItemLibraryEntry &itemLibraryEntry) { + // Clear containers so that we don't simply append to them in case the object is reused + itemLibraryEntry.m_data->hints.clear(); + itemLibraryEntry.m_data->properties.clear(); + stream >> itemLibraryEntry.m_data->name; stream >> itemLibraryEntry.m_data->typeName; stream >> itemLibraryEntry.m_data->majorVersion; diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index fe2e2fd49e8..ab9acc25e8c 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -243,11 +243,12 @@ static QmlObjectNode createQmlObjectNodeFromSource(AbstractView *view, QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, const Position &position, - NodeAbstractProperty parentproperty) + NodeAbstractProperty parentProperty, + bool createInTransaction) { QmlObjectNode newQmlObjectNode; - view->executeInTransaction("QmlItemNode::createQmlItemNode", [=, &newQmlObjectNode, &parentproperty](){ + auto createNodeFunc = [=, &newQmlObjectNode, &parentProperty]() { NodeMetaInfo metaInfo = view->model()->metaInfo(itemLibraryEntry.typeName()); int minorVersion = metaInfo.minorVersion(); @@ -274,8 +275,8 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, newQmlObjectNode = createQmlObjectNodeFromSource(view, itemLibraryEntry.qmlSource(), position); } - if (parentproperty.isValid()) - parentproperty.reparentHere(newQmlObjectNode); + if (parentProperty.isValid()) + parentProperty.reparentHere(newQmlObjectNode); if (!newQmlObjectNode.isValid()) return; @@ -289,7 +290,12 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, newQmlObjectNode.modelNode().variantProperty(propertyBindingEntry.first).setEnumeration(propertyBindingEntry.second.toUtf8()); Q_ASSERT(newQmlObjectNode.isValid()); - }); + }; + + if (createInTransaction) + view->executeInTransaction("QmlItemNode::createQmlItemNode", createNodeFunc); + else + createNodeFunc(); Q_ASSERT(newQmlObjectNode.isValid()); diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index ec4dc1f7e58..4d25edb8bc0 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -67,6 +67,7 @@ const char STANDALONE_MODE[] = "StandAloneMode"; const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView"; const char SIMPLE_COLOR_PALETTE_CONTENT[] = "SimpleColorPaletteContent"; const char ALWAYS_DESIGN_MODE[] = "AlwaysDesignMode"; +const char DISABLE_ITEM_LIBRARY_UPDATE_TIMER[] = "DisableItemLibraryUpdateTimer"; } class DesignerSettings : public QHash diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index 2cae7208c5d..0e657f777c0 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -398,19 +398,20 @@ void DocumentManager::findPathToIsoProFile(bool *iconResourceFileAlreadyExists, qCDebug(documentManagerLog) << "Checking" << node->displayName() << "(" << node << ")"; if (node->isVirtualFolderType() && node->displayName() == "Resources") { - auto virtualFolderNode = dynamic_cast(node); + ProjectExplorer::FolderNode *virtualFolderNode = node->asFolderNode(); + if (QTC_GUARD(virtualFolderNode)) { + for (int subFolderIndex = 0; subFolderIndex < virtualFolderNode->folderNodes().size() && !iconQrcFileNode; ++subFolderIndex) { + ProjectExplorer::FolderNode *subFolderNode = virtualFolderNode->folderNodes().at(subFolderIndex); - for (int subFolderIndex = 0; subFolderIndex < virtualFolderNode->folderNodes().size() && !iconQrcFileNode; ++subFolderIndex) { - ProjectExplorer::FolderNode *subFolderNode = virtualFolderNode->folderNodes().at(subFolderIndex); + qCDebug(documentManagerLog) << "Checking if" << subFolderNode->displayName() << "(" + << subFolderNode << ") is" << isoIconsQrcFile; - qCDebug(documentManagerLog) << "Checking if" << subFolderNode->displayName() << "(" - << subFolderNode << ") is" << isoIconsQrcFile; + if (subFolderNode->isFolderNodeType() && subFolderNode->displayName() == isoIconsQrcFile) { + qCDebug(documentManagerLog) << "Found" << isoIconsQrcFile << "in" << virtualFolderNode->filePath(); - if (subFolderNode->isFolderNodeType() && subFolderNode->displayName() == isoIconsQrcFile) { - qCDebug(documentManagerLog) << "Found" << isoIconsQrcFile << "in" << virtualFolderNode->filePath(); - - iconQrcFileNode = subFolderNode; - *resourceFileProPath = iconQrcFileNode->parentProjectNode()->filePath().toString(); + iconQrcFileNode = subFolderNode; + *resourceFileProPath = iconQrcFileNode->parentProjectNode()->filePath().toString(); + } } } } diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index b334dced8b6..0f5b06c5161 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -55,14 +55,15 @@ const char FORMEDITOR_NO_SNAPPING[] = "QmlDesigner.FormEditor.NoSnapping"; const char FORMEDITOR_NO_SNAPPING_AND_ANCHORING[] = "QmlDesigner.FormEditor.NoSnappingAndAnchoring"; const char FORMEDITOR_NO_SHOW_BOUNDING_RECTANGLE[] = "QmlDesigner.FormEditor.ShowBoundingRectangle"; const char EDIT3D_SELECTION_MODE[] = "QmlDesigner.Editor3D.SelectionModeToggle"; -const char EDIT3D_MOVE_TOOL[] = "QmlDesigner.Editor3D.MoveTool"; -const char EDIT3D_ROTATE_TOOL[] = "QmlDesigner.Editor3D.RotateTool"; -const char EDIT3D_SCALE_TOOL[] = "QmlDesigner.Editor3D.ScaleTool"; -const char EDIT3D_FIT_SELECTED[] = "QmlDesigner.Editor3D.FitSelected"; -const char EDIT3D_EDIT_CAMERA[] = "QmlDesigner.Editor3D.EditCameraToggle"; -const char EDIT3D_ORIENTATION[] = "QmlDesigner.Editor3D.OrientationToggle"; -const char EDIT3D_EDIT_LIGHT[] = "QmlDesigner.Editor3D.EditLightToggle"; -const char EDIT3D_RESET_VIEW[] = "QmlDesigner.Editor3D.ResetView"; +const char EDIT3D_MOVE_TOOL[] = "QmlDesigner.Editor3D.MoveTool"; +const char EDIT3D_ROTATE_TOOL[] = "QmlDesigner.Editor3D.RotateTool"; +const char EDIT3D_SCALE_TOOL[] = "QmlDesigner.Editor3D.ScaleTool"; +const char EDIT3D_FIT_SELECTED[] = "QmlDesigner.Editor3D.FitSelected"; +const char EDIT3D_EDIT_CAMERA[] = "QmlDesigner.Editor3D.EditCameraToggle"; +const char EDIT3D_ORIENTATION[] = "QmlDesigner.Editor3D.OrientationToggle"; +const char EDIT3D_EDIT_LIGHT[] = "QmlDesigner.Editor3D.EditLightToggle"; +const char EDIT3D_EDIT_SHOW_GRID[] = "QmlDesigner.Editor3D.ToggleGrid"; +const char EDIT3D_RESET_VIEW[] = "QmlDesigner.Editor3D.ResetView"; const char QML_DESIGNER_SUBFOLDER[] = "/designer/"; const char QUICK_3D_ASSETS_FOLDER[] = "/Quick3DAssets"; diff --git a/src/plugins/qmldesigner/qmldesignericons.h b/src/plugins/qmldesigner/qmldesignericons.h index 146565133d7..34c9061072e 100644 --- a/src/plugins/qmldesigner/qmldesignericons.h +++ b/src/plugins/qmldesigner/qmldesignericons.h @@ -51,6 +51,10 @@ const Utils::Icon EDIT3D_LIGHT_ON({ {QLatin1String(":/edit3d/images/edit_light_on.png"), Utils::Theme::IconsBaseColor}}); const Utils::Icon EDIT3D_LIGHT_OFF({ {QLatin1String(":/edit3d/images/edit_light_off.png"), Utils::Theme::IconsBaseColor}}); +const Utils::Icon EDIT3D_GRID_ON({ + {QLatin1String(":/edit3d/images/grid_on.png"), Utils::Theme::IconsBaseColor}}); +const Utils::Icon EDIT3D_GRID_OFF({ + {QLatin1String(":/edit3d/images/grid_off.png"), Utils::Theme::IconsBaseColor}}); const Utils::Icon EDIT3D_SELECTION_MODE_ON({ {QLatin1String(":/edit3d/images/select_group.png"), Utils::Theme::IconsBaseColor}}); const Utils::Icon EDIT3D_SELECTION_MODE_OFF({ diff --git a/src/shared/qbs b/src/shared/qbs index dcd57b60f8a..ee44dae4f53 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit dcd57b60f8a79a2ee9c46cb5fddf60846302d375 +Subproject commit ee44dae4f53d3c3fd16025c8d717f25084313070 diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index 94bc6a2fce5..cab493e9942 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -118,6 +118,12 @@ extend_qtc_executable(qml2puppet nodeinstanceserverinterface.cpp nodeinstanceserverinterface.h ) +extend_qtc_executable(qml2puppet + SOURCES_PREFIX "${SRCDIR}/qml2puppet/iconrenderer" + SOURCES + iconrenderer.cpp iconrenderer.h +) + extend_qtc_executable(qml2puppet SOURCES_PREFIX "${SRCDIR}/qml2puppet/instances" SOURCES diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs index 445ab2e867a..5ca88541b00 100644 --- a/src/tools/qml2puppet/qml2puppet.qbs +++ b/src/tools/qml2puppet/qml2puppet.qbs @@ -217,6 +217,8 @@ QtcTool { "editor3d/selectionboxgeometry.h", "editor3d/linegeometry.cpp", "editor3d/linegeometry.h", + "iconrenderer/iconrenderer.cpp", + "iconrenderer/iconrenderer.h", "qml2puppetmain.cpp", ] }