Merge remote-tracking branch 'origin/8.0' into 9.0
Conflicts: doc/qtcreator/src/qtquick/qt-design-viewer.qdoc src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp src/plugins/qmldesigner/designercore/model/abstractview.cpp src/plugins/qmldesigner/designercore/model/import.cpp src/plugins/qmldesigner/designercore/model/model_p.h src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp src/plugins/qmlprojectmanager/qmlproject.cpp Change-Id: I4236bf0da9306abf201f4679259e72dd7c1eddbe
@@ -3,13 +3,8 @@
|
||||
|
||||
/*!
|
||||
\page qt-design-viewer.html
|
||||
\if defined(qtdesignstudio)
|
||||
\previouspage creator-live-preview-android.html
|
||||
\nextpage studio-exporting-and-importing.html
|
||||
\else
|
||||
\previouspage creator-live-preview-devices.html
|
||||
\nextpage creator-building-targets.html
|
||||
\endif
|
||||
|
||||
\title Previewing in Browsers
|
||||
|
||||
@@ -24,24 +19,17 @@
|
||||
However, the actual performance of the application once started is
|
||||
indistinguishable from the same application running on the desktop.
|
||||
|
||||
\if defined(qtdesignstudio)
|
||||
To create a resource file out of your project, select \uicontrol Build >
|
||||
\uicontrol {Generate Resource File} in \QC. Then upload the package into
|
||||
\QDV.
|
||||
\else
|
||||
You can run \l{Creating Qt Quick UI Projects}{Qt Quick UI projects}, which
|
||||
have a .qmlproject file that define the main QML file and the import paths.
|
||||
Compress the project folder into a ZIP file that you upload to \QDV.
|
||||
\endif
|
||||
|
||||
The loaded applications remain locally in your browser. No data is uploaded
|
||||
into the cloud.
|
||||
|
||||
To preview an application in a web browser:
|
||||
|
||||
\list
|
||||
\li In the browser, open \l{http://qt-webassembly.io/designviewer/}
|
||||
{\QDV}.
|
||||
\list 1
|
||||
\li In the browser, open \l{ https://designviewer.qt.io/}{\QDV}.
|
||||
\li Drag and drop your application package to \QDV, or click the load
|
||||
icon to browse for your file.
|
||||
\endlist
|
||||
@@ -57,10 +57,15 @@
|
||||
You can preview Android applications live using an Android
|
||||
emulator.
|
||||
|
||||
\endif
|
||||
\li \l{Sharing Applications Online}
|
||||
|
||||
You can share applications online and view them in a web browser.
|
||||
|
||||
\else
|
||||
\li \l{Previewing in Browsers}
|
||||
|
||||
You can open \l{https://qt-webassembly.io/designviewer/}{\QDV}
|
||||
You can open \l{https://designviewer.qt.io/}{\QDV}
|
||||
in a browser and load applications to it.
|
||||
\endif
|
||||
\endlist
|
||||
*/
|
||||
|
||||
BIN
doc/qtdesignstudio/images/extended-state.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
doc/qtdesignstudio/images/no-extended-state.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 10 KiB |
BIN
doc/qtdesignstudio/images/qt-design-viewer.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
doc/qtdesignstudio/images/share-online-manage.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
doc/qtdesignstudio/images/share-online.webp
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
doc/qtdesignstudio/images/states-view-menu.png
Normal file
|
After Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.1 KiB |
43
doc/qtdesignstudio/src/overviews/qt-design-viewer.qdoc
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\page qt-design-viewer.html
|
||||
\previouspage creator-live-preview-android.html
|
||||
\nextpage studio-exporting-and-importing.html
|
||||
|
||||
\title Sharing Applications Online
|
||||
|
||||
\image qt-design-viewer.webp
|
||||
|
||||
In \QDS, you can share your applications in most widely-used web browsers,
|
||||
such as Apple Safari, Google Chrome, Microsoft Edge, and Mozilla Firefox,
|
||||
on the desktop and on mobile devices.
|
||||
|
||||
The application shared online runs in Qt Design Viewer, which is a QML
|
||||
viewer that runs in your web browser.
|
||||
|
||||
The startup and compilation time depend on your browser and configuration.
|
||||
However, the actual performance of the application once started is
|
||||
indistinguishable from the same application running on the desktop.
|
||||
|
||||
The loaded applications remain locally in your browser. No data is uploaded
|
||||
into the cloud.
|
||||
|
||||
\section1 Sharing your Application Online
|
||||
|
||||
To share your \QDS application online:
|
||||
|
||||
\list 1
|
||||
\li Open the application in \QDS.
|
||||
\li Select \uicontrol File > \uicontrol {Share Application Online}.
|
||||
\li In the dialog, select \uicontrol Share.
|
||||
\image share-online.webp
|
||||
\endlist
|
||||
|
||||
In the dialog, you can now open the application in a web
|
||||
browser, copy the link to share with others, or manage your shared
|
||||
applications.
|
||||
|
||||
\image share-online-manage.webp
|
||||
*/
|
||||
@@ -131,7 +131,7 @@
|
||||
\li \l{Previewing on Desktop}
|
||||
\li \l{Previewing on Devices}
|
||||
\li \l{Previewing Android Applications}
|
||||
\li \l{Previewing in Browsers}
|
||||
\li \l{Sharing Applications Online}
|
||||
\endlist
|
||||
\li \l {Asset Creation with Other Tools}
|
||||
\list
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
\page qtquick-states-view.html
|
||||
\previouspage qtquick-connection-view.html
|
||||
\nextpage studio-translations.html
|
||||
\sa {Working with States}
|
||||
|
||||
\title States
|
||||
|
||||
@@ -25,48 +26,4 @@
|
||||
|
||||
\youtube FzmLuRHQXaw
|
||||
|
||||
\section1 Summary of States View Actions
|
||||
|
||||
To open the \uicontrol Actions menu, select
|
||||
\inlineimage icons/action-icon.png
|
||||
. The actions available in the menu depend on the current context. For
|
||||
example, the option for editing an annotation becomes available after
|
||||
you add an annotation.
|
||||
|
||||
\table
|
||||
\header
|
||||
\li Action
|
||||
\li Purpose
|
||||
\li Read More
|
||||
\row
|
||||
\li \uicontrol {Set when Condition}
|
||||
\li Determines when a state should be applied.
|
||||
\li \l{Applying States}
|
||||
\row
|
||||
\li \uicontrol {Reset when Condition}
|
||||
\li Removes \c when condition for the state.
|
||||
\li \l{Applying States}
|
||||
\row
|
||||
\li \uicontrol {Set as Default}
|
||||
\li Sets the current state as the startup state of the application.
|
||||
\li \l{Setting the Default State}
|
||||
\row
|
||||
\li\uicontrol {Reset Default}
|
||||
\li Resets the current state as the default state.
|
||||
\li \l{Setting the Default State}
|
||||
\row
|
||||
\li \uicontrol {Add Annotation}
|
||||
\li Opens the \uicontrol {Annotation Editor} when you can add an
|
||||
annotation for the states that you create.
|
||||
\li \l{Annotating Designs}
|
||||
\row
|
||||
\li \uicontrol {Edit Annotation}
|
||||
\li Opens the \uicontrol {Annotation Editor} where you can edit the
|
||||
annotation for the state.
|
||||
\li \l{Annotating Designs}
|
||||
\row
|
||||
\li \uicontrol {Add Annotation}
|
||||
\li Removes the annotation for the state.
|
||||
\li \l{Annotating Designs}
|
||||
\endtable
|
||||
*/
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
\image qmldesigner-transitions.png "States view"
|
||||
|
||||
Click the new state to switch to it in the \l {2D} view, and then modify the
|
||||
values of the properties of components or component instances in
|
||||
\l Properties.
|
||||
Click the new state to switch to it in the \l {2D} and \l{3D} views, and
|
||||
then modify the values of the properties of components or component
|
||||
instances in \l Properties.
|
||||
|
||||
For example, to change the appearance of a button, you can define states in
|
||||
the button component to hide the button image and show another image in its
|
||||
@@ -60,21 +60,17 @@
|
||||
|
||||
\section1 Setting the Default State
|
||||
|
||||
To determine the startup state of the application,
|
||||
select \inlineimage icons/action-icon.png
|
||||
to open the \uicontrol Actions menu, and then select
|
||||
\uicontrol {Set as Default}.
|
||||
The default state determines the startup state of the application.
|
||||
|
||||
To reset the state later, select \uicontrol Actions >
|
||||
\uicontrol {Reset Default}.
|
||||
To set a state to the default state, select \uicontrol Default.
|
||||
|
||||
\section1 Applying States
|
||||
|
||||
To determine when a state should be applied, select \uicontrol Actions >
|
||||
\uicontrol {Set when Condition}. In \uicontrol {Binding Editor}, specify
|
||||
a \l [QtQuick]{State::when}{when} property for the state. Set the value of
|
||||
the property to a boolean expression that evaluates to \c true when you want
|
||||
the state to be applied.
|
||||
To determine when a state is applied, select \inlineimage icons/edit.png
|
||||
in the \uicontrol {When Condition} field. In \uicontrol {Binding Editor},
|
||||
specify a \l [QtQuick]{State::when}{when} property for the state. Set the
|
||||
value of the property to a boolean expression that evaluates to \c true when
|
||||
you want the state to be applied.
|
||||
|
||||
This enables you to evaluate the truthfulness of several components'
|
||||
properties and move the UI to the state in which these conditions apply.
|
||||
@@ -170,10 +166,40 @@
|
||||
\li Create additional states for each view and set the visibility
|
||||
or opacity of the components in the view.
|
||||
\li To determine which state is applied when the application starts,
|
||||
select \uicontrol Actions > \uicontrol {Set as Default}.
|
||||
select \uicontrol Default.
|
||||
\endlist
|
||||
|
||||
\if defined(qtcreator)
|
||||
\include qtquick-states-scxml.qdocinc scxml state machines
|
||||
\endif
|
||||
|
||||
\section1 State Groups
|
||||
|
||||
With state groups, you can change the state of certain components
|
||||
independently of other components and their states in the same view.
|
||||
|
||||
Each state group has its own property changes and transitions.
|
||||
|
||||
By default, there is one root state group.
|
||||
|
||||
\section1 Extending States
|
||||
|
||||
When a state extends another state, it inherits all the changes of that
|
||||
state. The state being extended is treated as the base state in regards to
|
||||
the changes specified by the extending state.
|
||||
|
||||
Using extended states can make the user interface and your QML code
|
||||
cleaner.
|
||||
|
||||
Below is an example where the only change between \e State1 and \e State2
|
||||
is the brightness of \e directionalLight.
|
||||
|
||||
Here, extended states are not used:
|
||||
|
||||
\image no-extended-state.webp
|
||||
|
||||
Here, \e State2 is extended from \e State1:
|
||||
|
||||
\image extended-state.webp
|
||||
|
||||
*/
|
||||
|
||||
@@ -162,6 +162,7 @@ ScrollView { // TODO: experiment using ListView instead of ScrollView + Column
|
||||
|
||||
readonly property string suffix: fileName.substr(-4)
|
||||
readonly property bool isFont: suffix === ".ttf" || suffix === ".otf"
|
||||
readonly property bool isEffect: suffix === ".qep"
|
||||
property bool currFileSelected: false
|
||||
|
||||
MouseArea {
|
||||
@@ -180,7 +181,7 @@ ScrollView { // TODO: experiment using ListView instead of ScrollView + Column
|
||||
allowTooltip = true
|
||||
}
|
||||
onPositionChanged: tooltipBackend.reposition()
|
||||
onPressed: (mouse)=> {
|
||||
onPressed: (mouse) => {
|
||||
forceActiveFocus()
|
||||
allowTooltip = false
|
||||
tooltipBackend.hideTooltip()
|
||||
@@ -212,7 +213,7 @@ ScrollView { // TODO: experiment using ListView instead of ScrollView + Column
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: (mouse)=> {
|
||||
onReleased: (mouse) => {
|
||||
allowTooltip = true
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (!(mouse.modifiers & Qt.ControlModifier))
|
||||
@@ -222,6 +223,14 @@ ScrollView { // TODO: experiment using ListView instead of ScrollView + Column
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: (mouse) => {
|
||||
forceActiveFocus()
|
||||
allowTooltip = false
|
||||
tooltipBackend.hideTooltip()
|
||||
if (mouse.button === Qt.LeftButton && isEffect)
|
||||
rootView.openEffectMaker(filePath)
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
visible: !isFont && mouseArea.containsMouse && !contextMenu.visible
|
||||
text: filePath
|
||||
|
||||
@@ -241,10 +241,15 @@ Item {
|
||||
|
||||
delegate: Section {
|
||||
width: root.width
|
||||
caption: bundleCategory
|
||||
caption: bundleCategoryName
|
||||
addTopPadding: false
|
||||
sectionBackgroundColor: "transparent"
|
||||
visible: bundleCategoryVisible
|
||||
expanded: bundleCategoryExpanded
|
||||
expandOnClick: false
|
||||
onToggleExpand: bundleCategoryExpanded = !bundleCategoryExpanded
|
||||
onExpand: bundleCategoryExpanded = true
|
||||
onCollapse: bundleCategoryExpanded = false
|
||||
|
||||
Grid {
|
||||
width: scrollView.width
|
||||
@@ -254,7 +259,7 @@ Item {
|
||||
columns: root.width / root.cellWidth
|
||||
|
||||
Repeater {
|
||||
model: bundleMaterialsModel
|
||||
model: bundleCategoryMaterials
|
||||
|
||||
delegate: BundleMaterialItem {
|
||||
width: root.cellWidth
|
||||
|
||||
@@ -80,6 +80,10 @@ StudioControls.Menu {
|
||||
root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.principledMaterialSections);
|
||||
break;
|
||||
|
||||
case "SpecularGlossyMaterial":
|
||||
root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.specularGlossyMaterialSections);
|
||||
break;
|
||||
|
||||
case "CustomMaterial":
|
||||
root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.customMaterialSections);
|
||||
break;
|
||||
|
||||
@@ -401,6 +401,7 @@ Item {
|
||||
ListElement { name: "Qt 5.15" }
|
||||
ListElement { name: "Qt 6.2" }
|
||||
ListElement { name: "Qt 6.3" }
|
||||
ListElement { name: "Qt 6.4" }
|
||||
}
|
||||
|
||||
onActivated: (index) => {
|
||||
|
||||
@@ -50,10 +50,19 @@ Item {
|
||||
Connections {
|
||||
target: Controller
|
||||
function onCollapseAll() {
|
||||
if (collapsible)
|
||||
section.expanded = false
|
||||
if (collapsible) {
|
||||
if (section.expandOnClick)
|
||||
section.expanded = false
|
||||
else
|
||||
section.collapse()
|
||||
}
|
||||
}
|
||||
function onExpandAll() {
|
||||
if (section.expandOnClick)
|
||||
section.expanded = true
|
||||
else
|
||||
section.expand()
|
||||
}
|
||||
function onExpandAll() { section.expanded = true }
|
||||
}
|
||||
|
||||
signal drop(var drag)
|
||||
@@ -61,6 +70,8 @@ Item {
|
||||
signal dropExit()
|
||||
signal showContextMenu()
|
||||
signal toggleExpand()
|
||||
signal expand()
|
||||
signal collapse()
|
||||
|
||||
DropArea {
|
||||
id: dropArea
|
||||
|
||||
@@ -49,126 +49,128 @@ QtObject {
|
||||
readonly property string centerHorizontal: "\u0042"
|
||||
readonly property string centerVertical: "\u0043"
|
||||
readonly property string closeCross: "\u0044"
|
||||
readonly property string colorPopupClose: "\u0045"
|
||||
readonly property string columnsAndRows: "\u0046"
|
||||
readonly property string copyStyle: "\u0047"
|
||||
readonly property string cornerA: "\u0048"
|
||||
readonly property string cornerB: "\u0049"
|
||||
readonly property string cornersAll: "\u004A"
|
||||
readonly property string curveDesigner: "\u004B"
|
||||
readonly property string curveEditor: "\u004C"
|
||||
readonly property string customMaterialEditor: "\u004D"
|
||||
readonly property string decisionNode: "\u004E"
|
||||
readonly property string deleteColumn: "\u004F"
|
||||
readonly property string deleteMaterial: "\u0050"
|
||||
readonly property string deleteRow: "\u0051"
|
||||
readonly property string deleteTable: "\u0052"
|
||||
readonly property string detach: "\u0053"
|
||||
readonly property string distributeBottom: "\u0054"
|
||||
readonly property string distributeCenterHorizontal: "\u0055"
|
||||
readonly property string distributeCenterVertical: "\u0056"
|
||||
readonly property string distributeLeft: "\u0057"
|
||||
readonly property string distributeOriginBottomRight: "\u0058"
|
||||
readonly property string distributeOriginCenter: "\u0059"
|
||||
readonly property string distributeOriginNone: "\u005A"
|
||||
readonly property string distributeOriginTopLeft: "\u005B"
|
||||
readonly property string distributeRight: "\u005C"
|
||||
readonly property string distributeSpacingHorizontal: "\u005D"
|
||||
readonly property string distributeSpacingVertical: "\u005E"
|
||||
readonly property string distributeTop: "\u005F"
|
||||
readonly property string download: "\u0060"
|
||||
readonly property string downloadUnavailable: "\u0061"
|
||||
readonly property string downloadUpdate: "\u0062"
|
||||
readonly property string downloaded: "\u0063"
|
||||
readonly property string edit: "\u0064"
|
||||
readonly property string eyeDropper: "\u0065"
|
||||
readonly property string favorite: "\u0066"
|
||||
readonly property string flowAction: "\u0067"
|
||||
readonly property string flowTransition: "\u0068"
|
||||
readonly property string fontStyleBold: "\u0069"
|
||||
readonly property string fontStyleItalic: "\u006A"
|
||||
readonly property string fontStyleStrikethrough: "\u006B"
|
||||
readonly property string fontStyleUnderline: "\u006C"
|
||||
readonly property string gradient: "\u006D"
|
||||
readonly property string gridView: "\u006E"
|
||||
readonly property string idAliasOff: "\u006F"
|
||||
readonly property string idAliasOn: "\u0070"
|
||||
readonly property string imported: "\u0071"
|
||||
readonly property string infinity: "\u0072"
|
||||
readonly property string keyframe: "\u0073"
|
||||
readonly property string linkTriangle: "\u0074"
|
||||
readonly property string linked: "\u0075"
|
||||
readonly property string listView: "\u0076"
|
||||
readonly property string lockOff: "\u0077"
|
||||
readonly property string lockOn: "\u0078"
|
||||
readonly property string materialPreviewEnvironment: "\u0079"
|
||||
readonly property string materialPreviewModel: "\u007A"
|
||||
readonly property string mergeCells: "\u007B"
|
||||
readonly property string minus: "\u007C"
|
||||
readonly property string mirror: "\u007D"
|
||||
readonly property string newMaterial: "\u007E"
|
||||
readonly property string openMaterialBrowser: "\u007F"
|
||||
readonly property string orientation: "\u0080"
|
||||
readonly property string paddingEdge: "\u0081"
|
||||
readonly property string paddingFrame: "\u0082"
|
||||
readonly property string pasteStyle: "\u0083"
|
||||
readonly property string pause: "\u0084"
|
||||
readonly property string pin: "\u0085"
|
||||
readonly property string play: "\u0086"
|
||||
readonly property string plus: "\u0087"
|
||||
readonly property string promote: "\u0088"
|
||||
readonly property string readOnly: "\u0089"
|
||||
readonly property string redo: "\u008A"
|
||||
readonly property string rotationFill: "\u008B"
|
||||
readonly property string rotationOutline: "\u008C"
|
||||
readonly property string search: "\u008D"
|
||||
readonly property string sectionToggle: "\u008E"
|
||||
readonly property string splitColumns: "\u008F"
|
||||
readonly property string splitRows: "\u0090"
|
||||
readonly property string startNode: "\u0091"
|
||||
readonly property string testIcon: "\u0092"
|
||||
readonly property string textAlignBottom: "\u0093"
|
||||
readonly property string textAlignCenter: "\u0094"
|
||||
readonly property string textAlignJustified: "\u0095"
|
||||
readonly property string textAlignLeft: "\u0096"
|
||||
readonly property string textAlignMiddle: "\u0097"
|
||||
readonly property string textAlignRight: "\u0098"
|
||||
readonly property string textAlignTop: "\u0099"
|
||||
readonly property string textBulletList: "\u009A"
|
||||
readonly property string textFullJustification: "\u009B"
|
||||
readonly property string textNumberedList: "\u009D"
|
||||
readonly property string tickIcon: "\u009E"
|
||||
readonly property string translationCreateFiles: "\u009F"
|
||||
readonly property string translationCreateReport: "\u00A0"
|
||||
readonly property string translationExport: "\u00A1"
|
||||
readonly property string translationImport: "\u00A2"
|
||||
readonly property string translationSelectLanguages: "\u00A3"
|
||||
readonly property string translationTest: "\u00A4"
|
||||
readonly property string transparent: "\u00A5"
|
||||
readonly property string triState: "\u00A6"
|
||||
readonly property string triangleArcA: "\u00A7"
|
||||
readonly property string triangleArcB: "\u00A8"
|
||||
readonly property string triangleCornerA: "\u00A9"
|
||||
readonly property string triangleCornerB: "\u00AA"
|
||||
readonly property string unLinked: "\u00AB"
|
||||
readonly property string undo: "\u00AC"
|
||||
readonly property string unpin: "\u00AE"
|
||||
readonly property string upDownIcon: "\u00AF"
|
||||
readonly property string upDownSquare2: "\u00B0"
|
||||
readonly property string visibilityOff: "\u00B1"
|
||||
readonly property string visibilityOn: "\u00B2"
|
||||
readonly property string wildcard: "\u00B3"
|
||||
readonly property string wizardsAutomotive: "\u00B4"
|
||||
readonly property string wizardsDesktop: "\u00B5"
|
||||
readonly property string wizardsGeneric: "\u00B6"
|
||||
readonly property string wizardsMcuEmpty: "\u00B7"
|
||||
readonly property string wizardsMcuGraph: "\u00B8"
|
||||
readonly property string wizardsMobile: "\u00B9"
|
||||
readonly property string wizardsUnknown: "\u00BA"
|
||||
readonly property string zoomAll: "\u00BB"
|
||||
readonly property string zoomIn: "\u00BC"
|
||||
readonly property string zoomOut: "\u00BD"
|
||||
readonly property string zoomSelection: "\u00BE"
|
||||
readonly property string closeLink: "\u0045"
|
||||
readonly property string colorPopupClose: "\u0046"
|
||||
readonly property string columnsAndRows: "\u0047"
|
||||
readonly property string copyLink: "\u0048"
|
||||
readonly property string copyStyle: "\u0049"
|
||||
readonly property string cornerA: "\u004A"
|
||||
readonly property string cornerB: "\u004B"
|
||||
readonly property string cornersAll: "\u004C"
|
||||
readonly property string curveDesigner: "\u004D"
|
||||
readonly property string curveEditor: "\u004E"
|
||||
readonly property string customMaterialEditor: "\u004F"
|
||||
readonly property string decisionNode: "\u0050"
|
||||
readonly property string deleteColumn: "\u0051"
|
||||
readonly property string deleteMaterial: "\u0052"
|
||||
readonly property string deleteRow: "\u0053"
|
||||
readonly property string deleteTable: "\u0054"
|
||||
readonly property string detach: "\u0055"
|
||||
readonly property string distributeBottom: "\u0056"
|
||||
readonly property string distributeCenterHorizontal: "\u0057"
|
||||
readonly property string distributeCenterVertical: "\u0058"
|
||||
readonly property string distributeLeft: "\u0059"
|
||||
readonly property string distributeOriginBottomRight: "\u005A"
|
||||
readonly property string distributeOriginCenter: "\u005B"
|
||||
readonly property string distributeOriginNone: "\u005C"
|
||||
readonly property string distributeOriginTopLeft: "\u005D"
|
||||
readonly property string distributeRight: "\u005E"
|
||||
readonly property string distributeSpacingHorizontal: "\u005F"
|
||||
readonly property string distributeSpacingVertical: "\u0060"
|
||||
readonly property string distributeTop: "\u0061"
|
||||
readonly property string download: "\u0062"
|
||||
readonly property string downloadUnavailable: "\u0063"
|
||||
readonly property string downloadUpdate: "\u0064"
|
||||
readonly property string downloaded: "\u0065"
|
||||
readonly property string edit: "\u0066"
|
||||
readonly property string eyeDropper: "\u0067"
|
||||
readonly property string favorite: "\u0068"
|
||||
readonly property string flowAction: "\u0069"
|
||||
readonly property string flowTransition: "\u006A"
|
||||
readonly property string fontStyleBold: "\u006B"
|
||||
readonly property string fontStyleItalic: "\u006C"
|
||||
readonly property string fontStyleStrikethrough: "\u006D"
|
||||
readonly property string fontStyleUnderline: "\u006E"
|
||||
readonly property string gradient: "\u006F"
|
||||
readonly property string gridView: "\u0070"
|
||||
readonly property string idAliasOff: "\u0071"
|
||||
readonly property string idAliasOn: "\u0072"
|
||||
readonly property string infinity: "\u0073"
|
||||
readonly property string keyframe: "\u0074"
|
||||
readonly property string linkTriangle: "\u0075"
|
||||
readonly property string linked: "\u0076"
|
||||
readonly property string listView: "\u0077"
|
||||
readonly property string lockOff: "\u0078"
|
||||
readonly property string lockOn: "\u0079"
|
||||
readonly property string materialPreviewEnvironment: "\u007A"
|
||||
readonly property string materialPreviewModel: "\u007B"
|
||||
readonly property string mergeCells: "\u007C"
|
||||
readonly property string minus: "\u007D"
|
||||
readonly property string mirror: "\u007E"
|
||||
readonly property string newMaterial: "\u007F"
|
||||
readonly property string openLink: "\u0080"
|
||||
readonly property string openMaterialBrowser: "\u0081"
|
||||
readonly property string orientation: "\u0082"
|
||||
readonly property string paddingEdge: "\u0083"
|
||||
readonly property string paddingFrame: "\u0084"
|
||||
readonly property string pasteStyle: "\u0085"
|
||||
readonly property string pause: "\u0086"
|
||||
readonly property string pin: "\u0087"
|
||||
readonly property string play: "\u0088"
|
||||
readonly property string plus: "\u0089"
|
||||
readonly property string promote: "\u008A"
|
||||
readonly property string readOnly: "\u008B"
|
||||
readonly property string redo: "\u008C"
|
||||
readonly property string rotationFill: "\u008D"
|
||||
readonly property string rotationOutline: "\u008E"
|
||||
readonly property string search: "\u008F"
|
||||
readonly property string sectionToggle: "\u0090"
|
||||
readonly property string splitColumns: "\u0091"
|
||||
readonly property string splitRows: "\u0092"
|
||||
readonly property string startNode: "\u0093"
|
||||
readonly property string testIcon: "\u0094"
|
||||
readonly property string textAlignBottom: "\u0095"
|
||||
readonly property string textAlignCenter: "\u0096"
|
||||
readonly property string textAlignJustified: "\u0097"
|
||||
readonly property string textAlignLeft: "\u0098"
|
||||
readonly property string textAlignMiddle: "\u0099"
|
||||
readonly property string textAlignRight: "\u009A"
|
||||
readonly property string textAlignTop: "\u009B"
|
||||
readonly property string textBulletList: "\u009D"
|
||||
readonly property string textFullJustification: "\u009E"
|
||||
readonly property string textNumberedList: "\u009F"
|
||||
readonly property string tickIcon: "\u00A0"
|
||||
readonly property string translationCreateFiles: "\u00A1"
|
||||
readonly property string translationCreateReport: "\u00A2"
|
||||
readonly property string translationExport: "\u00A3"
|
||||
readonly property string translationImport: "\u00A4"
|
||||
readonly property string translationSelectLanguages: "\u00A5"
|
||||
readonly property string translationTest: "\u00A6"
|
||||
readonly property string transparent: "\u00A7"
|
||||
readonly property string triState: "\u00A8"
|
||||
readonly property string triangleArcA: "\u00A9"
|
||||
readonly property string triangleArcB: "\u00AA"
|
||||
readonly property string triangleCornerA: "\u00AB"
|
||||
readonly property string triangleCornerB: "\u00AC"
|
||||
readonly property string unLinked: "\u00AE"
|
||||
readonly property string undo: "\u00AF"
|
||||
readonly property string unpin: "\u00B0"
|
||||
readonly property string upDownIcon: "\u00B1"
|
||||
readonly property string upDownSquare2: "\u00B2"
|
||||
readonly property string visibilityOff: "\u00B3"
|
||||
readonly property string visibilityOn: "\u00B4"
|
||||
readonly property string wildcard: "\u00B5"
|
||||
readonly property string wizardsAutomotive: "\u00B6"
|
||||
readonly property string wizardsDesktop: "\u00B7"
|
||||
readonly property string wizardsGeneric: "\u00B8"
|
||||
readonly property string wizardsMcuEmpty: "\u00B9"
|
||||
readonly property string wizardsMcuGraph: "\u00BA"
|
||||
readonly property string wizardsMobile: "\u00BB"
|
||||
readonly property string wizardsUnknown: "\u00BC"
|
||||
readonly property string zoomAll: "\u00BD"
|
||||
readonly property string zoomIn: "\u00BE"
|
||||
readonly property string zoomOut: "\u00BF"
|
||||
readonly property string zoomSelection: "\u00C0"
|
||||
|
||||
readonly property font iconFont: Qt.font({
|
||||
"family": controlIcons.name,
|
||||
|
||||
@@ -264,6 +264,14 @@
|
||||
'TargetQuickVersion': '6.3',
|
||||
'TargetQuick3DVersion': '6.3'
|
||||
})"
|
||||
},
|
||||
{
|
||||
"trKey": "Qt 6.4",
|
||||
"value":
|
||||
"({
|
||||
'TargetQuickVersion': '6.4',
|
||||
'TargetQuick3DVersion': '6.4'
|
||||
})"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -261,6 +261,13 @@
|
||||
"({
|
||||
'TargetQuickVersion': '6.3'
|
||||
})"
|
||||
},
|
||||
{
|
||||
"trKey": "Qt 6.4",
|
||||
"value":
|
||||
"({
|
||||
'TargetQuickVersion': '6.4'
|
||||
})"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ Project {
|
||||
Environment {
|
||||
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
|
||||
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
|
||||
QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT: "1"
|
||||
@if %{IsQt6Project}
|
||||
@else
|
||||
QMLSCENE_CORE_PROFILE: "true" // Required for macOS, but can create issues on embedded Linux
|
||||
@@ -99,7 +100,7 @@ Project {
|
||||
/* Required for deployment */
|
||||
targetDirectory: "/opt/%{ProjectName}"
|
||||
|
||||
qdsVersion: "3.7"
|
||||
qdsVersion: "3.8"
|
||||
|
||||
quickVersion: "%{QtQuickVersion}"
|
||||
|
||||
|
||||
@@ -15,4 +15,5 @@ void set_qt_environment()
|
||||
qputenv("QT_ENABLE_HIGHDPI_SCALING", "0");
|
||||
qputenv("QT_LOGGING_RULES", "qt.qml.connections=false");
|
||||
qputenv("QT_QUICK_CONTROLS_CONF", ":/qtquickcontrols2.conf");
|
||||
qputenv("QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT", "1");
|
||||
}
|
||||
|
||||
@@ -259,6 +259,13 @@
|
||||
"({
|
||||
'TargetQuickVersion': '6.3'
|
||||
})"
|
||||
},
|
||||
{
|
||||
"trKey": "Qt 6.4",
|
||||
"value":
|
||||
"({
|
||||
'TargetQuickVersion': '6.4'
|
||||
})"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
|
||||
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
|
||||
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
|
||||
{ "key": "UIClassName", "value": "Screen01" },
|
||||
{ "key": "UIClassFileName", "value": "%{JS: Util.fileName('%{UIClassName}', 'ui.qml')}" },
|
||||
{ "key": "IsQt6Project", "value": "%{JS: value('QtQuickVersion') !== '2.15' }" },
|
||||
{ "key": "QtQuickVersion", "value": "%{JS: %{TargetQtVersion}.TargetQuickVersion}" },
|
||||
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
|
||||
@@ -216,6 +218,13 @@
|
||||
"({
|
||||
'TargetQuickVersion': '6.3'
|
||||
})"
|
||||
},
|
||||
{
|
||||
"trKey": "Qt 6.4",
|
||||
"value":
|
||||
"({
|
||||
'TargetQuickVersion': '6.4'
|
||||
})"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -216,6 +216,13 @@
|
||||
"({
|
||||
'TargetQuickVersion': '6.3'
|
||||
})"
|
||||
},
|
||||
{
|
||||
"trKey": "Qt 6.4",
|
||||
"value":
|
||||
"({
|
||||
'TargetQuickVersion': '6.4'
|
||||
})"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -216,6 +216,13 @@
|
||||
"({
|
||||
'TargetQuickVersion': '6.3'
|
||||
})"
|
||||
},
|
||||
{
|
||||
"trKey": "Qt 6.4",
|
||||
"value":
|
||||
"({
|
||||
'TargetQuickVersion': '6.4'
|
||||
})"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
40
share/qtcreator/templates/wizards/files/effect/wizard.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"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": true,
|
||||
|
||||
"options": { "key": "DefaultSuffix", "value": "qep" },
|
||||
|
||||
"pages" :
|
||||
[
|
||||
{
|
||||
"trDisplayName": "Location",
|
||||
"trShortTitle": "Location",
|
||||
"typeId": "File"
|
||||
},
|
||||
{
|
||||
"trDisplayName": "Project Management",
|
||||
"trShortTitle": "Summary",
|
||||
"typeId": "Summary"
|
||||
}
|
||||
],
|
||||
"generators" :
|
||||
[
|
||||
{
|
||||
"typeId": "File",
|
||||
"data":
|
||||
{
|
||||
"source": "file.qep",
|
||||
"target": "%{JS: Util.fileName(value('TargetPath'), value('DefaultSuffix'))}",
|
||||
"openInEditor": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -181,7 +181,8 @@ bool AndroidDeployQtStep::init()
|
||||
}
|
||||
|
||||
const QtSupport::QtVersion * const qt = QtSupport::QtKitAspect::qtVersion(kit());
|
||||
if (qt && qt->supportsMultipleQtAbis() && !selectedAbis.contains(info.cpuAbi.first())) {
|
||||
if (qt && qt->supportsMultipleQtAbis() && !info.cpuAbi.isEmpty() &&
|
||||
!selectedAbis.contains(info.cpuAbi.first())) {
|
||||
TaskHub::addTask(DeploymentTask(Task::Warning,
|
||||
Tr::tr("Android: The main ABI of the deployment device (%1) is not selected. The app "
|
||||
"execution or debugging might not work properly. Add it from Projects > Build > "
|
||||
|
||||
@@ -68,7 +68,7 @@ void DocumentLocatorFilter::updateSymbols(const DocumentUri &uri,
|
||||
return;
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_currentSymbols = symbols;
|
||||
emit symbolsUpToDate({});
|
||||
emit symbolsUpToDate(QPrivateSignal());
|
||||
}
|
||||
|
||||
void DocumentLocatorFilter::resetSymbols()
|
||||
|
||||
@@ -7,6 +7,7 @@ QtcPlugin {
|
||||
Depends { name: "Qt.widgets" }
|
||||
Depends { name: "Qt.testlib"; condition: qtc.testsEnabled }
|
||||
Depends { name: "Utils" }
|
||||
Depends { name: "app_version_header" }
|
||||
|
||||
Depends { name: "Core" }
|
||||
Depends { name: "BareMetal" }
|
||||
|
||||
@@ -208,7 +208,7 @@ QObject *AssetsLibraryModel::rootDir() const
|
||||
bool AssetsLibraryModel::isEmpty() const
|
||||
{
|
||||
return m_isEmpty;
|
||||
};
|
||||
}
|
||||
|
||||
void AssetsLibraryModel::setIsEmpty(bool empty)
|
||||
{
|
||||
@@ -216,7 +216,7 @@ void AssetsLibraryModel::setIsEmpty(bool empty)
|
||||
m_isEmpty = empty;
|
||||
emit isEmptyChanged();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
QVariant AssetsLibraryModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
@@ -374,6 +374,13 @@ const QStringList &AssetsLibraryModel::supportedTexture3DSuffixes()
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &AssetsLibraryModel::supportedEffectMakerSuffixes()
|
||||
{
|
||||
// These are file types only supported by Effect Maker
|
||||
static QStringList retList {"*.qep"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QSet<QString> &AssetsLibraryModel::supportedSuffixes()
|
||||
{
|
||||
static QSet<QString> allSuffixes;
|
||||
@@ -388,6 +395,7 @@ const QSet<QString> &AssetsLibraryModel::supportedSuffixes()
|
||||
insertSuffixes(supportedAudioSuffixes());
|
||||
insertSuffixes(supportedVideoSuffixes());
|
||||
insertSuffixes(supportedTexture3DSuffixes());
|
||||
insertSuffixes(supportedEffectMakerSuffixes());
|
||||
}
|
||||
return allSuffixes;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
static const QStringList &supportedAudioSuffixes();
|
||||
static const QStringList &supportedVideoSuffixes();
|
||||
static const QStringList &supportedTexture3DSuffixes();
|
||||
static const QStringList &supportedEffectMakerSuffixes();
|
||||
static const QSet<QString> &supportedSuffixes();
|
||||
|
||||
const QSet<QString> &previewableSuffixes() const;
|
||||
|
||||
@@ -22,11 +22,18 @@
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/utilsicons.h>
|
||||
#include "utils/environment.h"
|
||||
#include "utils/filepath.h"
|
||||
#include "utils/qtcprocess.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/messagebox.h>
|
||||
|
||||
#include <projectexplorer/projecttree.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/project.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDrag>
|
||||
#include <QFileDialog>
|
||||
@@ -43,6 +50,9 @@
|
||||
#include <QQmlContext>
|
||||
#include <QQuickItem>
|
||||
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static QString propertyEditorResourcesPath()
|
||||
@@ -126,6 +136,11 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon
|
||||
m_assetCompressionTimer.start();
|
||||
});
|
||||
|
||||
connect(m_fileSystemWatcher, &Utils::FileSystemWatcher::fileChanged,
|
||||
[](const QString &changeFilePath) {
|
||||
QmlDesignerPlugin::instance()->emitAssetChanged(changeFilePath);
|
||||
});
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins({});
|
||||
layout->setSpacing(0);
|
||||
@@ -225,6 +240,48 @@ QSet<QString> AssetsLibraryWidget::supportedAssetSuffixes(bool complex)
|
||||
return suffixes;
|
||||
}
|
||||
|
||||
void AssetsLibraryWidget::openEffectMaker(const QString &filePath)
|
||||
{
|
||||
const ProjectExplorer::Target *target = ProjectExplorer::ProjectTree::currentTarget();
|
||||
if (!target) {
|
||||
qWarning() << __FUNCTION__ << "No project open";
|
||||
return;
|
||||
}
|
||||
|
||||
Utils::FilePath projectPath = target->project()->projectDirectory();
|
||||
QString effectName = QFileInfo(filePath).baseName();
|
||||
QString effectResDir = "asset_imports/Effects/" + effectName;
|
||||
Utils::FilePath effectResPath = projectPath.resolvePath(effectResDir);
|
||||
if (!effectResPath.exists())
|
||||
QDir(projectPath.toString()).mkpath(effectResDir);
|
||||
|
||||
const QtSupport::QtVersion *baseQtVersion = QtSupport::QtKitAspect::qtVersion(target->kit());
|
||||
if (baseQtVersion) {
|
||||
auto effectMakerPath = baseQtVersion->binPath().pathAppended("QQEffectMaker").withExecutableSuffix();
|
||||
if (!effectMakerPath.exists()) {
|
||||
qWarning() << __FUNCTION__ << "Cannot find EffectMaker app";
|
||||
return;
|
||||
}
|
||||
|
||||
Utils::FilePath effectPath = Utils::FilePath::fromString(filePath);
|
||||
QString effectContents = QString::fromUtf8(effectPath.fileContents().value_or(QByteArray()));
|
||||
QStringList arguments;
|
||||
arguments << filePath;
|
||||
if (effectContents.isEmpty())
|
||||
arguments << "--create";
|
||||
arguments << "--exportpath" << effectResPath.toString();
|
||||
|
||||
Utils::Environment env = Utils::Environment::systemEnvironment();
|
||||
if (env.osType() == Utils::OsTypeMac)
|
||||
env.appendOrSet("QSG_RHI_BACKEND", "metal");
|
||||
|
||||
m_qqemProcess.reset(new Utils::QtcProcess);
|
||||
m_qqemProcess->setEnvironment(env);
|
||||
m_qqemProcess->setCommand({ effectMakerPath, arguments });
|
||||
m_qqemProcess->start();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsLibraryWidget::setModel(Model *model)
|
||||
{
|
||||
m_model = model;
|
||||
@@ -296,6 +353,9 @@ QPair<QString, QByteArray> AssetsLibraryWidget::getAssetTypeAndData(const QStrin
|
||||
} else if (AssetsLibraryModel::supportedTexture3DSuffixes().contains(suffix)) {
|
||||
// Data: Image format (suffix)
|
||||
return {Constants::MIME_TYPE_ASSET_TEXTURE3D, suffix.toUtf8()};
|
||||
} else if (AssetsLibraryModel::supportedEffectMakerSuffixes().contains(suffix)) {
|
||||
// Data: Effect Maker format (suffix)
|
||||
return {Constants::MIME_TYPE_ASSET_EFFECT, suffix.toUtf8()};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
||||
@@ -20,7 +20,10 @@ QT_BEGIN_NAMESPACE
|
||||
class QShortcut;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Utils { class FileSystemWatcher; }
|
||||
namespace Utils {
|
||||
class FileSystemWatcher;
|
||||
class QtcProcess;
|
||||
}
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -61,6 +64,7 @@ public:
|
||||
const QList<QUrl> &complexFilePaths,
|
||||
const QString &targetDirPath = {});
|
||||
Q_INVOKABLE QSet<QString> supportedAssetSuffixes(bool complex);
|
||||
Q_INVOKABLE void openEffectMaker(const QString &filePath);
|
||||
|
||||
signals:
|
||||
void itemActivated(const QString &itemName);
|
||||
@@ -92,6 +96,8 @@ private:
|
||||
bool m_updateRetry = false;
|
||||
QString m_filterText;
|
||||
QPoint m_dragStartPoint;
|
||||
|
||||
std::unique_ptr<Utils::QtcProcess> m_qqemProcess;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -293,7 +293,8 @@ void ActionEditor::updateWindowName(const QString &targetName)
|
||||
}
|
||||
|
||||
void ActionEditor::invokeEditor(SignalHandlerProperty signalHandler,
|
||||
std::function<void(SignalHandlerProperty)> onReject,
|
||||
std::function<void(SignalHandlerProperty)> removeSignalFunction,
|
||||
bool removeOnReject,
|
||||
QObject * parent)
|
||||
{
|
||||
if (!signalHandler.isValid())
|
||||
@@ -324,15 +325,23 @@ void ActionEditor::invokeEditor(SignalHandlerProperty signalHandler,
|
||||
if (!editor)
|
||||
return;
|
||||
if (editor->m_modelNode.isValid()) {
|
||||
editor->m_modelNode.view()->executeInTransaction("ActionEditor::"
|
||||
"invokeEditorAccepted",
|
||||
[=]() {
|
||||
editor->m_modelNode
|
||||
.signalHandlerProperty(
|
||||
signalHandler.name())
|
||||
.setSource(
|
||||
editor->connectionValue());
|
||||
});
|
||||
editor->m_modelNode.view()
|
||||
->executeInTransaction("ActionEditor::"
|
||||
"invokeEditorAccepted",
|
||||
[=]() {
|
||||
if (!editor)
|
||||
return;
|
||||
|
||||
const QString newSource = editor->connectionValue();
|
||||
if ((newSource.isNull() || newSource.trimmed().isEmpty())
|
||||
&& removeSignalFunction) {
|
||||
removeSignalFunction(signalHandler);
|
||||
} else {
|
||||
editor->m_modelNode
|
||||
.signalHandlerProperty(signalHandler.name())
|
||||
.setSource(newSource);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//closing editor widget somewhy triggers rejected() signal. Lets disconect before it affects us:
|
||||
@@ -344,10 +353,10 @@ void ActionEditor::invokeEditor(SignalHandlerProperty signalHandler,
|
||||
if (!editor)
|
||||
return;
|
||||
|
||||
if (onReject) {
|
||||
if (removeOnReject && removeSignalFunction) {
|
||||
editor->m_modelNode.view()->executeInTransaction("ActionEditor::"
|
||||
"invokeEditorOnRejectFunc",
|
||||
[=]() { onReject(signalHandler); });
|
||||
[=]() { removeSignalFunction(signalHandler); });
|
||||
}
|
||||
|
||||
//closing editor widget somewhy triggers rejected() signal 2nd time. Lets disconect before it affects us:
|
||||
|
||||
@@ -46,7 +46,8 @@ public:
|
||||
Q_INVOKABLE void updateWindowName(const QString &targetName = {});
|
||||
|
||||
static void invokeEditor(SignalHandlerProperty signalHandler,
|
||||
std::function<void(SignalHandlerProperty)> onReject = nullptr,
|
||||
std::function<void(SignalHandlerProperty)> removeSignalFunction = nullptr,
|
||||
bool removeOnReject = false,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
@@ -211,8 +211,8 @@ const char addShadersDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResource
|
||||
const char add3DAssetsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "3D Assets");
|
||||
const char addQt3DSPresentationsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources",
|
||||
"Qt 3D Studio Presentations");
|
||||
|
||||
const char addCustomEffectDialogDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Add Custom Effect");
|
||||
const char addCustomEffectDialogDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources",
|
||||
"Effect Maker Files");
|
||||
|
||||
} //ComponentCoreConstants
|
||||
|
||||
|
||||
@@ -549,6 +549,8 @@ ModelNode createNewConnection(ModelNode targetNode)
|
||||
|
||||
void removeSignal(SignalHandlerProperty signalHandler)
|
||||
{
|
||||
if (!signalHandler.isValid())
|
||||
return;
|
||||
auto connectionNode = signalHandler.parentModelNode();
|
||||
auto connectionSignals = connectionNode.signalProperties();
|
||||
if (connectionSignals.size() > 1) {
|
||||
@@ -662,10 +664,14 @@ public:
|
||||
QString(
|
||||
QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Open Connections Editor")),
|
||||
[=](const SelectionContext &) {
|
||||
signalHandler.parentModelNode().view()->executeInTransaction(
|
||||
"ConnectionsModelNodeActionGroup::"
|
||||
"openConnectionsEditor",
|
||||
[signalHandler]() { ActionEditor::invokeEditor(signalHandler); });
|
||||
signalHandler.parentModelNode()
|
||||
.view()
|
||||
->executeInTransaction("ConnectionsModelNodeActionGroup::"
|
||||
"openConnectionsEditor",
|
||||
[signalHandler]() {
|
||||
ActionEditor::invokeEditor(signalHandler,
|
||||
removeSignal);
|
||||
});
|
||||
});
|
||||
|
||||
activeSignalHandlerGroup->addAction(openEditorAction);
|
||||
@@ -728,7 +734,7 @@ public:
|
||||
|
||||
newHandler.setSource(
|
||||
QString("console.log(\"%1.%2\")").arg(currentNode.id(), signalStr));
|
||||
ActionEditor::invokeEditor(newHandler, removeSignal);
|
||||
ActionEditor::invokeEditor(newHandler, removeSignal, true);
|
||||
});
|
||||
});
|
||||
newSignal->addAction(openEditorAction);
|
||||
|
||||
@@ -1607,10 +1607,23 @@ void updateImported3DAsset(const SelectionContext &selectionContext)
|
||||
if (selectionContext.view()) {
|
||||
selectionContext.view()->emitCustomNotification(
|
||||
"UpdateImported3DAsset", {selectionContext.currentSingleSelectedNode()});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Utils::FilePath getEffectsDirectory()
|
||||
{
|
||||
QString defaultDir = "asset_imports/Effects";
|
||||
Utils::FilePath projectPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
|
||||
Utils::FilePath effectsPath = projectPath.pathAppended(defaultDir);
|
||||
|
||||
if (!effectsPath.exists()) {
|
||||
QDir dir(projectPath.toString());
|
||||
dir.mkpath(defaultDir);
|
||||
}
|
||||
|
||||
return effectsPath;
|
||||
}
|
||||
|
||||
} // namespace ModelNodeOperations
|
||||
|
||||
} //QmlDesigner
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "selectioncontext.h"
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
enum class AddFilesResult { Succeeded, Failed, Cancelled };
|
||||
@@ -55,7 +57,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext);
|
||||
void increaseIndexOfStackedContainer(const SelectionContext &selectionContext);
|
||||
void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext);
|
||||
void addTabBarToStackedContainer(const SelectionContext &selectionContext);
|
||||
AddFilesResult addFilesToProject(const QStringList &fileNames, const QString &defaultDirectory);
|
||||
QMLDESIGNERCORE_EXPORT AddFilesResult addFilesToProject(const QStringList &fileNames, const QString &defaultDirectory);
|
||||
AddFilesResult addImageToProject(const QStringList &fileNames, const QString &directory);
|
||||
AddFilesResult addFontToProject(const QStringList &fileNames, const QString &directory);
|
||||
AddFilesResult addSoundToProject(const QStringList &fileNames, const QString &directory);
|
||||
@@ -76,6 +78,8 @@ void addMouseAreaFill(const SelectionContext &selectionContext);
|
||||
void openSignalDialog(const SelectionContext &selectionContext);
|
||||
void updateImported3DAsset(const SelectionContext &selectionContext);
|
||||
|
||||
QMLDESIGNERCORE_EXPORT Utils::FilePath getEffectsDirectory();
|
||||
|
||||
// ModelNodePreviewImageOperations
|
||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode);
|
||||
QVariant previewImageDataForImageNode(const ModelNode &modelNode);
|
||||
|
||||
@@ -57,8 +57,10 @@ public:
|
||||
centerHorizontal,
|
||||
centerVertical,
|
||||
closeCross,
|
||||
closeLink,
|
||||
colorPopupClose,
|
||||
columnsAndRows,
|
||||
copyLink,
|
||||
copyStyle,
|
||||
cornerA,
|
||||
cornerB,
|
||||
@@ -101,7 +103,6 @@ public:
|
||||
gridView,
|
||||
idAliasOff,
|
||||
idAliasOn,
|
||||
imported,
|
||||
infinity,
|
||||
keyframe,
|
||||
linkTriangle,
|
||||
@@ -115,6 +116,7 @@ public:
|
||||
minus,
|
||||
mirror,
|
||||
newMaterial,
|
||||
openLink,
|
||||
openMaterialBrowser,
|
||||
orientation,
|
||||
paddingEdge,
|
||||
|
||||
@@ -226,7 +226,7 @@ void Edit3DWidget::onCreateAction()
|
||||
// QString::number(entry.majorVersion())
|
||||
// + QLatin1Char('.')
|
||||
// + QString::number(entry.minorVersion()));
|
||||
// if (!m_view->model()->hasImport(import))
|
||||
// if (!m_view->model()->hasImport(import, true, true))
|
||||
// m_view->model()->changeImports({import}, {});
|
||||
|
||||
// int activeScene = m_view->rootModelNode().auxiliaryData("active3dScene@Internal").toInt();
|
||||
|
||||
@@ -220,7 +220,8 @@ void AbstractFormEditorTool::dragEnterEvent(const QList<QGraphicsItem*> &itemLis
|
||||
for (const QString &assetPath : assetPaths) {
|
||||
QString assetType = AssetsLibraryWidget::getAssetTypeAndData(assetPath).first;
|
||||
if (assetType == Constants::MIME_TYPE_ASSET_IMAGE
|
||||
|| assetType == Constants::MIME_TYPE_ASSET_FONT) {
|
||||
|| assetType == Constants::MIME_TYPE_ASSET_FONT
|
||||
|| assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
|
||||
hasValidAssets = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,38 +218,64 @@ static bool hasItemLibraryInfo(const QMimeData *mimeData)
|
||||
return mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
|
||||
}
|
||||
|
||||
void DragTool::dropEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event)
|
||||
void DragTool::dropEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSceneDragDropEvent *event)
|
||||
{
|
||||
if (canBeDropped(event->mimeData())) {
|
||||
event->accept();
|
||||
end(generateUseSnapping(event->modifiers()));
|
||||
|
||||
QString effectPath;
|
||||
const QStringList assetPaths = QString::fromUtf8(event->mimeData()
|
||||
->data(Constants::MIME_TYPE_ASSETS)).split(',');
|
||||
for (auto &path : assetPaths) {
|
||||
auto assetType = AssetsLibraryWidget::getAssetTypeAndData(path).first;
|
||||
if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
|
||||
effectPath = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool resetPuppet = false;
|
||||
for (auto &node : m_dragNodes) {
|
||||
if (node.isValid()) {
|
||||
if ((node.instanceParentItem().isValid()
|
||||
&& node.instanceParent().modelNode().metaInfo().isLayoutable())
|
||||
|| node.isFlowItem()) {
|
||||
node.removeProperty("x");
|
||||
node.removeProperty("y");
|
||||
resetPuppet = true;
|
||||
|
||||
if (!effectPath.isEmpty()) {
|
||||
FormEditorItem *targetContainerFormEditorItem = targetContainerOrRootItem(itemList);
|
||||
if (targetContainerFormEditorItem) {
|
||||
QmlItemNode parentQmlItemNode = targetContainerFormEditorItem->qmlItemNode();
|
||||
QString effectName = QFileInfo(effectPath).baseName();
|
||||
QmlItemNode effectNode = QmlItemNode::createQmlItemNodeForEffect(view(), parentQmlItemNode, effectName);
|
||||
|
||||
view()->setSelectedModelNodes({effectNode});
|
||||
view()->resetPuppet();
|
||||
|
||||
commitTransaction();
|
||||
}
|
||||
} else {
|
||||
for (QmlItemNode &node : m_dragNodes) {
|
||||
if (node.isValid()) {
|
||||
if ((node.instanceParentItem().isValid()
|
||||
&& node.instanceParent().modelNode().metaInfo().isLayoutable())
|
||||
|| node.isFlowItem()) {
|
||||
node.removeProperty("x");
|
||||
node.removeProperty("y");
|
||||
resetPuppet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (resetPuppet)
|
||||
view()->resetPuppet(); // Otherwise the layout might not reposition the items
|
||||
if (resetPuppet)
|
||||
view()->resetPuppet(); // Otherwise the layout might not reposition the items
|
||||
|
||||
commitTransaction();
|
||||
commitTransaction();
|
||||
|
||||
if (!m_dragNodes.isEmpty()) {
|
||||
QList<ModelNode> nodeList;
|
||||
for (auto &node : std::as_const(m_dragNodes)) {
|
||||
if (node.isValid())
|
||||
nodeList.append(node);
|
||||
if (!m_dragNodes.isEmpty()) {
|
||||
QList<ModelNode> nodeList;
|
||||
for (auto &node : std::as_const(m_dragNodes)) {
|
||||
if (node.isValid())
|
||||
nodeList.append(node);
|
||||
}
|
||||
view()->setSelectedModelNodes(nodeList);
|
||||
}
|
||||
view()->setSelectedModelNodes(nodeList);
|
||||
m_dragNodes.clear();
|
||||
}
|
||||
m_dragNodes.clear();
|
||||
|
||||
view()->changeToSelectionTool();
|
||||
}
|
||||
@@ -325,10 +351,17 @@ void DragTool::createDragNodes(const QMimeData *mimeData, const QPointF &scenePo
|
||||
|
||||
void DragTool::dragMoveEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSceneDragDropEvent *event)
|
||||
{
|
||||
if (!m_blockMove && !m_isAborted && canBeDropped(event->mimeData())) {
|
||||
FormEditorItem *targetContainerItem = targetContainerOrRootItem(itemList);
|
||||
const QStringList assetPaths = QString::fromUtf8(event->mimeData()
|
||||
->data(Constants::MIME_TYPE_ASSETS)).split(',');
|
||||
QString assetType = AssetsLibraryWidget::getAssetTypeAndData(assetPaths[0]).first;
|
||||
|
||||
if (!m_blockMove
|
||||
&& !m_isAborted
|
||||
&& canBeDropped(event->mimeData())
|
||||
&& assetType != Constants::MIME_TYPE_ASSET_EFFECT) {
|
||||
event->accept();
|
||||
if (!m_dragNodes.isEmpty()) {
|
||||
FormEditorItem *targetContainerItem = targetContainerOrRootItem(itemList);
|
||||
if (targetContainerItem) {
|
||||
move(event->scenePos(), itemList);
|
||||
} else {
|
||||
@@ -342,7 +375,7 @@ void DragTool::dragMoveEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSc
|
||||
} else {
|
||||
createDragNodes(event->mimeData(), event->scenePos(), itemList);
|
||||
}
|
||||
} else {
|
||||
} else if (assetType != Constants::MIME_TYPE_ASSET_EFFECT) {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ bool BundleMaterialCategory::visible() const
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
bool BundleMaterialCategory::expanded() const
|
||||
{
|
||||
return m_expanded;
|
||||
}
|
||||
|
||||
QList<BundleMaterial *> BundleMaterialCategory::categoryMaterials() const
|
||||
{
|
||||
return m_categoryMaterials;
|
||||
|
||||
@@ -35,8 +35,11 @@ class BundleMaterialCategory : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString categoryName MEMBER m_name CONSTANT)
|
||||
Q_PROPERTY(bool categoryVisible MEMBER m_visible NOTIFY categoryVisibleChanged)
|
||||
Q_PROPERTY(QString bundleCategoryName MEMBER m_name CONSTANT)
|
||||
Q_PROPERTY(bool bundleCategoryVisible MEMBER m_visible NOTIFY categoryVisibleChanged)
|
||||
Q_PROPERTY(bool bundleCategoryExpanded MEMBER m_expanded NOTIFY categoryExpandChanged)
|
||||
Q_PROPERTY(QList<BundleMaterial *> bundleCategoryMaterials MEMBER m_categoryMaterials
|
||||
NOTIFY bundleMaterialsModelChanged)
|
||||
|
||||
public:
|
||||
BundleMaterialCategory(QObject *parent, const QString &name);
|
||||
@@ -47,14 +50,18 @@ public:
|
||||
|
||||
QString name() const;
|
||||
bool visible() const;
|
||||
bool expanded() const;
|
||||
QList<BundleMaterial *> categoryMaterials() const;
|
||||
|
||||
signals:
|
||||
void categoryVisibleChanged();
|
||||
void categoryExpandChanged();
|
||||
void bundleMaterialsModelChanged();
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
bool m_visible = true;
|
||||
bool m_expanded = true;
|
||||
|
||||
QList<BundleMaterial *> m_categoryMaterials;
|
||||
};
|
||||
|
||||
@@ -54,17 +54,26 @@ QVariant MaterialBrowserBundleModel::data(const QModelIndex &index, int role) co
|
||||
QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.count(), return {});
|
||||
QTC_ASSERT(roleNames().contains(role), return {});
|
||||
|
||||
return m_bundleCategories.at(index.row())->property(roleNames().value(role));
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid() || !roleNames().contains(role))
|
||||
return false;
|
||||
|
||||
QByteArray roleName = roleNames().value(role);
|
||||
if (roleName == "bundleCategory")
|
||||
return m_bundleCategories.at(index.row())->name();
|
||||
BundleMaterialCategory *bundleCategory = m_bundleCategories.at(index.row());
|
||||
QVariant currValue = bundleCategory->property(roleName);
|
||||
|
||||
if (roleName == "bundleCategoryVisible")
|
||||
return m_bundleCategories.at(index.row())->visible();
|
||||
if (currValue != value) {
|
||||
bundleCategory->setProperty(roleName, value);
|
||||
|
||||
if (roleName == "bundleMaterialsModel")
|
||||
return QVariant::fromValue(m_bundleCategories.at(index.row())->categoryMaterials());
|
||||
emit dataChanged(index, index, {role});
|
||||
return true;
|
||||
}
|
||||
|
||||
return {};
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::isValidIndex(int idx) const
|
||||
@@ -75,16 +84,17 @@ bool MaterialBrowserBundleModel::isValidIndex(int idx) const
|
||||
QHash<int, QByteArray> MaterialBrowserBundleModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
{Qt::UserRole + 1, "bundleCategory"},
|
||||
{Qt::UserRole + 1, "bundleCategoryName"},
|
||||
{Qt::UserRole + 2, "bundleCategoryVisible"},
|
||||
{Qt::UserRole + 3, "bundleMaterialsModel"}
|
||||
{Qt::UserRole + 3, "bundleCategoryExpanded"},
|
||||
{Qt::UserRole + 4, "bundleCategoryMaterials"}
|
||||
};
|
||||
return roles;
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::loadMaterialBundle()
|
||||
{
|
||||
if (m_matBundleExists || m_probeMatBundleDir)
|
||||
if (m_matBundleLoaded || m_probeMatBundleDir)
|
||||
return;
|
||||
|
||||
QDir matBundleDir(qEnvironmentVariable("MATERIAL_BUNDLE_PATH"));
|
||||
@@ -120,7 +130,7 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
|
||||
}
|
||||
}
|
||||
|
||||
m_matBundleExists = true;
|
||||
m_matBundleLoaded = true;
|
||||
|
||||
QString bundleId = m_matBundleObj.value("id").toString();
|
||||
|
||||
@@ -174,20 +184,6 @@ void MaterialBrowserBundleModel::loadMaterialBundle()
|
||||
});
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::hasQuick3DImport() const
|
||||
{
|
||||
return m_hasQuick3DImport;
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::setHasQuick3DImport(bool b)
|
||||
{
|
||||
if (b == m_hasQuick3DImport)
|
||||
return;
|
||||
|
||||
m_hasQuick3DImport = b;
|
||||
emit hasQuick3DImportChanged();
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::hasMaterialRoot() const
|
||||
{
|
||||
return m_hasMaterialRoot;
|
||||
@@ -202,6 +198,11 @@ void MaterialBrowserBundleModel::setHasMaterialRoot(bool b)
|
||||
emit hasMaterialRootChanged();
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::matBundleExists() const
|
||||
{
|
||||
return m_matBundleLoaded && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 3;
|
||||
}
|
||||
|
||||
Internal::BundleImporter *MaterialBrowserBundleModel::bundleImporter() const
|
||||
{
|
||||
return m_importer;
|
||||
@@ -243,6 +244,17 @@ void MaterialBrowserBundleModel::updateImportedState(const QStringList &imported
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::setQuick3DImportVersion(int major, int minor)
|
||||
{
|
||||
bool bundleExisted = matBundleExists();
|
||||
|
||||
m_quick3dMajorVersion = major;
|
||||
m_quick3dMinorVersion = minor;
|
||||
|
||||
if (bundleExisted != matBundleExists())
|
||||
emit matBundleExistsChanged();
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::resetModel()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
@@ -46,9 +46,8 @@ class MaterialBrowserBundleModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool matBundleExists MEMBER m_matBundleExists CONSTANT)
|
||||
Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged)
|
||||
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
|
||||
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
|
||||
Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged)
|
||||
Q_PROPERTY(bool importerRunning MEMBER m_importerRunning NOTIFY importerRunningChanged)
|
||||
|
||||
@@ -57,17 +56,19 @@ public:
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void setSearchText(const QString &searchText);
|
||||
void updateImportedState(const QStringList &importedMats);
|
||||
|
||||
bool hasQuick3DImport() const;
|
||||
void setHasQuick3DImport(bool b);
|
||||
void setQuick3DImportVersion(int major, int minor);
|
||||
|
||||
bool hasMaterialRoot() const;
|
||||
void setHasMaterialRoot(bool b);
|
||||
|
||||
bool matBundleExists() const;
|
||||
|
||||
Internal::BundleImporter *bundleImporter() const;
|
||||
|
||||
void resetModel();
|
||||
@@ -86,6 +87,7 @@ signals:
|
||||
void bundleMaterialAboutToUnimport(const QmlDesigner::TypeName &type);
|
||||
void bundleMaterialUnimported(const QmlDesigner::NodeMetaInfo &metaInfo);
|
||||
void importerRunningChanged();
|
||||
void matBundleExistsChanged();
|
||||
|
||||
private:
|
||||
void loadMaterialBundle();
|
||||
@@ -97,11 +99,13 @@ private:
|
||||
Internal::BundleImporter *m_importer = nullptr;
|
||||
|
||||
bool m_isEmpty = true;
|
||||
bool m_hasQuick3DImport = false;
|
||||
bool m_hasMaterialRoot = false;
|
||||
bool m_matBundleExists = false;
|
||||
bool m_matBundleLoaded = false;
|
||||
bool m_probeMatBundleDir = false;
|
||||
bool m_importerRunning = false;
|
||||
|
||||
int m_quick3dMajorVersion = -1;
|
||||
int m_quick3dMinorVersion = -1;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -83,41 +83,54 @@ bool MaterialBrowserModel::loadPropertyGroups(const QString &path)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if (m_propertyGroupsObj.isEmpty()) {
|
||||
QFile matPropsFile(path);
|
||||
QFile matPropsFile(path);
|
||||
if (!matPropsFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning("Couldn't open propertyGroups.json");
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (!matPropsFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning("Couldn't open propertyGroups.json");
|
||||
if (ok) {
|
||||
QJsonDocument matPropsJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll());
|
||||
if (matPropsJsonDoc.isNull()) {
|
||||
qWarning("Invalid propertyGroups.json file");
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
QJsonDocument matPropsJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll());
|
||||
if (matPropsJsonDoc.isNull()) {
|
||||
qWarning("Invalid propertyGroups.json file");
|
||||
ok = false;
|
||||
} else {
|
||||
m_propertyGroupsObj = matPropsJsonDoc.object();
|
||||
}
|
||||
} else {
|
||||
m_propertyGroupsObj = matPropsJsonDoc.object();
|
||||
}
|
||||
}
|
||||
|
||||
m_defaultMaterialSections.clear();
|
||||
m_principledMaterialSections.clear();
|
||||
m_specularGlossyMaterialSections.clear();
|
||||
m_customMaterialSections.clear();
|
||||
if (ok) {
|
||||
m_defaultMaterialSections.append(m_propertyGroupsObj.value("DefaultMaterial").toObject().keys());
|
||||
m_principledMaterialSections.append(m_propertyGroupsObj.value("PrincipledMaterial").toObject().keys());
|
||||
m_specularGlossyMaterialSections.append(m_propertyGroupsObj.value("SpecularGlossyMaterial").toObject().keys());
|
||||
|
||||
QStringList customMatSections = m_propertyGroupsObj.value("CustomMaterial").toObject().keys();
|
||||
if (customMatSections.size() > 1) // as of now custom material has only 1 section, so we don't add it
|
||||
m_customMaterialSections.append(customMatSections);
|
||||
} else {
|
||||
m_propertyGroupsObj = {};
|
||||
}
|
||||
emit materialSectionsChanged();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void MaterialBrowserModel::unloadPropertyGroups()
|
||||
{
|
||||
if (!m_propertyGroupsObj.isEmpty()) {
|
||||
m_propertyGroupsObj = {};
|
||||
m_defaultMaterialSections.clear();
|
||||
m_principledMaterialSections.clear();
|
||||
m_specularGlossyMaterialSections.clear();
|
||||
m_customMaterialSections.clear();
|
||||
emit materialSectionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> MaterialBrowserModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
@@ -381,6 +394,7 @@ void MaterialBrowserModel::copyMaterialProperties(int idx, const QString §io
|
||||
}
|
||||
}
|
||||
validProps.remove("objectName");
|
||||
validProps.remove("data");
|
||||
|
||||
if (m_allPropsCopied || dynamicPropsCopied || m_propertyGroupsObj.empty()) {
|
||||
copiedProps = validProps.values();
|
||||
|
||||
@@ -25,6 +25,7 @@ class MaterialBrowserModel : public QAbstractListModel
|
||||
Q_PROPERTY(QString copiedMaterialType READ copiedMaterialType WRITE setCopiedMaterialType NOTIFY copiedMaterialTypeChanged)
|
||||
Q_PROPERTY(QStringList defaultMaterialSections MEMBER m_defaultMaterialSections NOTIFY materialSectionsChanged)
|
||||
Q_PROPERTY(QStringList principledMaterialSections MEMBER m_principledMaterialSections NOTIFY materialSectionsChanged)
|
||||
Q_PROPERTY(QStringList specularGlossyMaterialSections MEMBER m_specularGlossyMaterialSections NOTIFY materialSectionsChanged)
|
||||
Q_PROPERTY(QStringList customMaterialSections MEMBER m_customMaterialSections NOTIFY materialSectionsChanged)
|
||||
|
||||
public:
|
||||
@@ -58,6 +59,7 @@ public:
|
||||
int materialIndex(const ModelNode &material) const;
|
||||
ModelNode materialAt(int idx) const;
|
||||
bool loadPropertyGroups(const QString &path);
|
||||
void unloadPropertyGroups();
|
||||
|
||||
void resetModel();
|
||||
|
||||
@@ -105,6 +107,7 @@ private:
|
||||
QString m_searchText;
|
||||
QList<ModelNode> m_materialList;
|
||||
QStringList m_defaultMaterialSections;
|
||||
QStringList m_specularGlossyMaterialSections;
|
||||
QStringList m_principledMaterialSections;
|
||||
QStringList m_customMaterialSections;
|
||||
ModelNode m_copiedMaterial;
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#ifndef QMLDESIGNER_TEST
|
||||
#include <projectexplorer/kit.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
#endif
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QRegularExpression>
|
||||
#include <QTimer>
|
||||
@@ -100,7 +108,7 @@ WidgetInfo MaterialBrowserView::widgetInfo()
|
||||
}
|
||||
}
|
||||
for (const PropertyName &propName : std::as_const(propNames)) {
|
||||
if (propName != "objectName")
|
||||
if (propName != "objectName" && propName != "data")
|
||||
mat.removeProperty(propName);
|
||||
}
|
||||
}
|
||||
@@ -267,11 +275,12 @@ void MaterialBrowserView::modelAttached(Model *model)
|
||||
rootModelNode().metaInfo().isQtQuick3DMaterial());
|
||||
m_hasQuick3DImport = model->hasImport("QtQuick3D");
|
||||
|
||||
updateBundleMaterialsQuick3DVersion();
|
||||
updateBundleMaterialsImportedState();
|
||||
|
||||
// Project load is already very busy and may even trigger puppet reset, so let's wait a moment
|
||||
// before refreshing the model
|
||||
QTimer::singleShot(1000, this, [this]() {
|
||||
QTimer::singleShot(1000, model, [this]() {
|
||||
refreshModel(true);
|
||||
loadPropertyGroups(); // Needs the delay because it uses metaInfo
|
||||
});
|
||||
@@ -279,7 +288,7 @@ void MaterialBrowserView::modelAttached(Model *model)
|
||||
|
||||
void MaterialBrowserView::refreshModel(bool updateImages)
|
||||
{
|
||||
if (!model() || !model()->nodeInstanceView())
|
||||
if (!model())
|
||||
return;
|
||||
|
||||
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
|
||||
@@ -311,6 +320,11 @@ void MaterialBrowserView::modelAboutToBeDetached(Model *model)
|
||||
{
|
||||
m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport);
|
||||
|
||||
if (m_propertyGroupsLoaded) {
|
||||
m_propertyGroupsLoaded = false;
|
||||
m_widget->materialBrowserModel()->unloadPropertyGroups();
|
||||
}
|
||||
|
||||
AbstractView::modelAboutToBeDetached(model);
|
||||
}
|
||||
|
||||
@@ -416,7 +430,7 @@ void MaterialBrowserView::nodeRemoved([[maybe_unused]] const ModelNode &removedN
|
||||
|
||||
void QmlDesigner::MaterialBrowserView::loadPropertyGroups()
|
||||
{
|
||||
if (!m_hasQuick3DImport || m_propertyGroupsLoaded)
|
||||
if (!m_hasQuick3DImport || m_propertyGroupsLoaded || !model())
|
||||
return;
|
||||
|
||||
QString matPropsPath = model()->metaInfo("QtQuick3D.Material").importDirectoryPath()
|
||||
@@ -443,6 +457,41 @@ void MaterialBrowserView::updateBundleMaterialsImportedState()
|
||||
m_widget->materialBrowserBundleModel()->updateImportedState(importedBundleMats);
|
||||
}
|
||||
|
||||
void MaterialBrowserView::updateBundleMaterialsQuick3DVersion()
|
||||
{
|
||||
bool hasImport = false;
|
||||
int major = -1;
|
||||
int minor = -1;
|
||||
const QString url {"QtQuick3D"};
|
||||
const auto imports = model()->imports();
|
||||
for (const auto &import : imports) {
|
||||
if (import.url() == url) {
|
||||
hasImport = true;
|
||||
const int importMajor = import.majorVersion();
|
||||
if (major < importMajor) {
|
||||
minor = -1;
|
||||
major = importMajor;
|
||||
}
|
||||
if (major == importMajor)
|
||||
minor = qMax(minor, import.minorVersion());
|
||||
}
|
||||
}
|
||||
#ifndef QMLDESIGNER_TEST
|
||||
if (hasImport && major == -1) {
|
||||
// Import without specifying version, so we take the kit version
|
||||
auto target = ProjectExplorer::SessionManager::startupTarget();
|
||||
if (target) {
|
||||
QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target->kit());
|
||||
if (qtVersion) {
|
||||
major = qtVersion->qtVersion().majorVersion();
|
||||
minor = qtVersion->qtVersion().minorVersion();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_widget->materialBrowserBundleModel()->setQuick3DImportVersion(major, minor);
|
||||
}
|
||||
|
||||
ModelNode MaterialBrowserView::getBundleMaterialDefaultInstance(const TypeName &type)
|
||||
{
|
||||
const QList<ModelNode> materials = m_widget->materialBrowserModel()->materials();
|
||||
@@ -470,6 +519,8 @@ void MaterialBrowserView::importsChanged([[maybe_unused]] const QList<Import> &a
|
||||
{
|
||||
bool hasQuick3DImport = model()->hasImport("QtQuick3D");
|
||||
|
||||
updateBundleMaterialsQuick3DVersion();
|
||||
|
||||
if (hasQuick3DImport == m_hasQuick3DImport)
|
||||
return;
|
||||
|
||||
@@ -494,7 +545,7 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
|
||||
if (idx != -1)
|
||||
m_widget->materialBrowserModel()->selectMaterial(idx);
|
||||
} else if (identifier == "refresh_material_browser") {
|
||||
QTimer::singleShot(0, this, [this]() {
|
||||
QTimer::singleShot(0, model(), [this]() {
|
||||
refreshModel(true);
|
||||
});
|
||||
} else if (identifier == "delete_selected_material") {
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
bool isMaterial(const ModelNode &node) const;
|
||||
void loadPropertyGroups();
|
||||
void updateBundleMaterialsImportedState();
|
||||
void updateBundleMaterialsQuick3DVersion();
|
||||
void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const NodeMetaInfo &metaInfo = {});
|
||||
ModelNode getBundleMaterialDefaultInstance(const TypeName &type);
|
||||
|
||||
|
||||
@@ -59,9 +59,7 @@ MaterialEditorView::MaterialEditorView()
|
||||
m_ensureMatLibTimer.callOnTimeout([this] {
|
||||
if (model() && model()->rewriterView() && !model()->rewriterView()->hasIncompleteTypeInformation()
|
||||
&& model()->rewriterView()->errors().isEmpty()) {
|
||||
executeInTransaction("MaterialEditorView::MaterialEditorView", [this] {
|
||||
ensureMaterialLibraryNode();
|
||||
});
|
||||
ensureMaterialLibraryNode();
|
||||
m_ensureMatLibTimer.stop();
|
||||
}
|
||||
});
|
||||
@@ -714,8 +712,8 @@ void MaterialEditorView::updatePossibleTypes()
|
||||
return;
|
||||
|
||||
// Ensure basic types are always first
|
||||
static const QStringList basicTypes {"DefaultMaterial", "PrincipledMaterial", "CustomMaterial"};
|
||||
QStringList allTypes = basicTypes;
|
||||
QStringList nonQuick3dTypes;
|
||||
QStringList allTypes;
|
||||
|
||||
const QList<ItemLibraryEntry> itemLibEntries = m_itemLibraryInfo->entries();
|
||||
for (const ItemLibraryEntry &entry : itemLibEntries) {
|
||||
@@ -730,12 +728,22 @@ void MaterialEditorView::updatePossibleTypes()
|
||||
addImport = model()->hasImport(import, true, true);
|
||||
}
|
||||
if (addImport) {
|
||||
QString typeName = QString::fromLatin1(entry.typeName().split('.').last());
|
||||
if (!allTypes.contains(typeName))
|
||||
allTypes.append(typeName);
|
||||
const QList<QByteArray> typeSplit = entry.typeName().split('.');
|
||||
const QString typeName = QString::fromLatin1(typeSplit.last());
|
||||
if (typeSplit.size() == 2 && typeSplit.first() == "QtQuick3D") {
|
||||
if (!allTypes.contains(typeName))
|
||||
allTypes.append(typeName);
|
||||
} else if (!nonQuick3dTypes.contains(typeName)) {
|
||||
nonQuick3dTypes.append(typeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allTypes.sort();
|
||||
nonQuick3dTypes.sort();
|
||||
allTypes.append(nonQuick3dTypes);
|
||||
|
||||
m_qmlBackEnd->contextObject()->setPossibleTypes(allTypes);
|
||||
}
|
||||
|
||||
@@ -1006,6 +1014,8 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
|
||||
|
||||
TypeName matType = material.type();
|
||||
QmlObjectNode sourceMat(material);
|
||||
ModelNode duplicateMatNode;
|
||||
QList<AbstractProperty> dynamicProps;
|
||||
|
||||
executeInTransaction(__FUNCTION__, [&] {
|
||||
ModelNode matLib = materialLibraryNode();
|
||||
@@ -1016,25 +1026,57 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
|
||||
NodeMetaInfo metaInfo = model()->metaInfo(matType);
|
||||
QmlObjectNode duplicateMat = createModelNode(matType, metaInfo.majorVersion(), metaInfo.minorVersion());
|
||||
|
||||
duplicateMatNode = duplicateMat.modelNode();
|
||||
|
||||
// set name and id
|
||||
QString newName = sourceMat.modelNode().variantProperty("objectName").value().toString() + " copy";
|
||||
duplicateMat.modelNode().variantProperty("objectName").setValue(newName);
|
||||
duplicateMat.modelNode().setIdWithoutRefactoring(model()->generateIdFromName(newName, "material"));
|
||||
duplicateMatNode.variantProperty("objectName").setValue(newName);
|
||||
duplicateMatNode.setIdWithoutRefactoring(model()->generateIdFromName(newName, "material"));
|
||||
|
||||
// sync properties
|
||||
// sync properties. Only the base state is duplicated.
|
||||
const QList<AbstractProperty> props = material.properties();
|
||||
for (const AbstractProperty &prop : props) {
|
||||
if (prop.name() == "objectName")
|
||||
if (prop.name() == "objectName" || prop.name() == "data")
|
||||
continue;
|
||||
|
||||
if (prop.isVariantProperty())
|
||||
duplicateMat.setVariantProperty(prop.name(), prop.toVariantProperty().value());
|
||||
else if (prop.isBindingProperty())
|
||||
duplicateMat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
|
||||
if (prop.isVariantProperty()) {
|
||||
if (prop.isDynamic()) {
|
||||
dynamicProps.append(prop);
|
||||
} else {
|
||||
duplicateMatNode.variantProperty(prop.name())
|
||||
.setValue(prop.toVariantProperty().value());
|
||||
}
|
||||
} else if (prop.isBindingProperty()) {
|
||||
if (prop.isDynamic()) {
|
||||
dynamicProps.append(prop);
|
||||
} else {
|
||||
duplicateMatNode.bindingProperty(prop.name())
|
||||
.setExpression(prop.toBindingProperty().expression());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matLib.defaultNodeListProperty().reparentHere(duplicateMat);
|
||||
});
|
||||
|
||||
// For some reason, creating dynamic properties in the same transaction doesn't work, so
|
||||
// let's do it in separate transaction.
|
||||
// TODO: Fix the issue and merge transactions (QDS-8094)
|
||||
if (!dynamicProps.isEmpty()) {
|
||||
executeInTransaction(__FUNCTION__, [&] {
|
||||
for (const AbstractProperty &prop : std::as_const(dynamicProps)) {
|
||||
if (prop.isVariantProperty()) {
|
||||
duplicateMatNode.variantProperty(prop.name())
|
||||
.setDynamicTypeNameAndValue(prop.dynamicTypeName(),
|
||||
prop.toVariantProperty().value());
|
||||
} else if (prop.isBindingProperty()) {
|
||||
duplicateMatNode.bindingProperty(prop.name())
|
||||
.setDynamicTypeNameAndExpression(prop.dynamicTypeName(),
|
||||
prop.toBindingProperty().expression());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEditorView::customNotification([[maybe_unused]] const AbstractView *view,
|
||||
|
||||
@@ -18,6 +18,7 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
|
||||
// Texture
|
||||
// -> DefaultMaterial
|
||||
// -> PrincipledMaterial
|
||||
// -> SpecularGlossyMaterial
|
||||
// -> SpriteParticle3D
|
||||
// -> TextureInput
|
||||
// -> SceneEnvironment
|
||||
@@ -40,7 +41,8 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
|
||||
// -> Model
|
||||
|
||||
if (insertInfo.isQtQuick3DTexture()) {
|
||||
if (parentInfo.isQtQuick3DDefaultMaterial() || parentInfo.isQtQuick3DPrincipledMaterial()) {
|
||||
if (parentInfo.isQtQuick3DDefaultMaterial() || parentInfo.isQtQuick3DPrincipledMaterial()
|
||||
|| parentInfo.isQtQuick3DSpecularGlossyMaterial()) {
|
||||
// All texture properties are valid targets
|
||||
for (const auto &property : parentInfo.properties()) {
|
||||
const auto &propType = property.propertyType();
|
||||
|
||||
@@ -1024,7 +1024,8 @@ bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
|
||||
};
|
||||
|
||||
if (targetNode.metaInfo().isQtQuick3DDefaultMaterial()
|
||||
|| targetNode.metaInfo().isQtQuick3DPrincipledMaterial()) {
|
||||
|| targetNode.metaInfo().isQtQuick3DPrincipledMaterial()
|
||||
|| targetNode.metaInfo().isQtQuick3DSpecularGlossyMaterial()) {
|
||||
// if dropping an image on a material, create a texture instead of image
|
||||
// Show texture property selection dialog
|
||||
auto dialog = ChooseFromPropertyListDialog::createIfNeeded(targetNode,
|
||||
|
||||
@@ -69,6 +69,8 @@ EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *pa
|
||||
presetBar->setDrawBase(false);
|
||||
presetBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
|
||||
m_presets->initialize(presetBar);
|
||||
|
||||
auto *durationLabel = new QLabel("Duration (ms)");
|
||||
auto *durationEdit = new QSpinBox;
|
||||
durationEdit->setMaximum(std::numeric_limits<int>::max());
|
||||
@@ -85,6 +87,8 @@ EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *pa
|
||||
m_durationLayout->insertSpacing(4, hSpacing);
|
||||
m_durationLayout->addStretch(hSpacing);
|
||||
|
||||
m_splineEditor->setDuration(durationEdit->value());
|
||||
|
||||
m_buttons->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
auto callButtonsClicked = [this](QAbstractButton *button) {
|
||||
buttonsClicked(m_buttons->standardButton(button));
|
||||
@@ -122,9 +126,6 @@ EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *pa
|
||||
connect(durationEdit, &QSpinBox::valueChanged, m_splineEditor, &SplineEditor::setDuration);
|
||||
connect(animateButton, &QPushButton::clicked, m_splineEditor, &SplineEditor::animate);
|
||||
|
||||
m_presets->initialize(presetBar);
|
||||
|
||||
m_splineEditor->setDuration(durationEdit->value());
|
||||
|
||||
resize(QSize(1421, 918));
|
||||
}
|
||||
|
||||
@@ -33,6 +33,19 @@ constexpr int spacingg = 5;
|
||||
|
||||
const QColor background = Qt::white;
|
||||
|
||||
|
||||
QString makeNameUnique(const QString& name, const QStringList& currentNames)
|
||||
{
|
||||
QString n = name;
|
||||
int idx = 0;
|
||||
while (true) {
|
||||
if (!currentNames.contains(n))
|
||||
return n;
|
||||
n = name + "_" + QString::number(idx++);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
PresetItemDelegate::PresetItemDelegate(const QColor& background)
|
||||
: QStyledItemDelegate()
|
||||
, m_background(background)
|
||||
@@ -366,7 +379,7 @@ void PresetList::createItem()
|
||||
{
|
||||
EasingCurve curve;
|
||||
curve.makeDefault();
|
||||
createItem(createUniqueName(), curve);
|
||||
createItem(makeNameUnique("Default", allNames()), curve);
|
||||
}
|
||||
|
||||
void PresetList::createItem(const QString &name, const EasingCurve &curve)
|
||||
@@ -402,27 +415,6 @@ void PresetList::setItemData(const QModelIndex &index, const QVariant &curve, co
|
||||
}
|
||||
}
|
||||
|
||||
QString PresetList::createUniqueName() const
|
||||
{
|
||||
QStringList names = allNames();
|
||||
auto nameIsUnique = [&](const QString &name) {
|
||||
auto iter = std::find(names.begin(), names.end(), name);
|
||||
if (iter == names.end())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
int counter = 0;
|
||||
QString tmp("Default");
|
||||
QString name = tmp;
|
||||
|
||||
while (!nameIsUnique(name))
|
||||
name = tmp + QString(" %1").arg(counter++);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
QStringList PresetList::allNames() const
|
||||
{
|
||||
QStringList names;
|
||||
@@ -529,7 +521,8 @@ bool PresetEditor::writePresets(const EasingCurve &curve)
|
||||
|
||||
if (ok && !name.isEmpty()) {
|
||||
activate(m_customs->index());
|
||||
m_customs->createItem(name, curve);
|
||||
QString uname = makeNameUnique(name, m_customs->allNames());
|
||||
m_customs->createItem(uname, curve);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace QmlDesigner {
|
||||
class EasingCurve;
|
||||
class NamedEasingCurve;
|
||||
|
||||
QString makeNameUnique(const QString& name, const QStringList& currentNames);
|
||||
|
||||
class PresetItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -65,6 +67,8 @@ public:
|
||||
|
||||
QColor curveColor() const;
|
||||
|
||||
QStringList allNames() const;
|
||||
|
||||
void initialize(int index);
|
||||
|
||||
void readPresets();
|
||||
@@ -89,12 +93,8 @@ protected:
|
||||
const QVector<int> &roles = QVector<int>()) override;
|
||||
|
||||
private:
|
||||
QStringList allNames() const;
|
||||
|
||||
QList<NamedEasingCurve> storedCurves() const;
|
||||
|
||||
QString createUniqueName() const;
|
||||
|
||||
void removeSelectedItem();
|
||||
|
||||
private:
|
||||
|
||||
@@ -39,7 +39,9 @@ public:
|
||||
bool isSameModule(const Import &other) const;
|
||||
|
||||
int majorVersion() const;
|
||||
int minorVersion() const;
|
||||
static int majorFromVersion(const QString &version);
|
||||
static int minorFromVersion(const QString &version);
|
||||
|
||||
private:
|
||||
Import(const QString &url, const QString &file, const QString &version, const QString &alias, const QStringList &importPaths);
|
||||
|
||||
@@ -135,6 +135,7 @@ public:
|
||||
bool isQtQuick3DParticles3DSpriteParticle3D() const;
|
||||
bool isQtQuick3DPass() const;
|
||||
bool isQtQuick3DPrincipledMaterial() const;
|
||||
bool isQtQuick3DSpecularGlossyMaterial() const;
|
||||
bool isQtQuick3DSceneEnvironment() const;
|
||||
bool isQtQuick3DShader() const;
|
||||
bool isQtQuick3DTexture() const;
|
||||
|
||||
@@ -60,7 +60,9 @@ public:
|
||||
const QPointF &position,
|
||||
NodeAbstractProperty parentproperty,
|
||||
bool executeInTransaction = true);
|
||||
|
||||
static QmlItemNode createQmlItemNodeForEffect(AbstractView *view,
|
||||
const QmlItemNode &parentNode,
|
||||
const QString &effectName);
|
||||
QList<QmlItemNode> children() const;
|
||||
QList<QmlObjectNode> resources() const;
|
||||
QList<QmlObjectNode> allDirectSubNodes() const;
|
||||
|
||||
@@ -2734,6 +2734,16 @@ bool NodeMetaInfo::isQtQuick3DPrincipledMaterial() const
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::isQtQuick3DSpecularGlossyMaterial() const
|
||||
{
|
||||
if constexpr (useProjectStorage()) {
|
||||
using namespace Storage::Info;
|
||||
return isBasedOnCommonType<QtQuick3D, SpecularGlossyMaterial>(m_projectStorage, m_typeId);
|
||||
} else {
|
||||
return isValid() && isSubclassOf("QtQuick3D.SpecularGlossyMaterial");
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeMetaInfo::isQtQuick3DParticles3DSpriteParticle3D() const
|
||||
{
|
||||
if constexpr (useProjectStorage()) {
|
||||
|
||||
@@ -811,47 +811,48 @@ void AbstractView::changeRootNodeType(const TypeName &type, int majorVersion, in
|
||||
m_model.data()->d->changeRootNodeType(type, majorVersion, minorVersion);
|
||||
}
|
||||
|
||||
// Creates material library if it doesn't exist and moves any existing materials into it
|
||||
// This function should be called only from inside a transaction, as it potentially does many
|
||||
// changes to model, or undo stack should be cleared after the call.
|
||||
// Creates material library if it doesn't exist and moves any existing materials into it.
|
||||
void AbstractView::ensureMaterialLibraryNode()
|
||||
{
|
||||
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
|
||||
if (matLib.isValid() || rootModelNode().metaInfo().isQtQuick3DMaterial())
|
||||
return;
|
||||
|
||||
// Create material library node
|
||||
auto nodeType = rootModelNode().metaInfo().isQtQuick3DNode() ? model()->qtQuick3DNodeMetaInfo()
|
||||
: model()->qtQuickItemMetaInfo();
|
||||
matLib = createModelNode(nodeType.typeName(), nodeType.majorVersion(), nodeType.minorVersion());
|
||||
executeInTransaction(__FUNCTION__, [&] {
|
||||
// Create material library node
|
||||
auto nodeType = rootModelNode().metaInfo().isQtQuick3DNode()
|
||||
? model()->qtQuick3DNodeMetaInfo()
|
||||
: model()->qtQuickItemMetaInfo();
|
||||
matLib = createModelNode(nodeType.typeName(), nodeType.majorVersion(), nodeType.minorVersion());
|
||||
|
||||
matLib.setIdWithoutRefactoring(Constants::MATERIAL_LIB_ID);
|
||||
rootModelNode().defaultNodeListProperty().reparentHere(matLib);
|
||||
matLib.setIdWithoutRefactoring(Constants::MATERIAL_LIB_ID);
|
||||
rootModelNode().defaultNodeListProperty().reparentHere(matLib);
|
||||
});
|
||||
|
||||
const QList<ModelNode> materials = rootModelNode().subModelNodesOfType(
|
||||
model()->qtQuick3DMaterialMetaInfo());
|
||||
if (!materials.isEmpty()) {
|
||||
// Move all materials to under material library node
|
||||
for (const ModelNode &node : materials) {
|
||||
// If material has no name, set name to id
|
||||
QString matName = node.variantProperty("objectName").value().toString();
|
||||
if (matName.isEmpty()) {
|
||||
VariantProperty objNameProp = node.variantProperty("objectName");
|
||||
objNameProp.setValue(node.id());
|
||||
// Do the material reparentings in different transaction to work around issue QDS-8094
|
||||
executeInTransaction(__FUNCTION__, [&] {
|
||||
const QList<ModelNode> materials = rootModelNode().subModelNodesOfType(
|
||||
model()->qtQuick3DMaterialMetaInfo());
|
||||
if (!materials.isEmpty()) {
|
||||
// Move all materials to under material library node
|
||||
for (const ModelNode &node : materials) {
|
||||
// If material has no name, set name to id
|
||||
QString matName = node.variantProperty("objectName").value().toString();
|
||||
if (matName.isEmpty()) {
|
||||
VariantProperty objNameProp = node.variantProperty("objectName");
|
||||
objNameProp.setValue(node.id());
|
||||
}
|
||||
|
||||
matLib.defaultNodeListProperty().reparentHere(node);
|
||||
}
|
||||
|
||||
matLib.defaultNodeListProperty().reparentHere(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Returns ModelNode for project's material library.
|
||||
// Since this calls ensureMaterialLibraryNode(), it should only be called within a transaction.
|
||||
// Returns ModelNode for project's material library if it exists.
|
||||
ModelNode AbstractView::materialLibraryNode()
|
||||
{
|
||||
ensureMaterialLibraryNode();
|
||||
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
|
||||
return matLib;
|
||||
return modelNodeForId(Constants::MATERIAL_LIB_ID);
|
||||
}
|
||||
|
||||
// Assigns given material to a 3D model.
|
||||
|
||||
@@ -80,6 +80,11 @@ int Import::majorVersion() const
|
||||
return majorFromVersion(m_version);
|
||||
}
|
||||
|
||||
int Import::minorVersion() const
|
||||
{
|
||||
return minorFromVersion(m_version);
|
||||
}
|
||||
|
||||
int Import::majorFromVersion(const QString &version)
|
||||
{
|
||||
if (version.isEmpty())
|
||||
@@ -87,6 +92,16 @@ int Import::majorFromVersion(const QString &version)
|
||||
return version.split('.').first().toInt();
|
||||
}
|
||||
|
||||
int Import::minorFromVersion(const QString &version)
|
||||
{
|
||||
if (version.isEmpty())
|
||||
return -1;
|
||||
const QStringList parts = version.split('.');
|
||||
if (parts.size() < 2)
|
||||
return -1;
|
||||
return parts[1].toInt();
|
||||
}
|
||||
|
||||
size_t qHash(const Import &import)
|
||||
{
|
||||
return ::qHash(import.url()) ^ ::qHash(import.file()) ^ ::qHash(import.version()) ^ ::qHash(import.alias());
|
||||
|
||||
@@ -197,7 +197,7 @@ public:
|
||||
const AuxiliaryDataKeyView &key,
|
||||
const QVariant &data);
|
||||
void removeAuxiliaryData(const InternalNodePointer &node, const AuxiliaryDataKeyView &key);
|
||||
[[noreturn]] void resetModelByRewriter(const QString &description);
|
||||
void resetModelByRewriter(const QString &description);
|
||||
|
||||
// Imports:
|
||||
const QList<Import> &imports() const { return m_imports; }
|
||||
|
||||
@@ -159,6 +159,33 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view,
|
||||
return newQmlItemNode;
|
||||
}
|
||||
|
||||
QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
|
||||
const QmlItemNode &parentNode,
|
||||
const QString &effectName)
|
||||
{
|
||||
QmlItemNode newQmlItemNode;
|
||||
|
||||
QmlDesigner::Import import = Import::createLibraryImport("Effects." + effectName, "1.0");
|
||||
try {
|
||||
if (!view->model()->hasImport(import, true, true))
|
||||
view->model()->changeImports({import}, {});
|
||||
} catch (const Exception &e) {
|
||||
QTC_ASSERT(false, return QmlItemNode());
|
||||
}
|
||||
|
||||
TypeName type(effectName.toUtf8());
|
||||
newQmlItemNode = QmlItemNode(view->createModelNode(type, 1, 0));
|
||||
NodeAbstractProperty parentProperty = parentNode.defaultNodeAbstractProperty();
|
||||
parentProperty.reparentHere(newQmlItemNode);
|
||||
|
||||
newQmlItemNode.modelNode().bindingProperty("source").setExpression("parent");
|
||||
newQmlItemNode.modelNode().bindingProperty("anchors.fill").setExpression("parent");
|
||||
|
||||
QTC_ASSERT(newQmlItemNode.isValid(), return QmlItemNode());
|
||||
|
||||
return newQmlItemNode;
|
||||
}
|
||||
|
||||
bool QmlItemNode::isValid() const
|
||||
{
|
||||
return isValidQmlItemNode(modelNode());
|
||||
|
||||
@@ -70,7 +70,7 @@ QStringList supportedVersionsList()
|
||||
{
|
||||
static const QStringList list = {"2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6",
|
||||
"2.7", "2.8", "2.9", "2.10", "2.11", "2.12", "2.13",
|
||||
"2.14", "2.15", "6.0", "6.1", "6.2", "6.3"};
|
||||
"2.14", "2.15", "6.0", "6.1", "6.2", "6.3", "6.4"};
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -509,10 +509,6 @@ public:
|
||||
qDebug() << metaInfo.isValid() << metaInfo.typeName();
|
||||
if (metaInfo.isValid())
|
||||
qDebug() << metaInfo.superClasses().front().typeName();
|
||||
|
||||
if (!metaInfo.isFileComponent() && m_model == m_model->metaInfoProxyModel()
|
||||
&& metaInfo.isValid())
|
||||
throw RewritingException(__LINE__, __FUNCTION__, __FILE__, "test", "test");
|
||||
}
|
||||
|
||||
typeName = QString::fromUtf8(metaInfo.typeName());
|
||||
|
||||
@@ -66,6 +66,7 @@ inline constexpr char Picture[] = "Picture";
|
||||
inline constexpr char Popup[] = "Popup";
|
||||
inline constexpr char Positioner[] = "Positioner";
|
||||
inline constexpr char PrincipledMaterial[] = "PrincipledMaterial";
|
||||
inline constexpr char SpecularGlossyMaterial[] = "SpecularGlossyMaterial";
|
||||
inline constexpr char PropertyAnimation[] = "PropertyAnimation";
|
||||
inline constexpr char PropertyChanges[] = "PropertyChanges";
|
||||
inline constexpr char QML[] = "QML";
|
||||
|
||||
@@ -83,6 +83,7 @@ const char MIME_TYPE_ASSET_SOUND[] = "application/vnd.qtdesignstudio.asset
|
||||
const char MIME_TYPE_ASSET_VIDEO[] = "application/vnd.qtdesignstudio.asset.video";
|
||||
const char MIME_TYPE_ASSET_TEXTURE3D[] = "application/vnd.qtdesignstudio.asset.texture3d";
|
||||
const char MIME_TYPE_MODELNODE_LIST[] = "application/vnd.qtdesignstudio.modelnode.list";
|
||||
const char MIME_TYPE_ASSET_EFFECT[] = "application/vnd.qtdesignstudio.asset.effect";
|
||||
|
||||
// Menus
|
||||
const char M_VIEW_WORKSPACES[] = "QmlDesigner.Menu.View.Workspaces";
|
||||
|
||||
@@ -631,6 +631,11 @@ void QmlDesignerPlugin::emitCurrentTextEditorChanged(Core::IEditor *editor)
|
||||
d->blockEditorChange = false;
|
||||
}
|
||||
|
||||
void QmlDesignerPlugin::emitAssetChanged(const QString &assetPath)
|
||||
{
|
||||
emit assetChanged(assetPath);
|
||||
}
|
||||
|
||||
double QmlDesignerPlugin::formEditorDevicePixelRatio()
|
||||
{
|
||||
if (QmlDesignerPlugin::settings().value(DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO).toBool())
|
||||
|
||||
@@ -63,6 +63,8 @@ public:
|
||||
void switchToTextModeDeferred();
|
||||
void emitCurrentTextEditorChanged(Core::IEditor *editor);
|
||||
|
||||
void emitAssetChanged(const QString &assetPath);
|
||||
|
||||
static double formEditorDevicePixelRatio();
|
||||
|
||||
static void contextHelp(const Core::IContext::HelpCallback &callback, const QString &id);
|
||||
@@ -81,7 +83,7 @@ public:
|
||||
signals:
|
||||
void usageStatisticsNotifier(const QString &identifier);
|
||||
void usageStatisticsUsageTimer(const QString &identifier, int elapsed);
|
||||
|
||||
void assetChanged(const QString &assetPath);
|
||||
|
||||
private: // functions
|
||||
void integrateIntoQtCreator(QWidget *modeWidget);
|
||||
|
||||
@@ -459,7 +459,7 @@ MetaInfo {
|
||||
}
|
||||
|
||||
ItemLibraryEntry {
|
||||
name: "ColorAnimation"
|
||||
name: "Color Animation"
|
||||
category: "d.Qt Quick - Animation"
|
||||
libraryIcon: ":/qtquickplugin/images/item-icon.png"
|
||||
version: "2.0"
|
||||
|
||||
@@ -66,6 +66,14 @@ static int preferedQtTarget(Target *target)
|
||||
return 5;
|
||||
}
|
||||
|
||||
static bool allowOnlySingleProject()
|
||||
{
|
||||
QSettings *settings = Core::ICore::settings();
|
||||
const QString qdsAllowMultipleProjects = "QML/Designer/AllowMultipleProjects";
|
||||
|
||||
return !settings->value(qdsAllowMultipleProjects, false).toBool();
|
||||
}
|
||||
|
||||
Utils::FilePaths QmlProject::getUiQmlFilesForFolder(const Utils::FilePath &folder)
|
||||
{
|
||||
const Utils::FilePaths uiFiles = files([&](const ProjectExplorer::Node *node) {
|
||||
@@ -86,9 +94,10 @@ QmlProject::QmlProject(const Utils::FilePath &fileName)
|
||||
setBuildSystemCreator([](Target *t) { return new QmlBuildSystem(t); });
|
||||
|
||||
if (QmlProject::isQtDesignStudio()) {
|
||||
|
||||
EditorManager::closeAllDocuments();
|
||||
SessionManager::closeAllProjects();
|
||||
if (allowOnlySingleProject()) {
|
||||
EditorManager::closeAllDocuments();
|
||||
SessionManager::closeAllProjects();
|
||||
}
|
||||
|
||||
m_openFileConnection
|
||||
= connect(this,
|
||||
|
||||