Merge remote-tracking branch 'origin/qds/dev'

Conflicts:
	src/plugins/updateinfo/updateinfoplugin.cpp

Change-Id: Ie1bf2ad434f0224fb91caf91b443daae3d5b5ec0
This commit is contained in:
Eike Ziller
2023-01-12 09:07:27 +01:00
58 changed files with 1376 additions and 310 deletions

View File

@@ -84,7 +84,7 @@
\list \list
\li \uicontrol Component exports the layer as a separate UI file \li \uicontrol Component exports the layer as a separate UI file
that contains all the exportable artwork and text in it. Only that contains all the exportable artwork and text in it. Only
Artboards can be exported as components. Artboards and XD component layers can be exported as components.
\li \uicontrol Child exports each asset of the selected group \li \uicontrol Child exports each asset of the selected group
or layer a separate PNG file, with references or layer a separate PNG file, with references
to the images in the component file. to the images in the component file.

View File

@@ -181,7 +181,7 @@
Aside from the size, an area light has the same properties as a directional Aside from the size, an area light has the same properties as a directional
light. light.
The image below shows an example on how to light a component with different The image shows an example on how to light a component with different
colors using two different area lights. colors using two different area lights.
You can rotate, scale, and move area lights. You can rotate, scale, and move area lights.

View File

@@ -32,7 +32,7 @@
By default, a directional light and a perspective camera are used in a 3D By default, a directional light and a perspective camera are used in a 3D
scene created by using the wizard template mentioned above. To use other scene created by using the wizard template mentioned above. To use other
light and camera types, select the component in the \uicontrol{3D} or light and camera types, select the component in the \uicontrol{3D} or
\uicontrol Navigatorn view and change the type of the component in the \uicontrol \uicontrol Navigator view and change the type of the component in the \uicontrol
Type field in \l Properties. For example, to use a point light, enter Type field in \l Properties. For example, to use a point light, enter
\e {PointLight}. \e {PointLight}.

View File

@@ -0,0 +1,81 @@
{
"ContextMenuArea": {
"size": "28x28",
"Off": {
"Disabled": { "color": "DSiconColorDisabled" },
"Hovered": { "color": "DSnavigatorIconHover" },
"Normal": { "color": "DSnavigatorIcon" },
"Selected": { "color": "DSnavigatorIconSelected" }
},
"On": {
"Disabled": { "color": "DSiconColorDisabled" },
"Hovered": { "color": "DSnavigatorIconHover" },
"Normal": { "color": "DSnavigatorIcon" },
"Selected": { "color": "DSnavigatorIconSelected" }
}
},
"AddMouseAreaIcon": {
"iconName": "s_mouseArea"
},
"AnchorsIcon": {
"iconName": "s_anchors"
},
"AnnotationIcon": {
"iconName": "s_annotations"
},
"ArrangeIcon": {
"iconName": "s_arrange"
},
"ConnectionsIcon": {
"iconName": "s_connections"
},
"EditIcon": {
"iconName": "s_edit"
},
"EnterComponentIcon": {
"iconName": "s_enterComponent"
},
"EventListIcon": {
"iconName": "s_eventList"
},
"GroupSelectionIcon": {
"iconName": "s_group"
},
"LayoutsIcon": {
"iconName": "s_layouts"
},
"MakeComponentIcon": {
"iconName": "s_component"
},
"MergeWithTemplateIcon": {
"iconName": "s_merging"
},
"PositionsersIcon": {
"iconName": "s_positioners"
},
"SelecionIcon": {
"iconName": "s_selection"
},
"ShowBoundsIcon": {
"Off": {
"iconName": "visibilityOff"
},
"On": {
"iconName": "visibilityOn"
}
},
"SnappingIcon": {
"iconName": "s_snapping"
},
"TimelineIcon": {
"iconName": "s_timeline"
},
"VisibilityIcon": {
"Off": {
"iconName": "visibilityOff"
},
"On": {
"iconName": "visibilityOn"
}
}
}

View File

@@ -182,9 +182,36 @@ TreeViewDelegate {
} }
ToolTip { ToolTip {
id: assetTooltip
visible: !root.isFont && mouseArea.containsMouse && !root.assetsView.contextMenu.visible visible: !root.isFont && mouseArea.containsMouse && !root.assetsView.contextMenu.visible
text: model.filePath text: assetTooltip.__computeText()
delay: 1000 delay: 1000
function __computeText()
{
let filePath = model.filePath.replace(assetsModel.contentDirPath(), "")
let fileSize = rootView.assetFileSize(model.filePath)
let fileExtMatches = model.filePath.match(/\.(.*)$/)
let fileExt = fileExtMatches ? "(" + fileExtMatches[1] + ")" : ""
if (rootView.assetIsImage(model.filePath)) {
let size = rootView.imageSize(model.filePath)
return filePath + "\n"
+ size.width + " x " + size.height
+ "\n" + fileSize
+ " " + fileExt
} else {
return filePath + "\n"
+ fileSize
+ " " + fileExt
}
}
function refresh()
{
text = assetTooltip.__computeText()
}
} }
Timer { Timer {
@@ -293,5 +320,10 @@ TreeViewDelegate {
: "image://qmldesigner_assets/" + model.filePath : "image://qmldesigner_assets/" + model.filePath
} }
onStatusChanged: {
if (thumbnailImage.status === Image.Ready)
assetTooltip.refresh()
}
} // Image } // Image
} // TreeViewDelegate } // TreeViewDelegate

View File

@@ -47,6 +47,7 @@ Section {
SectionLayout { SectionLayout {
PropertyLabel { PropertyLabel {
text: qsTr("Position") text: qsTr("Position")
tooltip: qsTr("Sets the position of the component relative to its parent.")
enabled: xSpinBox.enabled || ySpinBox.enabled enabled: xSpinBox.enabled || ySpinBox.enabled
} }
@@ -66,7 +67,7 @@ Section {
ControlLabel { ControlLabel {
text: "X" text: "X"
tooltip: xSpinBox.enabled ? "X" : root.disabledTooltip tooltip: xSpinBox.enabled ? qsTr("X-coordinate") : root.disabledTooltip
enabled: xSpinBox.enabled enabled: xSpinBox.enabled
} }
@@ -87,7 +88,7 @@ Section {
ControlLabel { ControlLabel {
text: "Y" text: "Y"
tooltip: xSpinBox.enabled ? "Y" : root.disabledTooltip tooltip: xSpinBox.enabled ? qsTr("Y-coordinate") : root.disabledTooltip
enabled: ySpinBox.enabled enabled: ySpinBox.enabled
} }
/* /*
@@ -101,6 +102,7 @@ Section {
PropertyLabel { PropertyLabel {
text: qsTr("Size") text: qsTr("Size")
tooltip: qsTr("Sets the width and height of the component.")
enabled: widthSpinBox.enabled || heightSpinBox.enabled enabled: widthSpinBox.enabled || heightSpinBox.enabled
} }
@@ -157,11 +159,13 @@ Section {
PropertyLabel { PropertyLabel {
text: qsTr("Rotation") text: qsTr("Rotation")
tooltip: qsTr("Rotate the component at an angle.")
blockedByTemplate: !backendValues.rotation.isAvailable blockedByTemplate: !backendValues.rotation.isAvailable
} }
SecondColumnLayout { SecondColumnLayout {
SpinBox { SpinBox {
id: rotationSpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth + StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.rotation backendValue: backendValues.rotation
@@ -175,6 +179,7 @@ Section {
ControlLabel { ControlLabel {
text: "°" text: "°"
tooltip: rotationSpinBox.enabled ? qsTr("Angle (in degree)") : root.disabledTooltip
enabled: backendValues.rotation.isAvailable enabled: backendValues.rotation.isAvailable
} }
/* /*
@@ -210,11 +215,13 @@ Section {
PropertyLabel { PropertyLabel {
text: qsTr("Scale") text: qsTr("Scale")
tooltip: qsTr("Sets the scale of the component by percentage.")
blockedByTemplate: !backendValues.scale.isAvailable blockedByTemplate: !backendValues.scale.isAvailable
} }
SecondColumnLayout { SecondColumnLayout {
SpinBox { SpinBox {
id: scaleSpinBox
implicitWidth: StudioTheme.Values.singleControlColumnWidth implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth + StudioTheme.Values.actionIndicatorWidth
sliderIndicatorVisible: true sliderIndicatorVisible: true
@@ -230,13 +237,17 @@ Section {
ControlLabel { ControlLabel {
text: "%" text: "%"
tooltip: scaleSpinBox.enabled ? qsTr("Percentage") : root.disabledTooltip
enabled: backendValues.scale.isAvailable enabled: backendValues.scale.isAvailable
} }
ExpandingSpacer {} ExpandingSpacer {}
} }
PropertyLabel { text: qsTr("Z stack") } PropertyLabel {
text: qsTr("Z stack")
tooltip: qsTr("Sets the stacking order of the component.")
}
SecondColumnLayout { SecondColumnLayout {
SpinBox { SpinBox {
@@ -252,6 +263,7 @@ Section {
PropertyLabel { PropertyLabel {
text: qsTr("Origin") text: qsTr("Origin")
tooltip: qsTr("Sets the modification point of the component.")
blockedByTemplate: !backendValues.transformOrigin.isAvailable blockedByTemplate: !backendValues.transformOrigin.isAvailable
} }

View File

@@ -235,10 +235,10 @@ Section {
ExpandingSpacer {} ExpandingSpacer {}
} }
/*
PropertyLabel { PropertyLabel {
text: qsTr("Source Rectangle") text: qsTr("Source rectangle")
tooltip: qsTr("TODO.") tooltip: qsTr("Sets the rectangular area of the component that should be rendered into the texture.")
} }
SecondColumnLayout { SecondColumnLayout {
@@ -313,6 +313,5 @@ Section {
ExpandingSpacer {} ExpandingSpacer {}
} }
*/
} }
} }

View File

@@ -38,12 +38,21 @@ SecondColumnLayout {
property alias spacer: spacer property alias spacer: spacer
property bool __block: false
function resetShapeColor() { function resetShapeColor() {
colorEditor.backendValue.resetValue() colorEditor.backendValue.resetValue()
} }
function initEditor() { function initEditor() {
colorEditor.syncColor()
}
// Syncing color from backend to frontend and block reflection
function syncColor() {
colorEditor.__block = true
colorEditor.color = colorEditor.value colorEditor.color = colorEditor.value
colorEditor.__block = false
} }
Connections { Connections {
@@ -52,12 +61,12 @@ SecondColumnLayout {
function onValueChanged() { function onValueChanged() {
if (popupLoader.isNotInGradientMode()) if (popupLoader.isNotInGradientMode())
colorEditor.color = colorEditor.value colorEditor.syncColor()
} }
function onBackendValueChanged() { function onBackendValueChanged() {
if (popupLoader.isNotInGradientMode()) if (popupLoader.isNotInGradientMode())
colorEditor.color = colorEditor.value colorEditor.syncColor()
} }
} }
@@ -83,6 +92,9 @@ SecondColumnLayout {
} }
onColorChanged: { onColorChanged: {
if (colorEditor.__block)
return
if (!popupLoader.isInValidState) if (!popupLoader.isInValidState)
return return
@@ -211,24 +223,20 @@ SecondColumnLayout {
if (popupLoader.active && popupLoader.dialog) if (popupLoader.active && popupLoader.dialog)
popupLoader.dialog.determineActiveColorMode() popupLoader.dialog.determineActiveColorMode()
else else
colorEditor.color = colorEditor.value colorEditor.syncColor()
} }
property alias active: popupLoader.loader.active property alias active: popupLoader.loader.active
property Loader loader: Loader { property Loader loader: Loader {
parent: colorEditor parent: preview
active: colorEditor.supportGradient active: colorEditor.supportGradient
anchors.left: parent.left
anchors.leftMargin: 0
sourceComponent: ColorEditorPopup { sourceComponent: ColorEditorPopup {
id: cePopup id: cePopup
x: cePopup.__defaultX x: cePopup.__defaultX
y: cePopup.__defaultY y: cePopup.__defaultY
} }
onLoaded: { onLoaded: popupLoader.dialog.initEditor()
popupLoader.dialog.initEditor()
}
} }
} }
} }

View File

@@ -19,7 +19,10 @@ Section {
property bool showState: false property bool showState: false
SectionLayout { SectionLayout {
PropertyLabel { text: qsTr("Type") } PropertyLabel {
text: qsTr("Type")
tooltip: qsTr("Sets the QML type of the component.")
}
SecondColumnLayout { SecondColumnLayout {
z: 2 z: 2
@@ -44,7 +47,7 @@ Section {
typeLineEdit.visible = !typeLineEdit.visible typeLineEdit.visible = !typeLineEdit.visible
typeLineEdit.forceActiveFocus() typeLineEdit.forceActiveFocus()
} }
tooltip: qsTr("Changes the type of this component.") tooltip: qsTr("Sets the QML type of the component.")
enabled: !modelNodeBackend.multiSelection enabled: !modelNodeBackend.multiSelection
} }
@@ -83,7 +86,10 @@ Section {
ExpandingSpacer {} ExpandingSpacer {}
} }
PropertyLabel { text: qsTr("ID") } PropertyLabel {
text: qsTr("ID")
tooltip: qsTr("Sets a unique identification or name.")
}
SecondColumnLayout { SecondColumnLayout {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth } Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
@@ -167,7 +173,10 @@ Section {
ExpandingSpacer {} ExpandingSpacer {}
} }
PropertyLabel { text: qsTr("Name") } PropertyLabel {
text: qsTr("Name")
tooltip: qsTr("Adds a note with a title to explain the component.")
}
SecondColumnLayout { SecondColumnLayout {
enabled: !modelNodeBackend.multiSelection enabled: !modelNodeBackend.multiSelection
@@ -247,6 +256,7 @@ Section {
PropertyLabel { PropertyLabel {
visible: root.showState visible: root.showState
text: qsTr("State") text: qsTr("State")
tooltip: qsTr("Sets the state of the component.")
} }
SecondColumnLayout { SecondColumnLayout {

View File

@@ -51,33 +51,6 @@ TextInput {
border.width: 0 border.width: 0
} }
DragHandler {
id: dragHandler
target: null
acceptedDevices: PointerDevice.Mouse
enabled: true
property int initialValue: 0
onActiveChanged: {
if (active) {
initialValue = myControl.value
mouseArea.cursorShape = Qt.ClosedHandCursor
myControl.drag = true
} else {
mouseArea.cursorShape = Qt.PointingHandCursor
myControl.drag = false
}
}
onTranslationChanged: {
var currValue = myControl.value
myControl.value = initialValue + translation.x
if (currValue !== myControl.value)
myControl.valueModified()
}
}
Item { Item {
id: dragModifierWorkaround id: dragModifierWorkaround
Keys.onPressed: function(event) { Keys.onPressed: function(event) {
@@ -86,17 +59,20 @@ TextInput {
if (event.modifiers & Qt.ControlModifier) { if (event.modifiers & Qt.ControlModifier) {
mouseArea.stepSize = myControl.minStepSize mouseArea.stepSize = myControl.minStepSize
mouseArea.calcValue() mouseArea.calcValue()
myControl.valueModified()
} }
if (event.modifiers & Qt.ShiftModifier) { if (event.modifiers & Qt.ShiftModifier) {
mouseArea.stepSize = myControl.maxStepSize mouseArea.stepSize = myControl.maxStepSize
mouseArea.calcValue() mouseArea.calcValue()
myControl.valueModified()
} }
} }
Keys.onReleased: function(event) { Keys.onReleased: function(event) {
event.accepted = true event.accepted = true
mouseArea.stepSize = myControl.realStepSize mouseArea.stepSize = myControl.stepSize
mouseArea.calcValue() mouseArea.calcValue()
myControl.valueModified()
} }
} }
@@ -117,13 +93,13 @@ TextInput {
property int initialValue: myControl.value // value on drag operation starts property int initialValue: myControl.value // value on drag operation starts
property int pressStartX: 0 property real pressStartX: 0.0
property int dragStartX: 0 property real dragStartX: 0.0
property int translationX: 0 property real translationX: 0.0
property int dragDirection: 0 property real dragDirection: 0.0
property int totalUnits: 0 // total number of units dragged property real totalUnits: 0.0 // total number of units dragged
property int units: 0 property real units: 0.0
property real __pixelsPerUnit: textInput.devicePixelRatio * textInput.pixelsPerUnit property real __pixelsPerUnit: textInput.devicePixelRatio * textInput.pixelsPerUnit
@@ -176,7 +152,7 @@ TextInput {
mouseArea.translationX += translationX mouseArea.translationX += translationX
mouseArea.calcValue() mouseArea.calcValue()
//myControl.realValueModified() myControl.valueModified()
} }
onClicked: function(mouse) { onClicked: function(mouse) {

View File

@@ -95,82 +95,109 @@ QtObject {
readonly property string gridView: "\u0070" readonly property string gridView: "\u0070"
readonly property string idAliasOff: "\u0071" readonly property string idAliasOff: "\u0071"
readonly property string idAliasOn: "\u0072" readonly property string idAliasOn: "\u0072"
readonly property string infinity: "\u0073" readonly property string imported: "\u0073"
readonly property string keyframe: "\u0074" readonly property string infinity: "\u0074"
readonly property string linkTriangle: "\u0075" readonly property string keyframe: "\u0075"
readonly property string linked: "\u0076" readonly property string linkTriangle: "\u0076"
readonly property string listView: "\u0077" readonly property string linked: "\u0077"
readonly property string lockOff: "\u0078" readonly property string listView: "\u0078"
readonly property string lockOn: "\u0079" readonly property string lockOff: "\u0079"
readonly property string materialPreviewEnvironment: "\u007A" readonly property string lockOn: "\u007A"
readonly property string materialPreviewModel: "\u007B" readonly property string materialPreviewEnvironment: "\u007B"
readonly property string mergeCells: "\u007C" readonly property string materialPreviewModel: "\u007C"
readonly property string minus: "\u007D" readonly property string mergeCells: "\u007D"
readonly property string mirror: "\u007E" readonly property string minus: "\u007E"
readonly property string newMaterial: "\u007F" readonly property string mirror: "\u007F"
readonly property string openLink: "\u0080" readonly property string newMaterial: "\u0080"
readonly property string openMaterialBrowser: "\u0081" readonly property string openLink: "\u0081"
readonly property string orientation: "\u0082" readonly property string openMaterialBrowser: "\u0082"
readonly property string paddingEdge: "\u0083" readonly property string orientation: "\u0083"
readonly property string paddingFrame: "\u0084" readonly property string paddingEdge: "\u0084"
readonly property string pasteStyle: "\u0085" readonly property string paddingFrame: "\u0085"
readonly property string pause: "\u0086" readonly property string pasteStyle: "\u0086"
readonly property string pin: "\u0087" readonly property string pause: "\u0087"
readonly property string play: "\u0088" readonly property string pin: "\u0088"
readonly property string plus: "\u0089" readonly property string play: "\u0089"
readonly property string promote: "\u008A" readonly property string plus: "\u008A"
readonly property string readOnly: "\u008B" readonly property string promote: "\u008B"
readonly property string redo: "\u008C" readonly property string readOnly: "\u008C"
readonly property string rotationFill: "\u008D" readonly property string redo: "\u008D"
readonly property string rotationOutline: "\u008E" readonly property string rotationFill: "\u008E"
readonly property string search: "\u008F" readonly property string rotationOutline: "\u008F"
readonly property string sectionToggle: "\u0090" readonly property string s_anchors: "\u0090"
readonly property string splitColumns: "\u0091" readonly property string s_annotations: "\u0091"
readonly property string splitRows: "\u0092" readonly property string s_arrange: "\u0092"
readonly property string startNode: "\u0093" readonly property string s_boundingBox: "\u0093"
readonly property string testIcon: "\u0094" readonly property string s_component: "\u0094"
readonly property string textAlignBottom: "\u0095" readonly property string s_connections: "\u0095"
readonly property string textAlignCenter: "\u0096" readonly property string s_edit: "\u0096"
readonly property string textAlignJustified: "\u0097" readonly property string s_enterComponent: "\u0097"
readonly property string textAlignLeft: "\u0098" readonly property string s_eventList: "\u0098"
readonly property string textAlignMiddle: "\u0099" readonly property string s_group: "\u0099"
readonly property string textAlignRight: "\u009A" readonly property string s_layouts: "\u009A"
readonly property string textAlignTop: "\u009B" readonly property string s_merging: "\u009B"
readonly property string textBulletList: "\u009D" readonly property string s_mouseArea: "\u009D"
readonly property string textFullJustification: "\u009E" readonly property string s_positioners: "\u009E"
readonly property string textNumberedList: "\u009F" readonly property string s_selection: "\u009F"
readonly property string tickIcon: "\u00A0" readonly property string s_snapping: "\u00A0"
readonly property string translationCreateFiles: "\u00A1" readonly property string s_timeline: "\u00A1"
readonly property string translationCreateReport: "\u00A2" readonly property string s_visibility: "\u00A2"
readonly property string translationExport: "\u00A3" readonly property string search: "\u00A3"
readonly property string translationImport: "\u00A4" readonly property string sectionToggle: "\u00A4"
readonly property string translationSelectLanguages: "\u00A5" readonly property string splitColumns: "\u00A5"
readonly property string translationTest: "\u00A6" readonly property string splitRows: "\u00A6"
readonly property string transparent: "\u00A7" readonly property string startNode: "\u00A7"
readonly property string triState: "\u00A8" readonly property string testIcon: "\u00A8"
readonly property string triangleArcA: "\u00A9" readonly property string textAlignBottom: "\u00A9"
readonly property string triangleArcB: "\u00AA" readonly property string textAlignCenter: "\u00AA"
readonly property string triangleCornerA: "\u00AB" readonly property string textAlignJustified: "\u00AB"
readonly property string triangleCornerB: "\u00AC" readonly property string textAlignLeft: "\u00AC"
readonly property string unLinked: "\u00AE" readonly property string textAlignMiddle: "\u00AE"
readonly property string undo: "\u00AF" readonly property string textAlignRight: "\u00AF"
readonly property string unpin: "\u00B0" readonly property string textAlignTop: "\u00B0"
readonly property string upDownIcon: "\u00B1" readonly property string textBulletList: "\u00B1"
readonly property string upDownSquare2: "\u00B2" readonly property string textFullJustification: "\u00B2"
readonly property string visibilityOff: "\u00B3" readonly property string textNumberedList: "\u00B3"
readonly property string visibilityOn: "\u00B4" readonly property string tickIcon: "\u00B4"
readonly property string wildcard: "\u00B5" readonly property string topToolbar_annotations: "\u00B5"
readonly property string wizardsAutomotive: "\u00B6" readonly property string topToolbar_closeFile: "\u00B6"
readonly property string wizardsDesktop: "\u00B7" readonly property string topToolbar_designMode: "\u00B7"
readonly property string wizardsGeneric: "\u00B8" readonly property string topToolbar_enterComponent: "\u00B8"
readonly property string wizardsMcuEmpty: "\u00B9" readonly property string topToolbar_home: "\u00B9"
readonly property string wizardsMcuGraph: "\u00BA" readonly property string topToolbar_makeComponent: "\u00BA"
readonly property string wizardsMobile: "\u00BB" readonly property string topToolbar_navFile: "\u00BB"
readonly property string wizardsUnknown: "\u00BC" readonly property string topToolbar_runProject: "\u00BC"
readonly property string zoomAll: "\u00BD" readonly property string translationCreateFiles: "\u00BD"
readonly property string zoomIn: "\u00BE" readonly property string translationCreateReport: "\u00BE"
readonly property string zoomOut: "\u00BF" readonly property string translationExport: "\u00BF"
readonly property string zoomSelection: "\u00C0" readonly property string translationImport: "\u00C0"
readonly property string translationSelectLanguages: "\u00C1"
readonly property string translationTest: "\u00C2"
readonly property string transparent: "\u00C3"
readonly property string triState: "\u00C4"
readonly property string triangleArcA: "\u00C5"
readonly property string triangleArcB: "\u00C6"
readonly property string triangleCornerA: "\u00C7"
readonly property string triangleCornerB: "\u00C8"
readonly property string unLinked: "\u00C9"
readonly property string undo: "\u00CA"
readonly property string unpin: "\u00CB"
readonly property string upDownIcon: "\u00CC"
readonly property string upDownSquare2: "\u00CD"
readonly property string visibilityOff: "\u00CE"
readonly property string visibilityOn: "\u00CF"
readonly property string wildcard: "\u00D0"
readonly property string wizardsAutomotive: "\u00D1"
readonly property string wizardsDesktop: "\u00D2"
readonly property string wizardsGeneric: "\u00D3"
readonly property string wizardsMcuEmpty: "\u00D4"
readonly property string wizardsMcuGraph: "\u00D5"
readonly property string wizardsMobile: "\u00D6"
readonly property string wizardsUnknown: "\u00D7"
readonly property string zoomAll: "\u00D8"
readonly property string zoomIn: "\u00D9"
readonly property string zoomOut: "\u00DA"
readonly property string zoomSelection: "\u00DB"
readonly property font iconFont: Qt.font({ readonly property font iconFont: Qt.font({
"family": controlIcons.name, "family": controlIcons.name,

View File

@@ -613,6 +613,7 @@ extend_qtc_plugin(QmlDesigner
crumblebar.cpp crumblebar.h crumblebar.cpp crumblebar.h
designeractionmanager.cpp designeractionmanager.h designeractionmanager.cpp designeractionmanager.h
designeractionmanagerview.cpp designeractionmanagerview.h designeractionmanagerview.cpp designeractionmanagerview.h
designericons.cpp designericons.h
findimplementation.cpp findimplementation.h findimplementation.cpp findimplementation.h
layoutingridlayout.cpp layoutingridlayout.h layoutingridlayout.cpp layoutingridlayout.h
modelnodecontextmenu.cpp modelnodecontextmenu.h modelnodecontextmenu.cpp modelnodecontextmenu.h

View File

@@ -22,20 +22,13 @@ QPixmap AssetsLibraryIconProvider::requestPixmap(const QString &id, QSize *size,
QPixmap pixmap; QPixmap pixmap;
if (m_thumbnails.contains(id)) { if (m_thumbnails.contains(id)) {
pixmap = m_thumbnails[id]; pixmap = m_thumbnails[id].pixmap;
} else { } else {
pixmap = fetchPixmap(id, requestedSize); Thumbnail thumbnail = createThumbnail(id, requestedSize);
bool haveValidImage = true; pixmap = thumbnail.pixmap;
if (pixmap.isNull()) {
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/assets_default.png");
haveValidImage = false;
}
if (requestedSize.isValid()) if (thumbnail.assetType != Asset::MissingImage)
pixmap = pixmap.scaled(requestedSize, Qt::KeepAspectRatio); m_thumbnails[id] = thumbnail;
if (haveValidImage)
m_thumbnails[id] = pixmap;
} }
if (size) { if (size) {
@@ -46,6 +39,25 @@ QPixmap AssetsLibraryIconProvider::requestPixmap(const QString &id, QSize *size,
return pixmap; return pixmap;
} }
Thumbnail AssetsLibraryIconProvider::createThumbnail(const QString &id, const QSize &requestedSize)
{
auto [pixmap, fileSize] = fetchPixmap(id, requestedSize);
QSize originalSize = pixmap.size();
Asset::Type assetType = Asset(id).type();
if (pixmap.isNull()) {
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/assets_default.png");
if (assetType == Asset::Image)
assetType = Asset::MissingImage;
}
if (requestedSize.isValid())
pixmap = pixmap.scaled(requestedSize, Qt::KeepAspectRatio);
return Thumbnail{pixmap, originalSize, assetType, fileSize};
}
QPixmap AssetsLibraryIconProvider::generateFontIcons(const QString &filePath, const QSize &requestedSize) const QPixmap AssetsLibraryIconProvider::generateFontIcons(const QString &filePath, const QSize &requestedSize) const
{ {
QSize reqSize = requestedSize.isValid() ? requestedSize : QSize{48, 48}; QSize reqSize = requestedSize.isValid() ? requestedSize : QSize{48, 48};
@@ -55,18 +67,25 @@ QPixmap AssetsLibraryIconProvider::generateFontIcons(const QString &filePath, co
"Abc"}).pixmap(reqSize); "Abc"}).pixmap(reqSize);
} }
QPixmap AssetsLibraryIconProvider::fetchPixmap(const QString &id, const QSize &requestedSize) const QPair<QPixmap, qint64> AssetsLibraryIconProvider::fetchPixmap(const QString &id, const QSize &requestedSize) const
{ {
Asset asset(id); Asset asset(id);
if (id == "browse") { if (id == "browse") {
return Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/browse.png"); QString filePath = Utils::StyleHelper::dpiSpecificImageFile(":/AssetsLibrary/images/browse.png");
return {QPixmap{filePath}, 0};
} else if (asset.isFont()) { } else if (asset.isFont()) {
return generateFontIcons(id, requestedSize); qint64 size = QFileInfo(id).size();
QPixmap pixmap = generateFontIcons(id, requestedSize);
return {pixmap, size};
} else if (asset.isImage()) { } else if (asset.isImage()) {
return Utils::StyleHelper::dpiSpecificImageFile(id); QString filePath = Utils::StyleHelper::dpiSpecificImageFile(id);
} else if (asset.isTexture3D()) { qint64 size = QFileInfo(filePath).size();
return HdrImage{id}.toPixmap(); return {QPixmap{filePath}, size};
} else if (asset.isHdrFile()) {
qint64 size = QFileInfo(id).size();
QPixmap pixmap = HdrImage{id}.toPixmap();
return {pixmap, size};
} else { } else {
QString type; QString type;
if (asset.isShader()) if (asset.isShader())
@@ -81,9 +100,11 @@ QPixmap AssetsLibraryIconProvider::fetchPixmap(const QString &id, const QSize &r
QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type); QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type);
QString path = pathTemplate.arg('_' + QString::number(requestedSize.width())); QString path = pathTemplate.arg('_' + QString::number(requestedSize.width()));
return Utils::StyleHelper::dpiSpecificImageFile(QFileInfo::exists(path) QString filePath = Utils::StyleHelper::dpiSpecificImageFile(QFileInfo::exists(path)
? path ? path
: pathTemplate.arg("")); : pathTemplate.arg(""));
qint64 size = QFileInfo(filePath).size();
return {QPixmap{filePath}, size};
} }
} }
@@ -97,5 +118,23 @@ void AssetsLibraryIconProvider::invalidateThumbnail(const QString &id)
m_thumbnails.remove(id); m_thumbnails.remove(id);
} }
QSize AssetsLibraryIconProvider::imageSize(const QString &id)
{
static QSize invalidSize = {};
return m_thumbnails.contains(id) ? m_thumbnails[id].originalSize : invalidSize;
}
qint64 AssetsLibraryIconProvider::fileSize(const QString &id)
{
return m_thumbnails.contains(id) ? m_thumbnails[id].fileSize : 0;
}
bool AssetsLibraryIconProvider::assetIsImage(const QString &id)
{
return m_thumbnails.contains(id)
? (m_thumbnails[id].assetType == Asset::Type::Image || Asset(id).isHdrFile())
: false;
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -7,8 +7,18 @@
#include <QQuickImageProvider> #include <QQuickImageProvider>
#include "asset.h"
namespace QmlDesigner { namespace QmlDesigner {
struct Thumbnail
{
QPixmap pixmap;
QSize originalSize;
Asset::Type assetType;
qint64 fileSize;
};
class AssetsLibraryIconProvider : public QQuickImageProvider class AssetsLibraryIconProvider : public QQuickImageProvider
{ {
public: public:
@@ -17,10 +27,14 @@ public:
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override; QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
void clearCache(); void clearCache();
void invalidateThumbnail(const QString &id); void invalidateThumbnail(const QString &id);
QSize imageSize(const QString &id);
qint64 fileSize(const QString &id);
bool assetIsImage(const QString &id);
private: private:
QPixmap generateFontIcons(const QString &filePath, const QSize &requestedSize) const; QPixmap generateFontIcons(const QString &filePath, const QSize &requestedSize) const;
QPixmap fetchPixmap(const QString &id, const QSize &requestedSize) const; QPair<QPixmap, qint64> fetchPixmap(const QString &id, const QSize &requestedSize) const;
Thumbnail createThumbnail(const QString &id, const QSize &requestedSize);
SynchronousImageCache &m_fontImageCache; SynchronousImageCache &m_fontImageCache;
@@ -29,7 +43,7 @@ private:
std::vector<QSize> iconSizes = {{128, 128}, // Drag std::vector<QSize> iconSizes = {{128, 128}, // Drag
{96, 96}, // list @2x {96, 96}, // list @2x
{48, 48}}; // list {48, 48}}; // list
QHash<QString, QPixmap> m_thumbnails; QHash<QString, Thumbnail> m_thumbnails;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -91,6 +91,11 @@ QString AssetsLibraryModel::currentProjectDirPath() const
return DocumentManager::currentProjectDirPath().toString().append('/'); return DocumentManager::currentProjectDirPath().toString().append('/');
} }
QString AssetsLibraryModel::contentDirPath() const
{
return DocumentManager::currentResourcePath().toString().append('/');
}
bool AssetsLibraryModel::requestDeleteFiles(const QStringList &filePaths) bool AssetsLibraryModel::requestDeleteFiles(const QStringList &filePaths)
{ {
bool askBeforeDelete = QmlDesignerPlugin::settings() bool askBeforeDelete = QmlDesignerPlugin::settings()

View File

@@ -40,6 +40,7 @@ public:
Q_INVOKABLE QList<QModelIndex> parentIndices(const QModelIndex &index) const; Q_INVOKABLE QList<QModelIndex> parentIndices(const QModelIndex &index) const;
Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const; Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const;
Q_INVOKABLE QString currentProjectDirPath() const; Q_INVOKABLE QString currentProjectDirPath() const;
Q_INVOKABLE QString contentDirPath() const;
Q_INVOKABLE bool requestDeleteFiles(const QStringList &filePaths); Q_INVOKABLE bool requestDeleteFiles(const QStringList &filePaths);
Q_INVOKABLE void deleteFiles(const QStringList &filePaths, bool dontAskAgain); Q_INVOKABLE void deleteFiles(const QStringList &filePaths, bool dontAskAgain);
Q_INVOKABLE bool renameFolder(const QString &folderPath, const QString &newName); Q_INVOKABLE bool renameFolder(const QString &folderPath, const QString &newName);

View File

@@ -165,6 +165,22 @@ void AssetsLibraryWidget::invalidateThumbnail(const QString &id)
m_assetsIconProvider->invalidateThumbnail(id); m_assetsIconProvider->invalidateThumbnail(id);
} }
QSize AssetsLibraryWidget::imageSize(const QString &id)
{
return m_assetsIconProvider->imageSize(id);
}
QString AssetsLibraryWidget::assetFileSize(const QString &id)
{
qint64 fileSize = m_assetsIconProvider->fileSize(id);
return QLocale::system().formattedDataSize(fileSize, 2, QLocale::DataSizeTraditionalFormat);
}
bool AssetsLibraryWidget::assetIsImage(const QString &id)
{
return m_assetsIconProvider->assetIsImage(id);
}
QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets() QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
{ {
return {}; return {};

View File

@@ -74,6 +74,10 @@ public:
Q_INVOKABLE void openEffectMaker(const QString &filePath); Q_INVOKABLE void openEffectMaker(const QString &filePath);
Q_INVOKABLE bool qtVersionIsAtLeast6_4() const; Q_INVOKABLE bool qtVersionIsAtLeast6_4() const;
Q_INVOKABLE void invalidateThumbnail(const QString &id); Q_INVOKABLE void invalidateThumbnail(const QString &id);
Q_INVOKABLE QSize imageSize(const QString &id);
Q_INVOKABLE QString assetFileSize(const QString &id);
Q_INVOKABLE bool assetIsImage(const QString &id);
Q_INVOKABLE void addTextures(const QStringList &filePaths); Q_INVOKABLE void addTextures(const QStringList &filePaths);
Q_INVOKABLE void addLightProbe(const QString &filePaths); Q_INVOKABLE void addLightProbe(const QString &filePaths);

View File

@@ -6,6 +6,7 @@
#include "anchoraction.h" #include "anchoraction.h"
#include "changestyleaction.h" #include "changestyleaction.h"
#include "designeractionmanagerview.h" #include "designeractionmanagerview.h"
#include "designericons.h"
#include "designermcumanager.h" #include "designermcumanager.h"
#include "formatoperation.h" #include "formatoperation.h"
#include "modelnodecontextmenu_helper.h" #include "modelnodecontextmenu_helper.h"
@@ -286,14 +287,19 @@ QHash<QString, QStringList> DesignerActionManager::handleExternalAssetsDrop(cons
return addedCategoryFiles; return addedCategoryFiles;
} }
QIcon DesignerActionManager::contextIcon(int contextId) const
{
return m_designerIcons->icon(DesignerIcons::IconId(contextId), DesignerIcons::ContextMenuArea);
}
class VisiblityModelNodeAction : public ModelNodeContextMenuAction class VisiblityModelNodeAction : public ModelNodeContextMenuAction
{ {
public: public:
VisiblityModelNodeAction(const QByteArray &id, const QString &description, const QByteArray &category, const QKeySequence &key, int priority, VisiblityModelNodeAction(const QByteArray &id, const QString &description, const QIcon &icon, const QByteArray &category, const QKeySequence &key, int priority,
SelectionContextOperation action, SelectionContextOperation action,
SelectionContextPredicate enabled = &SelectionContextFunctors::always, SelectionContextPredicate enabled = &SelectionContextFunctors::always,
SelectionContextPredicate visibility = &SelectionContextFunctors::always) : SelectionContextPredicate visibility = &SelectionContextFunctors::always) :
ModelNodeContextMenuAction(id, description, {}, category, key, priority, action, enabled, visibility) ModelNodeContextMenuAction(id, description, icon, category, key, priority, action, enabled, visibility)
{} {}
void updateContext() override void updateContext() override
@@ -376,8 +382,8 @@ public:
class SelectionModelNodeAction : public ActionGroup class SelectionModelNodeAction : public ActionGroup
{ {
public: public:
SelectionModelNodeAction(const QString &displayName, const QByteArray &menuId, int priority) : SelectionModelNodeAction(const QString &displayName, const QByteArray &menuId, const QIcon &icon, int priority) :
ActionGroup(displayName, menuId, priority, ActionGroup(displayName, menuId, icon, priority,
&SelectionContextFunctors::always, &SelectionContextFunctors::selectionEnabled) &SelectionContextFunctors::always, &SelectionContextFunctors::selectionEnabled)
{} {}
@@ -599,9 +605,10 @@ void removeSignal(SignalHandlerProperty signalHandler)
class ConnectionsModelNodeActionGroup : public ActionGroup class ConnectionsModelNodeActionGroup : public ActionGroup
{ {
public: public:
ConnectionsModelNodeActionGroup(const QString &displayName, const QByteArray &menuId, int priority) ConnectionsModelNodeActionGroup(const QString &displayName, const QByteArray &menuId, const QIcon &icon, int priority)
: ActionGroup(displayName, : ActionGroup(displayName,
menuId, menuId,
icon,
priority, priority,
&SelectionContextFunctors::always, &SelectionContextFunctors::always,
&SelectionContextFunctors::selectionEnabled) &SelectionContextFunctors::selectionEnabled)
@@ -968,8 +975,8 @@ bool isFlowTargetOrTransition(const SelectionContext &context)
class FlowActionConnectAction : public ActionGroup class FlowActionConnectAction : public ActionGroup
{ {
public: public:
FlowActionConnectAction(const QString &displayName, const QByteArray &menuId, int priority) : FlowActionConnectAction(const QString &displayName, const QByteArray &menuId, const QIcon &icon, int priority) :
ActionGroup(displayName, menuId, priority, ActionGroup(displayName, menuId, icon, priority,
&isFlowActionItemItem, &flowOptionVisible) &isFlowActionItemItem, &flowOptionVisible)
{} {}
@@ -1341,16 +1348,19 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new SelectionModelNodeAction( addDesignerAction(new SelectionModelNodeAction(
selectionCategoryDisplayName, selectionCategoryDisplayName,
selectionCategory, selectionCategory,
contextIcon(DesignerIcons::SelecionIcon),
Priorities::SelectionCategory)); Priorities::SelectionCategory));
addDesignerAction(new ConnectionsModelNodeActionGroup( addDesignerAction(new ConnectionsModelNodeActionGroup(
connectionsCategoryDisplayName, connectionsCategoryDisplayName,
connectionsCategory, connectionsCategory,
contextIcon(DesignerIcons::ConnectionsIcon),
Priorities::ConnectionsCategory)); Priorities::ConnectionsCategory));
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
arrangeCategoryDisplayName, arrangeCategoryDisplayName,
arrangeCategory, arrangeCategory,
contextIcon(DesignerIcons::ArrangeIcon),
Priorities::ArrangeCategory, Priorities::ArrangeCategory,
&selectionNotEmpty)); &selectionNotEmpty));
@@ -1408,7 +1418,11 @@ void DesignerActionManager::createDefaultDesignerActions()
&reverse, &reverse,
&multiSelectionAndHasSameParent)); &multiSelectionAndHasSameParent));
addDesignerAction(new ActionGroup(editCategoryDisplayName, editCategory, Priorities::EditCategory, &selectionNotEmpty)); addDesignerAction(new ActionGroup(editCategoryDisplayName,
editCategory,
contextIcon(DesignerIcons::EditIcon),
Priorities::EditCategory,
&selectionNotEmpty));
addDesignerAction(new SeperatorDesignerAction(editCategory, 30)); addDesignerAction(new SeperatorDesignerAction(editCategory, 30));
@@ -1491,6 +1505,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new VisiblityModelNodeAction( addDesignerAction(new VisiblityModelNodeAction(
visiblityCommandId, visiblityCommandId,
visibilityDisplayName, visibilityDisplayName,
contextIcon(DesignerIcons::VisibilityIcon),
rootCategory, rootCategory,
QKeySequence("Ctrl+g"), QKeySequence("Ctrl+g"),
Priorities::Visibility, Priorities::Visibility,
@@ -1499,6 +1514,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ActionGroup(anchorsCategoryDisplayName, addDesignerAction(new ActionGroup(anchorsCategoryDisplayName,
anchorsCategory, anchorsCategory,
contextIcon(DesignerIcons::AnchorsIcon),
Priorities::AnchorsCategory, Priorities::AnchorsCategory,
&anchorsMenuEnabled)); &anchorsMenuEnabled));
@@ -1596,18 +1612,21 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
positionerCategoryDisplayName, positionerCategoryDisplayName,
positionerCategory, positionerCategory,
contextIcon(DesignerIcons::PositionsersIcon),
Priorities::PositionCategory, Priorities::PositionCategory,
&positionOptionVisible)); &positionOptionVisible));
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
layoutCategoryDisplayName, layoutCategoryDisplayName,
layoutCategory, layoutCategory,
contextIcon(DesignerIcons::LayoutsIcon),
Priorities::LayoutCategory, Priorities::LayoutCategory,
&layoutOptionVisible)); &layoutOptionVisible));
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
snappingCategoryDisplayName, snappingCategoryDisplayName,
snappingCategory, snappingCategory,
contextIcon(DesignerIcons::SnappingIcon),
Priorities::SnappingCategory, Priorities::SnappingCategory,
&selectionEnabled, &selectionEnabled,
&selectionEnabled)); &selectionEnabled));
@@ -1615,12 +1634,14 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
groupCategoryDisplayName, groupCategoryDisplayName,
groupCategory, groupCategory,
contextIcon(DesignerIcons::GroupSelectionIcon),
Priorities::Group, Priorities::Group,
&studioComponentsAvailableAndSelectionCanBeLayouted)); &studioComponentsAvailableAndSelectionCanBeLayouted));
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
flowCategoryDisplayName, flowCategoryDisplayName,
flowCategory, flowCategory,
{},
Priorities::FlowCategory, Priorities::FlowCategory,
&isFlowTargetOrTransition, &isFlowTargetOrTransition,
&flowOptionVisible)); &flowOptionVisible));
@@ -1629,6 +1650,7 @@ void DesignerActionManager::createDefaultDesignerActions()
auto effectMenu = new ActionGroup( auto effectMenu = new ActionGroup(
flowEffectCategoryDisplayName, flowEffectCategoryDisplayName,
flowEffectCategory, flowEffectCategory,
{},
Priorities::FlowCategory, Priorities::FlowCategory,
&isFlowTransitionItem, &isFlowTransitionItem,
&flowOptionVisible); &flowOptionVisible);
@@ -1662,6 +1684,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new FlowActionConnectAction( addDesignerAction(new FlowActionConnectAction(
flowConnectionCategoryDisplayName, flowConnectionCategoryDisplayName,
flowConnectionCategory, flowConnectionCategory,
{},
Priorities::FlowCategory)); Priorities::FlowCategory));
@@ -1688,6 +1711,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
stackedContainerCategoryDisplayName, stackedContainerCategoryDisplayName,
stackedContainerCategory, stackedContainerCategory,
{},
Priorities::StackedContainerCategory, Priorities::StackedContainerCategory,
&isStackedContainer)); &isStackedContainer));
@@ -1888,7 +1912,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ModelNodeContextMenuAction( addDesignerAction(new ModelNodeContextMenuAction(
goIntoComponentCommandId, goIntoComponentCommandId,
enterComponentDisplayName, enterComponentDisplayName,
{}, contextIcon(DesignerIcons::EnterComponentIcon),
rootCategory, rootCategory,
QKeySequence(Qt::Key_F2), QKeySequence(Qt::Key_F2),
Priorities::ComponentActions + 2, Priorities::ComponentActions + 2,
@@ -1898,7 +1922,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ModelNodeContextMenuAction( addDesignerAction(new ModelNodeContextMenuAction(
editAnnotationsCommandId, editAnnotationsCommandId,
editAnnotationsDisplayName, editAnnotationsDisplayName,
{}, contextIcon(DesignerIcons::AnnotationIcon),
rootCategory, rootCategory,
QKeySequence(), QKeySequence(),
Priorities::EditAnnotations, Priorities::EditAnnotations,
@@ -1909,7 +1933,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ModelNodeContextMenuAction( addDesignerAction(new ModelNodeContextMenuAction(
addMouseAreaFillCommandId, addMouseAreaFillCommandId,
addMouseAreaFillDisplayName, addMouseAreaFillDisplayName,
{}, contextIcon(DesignerIcons::AddMouseAreaIcon),
rootCategory, rootCategory,
QKeySequence(), QKeySequence(),
Priorities::AddMouseArea, Priorities::AddMouseArea,
@@ -1943,7 +1967,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ModelNodeContextMenuAction( addDesignerAction(new ModelNodeContextMenuAction(
makeComponentCommandId, makeComponentCommandId,
makeComponentDisplayName, makeComponentDisplayName,
{}, contextIcon(DesignerIcons::MakeComponentIcon),
rootCategory, rootCategory,
QKeySequence(), QKeySequence(),
Priorities::ComponentActions + 1, Priorities::ComponentActions + 1,
@@ -1954,7 +1978,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ModelNodeContextMenuAction( addDesignerAction(new ModelNodeContextMenuAction(
editMaterialCommandId, editMaterialCommandId,
editMaterialDisplayName, editMaterialDisplayName,
{}, contextIcon(DesignerIcons::EditIcon),
rootCategory, rootCategory,
QKeySequence(), QKeySequence(),
44, 44,
@@ -1974,6 +1998,7 @@ void DesignerActionManager::createDefaultDesignerActions()
addDesignerAction(new ActionGroup( addDesignerAction(new ActionGroup(
"", "",
genericToolBarCategory, genericToolBarCategory,
{},
Priorities::GenericToolBar)); Priorities::GenericToolBar));
addDesignerAction(new ChangeStyleAction()); addDesignerAction(new ChangeStyleAction());
@@ -2114,6 +2139,7 @@ DesignerActionManager::DesignerActionManager(DesignerActionManagerView *designer
: m_designerActionManagerView(designerActionManagerView) : m_designerActionManagerView(designerActionManagerView)
, m_externalDependencies(externalDependencies) , m_externalDependencies(externalDependencies)
{ {
setupIcons();
} }
DesignerActionManager::~DesignerActionManager() = default; DesignerActionManager::~DesignerActionManager() = default;
@@ -2145,6 +2171,20 @@ void DesignerActionManager::addCustomTransitionEffectAction()
&isFlowTransitionItem)); &isFlowTransitionItem));
} }
void DesignerActionManager::setupIcons()
{
m_designerIcons.reset(new DesignerIcons("qtds_propertyIconFont.ttf", designerIconResourcesPath()));
}
QString DesignerActionManager::designerIconResourcesPath() const
{
#ifdef SHARE_QML_PATH
if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/designericons.json";
#endif
return Core::ICore::resourcePath("qmldesigner/designericons.json").toString();
}
DesignerActionToolBar::DesignerActionToolBar(QWidget *parentWidget) : Utils::StyledBar(parentWidget), DesignerActionToolBar::DesignerActionToolBar(QWidget *parentWidget) : Utils::StyledBar(parentWidget),
m_toolBar(new QToolBar("ActionToolBar", this)) m_toolBar(new QToolBar("ActionToolBar", this))
{ {

View File

@@ -23,6 +23,7 @@ QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
class DesignerActionManagerView; class DesignerActionManagerView;
class DesignerIcons;
using AddResourceOperation = std::function<AddFilesResult(const QStringList &, const QString &, bool)>; using AddResourceOperation = std::function<AddFilesResult(const QStringList &, const QString &, bool)>;
using ModelNodePreviewImageOperation = std::function<QVariant(const ModelNode &)>; using ModelNodePreviewImageOperation = std::function<QVariant(const ModelNode &)>;
@@ -118,16 +119,20 @@ public:
ModelNodePreviewImageOperation modelNodePreviewOperation(const ModelNode &node) const; ModelNodePreviewImageOperation modelNodePreviewOperation(const ModelNode &node) const;
bool externalDragHasSupportedAssets(const QMimeData *data) const; bool externalDragHasSupportedAssets(const QMimeData *data) const;
QHash<QString, QStringList> handleExternalAssetsDrop(const QMimeData *data) const; QHash<QString, QStringList> handleExternalAssetsDrop(const QMimeData *data) const;
QIcon contextIcon(int contextId) const;
private: private:
void addTransitionEffectAction(const TypeName &typeName); void addTransitionEffectAction(const TypeName &typeName);
void addCustomTransitionEffectAction(); void addCustomTransitionEffectAction();
void setupIcons();
QString designerIconResourcesPath() const;
QList<QSharedPointer<ActionInterface> > m_designerActions; QList<QSharedPointer<ActionInterface> > m_designerActions;
DesignerActionManagerView *m_designerActionManagerView; DesignerActionManagerView *m_designerActionManagerView;
QList<AddResourceHandler> m_addResourceHandler; QList<AddResourceHandler> m_addResourceHandler;
QList<ModelNodePreviewImageHandler> m_modelNodePreviewImageHandlers; QList<ModelNodePreviewImageHandler> m_modelNodePreviewImageHandlers;
ExternalDependenciesInterface &m_externalDependencies; ExternalDependenciesInterface &m_externalDependencies;
QScopedPointer<DesignerIcons> m_designerIcons;
}; };
} //QmlDesigner } //QmlDesigner

View File

@@ -0,0 +1,418 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "designericons.h"
#include <invalidargumentexception.h>
#include <QCache>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMetaEnum>
#include <QRegularExpression>
using namespace QmlDesigner;
namespace { // Blank namespace
template <typename EType>
struct DesignerIconEnums
{
typedef EType EnumType;
static QString toString(const EnumType &enumValue);
static EnumType value(const QString &keyStr, bool *ok = nullptr);
static const QMetaEnum metaEnum;
static const QString keyName;
};
template <typename EType>
struct DesignerEnumConfidentType
{
typedef EType EnumType;
};
template <>
struct DesignerEnumConfidentType<QIcon::Mode>
{
typedef DesignerIcons::Mode EnumType;
};
template <>
struct DesignerEnumConfidentType<QIcon::State>
{
typedef DesignerIcons::State EnumType;
};
template <typename T>
QString getEnumName() {
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
QString enumName = QString::fromLatin1(metaEnum.enumName());
if (enumName.size() && enumName.at(0).isUpper())
enumName.replace(0, 1, enumName.at(0).toLower());
return enumName;
};
template <>
QString getEnumName<Theme::Icon>() {
return QLatin1String("iconName");
};
template <typename EType>
const QMetaEnum DesignerIconEnums<EType>::metaEnum =
QMetaEnum::fromType<typename DesignerEnumConfidentType<EType>::EnumType>();
template <typename EType>
const QString DesignerIconEnums<EType>::keyName =
getEnumName<typename DesignerEnumConfidentType<EType>::EnumType>();
template <typename EType>
QString DesignerIconEnums<EType>::toString(const EType &enumValue)
{
return QString::fromLatin1(metaEnum.valueToKey(enumValue));
}
template <typename EType>
EType DesignerIconEnums<EType>::value(const QString &keyStr, bool *ok)
{
return static_cast<EType>(metaEnum.keyToValue(keyStr.toLatin1(), ok));
}
Q_GLOBAL_STATIC(QStringList, _iconFontMandatoryKeys);
const QStringList & iconFontMandatoryKeys()
{
if (_iconFontMandatoryKeys->isEmpty()) {
*_iconFontMandatoryKeys
<< DesignerIconEnums<Theme::Icon>::keyName
<< DesignerIconEnums<Theme::Color>::keyName
<< DesignerIconEnums<QIcon::Mode>::keyName
<< DesignerIconEnums<QIcon::State>::keyName
<< "size";
}
return *_iconFontMandatoryKeys;
}
QJsonObject mergeJsons(const QJsonObject &prior, const QJsonObject &joiner)
{
QJsonObject object = prior;
const QStringList joinerKeys = joiner.keys();
for (const QString &joinerKey : joinerKeys) {
if (!object.contains(joinerKey)) {
object.insert(joinerKey, joiner.value(joinerKey));
} else {
QJsonValue ov = object.value(joinerKey);
QJsonValue jv = joiner.value(joinerKey);
if (ov.isObject() && jv.isObject()) {
QJsonObject mg = mergeJsons(ov.toObject(), jv.toObject());
object.insert(joinerKey, mg);
}
}
}
return object;
}
inline QString toJsonSize(const QSize &size)
{
return QString::fromLatin1("%1x%2").arg(size.width()).arg(size.height());
}
template <typename EnumType>
void pushSimpleEnumValue(QJsonObject &object, const EnumType &enumVal)
{
const QString &enumKey = DesignerIconEnums<EnumType>::keyName;
QString enumValue = DesignerIconEnums<EnumType>::toString(enumVal);
object.insert(enumKey, enumValue);
}
template <typename T>
T jsonSafeValue(const QJsonObject &jsonObject, const QString &symbolName,
std::function<bool (const T&)> validityCheck = [](const T&) -> bool {return true;})
{
if (!jsonObject.contains(symbolName))
throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, symbolName.toLatin1());
QVariant symbolVar = jsonObject.value(symbolName);
T extractedVal = symbolVar.value<T>();
if (!validityCheck(extractedVal))
throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, symbolName.toLatin1());
return extractedVal;
}
QSize jsonSafeSize(const QJsonObject &jsonObject, const QString &symbolName)
{
QString extractedVal = jsonSafeValue<QString>(jsonObject, symbolName);
QStringList dims = extractedVal.split("x");
if (dims.size() == 2) {
bool wOk;
bool hOk;
int cWidth = dims.first().toInt(&wOk);
int cHeight = dims.last().toInt(&hOk);
if (wOk && hOk)
return {cWidth, cHeight};
}
throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, symbolName.toLatin1());
return {};
}
template <typename T>
T jsonSafeMetaEnum(const QJsonObject &jsonObject, const QString &symbolName = DesignerIconEnums<T>::keyName)
{
QString extractedVal = jsonSafeValue<QString>(jsonObject, symbolName);
bool ok;
T enumIndex = static_cast<T> (DesignerIconEnums<T>::value(extractedVal, &ok));
if (ok)
return enumIndex;
throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, symbolName.toLatin1());
return {};
}
template <typename T>
struct JsonMap
{};
template <>
struct JsonMap<IconFontHelper>
{
static IconFontHelper value(const QJsonObject &jsonObject, const QJsonObject &telescopingMap)
{
QJsonObject fontHelperJson = mergeJsons(jsonObject, telescopingMap);
return IconFontHelper::fromJson(fontHelperJson);
}
static QJsonObject json(const IconFontHelper &iconFontHelper)
{
QJsonObject object;
pushSimpleEnumValue(object, iconFontHelper.themeIcon());
pushSimpleEnumValue(object, iconFontHelper.themeColor());
object.insert("size", toJsonSize(iconFontHelper.size()));
return object;
}
};
template <typename Key, typename Value>
struct JsonMap<QMap<Key, Value>>
{
typedef QMap<Key, Value> MapType;
static MapType value(const QJsonObject &mapObject, const QJsonObject &telescopingMap)
{
typedef typename MapType::key_type KeyType;
typedef typename MapType::mapped_type ValueType;
QMap<KeyType, ValueType> output;
QJsonObject curObject = mergeJsons(mapObject, telescopingMap);
const QStringList keyList = curObject.keys();
QStringList validKeys;
QString keyTypeStr = DesignerIconEnums<KeyType>::keyName;
QJsonObject nextTelescopingMap = telescopingMap;
for (const QString &jsonKey : keyList) {
bool keyAvailable = false;
DesignerIconEnums<KeyType>::value(jsonKey, &keyAvailable);
if (keyAvailable)
validKeys.append(jsonKey);
else
nextTelescopingMap.insert(jsonKey, curObject.value(jsonKey));
}
for (const QString &jsonKey : validKeys) {
bool keyAvailable = false;
const KeyType key = DesignerIconEnums<KeyType>::value(jsonKey, &keyAvailable);
QJsonValue jsonValue = curObject.value(jsonKey);
nextTelescopingMap.insert(keyTypeStr, jsonKey);
if (!jsonValue.isObject()) {
qWarning() << Q_FUNC_INFO << __LINE__ << "Value of the" << jsonKey << "should be a json object.";
continue;
}
output.insert(key, JsonMap<ValueType>::value(jsonValue.toObject(), nextTelescopingMap));
}
return output;
}
static QJsonObject json(const QMap<Key, Value> &map)
{
QJsonObject output;
for (const auto &[key, val] : map.asKeyValueRange())
output[DesignerIconEnums<Key>::toString(key)] = JsonMap<Value>::json(val);
return output;
}
};
} // End of blank namespace
class QmlDesigner::DesignerIconsPrivate
{
public:
DesignerIconsPrivate(const QString &fontName)
: mFontName(fontName) {}
QString mFontName;
DesignerIcons::IconsMap icons;
static QCache<QString, DesignerIcons::IconsMap> cache;
};
QCache<QString, DesignerIcons::IconsMap> DesignerIconsPrivate::cache(100);
IconFontHelper::IconFontHelper(Theme::Icon themeIcon, Theme::Color color, const QSize &size, QIcon::Mode mode, QIcon::State state)
: Super(Theme::getIconUnicode(themeIcon),
Theme::getColor(color),
size,
mode, state)
, mThemeIcon(themeIcon)
, mThemeColor(color)
{}
IconFontHelper IconFontHelper::fromJson(const QJsonObject &jsonObject)
{
try {
Theme::Icon iconName = jsonSafeMetaEnum<Theme::Icon>(jsonObject);
Theme::Color iconColor = jsonSafeMetaEnum<Theme::Color>(jsonObject);
QSize iconSize = jsonSafeSize(jsonObject, "size");
QIcon::Mode iconMode = jsonSafeMetaEnum<QIcon::Mode>(jsonObject);
QIcon::State iconState = jsonSafeMetaEnum<QIcon::State>(jsonObject);
return IconFontHelper(iconName, iconColor, iconSize, iconMode, iconState);
} catch (const Exception &exception) {
exception.showException("Faild to load IconFontHelper");
return {};
}
}
QJsonObject IconFontHelper::toJson() const
{
QJsonObject jsonObject;
pushSimpleEnumValue(jsonObject, themeIcon());
pushSimpleEnumValue(jsonObject, themeColor());
pushSimpleEnumValue(jsonObject, mode());
pushSimpleEnumValue(jsonObject, state());
jsonObject.insert("size", toJsonSize(size()));
return jsonObject;
}
Theme::Icon IconFontHelper::themeIcon() const
{
return mThemeIcon;
}
Theme::Color IconFontHelper::themeColor() const
{
return mThemeColor;
}
IconFontHelper::IconFontHelper()
: IconFontHelper({}, {}, {}, {}, {}) {}
DesignerIcons::DesignerIcons(const QString &fontName, const QString &iconDatabase)
: d(new DesignerIconsPrivate(fontName))
{
if (iconDatabase.size())
loadIconSettings(iconDatabase);
}
DesignerIcons::~DesignerIcons()
{
delete d;
}
QIcon DesignerIcons::icon(IconId icon, Area area) const
{
return Utils::StyleHelper::getIconFromIconFont(d->mFontName, helperList(icon, area));
}
void DesignerIcons::loadIconSettings(const QString &fileName)
{
if (d->cache.contains(fileName)) {
d->icons = *d->cache.object(fileName);
return;
}
QFile designerIconFile(fileName);
if (!designerIconFile.open(QFile::ReadOnly)) {
qWarning() << Q_FUNC_INFO << __LINE__ << "Can not open file:" << fileName << designerIconFile.errorString();
return;
}
if (designerIconFile.size() > 100e3) {
qWarning() << Q_FUNC_INFO << __LINE__ << "Large File:" << fileName;
return;
}
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(designerIconFile.readAll(), &parseError);
if (parseError.error != QJsonParseError::NoError) {
qWarning() << Q_FUNC_INFO << __LINE__ << "Json Parse Error - " << parseError.errorString() << "---\t File: " << fileName;
return;
}
if (!jsonDoc.isObject()) {
qWarning() << Q_FUNC_INFO << __LINE__ << "Invalid Json Array in file: " << fileName;
return;
}
clearAll();
d->icons = JsonMap<IconsMap>::value(jsonDoc.object(), {});
d->cache.insert(fileName, new IconsMap(d->icons), 1);
}
void DesignerIcons::exportSettings(const QString &fileName) const
{
QFile outFile(fileName);
if (!outFile.open(QFile::WriteOnly)) {
qWarning() << Q_FUNC_INFO << __LINE__ << "Can not open file for writing:" << fileName;
return;
}
QJsonDocument jsonDocument;
jsonDocument.setObject(JsonMap<IconsMap>::json(d->icons));
outFile.write(jsonDocument.toJson());
outFile.close();
}
void DesignerIcons::clearAll()
{
d->icons.clear();
}
void DesignerIcons::addIcon(const IconId &iconId, const Area &area, const IconFontHelper &fontHelper)
{
AreaMap &areaMap = d->icons[iconId];
IconMap &iconMap = areaMap[area];
ModeMap &modeMap = iconMap[static_cast<State>(fontHelper.state())];
modeMap.insert(static_cast<Mode>(fontHelper.mode()), fontHelper);
}
void DesignerIcons::addIcon(IconId iconId,
Area area,
QIcon::Mode mode,
QIcon::State state,
Theme::Icon themeIcon,
Theme::Color color,
const QSize &size)
{
addIcon(iconId, area, {themeIcon, color, size, mode, state});
}
void DesignerIcons::addIcon(IconId iconId, Area area, Theme::Icon themeIcon, Theme::Color color, const QSize &size)
{
addIcon(iconId, area, {themeIcon, color, size});
}
QList<Utils::StyleHelper::IconFontHelper> DesignerIcons::helperList(const IconId &iconId,
const Area &area) const
{
QList<Utils::StyleHelper::IconFontHelper> helperList;
const IconMap &iconMap = d->icons.value(iconId).value(area);
for (const ModeMap &modMap : iconMap) {
for (const IconFontHelper &iconFontHelper : modMap)
helperList.append(iconFontHelper);
}
return helperList;
}

View File

@@ -0,0 +1,133 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
#include "theme.h"
#include <utils/stylehelper.h>
#include <QIcon>
namespace QmlDesigner {
class DesignerIconsPrivate;
class IconFontHelper : public Utils::StyleHelper::IconFontHelper
{
typedef Utils::StyleHelper::IconFontHelper Super;
public:
IconFontHelper(Theme::Icon themeIcon,
Theme::Color color,
const QSize &size,
QIcon::Mode mode = QIcon::Normal,
QIcon::State state = QIcon::Off);
static IconFontHelper fromJson(const QJsonObject &jsonObject);
QJsonObject toJson() const;
Theme::Icon themeIcon() const;
Theme::Color themeColor() const;
private:
IconFontHelper();
Theme::Icon mThemeIcon;
Theme::Color mThemeColor;
};
class DesignerIcons
{
Q_GADGET
friend DesignerIconsPrivate;
public:
enum IconId {
AddMouseAreaIcon,
AlignBottomIcon,
AlignLeftIcon,
AlignRightIcon,
AlignTopIcon,
AnchorsIcon,
AnnotationIcon,
ArrangeIcon,
ConnectionsIcon,
EditIcon,
EnterComponentIcon,
EventListIcon,
GroupSelectionIcon,
LayoutsIcon,
MakeComponentIcon,
MergeWithTemplateIcon,
PositionsersIcon,
SelecionIcon,
SnappingIcon,
TimelineIcon,
ShowBoundsIcon,
VisibilityIcon
};
Q_ENUM(IconId)
enum Area {
TopToolbarArea,
ContextMenuArea
};
Q_ENUM(Area)
enum Mode {
Normal = QIcon::Normal,
Disabled = QIcon::Disabled,
Hovered = QIcon::Active,
Selected = QIcon::Selected
};
Q_ENUM(Mode)
enum State {
Off = QIcon::Off,
On = QIcon::On
};
Q_ENUM(State)
typedef QMap<Mode, IconFontHelper> ModeMap;
typedef QMap<State, ModeMap> IconMap;
typedef QMap<Area, IconMap> AreaMap;
typedef QMap<IconId, AreaMap> IconsMap;
explicit DesignerIcons(const QString &fontName,
const QString &iconDatabase = QString());
~DesignerIcons();
QIcon icon(IconId icon, Area area) const;
void loadIconSettings(const QString &fileName);
void exportSettings(const QString &fileName) const;
void clearAll();
void addIcon(const IconId &iconId,
const Area &area,
const IconFontHelper &fontHelper);
void addIcon(IconId iconId,
Area area,
QIcon::Mode mode,
QIcon::State state,
Theme::Icon themeIcon,
Theme::Color color,
const QSize &size);
void addIcon(IconId iconId,
Area area,
Theme::Icon themeIcon,
Theme::Color color,
const QSize &size);
private:
QList<Utils::StyleHelper::IconFontHelper> helperList(const IconId &iconId,
const Area &area) const;
DesignerIconsPrivate *d = nullptr;
};
}

View File

@@ -60,7 +60,7 @@ void populateMenu(QSet<ActionInterface* > &actionInterfaces,
|| actionInterface->type() == ActionInterface::FormEditorAction) { || actionInterface->type() == ActionInterface::FormEditorAction) {
QAction* action = actionInterface->action(); QAction* action = actionInterface->action();
actionInterface->currentContextChanged(selectionContext); actionInterface->currentContextChanged(selectionContext);
action->setIconVisibleInMenu(false); action->setIconVisibleInMenu(true);
menu->addAction(action); menu->addAction(action);
} }
} }

View File

@@ -141,7 +141,7 @@ public:
class ActionGroup : public AbstractActionGroup class ActionGroup : public AbstractActionGroup
{ {
public: public:
ActionGroup(const QString &displayName, const QByteArray &menuId, int priority, ActionGroup(const QString &displayName, const QByteArray &menuId, const QIcon &icon, int priority,
SelectionContextPredicate enabled = &SelectionContextFunctors::always, SelectionContextPredicate enabled = &SelectionContextFunctors::always,
SelectionContextPredicate visibility = &SelectionContextFunctors::always) : SelectionContextPredicate visibility = &SelectionContextFunctors::always) :
AbstractActionGroup(displayName), AbstractActionGroup(displayName),
@@ -150,6 +150,7 @@ public:
m_enabled(enabled), m_enabled(enabled),
m_visibility(visibility) m_visibility(visibility)
{ {
menu()->setIcon(icon);
} }
bool isVisible(const SelectionContext &m_selectionState) const override { return m_visibility(m_selectionState); } bool isVisible(const SelectionContext &m_selectionState) const override { return m_visibility(m_selectionState); }

View File

@@ -103,6 +103,7 @@ public:
gridView, gridView,
idAliasOff, idAliasOff,
idAliasOn, idAliasOn,
imported,
infinity, infinity,
keyframe, keyframe,
linkTriangle, linkTriangle,
@@ -131,6 +132,24 @@ public:
redo, redo,
rotationFill, rotationFill,
rotationOutline, rotationOutline,
s_anchors,
s_annotations,
s_arrange,
s_boundingBox,
s_component,
s_connections,
s_edit,
s_enterComponent,
s_eventList,
s_group,
s_layouts,
s_merging,
s_mouseArea,
s_positioners,
s_selection,
s_snapping,
s_timeline,
s_visibility,
search, search,
sectionToggle, sectionToggle,
splitColumns, splitColumns,
@@ -148,6 +167,14 @@ public:
textFullJustification, textFullJustification,
textNumberedList, textNumberedList,
tickIcon, tickIcon,
topToolbar_annotations,
topToolbar_closeFile,
topToolbar_designMode,
topToolbar_enterComponent,
topToolbar_home,
topToolbar_makeComponent,
topToolbar_navFile,
topToolbar_runProject,
translationCreateFiles, translationCreateFiles,
translationCreateReport, translationCreateReport,
translationExport, translationExport,

View File

@@ -5,9 +5,6 @@
#include "edit3dview.h" #include "edit3dview.h"
#include "edit3dwidget.h" #include "edit3dwidget.h"
#include "nodehints.h"
#include "qmlvisualnode.h"
#include <bindingproperty.h> #include <bindingproperty.h>
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <nodelistproperty.h> #include <nodelistproperty.h>
@@ -143,41 +140,6 @@ void Edit3DCanvas::resizeEvent(QResizeEvent *e)
m_parent->view()->edit3DViewResized(e->size()); m_parent->view()->edit3DViewResized(e->size());
} }
void Edit3DCanvas::dragEnterEvent(QDragEnterEvent *e)
{
// Block all drags if scene root node is locked
ModelNode node;
if (m_parent->view()->hasModelNodeForInternalId(m_activeScene))
node = m_parent->view()->modelNodeForInternalId(m_activeScene);
// Allow drop when there is no valid active scene, as the drop goes under the root node of
// the document in that case.
if (!ModelNode::isThisOrAncestorLocked(node)) {
QByteArray data = e->mimeData()->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
if (!data.isEmpty()) {
QDataStream stream(data);
stream >> m_itemLibraryEntry;
if (NodeHints::fromItemLibraryEntry(m_itemLibraryEntry).canBeDroppedInView3D())
e->accept();
}
}
}
void Edit3DCanvas::dropEvent(QDropEvent *e)
{
m_parent->view()->executeInTransaction(__FUNCTION__, [&] {
auto modelNode = QmlVisualNode::createQml3DNode(m_parent->view(), m_itemLibraryEntry, m_activeScene).modelNode();
QTC_ASSERT(modelNode.isValid(), return);
e->accept();
m_parent->view()->setSelectedModelNode(modelNode);
// if added node is a Model, assign it a material
if (modelNode.metaInfo().isQtQuick3DModel())
m_parent->view()->assignMaterialTo3dModel(modelNode);
});
}
void Edit3DCanvas::focusOutEvent(QFocusEvent *focusEvent) void Edit3DCanvas::focusOutEvent(QFocusEvent *focusEvent)
{ {
QmlDesignerPlugin::emitUsageStatisticsTime(Constants::EVENT_3DEDITOR_TIME, QmlDesignerPlugin::emitUsageStatisticsTime(Constants::EVENT_3DEDITOR_TIME,

View File

@@ -2,8 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once #pragma once
#include "itemlibraryinfo.h"
#include <QtWidgets/qwidget.h> #include <QtWidgets/qwidget.h>
#include <QtGui/qimage.h> #include <QtGui/qimage.h>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
@@ -38,8 +36,6 @@ protected:
void keyReleaseEvent(QKeyEvent *e) override; void keyReleaseEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void dragEnterEvent(QDragEnterEvent *e) override;
void dropEvent(QDropEvent *e) override;
void focusOutEvent(QFocusEvent *focusEvent) override; void focusOutEvent(QFocusEvent *focusEvent) override;
void focusInEvent(QFocusEvent *focusEvent) override; void focusInEvent(QFocusEvent *focusEvent) override;
@@ -49,7 +45,6 @@ private:
QPointer<Edit3DWidget> m_parent; QPointer<Edit3DWidget> m_parent;
QImage m_image; QImage m_image;
qint32 m_activeScene = -1; qint32 m_activeScene = -1;
ItemLibraryEntry m_itemLibraryEntry;
QElapsedTimer m_usageTimer; QElapsedTimer m_usageTimer;
qreal m_opacity = 1.0; qreal m_opacity = 1.0;
QWidget *m_busyIndicator = nullptr; QWidget *m_busyIndicator = nullptr;

View File

@@ -16,6 +16,7 @@
#include "qmldesignerconstants.h" #include "qmldesignerconstants.h"
#include "qmldesignericons.h" #include "qmldesignericons.h"
#include "qmldesignerplugin.h" #include "qmldesignerplugin.h"
#include "qmlvisualnode.h"
#include "seekerslider.h" #include "seekerslider.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -304,6 +305,16 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos
if (modelNode.isValid() && !modelNode.isSelected()) if (modelNode.isValid() && !modelNode.isSelected())
setSelectedModelNode(modelNode); setSelectedModelNode(modelNode);
m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode, pos3d); m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode, pos3d);
} else if (m_nodeAtPosReqType == NodeAtPosReqType::ComponentDrop) {
ModelNode createdNode;
executeInTransaction(__FUNCTION__, [&] {
createdNode = QmlVisualNode::createQml3DNode(
this, m_droppedEntry, edit3DWidget()->canvas()->activeScene(), pos3d).modelNode();
if (createdNode.metaInfo().isQtQuick3DModel())
assignMaterialTo3dModel(createdNode);
});
if (createdNode.isValid())
setSelectedModelNode(createdNode);
} else if (m_nodeAtPosReqType == NodeAtPosReqType::MaterialDrop) { } else if (m_nodeAtPosReqType == NodeAtPosReqType::MaterialDrop) {
bool isModel = modelNode.metaInfo().isQtQuick3DModel(); bool isModel = modelNode.metaInfo().isQtQuick3DModel();
if (m_droppedModelNode.isValid() && modelNode.isValid() && isModel) { if (m_droppedModelNode.isValid() && modelNode.isValid() && isModel) {
@@ -895,4 +906,11 @@ void Edit3DView::dropTexture(const ModelNode &textureNode, const QPointF &pos)
emitView3DAction(View3DActionType::GetNodeAtPos, pos); emitView3DAction(View3DActionType::GetNodeAtPos, pos);
} }
void Edit3DView::dropComponent(const ItemLibraryEntry &entry, const QPointF &pos)
{
m_nodeAtPosReqType = NodeAtPosReqType::ComponentDrop;
m_droppedEntry = entry;
emitView3DAction(View3DActionType::GetNodeAtPos, pos);
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once #pragma once
#include "itemlibraryinfo.h"
#include <qmldesignercomponents_global.h> #include <qmldesignercomponents_global.h>
#include <abstractview.h> #include <abstractview.h>
@@ -65,6 +66,7 @@ public:
void dropMaterial(const ModelNode &matNode, const QPointF &pos); void dropMaterial(const ModelNode &matNode, const QPointF &pos);
void dropBundleMaterial(const QPointF &pos); void dropBundleMaterial(const QPointF &pos);
void dropTexture(const ModelNode &textureNode, const QPointF &pos); void dropTexture(const ModelNode &textureNode, const QPointF &pos);
void dropComponent(const ItemLibraryEntry &entry, const QPointF &pos);
private slots: private slots:
void onEntriesChanged(); void onEntriesChanged();
@@ -72,6 +74,7 @@ private slots:
private: private:
enum class NodeAtPosReqType { enum class NodeAtPosReqType {
BundleMaterialDrop, BundleMaterialDrop,
ComponentDrop,
MaterialDrop, MaterialDrop,
TextureDrop, TextureDrop,
ContextMenu, ContextMenu,
@@ -122,6 +125,7 @@ private:
int particlemode; int particlemode;
ModelCache<QImage> m_canvasCache; ModelCache<QImage> m_canvasCache;
ModelNode m_droppedModelNode; ModelNode m_droppedModelNode;
ItemLibraryEntry m_droppedEntry;
NodeAtPosReqType m_nodeAtPosReqType; NodeAtPosReqType m_nodeAtPosReqType;
QPoint m_contextMenuPos; QPoint m_contextMenuPos;
QTimer m_compressionTimer; QTimer m_compressionTimer;

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "edit3dwidget.h" #include "edit3dwidget.h"
#include "designdocumentview.h" #include "designdocument.h"
#include "edit3dactions.h" #include "edit3dactions.h"
#include "edit3dcanvas.h" #include "edit3dcanvas.h"
#include "edit3dview.h" #include "edit3dview.h"
@@ -10,10 +10,10 @@
#include "metainfo.h" #include "metainfo.h"
#include "modelnodeoperations.h" #include "modelnodeoperations.h"
#include "nodeabstractproperty.h" #include "nodeabstractproperty.h"
#include "nodehints.h"
#include "qmldesignerconstants.h" #include "qmldesignerconstants.h"
#include "qmldesignerplugin.h" #include "qmldesignerplugin.h"
#include "qmlvisualnode.h" #include "qmlvisualnode.h"
#include "timelineactions.h"
#include "viewmanager.h" #include "viewmanager.h"
#include <auxiliarydataproperties.h> #include <auxiliarydataproperties.h>
@@ -249,6 +249,16 @@ bool Edit3DWidget::isPasteAvailable() const
return QApplication::clipboard()->text().startsWith(Constants::HEADER_3DPASTE_CONTENT); return QApplication::clipboard()->text().startsWith(Constants::HEADER_3DPASTE_CONTENT);
} }
bool Edit3DWidget::isSceneLocked() const
{
if (m_view && m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
if (ModelNode::isThisOrAncestorLocked(node))
return true;
}
return false;
}
// Called by the view to update the "create" sub-menu when the Quick3D entries are ready. // Called by the view to update the "create" sub-menu when the Quick3D entries are ready.
void Edit3DWidget::updateCreateSubMenu(const QStringList &keys, void Edit3DWidget::updateCreateSubMenu(const QStringList &keys,
const QHash<QString, QList<ItemLibraryEntry>> &entriesMap) const QHash<QString, QList<ItemLibraryEntry>> &entriesMap)
@@ -287,7 +297,7 @@ void Edit3DWidget::updateCreateSubMenu(const QStringList &keys,
void Edit3DWidget::onCreateAction() void Edit3DWidget::onCreateAction()
{ {
QAction *action = qobject_cast<QAction *>(sender()); QAction *action = qobject_cast<QAction *>(sender());
if (!action || !m_view || !m_view->model()) if (!action || !m_view || !m_view->model() || isSceneLocked())
return; return;
m_view->executeInTransaction(__FUNCTION__, [&] { m_view->executeInTransaction(__FUNCTION__, [&] {
@@ -374,6 +384,9 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode
const bool anyNodeSelected = view()->hasSelectedModelNodes(); const bool anyNodeSelected = view()->hasSelectedModelNodes();
const bool selectionExcludingRoot = anyNodeSelected && !view()->rootModelNode().isSelected(); const bool selectionExcludingRoot = anyNodeSelected && !view()->rootModelNode().isSelected();
if (m_createSubMenu)
m_createSubMenu->setEnabled(!isSceneLocked());
m_editComponentAction->setEnabled(isSingleComponent); m_editComponentAction->setEnabled(isSingleComponent);
m_editMaterialAction->setEnabled(isModel); m_editMaterialAction->setEnabled(isModel);
m_duplicateAction->setEnabled(selectionExcludingRoot); m_duplicateAction->setEnabled(selectionExcludingRoot);
@@ -407,6 +420,15 @@ Edit3DView *Edit3DWidget::view() const
void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent) void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
{ {
// Block all drags if scene root node is locked
if (m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
if (ModelNode::isThisOrAncestorLocked(node))
return;
}
m_draggedEntry = {};
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance() const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager(); ->viewManager().designerActionManager();
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()) if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData())
@@ -414,6 +436,14 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL) || dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_TEXTURE)) { || dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_TEXTURE)) {
dragEnterEvent->acceptProposedAction(); dragEnterEvent->acceptProposedAction();
} else if (dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
QByteArray data = dragEnterEvent->mimeData()->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
if (!data.isEmpty()) {
QDataStream stream(data);
stream >> m_draggedEntry;
if (NodeHints::fromItemLibraryEntry(m_draggedEntry).canBeDroppedInView3D())
dragEnterEvent->acceptProposedAction();
}
} }
} }
@@ -443,6 +473,13 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
return; return;
} }
// handle dropping from component view
if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
if (!m_draggedEntry.name().isEmpty())
m_view->dropComponent(m_draggedEntry, pos);
return;
}
// handle dropping external assets // handle dropping external assets
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance() const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager(); ->viewManager().designerActionManager();

View File

@@ -52,6 +52,7 @@ private:
void createContextMenu(); void createContextMenu();
bool isPasteAvailable() const; bool isPasteAvailable() const;
bool isSceneLocked() const;
QPointer<Edit3DView> m_edit3DView; QPointer<Edit3DView> m_edit3DView;
QPointer<Edit3DView> m_view; QPointer<Edit3DView> m_view;
@@ -77,6 +78,7 @@ private:
ModelNode m_contextMenuTarget; ModelNode m_contextMenuTarget;
QVector3D m_contextMenuPos3d; QVector3D m_contextMenuPos3d;
QHash<QString, ItemLibraryEntry> m_nameToEntry; QHash<QString, ItemLibraryEntry> m_nameToEntry;
ItemLibraryEntry m_draggedEntry;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -3,6 +3,7 @@
#include "eventlistpluginview.h" #include "eventlistpluginview.h"
#include "assigneventdialog.h" #include "assigneventdialog.h"
#include "connectsignaldialog.h" #include "connectsignaldialog.h"
#include "designericons.h"
#include "eventlistactions.h" #include "eventlistactions.h"
#include "eventlistdialog.h" #include "eventlistdialog.h"
@@ -45,6 +46,7 @@ void EventListPluginView::registerActions()
designerActionManager.addDesignerAction(new ActionGroup(tr("Event List"), designerActionManager.addDesignerAction(new ActionGroup(tr("Event List"),
ComponentCoreConstants::eventListCategory, ComponentCoreConstants::eventListCategory,
designerActionManager.contextIcon(DesignerIcons::EventListIcon),
ComponentCoreConstants::Priorities::EventListCategory, ComponentCoreConstants::Priorities::EventListCategory,
&SelectionContextFunctors::always, &SelectionContextFunctors::always,
&SelectionContextFunctors::always)); &SelectionContextFunctors::always));

View File

@@ -3,6 +3,7 @@
#include "formeditorwidget.h" #include "formeditorwidget.h"
#include "designeractionmanager.h" #include "designeractionmanager.h"
#include "designericons.h"
#include "designersettings.h" #include "designersettings.h"
#include "formeditoritem.h" #include "formeditoritem.h"
#include "formeditorscene.h" #include "formeditorscene.h"
@@ -104,6 +105,7 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view)
m_showBoundingRectAction = new QAction(tr("Show Bounds"), this); m_showBoundingRectAction = new QAction(tr("Show Bounds"), this);
m_showBoundingRectAction->setCheckable(true); m_showBoundingRectAction->setCheckable(true);
m_showBoundingRectAction->setChecked(false); m_showBoundingRectAction->setChecked(false);
m_showBoundingRectAction->setIcon(DesignerActionManager::instance().contextIcon(DesignerIcons::ShowBoundsIcon));
registerActionAsCommand(m_showBoundingRectAction, registerActionAsCommand(m_showBoundingRectAction,
Constants::FORMEDITOR_NO_SHOW_BOUNDING_RECTANGLE, Constants::FORMEDITOR_NO_SHOW_BOUNDING_RECTANGLE,
QKeySequence(Qt::Key_A), QKeySequence(Qt::Key_A),

View File

@@ -4,13 +4,16 @@
#include "materialeditorcontextobject.h" #include "materialeditorcontextobject.h"
#include <abstractview.h> #include <abstractview.h>
#include <bindingproperty.h>
#include <documentmanager.h>
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <rewritingexception.h> #include <rewritingexception.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmlmodelnodeproxy.h> #include <qmlmodelnodeproxy.h>
#include <qmlobjectnode.h> #include <qmlobjectnode.h>
#include <qmltimeline.h> #include <qmltimeline.h>
#include <documentmanager.h> #include <qmltimelinekeyframegroup.h>
#include <variantproperty.h>
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -129,6 +132,48 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName)
incompatibleProperties.append(property.name()); incompatibleProperties.append(property.name());
} }
// When switching between material types, copy base (diffuse) color and map properties of
// source type into corresponding properties of the target type.
const QList<PropertyName> baseColors = {"baseColor", "diffuseColor", "albedoColor"};
const QList<PropertyName> baseMaps = {"baseColorMap", "diffuseMap", "albedoMap"};
int sourceIndex = -1;
int targetIndex = -1;
NodeMetaInfo oldMetaInfo = m_selectedMaterial.metaInfo();
struct CopyData {
CopyData() {};
CopyData(PropertyName n) : name(n) {}
PropertyName name;
QVariant value;
bool isBinding = false;
};
QHash<PropertyName, CopyData> copyMap;
if (oldMetaInfo.isQtQuick3DPrincipledMaterial())
sourceIndex = 0;
else if (oldMetaInfo.isQtQuick3DDefaultMaterial())
sourceIndex = 1;
else if (oldMetaInfo.isQtQuick3DSpecularGlossyMaterial())
sourceIndex = 2;
if (metaInfo.isQtQuick3DPrincipledMaterial())
targetIndex = 0;
else if (metaInfo.isQtQuick3DDefaultMaterial())
targetIndex = 1;
else if (metaInfo.isQtQuick3DSpecularGlossyMaterial())
targetIndex = 2;
if (sourceIndex >= 0 && targetIndex >= 0) {
if (incompatibleProperties.contains(baseColors[sourceIndex])) {
copyMap.insert(baseColors[sourceIndex], baseColors[targetIndex]);
incompatibleProperties.removeOne(baseColors[sourceIndex]);
}
if (incompatibleProperties.contains(baseMaps[sourceIndex])) {
copyMap.insert(baseMaps[sourceIndex], baseMaps[targetIndex]);
incompatibleProperties.removeOne(baseMaps[sourceIndex]);
}
}
const auto &copyKeys = copyMap.keys();
Utils::sort(incompatibleProperties); Utils::sort(incompatibleProperties);
// Create a dialog showing incompatible properties and signals // Create a dialog showing incompatible properties and signals
@@ -159,10 +204,47 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName)
m_selectedMaterial.removeProperty(p); m_selectedMaterial.removeProperty(p);
} }
if (!copyKeys.isEmpty()) {
// Copy mapped properties to new name. Note that this will only copy the base
// property value and adjust the keyframe groups. Any other bindings related
// to the property will be ignored.
const QList<ModelNode> timeLines = QmlObjectNode(m_selectedMaterial).allTimelines();
for (const auto &key : std::as_const(copyKeys)) {
CopyData &copyData = copyMap[key];
for (const auto &timeLineNode : timeLines) {
QmlTimeline timeLine(timeLineNode);
if (timeLine.hasKeyframeGroup(m_selectedMaterial, key)) {
QmlTimelineKeyframeGroup group = timeLine.keyframeGroup(m_selectedMaterial,
key);
group.setPropertyName(copyData.name);
}
}
// Property value itself cannot be copied until type has been changed, so store it
AbstractProperty prop = m_selectedMaterial.property(key);
if (prop.isValid()) {
if (prop.isBindingProperty()) {
copyData.isBinding = true;
copyData.value = prop.toBindingProperty().expression();
} else {
copyData.value = prop.toVariantProperty().value();
}
}
m_selectedMaterial.removeProperty(key);
}
}
if (m_selectedMaterial.isRootNode()) if (m_selectedMaterial.isRootNode())
rewriterView->changeRootNodeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion()); rewriterView->changeRootNodeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
else else
m_selectedMaterial.changeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion()); m_selectedMaterial.changeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
for (const auto &key : copyKeys) {
const CopyData &copyData = copyMap[key];
if (copyData.isBinding)
m_selectedMaterial.bindingProperty(copyData.name).setExpression(copyData.value.toString());
else
m_selectedMaterial.variantProperty(copyData.name).setValue(copyData.value);
}
}); });
} }

View File

@@ -39,6 +39,8 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
// -> Model // -> Model
// BundleMaterial // BundleMaterial
// -> Model // -> Model
// Effect
// -> Item
if (insertInfo.isQtQuick3DTexture()) { if (insertInfo.isQtQuick3DTexture()) {
if (parentInfo.isQtQuick3DDefaultMaterial() || parentInfo.isQtQuick3DPrincipledMaterial() if (parentInfo.isQtQuick3DDefaultMaterial() || parentInfo.isQtQuick3DPrincipledMaterial()
@@ -88,11 +90,14 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
|| parentInfo.isQtQuick3DParticles3DAttractor3D()) || parentInfo.isQtQuick3DParticles3DAttractor3D())
propertyList.append("shape"); propertyList.append("shape");
} else if (insertInfo.isQtQuick3DMaterial()) { } else if (insertInfo.isQtQuick3DMaterial()) {
if (parentInfo.isQtQuick3DParticles3DModel()) if (parentInfo.isQtQuick3DModel())
propertyList.append("materials"); propertyList.append("materials");
// TODO merge conflict between Change-Id: If3c58f82797beabe76baf99ea2dddc59032729df and Change-Id: Iff2dea66e253b412105427134bd49cb16ed76193 } else if (insertInfo.typeName().startsWith("ComponentBundles.MaterialBundle")) {
// } else if (insertInfo.typeName().startsWith("ComponentBundles.MaterialBundle")) { if (parentInfo.isQtQuick3DModel())
// if (parentInfo.isSubclassOf("QtQuick3D.Model")) propertyList.append("materials");
} else if (insertInfo.isEffectMaker()) {
if (parentInfo.isQtQuickItem())
propertyList.append("effect");
} }
} }

View File

@@ -211,6 +211,7 @@ void NameItemDelegate::paint(QPainter *painter,
} }
ModelNode node = getModelNode(modelIndex); ModelNode node = getModelNode(modelIndex);
if (!ModelNode::isThisOrAncestorLocked(node)) {
NavigatorWidget *widget = qobject_cast<NavigatorWidget *>(styleOption.widget->parent()); NavigatorWidget *widget = qobject_cast<NavigatorWidget *>(styleOption.widget->parent());
if (widget && !widget->dragType().isEmpty()) { if (widget && !widget->dragType().isEmpty()) {
QByteArray dragType = widget->dragType(); QByteArray dragType = widget->dragType();
@@ -227,6 +228,7 @@ void NameItemDelegate::paint(QPainter *painter,
} }
delete filter; delete filter;
} }
}
iconOffset = drawIcon(painter, styleOption, modelIndex); iconOffset = drawIcon(painter, styleOption, modelIndex);

View File

@@ -1019,7 +1019,8 @@ ModelNode NavigatorTreeModel::handleItemLibraryEffectDrop(const QString &effectP
ModelNode targetNode(modelNodeForIndex(rowModelIndex)); ModelNode targetNode(modelNodeForIndex(rowModelIndex));
ModelNode newModelNode; ModelNode newModelNode;
if (targetNode.hasParentProperty() && targetNode.parentProperty().name() == "layer.effect") if ((targetNode.hasParentProperty() && targetNode.parentProperty().name() == "layer.effect")
|| !targetNode.metaInfo().isQtQuickItem())
return newModelNode; return newModelNode;
if (ModelNodeOperations::validateEffect(effectPath)) { if (ModelNodeOperations::validateEffect(effectPath)) {

View File

@@ -7,6 +7,8 @@
#include "qmldesignerconstants.h" #include "qmldesignerconstants.h"
#include "qmldesignericons.h" #include "qmldesignericons.h"
#include "qmldesignerplugin.h" #include "qmldesignerplugin.h"
#include "assetslibrarywidget.h"
#include "commontypecache.h"
#include "nameitemdelegate.h" #include "nameitemdelegate.h"
#include "iconcheckboxitemdelegate.h" #include "iconcheckboxitemdelegate.h"
@@ -266,6 +268,18 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
m_widget->setDragType(bundleMatType); m_widget->setDragType(bundleMatType);
m_widget->update(); m_widget->update();
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
if (assetsPaths.count() > 0) {
auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetsPaths[0]);
QString assetType = assetTypeAndData.first;
if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
// We use arbitrary type name because at this time we don't have effect maker
// specific type
m_widget->setDragType(Storage::Info::EffectMaker);
m_widget->update();
}
}
} }
} }
@@ -389,6 +403,13 @@ void NavigatorView::auxiliaryDataChanged(const ModelNode &modelNode,
[[maybe_unused]] const QVariant &data) [[maybe_unused]] const QVariant &data)
{ {
m_currentModelInterface->notifyDataChanged(modelNode); m_currentModelInterface->notifyDataChanged(modelNode);
if (key == lockedProperty) {
// Also notify data changed on child nodes to redraw them
const QList<ModelNode> childNodes = modelNode.allSubModelNodes();
for (const auto &childNode : childNodes)
m_currentModelInterface->notifyDataChanged(childNode);
}
} }
void NavigatorView::instanceErrorChanged(const QVector<ModelNode> &errorNodeList) void NavigatorView::instanceErrorChanged(const QVector<ModelNode> &errorNodeList)

View File

@@ -36,7 +36,7 @@ QQuickImageResponse *PropertyEditorImageProvider::requestImageResponse(const QSt
response->setImage(image.scaled(requestedSize, Qt::KeepAspectRatio)); response->setImage(image.scaled(requestedSize, Qt::KeepAspectRatio));
return; return;
} }
} else if (asset.isTexture3D()) { } else if (asset.isHdrFile()) {
HdrImage hdr{asset.id()}; HdrImage hdr{asset.id()};
if (!hdr.image().isNull()) { if (!hdr.image().isNull()) {
response->setImage(hdr.image().scaled(requestedSize, Qt::KeepAspectRatio)); response->setImage(hdr.image().scaled(requestedSize, Qt::KeepAspectRatio));

View File

@@ -3,6 +3,7 @@
#include "timelineview.h" #include "timelineview.h"
#include "designericons.h"
#include "easingcurve.h" #include "easingcurve.h"
#include "timelineactions.h" #include "timelineactions.h"
#include "timelineconstants.h" #include "timelineconstants.h"
@@ -584,6 +585,7 @@ void TimelineView::registerActions()
actionManager.addDesignerAction(new ActionGroup(TimelineConstants::timelineCategoryDisplayName, actionManager.addDesignerAction(new ActionGroup(TimelineConstants::timelineCategoryDisplayName,
TimelineConstants::timelineCategory, TimelineConstants::timelineCategory,
actionManager.contextIcon(DesignerIcons::TimelineIcon),
ComponentCoreConstants::Priorities::TimelineCategory, ComponentCoreConstants::Priorities::TimelineCategory,
timelineEnabled, timelineEnabled,
&SelectionContextFunctors::always)); &SelectionContextFunctors::always));

View File

@@ -100,6 +100,7 @@ public:
bool isAlias() const; bool isAlias() const;
bool isBool() const; bool isBool() const;
bool isColor() const; bool isColor() const;
bool isEffectMaker() const;
bool isFloat() const; bool isFloat() const;
bool isFlowViewFlowActionArea() const; bool isFlowViewFlowActionArea() const;
bool isFlowViewFlowDecision() const; bool isFlowViewFlowDecision() const;
@@ -129,7 +130,6 @@ public:
bool isQtQuick3DNode() const; bool isQtQuick3DNode() const;
bool isQtQuick3DParticles3DAffector3D() const; bool isQtQuick3DParticles3DAffector3D() const;
bool isQtQuick3DParticles3DAttractor3D() const; bool isQtQuick3DParticles3DAttractor3D() const;
bool isQtQuick3DParticles3DModel() const;
bool isQtQuick3DParticles3DParticle3D() const; bool isQtQuick3DParticles3DParticle3D() const;
bool isQtQuick3DParticles3DParticleEmitter3D() const; bool isQtQuick3DParticles3DParticleEmitter3D() const;
bool isQtQuick3DParticles3DSpriteParticle3D() const; bool isQtQuick3DParticles3DSpriteParticle3D() const;

View File

@@ -640,14 +640,12 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
case AuxiliaryDataType::Document: case AuxiliaryDataType::Document:
if ((key == lockedProperty || key == invisibleProperty) && hasInstanceForModelNode(node)) { if ((key == lockedProperty || key == invisibleProperty) && hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node); NodeInstance instance = instanceForModelNode(node);
if (value.isValid()) {
PropertyValueContainer container{instance.instanceId(), PropertyValueContainer container{instance.instanceId(),
PropertyName{key.name}, PropertyName{key.name},
value, value,
TypeName(), TypeName(),
key.type}; key.type};
m_nodeInstanceServer->changeAuxiliaryValues({{container}}); m_nodeInstanceServer->changeAuxiliaryValues({{container}});
}
}; };
break; break;

View File

@@ -343,6 +343,8 @@ static inline bool isValueType(const TypeName &type)
"QPointF", "QPointF",
"QSize", "QSize",
"QSizeF", "QSizeF",
"QRect",
"QRectF",
"QVector2D", "QVector2D",
"QVector3D", "QVector3D",
"QVector4D", "QVector4D",
@@ -361,6 +363,8 @@ static inline bool isValueType(const QString &type)
"QPointF", "QPointF",
"QSize", "QSize",
"QSizeF", "QSizeF",
"QRect",
"QRectF",
"QVector2D", "QVector2D",
"QVector3D", "QVector3D",
"QVector4D", "QVector4D",
@@ -405,7 +409,7 @@ QVector<PropertyInfo> getQmlTypes(const CppComponentValue *objectValue, const Co
if (objectValue->className().isEmpty()) if (objectValue->className().isEmpty())
return propertyList; return propertyList;
if (rec > 2) if (rec > 4)
return propertyList; return propertyList;
PropertyMemberProcessor processor(context); PropertyMemberProcessor processor(context);
@@ -427,9 +431,14 @@ QVector<PropertyInfo> getQmlTypes(const CppComponentValue *objectValue, const Co
} }
} }
if (isValueType(objectValue->propertyType(nameAsString))) { if (isValueType(objectValue->propertyType(nameAsString))) {
const ObjectValue *dotObjectValue = value_cast<ObjectValue>(objectValue->lookupMember(nameAsString, context)); const ObjectValue *dotObjectValue = value_cast<ObjectValue>(
objectValue->lookupMember(nameAsString, context));
if (dotObjectValue) { if (dotObjectValue) {
const QVector<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue, context, false, rec + 1); const QVector<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue,
context,
false,
rec + 1);
for (const PropertyInfo &propertyInfo : dotProperties) { for (const PropertyInfo &propertyInfo : dotProperties) {
const PropertyName dotName = name + '.' + propertyInfo.first; const PropertyName dotName = name + '.' + propertyInfo.first;
const TypeName type = propertyInfo.second; const TypeName type = propertyInfo.second;
@@ -521,7 +530,7 @@ QVector<PropertyInfo> getObjectTypes(const ObjectValue *objectValue, const Conte
if (objectValue->className().isEmpty()) if (objectValue->className().isEmpty())
return propertyList; return propertyList;
if (rec > 2) if (rec > 4)
return propertyList; return propertyList;
PropertyMemberProcessor processor(context); PropertyMemberProcessor processor(context);
@@ -535,6 +544,7 @@ QVector<PropertyInfo> getObjectTypes(const ObjectValue *objectValue, const Conte
if (isValueType(property.second)) { if (isValueType(property.second)) {
const Value *dotValue = objectValue->lookupMember(nameAsString, context); const Value *dotValue = objectValue->lookupMember(nameAsString, context);
if (!dotValue) if (!dotValue)
continue; continue;
@@ -542,7 +552,10 @@ QVector<PropertyInfo> getObjectTypes(const ObjectValue *objectValue, const Conte
dotValue = context->lookupReference(ref); dotValue = context->lookupReference(ref);
if (const ObjectValue *dotObjectValue = dotValue->asObjectValue()) { if (const ObjectValue *dotObjectValue = dotValue->asObjectValue()) {
const QVector<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue, context, false, rec + 1); const QVector<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue,
context,
false,
rec + 1);
for (const PropertyInfo &propertyInfo : dotProperties) { for (const PropertyInfo &propertyInfo : dotProperties) {
const PropertyName dotName = name + '.' + propertyInfo.first; const PropertyName dotName = name + '.' + propertyInfo.first;
const TypeName type = propertyInfo.second; const TypeName type = propertyInfo.second;
@@ -2535,6 +2548,13 @@ bool NodeMetaInfo::isColor() const
} }
} }
bool NodeMetaInfo::isEffectMaker() const
{
// We use arbitrary type name because at this time we don't have effect maker
// specific type
return typeName() == QString::fromUtf8(Storage::Info::EffectMaker);
}
bool NodeMetaInfo::isBool() const bool NodeMetaInfo::isBool() const
{ {
if constexpr (useProjectStorage()) { if constexpr (useProjectStorage()) {
@@ -2724,17 +2744,6 @@ bool NodeMetaInfo::isQtQuick3DView3D() const
} }
} }
bool NodeMetaInfo::isQtQuick3DParticles3DModel() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
return isBasedOnCommonType<QtQuick3D_Particles3D, Storage::Info::Model>(m_projectStorage,
m_typeId);
} else {
return isValid() && isSubclassOf("QtQuick3D.Particles3D.Model");
}
}
bool NodeMetaInfo::isQtQuick3DPrincipledMaterial() const bool NodeMetaInfo::isQtQuick3DPrincipledMaterial() const
{ {
if constexpr (useProjectStorage()) { if constexpr (useProjectStorage()) {

View File

@@ -1392,8 +1392,7 @@ ModelNode ModelNode::lowestCommonAncestor(const QList<ModelNode> &nodes)
ModelNode accumulatedNode = nodes.first(); ModelNode accumulatedNode = nodes.first();
int accumulatedNodeDepth = -1; int accumulatedNodeDepth = -1;
Utils::span<const ModelNode> nodesExceptFirst(nodes.constBegin() + 1, nodes.constEnd()); for (const ModelNode &node : Utils::span<const ModelNode>(nodes).subspan(1)) {
for (const ModelNode &node : nodesExceptFirst) {
accumulatedNode = QmlDesigner::lowestCommonAncestor(accumulatedNode, accumulatedNode = QmlDesigner::lowestCommonAncestor(accumulatedNode,
node, node,
accumulatedNodeDepth, accumulatedNodeDepth,

View File

@@ -280,7 +280,8 @@ bool isListElementType(const QmlDesigner::TypeName &type)
bool isComponentType(const QmlDesigner::TypeName &type) bool isComponentType(const QmlDesigner::TypeName &type)
{ {
return type == "Component" || type == "Qt.Component" || type == "QtQuick.Component" return type == "Component" || type == "Qt.Component" || type == "QtQuick.Component"
|| type == "QtQml.Component" || type == "<cpp>.QQmlComponent" || type == "QQmlComponent"; || type == "QtQml.Component" || type == "<cpp>.QQmlComponent" || type == "QQmlComponent"
|| type == "QML.Component";
} }
bool isCustomParserType(const QmlDesigner::TypeName &type) bool isCustomParserType(const QmlDesigner::TypeName &type)

View File

@@ -35,6 +35,7 @@ inline constexpr char DefaultMaterial[] = "DefaultMaterial";
inline constexpr char Dialog[] = "Dialog"; inline constexpr char Dialog[] = "Dialog";
inline constexpr char DoubleType[] = "double"; inline constexpr char DoubleType[] = "double";
inline constexpr char Effect[] = "Effect"; inline constexpr char Effect[] = "Effect";
inline constexpr char EffectMaker[] = "EffectMaker";
inline constexpr char FloatType[] = "float"; inline constexpr char FloatType[] = "float";
inline constexpr char FlowActionArea[] = "FlowActionArea"; inline constexpr char FlowActionArea[] = "FlowActionArea";
inline constexpr char FlowDecision[] = "FlowDecision"; inline constexpr char FlowDecision[] = "FlowDecision";

View File

@@ -40,6 +40,7 @@ QmlPreviewWidgetPlugin::QmlPreviewWidgetPlugin()
designerActionManager.addDesignerAction(new ActionGroup( designerActionManager.addDesignerAction(new ActionGroup(
QString(), QString(),
ComponentCoreConstants::qmlPreviewCategory, ComponentCoreConstants::qmlPreviewCategory,
{},
ComponentCoreConstants::Priorities::QmlPreviewCategory, ComponentCoreConstants::Priorities::QmlPreviewCategory,
&SelectionContextFunctors::always)); &SelectionContextFunctors::always));
s_previewPlugin = getPreviewPlugin(); s_previewPlugin = getPreviewPlugin();

View File

@@ -535,7 +535,7 @@ MetaInfo {
} }
Type { Type {
name: "QtQml.Component" name: "QML.Component"
icon: ":/qtquickplugin/images/component-icon16.png" icon: ":/qtquickplugin/images/component-icon16.png"
Hints { Hints {
@@ -547,7 +547,7 @@ MetaInfo {
name: "Component" name: "Component"
category: "e.Qt Quick - Component" category: "e.Qt Quick - Component"
libraryIcon: ":/qtquickplugin/images/component-icon.png" libraryIcon: ":/qtquickplugin/images/component-icon.png"
version: "2.0" version: "1.0"
QmlSource { source: ":/qtquickplugin/source/component.qml" } QmlSource { source: ":/qtquickplugin/source/component.qml" }
toolTip: qsTr("Allows you to define components inline, within a QML document.") toolTip: qsTr("Allows you to define components inline, within a QML document.")
@@ -555,7 +555,7 @@ MetaInfo {
} }
Type { Type {
name: "QtQml.Component" name: "QML.Component"
icon: ":/qtquickplugin/images/component-icon16.png" icon: ":/qtquickplugin/images/component-icon16.png"
Hints { Hints {
@@ -567,7 +567,7 @@ MetaInfo {
name: "Component 3D" name: "Component 3D"
category: "Qt Quick 3D Component" category: "Qt Quick 3D Component"
libraryIcon: ":/qtquickplugin/images/component-icon.png" libraryIcon: ":/qtquickplugin/images/component-icon.png"
version: "2.0" version: "1.0"
requiredImport: "QtQuick3D" requiredImport: "QtQuick3D"
QmlSource { source: ":/qtquickplugin/source/component3d.qml" } QmlSource { source: ":/qtquickplugin/source/component3d.qml" }

View File

@@ -154,6 +154,11 @@ bool Asset::isTexture3D() const
return type() == Asset::Type::Texture3D; return type() == Asset::Type::Texture3D;
} }
bool Asset::isHdrFile() const
{
return m_suffix == "*.hdr";
}
bool Asset::isEffect() const bool Asset::isEffect() const
{ {
return type() == Asset::Type::Effect; return type() == Asset::Type::Effect;

View File

@@ -8,7 +8,7 @@ namespace QmlDesigner {
class Asset class Asset
{ {
public: public:
enum Type { Unknown, Image, FragmentShader, Font, Audio, Video, Texture3D, Effect, Shader }; enum Type { Unknown, Image, MissingImage, FragmentShader, Font, Audio, Video, Texture3D, Effect, Shader };
Asset(const QString &filePath); Asset(const QString &filePath);
@@ -34,6 +34,7 @@ public:
bool isAudio() const; bool isAudio() const;
bool isVideo() const; bool isVideo() const;
bool isTexture3D() const; bool isTexture3D() const;
bool isHdrFile() const;
bool isEffect() const; bool isEffect() const;
bool isSupported() const; bool isSupported() const;

View File

@@ -223,8 +223,9 @@ static void showUpdateInfo(const QList<Update> &updates,
auto label = new QLabel; auto label = new QLabel;
label->setText("<qt><p>" + UpdateInfoPlugin::tr("Available updates:") + "<ul><li>" label->setText("<qt><p>" + UpdateInfoPlugin::tr("Available updates:") + "<ul><li>"
+ qtText + updateText + "</li></ul></p></qt>"); + qtText + updateText + "</li></ul></p></qt>");
label->setContentsMargins(0, 0, 0, 8); label->setContentsMargins(2, 2, 2, 2);
auto scrollArea = new QScrollArea; auto scrollArea = new QScrollArea;
scrollArea->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
scrollArea->setWidget(label); scrollArea->setWidget(label);
scrollArea->setFrameShape(QFrame::NoFrame); scrollArea->setFrameShape(QFrame::NoFrame);
scrollArea->viewport()->setAutoFillBackground(false); scrollArea->viewport()->setAutoFillBackground(false);

View File

@@ -567,6 +567,15 @@ void ObjectNodeInstance::doResetProperty(const PropertyName &propertyName)
QmlPrivateGate::doResetProperty(object(), context(), propertyName); QmlPrivateGate::doResetProperty(object(), context(), propertyName);
} }
static bool isPropertyBlackListed(const PropertyName &propertyName)
{
if (propertyName.contains(".") && propertyName.contains("__"))
return true;
if (propertyName.count(".") > 2)
return true;
return false;
}
QVariant ObjectNodeInstance::property(const PropertyName &name) const QVariant ObjectNodeInstance::property(const PropertyName &name) const
{ {
if (ignoredProperties().contains(name)) if (ignoredProperties().contains(name))
@@ -574,7 +583,7 @@ QVariant ObjectNodeInstance::property(const PropertyName &name) const
// TODO: handle model nodes // TODO: handle model nodes
if (QmlPrivateGate::isPropertyBlackListed(name)) if (isPropertyBlackListed(name))
return QVariant(); return QVariant();
QQmlProperty property(object(), QString::fromUtf8(name), context()); QQmlProperty property(object(), QString::fromUtf8(name), context());
@@ -612,6 +621,37 @@ void ObjectNodeInstance::ensureVector3DDotProperties(PropertyNameList &list) con
} }
} }
void ObjectNodeInstance::ensureValueTypeProperties(PropertyNameList &list) const
{
const PropertyNameList pointDotProperties = {"x", "y"};
const PropertyNameList sizeDotProperties = {"width", "height"};
const PropertyNameList rectDotProperties = {"x", "y", "width", "height"};
PropertyNameList valueTypeProperties;
for (const auto &property : list) {
const QString name = instanceType(property);
PropertyNameList dotProperties;
if (name == "QPoint" || name == "QPointF")
dotProperties = pointDotProperties;
if (name == "QSize" || name == "QSizeF")
dotProperties = sizeDotProperties;
if (name == "QRect" || name == "QRectF")
dotProperties = rectDotProperties;
for (const auto &dotProperty : dotProperties)
valueTypeProperties.append(property + "." + dotProperty);
}
for (const auto &valueTypeProperty : valueTypeProperties) {
if (!list.contains(valueTypeProperty))
list.append(valueTypeProperty);
}
}
PropertyNameList ObjectNodeInstance::propertyNames() const PropertyNameList ObjectNodeInstance::propertyNames() const
{ {
PropertyNameList list; PropertyNameList list;
@@ -619,13 +659,14 @@ PropertyNameList ObjectNodeInstance::propertyNames() const
list = QmlPrivateGate::allPropertyNames(object()); list = QmlPrivateGate::allPropertyNames(object());
ensureVector3DDotProperties(list); ensureVector3DDotProperties(list);
ensureValueTypeProperties(list);
return list; return list;
} }
QString ObjectNodeInstance::instanceType(const PropertyName &name) const QString ObjectNodeInstance::instanceType(const PropertyName &name) const
{ {
if (QmlPrivateGate::isPropertyBlackListed(name)) if (isPropertyBlackListed(name))
return QLatin1String("undefined"); return QLatin1String("undefined");
QQmlProperty property(object(), QString::fromUtf8(name), context()); QQmlProperty property(object(), QString::fromUtf8(name), context());

View File

@@ -199,6 +199,7 @@ protected:
void initializePropertyWatcher(const ObjectNodeInstance::Pointer &objectNodeInstance); void initializePropertyWatcher(const ObjectNodeInstance::Pointer &objectNodeInstance);
void ensureVector3DDotProperties(PropertyNameList &list) const; void ensureVector3DDotProperties(PropertyNameList &list) const;
void ensureValueTypeProperties(PropertyNameList &list) const;
private: private:
QString m_id; QString m_id;

View File

@@ -345,7 +345,7 @@ void Qt5InformationNodeInstanceServer::updateRotationBlocks(
if (helper) { if (helper) {
QSet<QQuick3DNode *> blockedNodes; QSet<QQuick3DNode *> blockedNodes;
QSet<QQuick3DNode *> unblockedNodes; QSet<QQuick3DNode *> unblockedNodes;
const PropertyName rotBlocked = "rotBlocked"; const PropertyName rotBlocked = "rotBlock";
for (const auto &container : valueChanges) { for (const auto &container : valueChanges) {
if (container.name() == rotBlocked if (container.name() == rotBlocked
&& container.auxiliaryDataType() == AuxiliaryDataType::NodeInstanceAuxiliary) { && container.auxiliaryDataType() == AuxiliaryDataType::NodeInstanceAuxiliary) {

View File

@@ -40,18 +40,22 @@ public:
, m_args({argc, argv}) , m_args({argc, argv})
{ {
m_argParser.setApplicationDescription("QML Runtime Provider for QDS"); m_argParser.setApplicationDescription("QML Runtime Provider for QDS");
m_argParser.addOptions( m_argParser.addOptions({{"qml-puppet", "Run QML Puppet (default)"},
{{"qml-puppet", "Run QML Puppet (default)"},
{"qml-runtime", "Run QML Runtime"}, {"qml-runtime", "Run QML Runtime"},
{"appinfo", "Print build information"}, {"appinfo", "Print build information"},
{"test", "Run test mode"} {"test", "Run test mode"}});
});
} }
int run() int run()
{ {
populateParser(); populateParser();
initCoreApp(); initCoreApp();
if (!m_coreApp) { //default to QGuiApplication
createCoreApp<QGuiApplication>();
qWarning() << "CoreApp is not initialized! Falling back to QGuiApplication!";
}
initParser(); initParser();
initQmlRunner(); initQmlRunner();
return m_coreApp->exec(); return m_coreApp->exec();
@@ -88,11 +92,6 @@ private:
QCommandLineOption optHelp = m_argParser.addHelpOption(); QCommandLineOption optHelp = m_argParser.addHelpOption();
QCommandLineOption optVers = m_argParser.addVersionOption(); QCommandLineOption optVers = m_argParser.addVersionOption();
if (!m_coreApp) {
qCritical() << "Cannot initialize coreapp!";
m_argParser.showHelp();
}
if (!m_argParser.parse(m_coreApp->arguments())) { if (!m_argParser.parse(m_coreApp->arguments())) {
std::cout << "Error: " << m_argParser.errorText().toStdString() << std::endl std::cout << "Error: " << m_argParser.errorText().toStdString() << std::endl
<< std::endl; << std::endl;

View File

@@ -241,7 +241,8 @@ void QmlRuntime::initQmlRunner()
loadConf(confFile, !m_verboseMode); loadConf(confFile, !m_verboseMode);
// Load files // Load files
QScopedPointer<LoadWatcher> lw(new LoadWatcher(m_qmlEngine.data(), files.size(), m_conf.data())); LoadWatcher *lw = new LoadWatcher(m_qmlEngine.data(), files.size(), m_conf.data());
lw->setParent(this);
for (const QString &path : std::as_const(files)) { for (const QString &path : std::as_const(files)) {
QUrl url = QUrl::fromUserInput(path, QDir::currentPath(), QUrl::AssumeLocalFile); QUrl url = QUrl::fromUserInput(path, QDir::currentPath(), QUrl::AssumeLocalFile);

View File

@@ -4,22 +4,46 @@ import QtQuick.Window 2.0
import QtQuick 2.0 import QtQuick 2.0
Window { Window {
id: window
property Item containedObject: null property Item containedObject: null
property bool __resizeGuard: false
readonly property Item firstChild: window.contentItem.children.length > 0 ? window.contentItem.children[0] : null
property bool writeGuard: false
onFirstChildChanged: {
window.writeGuard = true
window.containedObject = window.firstChild
window.writeGuard = false
}
onContainedObjectChanged: { onContainedObjectChanged: {
if (window.writeGuard)
return
if (containedObject == undefined || containedObject == null) { if (containedObject == undefined || containedObject == null) {
visible = false visible = false
return return
} }
__resizeGuard = true
width = containedObject.width window.width = containedObject.width
height = containedObject.height window.height = containedObject.height
containedObject.parent = contentItem containedObject.parent = contentItem
visible = true window.visible = true
__resizeGuard = false }
Binding {
target: window.firstChild
when: window.firstChild
property: "height"
value: window.height
}
Binding {
target: window.firstChild
when: window.firstChild
property: "width"
value: window.width
} }
onWidthChanged: if (!__resizeGuard && containedObject)
containedObject.width = width
onHeightChanged: if (!__resizeGuard && containedObject)
containedObject.height = height
} }