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

Change-Id: I09a0e8514c8ad7badaa7af6d101c71d5c96b5465
This commit is contained in:
Tim Jenssen
2024-01-31 20:25:34 +01:00
208 changed files with 1726 additions and 2189 deletions

View File

@@ -17,33 +17,35 @@
To preview the currently active QML file on the desktop:
\list
\li Select \uicontrol Build > \uicontrol {QML Preview}.
\li Select the \inlineimage icons/live_preview.png
(\uicontrol {Show Live Preview}) button.
\li Select the \uicontrol {Live Preview} button on the top toolbar.
\li Press \key {Alt+P}.
\endlist
\image studio-live-preview.png
\image studio-live-preview.webp
\endif
To preview any QML file that belongs to the project, right-click the
To preview any QML file that belongs to the project,
\list
\li Select the \uicontrol {Live Preview} button on the top toolbar.
\li Right-click the
filename in the \l Projects view, and select \uicontrol {Preview File}.
\endlist
\if defined(qtdesignstudio)
To preview the whole UI, select \uicontrol {Show Live Preview}
To preview the whole UI, select \uicontrol {Live Preview}
when viewing the main QML file of the project.
To view the UI in different sizes, select the zooming level on the toolbar.
The frames-per-second (FPS) refresh rate of animations is displayed in the
\uicontrol FPS field.
\section1 Selecting the Preview Tool
By default, the QML runtime is used for previewing. To use some
other tool, specify it in the \uicontrol {QML viewer} field in the run
settings of the project in the Projects mode.
\note Click \inlineimage icons/settings.png
to access the setting options.
\image studio-run-settings.png "Run settings"
\endif
*/

View File

@@ -32,7 +32,7 @@
\if defined(qtcreator)
\image qtcreator-live-preview.png
\else
\image studio-live-preview.png
\image studio-live-preview.webp
\endif
\list

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -82,9 +82,9 @@
\li \b X
\li \b -
\li \b -
\li The feature is fully supported as such, but there are some
limitations such as StateGroup and the ones listed in
\l {\QMCU Known Issues or Limitations}.
\li The feature is fully supported, but there are some limitations listed
in \l {\QMCU Known Issues or Limitations}.
In addition, StateGroup is disabled.
\row
\li \l {Transitions}
\li \b X
@@ -98,7 +98,6 @@
\li \b -
\li The \uicontrol Translations view previews with regular Qt Quick instead
of \QUL, and it can be inaccurate in calculating the text overflow in some translations.
Also, the developer needs to configure the \QUL project to use \QDS translations (.ts) files.
\row
\li \l {Timeline}
\li \b X

View File

@@ -30,7 +30,7 @@
\section1 Importing Designs From Other Design Tools
\image studio-imported-assets.png "UI imported into Qt Design Studio"
\image studio-imported-assets.webp "UI imported into Qt Design Studio"
\QB enables you to export assets and then import them to a \QDS project
as images and QML files for editing in the \l {2D} view. If you make changes

View File

@@ -12,7 +12,7 @@
You specify an image to use as the source file for the \uicontrol Texture,
and also define how it is mapped to meshes in a 3D scene.
\image studio-qtquick-3d-texture.png "Texture attached to a material in Design mode"
\image studio-qtquick-3d-texture.webp {Texture attached to a material in Design mode}
\section1 Selecting the Mapping Method
@@ -53,7 +53,7 @@
\section1 UV Scaling
The \uicontrol {U scale} and \uicontrol {V scale} properties define how
The \uicontrol {U} and \uicontrol {V} scale properties define how
to scale the U and V texture coordinates when mapping to a mesh's UV
coordinates.
@@ -77,8 +77,8 @@
the component in the \uicontrol {U position} field. To offset the mapping
from bottom to top, set it in the \uicontrol {V position} field.
Specify the U and V pivot point in the \uicontrol {U pivot} and
\uicontrol {V pivot} fields.
Specify the U and V pivot points in the \uicontrol {U} and
\uicontrol {V} pivot fields.
To rotate the texture around the pivot point, specify rotation as degrees
in the \uicontrol {UV rotation} field. A positive value indicates clockwise
@@ -89,28 +89,31 @@
\section1 Applying Textures to Materials
Drag-and-drop an image from \l Assets on a material to
create a texture component. Dragging an image to a default or principled
material opens a \uicontrol {Select Texture Property} dialog. You can select
the property to attach the texture to in the \uicontrol {Set texture to property}
field. For a custom material, you must assign the texture to a map. If the
\uicontrol Texture component is not displayed in \uicontrol {Components},
you should add the \uicontrol {Qt Quick 3D} module to your project, as
described in \l {Adding and Removing Modules}.
To create and apply a texture on the material from an image:
\list 1
\li Drag an image from \l Assets to a material
in \uicontrol {Material Browser}.
\li Select a property from the list of properties.
\li Select \uicontrol Apply.
\endlist
To use Texture components to apply textures to materials, drag-and-drop a
Texture component from \uicontrol Components >
\uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D} to a material component
in \l Navigator. The new texture should now be visible in the \l {2D}
and \l {3D} views. \note If the colors in your texture are not visualized
correctly, you should check the color in the \uicontrol Diffuse property of
the material and try changing it to white (#ffffff).
Alternatively, you can add textures to materials as instructed
in \l {Working with Textures}.
\image studio-qtquick-3d-material-texture.png "Material properties"
\note If the colors in your texture are not visualized
correctly, try setting the \uicontrol {Base Color}
in \uicontrol {Material Editor} to \e {white (#ffffff)}.
To change the source file for the texture, select the \uicontrol Texture
component in \uicontrol Navigator, go to the \l Properties view, and specify
a new image to use in the \uicontrol Source field.
\image studio-qtquick-3d-material-texture.webp {Material Editor}
\image studio-qtquick-3d-texture-properties.png "Texture properties"
To change the source file for the texture:
\list 1
\li Double-click the texture in \uicontrol {Material Browser}.
\li In \uicontrol {Texture Editor}, select \inlineimage icons/add-file-16px.png
next to \uicontrol {Source}.
\li Select the new texture.
\li Select \uicontrol Open.
\endlist
\image studio-qtquick-3d-texture-properties.webp {Texture Editor}
*/

View File

@@ -201,7 +201,7 @@ TreeViewDelegate {
mouseArea.allowTooltip = false
AssetsLibraryBackend.tooltipBackend.hideTooltip()
if (mouse.button === Qt.LeftButton && root.isEffect)
AssetsLibraryBackend.rootView.openEffectMaker(filePath)
AssetsLibraryBackend.rootView.openEffectComposer(filePath)
}
ToolTip {

View File

@@ -74,16 +74,16 @@ Item {
}
Component {
id: numberEditor
id: realEditor
EditorPopup {
editor: numberField
editor: realField
StudioControls.RealSpinBox {
id: numberField
id: realField
property alias editValue: numberField.realValue
property alias editValue: realField.realValue
actionIndicator.visible: false
realFrom: -9e9
@@ -95,6 +95,27 @@ Item {
}
}
Component {
id: integerEditor
EditorPopup {
editor: integerField
StudioControls.SpinBox {
id: integerField
property alias editValue: integerField.value
actionIndicatorVisible: false
spinBoxIndicatorVisible: true
from: -2147483647
to: 2147483647
decimals: 0
}
}
}
Component {
id: boolEditor
@@ -150,7 +171,8 @@ Item {
name: "default"
when: columnType !== CollectionDetails.DataType.Boolean
&& columnType !== CollectionDetails.DataType.Color
&& columnType !== CollectionDetails.DataType.Number
&& columnType !== CollectionDetails.DataType.Integer
&& columnType !== CollectionDetails.DataType.Real
PropertyChanges {
target: editorLoader
@@ -158,12 +180,21 @@ Item {
}
},
State {
name: "number"
when: columnType === CollectionDetails.DataType.Number
name: "integer"
when: columnType === CollectionDetails.DataType.Integer
PropertyChanges {
target: editorLoader
sourceComponent: numberEditor
sourceComponent: integerEditor
}
},
State {
name: "real"
when: columnType === CollectionDetails.DataType.Real
PropertyChanges {
target: editorLoader
sourceComponent: realEditor
}
},
State {

View File

@@ -10,15 +10,15 @@ import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
import CollectionEditorBackend
Item {
Rectangle {
id: root
property real iconHeight: 2 * StudioTheme.Values.bigFont
required property var model
required property var backend
property int selectedRow: -1
implicitHeight: container.height
implicitHeight: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground
function addNewColumn() {
addColumnDialog.popUp(root.model.columnCount())
@@ -30,32 +30,36 @@ Item {
RowLayout {
id: container
width: parent.width
anchors.fill: parent
anchors.topMargin: StudioTheme.Values.toolbarVerticalMargin
anchors.bottomMargin: StudioTheme.Values.toolbarVerticalMargin
spacing: StudioTheme.Values.sectionRowSpacing
RowLayout {
id: leftSideToolbar
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.leftMargin: StudioTheme.Values.toolbarHorizontalMargin
spacing: StudioTheme.Values.sectionRowSpacing
IconButton {
icon: StudioTheme.Constants.addcolumnleft_medium
tooltip: qsTr("Add property left %1").arg(leftSideToolbar.topPadding)
buttonIcon: StudioTheme.Constants.addcolumnleft_medium
tooltip: qsTr("Add property left")
enabled: root.model.selectedColumn > -1
onClicked: addColumnDialog.popUp(root.model.selectedColumn - 1)
onClicked: addColumnDialog.popUp(root.model.selectedColumn)
}
IconButton {
icon: StudioTheme.Constants.addcolumnright_medium
buttonIcon: StudioTheme.Constants.addcolumnright_medium
tooltip: qsTr("Add property right")
enabled: root.model.selectedColumn > -1
onClicked: addColumnDialog.popUp(root.model.selectedColumn + 1)
}
IconButton {
icon: StudioTheme.Constants.deletecolumn_medium
buttonIcon: StudioTheme.Constants.deletecolumn_medium
tooltip: qsTr("Delete selected property")
enabled: root.model.selectedColumn > -1
onClicked: root.model.removeColumn(root.model.selectedColumn)
@@ -67,46 +71,43 @@ Item {
}
IconButton {
icon: StudioTheme.Constants.addrowbelow_medium
buttonIcon: StudioTheme.Constants.addrowbelow_medium
tooltip: qsTr("Insert row below")
enabled: root.model.selectedRow > -1
onClicked: root.model.insertRow(root.model.selectedRow + 1)
}
IconButton {
icon: StudioTheme.Constants.addrowabove_medium
buttonIcon: StudioTheme.Constants.addrowabove_medium
tooltip: qsTr("Insert row above")
enabled: root.model.selectedRow > -1
onClicked: root.model.insertRow(root.model.selectedRow)
}
IconButton {
icon: StudioTheme.Constants.deleterow_medium
buttonIcon: StudioTheme.Constants.deleterow_medium
tooltip: qsTr("Delete selected row")
enabled: root.model.selectedRow > -1
onClicked: root.model.removeRow(root.model.selectedRow)
}
}
Item { // spacer
Layout.minimumHeight: 1
Layout.fillWidth: true
}
RowLayout {
id: rightSideToolbar
spacing: StudioTheme.Values.sectionRowSpacing
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: StudioTheme.Values.toolbarHorizontalMargin
IconButton {
icon: StudioTheme.Constants.save_medium
buttonIcon: StudioTheme.Constants.save_medium
tooltip: qsTr("Save changes")
enabled: root.model.collectionName !== ""
onClicked: root.model.saveDataStoreCollections()
}
IconButton {
icon: StudioTheme.Constants.export_medium
buttonIcon: StudioTheme.Constants.export_medium
tooltip: qsTr("Export model")
enabled: root.model.collectionName !== ""
onClicked: fileDialog.open()
@@ -131,11 +132,8 @@ Item {
}
}
component IconButton: HelperWidgets.IconButton {
Layout.preferredHeight: root.iconHeight
Layout.preferredWidth: root.iconHeight
radius: StudioTheme.Values.smallRadius
iconSize: StudioTheme.Values.bigFont
component IconButton: HelperWidgets.AbstractButton {
style: StudioTheme.Values.viewBarButtonStyle
}
component Spacer: Item {
@@ -160,6 +158,7 @@ Item {
{
addColumnDialog.clickedIndex = index
columnName.text = ""
columnName.forceActiveFocus()
addedPropertyType.currentIndex = addedPropertyType.find("String")
addColumnDialog.open()

View File

@@ -20,62 +20,34 @@ Rectangle {
implicitHeight: 400
color: StudioTheme.Values.themeControlBackground
ColumnLayout {
Column {
id: topRow
visible: collectionNameText.text !== ""
spacing: 0
anchors {
fill: parent
topMargin: 10
leftMargin: 15
rightMargin: 15
bottomMargin: 10
}
Text {
id: collectionNameText
leftPadding: 8
rightPadding: 8
topPadding: 3
bottomPadding: 3
color: StudioTheme.Values.themeTextColor
text: root.model.collectionName
font.pixelSize: StudioTheme.Values.baseFontSize
elide: Text.ElideRight
}
Item { // spacer
implicitWidth: 1
implicitHeight: 10
}
visible: root.model.collectionName !== ""
width: parent.width
spacing: 10
CollectionDetailsToolbar {
id: toolbar
model: root.model
backend: root.backend
Layout.fillWidth: true
Layout.minimumWidth: implicitWidth
}
Item { // spacer
implicitWidth: 1
implicitHeight: 5
width: parent.width
}
GridLayout {
columns: 3
rowSpacing: 1
columnSpacing: 1
width: parent.width
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumWidth: parent.width
anchors {
left: parent.left
leftMargin: StudioTheme.Values.collectionTableHorizontalMargin
}
Rectangle {
id: tableTopLeftCorner
clip: true
visible: !tableView.model.isEmpty
color: StudioTheme.Values.themeControlBackgroundInteraction
@@ -128,6 +100,8 @@ Rectangle {
headerMenu.clickedHeaderIndex = index
headerMenu.dialogPos = parent.mapToGlobal(posX, parent.height)
headerMenu.popup()
} else {
headerMenu.close()
}
}
}
@@ -188,6 +162,7 @@ Rectangle {
Layout.preferredHeight: tableView.height
Layout.rowSpan: 2
Layout.alignment: Qt.AlignTop + Qt.AlignLeft
width: implicitWidth // suppresses GridLayout warnings when resizing
delegate: HeaderDelegate {
selectedItem: tableView.model.selectedRow
@@ -208,11 +183,33 @@ Rectangle {
model: root.sortedModel
clip: true
property point tableStart: tableTopLeftCorner.mapToItem(root, Qt.point(x, y));
Layout.alignment: Qt.AlignTop + Qt.AlignLeft
Layout.preferredWidth: tableView.contentWidth
Layout.preferredHeight: tableView.contentHeight
Layout.minimumWidth: 100
Layout.minimumHeight: 20
Layout.maximumWidth: root.width
Layout.maximumWidth: root.width - (tableStart.x + addColumnContainer.width)
Layout.maximumHeight: root.height - (tableStart.y + addRowContainer.height)
columnWidthProvider: function(column) {
if (!isColumnLoaded(column))
return -1
let w = explicitColumnWidth(column)
if (w < 0)
w = implicitColumnWidth(column)
return Math.max(w, StudioTheme.Values.collectionCellMinimumWidth)
}
rowHeightProvider: function(row) {
if (!isRowLoaded(row))
return -1
let h = explicitRowHeight(row)
if (h < 0)
h = implicitRowHeight(row)
return Math.max(h, StudioTheme.Values.collectionCellMinimumHeight)
}
delegate: Rectangle {
id: itemCell
@@ -261,7 +258,7 @@ Rectangle {
id: cellText
Text {
text: display
text: display ?? ""
color: itemSelected ? StudioTheme.Values.themeInteraction
: StudioTheme.Values.themePlaceholderTextColorInteraction
leftPadding: 5
@@ -361,6 +358,26 @@ Rectangle {
}
}
}
HoverHandler { id: hoverHandler }
ScrollBar.horizontal: StudioControls.TransientScrollBar {
id: horizontalScrollBar
style: StudioTheme.Values.viewStyle
orientation: Qt.Horizontal
show: (hoverHandler.hovered || tableView.focus || horizontalScrollBar.inUse)
&& horizontalScrollBar.isNeeded
}
ScrollBar.vertical: StudioControls.TransientScrollBar {
id: verticalScrollBar
style: StudioTheme.Values.viewStyle
orientation: Qt.Vertical
show: (hoverHandler.hovered || tableView.focus || verticalScrollBar.inUse)
&& verticalScrollBar.isNeeded
}
}
HelperWidgets.IconButton {
@@ -439,7 +456,6 @@ Rectangle {
color: StudioTheme.Values.themeTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
elide: Text.ElideRight
}
@@ -481,7 +497,7 @@ Rectangle {
Connections {
target: root.parent
onIsHorizontalChanged: editPropertyDialog.close()
function onIsHorizontalChanged() { editPropertyDialog.close() }
}
StudioControls.Dialog {

View File

@@ -49,6 +49,9 @@ Item {
id: grid
readonly property bool isHorizontal: width >= 500
columnSpacing: 0
rowSpacing: 0
anchors.fill: parent
columns: isHorizontal ? 3 : 1
@@ -62,6 +65,7 @@ Item {
Rectangle {
color: StudioTheme.Values.themeToolbarBackground
Layout.preferredHeight: StudioTheme.Values.toolbarHeight
Layout.fillWidth: true

View File

@@ -28,6 +28,7 @@ StudioControls.Dialog {
nameTextField.forceActiveFocus()
typeComboBox.initialType = root.model.propertyType(root.__propertyIndex)
typeComboBox.currentIndex = typeComboBox.find(typeComboBox.initialType)
let newPoint = mapFromGlobal(initialPosition.x, initialPosition.y)
x = newPoint.x
@@ -92,8 +93,6 @@ StudioControls.Dialog {
model: root.model.typesList()
actionIndicatorVisible: false
onInitialTypeChanged: typeComboBox.currentIndex = typeComboBox.find(initialType)
}
}

View File

@@ -0,0 +1,288 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Templates as T
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectComposerBackend
ColumnLayout {
id: root
spacing: 1
readonly property var backendModel: EffectComposerBackend.effectComposerModel
property var draggedSec: null
property var secsY: []
property int moveFromIdx: 0
property int moveToIdx: 0
property bool previewAnimationRunning: false
// Invoked after save changes is done
property var onSaveChangesCallback: () => {}
// Invoked from C++ side when open composition is requested and there are unsaved changes
function promptToSaveBeforeOpen() {
root.onSaveChangesCallback = () => { EffectComposerBackend.rootView.doOpenComposition() }
saveChangesDialog.open()
}
Connections {
target: root.backendModel
function onIsEmptyChanged() {
if (root.backendModel.isEmpty)
saveAsDialog.close()
}
}
SaveAsDialog {
id: saveAsDialog
anchors.centerIn: parent
}
SaveChangesDialog {
id: saveChangesDialog
anchors.centerIn: parent
onSave: {
if (root.backendModel.currentComposition === "") {
// if current composition is unsaved, show save as dialog and clear afterwards
saveAsDialog.clearOnClose = true
saveAsDialog.open()
} else {
root.onSaveChangesCallback()
}
}
onDiscard: {
root.onSaveChangesCallback()
}
}
EffectComposerTopBar {
Layout.fillWidth: true
onAddClicked: {
root.onSaveChangesCallback = () => { root.backendModel.clear(true) }
if (root.backendModel.hasUnsavedChanges)
saveChangesDialog.open()
else
root.backendModel.clear(true)
}
onSaveClicked: {
let name = root.backendModel.currentComposition
if (name === "")
saveAsDialog.open()
else
root.backendModel.saveComposition(name)
}
onSaveAsClicked: saveAsDialog.open()
onAssignToSelectedClicked: {
root.backendModel.assignToSelected()
}
}
SplitView {
id: splitView
Layout.fillWidth: true
Layout.fillHeight: true
orientation: root.width > root.height ? Qt.Horizontal : Qt.Vertical
handle: Rectangle {
implicitWidth: splitView.orientation === Qt.Horizontal ? 6 : splitView.width
implicitHeight: splitView.orientation === Qt.Horizontal ? splitView.height : 6
color: T.SplitHandle.pressed ? StudioTheme.Values.themeSliderHandleInteraction
: (T.SplitHandle.hovered ? StudioTheme.Values.themeSliderHandleHover
: "transparent")
}
EffectComposerPreview {
mainRoot: root
SplitView.minimumWidth: 250
SplitView.minimumHeight: 200
SplitView.preferredWidth: 300
SplitView.preferredHeight: 300
Layout.fillWidth: true
Layout.fillHeight: true
FrameAnimation {
id: previewFrameTimer
running: true
paused: !previewAnimationRunning
}
}
Column {
spacing: 1
SplitView.minimumWidth: 250
SplitView.minimumHeight: 100
Component.onCompleted: HelperWidgets.Controller.mainScrollView = scrollView
Rectangle {
width: parent.width
height: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground
EffectNodesComboBox {
mainRoot: root
anchors.verticalCenter: parent.verticalCenter
x: 5
width: parent.width - 50
}
HelperWidgets.AbstractButton {
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.clearList_medium
tooltip: qsTr("Remove all effect nodes.")
enabled: !root.backendModel.isEmpty
onClicked: root.backendModel.clear()
}
HelperWidgets.AbstractButton {
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.code
tooltip: qsTr("Open Shader in Code Editor.")
visible: false // TODO: to be implemented
onClicked: {} // TODO
}
}
Item {
width: parent.width
height: parent.height - y
HelperWidgets.ScrollView {
id: scrollView
anchors.fill: parent
clip: true
interactive: !HelperWidgets.Controller.contextMenuOpened
onContentHeightChanged: {
if (scrollView.contentItem.height > scrollView.height) {
let lastItemH = repeater.itemAt(repeater.count - 1).height
scrollView.contentY = scrollView.contentItem.height - lastItemH
}
}
Column {
id: nodesCol
width: scrollView.width
spacing: 1
Repeater {
id: repeater
width: parent.width
model: root.backendModel
onCountChanged: {
HelperWidgets.Controller.setCount("EffectComposer", repeater.count)
}
delegate: EffectCompositionNode {
width: parent.width
modelIndex: index
Behavior on y {
PropertyAnimation {
duration: 300
easing.type: Easing.InOutQuad
}
}
onStartDrag: (section) => {
root.draggedSec = section
root.moveFromIdx = index
highlightBorder = true
root.secsY = []
for (let i = 0; i < repeater.count; ++i)
root.secsY[i] = repeater.itemAt(i).y
}
onStopDrag: {
if (root.moveFromIdx === root.moveToIdx)
root.draggedSec.y = root.secsY[root.moveFromIdx]
else
root.backendModel.moveNode(root.moveFromIdx, root.moveToIdx)
highlightBorder = false
root.draggedSec = null
}
}
} // Repeater
Timer {
running: root.draggedSec
interval: 50
repeat: true
onTriggered: {
root.moveToIdx = root.moveFromIdx
for (let i = 0; i < repeater.count; ++i) {
let currItem = repeater.itemAt(i)
if (i > root.moveFromIdx) {
if (root.draggedSec.y > currItem.y + (currItem.height - root.draggedSec.height) * .5) {
currItem.y = root.secsY[i] - root.draggedSec.height - nodesCol.spacing
root.moveToIdx = i
} else {
currItem.y = root.secsY[i]
}
} else if (i < root.moveFromIdx) {
if (!repeater.model.isDependencyNode(i)
&& root.draggedSec.y < currItem.y + (currItem.height - root.draggedSec.height) * .5) {
currItem.y = root.secsY[i] + root.draggedSec.height + nodesCol.spacing
root.moveToIdx = Math.min(root.moveToIdx, i)
} else {
currItem.y = root.secsY[i]
}
}
}
}
} // Timer
} // Column
} // ScrollView
Text {
text: root.backendModel.isEnabled ? qsTr("Add an effect node to start")
: qsTr("Effect Composer is disabled on MCU projects")
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFontSize
anchors.centerIn: parent
visible: root.backendModel.isEmpty
}
} // Item
} // Column
} // SplitView
}

View File

@@ -5,7 +5,7 @@ import QtQuick
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Column {
id: root
@@ -14,10 +14,8 @@ Column {
property int animatedFrame: previewFrameTimer.currentFrame
property bool timeRunning: previewAnimationRunning
width: parent.width
required property Item mainRoot
property var effectMakerModel: EffectMakerBackend.effectMakerModel
property var effectComposerModel: EffectComposerBackend.effectComposerModel
property alias source: source
// The delay in ms to wait until updating the effect
readonly property int updateDelay: 100
@@ -33,11 +31,11 @@ Column {
oldComponent.destroy();
try {
const newObject = Qt.createQmlObject(
effectMakerModel.qmlComponentString,
effectComposerModel.qmlComponentString,
componentParent,
""
);
effectMakerModel.resetEffectError(0);
effectComposerModel.resetEffectError(0);
} catch (error) {
let errorString = "QML: ERROR: ";
let errorLine = -1;
@@ -47,7 +45,7 @@ Column {
errorString += e.lineNumber + ": " + e.message;
errorLine = e.lineNumber;
}
effectMakerModel.setEffectError(errorString, 0, errorLine);
effectComposerModel.setEffectError(errorString, 0, errorLine);
source.visible = true;
}
}
@@ -166,7 +164,7 @@ Column {
color: colorEditor.color
width: parent.width
height: 200
height: root.height - y
clip: true
Item { // Source item as a canvas (render target) for effect
@@ -212,7 +210,7 @@ Column {
}
Connections {
target: effectMakerModel
target: effectComposerModel
function onShadersBaked() {
console.log("Shaders Baked!")
updateTimer.restart()
@@ -223,7 +221,7 @@ Column {
id: updateTimer
interval: updateDelay
onTriggered: {
effectMakerModel.updateQmlComponent()
effectComposerModel.updateQmlComponent()
createNewComponent()
}
}

View File

@@ -5,15 +5,16 @@ import QtQuick
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Rectangle {
id: root
width: parent.width
height: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground
readonly property var backendModel: EffectComposerBackend.effectComposerModel
signal addClicked
signal saveClicked
signal saveAsClicked
@@ -27,7 +28,7 @@ Rectangle {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.add_medium
tooltip: qsTr("Add new composition")
enabled: root.backendModel.isEnabled
onClicked: root.addClicked()
}
@@ -35,8 +36,8 @@ Rectangle {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.save_medium
tooltip: qsTr("Save current composition")
enabled: EffectMakerBackend.effectMakerModel.hasUnsavedChanges
|| EffectMakerBackend.effectMakerModel.currentComposition === ""
enabled: root.backendModel.isEnabled && (root.backendModel.hasUnsavedChanges
|| root.backendModel.currentComposition === "")
onClicked: root.saveClicked()
}
@@ -45,7 +46,7 @@ Rectangle {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.saveAs_medium
tooltip: qsTr("Save current composition with a new name")
enabled: !EffectMakerBackend.effectMakerModel.isEmpty
enabled: root.backendModel.isEnabled && !root.backendModel.isEmpty
onClicked: root.saveAsClicked()
}
@@ -54,7 +55,7 @@ Rectangle {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.assignTo_medium
tooltip: qsTr("Assign current composition to selected item")
enabled: EffectMakerBackend.effectMakerModel.currentComposition !== ""
enabled: root.backendModel.isEnabled && root.backendModel.currentComposition !== ""
onClicked: root.assignToSelectedClicked()
}
@@ -62,7 +63,7 @@ Rectangle {
Text {
readonly property string compName: EffectMakerBackend.effectMakerModel.currentComposition
readonly property string compName: root.backendModel.currentComposition
text: compName !== "" ? compName : qsTr("Untitled")
anchors.centerIn: parent
@@ -76,11 +77,13 @@ Rectangle {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.help
tooltip: qsTr("How to use Effect Maker:
tooltip: qsTr("How to use Effect Composer:
1. Click \"+ Add Effect\" to add effect node
2. Adjust the effect nodes properties
3. Change the order of the effects, if you like
4. See the preview
5. Save in the library, if you wish to reuse the effect later") // TODO: revise with doc engineer
onClicked: Qt.openUrlExternally("https://doc.qt.io/qtdesignstudio/qt-using-effect-maker-effects.html")
}
}

View File

@@ -6,7 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
HelperWidgets.Section {
id: root
@@ -14,7 +14,7 @@ HelperWidgets.Section {
property int modelIndex: 0
caption: nodeName
category: "EffectMaker"
category: "EffectComposer"
draggable: !isDependency
fillBackground: true
@@ -23,7 +23,7 @@ HelperWidgets.Section {
visible: repeater.count > 0 || !isDependency
onCloseButtonClicked: {
EffectMakerBackend.effectMakerModel.removeNode(root.modelIndex)
EffectComposerBackend.effectComposerModel.removeNode(root.modelIndex)
}
showEyeButton: !isDependency

View File

@@ -7,7 +7,7 @@ import QtQuick.Layouts
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Item {
id: root

View File

@@ -6,7 +6,7 @@ import QtQuick.Controls
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Rectangle {
id: root
@@ -25,7 +25,8 @@ Rectangle {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
tooltip: modelData.canBeAdded ? "" : qsTr("Existing effect has conflicting properties, this effect cannot be added.")
tooltip: modelData.canBeAdded ? modelData.nodeDescription
: qsTr("Existing effect has conflicting properties, this effect cannot be added.")
onClicked: {
if (modelData.canBeAdded)
@@ -35,6 +36,7 @@ Rectangle {
Row {
spacing: 5
anchors.fill: parent
IconImage {
id: nodeIcon
@@ -51,8 +53,11 @@ Rectangle {
text: modelData.nodeName
color: modelData.canBeAdded ? StudioTheme.Values.themeTextColor
: StudioTheme.Values.themeTextColorDisabled
font.pointSize: StudioTheme.Values.smallFontSize
anchors.verticalCenter: nodeIcon.verticalCenter
wrapMode: Text.WordWrap
width: parent.width - parent.spacing - nodeIcon.width
}
}
}

View File

@@ -5,7 +5,7 @@ import QtQuick
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
StudioControls.ComboBox {
id: root
@@ -23,8 +23,8 @@ StudioControls.ComboBox {
readonly property int popupHeight: Math.min(800, row.height + 2)
function calculateWindowGeometry() {
var globalPos = EffectMakerBackend.rootView.globalPos(mainRoot.mapFromItem(root, 0, 0))
var screenRect = EffectMakerBackend.rootView.screenRect();
var globalPos = EffectComposerBackend.rootView.globalPos(mainRoot.mapFromItem(root, 0, 0))
var screenRect = EffectComposerBackend.rootView.screenRect();
window.width = row.width + 2 // 2: scrollView left and right 1px margins
@@ -97,7 +97,7 @@ StudioControls.ComboBox {
spacing: 10
Repeater {
model: EffectMakerBackend.effectMakerNodesModel
model: EffectComposerBackend.effectComposerNodesModel
Column {
spacing: 10
@@ -115,7 +115,7 @@ StudioControls.ComboBox {
EffectNode {
onAddEffectNode: (nodeQenPath) => {
EffectMakerBackend.rootView.addEffectNode(modelData.nodeQenPath)
EffectComposerBackend.rootView.addEffectNode(modelData.nodeQenPath)
root.popup.close()
}
}

View File

@@ -5,7 +5,7 @@ import QtQuick
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
StudioControls.ComboBox {
id: root
@@ -32,8 +32,8 @@ StudioControls.ComboBox {
readonly property int popupHeight: Math.min(800, col.height + 2)
function calculateWindowGeometry() {
var globalPos = EffectMakerBackend.rootView.globalPos(mainRoot.mapFromItem(root, 0, 0))
var screenRect = EffectMakerBackend.rootView.screenRect();
var globalPos = EffectComposerBackend.rootView.globalPos(mainRoot.mapFromItem(root, 0, 0))
var screenRect = EffectComposerBackend.rootView.screenRect();
window.width = col.width + 2 // 2: scrollView left and right 1px margins

View File

@@ -6,7 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
StudioControls.Dialog {
id: root
@@ -18,10 +18,10 @@ StudioControls.Dialog {
implicitWidth: 250
implicitHeight: 160
property bool clearOnClose: false // clear the effect maker after saving
property bool clearOnClose: false // clear the effect composer after saving
onOpened: {
nameText.text = EffectMakerBackend.effectMakerModel.getUniqueEffectName()
nameText.text = EffectComposerBackend.effectComposerModel.getUniqueEffectName()
nameText.selectAll()
nameText.forceActiveFocus()
emptyText.text = ""
@@ -87,10 +87,10 @@ StudioControls.Dialog {
if (!enabled) // needed since this event handler can be triggered from keyboard events
return
EffectMakerBackend.effectMakerModel.saveComposition(nameText.text)
EffectComposerBackend.effectComposerModel.saveComposition(nameText.text)
if (root.clearOnClose) {
EffectMakerBackend.effectMakerModel.clear()
EffectComposerBackend.effectComposerModel.clear()
root.clearOnClose = false
}
@@ -103,7 +103,7 @@ StudioControls.Dialog {
onClicked: {
if (root.clearOnClose) {
EffectMakerBackend.effectMakerModel.clear()
EffectComposerBackend.effectComposerModel.clear()
root.clearOnClose = false
}

View File

@@ -6,7 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
StudioControls.Dialog {
id: root
@@ -43,9 +43,9 @@ StudioControls.Dialog {
width: 50
text: qsTr("Save")
onClicked: {
let name = EffectMakerBackend.effectMakerModel.currentComposition
let name = EffectComposerBackend.effectComposerModel.currentComposition
if (name !== "")
EffectMakerBackend.effectMakerModel.saveComposition(name)
EffectComposerBackend.effectComposerModel.saveComposition(name)
root.save()
root.accept()

View File

@@ -0,0 +1,16 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectComposerBackend
Item { // The wrapper Item is used to limit hovering and clicking the CheckBox to its area
StudioControls.CheckBox {
actionIndicatorVisible: false
checked: uniformValue
onToggled: uniformValue = checked
anchors.verticalCenter: parent.verticalCenter
}
}

View File

@@ -4,7 +4,7 @@
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Row {
id: itemPane

View File

@@ -4,7 +4,7 @@
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Row {
width: parent.width

View File

@@ -4,7 +4,7 @@
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Row {
width: parent.width

View File

@@ -4,18 +4,18 @@
import QtQuick
import HelperWidgets as HelperWidgets
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Row {
id: itemPane
width: parent.width
spacing: 5
HelperWidgets.UrlChooser {
backendValue: uniformBackendValue
actionIndicatorVisible: false
comboBox.width: Math.min(parent.width - 70, 300)
onAbsoluteFilePathChanged: uniformValue = absoluteFilePath
@@ -30,7 +30,7 @@ Row {
return urlStr
}
defaultItems: [uniformDefaultValue.split('/').pop()]
defaultPaths: [defaultAsString(uniformDefaultValue)]
defaultItems: uniformDefaultValue ? [uniformDefaultValue.split('/').pop()] : undefined
defaultPaths: uniformDefaultValue ? [defaultAsString(uniformDefaultValue)] : undefined
}
}

View File

@@ -4,7 +4,7 @@
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
Row {
width: parent.width
@@ -35,8 +35,8 @@ Row {
to: uniformMaxValue
value: uniformValue
onMoved: {
uniformValue = value
spinBox.value = value
uniformValue = Math.round(value)
spinBox.value = Math.round(value)
}
}
}

View File

@@ -5,7 +5,7 @@ import QtQuick
import QtQuick.Layouts
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
RowLayout {
width: parent.width

View File

@@ -5,7 +5,7 @@ import QtQuick
import QtQuick.Layouts
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
RowLayout {
width: parent.width

View File

@@ -5,7 +5,7 @@ import QtQuick
import QtQuick.Layouts
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
import EffectComposerBackend
RowLayout {
width: parent.width

View File

@@ -1,243 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
Item {
id: root
property var draggedSec: null
property var secsY: []
property int moveFromIdx: 0
property int moveToIdx: 0
property bool previewAnimationRunning: false
// Invoked after save changes is done
property var onSaveChangesCallback: () => {}
// Invoked from C++ side when open composition is requested and there are unsaved changes
function promptToSaveBeforeOpen() {
root.onSaveChangesCallback = () => { EffectMakerBackend.rootView.doOpenComposition() }
saveChangesDialog.open()
}
Connections {
target: EffectMakerBackend.effectMakerModel
function onIsEmptyChanged() {
if (EffectMakerBackend.effectMakerModel.isEmpty)
saveAsDialog.close()
}
}
SaveAsDialog {
id: saveAsDialog
anchors.centerIn: parent
}
SaveChangesDialog {
id: saveChangesDialog
anchors.centerIn: parent
onSave: {
if (EffectMakerBackend.effectMakerModel.currentComposition === "") {
// if current composition is unsaved, show save as dialog and clear afterwards
saveAsDialog.clearOnClose = true
saveAsDialog.open()
} else {
root.onSaveChangesCallback()
}
}
onDiscard: {
root.onSaveChangesCallback()
}
}
Column {
id: col
anchors.fill: parent
spacing: 1
EffectMakerTopBar {
onAddClicked: {
root.onSaveChangesCallback = () => { EffectMakerBackend.effectMakerModel.clear(true) }
if (EffectMakerBackend.effectMakerModel.hasUnsavedChanges)
saveChangesDialog.open()
else
EffectMakerBackend.effectMakerModel.clear(true)
}
onSaveClicked: {
let name = EffectMakerBackend.effectMakerModel.currentComposition
if (name === "")
saveAsDialog.open()
else
EffectMakerBackend.effectMakerModel.saveComposition(name)
}
onSaveAsClicked: saveAsDialog.open()
onAssignToSelectedClicked: {
EffectMakerBackend.effectMakerModel.assignToSelected()
}
}
EffectMakerPreview {
mainRoot: root
FrameAnimation {
id: previewFrameTimer
running: true
paused: !previewAnimationRunning
}
}
Rectangle {
width: parent.width
height: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground
EffectNodesComboBox {
mainRoot: root
anchors.verticalCenter: parent.verticalCenter
x: 5
width: parent.width - 50
}
HelperWidgets.AbstractButton {
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.clearList_medium
tooltip: qsTr("Remove all effect nodes.")
enabled: !EffectMakerBackend.effectMakerModel.isEmpty
onClicked: EffectMakerBackend.effectMakerModel.clear()
}
HelperWidgets.AbstractButton {
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.code
tooltip: qsTr("Open Shader in Code Editor.")
visible: false // TODO: to be implemented
onClicked: {} // TODO
}
}
Component.onCompleted: HelperWidgets.Controller.mainScrollView = scrollView
HelperWidgets.ScrollView {
id: scrollView
width: parent.width
height: parent.height - y
clip: true
Column {
width: scrollView.width
spacing: 1
Repeater {
id: repeater
width: root.width
model: EffectMakerBackend.effectMakerModel
onCountChanged: {
HelperWidgets.Controller.setCount("EffectMaker", repeater.count)
}
delegate: EffectCompositionNode {
width: root.width
modelIndex: index
Behavior on y {
PropertyAnimation {
duration: 300
easing.type: Easing.InOutQuad
}
}
onStartDrag: (section) => {
root.draggedSec = section
root.moveFromIdx = index
highlightBorder = true
root.secsY = []
for (let i = 0; i < repeater.count; ++i)
root.secsY[i] = repeater.itemAt(i).y
}
onStopDrag: {
if (root.moveFromIdx === root.moveToIdx)
root.draggedSec.y = root.secsY[root.moveFromIdx]
else
EffectMakerBackend.effectMakerModel.moveNode(root.moveFromIdx, root.moveToIdx)
highlightBorder = false
root.draggedSec = null
}
}
} // Repeater
Timer {
running: root.draggedSec
interval: 50
repeat: true
onTriggered: {
root.moveToIdx = root.moveFromIdx
for (let i = 0; i < repeater.count; ++i) {
let currItem = repeater.itemAt(i)
if (i > root.moveFromIdx) {
if (root.draggedSec.y > currItem.y + (currItem.height - root.draggedSec.height) * .5) {
currItem.y = root.secsY[i] - root.draggedSec.height
root.moveToIdx = i
} else {
currItem.y = root.secsY[i]
}
} else if (i < root.moveFromIdx) {
if (!repeater.model.isDependencyNode(i)
&& root.draggedSec.y < currItem.y + (currItem.height - root.draggedSec.height) * .5) {
currItem.y = root.secsY[i] + root.draggedSec.height
root.moveToIdx = Math.min(root.moveToIdx, i)
} else {
currItem.y = root.secsY[i]
}
}
}
}
} // Timer
} // Column
} // ScrollView
}
Text {
id: emptyText
text: qsTr("Add an effect node to start")
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFontSize
x: scrollView.x + (scrollView.width - emptyText.width) * .5
y: scrollView.y + scrollView.height * .5
visible: EffectMakerBackend.effectMakerModel.isEmpty
}
}

View File

@@ -1,13 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
StudioControls.CheckBox {
actionIndicatorVisible: false
checked: uniformValue
onToggled: uniformValue = checked
}

View File

@@ -237,6 +237,7 @@ SecondColumnLayout {
shapeGradients: colorEditor.shapeGradients
supportGradient: colorEditor.supportGradient
width: popupDialog.contentWidth
visible: popupDialog.visible
}
onLoaded: {

View File

@@ -827,7 +827,7 @@ Column {
twoColumnWidth: root.twoColumnWidth
fourColumnWidth: root.fourColumnWidth
enableSingletonConnection: root.opened
enableSingletonConnection: root.visible
onSelectedColorChanged: {
colorPicker.color = colorPalette.selectedColor
colorEditor.color = colorPalette.selectedColor

View File

@@ -516,6 +516,8 @@ Section {
return aliasEditor
if (propertyType == "variant")
return readonlyEditor
if (propertyType == "var")
return readonlyEditor
if (propertyType == "TextureInput")
return textureInputEditor
if (propertyType == "vector2d" || propertyType == "vector3d" || propertyType == "vector4d")

View File

@@ -32,6 +32,8 @@ Row {
property alias spacer: spacer
property alias actionIndicatorVisible: comboBox.actionIndicatorVisible
property bool hideDuplicates: true
FileResourcesModel {
id: fileModel
modelNodeBackendProperty: modelNodeBackend
@@ -423,6 +425,8 @@ Row {
// QtDS very slow. This will happen when selecting different items in the scene.
comboBox.model = {}
let nameSet = new Set;
if (root.defaultItems !== undefined) {
for (var i = 0; i < root.defaultItems.length; ++i) {
comboBox.listModel.append({
@@ -433,6 +437,7 @@ Row {
name: root.defaultItems[i],
group: 0
})
nameSet.add(root.defaultItems[i])
}
}
@@ -440,12 +445,15 @@ Row {
for (var j = 0; j < myModel.length; ++j) {
let item = myModel[j]
if (!root.hideDuplicates || !nameSet.has(item.fileName)) {
comboBox.listModel.append({
absoluteFilePath: item.absoluteFilePath,
relativeFilePath: item.relativeFilePath,
name: item.fileName,
group: 1
})
nameSet.add(item.fileName)
}
}
comboBox.model = Qt.binding(function() { return comboBox.listModel })
@@ -461,6 +469,7 @@ Row {
onDefaultItemsChanged: root.createModel()
onDefaultPathsChanged: root.createModel()
onHideDuplicatesChanged: root.createModel()
Component.onCompleted: {
root.createModel()

View File

@@ -90,6 +90,7 @@ Item {
sourceComponent: ColorEditorPopup {
id: popup
width: popupDialog.contentWidth
visible: popupDialog.visible
onActivateColor: function(color) {
colorBackend.activateColor(color)

View File

@@ -246,6 +246,10 @@ QtObject {
property real collectionItemTextSideMargin: 10
property real collectionItemTextMargin: 5
property real collectionItemTextPadding: 5
property real collectionTableHorizontalMargin: 10
property real collectionTableVerticalMargin: 10
property real collectionCellMinimumWidth: 60
property real collectionCellMinimumHeight: 20
// NEW NEW NEW
readonly property int flowMargin: 7

View File

@@ -52,10 +52,10 @@ Rectangle {
Item {
id: __materialLibrary__
DefaultMaterial {
PrincipledMaterial {
id: defaultMaterial
objectName: "Default Material"
diffuseColor: "#4aee45"
baseColor: "#4aee45"
}
}

View File

@@ -382,22 +382,6 @@
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
},
{
"source": "../shared-plugin/name/JsonData.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/JsonData.qml"
},
{
"source": "../shared-plugin/name/DataStore.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DataStore.qml"
},
{
"source": "../shared-plugin/name/models.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/models.json"
},
{
"source": "../shared-plugin/name/data.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/data.json"
}
]
}

View File

@@ -395,22 +395,6 @@
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
},
{
"source": "../shared-plugin/name/JsonData.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/JsonData.qml"
},
{
"source": "../shared-plugin/name/DataStore.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DataStore.qml"
},
{
"source": "../shared-plugin/name/models.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/models.json"
},
{
"source": "../shared-plugin/name/data.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/data.json"
}
]
}

View File

@@ -382,22 +382,6 @@
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
},
{
"source": "../shared-plugin/name/JsonData.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/JsonData.qml"
},
{
"source": "../shared-plugin/name/DataStore.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DataStore.qml"
},
{
"source": "../shared-plugin/name/models.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/models.json"
},
{
"source": "../shared-plugin/name/data.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/data.json"
}
]
}

View File

@@ -341,22 +341,6 @@
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
},
{
"source": "../shared-plugin/name/JsonData.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/JsonData.qml"
},
{
"source": "../shared-plugin/name/DataStore.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DataStore.qml"
},
{
"source": "../shared-plugin/name/models.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/models.json"
},
{
"source": "../shared-plugin/name/data.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/data.json"
}
]
}

View File

@@ -343,22 +343,6 @@
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
},
{
"source": "../shared-plugin/name/JsonData.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/JsonData.qml"
},
{
"source": "../shared-plugin/name/DataStore.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DataStore.qml"
},
{
"source": "../shared-plugin/name/models.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/models.json"
},
{
"source": "../shared-plugin/name/data.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/data.json"
}
]
}

View File

@@ -343,22 +343,6 @@
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
},
{
"source": "../shared-plugin/name/JsonData.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/JsonData.qml"
},
{
"source": "../shared-plugin/name/DataStore.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DataStore.qml"
},
{
"source": "../shared-plugin/name/models.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/models.json"
},
{
"source": "../shared-plugin/name/data.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/data.json"
}
]
}

View File

@@ -13,12 +13,7 @@ qt6_add_qml_module(%{ImportModuleName}
RESOURCE_PREFIX "/qt/qml"
QML_FILES
Constants.qml
DataStore.qml
DirectoryFontLoader.qml
EventListModel.qml
EventListSimulator.qml
JsonData.qml
RESOURCES
data.json
models.json
)

View File

@@ -1,5 +1,4 @@
Module %{ImportModuleName}
singleton DataStore 1.0 DataStore.qml
singleton Constants 1.0 Constants.qml
EventListSimulator 1.0 EventListSimulator.qml
EventListModel 1.0 EventListModel.qml

View File

@@ -1,5 +1,4 @@
singleton Constants 1.0 Constants.qml
singleton DataStore 1.0 DataStore.qml
EventListModel 1.0 EventListModel.qml
EventListSimulator 1.0 EventListSimulator.qml
DirectoryFontLoader 1.0 DirectoryFontLoader.qml

View File

@@ -6,29 +6,29 @@ import WelcomeScreen 1.0
import StudioTheme 1.0 as StudioTheme
Item {
id: twitterButton
id: figmaButton
state: "darkNormal"
property bool isHovered: mouseArea.containsMouse
Image {
id: twitterDarkNormal
id: figmaDarkNormal
anchors.fill: parent
source: "images/twitterDarkNormal.png"
source: "images/figmaDarkNormal.png"
fillMode: Image.PreserveAspectFit
}
Image {
id: twitterLightNormal
id: figmaLightNormal
anchors.fill: parent
source: "images/twitterLightNormal.png"
source: "images/figmaLightNormal.png"
fillMode: Image.PreserveAspectFit
}
Image {
id: twitterHover
id: figmaHover
anchors.fill: parent
source: "images/twitterHover.png"
source: "images/figmaHover.png"
fillMode: Image.PreserveAspectFit
}
@@ -39,7 +39,7 @@ Item {
Connections {
target: mouseArea
function onClicked(mouse) { Qt.openUrlExternally("https://twitter.com/qtproject/") }
function onClicked(mouse) { Qt.openUrlExternally("https://www.figma.com/@qtdesignstudio/") }
}
}
@@ -49,17 +49,17 @@ Item {
when: !StudioTheme.Values.isLightTheme && !mouseArea.containsMouse && !mouseArea.pressed
PropertyChanges {
target: twitterDarkNormal
target: figmaDarkNormal
visible: true
}
PropertyChanges {
target: twitterLightNormal
target: figmaLightNormal
visible: false
}
PropertyChanges {
target: twitterHover
target: figmaHover
visible: false
}
},
@@ -68,17 +68,17 @@ Item {
when: StudioTheme.Values.isLightTheme && !mouseArea.containsMouse && !mouseArea.pressed
PropertyChanges {
target: twitterHover
target: figmaHover
visible: false
}
PropertyChanges {
target: twitterLightNormal
target: figmaLightNormal
visible: true
}
PropertyChanges {
target: twitterDarkNormal
target: figmaDarkNormal
visible: false
}
},
@@ -87,17 +87,17 @@ Item {
when: mouseArea.containsMouse && !mouseArea.pressed
PropertyChanges {
target: twitterHover
target: figmaHover
visible: true
}
PropertyChanges {
target: twitterLightNormal
target: figmaLightNormal
visible: false
}
PropertyChanges {
target: twitterDarkNormal
target: figmaDarkNormal
visible: false
}
},
@@ -106,18 +106,18 @@ Item {
when: (mouseArea.containsMouse || !mouseArea.containsMouse) && mouseArea.pressed
PropertyChanges {
target: twitterHover
target: figmaHover
visible: true
scale: 1.1
}
PropertyChanges {
target: twitterLightNormal
target: figmaLightNormal
visible: false
}
PropertyChanges {
target: twitterDarkNormal
target: figmaDarkNormal
visible: false
}
}

View File

@@ -80,8 +80,8 @@ Button {
Layout.fillWidth: true
}
TwitterButton {
id: twitterButton
FigmaButton {
id: figmaButton
Layout.maximumHeight: 15
Layout.minimumHeight: 15
Layout.preferredHeight: 15
@@ -100,7 +100,7 @@ Button {
states: [
State {
name: "normal"
when: !youtubeButton.isHovered && !twitterButton.isHovered && !control.hovered
when: !youtubeButton.isHovered && !figmaButton.isHovered && !control.hovered
PropertyChanges {
target: buttonBackground
@@ -110,7 +110,7 @@ Button {
},
State {
name: "hover"
when: control.hovered || youtubeButton.isHovered || twitterButton.isHovered
when: control.hovered || youtubeButton.isHovered || figmaButton.isHovered
PropertyChanges {
target: buttonBackground

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -74,8 +74,8 @@
<container floating="true">
<geometry>AdnQywADAAAAAAQuAAAB5gAABdEAAAOcAAAELgAAAfkAAAXRAAADnAAAAAAAAAAACgAAAAQuAAAB+QAABdEAAAOc</geometry>
<splitter orientation="Vertical" count="1">
<area tabs="1" current="Effect Maker">
<widget name="Effect Maker" closed="true"/>
<area tabs="1" current="Effect Composer">
<widget name="Effect Composer" closed="true"/>
</area>
<sizes>420</sizes>
</splitter>

View File

@@ -261,26 +261,6 @@
"source": "%{QdsWizardPath}/shared-plugin/name/designer/plugin.metainfo",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo",
"condition": "%{QdsProjectStyle}"
},
{
"source": "%{QdsWizardPath}/shared-plugin/name/JsonData.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/JsonData.qml",
"condition": "%{QdsProjectStyle}"
},
{
"source": "%{QdsWizardPath}/shared-plugin/name/DataStore.qml.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DataStore.qml",
"condition": "%{QdsProjectStyle}"
},
{
"source": "%{QdsWizardPath}/shared-plugin/name/models.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/models.json",
"condition": "%{QdsProjectStyle}"
},
{
"source": "%{QdsWizardPath}/shared-plugin/name/data.json.tpl",
"target": "%{ProjectDirectory}/imports/%{ImportModuleName}/data.json",
"condition": "%{QdsProjectStyle}"
}
]
}

View File

@@ -109,7 +109,7 @@ if (WITH_QMLDESIGNER)
set(qmldesigner_builddir ${PROJECT_BINARY_DIR}/qmldsgnr)
endif()
add_subdirectory(qmldesigner ${qmldesigner_builddir})
add_subdirectory(effectmakernew)
add_subdirectory(effectcomposer)
add_subdirectory(studiowelcome)
add_subdirectory(insight)
endif()

View File

@@ -110,6 +110,10 @@ GeneralSettingsWidget::GeneralSettingsWidget()
m_languageBox->setObjectName("languageBox");
m_languageBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
m_languageBox->setMinimumContentsLength(20);
if (Core::ICore::isQtDesignStudio()) {
m_languageBox->setDisabled(true);
m_languageBox->setToolTip("Qt Design Studio is currently available in English only.");
}
m_codecBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
m_codecBox->setMinimumContentsLength(20);
@@ -211,7 +215,7 @@ void GeneralSettingsWidget::fillLanguageBox() const
m_languageBox->addItem(Tr::tr("<System Language>"), QString());
// need to add this explicitly, since there is no qm file for English
m_languageBox->addItem(QLatin1String("English"), QLatin1String("C"));
if (currentLocale == QLatin1String("C"))
if (currentLocale == QLatin1String("C") || Core::ICore::isQtDesignStudio())
m_languageBox->setCurrentIndex(m_languageBox->count() - 1);
const FilePath creatorTrPath = ICore::resourcePath("translations");

View File

@@ -1,4 +1,4 @@
add_qtc_plugin(EffectMakerNew
add_qtc_plugin(EffectComposer
CONDITION TARGET Qt::Quick AND TARGET QtCreator::QmlDesigner
PLUGIN_DEPENDS
QtCreator::QmlDesigner QtCreator::ProjectExplorer QtCreator::QmlProjectManager
@@ -6,18 +6,18 @@ add_qtc_plugin(EffectMakerNew
Qt::Core Qt::CorePrivate Qt::Widgets Qt::Qml Qt::QmlPrivate Qt::Quick
QtCreator::Utils
SOURCES
effectmakerplugin.cpp
effectmakerwidget.cpp effectmakerwidget.h
effectmakerview.cpp effectmakerview.h
effectmakermodel.cpp effectmakermodel.h
effectmakernodesmodel.cpp effectmakernodesmodel.h
effectmakeruniformsmodel.cpp effectmakeruniformsmodel.h
effectcomposerplugin.cpp
effectcomposerwidget.cpp effectcomposerwidget.h
effectcomposerview.cpp effectcomposerview.h
effectcomposermodel.cpp effectcomposermodel.h
effectcomposernodesmodel.cpp effectcomposernodesmodel.h
effectcomposeruniformsmodel.cpp effectcomposeruniformsmodel.h
effectnode.cpp effectnode.h
effectnodescategory.cpp effectnodescategory.h
compositionnode.cpp compositionnode.h
uniform.cpp uniform.h
effectutils.cpp effectutils.h
effectmakercontextobject.cpp effectmakercontextobject.h
effectcomposercontextobject.cpp effectcomposercontextobject.h
shaderfeatures.cpp shaderfeatures.h
syntaxhighlighterdata.cpp syntaxhighlighterdata.h
propertyhandler.cpp propertyhandler.h

View File

@@ -1,5 +1,5 @@
{
"Name" : "EffectMakerNew",
"Name" : "EffectComposer",
"Version" : "${IDE_VERSION}",
"CompatVersion" : "${IDE_VERSION_COMPAT}",
"Vendor" : "The Qt Company Ltd",
@@ -8,7 +8,7 @@
"",
"Licensees holding valid Qt Enterprise licenses may use this plugin in accordance with the Qt Enterprise License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company."
],
"Description" : "Plugin for Effect Maker.",
"Description" : "Plugin for Effect Composer.",
"Url" : "http://www.qt.io",
"DisabledByDefault" : true,
${IDE_PLUGIN_DEPENDENCIES}

View File

@@ -4,7 +4,7 @@
#include "compositionnode.h"
#include "effectutils.h"
#include "effectmakeruniformsmodel.h"
#include "effectcomposeruniformsmodel.h"
#include "propertyhandler.h"
#include "uniform.h"
@@ -12,7 +12,7 @@
#include <QJsonArray>
#include <QJsonDocument>
namespace EffectMaker {
namespace EffectComposer {
CompositionNode::CompositionNode(const QString &effectName, const QString &qenPath,
const QJsonObject &jsonObject)
@@ -187,5 +187,5 @@ QString CompositionNode::name() const
return m_name;
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -3,12 +3,12 @@
#pragma once
#include "effectmakeruniformsmodel.h"
#include "effectcomposeruniformsmodel.h"
#include <QJsonObject>
#include <QObject>
namespace EffectMaker {
namespace EffectComposer {
class CompositionNode : public QObject
{
@@ -72,8 +72,7 @@ private:
QList<Uniform *> m_uniforms;
EffectMakerUniformsModel m_unifomrsModel;
EffectComposerUniformsModel m_unifomrsModel;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "effectmakercontextobject.h"
#include "effectcomposercontextobject.h"
#include <abstractview.h>
#include <bindingproperty.h>
@@ -27,15 +27,15 @@
#include <coreplugin/icore.h>
namespace EffectMaker {
namespace EffectComposer {
EffectMakerContextObject::EffectMakerContextObject(QQmlContext *context, QObject *parent)
EffectComposerContextObject::EffectComposerContextObject(QQmlContext *context, QObject *parent)
: QObject(parent)
, m_qmlContext(context)
{
}
QString EffectMakerContextObject::convertColorToString(const QVariant &color)
QString EffectComposerContextObject::convertColorToString(const QVariant &color)
{
QString colorString;
QColor theColor;
@@ -52,17 +52,17 @@ QString EffectMakerContextObject::convertColorToString(const QVariant &color)
}
// TODO: this method is used by the ColorEditor helper widget, check if at all needed?
QColor EffectMakerContextObject::colorFromString(const QString &colorString)
QColor EffectComposerContextObject::colorFromString(const QString &colorString)
{
return colorString;
}
int EffectMakerContextObject::majorVersion() const
int EffectComposerContextObject::majorVersion() const
{
return m_majorVersion;
}
void EffectMakerContextObject::setMajorVersion(int majorVersion)
void EffectComposerContextObject::setMajorVersion(int majorVersion)
{
if (m_majorVersion == majorVersion)
return;
@@ -72,7 +72,7 @@ void EffectMakerContextObject::setMajorVersion(int majorVersion)
emit majorVersionChanged();
}
void EffectMakerContextObject::setStateName(const QString &newStateName)
void EffectComposerContextObject::setStateName(const QString &newStateName)
{
if (newStateName == m_stateName)
return;
@@ -81,7 +81,7 @@ void EffectMakerContextObject::setStateName(const QString &newStateName)
emit stateNameChanged();
}
void EffectMakerContextObject::setAllStateNames(const QStringList &allStates)
void EffectComposerContextObject::setAllStateNames(const QStringList &allStates)
{
if (allStates == m_allStateNames)
return;
@@ -90,7 +90,7 @@ void EffectMakerContextObject::setAllStateNames(const QStringList &allStates)
emit allStateNamesChanged();
}
void EffectMakerContextObject::setIsBaseState(bool newIsBaseState)
void EffectComposerContextObject::setIsBaseState(bool newIsBaseState)
{
if (newIsBaseState == m_isBaseState)
return;
@@ -99,7 +99,7 @@ void EffectMakerContextObject::setIsBaseState(bool newIsBaseState)
emit isBaseStateChanged();
}
void EffectMakerContextObject::setSelectionChanged(bool newSelectionChanged)
void EffectComposerContextObject::setSelectionChanged(bool newSelectionChanged)
{
if (newSelectionChanged == m_selectionChanged)
return;
@@ -108,7 +108,7 @@ void EffectMakerContextObject::setSelectionChanged(bool newSelectionChanged)
emit selectionChangedChanged();
}
void EffectMakerContextObject::setBackendValues(QQmlPropertyMap *newBackendValues)
void EffectComposerContextObject::setBackendValues(QQmlPropertyMap *newBackendValues)
{
if (newBackendValues == m_backendValues)
return;
@@ -117,17 +117,17 @@ void EffectMakerContextObject::setBackendValues(QQmlPropertyMap *newBackendValue
emit backendValuesChanged();
}
void EffectMakerContextObject::setModel(QmlDesigner::Model *model)
void EffectComposerContextObject::setModel(QmlDesigner::Model *model)
{
m_model = model;
}
void EffectMakerContextObject::triggerSelectionChanged()
void EffectComposerContextObject::triggerSelectionChanged()
{
setSelectionChanged(!m_selectionChanged);
}
void EffectMakerContextObject::hideCursor()
void EffectComposerContextObject::hideCursor()
{
if (QApplication::overrideCursor())
return;
@@ -138,7 +138,7 @@ void EffectMakerContextObject::hideCursor()
m_lastPos = QCursor::pos(w->screen());
}
void EffectMakerContextObject::restoreCursor()
void EffectComposerContextObject::restoreCursor()
{
if (!QApplication::overrideCursor())
return;
@@ -149,7 +149,7 @@ void EffectMakerContextObject::restoreCursor()
QCursor::setPos(w->screen(), m_lastPos);
}
void EffectMakerContextObject::holdCursorInPlace()
void EffectComposerContextObject::holdCursorInPlace()
{
if (!QApplication::overrideCursor())
return;
@@ -158,7 +158,7 @@ void EffectMakerContextObject::holdCursorInPlace()
QCursor::setPos(w->screen(), m_lastPos);
}
int EffectMakerContextObject::devicePixelRatio()
int EffectComposerContextObject::devicePixelRatio()
{
if (QWidget *w = QApplication::activeWindow())
return w->devicePixelRatio();
@@ -166,7 +166,7 @@ int EffectMakerContextObject::devicePixelRatio()
return 1;
}
QStringList EffectMakerContextObject::allStatesForId(const QString &id)
QStringList EffectComposerContextObject::allStatesForId(const QString &id)
{
if (m_model && m_model->rewriterView()) {
const QmlDesigner::QmlObjectNode node = m_model->rewriterView()->modelNodeForId(id);
@@ -177,10 +177,10 @@ QStringList EffectMakerContextObject::allStatesForId(const QString &id)
return {};
}
bool EffectMakerContextObject::isBlocked(const QString &) const
bool EffectComposerContextObject::isBlocked(const QString &) const
{
return false;
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -14,9 +14,9 @@
#include <QPoint>
#include <QMouseEvent>
namespace EffectMaker {
namespace EffectComposer {
class EffectMakerContextObject : public QObject
class EffectComposerContextObject : public QObject
{
Q_OBJECT
@@ -32,7 +32,7 @@ class EffectMakerContextObject : public QObject
Q_PROPERTY(QQmlPropertyMap *backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged)
public:
EffectMakerContextObject(QQmlContext *context, QObject *parent = nullptr);
EffectComposerContextObject(QQmlContext *context, QObject *parent = nullptr);
QString stateName() const { return m_stateName; }
QStringList allStateNames() const { return m_allStateNames; }
@@ -98,5 +98,5 @@ private:
bool m_selectionChanged = false;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "effectmakermodel.h"
#include "effectcomposermodel.h"
#include "compositionnode.h"
#include "effectutils.h"
@@ -26,7 +26,7 @@
#include <QLibraryInfo>
#include <QVector2D>
namespace EffectMaker {
namespace EffectComposer {
enum class FileType
{
@@ -49,12 +49,12 @@ static bool writeToFile(const QByteArray &buf, const QString &filename, FileType
return true;
}
EffectMakerModel::EffectMakerModel(QObject *parent)
EffectComposerModel::EffectComposerModel(QObject *parent)
: QAbstractListModel{parent}
{
}
QHash<int, QByteArray> EffectMakerModel::roleNames() const
QHash<int, QByteArray> EffectComposerModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[NameRole] = "nodeName";
@@ -64,14 +64,14 @@ QHash<int, QByteArray> EffectMakerModel::roleNames() const
return roles;
}
int EffectMakerModel::rowCount(const QModelIndex &parent) const
int EffectComposerModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_nodes.count();
}
QVariant EffectMakerModel::data(const QModelIndex &index, int role) const
QVariant EffectComposerModel::data(const QModelIndex &index, int role) const
{
QTC_ASSERT(index.isValid() && index.row() < m_nodes.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
@@ -79,7 +79,7 @@ QVariant EffectMakerModel::data(const QModelIndex &index, int role) const
return m_nodes.at(index.row())->property(roleNames().value(role));
}
bool EffectMakerModel::setData(const QModelIndex &index, const QVariant &value, int role)
bool EffectComposerModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || !roleNames().contains(role))
return false;
@@ -95,7 +95,7 @@ bool EffectMakerModel::setData(const QModelIndex &index, const QVariant &value,
return true;
}
void EffectMakerModel::setIsEmpty(bool val)
void EffectComposerModel::setIsEmpty(bool val)
{
if (m_isEmpty != val) {
m_isEmpty = val;
@@ -106,12 +106,12 @@ void EffectMakerModel::setIsEmpty(bool val)
}
}
void EffectMakerModel::addNode(const QString &nodeQenPath)
void EffectComposerModel::addNode(const QString &nodeQenPath)
{
beginResetModel();
auto *node = new CompositionNode({}, nodeQenPath);
connect(qobject_cast<EffectMakerUniformsModel *>(node->uniformsModel()),
&EffectMakerUniformsModel::dataChanged, this, [this] {
connect(qobject_cast<EffectComposerUniformsModel *>(node->uniformsModel()),
&EffectComposerUniformsModel::dataChanged, this, [this] {
setHasUnsavedChanges(true);
});
@@ -125,8 +125,8 @@ void EffectMakerModel::addNode(const QString &nodeQenPath)
const QString path = EffectUtils::nodesSourcesPath() + "/common/" + requiredId + ".qen";
auto requiredNode = new CompositionNode({}, path);
connect(qobject_cast<EffectMakerUniformsModel *>(requiredNode->uniformsModel()),
&EffectMakerUniformsModel::dataChanged, this, [this] {
connect(qobject_cast<EffectComposerUniformsModel *>(requiredNode->uniformsModel()),
&EffectComposerUniformsModel::dataChanged, this, [this] {
setHasUnsavedChanges(true);
});
requiredNode->setRefCount(1);
@@ -144,7 +144,7 @@ void EffectMakerModel::addNode(const QString &nodeQenPath)
emit nodesChanged();
}
CompositionNode *EffectMakerModel::findNodeById(const QString &id) const
CompositionNode *EffectComposerModel::findNodeById(const QString &id) const
{
for (CompositionNode *node : std::as_const(m_nodes)) {
if (node->id() == id)
@@ -153,7 +153,7 @@ CompositionNode *EffectMakerModel::findNodeById(const QString &id) const
return {};
}
void EffectMakerModel::moveNode(int fromIdx, int toIdx)
void EffectComposerModel::moveNode(int fromIdx, int toIdx)
{
if (fromIdx == toIdx)
return;
@@ -167,7 +167,7 @@ void EffectMakerModel::moveNode(int fromIdx, int toIdx)
bakeShaders();
}
void EffectMakerModel::removeNode(int idx)
void EffectComposerModel::removeNode(int idx)
{
beginResetModel();
CompositionNode *node = m_nodes.takeAt(idx);
@@ -193,7 +193,7 @@ void EffectMakerModel::removeNode(int idx)
emit nodesChanged();
}
void EffectMakerModel::clear(bool clearName)
void EffectComposerModel::clear(bool clearName)
{
beginResetModel();
qDeleteAll(m_nodes);
@@ -209,14 +209,14 @@ void EffectMakerModel::clear(bool clearName)
emit nodesChanged();
}
void EffectMakerModel::assignToSelected()
void EffectComposerModel::assignToSelected()
{
const QString effectsAssetsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory();
const QString path = effectsAssetsDir + QDir::separator() + m_currentComposition + ".qep";
emit assignToSelectedTriggered(path);
}
QString EffectMakerModel::getUniqueEffectName() const
QString EffectComposerModel::getUniqueEffectName() const
{
const QString effectsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory();
const QString path = effectsDir + QDir::separator() + "Effect%1.qep";
@@ -229,12 +229,12 @@ QString EffectMakerModel::getUniqueEffectName() const
return QString("Effect%1").arg(num, 2, 10, QChar('0'));
}
QString EffectMakerModel::fragmentShader() const
QString EffectComposerModel::fragmentShader() const
{
return m_fragmentShader;
}
void EffectMakerModel::setFragmentShader(const QString &newFragmentShader)
void EffectComposerModel::setFragmentShader(const QString &newFragmentShader)
{
if (m_fragmentShader == newFragmentShader)
return;
@@ -242,12 +242,12 @@ void EffectMakerModel::setFragmentShader(const QString &newFragmentShader)
m_fragmentShader = newFragmentShader;
}
QString EffectMakerModel::vertexShader() const
QString EffectComposerModel::vertexShader() const
{
return m_vertexShader;
}
void EffectMakerModel::setVertexShader(const QString &newVertexShader)
void EffectComposerModel::setVertexShader(const QString &newVertexShader)
{
if (m_vertexShader == newVertexShader)
return;
@@ -255,20 +255,20 @@ void EffectMakerModel::setVertexShader(const QString &newVertexShader)
m_vertexShader = newVertexShader;
}
const QString &EffectMakerModel::qmlComponentString() const
const QString &EffectComposerModel::qmlComponentString() const
{
return m_qmlComponentString;
}
const QList<Uniform *> EffectMakerModel::allUniforms() const
const QList<Uniform *> EffectComposerModel::allUniforms() const
{
QList<Uniform *> uniforms = {};
for (const auto &node : std::as_const(m_nodes))
uniforms.append(static_cast<EffectMakerUniformsModel *>(node->uniformsModel())->uniforms());
uniforms.append(static_cast<EffectComposerUniformsModel *>(node->uniformsModel())->uniforms());
return uniforms;
}
const QString EffectMakerModel::getBufUniform()
const QString EffectComposerModel::getBufUniform()
{
QList<Uniform *> uniforms = allUniforms();
QString s;
@@ -295,7 +295,7 @@ const QString EffectMakerModel::getBufUniform()
return s;
}
const QString EffectMakerModel::getVSUniforms()
const QString EffectComposerModel::getVSUniforms()
{
QString s;
s += "#version 440\n";
@@ -313,7 +313,7 @@ const QString EffectMakerModel::getVSUniforms()
return s;
}
const QString EffectMakerModel::getFSUniforms()
const QString EffectComposerModel::getFSUniforms()
{
const QList<Uniform *> uniforms = allUniforms();
QString s;
@@ -359,7 +359,7 @@ const QString EffectMakerModel::getFSUniforms()
// Detects common GLSL error messages and returns potential
// additional error information related to them.
QString EffectMakerModel::detectErrorMessage(const QString &errorMessage)
QString EffectComposerModel::detectErrorMessage(const QString &errorMessage)
{
static QHash<QString, QString> nodeErrors {
{ "'BLUR_HELPER_MAX_LEVEL' : undeclared identifier", "BlurHelper"},
@@ -380,7 +380,7 @@ QString EffectMakerModel::detectErrorMessage(const QString &errorMessage)
}
// Return first error message (if any)
EffectError EffectMakerModel::effectError() const
EffectError EffectComposerModel::effectError() const
{
for (const EffectError &e : std::as_const(m_effectErrors)) {
if (!e.m_message.isEmpty())
@@ -392,7 +392,7 @@ EffectError EffectMakerModel::effectError() const
// Set the effect error message with optional type and lineNumber.
// Type comes from ErrorTypes, defaulting to common errors (-1).
// Note that type must match with UI editor tab index.
void EffectMakerModel::setEffectError(const QString &errorMessage, int type, int lineNumber)
void EffectComposerModel::setEffectError(const QString &errorMessage, int type, int lineNumber)
{
EffectError error;
error.m_type = type;
@@ -557,7 +557,7 @@ QJsonObject nodeToJson(const CompositionNode &node)
return nodeObject;
}
QString EffectMakerModel::getQmlEffectString()
QString EffectComposerModel::getQmlEffectString()
{
QString s;
@@ -571,7 +571,9 @@ import QtQuick
Item {
id: rootItem
// This is an internal property used by tooling to identify effect items
property var _isEffectItem
property Item _oldParent: null
)"
};
@@ -616,6 +618,20 @@ R"(
)"
};
if (m_shaderFeatures.enabled(ShaderFeatures::Mipmap)) {
QString mipmap1{
R"(parent.layer.smooth = true
parent.layer.mipmap = true
%1)"
};
QString mipmap2{
R"(_oldParent.layer.smooth = false
_oldParent.layer.mipmap = false
%2)"
};
parentChanged = parentChanged.arg(mipmap1, mipmap2);
}
parentChanged = parentChanged.arg(m_shaderFeatures.enabled(ShaderFeatures::Source)
? QString("source = parent") : QString(),
m_shaderFeatures.enabled(ShaderFeatures::Source)
@@ -648,7 +664,7 @@ R"(
return s;
}
void EffectMakerModel::saveComposition(const QString &name)
void EffectComposerModel::saveComposition(const QString &name)
{
const QString effectsAssetsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory();
const QString path = effectsAssetsDir + QDir::separator() + name + ".qep";
@@ -685,7 +701,7 @@ void EffectMakerModel::saveComposition(const QString &name)
saveResources(name);
}
void EffectMakerModel::openComposition(const QString &path)
void EffectComposerModel::openComposition(const QString &path)
{
clear(true);
@@ -741,8 +757,8 @@ void EffectMakerModel::openComposition(const QString &path)
for (const auto &nodeElement : nodesArray) {
auto *node = new CompositionNode(effectName, {}, nodeElement.toObject());
connect(qobject_cast<EffectMakerUniformsModel *>(node->uniformsModel()),
&EffectMakerUniformsModel::dataChanged, this, [this] {
connect(qobject_cast<EffectComposerUniformsModel *>(node->uniformsModel()),
&EffectComposerUniformsModel::dataChanged, this, [this] {
setHasUnsavedChanges(true);
});
m_nodes.append(node);
@@ -767,7 +783,7 @@ void EffectMakerModel::openComposition(const QString &path)
emit nodesChanged();
}
void EffectMakerModel::saveResources(const QString &name)
void EffectComposerModel::saveResources(const QString &name)
{
// Make sure that uniforms are up-to-date
updateCustomUniforms();
@@ -878,7 +894,7 @@ void EffectMakerModel::saveResources(const QString &name)
emit resourcesSaved(QString("Effects.%1.%1").arg(name).toUtf8(), effectPath);
}
void EffectMakerModel::resetEffectError(int type)
void EffectComposerModel::resetEffectError(int type)
{
if (m_effectErrors.contains(type)) {
m_effectErrors.remove(type);
@@ -887,7 +903,7 @@ void EffectMakerModel::resetEffectError(int type)
}
// Get value in QML format that used for exports
QString EffectMakerModel::valueAsString(const Uniform &uniform)
QString EffectComposerModel::valueAsString(const Uniform &uniform)
{
if (uniform.type() == Uniform::Type::Bool) {
return uniform.value().toBool() ? QString("true") : QString("false");
@@ -905,7 +921,7 @@ QString EffectMakerModel::valueAsString(const Uniform &uniform)
QVector4D v4 = uniform.value().value<QVector4D>();
return QString("Qt.vector4d(%1, %2, %3, %4)").arg(v4.x()).arg(v4.y()).arg(v4.z()).arg(v4.w());
} else if (uniform.type() == Uniform::Type::Sampler) {
return getImageElementName(uniform);
return getImageElementName(uniform, true);
} else if (uniform.type() == Uniform::Type::Color) {
return QString("\"%1\"").arg(uniform.value().toString());
} else if (uniform.type() == Uniform::Type::Define) {
@@ -917,7 +933,7 @@ QString EffectMakerModel::valueAsString(const Uniform &uniform)
}
// Get value in QML binding that used for previews
QString EffectMakerModel::valueAsBinding(const Uniform &uniform)
QString EffectComposerModel::valueAsBinding(const Uniform &uniform)
{
if (uniform.type() == Uniform::Type::Bool
|| uniform.type() == Uniform::Type::Int
@@ -941,7 +957,7 @@ QString EffectMakerModel::valueAsBinding(const Uniform &uniform)
QString sw = QString("g_propertyData.%1.w").arg(uniform.name());
return QString("Qt.vector4d(%1, %2, %3, %4)").arg(sx, sy, sz, sw);
} else if (uniform.type() == Uniform::Type::Sampler) {
return getImageElementName(uniform);
return getImageElementName(uniform, false);
} else {
qWarning() << QString("Unhandled const variable type: %1").arg(int(uniform.type())).toLatin1();
return QString();
@@ -949,7 +965,7 @@ QString EffectMakerModel::valueAsBinding(const Uniform &uniform)
}
// Get value in GLSL format that is used for non-exported const properties
QString EffectMakerModel::valueAsVariable(const Uniform &uniform)
QString EffectComposerModel::valueAsVariable(const Uniform &uniform)
{
if (uniform.type() == Uniform::Type::Bool) {
return uniform.value().toBool() ? QString("true") : QString("false");
@@ -976,16 +992,16 @@ QString EffectMakerModel::valueAsVariable(const Uniform &uniform)
}
// Return name for the image property Image element
QString EffectMakerModel::getImageElementName(const Uniform &uniform)
QString EffectComposerModel::getImageElementName(const Uniform &uniform, bool localFiles)
{
if (uniform.value().toString().isEmpty())
if (localFiles && uniform.value().toString().isEmpty())
return QStringLiteral("null");
QString simplifiedName = uniform.name().simplified();
simplifiedName = simplifiedName.remove(' ');
return QStringLiteral("imageItem") + simplifiedName;
}
const QString EffectMakerModel::getConstVariables()
const QString EffectComposerModel::getConstVariables()
{
const QList<Uniform *> uniforms = allUniforms();
QString s;
@@ -1001,7 +1017,7 @@ const QString EffectMakerModel::getConstVariables()
return s;
}
const QString EffectMakerModel::getDefineProperties()
const QString EffectComposerModel::getDefineProperties()
{
const QList<Uniform *> uniforms = allUniforms();
QString s;
@@ -1018,7 +1034,7 @@ const QString EffectMakerModel::getDefineProperties()
return s;
}
int EffectMakerModel::getTagIndex(const QStringList &code, const QString &tag)
int EffectComposerModel::getTagIndex(const QStringList &code, const QString &tag)
{
int index = -1;
int line = 0;
@@ -1040,7 +1056,7 @@ int EffectMakerModel::getTagIndex(const QStringList &code, const QString &tag)
return index;
}
QString EffectMakerModel::processVertexRootLine(const QString &line)
QString EffectComposerModel::processVertexRootLine(const QString &line)
{
QString output;
QStringList lineList = line.split(m_spaceReg, Qt::SkipEmptyParts);
@@ -1054,7 +1070,7 @@ QString EffectMakerModel::processVertexRootLine(const QString &line)
return output;
}
QString EffectMakerModel::processFragmentRootLine(const QString &line)
QString EffectComposerModel::processFragmentRootLine(const QString &line)
{
QString output;
QStringList lineList = line.split(m_spaceReg, Qt::SkipEmptyParts);
@@ -1065,7 +1081,7 @@ QString EffectMakerModel::processFragmentRootLine(const QString &line)
return output;
}
QStringList EffectMakerModel::getDefaultRootVertexShader()
QStringList EffectComposerModel::getDefaultRootVertexShader()
{
if (m_defaultRootVertexShader.isEmpty()) {
m_defaultRootVertexShader << "void main() {";
@@ -1079,7 +1095,7 @@ QStringList EffectMakerModel::getDefaultRootVertexShader()
return m_defaultRootVertexShader;
}
QStringList EffectMakerModel::getDefaultRootFragmentShader()
QStringList EffectComposerModel::getDefaultRootFragmentShader()
{
if (m_defaultRootFragmentShader.isEmpty()) {
m_defaultRootFragmentShader << "void main() {";
@@ -1093,7 +1109,7 @@ QStringList EffectMakerModel::getDefaultRootFragmentShader()
// Remove all post-processing tags ("@tag") from the code.
// Except "@nodes" tag as that is handled later.
QStringList EffectMakerModel::removeTagsFromCode(const QStringList &codeLines)
QStringList EffectComposerModel::removeTagsFromCode(const QStringList &codeLines)
{
QStringList s;
for (const QString &line : codeLines) {
@@ -1118,13 +1134,13 @@ QStringList EffectMakerModel::removeTagsFromCode(const QStringList &codeLines)
return s;
}
QString EffectMakerModel::removeTagsFromCode(const QString &code)
QString EffectComposerModel::removeTagsFromCode(const QString &code)
{
QStringList codeLines = removeTagsFromCode(code.split('\n'));
return codeLines.join('\n');
}
QString EffectMakerModel::getCustomShaderVaryings(bool outState)
QString EffectComposerModel::getCustomShaderVaryings(bool outState)
{
QString output;
QString direction = outState ? QStringLiteral("out") : QStringLiteral("in");
@@ -1136,7 +1152,7 @@ QString EffectMakerModel::getCustomShaderVaryings(bool outState)
return output;
}
QString EffectMakerModel::generateVertexShader(bool includeUniforms)
QString EffectComposerModel::generateVertexShader(bool includeUniforms)
{
QString s;
@@ -1192,7 +1208,7 @@ QString EffectMakerModel::generateVertexShader(bool includeUniforms)
return s;
}
QString EffectMakerModel::generateFragmentShader(bool includeUniforms)
QString EffectComposerModel::generateFragmentShader(bool includeUniforms)
{
QString s;
@@ -1247,7 +1263,7 @@ QString EffectMakerModel::generateFragmentShader(bool includeUniforms)
return s;
}
void EffectMakerModel::handleQsbProcessExit(Utils::Process *qsbProcess, const QString &shader, bool preview)
void EffectComposerModel::handleQsbProcessExit(Utils::Process *qsbProcess, const QString &shader, bool preview)
{
--m_remainingQsbTargets;
@@ -1279,7 +1295,7 @@ void EffectMakerModel::handleQsbProcessExit(Utils::Process *qsbProcess, const QS
// Generates string of the custom properties (uniforms) into ShaderEffect component
// Also generates QML images elements for samplers.
void EffectMakerModel::updateCustomUniforms()
void EffectComposerModel::updateCustomUniforms()
{
QString exportedRootPropertiesString;
QString previewEffectPropertiesString;
@@ -1345,7 +1361,7 @@ void EffectMakerModel::updateCustomUniforms()
m_exportedEffectPropertiesString = exportedEffectPropertiesString;
}
void EffectMakerModel::createFiles()
void EffectComposerModel::createFiles()
{
if (QFileInfo(m_vertexShaderFilename).exists())
QFile(m_vertexShaderFilename).remove();
@@ -1378,7 +1394,7 @@ void EffectMakerModel::createFiles()
}
}
void EffectMakerModel::bakeShaders()
void EffectComposerModel::bakeShaders()
{
const QString failMessage = "Shader baking failed: ";
@@ -1460,12 +1476,12 @@ void EffectMakerModel::bakeShaders()
}
bool EffectMakerModel::shadersUpToDate() const
bool EffectComposerModel::shadersUpToDate() const
{
return m_shadersUpToDate;
}
void EffectMakerModel::setShadersUpToDate(bool UpToDate)
void EffectComposerModel::setShadersUpToDate(bool UpToDate)
{
if (m_shadersUpToDate == UpToDate)
return;
@@ -1473,9 +1489,22 @@ void EffectMakerModel::setShadersUpToDate(bool UpToDate)
emit shadersUpToDateChanged();
}
bool EffectComposerModel::isEnabled() const
{
return m_isEnabled;
}
void EffectComposerModel::setIsEnabled(bool enabled)
{
if (m_isEnabled == enabled)
return;
m_isEnabled = enabled;
emit isEnabledChanged();
}
// Returns name for image mipmap property.
// e.g. "myImage" -> "myImageMipmap".
QString EffectMakerModel::mipmapPropertyName(const QString &name) const
QString EffectComposerModel::mipmapPropertyName(const QString &name) const
{
QString simplifiedName = name.simplified();
simplifiedName = simplifiedName.remove(' ');
@@ -1483,17 +1512,19 @@ QString EffectMakerModel::mipmapPropertyName(const QString &name) const
return simplifiedName;
}
QString EffectMakerModel::getQmlImagesString(bool localFiles)
QString EffectComposerModel::getQmlImagesString(bool localFiles)
{
QString imagesString;
const QList<Uniform *> uniforms = allUniforms();
for (Uniform *uniform : uniforms) {
if (uniform->type() == Uniform::Type::Sampler) {
QString imagePath = uniform->value().toString();
if (imagePath.isEmpty())
// For preview, generate image element even if path is empty, as changing uniform values
// will not trigger qml code regeneration
if (localFiles && imagePath.isEmpty())
continue;
imagesString += " Image {\n";
QString simplifiedName = getImageElementName(*uniform);
QString simplifiedName = getImageElementName(*uniform, localFiles);
imagesString += QString(" id: %1\n").arg(simplifiedName);
imagesString += " anchors.fill: parent\n";
// File paths are absolute, return as local when requested
@@ -1517,7 +1548,7 @@ QString EffectMakerModel::getQmlImagesString(bool localFiles)
return imagesString;
}
QString EffectMakerModel::getQmlComponentString(bool localFiles)
QString EffectComposerModel::getQmlComponentString(bool localFiles)
{
auto addProperty = [localFiles](const QString &name, const QString &var,
const QString &type, bool blurHelper = false)
@@ -1604,12 +1635,12 @@ QString EffectMakerModel::getQmlComponentString(bool localFiles)
return s;
}
QString EffectMakerModel::currentComposition() const
QString EffectComposerModel::currentComposition() const
{
return m_currentComposition;
}
void EffectMakerModel::setCurrentComposition(const QString &newCurrentComposition)
void EffectComposerModel::setCurrentComposition(const QString &newCurrentComposition)
{
if (m_currentComposition == newCurrentComposition)
return;
@@ -1618,12 +1649,12 @@ void EffectMakerModel::setCurrentComposition(const QString &newCurrentCompositio
emit currentCompositionChanged();
}
bool EffectMakerModel::hasUnsavedChanges() const
bool EffectComposerModel::hasUnsavedChanges() const
{
return m_hasUnsavedChanges;
}
void EffectMakerModel::setHasUnsavedChanges(bool val)
void EffectComposerModel::setHasUnsavedChanges(bool val)
{
if (m_hasUnsavedChanges == val)
return;
@@ -1632,7 +1663,7 @@ void EffectMakerModel::setHasUnsavedChanges(bool val)
emit hasUnsavedChangesChanged();
}
QStringList EffectMakerModel::uniformNames() const
QStringList EffectComposerModel::uniformNames() const
{
QStringList usedList;
const QList<Uniform *> uniforms = allUniforms();
@@ -1641,14 +1672,14 @@ QStringList EffectMakerModel::uniformNames() const
return usedList;
}
bool EffectMakerModel::isDependencyNode(int index) const
bool EffectComposerModel::isDependencyNode(int index) const
{
if (m_nodes.size() > index)
return m_nodes[index]->isDependency();
return false;
}
void EffectMakerModel::updateQmlComponent()
void EffectComposerModel::updateQmlComponent()
{
// Clear possible QML runtime errors
resetEffectError(ErrorQMLRuntime);
@@ -1657,11 +1688,11 @@ void EffectMakerModel::updateQmlComponent()
// Removes "file:" from the URL path.
// So e.g. "file:///C:/myimages/steel1.jpg" -> "C:/myimages/steel1.jpg"
QString EffectMakerModel::stripFileFromURL(const QString &urlString) const
QString EffectComposerModel::stripFileFromURL(const QString &urlString) const
{
QUrl url(urlString);
QString filePath = (url.scheme() == QStringLiteral("file")) ? url.toLocalFile() : url.toString();
return filePath;
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -21,7 +21,7 @@ namespace Utils {
class Process;
}
namespace EffectMaker {
namespace EffectComposer {
class CompositionNode;
class Uniform;
@@ -38,7 +38,7 @@ public:
int m_type = -1;
};
class EffectMakerModel : public QAbstractListModel
class EffectComposerModel : public QAbstractListModel
{
Q_OBJECT
@@ -46,11 +46,12 @@ class EffectMakerModel : public QAbstractListModel
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
Q_PROPERTY(bool hasUnsavedChanges MEMBER m_hasUnsavedChanges WRITE setHasUnsavedChanges NOTIFY hasUnsavedChangesChanged)
Q_PROPERTY(bool shadersUpToDate READ shadersUpToDate WRITE setShadersUpToDate NOTIFY shadersUpToDateChanged)
Q_PROPERTY(bool isEnabled READ isEnabled WRITE setIsEnabled NOTIFY isEnabledChanged)
Q_PROPERTY(QString qmlComponentString READ qmlComponentString)
Q_PROPERTY(QString currentComposition READ currentComposition WRITE setCurrentComposition NOTIFY currentCompositionChanged)
public:
EffectMakerModel(QObject *parent = nullptr);
EffectComposerModel(QObject *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
@@ -73,6 +74,9 @@ public:
bool shadersUpToDate() const;
void setShadersUpToDate(bool newShadersUpToDate);
bool isEnabled() const;
void setIsEnabled(bool enabled);
QString fragmentShader() const;
void setFragmentShader(const QString &newFragmentShader);
@@ -105,6 +109,7 @@ signals:
void selectedIndexChanged(int idx);
void effectErrorChanged();
void shadersUpToDateChanged();
void isEnabledChanged();
void shadersBaked();
void currentCompositionChanged();
void nodesChanged();
@@ -143,7 +148,7 @@ private:
QString valueAsString(const Uniform &uniform);
QString valueAsBinding(const Uniform &uniform);
QString valueAsVariable(const Uniform &uniform);
QString getImageElementName(const Uniform &uniform);
QString getImageElementName(const Uniform &uniform, bool localFiles);
const QString getConstVariables();
const QString getDefineProperties();
int getTagIndex(const QStringList &code, const QString &tag);
@@ -201,10 +206,11 @@ private:
QString m_previewEffectPropertiesString;
QString m_qmlComponentString;
bool m_loadComponentImages = true;
bool m_isEnabled = true;
QString m_currentComposition;
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "effectmakernodesmodel.h"
#include "effectcomposernodesmodel.h"
#include "effectutils.h"
#include <utils/filepath.h>
@@ -9,14 +9,14 @@
#include <QCoreApplication>
namespace EffectMaker {
namespace EffectComposer {
EffectMakerNodesModel::EffectMakerNodesModel(QObject *parent)
EffectComposerNodesModel::EffectComposerNodesModel(QObject *parent)
: QAbstractListModel{parent}
{
}
QHash<int, QByteArray> EffectMakerNodesModel::roleNames() const
QHash<int, QByteArray> EffectComposerNodesModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[CategoryNameRole] = "categoryName";
@@ -25,14 +25,14 @@ QHash<int, QByteArray> EffectMakerNodesModel::roleNames() const
return roles;
}
int EffectMakerNodesModel::rowCount(const QModelIndex &parent) const
int EffectComposerNodesModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_categories.count();
}
QVariant EffectMakerNodesModel::data(const QModelIndex &index, int role) const
QVariant EffectComposerNodesModel::data(const QModelIndex &index, int role) const
{
QTC_ASSERT(index.isValid() && index.row() < m_categories.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
@@ -40,7 +40,7 @@ QVariant EffectMakerNodesModel::data(const QModelIndex &index, int role) const
return m_categories.at(index.row())->property(roleNames().value(role));
}
void EffectMakerNodesModel::loadModel()
void EffectComposerNodesModel::loadModel()
{
if (m_modelLoaded)
return;
@@ -86,13 +86,13 @@ void EffectMakerNodesModel::loadModel()
resetModel();
}
void EffectMakerNodesModel::resetModel()
void EffectComposerNodesModel::resetModel()
{
beginResetModel();
endResetModel();
}
void EffectMakerNodesModel::updateCanBeAdded(const QStringList &uniforms)
void EffectComposerNodesModel::updateCanBeAdded(const QStringList &uniforms)
{
for (const EffectNodesCategory *cat : std::as_const(m_categories)) {
const QList<EffectNode *> nodes = cat->nodes();
@@ -108,4 +108,4 @@ void EffectMakerNodesModel::updateCanBeAdded(const QStringList &uniforms)
}
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -7,9 +7,9 @@
#include <QStandardItemModel>
namespace EffectMaker {
namespace EffectComposer {
class EffectMakerNodesModel : public QAbstractListModel
class EffectComposerNodesModel : public QAbstractListModel
{
Q_OBJECT
@@ -19,7 +19,7 @@ class EffectMakerNodesModel : public QAbstractListModel
};
public:
EffectMakerNodesModel(QObject *parent = nullptr);
EffectComposerNodesModel(QObject *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
@@ -40,5 +40,5 @@ private:
bool m_modelLoaded = false;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -0,0 +1,51 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <effectcomposerview.h>
#include <qmldesignerplugin.h>
#include <extensionsystem/iplugin.h>
namespace EffectComposer {
static bool enableEffectComposer()
{
return true;
}
class EffectComposerPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "EffectComposer.json")
public:
EffectComposerPlugin() {}
~EffectComposerPlugin() override {}
bool delayedInitialize() override
{
if (m_delayedInitialized)
return true;
if (enableEffectComposer()) {
auto *designerPlugin = QmlDesigner::QmlDesignerPlugin::instance();
auto &viewManager = designerPlugin->viewManager();
viewManager.registerView(std::make_unique<EffectComposerView>(
QmlDesigner::QmlDesignerPlugin::externalDependenciesForPluginInitializationOnly()));
}
m_delayedInitialized = true;
return true;
}
private:
bool m_delayedInitialized = false;
};
} // namespace EffectComposer
#include "effectcomposerplugin.moc"

View File

@@ -1,21 +1,21 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "effectmakeruniformsmodel.h"
#include "effectcomposeruniformsmodel.h"
#include "propertyhandler.h"
#include "uniform.h"
#include <utils/qtcassert.h>
namespace EffectMaker {
namespace EffectComposer {
EffectMakerUniformsModel::EffectMakerUniformsModel(QObject *parent)
EffectComposerUniformsModel::EffectComposerUniformsModel(QObject *parent)
: QAbstractListModel{parent}
{
}
QHash<int, QByteArray> EffectMakerUniformsModel::roleNames() const
QHash<int, QByteArray> EffectComposerUniformsModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[NameRole] = "uniformName";
@@ -30,14 +30,14 @@ QHash<int, QByteArray> EffectMakerUniformsModel::roleNames() const
return roles;
}
int EffectMakerUniformsModel::rowCount(const QModelIndex &parent) const
int EffectComposerUniformsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_uniforms.size();
}
QVariant EffectMakerUniformsModel::data(const QModelIndex &index, int role) const
QVariant EffectComposerUniformsModel::data(const QModelIndex &index, int role) const
{
QTC_ASSERT(index.isValid() && index.row() < m_uniforms.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
@@ -45,7 +45,7 @@ QVariant EffectMakerUniformsModel::data(const QModelIndex &index, int role) cons
return m_uniforms.at(index.row())->property(roleNames().value(role));
}
bool EffectMakerUniformsModel::setData(const QModelIndex &index, const QVariant &value, int role)
bool EffectComposerUniformsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || !roleNames().contains(role))
return false;
@@ -71,23 +71,23 @@ bool EffectMakerUniformsModel::setData(const QModelIndex &index, const QVariant
return true;
}
void EffectMakerUniformsModel::resetModel()
void EffectComposerUniformsModel::resetModel()
{
beginResetModel();
endResetModel();
}
void EffectMakerUniformsModel::addUniform(Uniform *uniform)
void EffectComposerUniformsModel::addUniform(Uniform *uniform)
{
beginInsertRows({}, m_uniforms.size(), m_uniforms.size());
m_uniforms.append(uniform);
endInsertRows();
}
QList<Uniform *> EffectMakerUniformsModel::uniforms() const
QList<Uniform *> EffectComposerUniformsModel::uniforms() const
{
return m_uniforms;
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -5,16 +5,16 @@
#include <QStandardItemModel>
namespace EffectMaker {
namespace EffectComposer {
class Uniform;
class EffectMakerUniformsModel : public QAbstractListModel
class EffectComposerUniformsModel : public QAbstractListModel
{
Q_OBJECT
public:
EffectMakerUniformsModel(QObject *parent = nullptr);
EffectComposerUniformsModel(QObject *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
@@ -43,5 +43,5 @@ private:
QList<Uniform *> m_uniforms;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -0,0 +1,102 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "effectcomposerview.h"
#include "effectcomposermodel.h"
#include "effectcomposernodesmodel.h"
#include "effectcomposerwidget.h"
#include <designermcumanager.h>
#include <documentmanager.h>
#include <modelnodeoperations.h>
#include <qmldesignerconstants.h>
#include <coreplugin/icore.h>
namespace EffectComposer {
EffectComposerContext::EffectComposerContext(QWidget *widget)
: IContext(widget)
{
setWidget(widget);
setContext(Core::Context(QmlDesigner::Constants::C_QMLEFFECTCOMPOSER,
QmlDesigner::Constants::C_QT_QUICK_TOOLS_MENU));
}
void EffectComposerContext::contextHelp(const HelpCallback &callback) const
{
qobject_cast<EffectComposerWidget *>(m_widget)->contextHelp(callback);
}
EffectComposerView::EffectComposerView(QmlDesigner::ExternalDependenciesInterface &externalDependencies)
: AbstractView{externalDependencies}
{
}
EffectComposerView::~EffectComposerView()
{}
bool EffectComposerView::hasWidget() const
{
return true;
}
QmlDesigner::WidgetInfo EffectComposerView::widgetInfo()
{
if (m_widget.isNull()) {
m_widget = new EffectComposerWidget{this};
connect(m_widget->effectComposerModel(), &EffectComposerModel::assignToSelectedTriggered, this,
[&] (const QString &effectPath) {
executeInTransaction("EffectComposerView::widgetInfo", [&] {
const QList<QmlDesigner::ModelNode> selectedNodes = selectedModelNodes();
for (const QmlDesigner::ModelNode &node : selectedNodes)
QmlDesigner::ModelNodeOperations::handleItemLibraryEffectDrop(effectPath, node);
});
});
auto context = new EffectComposerContext(m_widget.data());
Core::ICore::addContextObject(context);
}
return createWidgetInfo(m_widget.data(), "EffectComposer",
QmlDesigner::WidgetInfo::LeftPane, 0, tr("Effect Composer [beta]"));
}
void EffectComposerView::customNotification([[maybe_unused]] const AbstractView *view,
const QString &identifier,
[[maybe_unused]] const QList<QmlDesigner::ModelNode> &nodeList,
const QList<QVariant> &data)
{
if (identifier == "open_effectcomposer_composition" && data.count() > 0) {
const QString compositionPath = data[0].toString();
m_widget->openComposition(compositionPath);
}
}
void EffectComposerView::modelAttached(QmlDesigner::Model *model)
{
AbstractView::modelAttached(model);
m_widget->effectComposerNodesModel()->loadModel();
QString currProjectPath = QmlDesigner::DocumentManager::currentProjectDirPath().toString();
if (m_currProjectPath != currProjectPath) { // starting a new project
m_widget->effectComposerModel()->clear(true);
m_widget->effectComposerModel()->setIsEnabled(
!QmlDesigner::DesignerMcuManager::instance().isMCUProject());
}
m_currProjectPath = currProjectPath;
m_widget->initView();
}
void EffectComposerView::modelAboutToBeDetached(QmlDesigner::Model *model)
{
AbstractView::modelAboutToBeDetached(model);
}
} // namespace EffectComposer

View File

@@ -9,24 +9,24 @@
#include <QPointer>
namespace EffectMaker {
namespace EffectComposer {
class EffectMakerWidget;
class EffectComposerWidget;
class EffectMakerContext : public Core::IContext
class EffectComposerContext : public Core::IContext
{
Q_OBJECT
public:
EffectMakerContext(QWidget *widget);
EffectComposerContext(QWidget *widget);
void contextHelp(const Core::IContext::HelpCallback &callback) const override;
};
class EffectMakerView : public QmlDesigner::AbstractView
class EffectComposerView : public QmlDesigner::AbstractView
{
public:
EffectMakerView(QmlDesigner::ExternalDependenciesInterface &externalDependencies);
~EffectMakerView() override;
EffectComposerView(QmlDesigner::ExternalDependenciesInterface &externalDependencies);
~EffectComposerView() override;
bool hasWidget() const override;
QmlDesigner::WidgetInfo widgetInfo() override;
@@ -39,7 +39,8 @@ private:
void customNotification(const AbstractView *view, const QString &identifier,
const QList<QmlDesigner::ModelNode> &nodeList, const QList<QVariant> &data) override;
QPointer<EffectMakerWidget> m_widget;
QPointer<EffectComposerWidget> m_widget;
QString m_currProjectPath;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -1,21 +1,21 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "effectmakerwidget.h"
#include "effectcomposerwidget.h"
#include "effectmakercontextobject.h"
#include "effectmakermodel.h"
#include "effectmakernodesmodel.h"
#include "effectmakerview.h"
#include "effectcomposercontextobject.h"
#include "effectcomposermodel.h"
#include "effectcomposernodesmodel.h"
#include "effectcomposerview.h"
#include "effectutils.h"
#include "propertyhandler.h"
//#include "qmldesigner/designercore/imagecache/midsizeimagecacheprovider.h"
#include "qmldesignerconstants.h"
#include "qmldesignerplugin.h"
#include "theme.h"
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include <qmldesigner/documentmanager.h>
#include <qmldesigner/qmldesignerconstants.h>
@@ -35,7 +35,7 @@
#include <QQuickItem>
#include <QTimer>
namespace EffectMaker {
namespace EffectComposer {
static QString propertyEditorResourcesPath()
{
@@ -46,19 +46,19 @@ static QString propertyEditorResourcesPath()
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
EffectMakerWidget::EffectMakerWidget(EffectMakerView *view)
: m_effectMakerModel{new EffectMakerModel(this)}
, m_effectMakerNodesModel{new EffectMakerNodesModel(this)}
, m_effectMakerView(view)
EffectComposerWidget::EffectComposerWidget(EffectComposerView *view)
: m_effectComposerModel{new EffectComposerModel(this)}
, m_effectComposerNodesModel{new EffectComposerNodesModel(this)}
, m_effectComposerView(view)
, m_quickWidget{new StudioQuickWidget(this)}
{
setWindowTitle(tr("Effect Maker", "Title of effect maker widget"));
setWindowTitle(tr("Effect Composer", "Title of effect composer widget"));
setMinimumWidth(250);
m_quickWidget->quickWidget()->installEventFilter(this);
// create the inner widget
m_quickWidget->quickWidget()->setObjectName(QmlDesigner::Constants::OBJECT_NAME_EFFECT_MAKER);
m_quickWidget->quickWidget()->setObjectName(QmlDesigner::Constants::OBJECT_NAME_EFFECT_COMPOSER);
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
QmlDesigner::Theme::setupTheme(m_quickWidget->engine());
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
@@ -74,7 +74,7 @@ EffectMakerWidget::EffectMakerWidget(EffectMakerView *view)
setStyleSheet(QmlDesigner::Theme::replaceCssColors(
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
QmlDesigner::QmlDesignerPlugin::trackWidgetFocusTime(this, QmlDesigner::Constants::EVENT_EFFECTMAKER_TIME);
QmlDesigner::QmlDesignerPlugin::trackWidgetFocusTime(this, QmlDesigner::Constants::EVENT_EFFECTCOMPOSER_TIME);
m_quickWidget->rootContext()->setContextProperty("g_propertyData", &g_propertyData);
@@ -82,23 +82,21 @@ EffectMakerWidget::EffectMakerWidget(EffectMakerView *view)
g_propertyData.insert(QString("blur_vs_path"), QString(blurPath + "bluritems.vert.qsb"));
g_propertyData.insert(QString("blur_fs_path"), QString(blurPath + "bluritems.frag.qsb"));
auto map = m_quickWidget->registerPropertyMap("EffectMakerBackend");
map->setProperties({{"effectMakerNodesModel", QVariant::fromValue(m_effectMakerNodesModel.data())},
{"effectMakerModel", QVariant::fromValue(m_effectMakerModel.data())},
auto map = m_quickWidget->registerPropertyMap("EffectComposerBackend");
map->setProperties({{"effectComposerNodesModel", QVariant::fromValue(m_effectComposerNodesModel.data())},
{"effectComposerModel", QVariant::fromValue(m_effectComposerModel.data())},
{"rootView", QVariant::fromValue(this)}});
QmlDesigner::QmlDesignerPlugin::trackWidgetFocusTime(
this, QmlDesigner::Constants::EVENT_NEWEFFECTMAKER_TIME);
connect(m_effectMakerModel.data(), &EffectMakerModel::nodesChanged, this, [this]() {
m_effectMakerNodesModel->updateCanBeAdded(m_effectMakerModel->uniformNames());
connect(m_effectComposerModel.data(), &EffectComposerModel::nodesChanged, this, [this]() {
m_effectComposerNodesModel->updateCanBeAdded(m_effectComposerModel->uniformNames());
});
connect(m_effectMakerModel.data(), &EffectMakerModel::resourcesSaved,
connect(m_effectComposerModel.data(), &EffectComposerModel::resourcesSaved,
this, [this](const QmlDesigner::TypeName &type, const Utils::FilePath &path) {
if (!m_importScan.timer) {
m_importScan.timer = new QTimer(this);
connect(m_importScan.timer, &QTimer::timeout,
this, &EffectMakerWidget::handleImportScanTimer);
this, &EffectComposerWidget::handleImportScanTimer);
}
if (m_importScan.timer->isActive() && !m_importScan.future.isFinished())
@@ -110,10 +108,27 @@ EffectMakerWidget::EffectMakerWidget(EffectMakerView *view)
m_importScan.timer->start(100);
});
connect(m_effectComposerModel.data(), &EffectComposerModel::hasUnsavedChangesChanged,
this, [this]() {
if (m_effectComposerModel->hasUnsavedChanges() && !m_effectComposerModel->currentComposition().isEmpty()) {
if (auto doc = QmlDesigner::QmlDesignerPlugin::instance()->documentManager().currentDesignDocument())
doc->setModified();
}
});
connect(Core::EditorManager::instance(), &Core::EditorManager::aboutToSave,
this, [this](Core::IDocument *document) {
if (m_effectComposerModel->hasUnsavedChanges()) {
QString compName = m_effectComposerModel->currentComposition();
if (!compName.isEmpty())
m_effectComposerModel->saveComposition(compName);
}
});
}
bool EffectMakerWidget::eventFilter(QObject *obj, QEvent *event)
bool EffectComposerWidget::eventFilter(QObject *obj, QEvent *event)
{
Q_UNUSED(obj)
Q_UNUSED(event)
@@ -123,70 +138,76 @@ bool EffectMakerWidget::eventFilter(QObject *obj, QEvent *event)
return false;
}
void EffectMakerWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
void EffectComposerWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
{
Q_UNUSED(callback)
}
StudioQuickWidget *EffectMakerWidget::quickWidget() const
StudioQuickWidget *EffectComposerWidget::quickWidget() const
{
return m_quickWidget.data();
}
QPointer<EffectMakerModel> EffectMakerWidget::effectMakerModel() const
QPointer<EffectComposerModel> EffectComposerWidget::effectComposerModel() const
{
return m_effectMakerModel;
return m_effectComposerModel;
}
QPointer<EffectMakerNodesModel> EffectMakerWidget::effectMakerNodesModel() const
QPointer<EffectComposerNodesModel> EffectComposerWidget::effectComposerNodesModel() const
{
return m_effectMakerNodesModel;
return m_effectComposerNodesModel;
}
void EffectMakerWidget::addEffectNode(const QString &nodeQenPath)
void EffectComposerWidget::addEffectNode(const QString &nodeQenPath)
{
m_effectMakerModel->addNode(nodeQenPath);
m_effectComposerModel->addNode(nodeQenPath);
if (!nodeQenPath.isEmpty()) {
using namespace QmlDesigner;
QString id = nodeQenPath.split('/').last().chopped(4).prepend('_');
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_EFFECTCOMPOSER_NODE + id);
}
}
void EffectMakerWidget::focusSection(int section)
void EffectComposerWidget::focusSection(int section)
{
Q_UNUSED(section)
}
QRect EffectMakerWidget::screenRect() const
QRect EffectComposerWidget::screenRect() const
{
if (m_quickWidget && m_quickWidget->screen())
return m_quickWidget->screen()->availableGeometry();
return {};
}
QPoint EffectMakerWidget::globalPos(const QPoint &point) const
QPoint EffectComposerWidget::globalPos(const QPoint &point) const
{
if (m_quickWidget)
return m_quickWidget->mapToGlobal(point);
return point;
}
QSize EffectMakerWidget::sizeHint() const
QSize EffectComposerWidget::sizeHint() const
{
return {420, 420};
}
QString EffectMakerWidget::qmlSourcesPath()
QString EffectComposerWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/effectMakerQmlSources";
return QLatin1String(SHARE_QML_PATH) + "/effectComposerQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/effectMakerQmlSources").toString();
return Core::ICore::resourcePath("qmldesigner/effectComposerQmlSources").toString();
}
void EffectMakerWidget::initView()
void EffectComposerWidget::initView()
{
auto ctxObj = new EffectMakerContextObject(m_quickWidget->rootContext());
auto ctxObj = new EffectComposerContextObject(m_quickWidget->rootContext());
m_quickWidget->rootContext()->setContextObject(ctxObj);
m_backendModelNode.setup(m_effectMakerView->rootModelNode());
m_backendModelNode.setup(m_effectComposerView->rootModelNode());
m_quickWidget->rootContext()->setContextProperty("anchorBackend", &m_backendAnchorBinding);
m_quickWidget->rootContext()->setContextProperty("modelNodeBackend", &m_backendModelNode);
m_quickWidget->rootContext()->setContextProperty("activeDragSuffix", "");
@@ -200,29 +221,29 @@ void EffectMakerWidget::initView()
reloadQmlSource();
}
void EffectMakerWidget::openComposition(const QString &path)
void EffectComposerWidget::openComposition(const QString &path)
{
m_compositionPath = path;
if (effectMakerModel()->hasUnsavedChanges())
if (effectComposerModel()->hasUnsavedChanges())
QMetaObject::invokeMethod(quickWidget()->rootObject(), "promptToSaveBeforeOpen");
else
doOpenComposition();
}
void EffectMakerWidget::doOpenComposition()
void EffectComposerWidget::doOpenComposition()
{
effectMakerModel()->openComposition(m_compositionPath);
effectComposerModel()->openComposition(m_compositionPath);
}
void EffectMakerWidget::reloadQmlSource()
void EffectComposerWidget::reloadQmlSource()
{
const QString effectMakerQmlPath = qmlSourcesPath() + "/EffectMaker.qml";
QTC_ASSERT(QFileInfo::exists(effectMakerQmlPath), return);
m_quickWidget->setSource(QUrl::fromLocalFile(effectMakerQmlPath));
const QString effectComposerQmlPath = qmlSourcesPath() + "/EffectComposer.qml";
QTC_ASSERT(QFileInfo::exists(effectComposerQmlPath), return);
m_quickWidget->setSource(QUrl::fromLocalFile(effectComposerQmlPath));
}
void EffectMakerWidget::handleImportScanTimer()
void EffectComposerWidget::handleImportScanTimer()
{
++m_importScan.counter;
@@ -247,24 +268,24 @@ void EffectMakerWidget::handleImportScanTimer()
m_importScan.timer->stop();
m_importScan.counter = 0;
} else if (m_importScan.counter == 101) {
if (m_effectMakerView->model() && m_effectMakerView->model()->rewriterView()) {
if (m_effectComposerView->model() && m_effectComposerView->model()->rewriterView()) {
QmlDesigner::QmlDesignerPlugin::instance()->documentManager().resetPossibleImports();
m_effectMakerView->model()->rewriterView()->forceAmend();
m_effectComposerView->model()->rewriterView()->forceAmend();
}
} else if (m_importScan.counter == 102) {
if (m_effectMakerView->model()) {
if (m_effectComposerView->model()) {
// If type is in use, we have to reset puppet to update 2D view
if (!m_effectMakerView->allModelNodesOfType(
m_effectMakerView->model()->metaInfo(m_importScan.type)).isEmpty()) {
m_effectMakerView->resetPuppet();
if (!m_effectComposerView->allModelNodesOfType(
m_effectComposerView->model()->metaInfo(m_importScan.type)).isEmpty()) {
m_effectComposerView->resetPuppet();
}
}
} else if (m_importScan.counter >= 103) {
// Refresh property view by resetting selection if any selected node is of updated type
if (m_effectMakerView->model() && m_effectMakerView->hasSelectedModelNodes()) {
const auto nodes = m_effectMakerView->selectedModelNodes();
if (m_effectComposerView->model() && m_effectComposerView->hasSelectedModelNodes()) {
const auto nodes = m_effectComposerView->selectedModelNodes();
QmlDesigner::MetaInfoType metaType
= m_effectMakerView->model()->metaInfo(m_importScan.type).type();
= m_effectComposerView->model()->metaInfo(m_importScan.type).type();
bool match = false;
for (const QmlDesigner::ModelNode &node : nodes) {
if (node.metaInfo().type() == metaType) {
@@ -273,8 +294,8 @@ void EffectMakerWidget::handleImportScanTimer()
}
}
if (match) {
m_effectMakerView->clearSelectedModelNodes();
m_effectMakerView->setSelectedModelNodes(nodes);
m_effectComposerView->clearSelectedModelNodes();
m_effectComposerView->setSelectedModelNodes(nodes);
}
}
m_importScan.timer->stop();
@@ -282,5 +303,5 @@ void EffectMakerWidget::handleImportScanTimer()
}
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -3,8 +3,8 @@
#pragma once
#include "qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h"
#include "qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h"
#include <qmldesigner/components/propertyeditor/qmlanchorbindingproxy.h>
#include <qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h>
#include <coreplugin/icontext.h>
@@ -17,19 +17,19 @@ QT_BEGIN_NAMESPACE
class QTimer;
QT_END_NAMESPACE
namespace EffectMaker {
namespace EffectComposer {
class EffectMakerView;
class EffectMakerModel;
class EffectMakerNodesModel;
class EffectComposerView;
class EffectComposerModel;
class EffectComposerNodesModel;
class EffectMakerWidget : public QFrame
class EffectComposerWidget : public QFrame
{
Q_OBJECT
public:
EffectMakerWidget(EffectMakerView *view);
~EffectMakerWidget() = default;
EffectComposerWidget(EffectComposerView *view);
~EffectComposerWidget() = default;
void contextHelp(const Core::IContext::HelpCallback &callback) const;
@@ -42,8 +42,8 @@ public:
void openComposition(const QString &path);
StudioQuickWidget *quickWidget() const;
QPointer<EffectMakerModel> effectMakerModel() const;
QPointer<EffectMakerNodesModel> effectMakerNodesModel() const;
QPointer<EffectComposerModel> effectComposerModel() const;
QPointer<EffectComposerNodesModel> effectComposerNodesModel() const;
Q_INVOKABLE void addEffectNode(const QString &nodeQenPath);
Q_INVOKABLE void focusSection(int section);
@@ -60,9 +60,9 @@ private:
void reloadQmlSource();
void handleImportScanTimer();
QPointer<EffectMakerModel> m_effectMakerModel;
QPointer<EffectMakerNodesModel> m_effectMakerNodesModel;
QPointer<EffectMakerView> m_effectMakerView;
QPointer<EffectComposerModel> m_effectComposerModel;
QPointer<EffectComposerNodesModel> m_effectComposerNodesModel;
QPointer<EffectComposerView> m_effectComposerView;
QPointer<StudioQuickWidget> m_quickWidget;
QmlDesigner::QmlModelNodeProxy m_backendModelNode;
QmlDesigner::QmlAnchorBindingProxy m_backendAnchorBinding;
@@ -79,5 +79,5 @@ private:
QString m_compositionPath;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -8,15 +8,15 @@
#include <QDir>
#include <QFileInfo>
namespace EffectMaker {
namespace EffectComposer {
EffectNode::EffectNode(const QString &qenPath)
: m_qenPath(qenPath)
{
const QFileInfo fileInfo = QFileInfo(qenPath);
m_name = fileInfo.baseName();
QString iconPath = QStringLiteral("%1/icon/%2.svg").arg(fileInfo.absolutePath(), m_name);
QString iconPath = QStringLiteral("%1/icon/%2.svg").arg(fileInfo.absolutePath(),
fileInfo.baseName());
if (!QFileInfo::exists(iconPath)) {
QDir parentDir = QDir(fileInfo.absolutePath());
parentDir.cdUp();
@@ -26,8 +26,11 @@ EffectNode::EffectNode(const QString &qenPath)
m_iconPath = QUrl::fromLocalFile(iconPath);
CompositionNode node({}, qenPath);
const QList<Uniform *> uniforms = node.uniforms();
m_name = node.name();
m_description = node.description();
const QList<Uniform *> uniforms = node.uniforms();
for (const Uniform *uniform : uniforms)
m_uniformNames.insert(uniform->name());
}
@@ -60,5 +63,5 @@ bool EffectNode::hasUniform(const QString &name)
return m_uniformNames.contains(name);
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -7,7 +7,7 @@
#include <QSet>
#include <QUrl>
namespace EffectMaker {
namespace EffectComposer {
class EffectNode : public QObject
{
@@ -42,5 +42,5 @@ private:
QSet<QString> m_uniformNames;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -3,7 +3,7 @@
#include "effectnodescategory.h"
namespace EffectMaker {
namespace EffectComposer {
EffectNodesCategory::EffectNodesCategory(const QString &name, const QList<EffectNode *> &nodes)
: m_name(name),
@@ -19,5 +19,5 @@ QList<EffectNode *> EffectNodesCategory::nodes() const
return m_categoryNodes;
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -7,7 +7,7 @@
#include <QObject>
namespace EffectMaker {
namespace EffectComposer {
class EffectNodesCategory : public QObject
{
@@ -27,5 +27,5 @@ private:
QList<EffectNode *> m_categoryNodes;
};
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -7,7 +7,7 @@
#include <QJsonArray>
namespace EffectMaker {
namespace EffectComposer {
QString EffectUtils::codeFromJsonArray(const QJsonArray &codeArray)
{
@@ -26,10 +26,9 @@ QString EffectUtils::nodesSourcesPath()
{
#ifdef SHARE_QML_PATH
if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/effectMakerNodes";
return QLatin1String(SHARE_QML_PATH) + "/effectComposerNodes";
#endif
return Core::ICore::resourcePath("qmldesigner/effectMakerNodes").toString();
return Core::ICore::resourcePath("qmldesigner/effectComposerNodes").toString();
}
} // namespace EffectMaker
} // namespace EffectComposer

View File

@@ -7,7 +7,7 @@
QT_FORWARD_DECLARE_CLASS(QJsonArray)
namespace EffectMaker {
namespace EffectComposer {
class EffectUtils
{
@@ -19,5 +19,5 @@ public:
static QString nodesSourcesPath();
};
} // namespace EffectMaker
} // namespace EffectComposer

Some files were not shown because too many files have changed in this diff Show More