Skip to content

Feature/table view#3142

Draft
raphaelKoskas wants to merge 2 commits into
developfrom
feature/tableView
Draft

Feature/table view#3142
raphaelKoskas wants to merge 2 commits into
developfrom
feature/tableView

Conversation

@raphaelKoskas

Copy link
Copy Markdown

Description

Features list

  • Added the tableViewAttributeComponent
  • Added the listAttributeComponent/tableViewAttributeComponent switch, in the case of listAttribtes of groupsAttributes

Implementation remarks

We use repeaters instead of a real tableview as tablemodel does not seem to support dynamic layout generation.

We use repeaters instead of a real tableview as tablemodel does not seem to support dynamic layout generation.
@raphaelKoskas raphaelKoskas added this to the Meshroom 2026.1.0 milestone Jun 19, 2026
@raphaelKoskas raphaelKoskas self-assigned this Jun 19, 2026
@raphaelKoskas raphaelKoskas added the feature new feature (proposed as PR or issue planned by dev) label Jun 19, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new tableViewAttributeComponent in AttributeItemDelegate.qml to render list attributes of type GroupAttribute as a table. The reviewer provided valuable feedback, identifying that directly setting cell values bypasses Meshroom's scene management and undo/redo stack, and that resizing columns and rows using local coordinates on moving MouseArea elements causes feedback loops and jitter. Additionally, the reviewer suggested replacing the manual scrollbar implementation with a Flickable component to support native scrolling features.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +1026 to +1043
TextInput {
id: cellInput
anchors.fill: parent
anchors.margins: 4
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: TextInput.AlignHCenter
color: "#aaaaaa"
selectionColor: "#5599ff"
clip: true
text: {
var cell = rowItem.object.value.at(index)
return cell ? String(cell.value) : ""
}
onEditingFinished: {
var cell = rowItem.object.value.at(cellRect.index)
if (cell) cell.value = text
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Directly setting cell.value = text bypasses Meshroom's scene management and undo/redo stack (_currentScene). This can lead to desynchronization between the UI and the underlying Python graph/history. Additionally, values for numeric parameters (IntParam, FloatParam) should be converted to numbers.

We can also optimize the text binding by declaring cell as a property of the TextInput to make the dependency explicit and avoid block bindings.

                                                    TextInput {
                                                        id: cellInput
                                                        property var cell: rowItem.object.value.at(index)
                                                        anchors.fill: parent
                                                        anchors.margins: 4
                                                        verticalAlignment: TextInput.AlignVCenter
                                                        horizontalAlignment: TextInput.AlignHCenter
                                                        color: "#aaaaaa"
                                                        selectionColor: "#5599ff"
                                                        clip: true
                                                        text: cell ? String(cell.value) : ""
                                                        onEditingFinished: {
                                                            if (cell) {
                                                                var val = text
                                                                if (cell.type === "IntParam" || cell.type === "FloatParam") {
                                                                    val = Number(text)
                                                                }
                                                                _currentScene.setAttribute(cell, val)
                                                            }
                                                        }
                                                    }

Comment on lines +977 to +995
MouseArea {
width: 6
height: parent.height
anchors.right: parent.right
cursorShape: Qt.SizeHorCursor
property real startX: 0
property real startW: 0
onPressed: function(mouse) {
startX = mouse.x
startW = tableLayout.columnWidths[headerCell.index]
}
onPositionChanged: function(mouse) {
if (!pressed) return
var newW = Math.max(40, startW + (mouse.x - startX))
var arr = tableLayout.columnWidths.slice()
arr[headerCell.index] = newW
tableLayout.columnWidths = arr
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Resizing columns using local coordinates (mouse.x) on a MouseArea that moves as a result of the resize causes a feedback loop. When the column width increases, the MouseArea shifts to the right, which immediately decreases the local mouse.x coordinate, leading to severe jitter and unstable dragging.

To fix this, map the mouse coordinates to a stable parent coordinate space (like tableLayout) that does not shift during resizing.

                                        MouseArea {
                                            width: 6
                                            height: parent.height
                                            anchors.right: parent.right
                                            cursorShape: Qt.SizeHorCursor
                                            property real startX: 0
                                            property real startW: 0
                                            onPressed: function(mouse) {
                                                var stablePoint = mapToItem(tableLayout, mouse.x, mouse.y)
                                                startX = stablePoint.x
                                                startW = tableLayout.columnWidths[headerCell.index]
                                            }
                                            onPositionChanged: function(mouse) {
                                                if (!pressed) return
                                                var stablePoint = mapToItem(tableLayout, mouse.x, mouse.y)
                                                var newW = Math.max(40, startW + (stablePoint.x - startX))
                                                var arr  = tableLayout.columnWidths.slice()
                                                arr[headerCell.index] = newW
                                                tableLayout.columnWidths = arr
                                            }
                                        }

Comment on lines +1047 to +1065
MouseArea {
width: parent.width
height: 6
anchors.bottom: parent.bottom
cursorShape: Qt.SizeVerCursor
property real startY: 0
property real startH: 0
onPressed: function(mouse) {
startY = mouse.y
startH = tableLayout.rowHeights[rowItem.index]
}
onPositionChanged: function(mouse) {
if (!pressed) return
var newH = Math.max(20, startH + (mouse.y - startY))
var arr = tableLayout.rowHeights.slice()
arr[rowItem.index] = newH
tableLayout.rowHeights = arr
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the column resizing issue, resizing row heights using local coordinates (mouse.y) on a MouseArea anchored to the bottom of the row causes a feedback loop and jitter. As the row height increases, the MouseArea moves down, shifting the local mouse.y coordinate.

Map the coordinates to the stable tableLayout item to ensure smooth dragging.

                                        MouseArea {
                                            width:  parent.width
                                            height: 6
                                            anchors.bottom: parent.bottom
                                            cursorShape: Qt.SizeVerCursor
                                            property real startY: 0
                                            property real startH: 0
                                            onPressed: function(mouse) {
                                                var stablePoint = mapToItem(tableLayout, mouse.x, mouse.y)
                                                startY = stablePoint.y
                                                startH = tableLayout.rowHeights[rowItem.index]
                                            }
                                            onPositionChanged: function(mouse) {
                                                if (!pressed) return
                                                var stablePoint = mapToItem(tableLayout, mouse.x, mouse.y)
                                                var newH = Math.max(20, startH + (stablePoint.y - startY))
                                                var arr  = tableLayout.rowHeights.slice()
                                                arr[rowItem.index] = newH
                                                tableLayout.rowHeights = arr
                                            }
                                        }

Comment on lines +910 to +950
Item {
id: outerFrame
Layout.fillWidth: true
Layout.preferredHeight: Math.min(tableLayout.totalTableHeight + 30, 330)
ScrollBar {
id: hBar
orientation: Qt.Horizontal
anchors.left: outerFrame.left
anchors.right: outerFrame.right
anchors.bottom: outerFrame.bottom
anchors.rightMargin: vBar.width
policy: ScrollBar.AlwaysOn
size: (outerFrame.width - vBar.width) /
Math.max(tableLayout.totalTableWidth, 1)
}
ScrollBar {
id: vBar
orientation: Qt.Vertical
anchors.top: outerFrame.top
anchors.bottom: outerFrame.bottom
anchors.right: outerFrame.right
anchors.bottomMargin: hBar.height
policy: ScrollBar.AlwaysOn
size: (outerFrame.height - hBar.height) /
Math.max(tableLayout.totalTableHeight + 30, 1)
}
Item {
id: viewport
anchors.left: outerFrame.left
anchors.top: outerFrame.top
anchors.right: outerFrame.right
anchors.bottom: outerFrame.bottom
anchors.rightMargin: vBar.width
anchors.bottomMargin: hBar.height
clip: true
Item {
id: content
width: tableLayout.totalTableWidth
height: tableLayout.totalTableHeight + 30
x: -hBar.position * tableLayout.totalTableWidth
y: -vBar.position * (tableLayout.totalTableHeight + 30)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current manual scrollbar implementation binds x and y coordinates of a plain Item to the scrollbar positions. This approach lacks native scrolling features such as mouse wheel scrolling, trackpad panning, keyboard navigation, and kinetic flicking.

Using a Flickable instead of a plain Item viewport allows you to get all these native features for free, while still keeping the scrollbars positioned exactly where they are.

                Item {
                    id: outerFrame
                    Layout.fillWidth: true
                    Layout.preferredHeight: Math.min(tableLayout.totalTableHeight + 30, 330)
                    Flickable {
                        id: flickable
                        anchors.left:   outerFrame.left
                        anchors.top:    outerFrame.top
                        anchors.right:  outerFrame.right
                        anchors.bottom: outerFrame.bottom
                        anchors.rightMargin:  vBar.width
                        anchors.bottomMargin: hBar.height
                        clip: true
                        contentWidth:  tableLayout.totalTableWidth
                        contentHeight: tableLayout.totalTableHeight + 30
                        ScrollBar.horizontal: ScrollBar {
                            id: hBar
                            parent: outerFrame
                            anchors.left:   outerFrame.left
                            anchors.right:  outerFrame.right
                            anchors.bottom: outerFrame.bottom
                            anchors.rightMargin: vBar.width
                            policy: ScrollBar.AlwaysOn
                        }
                        ScrollBar.vertical: ScrollBar {
                            id: vBar
                            parent: outerFrame
                            anchors.top:    outerFrame.top
                            anchors.bottom: outerFrame.bottom
                            anchors.right:  outerFrame.right
                            anchors.bottomMargin: hBar.height
                            policy: ScrollBar.AlwaysOn
                        }
                        Item {
                            id: content
                            width:  tableLayout.totalTableWidth
                            height: tableLayout.totalTableHeight + 30

@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.35%. Comparing base (69493f5) to head (0340d3a).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3142   +/-   ##
========================================
  Coverage    85.35%   85.35%           
========================================
  Files           73       73           
  Lines        11453    11453           
========================================
  Hits          9776     9776           
  Misses        1677     1677           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cbentejac cbentejac marked this pull request as draft June 24, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature new feature (proposed as PR or issue planned by dev)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant