Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7cd45c7
[GraphEditor] Took out Slider Component
Aug 6, 2026
f1103bc
[GraphEditor] Took out notComputed Component
Aug 6, 2026
38e0b37
[GraphEditor] Took out PushButton Component
Aug 6, 2026
87bf13b
[GraphEditor] Took out TextField Component
Aug 6, 2026
4868df8
[GraphEditor] Took out TextArea Component
Aug 6, 2026
48fd621
[GraphEditor] Took out Color Component
Aug 6, 2026
9f4ba8e
[GraphEditor] Took out CheckBox Component
Aug 6, 2026
ccbdb9a
[GraphEditor] Adding the checkBox qml file
Aug 6, 2026
170209f
[GraphEditor] Fixed setTextFieldAttribute errors
Aug 7, 2026
6681381
[GraphEditor] Took out ColorHue Component
Aug 7, 2026
d308ab4
[GraphEditor] Made checkbox component agnostic
Aug 7, 2026
e5b7a00
[GraphEditor] Renamed checkBox signal
Aug 7, 2026
f170b8a
[GraphEditor] Color attribute changes
Aug 11, 2026
3c33233
[GraphEditor] Made color component agnostic
Aug 11, 2026
0cfa641
[GraphEditor] Renamed components to avoid confusion with Qt.Controls …
Aug 12, 2026
8d6557b
[GraphEditor] Made colorhue component agnostic
Aug 12, 2026
acbfa9d
[GraphEditor] Added a whitespace between the braces and the identifier
Aug 18, 2026
96b9908
[GraphEditor] Removed attribute properties in the components
Aug 12, 2026
d896603
[GraphEditor] Implemented ternary operator logic directly inside keye…
Aug 12, 2026
42e1518
[GraphEditor] Restored root.attribute calls inside setTextFieldAttribute
Aug 12, 2026
7ae0a07
[GraphEditor] Removed the pushbutton separated component
Aug 13, 2026
3d8549b
[GraphEditor] Fixed textComponents errors, and added backup values to…
Aug 14, 2026
c64e6f5
[GraphEditor] Externalised texfield toggle logic, and slider also han…
Aug 14, 2026
0ccb365
[GraphEditor] Fixed invalid number of arguments in setTextFieldAttribute
Aug 14, 2026
3d0f222
[GraphEditor] Changed variable name inside CheckBoxRow.qml
raphaelKoskas Aug 18, 2026
27772a9
[GraphEditor] Changed variable name inside SliderField.qml
Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions meshroom/ui/qml/GraphEditor/AttributeControls/CheckBoxRow.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import QtQuick
import QtQuick.Controls

Row {
id: root
property bool editable
property var checked
signal toggled()
CheckBox {
enabled: root.editable
checked: root.checked
onToggled: {
root.toggled()
}
}
}
66 changes: 66 additions & 0 deletions meshroom/ui/qml/GraphEditor/AttributeControls/Color.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs

RowLayout {
id: root
required property var value
property bool editable
property string previousColor: ""
signal clicked(var checked, var previousColor, var colorTextValue)
signal editingFinished(var text)
signal accepted(var text)
signal destruction(bool activeFocus, var text)
CheckBox {
id: colorCheckbox
Layout.alignment: Qt.AlignLeft
checked: root.value === "" ? false : true
checkable: root.editable
text: "Custom Color"
onClicked: {
root.clicked(checked, previousColor, colorText.text)

}
}
TextField {
id: colorText
Layout.alignment: Qt.AlignLeft
implicitWidth: 100
enabled: colorCheckbox.checked && root.editable
visible: colorCheckbox.checked
text: colorCheckbox.checked ? root.value : ""
selectByMouse: true
onEditingFinished: root.editingFinished( text)
onAccepted: root.accepted(text)
Component.onDestruction: root.destruction(activeFocus, text)
}
Rectangle {
height: colorText.height
width: colorText.width / 2
Layout.alignment: Qt.AlignLeft
visible: colorCheckbox.checked
color: colorCheckbox.checked ? colorDialog.selectedColor : ""
MouseArea {
enabled: root.editable
anchors.fill: parent
onClicked: colorDialog.open()
}
}
ColorDialog {
id: colorDialog
title: "Please choose a color"
selectedColor: colorText.text
onAccepted: {
colorText.text = colorDialog.selectedColor
// Artificially trigger change of value
colorText.editingFinished()
close()
}
onRejected: close()
}
Item {
// Dummy item to fill out the space if needed
Layout.fillWidth: true
}
}
51 changes: 51 additions & 0 deletions meshroom/ui/qml/GraphEditor/AttributeControls/ColorHue.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

RowLayout {
id: root
required property var value
property bool editable
signal editingFinished(var text)
signal accepted(var text)
signal destruction(bool activeFocus, var text)
signal pressedChanged(bool pressed, var formattedValue)
TextField {
implicitWidth: 100
enabled: root.editable
// Cast value to string to avoid intrusive scientific notations on numbers
property string displayValue: String(slider.pressed ? slider.formattedValue : root.value)
text: displayValue
selectByMouse: true
validator: DoubleValidator {
locale: 'C' // Use '.' decimal separator disregarding the system locale
}
onEditingFinished: root.editingFinished(text)
onAccepted: root.accepted(text)
Component.onDestruction: root.destruction(activeFocus, text)
}
Rectangle {
height: slider.height
width: height
color: Qt.hsla(slider.pressed ? slider.formattedValue : root.value, 1, 0.5, 1)
}
Slider {
id: slider
Layout.fillWidth: true
readonly property int stepDecimalCount: 2
readonly property real formattedValue: value.toFixed(stepDecimalCount)
enabled: root.editable
value: root.value
from: 0
to: 1
stepSize: 0.01
snapMode: Slider.SnapAlways
onPressedChanged: root.pressedChanged(pressed, formattedValue)
background: ShaderEffect {
width: slider.availableWidth
height: slider.availableHeight
blending: false
fragmentShader: "qrc:/shaders/AttributeItemDelegate.frag.qsb"
}
}
}
16 changes: 16 additions & 0 deletions meshroom/ui/qml/GraphEditor/AttributeControls/NotComputed.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import QtQuick
import MaterialIcons

MaterialLabel {
anchors.fill: parent
text: MaterialIcons.do_not_disturb_alt
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
padding: 4
background: Rectangle {
anchors.fill: parent
border.width: 0
radius: 20
color: Qt.darker(palette.window, 1.1)
}
}
69 changes: 69 additions & 0 deletions meshroom/ui/qml/GraphEditor/AttributeControls/SliderField.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

import Utils

RowLayout {
id: root
required property var checked
required property var type
required property int length
required property int start
required property int end
required property int step
property bool editable
signal editingFinished(bool hasExprError, var evaluatedValue, var text, var displayValue)
signal accepted(bool hasExprError, var evaluatedValue, var text, var displayValue)
signal destruction(bool activeFocus, bool hasExprError, var text)
signal pressedChanged(bool pressed, var formattedValue)
ExpressionTextField {
id: expressionTextField
implicitWidth: 100
Layout.fillWidth: !slider.active
enabled: root.editable
// Cast value to string to avoid intrusive scientific notations on numbers
property string displayValue: String(slider.active && slider.item.pressed ? slider.item.formattedValue : checked)
text: displayValue
selectByMouse: true
// Note: Use autoScroll as a workaround for alignment
// When the value change keep the text align to the left to be able to read the most important part
// of the number. When we are editing (item is in focus), the content should follow the editing.
autoScroll: activeFocus
isInt: root.type === "FloatParam" ? false : true
onEditingFinished: root.editingFinished(hasExprError, expressionTextField.evaluatedValue, expressionTextField.text, expressionTextField.displayValue)
background: Rectangle {
border.color: errorMessages.length ? "orange" : "transparent"
color: Qt.darker(palette.window, 1.2)
radius: 2
}
onAccepted: {
root.accepted(hasExprError, expressionTextField.evaluatedValue, expressionTextField.text, expressionTextField.displayValue)
// When the text is too long, display the left part
// (with the most important values and cut the floating point details)
ensureVisible(0)
}
Component.onDestruction: root.destruction(activeFocus, hasExprError, expressionTextField.evaluatedValue)
Component.onCompleted: {
// When the text is too long, display the left part
// (with the most important values and cut the floating point details)
ensureVisible(0)
}
}
Loader {
id: slider
Layout.fillWidth: true
active: root.length === 3
sourceComponent: Slider {
readonly property int stepDecimalCount: stepSize < 1 ? String(stepSize).split(".").pop().length : 0
readonly property real formattedValue: value.toFixed(stepDecimalCount)
enabled: root.editable
value: root.checked
from: root.start
to: root.end
stepSize: root.step
snapMode: Slider.SnapAlways
onPressedChanged: root.pressedChanged(pressed, formattedValue)
}
}
}
51 changes: 51 additions & 0 deletions meshroom/ui/qml/GraphEditor/AttributeControls/TextAreaFlick.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import QtQuick
import QtQuick.Controls

import Controls

Rectangle {
id: root
required property string label
property bool isLarge
property bool editable
signal editingFinished(var text)
signal destruction(bool activeFocus, var text)
signal dropped(bool hasUrls, bool hasText, var urlText, var text)
// Fixed background for the flickable object
color: palette.base
width: parent.width
height: root.isLarge ? 400 : 70
Flickable {
width: parent.width
height: parent.height
contentWidth: width
contentHeight: height
ScrollBar.vertical: MScrollBar {}
TextArea.flickable: TextArea {
wrapMode: Text.WordWrap
padding: 0
rightPadding: 5
bottomPadding: 2
topPadding: 2
readOnly: !root.editable
onEditingFinished: root.editingFinished(text)
text: root.label
selectByMouse: true
background: Rectangle {
visible: errorMessages.length
border.color: "orange"
color: "transparent"
radius: 2
}
onPressed: {
root.forceActiveFocus()
}
Component.onDestruction: root.destruction(activeFocus, text)
DropArea {
enabled: root.editable
anchors.fill: parent
onDropped: (drop) => root.dropped(drop.hasUrls, drop.hasText && drop.text != '', Filepath.urlToString(drop.urls[0]), drop.text)
}
}
}
}
115 changes: 115 additions & 0 deletions meshroom/ui/qml/GraphEditor/AttributeControls/TextFieldRow.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

RowLayout {
id: root
required property string text
required property bool mandatory
required property var attribute
property bool editable
signal editingFinished(var text)
signal accepted(var parameterLabel, var text)
signal destruction(bool activeFocus, var text)
signal dropped(bool hasUrls, bool hasText, var urlText, var text)
signal triggered(var text, int start, int end, int length, var clipboard)
anchors.fill: parent
TextField {
id: textField
Layout.fillWidth: true
readOnly: !root.editable
text: root.text
placeholderText: root.mandatory ? "This field is required" : ""
placeholderTextColor: "gray"
// Don't disable the component to keep interactive features (text selection, context menu...).
// Only override the look by using the Disabled palette.
SystemPalette {
id: disabledPalette
colorGroup: SystemPalette.Disabled
}
background: Rectangle {
border.color: errorMessages.length ? "orange" : "transparent"
color: Qt.darker(palette.window, 1.2)
radius: 2
}
states: [
State {
when: readOnly
PropertyChanges {
target: textField
color: disabledPalette.text
}
}
]
selectByMouse: true
persistentSelection: false
onEditingFinished: root.editingFinished(text)

onAccepted: root.accepted(parameterLabel, text)
Keys.onPressed: function(event) {
if ((event.key == Qt.Key_Escape)) {
event.accepted = true
parameterLabel.forceActiveFocus()
}
}
Component.onDestruction: root.destruction(activeFocus, text)
DropArea {
enabled: root.editable
anchors.fill: parent
onDropped: (drop) => root.dropped(drop.hasUrls, drop.hasText && drop.text != '', Filepath.urlToString(drop.urls[0]), drop.text)
}
onPressed: (event) => {
if (event.button == Qt.RightButton) {
// Keep selection persistent while context menu is open to
// visualize what is being copied or what will be replaced on paste.
persistentSelection = true
const menu = textFieldMenuComponent.createObject(textField)
menu.popup()
if (selectedText === "") {
cursorPosition = positionAt(event.x, event.y)
}
}
}
Component {
id: textFieldMenuComponent
Menu {
onOpened: {
// Keep cursor visible to see where pasting would happen.
textField.cursorVisible = true
}
onClosed: {
// Disable selection persistency behavior once menu is closed and
// give focus back to the parent TextField.
textField.persistentSelection = false
textField.forceActiveFocus()
destroy()
}
MenuItem {
text: "Copy"
enabled: root.text != ""
onTriggered: {
const hasSelection = textField.selectionStart !== textField.selectionEnd
if (hasSelection) {
// Use `TextField.copy` to copy only the current selection.
textField.copy()
}
else {
Clipboard.setText(root.text)
}
}
}
MenuItem {
text: "Paste"
enabled: !readOnly
onTriggered: {
const clipboardText = Clipboard.getText()
if (clipboardText.length === 0) {
return
}
triggered(textField.text, textField.selectionStart, textField.selectionEnd, textField.text.length, clipboardText)
}
}
}
}
}
}
Loading