Welcome to mirror list, hosted at ThFree Co, Russian Federation.

TableView.qml « qml « resources - github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5e0b863f5a77b85d11d33021449027a6ceefcc1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//Copyright (C) 2022 Ultimaker B.V.
//Cura is released under the terms of the LGPLv3 or higher.

import Qt.labs.qmlmodels 1.0
import QtQuick 2.15
import QtQuick.Controls 2.15

import UM 1.5 as UM

/*
 * A re-sizeable table of data.
 *
 * This table combines a list of headers with a TableView to show certain roles in a table.
 * The columns of the table can be resized.
 * When the table becomes too big, you can scroll through the table. When a column becomes too small, the contents of
 * the table are elided.
 * The table gets Cura's themeing.
 */
Item
{
    id: tableBase

    required property var columnHeaders //The text to show in the headers of each column.
    property alias model: tableView.model //A TableModel to display in this table. To use a ListModel for the rows, use "rows: listModel.items"
    property int currentRow: -1 //The selected row index.
    property var onDoubleClicked: function(row) {} //Something to execute when double clicked. Accepts one argument: The index of the row that was clicked on.
    property bool allowSelection: true //Whether to allow the user to select items.
    property string sectionRole: ""

    property alias flickableDirection: tableView.flickableDirection
    Row
    {
        id: headerBar
        Repeater
        {
            id: headerRepeater
            model: columnHeaders
            Rectangle
            {
                width: Math.max(1, Math.round(tableBase.width / headerRepeater.count))
                height: UM.Theme.getSize("section").height

                color: UM.Theme.getColor("main_background")
                border.width: UM.Theme.getSize("default_lining").width
                border.color: UM.Theme.getColor("thick_lining")

                UM.Label
                {
                    id: contentText
                    anchors.left: parent.left
                    anchors.leftMargin: UM.Theme.getSize("default_margin").width
                    anchors.right: parent.right
                    anchors.rightMargin: UM.Theme.getSize("narrow_margin").width
                    wrapMode: Text.NoWrap
                    text: modelData
                    font: UM.Theme.getFont("medium_bold")
                    elide: Text.ElideRight
                }
                Item //Resize handle.
                {
                    anchors
                    {
                        right: parent.right
                        top: parent.top
                        bottom: parent.bottom
                    }
                    width: UM.Theme.getSize("default_lining").width

                    MouseArea
                    {
                        anchors.fill: parent

                        cursorShape: Qt.SizeHorCursor
                        drag
                        {
                            target: parent
                            axis: Drag.XAxis
                        }
                        onMouseXChanged:
                        {
                            if(drag.active)
                            {
                                let new_width = parent.parent.width + mouseX;
                                let sum_widths = mouseX;
                                for(let i = 0; i < headerBar.children.length; ++i)
                                {
                                    sum_widths += headerBar.children[i].width;
                                }
                                if(sum_widths > tableBase.width)
                                {
                                    new_width -= sum_widths - tableBase.width; //Limit the total width to not exceed the view.
                                }
                                let width_fraction = new_width / tableBase.width; //Scale with the same fraction along with the total width, if the table is resized.
                                parent.parent.width = Qt.binding(function() { return Math.max(10, Math.round(tableBase.width * width_fraction)) });
                            }
                        }
                    }
                }

                onWidthChanged: tableView.forceLayout(); //Rescale table cells underneath as well.
            }
        }
    }
    Rectangle
    {
        color: UM.Theme.getColor("main_background")
        anchors
        {
            top: headerBar.bottom
            topMargin: -UM.Theme.getSize("default_lining").width
            left: parent.left
            right: parent.right
            bottom: parent.bottom
        }
        border.width: UM.Theme.getSize("default_lining").width
        border.color: UM.Theme.getColor("thick_lining")
    }

    TableView
    {
        id: tableView
        anchors
        {
            top: headerBar.bottom
            left: parent.left
            right: parent.right
            bottom: parent.bottom
            margins: UM.Theme.getSize("default_lining").width
        }

        flickableDirection: Flickable.AutoFlickIfNeeded
        contentWidth: -1 // AUto calculate the contendWidth
        clip: true
        ScrollBar.vertical: UM.ScrollBar {}
        columnWidthProvider: function(column)
        {
            return headerBar.children[column].width; //Cells get the same width as their column header.
        }

        delegate: Rectangle
        {
            implicitHeight: Math.max(1, cellContent.height)

            color: UM.Theme.getColor((tableBase.currentRow == row) ? "text_selection" : "main_background")

            UM.Label
            {
                id: cellContent
                anchors
                {
                    left: parent.left
                    leftMargin: UM.Theme.getSize("default_margin").width
                    right: parent.right
                }
                wrapMode: Text.NoWrap
                text: display
                verticalAlignment: Text.AlignVCenter
                elide: Text.ElideRight
            }
            TextMetrics
            {
                id: cellTextMetrics
                text: cellContent.text
                font: cellContent.font
                elide: cellContent.elide
                elideWidth: cellContent.width
            }
            UM.TooltipArea
            {
                anchors.fill: parent

                acceptedButtons: Qt.LeftButton
                text: (cellTextMetrics.elidedText == cellContent.text) ? "" : cellContent.text //Show full text in tooltip if it was elided.
                onClicked:
                {
                    if(tableBase.allowSelection)
                    {
                        tableBase.currentRow = row; //Select this row.
                    }
                }
                onDoubleClicked:
                {
                    tableBase.onDoubleClicked(row);
                }
            }
        }

        Connections
        {
            target: model
            function onRowCountChanged()
            {
                tableView.contentY = 0; //When the number of rows is reduced, make sure to scroll back to the start.
            }
        }
    }

    Connections
    {
        target: model
        function onRowsChanged()
        {
            let first_column = model.columns[0].display;
            if(model.rows.length > 0 && model.rows[0][first_column].startsWith("<b>")) //First item is already a section header.
            {
                return; //Assume we already added section headers. Prevent infinite recursion.
            }
            if(sectionRole === "" || model.rows.length == 0) //No section headers, or no items at all.
            {
                tableView.model.rows = model.rows;
                return;
            }

            //Insert section headers in the rows.
            let last_section = "";
            let new_rows = [];
            for(let i = 0; i < model.rows.length; ++i)
            {
                let item_section = model.rows[i][sectionRole];
                if(item_section !== last_section) //Starting a new section.
                {
                    let section_header = {};
                    for(let key in model.rows[i])
                    {
                        section_header[key] = (key === first_column) ? "<b>" + item_section + "</b>" : ""; //Put the section header in the first column.
                    }
                    new_rows.push(section_header); //Add a row representing a section header.
                    last_section = item_section;
                }
                new_rows.push(model.rows[i]);
            }
            tableView.model.rows = new_rows;
        }
    }
}