diff --git a/doc/qtcreator/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc b/doc/qtcreator/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
index 1e6956a449a..72836730372 100644
--- a/doc/qtcreator/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-from-qmlproject-to-pro.qdoc
@@ -31,6 +31,13 @@
can be built with CMake. You can open the \e CMakeLists.txt project file in
Qt Creator to continue developing the project.
+ \target wizard-template-note
+ \note Since \QDS 3.9.0, \QDS project wizard templates generate projects that
+ automatically checkout and build the Qt Quick Studio Components from
+ \l{https://code.qt.io/cgit/qt-labs/qtquickdesigner-components.git/} {Qt Code Review},
+ using CMake. To turn off this feature, use the option \e BUILD_QDS_COMPONENTS
+ in the CMake configuration.
+
\if defined(qtdesignstudio)
For more information, see \l{Designer-Developer Workflow}.
\else
@@ -149,10 +156,8 @@
\section1 Adding Qt Quick Designer Components to Qt Installations
- If you use Qt Quick Studio Components or Effects in your project, you have
- to check out and install the \e {Qt Quick Designer Components} module from
- \l{https://code.qt.io/cgit/qt-labs/qtquickdesigner-components.git/}
- {Qt Code Review}.
+ Since \QDS 3.9, the Qt Quick Studio Components module is installed by default
+ as part of the application. You can also install the module manually.
For example:
\list 1
diff --git a/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc b/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
index 1753da63f7b..146501328c2 100644
--- a/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
+++ b/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
@@ -32,8 +32,8 @@
your project as a fully working C++ application with developers.
If you add or remove QML files in \QDS, you have to regenerate the
- \e CMakeLists.txt project configuration file by selecting \uicontrol Build
- > \uicontrol Run > \uicontrol {Generate CMakeLists.txt Files}.
+ \e CMakeLists.txt project configuration file by selecting \uicontrol File
+ > \uicontrol {Export Project} > \uicontrol {Generate CMake Build Files}.
If you use Git, you can clone an example project
\l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/playground/AuroraCluster0}
@@ -99,6 +99,8 @@
This isn't mandatory.
\li Generate CMake files and C++ source files that are used to compile the application into
- an executable file by selecting \uicontrol Build > \uicontrol{Generate CMakeLists.txt files}.
+ an executable file by selecting \uicontrol File > \uicontrol {Export Project} >
+ \uicontrol {Generate CMake Build Files}.
+
\endlist
*/
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-setup.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-setup.qdoc
index 4d71150dcaf..33d130f3360 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-setup.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-setup.qdoc
@@ -10,11 +10,19 @@
\note \QBF is included in the
\l{https://www.qt.io/pricing}{\QDS Enterprise license}.
- \QBF is delivered with \QDS as a developer plugin that you can install to
- the Desktop version of Figma. To install the plugin, open the Plugin Manager
- of Figma and press the plus button to create a new plugin. Then choose the
- \e Manifest.json file that comes with \QDS.
+ You need both Figma and Qt accounts to use \QBF in \QDS.
+ To use \QBF in \QDS:
+ \list 1
+ \li Go to \l {https://www.figma.com/community/plugin/1167809465162924409/Qt-Bridge-for-Figma}
+ {\QBF plugin page}.
+ \li Select \uicontrol {Try it out}.
+ \li Select your logged in Figma account.
+ \li After the plugin loads, select \uicontrol Run.
+ \li Select \uicontrol Export, to get the \e {.qtbridge} file in your
+ local drive.
+ \li In \QDS, drag the file to the \uicontrol 2D, \uicontrol 3D, \uicontrol Assets,
+ or \uicontrol Navigator view in an open project .
+ \endlist
- You can launch the Figma plugin from \uicontrol Plugins >
- \uicontrol Development > \uicontrol {\QBF} in Figma.
+ You can launch the installed Figma plugin from \uicontrol Plugins > \uicontrol {\QBF} in Figma.
*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
index a1e35898812..1e426f011e1 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
@@ -24,9 +24,9 @@
set of files (icons, translation files, and so on) and you don't want
to run the risk of losing the files.
- To package your application, select \uicontrol Build >
- \uicontrol {Generate QRC Resource File}. Then select the
- files to package in the \uicontrol {Add Resources} dialog.
+ To package your application, select \uicontrol File >
+ \uicontrol {Export Project} > \uicontrol {Generate QRC Resource File}.
+ Then select the files to package in the \uicontrol {Add Resources} dialog.
\image studio-add-resources.png "Add Resources dialog"
@@ -44,10 +44,11 @@
\section1 Embedding Resources into Applications
- Alternatively, you can embedd the resources into your application by
- selecting \uicontrol Build > \uicontrol {Generate Deployable Package}.
- Select the location for the .qmlrc file, and then select the files to
- embedd in the \uicontrol {Add Resources} dialog.
+ Alternatively, you can embed the resources into your application by
+ selecting \uicontrol File > \uicontrol {Export Project} >
+ \uicontrol {Generate Deployable Package}. Select the location for
+ the .qmlrc file, and then select the files to embed in the
+ \uicontrol {Add Resources} dialog.
When you select \uicontrol OK, \QDS creates a resource collection file
(.qmlrc) in the location you selected.
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
index d6c24d4b2af..494bebd07cc 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
@@ -23,6 +23,7 @@ Image {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
+ hoverEnabled: true
onPressed: (mouse) => {
if (mouse.button === Qt.LeftButton)
@@ -31,4 +32,20 @@ Image {
root.showContextMenu()
}
}
+
+ ToolTip {
+ visible: mouseArea.containsMouse
+ // contentWidth is not calculated correctly by the toolTip (resulting in a wider tooltip than
+ // needed). Using a helper Text to calculate the correct width
+ contentWidth: helperText.width
+ bottomInset: -2
+ text: modelData.textureToolTip
+ delay: 1000
+
+ Text {
+ id: helperText
+ text: modelData.textureToolTip
+ visible: false
+ }
+ }
}
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml
index a28becff06b..2bbfff5223c 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetDelegate.qml
@@ -12,7 +12,7 @@ TreeViewDelegate {
required property Item assetsRoot
property bool hasChildWithDropHover: false
- property bool isHoveringDrop: false
+ property bool isHighlighted: false
readonly property string suffix: model.fileName.substr(-4)
readonly property bool isFont: root.suffix === ".ttf" || root.suffix === ".otf"
readonly property bool isEffect: root.suffix === ".qep"
@@ -26,7 +26,12 @@ TreeViewDelegate {
readonly property int __dirItemHeight: 21
implicitHeight: root.__isDirectory ? root.__dirItemHeight : root.__fileItemHeight
- implicitWidth: root.assetsView.width > 0 ? root.assetsView.width : 10
+ implicitWidth: {
+ if (root.assetsView.verticalScrollBar.scrollBarVisible)
+ return root.assetsView.width - root.indentation - root.assetsView.verticalScrollBar.width
+ else
+ return root.assetsView.width - root.indentation
+ }
leftMargin: root.__isDirectory ? 0 : thumbnailImage.width
@@ -54,17 +59,6 @@ TreeViewDelegate {
}
}
- onImplicitWidthChanged: {
- // a small hack, to fix a glitch: when resizing the width of the tree view,
- // the widths of the delegate items remain the same as before, unless we re-set
- // that width explicitly.
- var newWidth = root.implicitWidth - (root.assetsView.verticalScrollBar.scrollBarVisible
- ? root.assetsView.verticalScrollBar.width
- : 0)
- bg.width = newWidth
- bg.implicitWidth = newWidth
- }
-
onDepthChanged: {
if (root.depth > root.initialDepth && root.initialDepth >= 0)
root.depth = root.initialDepth
@@ -73,8 +67,10 @@ TreeViewDelegate {
background: Rectangle {
id: bg
+ width: root.implicitWidth
+
color: {
- if (root.__isDirectory && (root.isHoveringDrop || root.hasChildWithDropHover))
+ if (root.__isDirectory && (root.isHighlighted || root.hasChildWithDropHover))
return StudioTheme.Values.themeInteraction
if (!root.__isDirectory && root.assetsView.selectedAssets[root.__itemPath])
@@ -120,40 +116,6 @@ TreeViewDelegate {
}
}
- DropArea {
- id: treeDropArea
-
- enabled: true
- anchors.fill: parent
-
- onEntered: (drag) => {
- root.assetsRoot.updateDropExtFiles(drag)
- root.isHoveringDrop = drag.accepted && root.assetsRoot.dropSimpleExtFiles.length > 0
- if (root.isHoveringDrop)
- root.assetsView.startDropHoverOver(root.__currentRow)
- }
-
- onDropped: (drag) => {
- root.isHoveringDrop = false
- root.assetsView.endDropHover(root.__currentRow)
-
- let dirPath = root.__isDirectory
- ? model.filePath
- : assetsModel.parentDirPath(model.filePath);
-
- rootView.emitExtFilesDrop(root.assetsRoot.dropSimpleExtFiles,
- root.assetsRoot.dropComplexExtFiles,
- dirPath)
- }
-
- onExited: {
- if (root.isHoveringDrop) {
- root.isHoveringDrop = false
- root.assetsView.endDropHover(root.__currentRow)
- }
- }
- }
-
MouseArea {
id: mouseArea
@@ -247,6 +209,14 @@ TreeViewDelegate {
}
} // MouseArea
+ function getDirPath()
+ {
+ if (root.__isDirectory)
+ return model.filePath
+ else
+ return assetsModel.parentDirPath(model.filePath)
+ }
+
function __openContextMenuForCurrentRow()
{
let modelIndex = assetsModel.indexForPath(model.filePath)
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml
index 6dedaf79012..3337be90ef0 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml
@@ -183,4 +183,17 @@ StudioControls.Menu {
}
}
}
+
+ StudioControls.MenuItem {
+ text: qsTr("New Effect")
+ visible: assetsModel.canCreateEffects()
+
+ NewEffectDialog {
+ id: newEffectDialog
+ parent: root.assetsView
+ dirPath: root.__dirPath
+ }
+
+ onTriggered: newEffectDialog.open()
+ }
}
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsView.qml
index 782cca5ebc6..dcffab432be 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsView.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsView.qml
@@ -250,8 +250,12 @@ TreeView {
function startDropHoverOver(row)
{
let index = root.__modelIndex(row)
- if (assetsModel.isDirectory(index))
+ if (assetsModel.isDirectory(index)) {
+ let item = root.__getDelegateItemForIndex(index)
+ if (item)
+ item.isHighlighted = true
return
+ }
let parentItem = root.__getDelegateParentForIndex(index)
if (parentItem)
@@ -261,8 +265,12 @@ TreeView {
function endDropHover(row)
{
let index = root.__modelIndex(row)
- if (assetsModel.isDirectory(index))
+ if (assetsModel.isDirectory(index)) {
+ let item = root.__getDelegateItemForIndex(index)
+ if (item)
+ item.isHighlighted = false
return
+ }
let parentItem = root.__getDelegateParentForIndex(index)
if (parentItem)
@@ -292,6 +300,12 @@ TreeView {
return root.itemAtCell(parentCell)
}
+ function __getDelegateItemForIndex(index)
+ {
+ let cell = root.cellAtIndex(index)
+ return root.itemAtCell(cell)
+ }
+
function __modelIndex(row)
{
// The modelIndex() function exists since 6.3. In Qt 6.3, this modelIndex() function was a
@@ -303,6 +317,76 @@ TreeView {
return root.modelIndex(row, 0)
}
+ DropArea {
+ id: dropArea
+ enabled: true
+ anchors.fill: parent
+
+ property bool __isHoveringDrop: false
+ property int __rowHoveringOver: -1
+
+ function __rowAndItem(drag)
+ {
+ let pos = dropArea.mapToItem(root, drag.x, drag.y)
+ let cell = root.cellAtPos(pos.x, pos.y, true)
+ let item = root.itemAtCell(cell)
+
+ return [cell.y, item]
+ }
+
+ onEntered: (drag) => {
+ root.assetsRoot.updateDropExtFiles(drag)
+
+ let [row, item] = dropArea.__rowAndItem(drag)
+ dropArea.__isHoveringDrop = drag.accepted && root.assetsRoot.dropSimpleExtFiles.length > 0
+
+ if (item && dropArea.__isHoveringDrop)
+ root.startDropHoverOver(row)
+
+ dropArea.__rowHoveringOver = row
+ }
+
+ onDropped: (drag) => {
+ let [row, item] = dropArea.__rowAndItem(drag)
+
+ if (item) {
+ root.endDropHover(row)
+
+ let dirPath = item.getDirPath()
+
+ rootView.emitExtFilesDrop(root.assetsRoot.dropSimpleExtFiles,
+ root.assetsRoot.dropComplexExtFiles,
+ dirPath)
+ }
+
+ dropArea.__isHoveringDrop = false
+ dropArea.__rowHoveringOver = -1
+ }
+
+ onPositionChanged: (drag) => {
+ let [row, item] = dropArea.__rowAndItem(drag)
+
+ if (dropArea.__rowHoveringOver !== row && dropArea.__rowHoveringOver > -1) {
+ root.endDropHover(dropArea.__rowHoveringOver)
+
+ if (item)
+ root.startDropHoverOver(row)
+ }
+
+ dropArea.__rowHoveringOver = row
+ }
+
+ onExited: {
+ if (!dropArea.__isHoveringDrop || dropArea.__rowHoveringOver === -1)
+ return
+
+ root.endDropHover(dropArea.__rowHoveringOver)
+
+ dropArea.__isHoveringDrop = false
+ dropArea.__rowHoveringOver = -1
+ }
+ }
+
delegate: AssetDelegate {
assetsView: root
assetsRoot: root.assetsRoot
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/NewEffectDialog.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/NewEffectDialog.qml
new file mode 100644
index 00000000000..f57284e6782
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/NewEffectDialog.qml
@@ -0,0 +1,105 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
+
+Dialog {
+ id: root
+
+ title: qsTr("Create New Effect")
+ anchors.centerIn: parent
+ closePolicy: Popup.CloseOnEscape
+ modal: true
+
+ required property string dirPath
+ readonly property int __maxPath: 32
+
+ HelperWidgets.RegExpValidator {
+ id: effectNameValidator
+ regExp: /^[A-Z]\w[A-Za-z0-9_]*$/
+ }
+
+ ErrorDialog {
+ id: creationFailedDialog
+ title: qsTr("Could not create effect")
+ message: qsTr("An error occurred while trying to create the effect.")
+ }
+
+ contentItem: Column {
+ spacing: 2
+
+ Row {
+ Text {
+ text: qsTr("Effect name: ")
+ anchors.verticalCenter: parent.verticalCenter
+ color: StudioTheme.Values.themeTextColor
+ }
+
+ StudioControls.TextField {
+ id: effectName
+
+ actionIndicator.visible: false
+ translationIndicator.visible: false
+ validator: effectNameValidator
+
+ Keys.onEnterPressed: btnCreate.onClicked()
+ Keys.onReturnPressed: btnCreate.onClicked()
+ }
+ }
+
+ Text {
+ text: qsTr("Effect name cannot be empty.")
+ color: "#ff0000"
+ anchors.right: parent.right
+ visible: effectName.text === ""
+ }
+
+ Text {
+ text: qsTr("Effect path is too long.")
+ color: "#ff0000"
+ anchors.right: parent.right
+ visible: effectName.text.length > root.__maxPath
+ }
+
+ Item { // spacer
+ width: 1
+ height: 20
+ }
+
+ Row {
+ anchors.right: parent.right
+
+ HelperWidgets.Button {
+ id: btnCreate
+
+ text: qsTr("Create")
+ enabled: effectName.text !== ""
+ && effectName.length >=3
+ && effectName.text.length <= root.__maxPath
+ onClicked: {
+ const path = assetsModel.getUniqueEffectPath(root.dirPath, effectName.text)
+ if (assetsModel.createNewEffect(path))
+ root.accept()
+ else
+ creationFailedDialog.open()
+ }
+ }
+
+ HelperWidgets.Button {
+ text: qsTr("Cancel")
+ onClicked: root.reject()
+ }
+ }
+ }
+
+ onOpened: {
+ const path = assetsModel.getUniqueEffectPath(root.dirPath, "Effect01")
+ effectName.text = path.split('/').pop().replace(".qep", '')
+ effectName.selectAll()
+ effectName.forceActiveFocus()
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml
index 306d4aeda98..d0fb8719ad1 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Menu.qml
@@ -40,5 +40,13 @@ T.Menu {
color: StudioTheme.Values.themeControlBackground
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
+ MouseArea {
+ // This mouse area is here to eat clicks that are not handled by menu items
+ // to prevent them going through to the underlying view.
+ // This is primarily problem with disabled menu items, but right clicks would go
+ // through enabled menu items as well.
+ anchors.fill: parent
+ acceptedButtons: Qt.AllButtons
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/files/effect/file.qep b/share/qtcreator/qmldesigner/studio_templates/files/effect/file.qep
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/share/qtcreator/qmldesigner/studio_templates/files/effect/wizard.json b/share/qtcreator/qmldesigner/studio_templates/files/effect/wizard.json
deleted file mode 100644
index 3dedbb5080d..00000000000
--- a/share/qtcreator/qmldesigner/studio_templates/files/effect/wizard.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{
- "version": 1,
- "supportedProjectTypes": [ ],
- "id": "J.QEP",
- "category": "U.QEP",
- "trDescription": "Creates an Effect Maker file.",
- "trDisplayName": "Effect File (Effect Maker)",
- "trDisplayCategory": "Effects",
- "iconText": "qep",
- "platformIndependent": true,
- "enabled": "%{JS: value('Features').indexOf('QmlDesigner.Wizards.Enterprise') >= 0}",
- "featuresRequired": [ "QmlDesigner.Wizards.Enterprise" ],
-
- "options": [
- { "key": "EffectFile", "value": "%{Class}.qep" },
- { "key": "DoNotOpenFile", "value": "true" }
- ],
-
- "pages" :
- [
- {
- "trDisplayName": "Define Class",
- "trShortTitle": "Details",
- "typeId": "Fields",
- "data" :
- [
- {
- "name": "Class",
- "trDisplayName": "Effect name:",
- "mandatory": true,
- "type": "LineEdit",
- "data": {
- "validator": "(?:[A-Z_][a-zA-Z_0-9]*|)",
- "fixup": "%{JS: '%{INPUT}'.charAt(0).toUpperCase() + '%{INPUT}'.slice(1) }"
- }
- },
- {
- "name": "TargetPath",
- "type": "PathChooser",
- "trDisplayName": "Path:",
- "mandatory": true,
- "data":
- {
- "kind": "existingDirectory",
- "basePath": "%{InitialPath}",
- "path": "%{InitialPath}"
- }
- }
- ]
- }
-],
- "generators" :
- [
- {
- "typeId": "File",
- "data":
- {
- "source": "file.qep",
- "target": "%{TargetPath}/%{EffectFile}",
- "openInEditor": false
- }
- }
- ]
-}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl
index 6878a1023c3..9daf9759b19 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl
@@ -10,6 +10,11 @@ set(CMAKE_AUTOMOC ON)
find_package(QT NAMES Qt6 COMPONENTS Gui Qml Quick)
find_package(Qt6 REQUIRED COMPONENTS Core Qml Quick)
+# To build this application you need Qt 6.2.0 or higher
+if (Qt6_VERSION VERSION_LESS 6.2.0)
+message(FATAL_ERROR "You need Qt 6.2.0 or newer to build the application.")
+endif()
+
qt_add_executable(${CMAKE_PROJECT_NAME} src/main.cpp)
# qt_standard_project_setup() requires Qt 6.3 or higher. See https://doc.qt.io/qt-6/qt-standard-project-setup.html for details.
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index 23e74f819bd..8075e6821ed 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -63,7 +63,7 @@ static const char *qtQuickUISuffix = "ui.qml";
static void maybeAddPath(ViewerContext &context, const Utils::FilePath &path)
{
- if (!path.isEmpty() && !(context.paths.count(path) > 0))
+ if (!path.isEmpty() && (context.paths.count(path) <= 0))
context.paths.insert(path);
}
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 8e524d8c5bc..ffb9faf87df 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -35,8 +35,10 @@ add_qtc_library(QmlDesignerUtils STATIC
PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/utils
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/utils
SOURCES
+ asset.cpp asset.h
designersettings.cpp designersettings.h
hdrimage.cpp hdrimage.h
+ imageutils.cpp imageutils.h
qmldesignerutils_global.h
)
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp
index bc56e9b7f3f..14a433e8602 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "assetslibraryiconprovider.h"
-#include "assetslibrarymodel.h"
+#include "asset.h"
#include "modelnodeoperations.h"
#include
@@ -25,13 +25,17 @@ QPixmap AssetsLibraryIconProvider::requestPixmap(const QString &id, QSize *size,
pixmap = m_thumbnails[id];
} else {
pixmap = fetchPixmap(id, requestedSize);
- if (pixmap.isNull())
+ bool haveValidImage = true;
+ if (pixmap.isNull()) {
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/assets_default.png");
+ haveValidImage = false;
+ }
if (requestedSize.isValid())
pixmap = pixmap.scaled(requestedSize, Qt::KeepAspectRatio);
- m_thumbnails[id] = pixmap;
+ if (haveValidImage)
+ m_thumbnails[id] = pixmap;
}
if (size) {
@@ -53,24 +57,25 @@ QPixmap AssetsLibraryIconProvider::generateFontIcons(const QString &filePath, co
QPixmap AssetsLibraryIconProvider::fetchPixmap(const QString &id, const QSize &requestedSize) const
{
- const QString suffix = "*." + id.split('.').last().toLower();
+ Asset asset(id);
+
if (id == "browse") {
return Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/browse.png");
- } else if (AssetsLibraryModel::supportedFontSuffixes().contains(suffix)) {
+ } else if (asset.isFont()) {
return generateFontIcons(id, requestedSize);
- } else if (AssetsLibraryModel::supportedImageSuffixes().contains(suffix)) {
+ } else if (asset.isImage()) {
return Utils::StyleHelper::dpiSpecificImageFile(id);
- } else if (AssetsLibraryModel::supportedTexture3DSuffixes().contains(suffix)) {
+ } else if (asset.isTexture3D()) {
return HdrImage{id}.toPixmap();
} else {
QString type;
- if (AssetsLibraryModel::supportedShaderSuffixes().contains(suffix))
+ if (asset.isShader())
type = "shader";
- else if (AssetsLibraryModel::supportedAudioSuffixes().contains(suffix))
+ else if (asset.isAudio())
type = "sound";
- else if (AssetsLibraryModel::supportedVideoSuffixes().contains(suffix))
+ else if (asset.isVideo())
type = "video";
- else if (AssetsLibraryModel::supportedEffectMakerSuffixes().contains(suffix))
+ else if (asset.isEffect())
type = QmlDesigner::ModelNodeOperations::getEffectIcon(id);
QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type);
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
index 6587c89cf32..0953eff9eb1 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
@@ -1,13 +1,13 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include
#include
#include
-#include
#include
#include
+#include "asset.h"
#include "assetslibrarymodel.h"
#include
@@ -134,32 +134,10 @@ bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &
bool AssetsLibraryModel::addNewFolder(const QString &folderPath)
{
QString iterPath = folderPath;
- static QRegularExpression rgx("\\d+$"); // matches a number at the end of a string
QDir dir{folderPath};
while (dir.exists()) {
- // if the folder name ends with a number, increment it
- QRegularExpressionMatch match = rgx.match(iterPath);
- if (match.hasMatch()) { // ends with a number
- QString numStr = match.captured(0);
- int num = match.captured(0).toInt();
-
- // get number of padding zeros, ex: for "005" = 2
- int nPaddingZeros = 0;
- for (; nPaddingZeros < numStr.size() && numStr[nPaddingZeros] == '0'; ++nPaddingZeros);
-
- ++num;
-
- // if the incremented number's digits increased, decrease the padding zeros
- if (std::fmod(std::log10(num), 1.0) == 0)
- --nPaddingZeros;
-
- iterPath = folderPath.mid(0, match.capturedStart())
- + QString('0').repeated(nPaddingZeros)
- + QString::number(num);
- } else {
- iterPath = folderPath + '1';
- }
+ iterPath = getUniqueName(iterPath);
dir.setPath(iterPath);
}
@@ -180,12 +158,49 @@ bool AssetsLibraryModel::deleteFolderRecursively(const QModelIndex &folderIndex)
bool AssetsLibraryModel::allFilePathsAreImages(const QStringList &filePaths) const
{
return Utils::allOf(filePaths, [](const QString &path) {
- const QString suffix = "*." + path.split('.').last().toLower();
-
- return AssetsLibraryModel::supportedImageSuffixes().contains(suffix);
+ return Asset(path).isImage();
});
}
+QString AssetsLibraryModel::getUniqueEffectPath(const QString &parentFolder, const QString &effectName)
+{
+ auto genEffectPath = [=](const QString &name) {
+ return QString(parentFolder + "/" + name + ".qep");
+ };
+
+ QString uniqueName = effectName;
+ QString path = genEffectPath(uniqueName);
+ QFileInfo file{path};
+
+ while (file.exists()) {
+ uniqueName = getUniqueName(uniqueName);
+
+ path = genEffectPath(uniqueName);
+ file.setFile(path);
+ }
+
+ return path;
+}
+
+bool AssetsLibraryModel::createNewEffect(const QString &effectPath, bool openEffectMaker)
+{
+ bool created = QFile(effectPath).open(QIODevice::WriteOnly);
+
+ if (created && openEffectMaker)
+ ModelNodeOperations::openEffectMaker(effectPath);
+
+ return created;
+}
+
+bool AssetsLibraryModel::canCreateEffects() const
+{
+#ifdef LICENSECHECKER
+ return checkLicense() == FoundLicense::enterprise;
+#else
+ return true;
+#endif
+}
+
bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
QString path = m_sourceFsModel->filePath(sourceParent);
@@ -242,6 +257,36 @@ void AssetsLibraryModel::syncHaveFiles()
setHaveFiles(checkHaveFiles());
}
+QString AssetsLibraryModel::getUniqueName(const QString &oldName) {
+ static QRegularExpression rgx("\\d+$"); // matches a number at the end of a string
+
+ QString uniqueName = oldName;
+ // if the folder name ends with a number, increment it
+ QRegularExpressionMatch match = rgx.match(uniqueName);
+ if (match.hasMatch()) { // ends with a number
+ QString numStr = match.captured(0);
+ int num = match.captured(0).toInt();
+
+ // get number of padding zeros, ex: for "005" = 2
+ int nPaddingZeros = 0;
+ for (; nPaddingZeros < numStr.size() && numStr[nPaddingZeros] == '0'; ++nPaddingZeros);
+
+ ++num;
+
+ // if the incremented number's digits increased, decrease the padding zeros
+ if (std::fmod(std::log10(num), 1.0) == 0)
+ --nPaddingZeros;
+
+ uniqueName = oldName.mid(0, match.capturedStart())
+ + QString('0').repeated(nPaddingZeros)
+ + QString::number(num);
+ } else {
+ uniqueName = oldName + '1';
+ }
+
+ return uniqueName;
+}
+
void AssetsLibraryModel::setRootPath(const QString &newPath)
{
beginResetModel();
@@ -252,7 +297,7 @@ void AssetsLibraryModel::setRootPath(const QString &newPath)
m_rootPath = newPath;
m_sourceFsModel->setRootPath(newPath);
- m_sourceFsModel->setNameFilters(supportedSuffixes().values());
+ m_sourceFsModel->setNameFilters(Asset::supportedSuffixes().values());
m_sourceFsModel->setNameFilterDisables(false);
endResetModel();
@@ -327,80 +372,4 @@ QString AssetsLibraryModel::parentDirPath(const QString &path) const
return filePath(parentIdx);
}
-const QStringList &AssetsLibraryModel::supportedImageSuffixes()
-{
- static QStringList retList;
- if (retList.isEmpty()) {
- const QList suffixes = QImageReader::supportedImageFormats();
- for (const QByteArray &suffix : suffixes)
- retList.append("*." + QString::fromUtf8(suffix));
- }
- return retList;
-}
-
-const QStringList &AssetsLibraryModel::supportedFragmentShaderSuffixes()
-{
- static const QStringList retList {"*.frag", "*.glsl", "*.glslf", "*.fsh"};
- return retList;
-}
-
-const QStringList &AssetsLibraryModel::supportedShaderSuffixes()
-{
- static const QStringList retList {"*.frag", "*.vert",
- "*.glsl", "*.glslv", "*.glslf",
- "*.vsh", "*.fsh"};
- return retList;
-}
-
-const QStringList &AssetsLibraryModel::supportedFontSuffixes()
-{
- static const QStringList retList {"*.ttf", "*.otf"};
- return retList;
-}
-
-const QStringList &AssetsLibraryModel::supportedAudioSuffixes()
-{
- static const QStringList retList {"*.wav", "*.mp3"};
- return retList;
-}
-
-const QStringList &AssetsLibraryModel::supportedVideoSuffixes()
-{
- static const QStringList retList {"*.mp4"};
- return retList;
-}
-
-const QStringList &AssetsLibraryModel::supportedTexture3DSuffixes()
-{
- // These are file types only supported by 3D textures
- static QStringList retList {"*.hdr", "*.ktx"};
- return retList;
-}
-
-const QStringList &AssetsLibraryModel::supportedEffectMakerSuffixes()
-{
- // These are file types only supported by Effect Maker
- static QStringList retList {"*.qep"};
- return retList;
-}
-
-const QSet &AssetsLibraryModel::supportedSuffixes()
-{
- static QSet allSuffixes;
- if (allSuffixes.isEmpty()) {
- auto insertSuffixes = [](const QStringList &suffixes) {
- for (const auto &suffix : suffixes)
- allSuffixes.insert(suffix);
- };
- insertSuffixes(supportedImageSuffixes());
- insertSuffixes(supportedShaderSuffixes());
- insertSuffixes(supportedFontSuffixes());
- insertSuffixes(supportedAudioSuffixes());
- insertSuffixes(supportedVideoSuffixes());
- insertSuffixes(supportedTexture3DSuffixes());
- insertSuffixes(supportedEffectMakerSuffixes());
- }
- return allSuffixes;
-}
-
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
index 99c96017084..0538bedf42b 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
@@ -1,14 +1,14 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
+#include
#include
#include
-#include
-#include
#include
+#include
namespace QmlDesigner {
@@ -47,6 +47,11 @@ public:
Q_INVOKABLE bool deleteFolderRecursively(const QModelIndex &folderIndex);
Q_INVOKABLE bool allFilePathsAreImages(const QStringList &filePaths) const;
+ Q_INVOKABLE QString getUniqueEffectPath(const QString &parentFolder, const QString &effectName);
+ Q_INVOKABLE bool createNewEffect(const QString &effectPath, bool openEffectMaker = true);
+
+ Q_INVOKABLE bool canCreateEffects() const;
+
int columnCount(const QModelIndex &parent = QModelIndex()) const override
{
int result = QSortFilterProxyModel::columnCount(parent);
@@ -55,16 +60,6 @@ public:
bool haveFiles() const { return m_haveFiles; }
- static const QStringList &supportedImageSuffixes();
- static const QStringList &supportedFragmentShaderSuffixes();
- static const QStringList &supportedShaderSuffixes();
- static const QStringList &supportedFontSuffixes();
- static const QStringList &supportedAudioSuffixes();
- static const QStringList &supportedVideoSuffixes();
- static const QStringList &supportedTexture3DSuffixes();
- static const QStringList &supportedEffectMakerSuffixes();
- static const QSet &supportedSuffixes();
-
signals:
void directoryLoaded(const QString &path);
void rootPathChanged();
@@ -79,6 +74,7 @@ private:
void destroyBackendModel();
bool checkHaveFiles(const QModelIndex &parentIdx) const;
bool checkHaveFiles() const;
+ QString getUniqueName(const QString &oldName);
QString m_searchText;
QString m_rootPath;
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
index 05ebb729869..cc9263eda46 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
@@ -3,8 +3,9 @@
#include "assetslibrarywidget.h"
-#include "assetslibrarymodel.h"
+#include "asset.h"
#include "assetslibraryiconprovider.h"
+#include "assetslibrarymodel.h"
#include
@@ -229,7 +230,7 @@ QSet AssetsLibraryWidget::supportedAssetSuffixes(bool complex)
QSet suffixes;
for (const AddResourceHandler &handler : handlers) {
- if (AssetsLibraryModel::supportedSuffixes().contains(handler.filter) != complex)
+ if (Asset(handler.filter).isSupported() != complex)
suffixes.insert(handler.filter);
}
@@ -290,32 +291,32 @@ void AssetsLibraryWidget::startDragAsset(const QStringList &assetPaths, const QP
QPair AssetsLibraryWidget::getAssetTypeAndData(const QString &assetPath)
{
- QString suffix = "*." + assetPath.split('.').last().toLower();
- if (!suffix.isEmpty()) {
- if (AssetsLibraryModel::supportedImageSuffixes().contains(suffix)) {
+ Asset asset(assetPath);
+ if (asset.hasSuffix()) {
+ if (asset.isImage()) {
// Data: Image format (suffix)
- return {Constants::MIME_TYPE_ASSET_IMAGE, suffix.toUtf8()};
- } else if (AssetsLibraryModel::supportedFontSuffixes().contains(suffix)) {
+ return {Constants::MIME_TYPE_ASSET_IMAGE, asset.suffix().toUtf8()};
+ } else if (asset.isFont()) {
// Data: Font family name
QRawFont font(assetPath, 10);
QString fontFamily = font.isValid() ? font.familyName() : "";
return {Constants::MIME_TYPE_ASSET_FONT, fontFamily.toUtf8()};
- } else if (AssetsLibraryModel::supportedShaderSuffixes().contains(suffix)) {
+ } else if (asset.isShader()) {
// Data: shader type, frament (f) or vertex (v)
return {Constants::MIME_TYPE_ASSET_SHADER,
- AssetsLibraryModel::supportedFragmentShaderSuffixes().contains(suffix) ? "f" : "v"};
- } else if (AssetsLibraryModel::supportedAudioSuffixes().contains(suffix)) {
+ asset.isFragmentShader() ? "f" : "v"};
+ } else if (asset.isAudio()) {
// No extra data for sounds
return {Constants::MIME_TYPE_ASSET_SOUND, {}};
- } else if (AssetsLibraryModel::supportedVideoSuffixes().contains(suffix)) {
+ } else if (asset.isVideo()) {
// No extra data for videos
return {Constants::MIME_TYPE_ASSET_VIDEO, {}};
- } else if (AssetsLibraryModel::supportedTexture3DSuffixes().contains(suffix)) {
+ } else if (asset.isTexture3D()) {
// Data: Image format (suffix)
- return {Constants::MIME_TYPE_ASSET_TEXTURE3D, suffix.toUtf8()};
- } else if (AssetsLibraryModel::supportedEffectMakerSuffixes().contains(suffix)) {
+ return {Constants::MIME_TYPE_ASSET_TEXTURE3D, asset.suffix().toUtf8()};
+ } else if (asset.isEffect()) {
// Data: Effect Maker format (suffix)
- return {Constants::MIME_TYPE_ASSET_EFFECT, suffix.toUtf8()};
+ return {Constants::MIME_TYPE_ASSET_EFFECT, asset.suffix().toUtf8()};
}
}
return {};
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 711b84c3798..bd9031ddc26 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -1525,8 +1525,11 @@ void mergeWithTemplate(const SelectionContext &selectionContext, ExternalDepende
const QString templateFile = getTemplateDialog(projectPath);
- if (QFileInfo::exists(templateFile))
- StylesheetMerger::styleMerge(selectionContext.view()->model(), templateFile, externalDependencies);
+ if (QFileInfo::exists(templateFile)) {
+ StylesheetMerger::styleMerge(Utils::FilePath::fromString(templateFile),
+ selectionContext.view()->model(),
+ externalDependencies);
+ }
}
void removeGroup(const SelectionContext &selectionContext)
@@ -1674,7 +1677,7 @@ void openEffectMaker(const QString &filePath)
}
}
-Utils::FilePath getEffectsDirectory()
+Utils::FilePath getEffectsImportDirectory()
{
QString defaultDir = "asset_imports/Effects";
Utils::FilePath projectPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
@@ -1688,6 +1691,11 @@ Utils::FilePath getEffectsDirectory()
return effectsPath;
}
+QString getEffectsDefaultDirectory(const QString &defaultDir)
+{
+ return getAssetDefaultDirectory("effects", defaultDir);
+}
+
QString getEffectIcon(const QString &effectPath)
{
const ProjectExplorer::Target *target = ProjectExplorer::ProjectTree::currentTarget();
@@ -1715,7 +1723,7 @@ bool useLayerEffect()
bool validateEffect(const QString &effectPath)
{
const QString effectName = QFileInfo(effectPath).baseName();
- Utils::FilePath effectsResDir = ModelNodeOperations::getEffectsDirectory();
+ Utils::FilePath effectsResDir = ModelNodeOperations::getEffectsImportDirectory();
Utils::FilePath qmlPath = effectsResDir.resolvePath(effectName + "/" + effectName + ".qml");
if (!qmlPath.exists()) {
QMessageBox msgBox;
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
index 2e60b253195..1cee080c561 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
@@ -119,7 +119,8 @@ void addMouseAreaFill(const SelectionContext &selectionContext);
void openSignalDialog(const SelectionContext &selectionContext);
void updateImported3DAsset(const SelectionContext &selectionContext);
-QMLDESIGNERCORE_EXPORT Utils::FilePath getEffectsDirectory();
+QMLDESIGNERCORE_EXPORT Utils::FilePath getEffectsImportDirectory();
+QMLDESIGNERCORE_EXPORT QString getEffectsDefaultDirectory(const QString &defaultDir);
void openEffectMaker(const QString &filePath);
QString getEffectIcon(const QString &effectPath);
bool useLayerEffect();
diff --git a/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp b/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp
index 487f84229c4..46c5b665f90 100644
--- a/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/navigation2d.cpp
@@ -76,19 +76,19 @@ bool Navigation2dFilter::wheelEvent(QWheelEvent *event)
bool zoomChangedConnected = QObject::isSignalConnected(zoomChangedSignal);
if (zoomChangedConnected) {
- const double globalMouseSpeed =
- QmlDesignerPlugin::settings().value(DesignerSettingsKey::EDITOR_ZOOM_FACTOR).toDouble();
-
- double speed = globalMouseSpeed/20.;
- if (Utils::HostOsInfo::isMacHost())
- speed = 1.0/200.;
-
- if (QPointF delta = event->pixelDelta(); !delta.isNull()) {
+ double speed = 1.0 / 200.0;
+ bool isMac = Utils::HostOsInfo::isMacHost();
+ if (QPointF delta = event->pixelDelta(); !delta.isNull() && isMac) {
double dist = std::abs(delta.x()) > std::abs(delta.y()) ? -delta.x() : delta.y();
emit zoomChanged(dist * speed, event->position());
event->accept();
return true;
} else if (QPointF delta = event->angleDelta(); !delta.isNull()) {
+
+ const double globalMouseSpeed =
+ QmlDesignerPlugin::settings().value(DesignerSettingsKey::EDITOR_ZOOM_FACTOR).toDouble();
+ speed = globalMouseSpeed / 20.0;
+
constexpr double degreePerStep = 15.;
constexpr double stepCount = 8.;
double dist = std::abs(delta.x()) > std::abs(delta.y()) ? -delta.x() : delta.y();
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
index 288e04aaff6..84cd0f98362 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
@@ -3,12 +3,17 @@
#include "contentlibrarytexture.h"
+#include "imageutils.h"
+
namespace QmlDesigner {
ContentLibraryTexture::ContentLibraryTexture(QObject *parent, const QString &path, const QUrl &icon)
: QObject(parent)
, m_path(path)
- , m_icon(icon) {}
+ , m_icon(icon)
+{
+ m_toolTip = QLatin1String("%1\n%2").arg(path.split('/').last(), ImageUtils::imageInfo(path));
+}
bool ContentLibraryTexture::filter(const QString &searchText)
{
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
index 88d50158325..468dfea09e4 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
@@ -13,6 +13,7 @@ class ContentLibraryTexture : public QObject
Q_OBJECT
Q_PROPERTY(QString texturePath MEMBER m_path CONSTANT)
+ Q_PROPERTY(QString textureToolTip MEMBER m_toolTip CONSTANT)
Q_PROPERTY(QUrl textureIcon MEMBER m_icon CONSTANT)
Q_PROPERTY(bool textureVisible MEMBER m_visible NOTIFY textureVisibleChanged)
@@ -29,6 +30,7 @@ signals:
private:
QString m_path;
+ QString m_toolTip;
QUrl m_icon;
bool m_visible = true;
diff --git a/src/plugins/qmldesigner/components/createtexture.cpp b/src/plugins/qmldesigner/components/createtexture.cpp
index 91e40959806..a17a61e84ea 100644
--- a/src/plugins/qmldesigner/components/createtexture.cpp
+++ b/src/plugins/qmldesigner/components/createtexture.cpp
@@ -65,19 +65,27 @@ ModelNode CreateTexture::createTextureFromImage(const QString &assetPath, AddTex
NodeMetaInfo metaInfo = m_view->model()->qtQuick3DTextureMetaInfo();
- Utils::FilePath imagePath = ModelNodeOperations::getImagesDefaultDirectory()
- .pathAppended(Utils::FilePath::fromString(assetPath).fileName());
- QString sourceVal = imagePath.relativePathFrom(
- QmlDesigner::DocumentManager::currentFilePath()).toString();
+ Utils::FilePath currentDocumentPath = QmlDesigner::DocumentManager::currentFilePath();
+ Utils::FilePath imageTargetPath;
+ if (m_importFile) {
+ QString assetName = Utils::FilePath::fromString(assetPath).fileName();
+ // if the asset had to be imported from somewhere else, then assetPath is the source where
+ // the asset was taken from, and we have to compute where it was placed in the project.
+ imageTargetPath = ModelNodeOperations::getImagesDefaultDirectory().pathAppended(assetName);
+ } else {
+ imageTargetPath = Utils::FilePath::fromString(assetPath);
+ }
- ModelNode newTexNode = m_view->getTextureDefaultInstance(sourceVal);
+ QString textureSource = imageTargetPath.relativePathFrom(currentDocumentPath).toString();
+
+ ModelNode newTexNode = m_view->getTextureDefaultInstance(textureSource);
if (!newTexNode.isValid()) {
newTexNode = m_view->createModelNode("QtQuick3D.Texture",
metaInfo.majorVersion(),
metaInfo.minorVersion());
newTexNode.validId();
VariantProperty sourceProp = newTexNode.variantProperty("source");
- sourceProp.setValue(sourceVal);
+ sourceProp.setValue(textureSource);
matLib.defaultNodeListProperty().reparentHere(newTexNode);
}
diff --git a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp
index 07d65cb3c33..42f5bc45dd5 100644
--- a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp
@@ -44,7 +44,7 @@ QColorDialog *BackgroundColorSelection::createColorDialog(QWidget *parent,
QObject::connect(dialog, &QColorDialog::currentColorChanged, dialog,
[actionType, view](const QColor &color) {
- Edit3DViewConfig::setColor(view, actionType, color);
+ Edit3DViewConfig::setColors(view, actionType, {color});
});
QObject::connect(dialog, &QColorDialog::colorSelected, dialog,
@@ -52,13 +52,13 @@ QColorDialog *BackgroundColorSelection::createColorDialog(QWidget *parent,
if (colorSelected)
colorSelected();
- Edit3DViewConfig::saveColor(key, color);
+ Edit3DViewConfig::saveColors(key, {color});
});
- if (Edit3DViewConfig::isColorValid(oldColorConfig)) {
+ if (Edit3DViewConfig::colorsValid(oldColorConfig)) {
QObject::connect(dialog, &QColorDialog::rejected, dialog,
[actionType, oldColorConfig, view]() {
- Edit3DViewConfig::setColor(view, actionType, oldColorConfig);
+ Edit3DViewConfig::setColors(view, actionType, oldColorConfig);
});
}
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
index d5c93ca4b97..5b271a4c13d 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
@@ -3,7 +3,6 @@
#include "edit3dactions.h"
#include "edit3dview.h"
-#include "edit3dwidget.h"
#include
#include
@@ -18,7 +17,7 @@ namespace QmlDesigner {
Edit3DActionTemplate::Edit3DActionTemplate(const QString &description,
SelectionContextOperation action,
- AbstractView *view,
+ Edit3DView *view,
View3DActionType type)
: DefaultAction(description)
, m_action(action)
@@ -45,12 +44,14 @@ Edit3DAction::Edit3DAction(const QByteArray &menuId,
bool checked,
const QIcon &iconOff,
const QIcon &iconOn,
- AbstractView *view,
+ Edit3DView *view,
SelectionContextOperation selectionAction,
const QString &toolTip)
: AbstractAction(new Edit3DActionTemplate(description, selectionAction, view, type))
, m_menuId(menuId)
+ , m_actionTemplate(qobject_cast(defaultAction()))
{
+ view->registerEdit3DAction(this);
action()->setShortcut(key);
action()->setShortcutContext(Qt::WidgetWithChildrenShortcut);
action()->setCheckable(checkable);
@@ -73,11 +74,21 @@ Edit3DAction::Edit3DAction(const QByteArray &menuId,
}
}
+Edit3DAction::~Edit3DAction()
+{
+ m_actionTemplate->m_view->unregisterEdit3DAction(this);
+}
+
QByteArray Edit3DAction::category() const
{
return QByteArray();
}
+View3DActionType Edit3DAction::actionType() const
+{
+ return m_actionTemplate->m_type;
+}
+
bool Edit3DAction::isVisible([[maybe_unused]] const SelectionContext &selectionContext) const
{
return true;
@@ -96,7 +107,7 @@ Edit3DCameraAction::Edit3DCameraAction(const QByteArray &menuId,
bool checked,
const QIcon &iconOff,
const QIcon &iconOn,
- AbstractView *view,
+ Edit3DView *view,
SelectionContextOperation selectionAction)
: Edit3DAction(menuId, type, description, key, checkable, checked, iconOff, iconOn, view, selectionAction)
{
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
index 14f63c3796e..a78b95d784a 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
@@ -10,19 +10,22 @@
namespace QmlDesigner {
using SelectionContextOperation = std::function;
+class Edit3DView;
class Edit3DActionTemplate : public DefaultAction
{
+ Q_OBJECT
+
public:
Edit3DActionTemplate(const QString &description,
SelectionContextOperation action,
- AbstractView *view,
+ Edit3DView *view,
View3DActionType type);
void actionTriggered(bool b) override;
SelectionContextOperation m_action;
- AbstractView *m_view;
+ Edit3DView *m_view = nullptr;
View3DActionType m_type;
};
@@ -37,10 +40,12 @@ public:
bool checked,
const QIcon &iconOff,
const QIcon &iconOn,
- AbstractView *view,
+ Edit3DView *view,
SelectionContextOperation selectionAction = nullptr,
const QString &toolTip = {});
+ virtual ~Edit3DAction();
+
QByteArray category() const override;
int priority() const override
@@ -58,12 +63,15 @@ public:
return m_menuId;
}
+ View3DActionType actionType() const;
+
protected:
bool isVisible(const SelectionContext &selectionContext) const override;
bool isEnabled(const SelectionContext &selectionContext) const override;
private:
QByteArray m_menuId;
+ Edit3DActionTemplate *m_actionTemplate = nullptr;
};
class Edit3DCameraAction : public Edit3DAction
@@ -77,7 +85,7 @@ public:
bool checked,
const QIcon &iconOff,
const QIcon &iconOn,
- AbstractView *view,
+ Edit3DView *view,
SelectionContextOperation selectionAction = nullptr);
protected:
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index b7efef60d6a..038c658c51e 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -38,7 +38,9 @@ Edit3DView::Edit3DView(ExternalDependenciesInterface &externalDependencies)
}
Edit3DView::~Edit3DView()
-{}
+{
+ qDeleteAll(m_edit3DActions);
+}
void Edit3DView::createEdit3DWidget()
{
@@ -197,6 +199,31 @@ void Edit3DView::onEntriesChanged()
m_compressionTimer.start();
}
+void Edit3DView::registerEdit3DAction(Edit3DAction *action)
+{
+ View3DActionType actionType = action->actionType();
+ if (actionType == View3DActionType::Empty)
+ return;
+
+ if (m_edit3DActions.contains(actionType)) {
+ Edit3DAction *formerAction = m_edit3DActions.value(actionType);
+ if (formerAction == action)
+ return;
+
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Reregistering action for" << int(actionType);
+ delete formerAction;
+ }
+
+ m_edit3DActions.insert(actionType, action);
+}
+
+void Edit3DView::unregisterEdit3DAction(Edit3DAction *action)
+{
+ View3DActionType actionType = action->actionType();
+ if (m_edit3DActions.value(actionType, nullptr) == action)
+ m_edit3DActions.remove(actionType);
+}
+
void Edit3DView::handleEntriesChanged()
{
if (!model())
@@ -389,12 +416,12 @@ Edit3DAction *Edit3DView::createResetColorAction(QAction *syncBackgroundColorAct
auto operation = [this, syncBackgroundColorAction](const SelectionContext &) {
QList bgColors = {QRgb(0x222222), QRgb(0x999999)};
- Edit3DViewConfig::setColor(this, View3DActionType::SelectBackgroundColor, bgColors);
- Edit3DViewConfig::saveColor(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, bgColors);
+ Edit3DViewConfig::setColors(this, View3DActionType::SelectBackgroundColor, bgColors);
+ Edit3DViewConfig::saveColors(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, bgColors);
QColor gridColor{0xaaaaaa};
- Edit3DViewConfig::setColor(this, View3DActionType::SelectGridColor, gridColor);
- Edit3DViewConfig::saveColor(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, gridColor);
+ Edit3DViewConfig::setColors(this, View3DActionType::SelectGridColor, {gridColor});
+ Edit3DViewConfig::saveColors(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, {gridColor});
if (syncBackgroundColorAction->isChecked()) {
Edit3DViewConfig::set(this, View3DActionType::SyncBackgroundColor, false);
@@ -812,6 +839,11 @@ QVector Edit3DView::backgroundColorActions() const
return m_backgroundColorActions;
}
+Edit3DAction *Edit3DView::edit3DAction(View3DActionType type) const
+{
+ return m_edit3DActions.value(type, nullptr);
+}
+
void Edit3DView::addQuick3DImport()
{
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index a14399e1c70..7653730480f 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -57,6 +57,7 @@ public:
QVector rightActions() const;
QVector visibilityToggleActions() const;
QVector backgroundColorActions() const;
+ Edit3DAction *edit3DAction(View3DActionType type) const;
void setSeeker(SeekerSlider *slider);
void addQuick3DImport();
@@ -77,6 +78,9 @@ private:
None
};
+ void registerEdit3DAction(Edit3DAction *action);
+ void unregisterEdit3DAction(Edit3DAction *action);
+
void createEdit3DWidget();
void checkImports();
void handleEntriesChanged();
@@ -92,6 +96,7 @@ private:
QVector m_rightActions;
QVector m_visibilityToggleActions;
QVector m_backgroundColorActions;
+ QMap m_edit3DActions;
Edit3DAction *m_selectionModeAction = nullptr;
Edit3DAction *m_moveToolAction = nullptr;
Edit3DAction *m_rotateToolAction = nullptr;
@@ -120,6 +125,8 @@ private:
NodeAtPosReqType m_nodeAtPosReqType;
QPoint m_contextMenuPos;
QTimer m_compressionTimer;
+
+ friend class Edit3DAction;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h b/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h
index 267e27042c9..e0eba1115c9 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h
@@ -28,17 +28,9 @@ public:
});
}
- static void setColor(AbstractView *view, View3DActionType type, const QList &colorConfig)
+ static void setColors(AbstractView *view, View3DActionType type, const QList &colorConfig)
{
- if (colorConfig.size() == 1)
- setColor(view, type, colorConfig.at(0));
- else
- setVariant(view, type, QVariant::fromValue(colorConfig));
- }
-
- static void setColor(AbstractView *view, View3DActionType type, const QColor &color)
- {
- setVariant(view, type, QVariant::fromValue(color));
+ setVariant(view, type, QVariant::fromValue(colorConfig));
}
template
@@ -47,7 +39,7 @@ public:
setVariant(view, type, QVariant::fromValue(value));
}
- static void saveColor(const QByteArray &key, const QList &colorConfig)
+ static void saveColors(const QByteArray &key, const QList &colorConfig)
{
QStringList colorNames = Utils::transform(colorConfig, [](const QColor &color) {
return color.name();
@@ -56,12 +48,7 @@ public:
saveVariant(key, QVariant::fromValue(colorNames));
}
- static void saveColor(const QByteArray &key, const QColor &color)
- {
- saveVariant(key, QVariant::fromValue(color.name()));
- }
-
- static bool isColorValid(const QList &colorConfig) { return !colorConfig.isEmpty(); }
+ static bool colorsValid(const QList &colorConfig) { return !colorConfig.isEmpty(); }
private:
static void setVariant(AbstractView *view, View3DActionType type, const QVariant &colorConfig)
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
index ca57d229d3b..f3af3a5ee2e 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
@@ -232,6 +232,14 @@ void Edit3DWidget::createContextMenu()
view()->setSelectedModelNode(parentNode);
});
+ QAction *defaultToggleGroupAction = view()->edit3DAction(View3DActionType::SelectionModeToggle)->action();
+ m_toggleGroupAction = m_contextMenu->addAction(tr("Group Selection Mode"), [&](const bool &mode) {
+ view()->edit3DAction(View3DActionType::SelectionModeToggle)->action()->trigger();
+ });
+ connect(defaultToggleGroupAction, &QAction::toggled, m_toggleGroupAction, &QAction::setChecked);
+ m_toggleGroupAction->setCheckable(true);
+ m_toggleGroupAction->setChecked(defaultToggleGroupAction->isChecked());
+
m_contextMenu->addSeparator();
}
@@ -375,6 +383,7 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode
m_alignCameraAction->setEnabled(isCamera);
m_alignViewAction->setEnabled(isCamera);
m_selectParentAction->setEnabled(selectionExcludingRoot);
+ m_toggleGroupAction->setEnabled(true);
m_contextMenu->popup(mapToGlobal(pos));
}
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
index 25948d5d9aa..f1a9c09f445 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
@@ -72,6 +72,7 @@ private:
QPointer m_alignCameraAction;
QPointer m_alignViewAction;
QPointer m_selectParentAction;
+ QPointer m_toggleGroupAction;
QPointer m_createSubMenu;
ModelNode m_contextMenuTarget;
QVector3D m_contextMenuPos3d;
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
index f348580937d..9972a446227 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
@@ -3,8 +3,8 @@
#include "materialbrowsertexturesmodel.h"
-#include "designeractionmanager.h"
#include "designmodewidget.h"
+#include "imageutils.h"
#include "qmldesignerplugin.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
@@ -52,24 +52,18 @@ QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role)
return m_textureList.at(index.row()).internalId();
if (role == RoleTexToolTip) {
- QString source = QmlObjectNode(m_textureList.at(index.row())).modelValue("source").toString();
+ QString source = data(index, RoleTexSource).toString(); // absolute path
if (source.isEmpty())
return tr("Texture has no source image.");
- const QString noData = tr("Texture has no data.");
+ ModelNode texNode = m_textureList.at(index.row());
+ QString info = ImageUtils::imageInfo(source);
- auto op = QmlDesignerPlugin::instance()->viewManager().designerActionManager()
- .modelNodePreviewOperation(m_textureList.at(index.row()));
- if (!op)
- return noData;
+ if (info.isEmpty())
+ return tr("Texture has no data.");
- QVariantMap imgMap = op(m_textureList.at(index.row())).toMap();
- if (imgMap.isEmpty())
- return noData;
-
- return QLatin1String("%1\n%2\n%3").arg(imgMap.value("id").toString(),
- source.split('/').last(),
- imgMap.value("info").toString());
+ QString sourceRelative = QmlObjectNode(texNode).modelValue("source").toString();
+ return QLatin1String("%1\n%2\n%3").arg(texNode.id(), sourceRelative, info);
}
return {};
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 66b6f640faf..a7a163ab18b 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -797,10 +797,7 @@ void NavigatorTreeModel::handleMaterialDrop(const QMimeData *mimeData, int rowNu
if (!targetNode.metaInfo().isQtQuick3DModel())
return;
- QByteArray data = mimeData->data(Constants::MIME_TYPE_MATERIAL);
- QDataStream stream(data);
- qint32 internalId;
- stream >> internalId;
+ qint32 internalId = mimeData->data(Constants::MIME_TYPE_MATERIAL).toInt();
ModelNode matNode = m_view->modelNodeForInternalId(internalId);
m_view->executeInTransaction(__FUNCTION__, [&] {
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index 2175f786691..31106a87356 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -253,10 +253,7 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
m_widget->setDragType(itemLibraryEntry.typeName());
m_widget->update();
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
- QByteArray data = mimeData->data(Constants::MIME_TYPE_MATERIAL);
- QDataStream stream(data);
- qint32 internalId;
- stream >> internalId;
+ qint32 internalId = mimeData->data(Constants::MIME_TYPE_MATERIAL).toInt();
ModelNode matNode = modelNodeForInternalId(internalId);
m_widget->setDragType(matNode.metaInfo().typeName());
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp
index e7ff48450d1..fc5a09818ca 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "propertyeditorimageprovider.h"
-#include "assetslibrarymodel.h"
+#include "asset.h"
#include
#include
@@ -16,12 +16,12 @@ namespace QmlDesigner {
QQuickImageResponse *PropertyEditorImageProvider::requestImageResponse(const QString &id,
const QSize &requestedSize)
{
- const QString suffix = "*." + id.split('.').last().toLower();
+ Asset asset(id);
- if (suffix == "*.mesh")
+ if (asset.suffix() == "*.mesh")
return m_smallImageCacheProvider.requestImageResponse(id, requestedSize);
- if (suffix == "*.builtin")
+ if (asset.suffix() == "*.builtin")
return m_smallImageCacheProvider.requestImageResponse("#" + id.split('.').first(),
requestedSize);
@@ -29,15 +29,15 @@ QQuickImageResponse *PropertyEditorImageProvider::requestImageResponse(const QSt
QMetaObject::invokeMethod(
response.get(),
- [response = QPointer(response.get()), suffix, id, requestedSize] {
- if (AssetsLibraryModel::supportedImageSuffixes().contains(suffix)) {
- QImage image = QImage(Utils::StyleHelper::dpiSpecificImageFile(id));
+ [response = QPointer(response.get()), asset, requestedSize] {
+ if (asset.isImage()) {
+ QImage image = QImage(Utils::StyleHelper::dpiSpecificImageFile(asset.id()));
if (!image.isNull()) {
response->setImage(image.scaled(requestedSize, Qt::KeepAspectRatio));
return;
}
- } else if (AssetsLibraryModel::supportedTexture3DSuffixes().contains(suffix)) {
- HdrImage hdr{id};
+ } else if (asset.isTexture3D()) {
+ HdrImage hdr{asset.id()};
if (!hdr.image().isNull()) {
response->setImage(hdr.image().scaled(requestedSize, Qt::KeepAspectRatio));
return;
diff --git a/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h b/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h
index f4e09cf6f5b..036cb9df659 100644
--- a/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h
+++ b/src/plugins/qmldesigner/designercore/include/stylesheetmerger.h
@@ -5,6 +5,8 @@
#include "qmldesignercorelib_global.h"
+#include "utils/filepath.h"
+
#include
#include
#include
@@ -26,7 +28,12 @@ class QMLDESIGNERCORE_EXPORT StylesheetMerger
public:
StylesheetMerger(AbstractView*, AbstractView*);
void merge();
- static void styleMerge(Model *model, const QString &templateFile, class ExternalDependenciesInterface &externalDependencies);
+ static void styleMerge(const Utils::FilePath &templateFile,
+ Model *model,
+ class ExternalDependenciesInterface &ed);
+ static void styleMerge(const QString &qmlTemplateString,
+ Model *model,
+ class ExternalDependenciesInterface &externalDependencies);
private:
void preprocessStyleSheet();
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 661b303a940..c715b659787 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -25,6 +25,7 @@
#include "createscenecommand.h"
#include "debugoutputcommand.h"
#include "informationchangedcommand.h"
+#include "imageutils.h"
#include "inputeventcommand.h"
#include "nodeabstractproperty.h"
#include "nodeinstanceserverproxy.h"
@@ -83,6 +84,8 @@
#include
#include
+#include
+#include
#include
#include
#include
@@ -135,12 +138,13 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
// related to a single event to be received before we act.
m_resetTimer.setSingleShot(true);
m_resetTimer.setInterval(100);
- QObject::connect(&m_resetTimer, &QTimer::timeout, [this] {
- resetPuppet();
+ QObject::connect(&m_resetTimer, &QTimer::timeout, this, [this] {
+ if (isAttached())
+ resetPuppet();
});
m_updateWatcherTimer.setSingleShot(true);
m_updateWatcherTimer.setInterval(100);
- QObject::connect(&m_updateWatcherTimer, &QTimer::timeout, [this] {
+ QObject::connect(&m_updateWatcherTimer, &QTimer::timeout, this, [this] {
for (const auto &path : std::as_const(m_pendingUpdateDirs))
updateWatcher(path);
m_pendingUpdateDirs.clear();
@@ -151,11 +155,11 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
// unnecessary generation when project with multiple shaders is opened.
m_generateQsbFilesTimer.setSingleShot(true);
m_generateQsbFilesTimer.setInterval(100);
- QObject::connect(&m_generateQsbFilesTimer, &QTimer::timeout, [this] {
+ QObject::connect(&m_generateQsbFilesTimer, &QTimer::timeout, this, [this] {
handleShaderChanges();
});
- connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged,
+ connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, this,
[this](const QString &path) {
const QSet pendingDirs = m_pendingUpdateDirs;
for (const auto &pendingPath : pendingDirs) {
@@ -171,7 +175,7 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
m_updateWatcherTimer.start();
});
- connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, [this](const QString &path) {
+ connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) {
if (m_qsbTargets.contains(path)) {
m_qsbTargets.insert(path, true);
m_generateQsbFilesTimer.start();
@@ -1909,23 +1913,7 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
imageData.pixmap = originalPixmap.scaled(dim, dim, Qt::KeepAspectRatio);
imageData.pixmap.setDevicePixelRatio(ratio);
imageData.time = modified;
-
- double imgSize = double(imageFi.size());
- static QStringList units({::QmlDesigner::NodeInstanceView::tr("B"),
- ::QmlDesigner::NodeInstanceView::tr("KB"),
- ::QmlDesigner::NodeInstanceView::tr("MB"),
- ::QmlDesigner::NodeInstanceView::tr("GB")});
- int unitIndex = 0;
- while (imgSize > 1024. && unitIndex < units.size() - 1) {
- ++unitIndex;
- imgSize /= 1024.;
- }
- imageData.info = QStringLiteral("%1 x %2\n%3%4 (%5)")
- .arg(originalPixmap.width())
- .arg(originalPixmap.height())
- .arg(QString::number(imgSize, 'g', 3))
- .arg(units[unitIndex])
- .arg(imageFi.suffix());
+ imageData.info = ImageUtils::imageInfo(imageSource);
m_imageDataMap.insert(imageData.id, imageData);
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp b/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp
index 268f43eb42d..56b3cdafc2d 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp
@@ -35,7 +35,7 @@ QProcessUniquePointer puppetProcess(const QString &puppetPath,
processFinishCallback);
if (forwardOutput == puppetMode || forwardOutput == "all") {
- puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
+ puppetProcess->setProcessChannelMode(QProcess::ForwardedChannels);
QObject::connect(puppetProcess.get(), &QProcess::readyRead, processOutputCallback);
}
puppetProcess->setWorkingDirectory(workingDirectory);
@@ -46,7 +46,6 @@ QProcessUniquePointer puppetProcess(const QString &puppetPath,
else
processArguments = {socketToken, puppetMode};
- processArguments.push_back("-graphicssystem raster");
processArguments.push_back(freeTypeOption);
puppetProcess->start(puppetPath, processArguments);
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index cdda880f84b..7914ca76437 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -562,9 +562,9 @@ QVector getObjectTypes(const ObjectValue *objectValue, const Conte
const CppComponentValue * qmlObjectValue = value_cast(prototype);
if (qmlObjectValue)
- propertyList.append(getQmlTypes(qmlObjectValue, context, local, rec));
+ propertyList.append(getQmlTypes(qmlObjectValue, context, local, rec + 1));
else
- propertyList.append(getObjectTypes(prototype, context, local, rec));
+ propertyList.append(getObjectTypes(prototype, context, local, rec + 1));
}
return propertyList;
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index 20d39362a0e..50497c58359 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -559,6 +559,7 @@ void AbstractView::resetView()
void AbstractView::resetPuppet()
{
+ QTC_ASSERT(isAttached(), return);
emitCustomNotification(QStringLiteral("reset QmlPuppet"));
}
@@ -689,7 +690,8 @@ void AbstractView::emitCustomNotification(const QString &identifier, const QList
void AbstractView::emitCustomNotification(const QString &identifier, const QList &nodeList, const QList &data)
{
- model()->d->notifyCustomNotification(this, identifier, nodeList, data);
+ if (model())
+ model()->d->notifyCustomNotification(this, identifier, nodeList, data);
}
void AbstractView::emitInstancePropertyChange(const QList > &propertyList)
diff --git a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
index dd377cc0180..6df3e58a1d1 100644
--- a/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/stylesheetmerger.cpp
@@ -515,11 +515,24 @@ void StylesheetMerger::merge()
}
}
-void StylesheetMerger::styleMerge(Model *model, const QString &templateFile, ExternalDependenciesInterface &externalDependencies)
+void StylesheetMerger::styleMerge(const Utils::FilePath &templateFile,
+ Model *model,
+ ExternalDependenciesInterface &externalDependencies)
+{
+ Utils::FileReader reader;
+
+ QTC_ASSERT(reader.fetch(templateFile), return );
+ const QString qmlTemplateString = QString::fromUtf8(reader.data());
+ StylesheetMerger::styleMerge(qmlTemplateString, model, externalDependencies);
+}
+
+void StylesheetMerger::styleMerge(const QString &qmlTemplateString,
+ Model *model,
+ ExternalDependenciesInterface &externalDependencies)
{
Model *parentModel = model;
- QTC_ASSERT(parentModel, return);
+ QTC_ASSERT(parentModel, return );
auto templateModel(Model::create("QtQuick.Item", 2, 1, parentModel));
Q_ASSERT(templateModel.get());
@@ -527,10 +540,6 @@ void StylesheetMerger::styleMerge(Model *model, const QString &templateFile, Ext
templateModel->setFileUrl(parentModel->fileUrl());
QPlainTextEdit textEditTemplate;
- Utils::FileReader reader;
-
- QTC_ASSERT(reader.fetch(Utils::FilePath::fromString(templateFile)), return);
- QString qmlTemplateString = QString::fromUtf8(reader.data());
QString imports;
for (const Import &import : parentModel->imports()) {
@@ -541,13 +550,14 @@ void StylesheetMerger::styleMerge(Model *model, const QString &templateFile, Ext
textEditTemplate.setPlainText(imports + qmlTemplateString);
NotIndentingTextEditModifier textModifierTemplate(&textEditTemplate);
- QScopedPointer templateRewriterView(new RewriterView(externalDependencies, RewriterView::Amend));
+ QScopedPointer templateRewriterView(
+ new RewriterView(externalDependencies, RewriterView::Amend));
templateRewriterView->setTextModifier(&textModifierTemplate);
templateModel->attachView(templateRewriterView.data());
templateRewriterView->setCheckSemanticErrors(false);
ModelNode templateRootNode = templateRewriterView->rootModelNode();
- QTC_ASSERT(templateRootNode.isValid(), return);
+ QTC_ASSERT(templateRootNode.isValid(), return );
auto styleModel(Model::create("QtQuick.Item", 2, 1, parentModel));
Q_ASSERT(styleModel.get());
@@ -556,11 +566,12 @@ void StylesheetMerger::styleMerge(Model *model, const QString &templateFile, Ext
QPlainTextEdit textEditStyle;
RewriterView *parentRewriterView = parentModel->rewriterView();
- QTC_ASSERT(parentRewriterView, return);
+ QTC_ASSERT(parentRewriterView, return );
textEditStyle.setPlainText(parentRewriterView->textModifierContent());
NotIndentingTextEditModifier textModifierStyle(&textEditStyle);
- QScopedPointer styleRewriterView(new RewriterView(externalDependencies, RewriterView::Amend));
+ QScopedPointer styleRewriterView(
+ new RewriterView(externalDependencies, RewriterView::Amend));
styleRewriterView->setTextModifier(&textModifierStyle);
styleModel->attachView(styleRewriterView.data());
diff --git a/src/plugins/qmldesigner/utils/asset.cpp b/src/plugins/qmldesigner/utils/asset.cpp
new file mode 100644
index 00000000000..6a0a4658429
--- /dev/null
+++ b/src/plugins/qmldesigner/utils/asset.cpp
@@ -0,0 +1,182 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#include
+
+#include "asset.h"
+
+namespace QmlDesigner {
+
+Asset::Asset(const QString &filePath)
+ : m_filePath(filePath)
+{
+ m_suffix = "*." + filePath.split('.').last().toLower();
+}
+
+
+const QStringList &Asset::supportedImageSuffixes()
+{
+ static QStringList retList;
+ if (retList.isEmpty()) {
+ const QList suffixes = QImageReader::supportedImageFormats();
+ for (const QByteArray &suffix : suffixes)
+ retList.append("*." + QString::fromUtf8(suffix));
+ }
+ return retList;
+}
+
+const QStringList &Asset::supportedFragmentShaderSuffixes()
+{
+ static const QStringList retList {"*.frag", "*.glsl", "*.glslf", "*.fsh"};
+ return retList;
+}
+
+const QStringList &Asset::supportedShaderSuffixes()
+{
+ static const QStringList retList {"*.frag", "*.vert",
+ "*.glsl", "*.glslv", "*.glslf",
+ "*.vsh", "*.fsh"};
+ return retList;
+}
+
+const QStringList &Asset::supportedFontSuffixes()
+{
+ static const QStringList retList {"*.ttf", "*.otf"};
+ return retList;
+}
+
+const QStringList &Asset::supportedAudioSuffixes()
+{
+ static const QStringList retList {"*.wav", "*.mp3"};
+ return retList;
+}
+
+const QStringList &Asset::supportedVideoSuffixes()
+{
+ static const QStringList retList {"*.mp4"};
+ return retList;
+}
+
+const QStringList &Asset::supportedTexture3DSuffixes()
+{
+ // These are file types only supported by 3D textures
+ static QStringList retList {"*.hdr", "*.ktx"};
+ return retList;
+}
+
+const QStringList &Asset::supportedEffectMakerSuffixes()
+{
+ // These are file types only supported by Effect Maker
+ static QStringList retList {"*.qep"};
+ return retList;
+}
+
+const QSet &Asset::supportedSuffixes()
+{
+ static QSet allSuffixes;
+ if (allSuffixes.isEmpty()) {
+ auto insertSuffixes = [](const QStringList &suffixes) {
+ for (const auto &suffix : suffixes)
+ allSuffixes.insert(suffix);
+ };
+ insertSuffixes(supportedImageSuffixes());
+ insertSuffixes(supportedShaderSuffixes());
+ insertSuffixes(supportedFontSuffixes());
+ insertSuffixes(supportedAudioSuffixes());
+ insertSuffixes(supportedVideoSuffixes());
+ insertSuffixes(supportedTexture3DSuffixes());
+ insertSuffixes(supportedEffectMakerSuffixes());
+ }
+ return allSuffixes;
+}
+
+Asset::Type Asset::type() const
+{
+ if (supportedImageSuffixes().contains(m_suffix))
+ return Asset::Type::Image;
+
+ if (supportedFragmentShaderSuffixes().contains(m_suffix))
+ return Asset::Type::FragmentShader;
+
+ if (supportedShaderSuffixes().contains(m_suffix))
+ return Asset::Type::Shader;
+
+ if (supportedFontSuffixes().contains(m_suffix))
+ return Asset::Type::Font;
+
+ if (supportedAudioSuffixes().contains(m_suffix))
+ return Asset::Type::Audio;
+
+ if (supportedVideoSuffixes().contains(m_suffix))
+ return Asset::Type::Video;
+
+ if (supportedTexture3DSuffixes().contains(m_suffix))
+ return Asset::Type::Texture3D;
+
+ if (supportedEffectMakerSuffixes().contains(m_suffix))
+ return Asset::Type::Effect;
+
+ return Asset::Type::Unknown;
+}
+
+bool Asset::isImage() const
+{
+ return type() == Asset::Type::Image;
+}
+
+bool Asset::isFragmentShader() const
+{
+ return type() == Asset::Type::FragmentShader;
+}
+
+bool Asset::isShader() const
+{
+ return type() == Asset::Type::Shader;
+}
+
+bool Asset::isFont() const
+{
+ return type() == Asset::Type::Font;
+}
+
+bool Asset::isAudio() const
+{
+ return type() == Asset::Type::Audio;
+}
+
+bool Asset::isVideo() const
+{
+ return type() == Asset::Type::Video;
+}
+
+bool Asset::isTexture3D() const
+{
+ return type() == Asset::Type::Texture3D;
+}
+
+bool Asset::isEffect() const
+{
+ return type() == Asset::Type::Effect;
+}
+
+const QString Asset::suffix() const
+{
+ return m_suffix;
+}
+
+const QString Asset::id() const
+{
+ return m_filePath;
+}
+
+bool Asset::isSupported() const
+{
+ return supportedSuffixes().contains(m_filePath);
+}
+
+bool Asset::hasSuffix() const
+{
+ return !m_suffix.isEmpty();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/utils/asset.h b/src/plugins/qmldesigner/utils/asset.h
new file mode 100644
index 00000000000..279edb93e1b
--- /dev/null
+++ b/src/plugins/qmldesigner/utils/asset.h
@@ -0,0 +1,45 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+namespace QmlDesigner {
+
+class Asset
+{
+public:
+ enum Type { Unknown, Image, FragmentShader, Font, Audio, Video, Texture3D, Effect, Shader };
+
+ Asset(const QString &filePath);
+
+ static const QStringList &supportedImageSuffixes();
+ static const QStringList &supportedFragmentShaderSuffixes();
+ static const QStringList &supportedShaderSuffixes();
+ static const QStringList &supportedFontSuffixes();
+ static const QStringList &supportedAudioSuffixes();
+ static const QStringList &supportedVideoSuffixes();
+ static const QStringList &supportedTexture3DSuffixes();
+ static const QStringList &supportedEffectMakerSuffixes();
+ static const QSet &supportedSuffixes();
+
+ const QString suffix() const;
+ const QString id() const;
+ bool hasSuffix() const;
+
+ Type type() const;
+ bool isImage() const;
+ bool isFragmentShader() const;
+ bool isShader() const;
+ bool isFont() const;
+ bool isAudio() const;
+ bool isVideo() const;
+ bool isTexture3D() const;
+ bool isEffect() const;
+ bool isSupported() const;
+
+private:
+ QString m_filePath;
+ QString m_suffix;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/utils/imageutils.cpp b/src/plugins/qmldesigner/utils/imageutils.cpp
new file mode 100644
index 00000000000..c1e3b8f4950
--- /dev/null
+++ b/src/plugins/qmldesigner/utils/imageutils.cpp
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#include "imageutils.h"
+
+#include
+#include
+#include
+
+namespace QmlDesigner {
+
+QString QmlDesigner::ImageUtils::imageInfo(const QString &path)
+{
+ QFileInfo info(path);
+ if (!info.exists())
+ return {};
+
+ int width = 0;
+ int height = 0;
+ if (info.suffix() == "hdr") {
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return {};
+
+ while (!file.atEnd()) {
+ QByteArray line = file.readLine();
+ if (sscanf(line.constData(), "-Y %d +X %d", &height, &width))
+ break;
+ }
+ } else {
+ QSize size = QImageReader(path).size();
+ width = size.width();
+ height = size.height();
+ }
+
+ if (width == 0 && height == 0)
+ return {};
+
+ return QLatin1String("%1 x %2\n%3 (%4)")
+ .arg(QString::number(width),
+ QString::number(height),
+ QLocale::system().formattedDataSize(info.size(), 2, QLocale::DataSizeTraditionalFormat),
+ info.suffix());
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/utils/imageutils.h b/src/plugins/qmldesigner/utils/imageutils.h
new file mode 100644
index 00000000000..3b740b76b1e
--- /dev/null
+++ b/src/plugins/qmldesigner/utils/imageutils.h
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+#pragma once
+
+#include
+
+namespace QmlDesigner {
+
+class ImageUtils
+{
+public:
+ ImageUtils();
+
+ static QString imageInfo(const QString &path);
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp
index 8d7eee5a13c..0211b8d3cd0 100644
--- a/src/plugins/studiowelcome/examplecheckout.cpp
+++ b/src/plugins/studiowelcome/examplecheckout.cpp
@@ -75,13 +75,13 @@ void FileDownloader::start()
auto request = QNetworkRequest(m_url);
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
QNetworkRequest::UserVerifiedRedirectPolicy);
- QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
+ m_reply = Utils::NetworkAccessManager::instance()->get(request);
- QNetworkReply::connect(reply, &QNetworkReply::readyRead, this, [this, reply]() {
- m_tempFile.write(reply->readAll());
+ QNetworkReply::connect(m_reply, &QNetworkReply::readyRead, this, [this]() {
+ m_tempFile.write(m_reply->readAll());
});
- QNetworkReply::connect(reply,
+ QNetworkReply::connect(m_reply,
&QNetworkReply::downloadProgress,
this,
[this](qint64 current, qint64 max) {
@@ -92,16 +92,21 @@ void FileDownloader::start()
emit progressChanged();
});
- QNetworkReply::connect(reply, &QNetworkReply::redirected, [reply](const QUrl &) {
- emit reply->redirectAllowed();
+ QNetworkReply::connect(m_reply, &QNetworkReply::redirected, [this](const QUrl &) {
+ emit m_reply->redirectAllowed();
});
- QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
- if (reply->error()) {
+ QNetworkReply::connect(m_reply, &QNetworkReply::finished, this, [this]() {
+ if (m_reply->error()) {
if (m_tempFile.exists())
m_tempFile.remove();
- qWarning() << Q_FUNC_INFO << m_url << reply->errorString();
- emit downloadFailed();
+
+ if (m_reply->error() != QNetworkReply::OperationCanceledError) {
+ qWarning() << Q_FUNC_INFO << m_url << m_reply->errorString();
+ emit downloadFailed();
+ } else {
+ emit downloadCanceled();
+ }
} else {
m_tempFile.flush();
m_tempFile.close();
@@ -109,9 +114,17 @@ void FileDownloader::start()
emit tempFileChanged();
emit finishedChanged();
}
+
+ m_reply = nullptr;
});
}
+void FileDownloader::cancel()
+{
+ if (m_reply)
+ m_reply->abort();
+}
+
void FileDownloader::setUrl(const QUrl &url)
{
m_url = url;
diff --git a/src/plugins/studiowelcome/examplecheckout.h b/src/plugins/studiowelcome/examplecheckout.h
index 7e7a0dff882..8c1446518c9 100644
--- a/src/plugins/studiowelcome/examplecheckout.h
+++ b/src/plugins/studiowelcome/examplecheckout.h
@@ -112,6 +112,7 @@ public:
bool available() const;
Q_INVOKABLE void start();
+ Q_INVOKABLE void cancel();
signals:
void finishedChanged();
@@ -123,6 +124,8 @@ signals:
void lastModifiedChanged();
void availableChanged();
+ void downloadCanceled();
+
private:
void probeUrl();
@@ -133,6 +136,8 @@ private:
QFile m_tempFile;
QDateTime m_lastModified;
bool m_available = false;
+
+ QNetworkReply *m_reply = nullptr;
};
class DataModelDownloader : public QObject
diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp
index bac6122a86c..25c547e1358 100644
--- a/src/plugins/updateinfo/updateinfoplugin.cpp
+++ b/src/plugins/updateinfo/updateinfoplugin.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
@@ -223,7 +224,12 @@ static void showUpdateInfo(const QList &updates,
label->setText("" + UpdateInfoPlugin::tr("Available updates:") + "
- "
+ qtText + updateText + "
");
label->setContentsMargins(0, 0, 0, 8);
- return label;
+ auto scrollArea = new QScrollArea;
+ scrollArea->setWidget(label);
+ scrollArea->setFrameShape(QFrame::NoFrame);
+ scrollArea->viewport()->setAutoFillBackground(false);
+ label->setAutoFillBackground(false);
+ return scrollArea;
});
}
ICore::infoBar()->removeInfo(InstallUpdates); // remove any existing notifications
diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt
index 88da74ea363..9703bb2cdb9 100644
--- a/src/tools/qml2puppet/CMakeLists.txt
+++ b/src/tools/qml2puppet/CMakeLists.txt
@@ -23,6 +23,8 @@ if (NOT QT_CREATOR_API_DEFINED)
)
endif()
+configure_file(../../app/app_version.h.cmakein app/app_version.h ESCAPE_QUOTES)
+
if (NOT TARGET QmlPuppetCommunication)
include(../../libs/qmlpuppetcommunication/QmlPuppetCommunication.cmake)
endif()
@@ -34,13 +36,34 @@ add_qtc_executable(qml2puppet
Qt5::CorePrivate Qt5::Widgets Qt5::QmlPrivate
Qt5::QuickPrivate Qt5::Network Qt5::GuiPrivate
QmlPuppetCommunication
+ INCLUDES
+ ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
SOURCES
- qml2puppet/qml2puppetmain.cpp
+ qml2puppet/main.cpp
+ qml2puppet/qmlbase.h qml2puppet/appmetadata.h
+ qml2puppet/qmlpuppet.h qml2puppet/qmlpuppet.cpp qml2puppet/configcrashpad.h
qmlpuppet.qrc
PROPERTIES
OUTPUT_NAME qml2puppet-${IDE_VERSION}
)
+if(TARGET qml2puppet)
+ execute_process(
+ COMMAND git describe --tags --always --dirty=+
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ RESULT_VARIABLE GIT_SHA_RESULT
+ OUTPUT_VARIABLE GIT_SHA_OUTPUT
+ ERROR_VARIABLE GIT_SHA_ERROR
+ )
+
+ #if we are not a git repository use the .tag file
+ if(NOT GIT_SHA_OUTPUT)
+ file(READ ${CMAKE_CURRENT_SOURCE_DIR}/../../../.tag GIT_SHA_OUTPUT)
+ endif()
+
+ add_definitions( -D GIT_SHA=${GIT_SHA_OUTPUT} )
+endif()
+
extend_qtc_executable(qml2puppet
CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0
SOURCES
@@ -191,10 +214,27 @@ extend_qtc_executable(qml2puppet
DEPENDS Nanotrace
)
-if (QTC_STATIC_BUILD AND Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0)
- qt6_import_qml_plugins(qml2puppet PATH_TO_SCAN ${SRCDIR})
+if (Qt5_VERSION VERSION_GREATER_EQUAL 6.4.0)
+ extend_qtc_executable(qml2puppet
+ DEFINES ENABLE_INTERNAL_QML_RUNTIME
+ PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/qml2puppet/runner
+ SOURCES_PREFIX qml2puppet/runner
+ SOURCES
+ qmlruntime.h qmlruntime.cpp
+ qmlconfiguration.h loadwatcher.h
+ )
+
+ # Turn the tool into its own self-contained qml module
+ qt_add_qml_module(qml2puppet
+ URI QmlRuntime.QmlConfiguration
+ VERSION 1.0
+ )
+ if (QTC_STATIC_BUILD)
+ qt_import_qml_plugins(qml2puppet PATH_TO_SCAN ${SRCDIR})
+ endif()
endif()
+
# Crashpad
# only windows requires separate crashpad client per process until client->SetHandlerIPCPipe()
# is implemented (check the TODO inside startCrashpad())
diff --git a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
index 819f1e2be90..7f7b148460b 100644
--- a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
+++ b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
@@ -194,24 +194,18 @@ Item {
function updateViewStates(viewStates)
{
if ("selectBackgroundColor" in viewStates) {
- if (Array.isArray(viewStates.selectBackgroundColor)) {
- var colors = viewStates.selectBackgroundColor
- if (colors.length === 1) {
- backgroundGradientColorStart = colors[0];
- backgroundGradientColorEnd = colors[0];
- } else {
- backgroundGradientColorStart = colors[0];
- backgroundGradientColorEnd = colors[1];
- }
+ var colors = viewStates.selectBackgroundColor
+ if (colors.length === 1) {
+ backgroundGradientColorStart = colors[0];
+ backgroundGradientColorEnd = colors[0];
} else {
- var color = viewStates.selectBackgroundColor
- backgroundGradientColorStart = color;
- backgroundGradientColorEnd = color;
+ backgroundGradientColorStart = colors[0];
+ backgroundGradientColorEnd = colors[1];
}
}
- if ("selectGridColor" in viewStates)
- viewRoot.gridColor = viewStates.selectGridColor
+ if ("selectGridColor" in viewStates && viewStates.selectGridColor.length === 1)
+ viewRoot.gridColor = viewStates.selectGridColor[0]
}
// If resetToDefault is true, tool states not specifically set to anything will be reset to
diff --git a/src/tools/qml2puppet/qml2puppet/appmetadata.h b/src/tools/qml2puppet/qml2puppet/appmetadata.h
new file mode 100644
index 00000000000..7f11276e619
--- /dev/null
+++ b/src/tools/qml2puppet/qml2puppet/appmetadata.h
@@ -0,0 +1,96 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH
+// Qt-GPL-exception-1.0
+#pragma once
+
+#include
+#include
+
+#include
+
+// Common functions can be used in all QDS apps
+namespace QDSMeta {
+
+namespace Logging {
+inline Q_LOGGING_CATEGORY(deprecated, "qt.tools.qds.deprecated");
+inline Q_LOGGING_CATEGORY(verbose1, "qt.tools.qds.verbose1");
+inline Q_LOGGING_CATEGORY(verbose2, "qt.tools.qds.verbose2");
+
+inline void registerMessageHandler()
+{
+ qInstallMessageHandler(
+ [](QtMsgType type, const QMessageLogContext &context, const QString &msg) {
+ auto tPrinter = [&](const QString &msgPrefix) {
+ fprintf(stderr,
+ "%s: %s (%s:%u, %s)\n",
+ msgPrefix.toLocal8Bit().constData(),
+ msg.toLocal8Bit().constData(),
+ context.file,
+ context.line,
+ context.function);
+ };
+
+ if (type == QtDebugMsg)
+ tPrinter("Debug");
+ else if (type == QtInfoMsg)
+ tPrinter("Info");
+ else if (type == QtWarningMsg)
+ tPrinter("Warning");
+ else if (type == QtCriticalMsg)
+ tPrinter("Critical");
+ else if (type == QtFatalMsg) {
+ tPrinter("Fatal");
+ abort();
+ }
+ });
+}
+} // namespace Logging
+
+namespace AppInfo {
+
+#define STRINGIFY_INTERNAL(x) #x
+#define QDS_STRINGIFY(x) STRINGIFY_INTERNAL(x)
+
+inline void printAppInfo()
+{
+ qInfo() << Qt::endl
+ << "<< QDS Meta Info >>" << Qt::endl
+ << "App Info" << Qt::endl
+ << " - Name :" << Core::Constants::IDE_ID << Qt::endl
+ << " - Version :" << Core::Constants::IDE_VERSION_DISPLAY << Qt::endl
+ << " - Author :" << Core::Constants::IDE_AUTHOR << Qt::endl
+ << " - Year :" << Core::Constants::IDE_YEAR << Qt::endl
+ << " - App :" << QCoreApplication::applicationName() << Qt::endl
+ << "Build Info " << Qt::endl
+ << " - Date :" << __DATE__ << Qt::endl
+ << " - Commit :" << QStringLiteral(QDS_STRINGIFY(GIT_SHA)) << Qt::endl
+ << " - Qt Version :" << QT_VERSION_STR << Qt::endl
+ << "Compiler Info " << Qt::endl
+#if defined(__GNUC__)
+ << " - GCC :" << __GNUC__ << Qt::endl
+ << " - GCC Minor :" << __GNUC_MINOR__ << Qt::endl
+ << " - GCC Patch :" << __GNUC_PATCHLEVEL__ << Qt::endl
+#endif
+#if defined(_MSC_VER)
+ << " - MSC Short :" << _MSC_VER << Qt::endl
+ << " - MSC Full :" << _MSC_FULL_VER << Qt::endl
+#endif
+#if defined(__clang__)
+ << " - clang maj :" << __clang_major__ << Qt::endl
+ << " - clang min :" << __clang_minor__ << Qt::endl
+ << " - clang patch :" << __clang_patchlevel__ << Qt::endl
+#endif
+ << "<< End Of QDS Meta Info >>" << Qt::endl;
+ exit(0);
+}
+
+inline void registerAppInfo(const QString &appName)
+{
+ QCoreApplication::setOrganizationName(Core::Constants::IDE_AUTHOR);
+ QCoreApplication::setOrganizationDomain("qt-project.org");
+ QCoreApplication::setApplicationName(appName);
+ QCoreApplication::setApplicationVersion(Core::Constants::IDE_VERSION_LONG);
+}
+
+} // namespace AppInfo
+} // namespace QDSMeta
diff --git a/src/tools/qml2puppet/qml2puppet/configcrashpad.h b/src/tools/qml2puppet/qml2puppet/configcrashpad.h
new file mode 100644
index 00000000000..7b663b84498
--- /dev/null
+++ b/src/tools/qml2puppet/qml2puppet/configcrashpad.h
@@ -0,0 +1,66 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
+#pragma once
+
+#include
+
+#ifdef ENABLE_QT_BREAKPAD
+#include
+#endif
+
+#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
+#define NOMINMAX
+#include "client/crash_report_database.h"
+#include "client/crashpad_client.h"
+#include "client/settings.h"
+#endif
+
+namespace {
+#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
+ bool startCrashpad()
+ {
+ using namespace crashpad;
+
+ // Cache directory that will store crashpad information and minidumps
+ base::FilePath database(L"crashpad_reports");
+ base::FilePath handler(L"crashpad_handler.exe");
+
+ // URL used to submit minidumps to
+ std::string url(CRASHPAD_BACKEND_URL);
+
+ // Optional annotations passed via --annotations to the handler
+ std::map annotations;
+ annotations["qt-version"] = QT_VERSION_STR;
+
+ // Optional arguments to pass to the handler
+ std::vector arguments;
+ arguments.push_back("--no-rate-limit");
+
+ CrashpadClient *client = new CrashpadClient();
+ bool success = client->StartHandler(handler,
+ database,
+ database,
+ url,
+ annotations,
+ arguments,
+ /* restartable */ true,
+ /* asynchronous_start */ true);
+ // TODO: research using this method, should avoid creating a separate CrashpadClient for the
+ // puppet (needed only on windows according to docs).
+ // client->SetHandlerIPCPipe(L"\\\\.\\pipe\\qml2puppet");
+
+ return success;
+ }
+
+#ifdef ENABLE_QT_BREAKPAD
+ const QString libexecPath = QCoreApplication::applicationDirPath() + '/'
+ + RELATIVE_LIBEXEC_PATH;
+ QtSystemExceptionHandler systemExceptionHandler(libexecPath);
+#endif //#ifdef ENABLE_QT_BREAKPAD
+#else //#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
+ bool startCrashpad()
+ {
+ return false;
+ }
+#endif //#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
+}
diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp
index d3209e4ccbe..05692d000bd 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp
@@ -1043,6 +1043,21 @@ QList NodeInstanceServer::allGroupStateInstances() const
return groups;
}
+QList NodeInstanceServer::allView3DInstances() const
+{
+ QList view3Ds;
+ std::copy_if(nodeInstances().cbegin(),
+ nodeInstances().cend(),
+ std::back_inserter(view3Ds),
+ [](const ServerNodeInstance &instance) {
+ return instance.isValid()
+ && ServerNodeInstance::isSubclassOf(instance.internalObject(),
+ QByteArrayLiteral("QQuick3DViewport"));
+ });
+
+ return view3Ds;
+}
+
void NodeInstanceServer::setStateInstance(const ServerNodeInstance &stateInstance)
{
m_activeStateInstance = stateInstance;
diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h
index 59236a236fc..70b0c841859 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h
+++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h
@@ -179,6 +179,7 @@ public:
ServerNodeInstance rootNodeInstance() const;
QList allGroupStateInstances() const;
+ QList allView3DInstances() const;
void notifyPropertyChange(qint32 instanceid, const PropertyName &propertyName);
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index f71d1ebde8b..a84409b3331 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -921,9 +921,9 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D([[maybe_unu
if (toolStates.contains("syncBackgroundColor")) {
bool sync = toolStates["syncBackgroundColor"].toBool();
if (sync) {
- QColor color = helper->sceneEnvironmentColor(sceneId);
+ QList colors{helper->sceneEnvironmentColor(sceneId)};
View3DActionCommand cmd(View3DActionType::SelectBackgroundColor,
- QVariant::fromValue(color));
+ QVariant::fromValue(colors));
view3DAction(cmd);
}
}
@@ -2276,9 +2276,10 @@ void Qt5InformationNodeInstanceServer::setSceneEnvironmentColor(const PropertyVa
if (toolStates.contains("syncBackgroundColor")) {
bool sync = toolStates["syncBackgroundColor"].toBool();
+ QList colors{color};
if (sync) {
View3DActionCommand cmd(View3DActionType::SelectBackgroundColor,
- QVariant::fromValue(color));
+ QVariant::fromValue(colors));
view3DAction(cmd);
}
}
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
index 6f3fced1b78..125a128594d 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
@@ -53,28 +53,41 @@ void Qt5PreviewNodeInstanceServer::collectItemChangesAndSendChangeCommands()
QQuickDesignerSupport::polishItems(quickWindow());
QVector imageContainerVector;
+
+ // Base state needs to be rendered twice to properly render shared resources,
+ // if there is more than one View3D and at least one of them is dirty.
+ bool dirtyView3d = false;
+ const QList view3dInstances = allView3DInstances();
+ for (const auto &instance : view3dInstances) {
+ if (QQuickDesignerSupport::isDirty(instance.rootQuickItem(),
+ QQuickDesignerSupport::ContentUpdateMask)) {
+ dirtyView3d = true;
+ break;
+ }
+ }
+ if (dirtyView3d)
+ renderPreviewImage();
imageContainerVector.append(ImageContainer(0, renderPreviewImage(), -1));
- QList stateInstances = rootNodeInstance().stateInstances();
+ QList stateInstances = rootNodeInstance().stateInstances();
- const QList groupInstances = allGroupStateInstances();
+ const QList groupInstances = allGroupStateInstances();
- for (ServerNodeInstance instance : groupInstances) {
- stateInstances.append(instance.stateInstances());
- }
+ for (const ServerNodeInstance &instance : groupInstances)
+ stateInstances.append(instance.stateInstances());
- for (ServerNodeInstance instance : std::as_const(stateInstances)) {
- instance.activateState();
- QImage previewImage = renderPreviewImage();
- if (!previewImage.isNull())
- imageContainerVector.append(ImageContainer(instance.instanceId(),
- renderPreviewImage(),
- instance.instanceId()));
- instance.deactivateState();
- }
+ for (ServerNodeInstance instance : std::as_const(stateInstances)) {
+ instance.activateState();
+ QImage previewImage = renderPreviewImage();
+ if (!previewImage.isNull())
+ imageContainerVector.append(ImageContainer(instance.instanceId(),
+ renderPreviewImage(),
+ instance.instanceId()));
+ instance.deactivateState();
+ }
nodeInstanceClient()->statePreviewImagesChanged(
- StatePreviewImageChangedCommand(imageContainerVector));
+ StatePreviewImageChangedCommand(imageContainerVector));
slowDownRenderTimer();
handleExtraRender();
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
index b1af7fb4f6d..c237b9451b3 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
@@ -56,6 +56,7 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
if (quickWindow() && nodeInstanceClient()->bytesToWrite() < 10000) {
bool windowDirty = false;
+ bool hasView3D = false;
for (QQuickItem *item : allItems()) {
if (item) {
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
@@ -65,8 +66,13 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
}
} else {
if (hasInstanceForObject(item)) {
- if (QQuickDesignerSupport::isDirty(item, QQuickDesignerSupport::ContentUpdateMask))
+ if (QQuickDesignerSupport::isDirty(item, QQuickDesignerSupport::ContentUpdateMask)) {
+ if (!hasView3D && ServerNodeInstance::isSubclassOf(
+ item, QByteArrayLiteral("QQuick3DViewport"))) {
+ hasView3D = true;
+ }
m_dirtyInstanceSet.insert(instanceForObject(item));
+ }
if (QQuickItem *effectParent = parentEffectItem(item)) {
if ((QQuickDesignerSupport::isDirty(
item,
@@ -100,9 +106,19 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()}));
} else {
if (!m_dirtyInstanceSet.isEmpty()) {
- nodeInstanceClient()->pixmapChanged(
- createPixmapChangedCommand(QtHelpers::toList(m_dirtyInstanceSet)));
- m_dirtyInstanceSet.clear();
+ auto renderList = QtHelpers::toList(m_dirtyInstanceSet);
+
+ // If there is a View3D to be rendered, add all other View3Ds to be rendered
+ // as well, in case they share materials.
+ if (hasView3D) {
+ const QList view3Ds = allView3DInstances();
+ for (auto &view3D : view3Ds) {
+ if (!m_dirtyInstanceSet.contains(view3D))
+ renderList.append(view3D);
+ }
+ }
+
+ nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(renderList));
}
}
diff --git a/src/tools/qml2puppet/qml2puppet/main.cpp b/src/tools/qml2puppet/qml2puppet/main.cpp
new file mode 100644
index 00000000000..84f273a31cb
--- /dev/null
+++ b/src/tools/qml2puppet/qml2puppet/main.cpp
@@ -0,0 +1,31 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#include "qmlpuppet.h"
+
+#ifdef ENABLE_INTERNAL_QML_RUNTIME
+#include "runner/qmlruntime.h"
+#endif
+
+QmlBase *getQmlRunner(int &argc, char **argv)
+{
+#ifdef ENABLE_INTERNAL_QML_RUNTIME
+ for (int i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "--qml-runtime")){
+ qInfo() << "Starting QML Runtime";
+ return new QmlRuntime(argc, argv);
+ }
+ }
+#endif
+ qInfo() << "Starting QML Puppet";
+ return new QmlPuppet(argc, argv);
+}
+
+int main(int argc, char *argv[])
+{
+ QDSMeta::Logging::registerMessageHandler();
+ QDSMeta::AppInfo::registerAppInfo("Qml2Puppet");
+
+ QmlBase *qmlRunner = getQmlRunner(argc, argv);
+ return qmlRunner->run();
+}
diff --git a/src/tools/qml2puppet/qml2puppet/qml2puppetmain.cpp b/src/tools/qml2puppet/qml2puppet/qml2puppetmain.cpp
deleted file mode 100644
index 2d7518b81bc..00000000000
--- a/src/tools/qml2puppet/qml2puppet/qml2puppetmain.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
-
-#include "iconrenderer/iconrenderer.h"
-#include "import3d/import3d.h"
-
-#include
-#ifdef MULTILANGUAGE_TRANSLATIONPROVIDER
-#include
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#ifdef ENABLE_QT_BREAKPAD
-#include
-#endif
-
-#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
-#define NOMINMAX
-#include "client/crashpad_client.h"
-#include "client/crash_report_database.h"
-#include "client/settings.h"
-#endif
-
-#ifdef Q_OS_WIN
-#include
-#endif
-
-namespace {
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
-{
- QByteArray localMsg = msg.toLocal8Bit();
- switch (type) {
- case QtDebugMsg:
- fprintf(stderr,
- "Debug: %s (%s:%u, %s)\n",
- localMsg.constData(),
- context.file,
- context.line,
- context.function);
- break;
- case QtInfoMsg:
- fprintf(stderr,
- "Info: %s (%s:%u, %s)\n",
- localMsg.constData(),
- context.file,
- context.line,
- context.function);
- break;
- case QtWarningMsg:
- fprintf(stderr,
- "Warning: %s (%s:%u, %s)\n",
- localMsg.constData(),
- context.file,
- context.line,
- context.function);
- break;
- case QtCriticalMsg:
- fprintf(stderr,
- "Critical: %s (%s:%u, %s)\n",
- localMsg.constData(),
- context.file,
- context.line,
- context.function);
- break;
- case QtFatalMsg:
- fprintf(stderr,
- "Fatal: %s (%s:%u, %s)\n",
- localMsg.constData(),
- context.file,
- context.line,
- context.function);
- abort();
- }
-}
-#endif
-
-#if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN)
-bool startCrashpad()
-{
- using namespace crashpad;
-
- // Cache directory that will store crashpad information and minidumps
- base::FilePath database(L"crashpad_reports");
- base::FilePath handler(L"crashpad_handler.exe");
-
- // URL used to submit minidumps to
- std::string url(CRASHPAD_BACKEND_URL);
-
- // Optional annotations passed via --annotations to the handler
- std::map annotations;
- annotations["qt-version"] = QT_VERSION_STR;
-
- // Optional arguments to pass to the handler
- std::vector arguments;
- arguments.push_back("--no-rate-limit");
-
- CrashpadClient *client = new CrashpadClient();
- bool success = client->StartHandler(
- handler,
- database,
- database,
- url,
- annotations,
- arguments,
- /* restartable */ true,
- /* asynchronous_start */ true
- );
- // TODO: research using this method, should avoid creating a separate CrashpadClient for the
- // puppet (needed only on windows according to docs).
-// client->SetHandlerIPCPipe(L"\\\\.\\pipe\\qml2puppet");
-
- return success;
-}
-#endif
-
-int internalMain(QGuiApplication *application)
-{
- QCoreApplication::setOrganizationName("QtProject");
- QCoreApplication::setOrganizationDomain("qt-project.org");
- QCoreApplication::setApplicationName("Qml2Puppet");
- QCoreApplication::setApplicationVersion("1.0.0");
-
- if (application->arguments().count() < 2
- || (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() < 3)
- || (application->arguments().at(1) == "--rendericon" && application->arguments().count() < 5)
- || (application->arguments().at(1) == "--import3dAsset" && application->arguments().count() < 6)) {
- qDebug() << "Usage:\n";
- qDebug() << "--test";
- qDebug() << "--version";
- qDebug() << "--readcapturedstream [control stream file]";
- qDebug() << "--rendericon ";
- qDebug() << "--import3dAsset