Warning, /plasma/plasma-systemmonitor/src/table/BaseTableView.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 import QtQuick 2.12 0008 import QtQuick.Controls 2.12 0009 import QtQuick.Layouts 1.12 0010 import QtQml.Models 2.12 0011 0012 import org.kde.kirigami 2.2 as Kirigami 0013 import org.kde.ksysguard.table 1.0 as Table 0014 0015 FocusScope { 0016 id: root 0017 0018 property var model 0019 property alias delegate: tableView.delegate 0020 0021 property alias headerModel: heading.sourceModel 0022 0023 property alias sortColumn: heading.sortColumn 0024 property alias sortOrder: heading.sortOrder 0025 property alias sortName: heading.sortName 0026 property alias idRole: heading.idRole 0027 0028 // Column widths in fractions of the entire view width 0029 // Since column sizes are relative to a given view width, the widths of individual 0030 // columns need to be expressed as a fraction of the entire width. columnWidths 0031 // and defaultColumnWidth both store these fractions. Note that minimumColumnWidth 0032 // is expressed as a pixel value since we do not want that to scale with view width. 0033 property var columnWidths: [] 0034 property real defaultColumnWidth: 0.1 0035 property real minimumColumnWidth: Kirigami.Units.gridUnit * 4 0036 property real rowHeight: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2 0037 0038 readonly property alias headerHeight: heading.height 0039 0040 readonly property alias selection: tableView.selectionModel 0041 readonly property alias rows: tableView.rows 0042 readonly property alias columns: tableView.columns 0043 0044 signal contextMenuRequested(var index, point position) 0045 signal headerContextMenuRequested(int column, point position) 0046 signal sort(int column, int order) 0047 0048 Layout.minimumHeight: heading.height + root.rowHeight * 3 0049 0050 clip: true 0051 0052 function setColumnWidth(index, width) { 0053 if (index < 0 || index >= tableView.columns || width < minimumColumnWidth) { 0054 return 0055 } 0056 0057 while (index >= columnWidths.length) { 0058 columnWidths.push(defaultColumnWidth) 0059 } 0060 0061 columnWidths[index] = width / scrollView.innerWidth 0062 columnWidthsChanged(); 0063 } 0064 0065 // This is a workaround for a small memory leak in QQmlPropertyCache. 0066 // When using Connection {} in combination with 0067 // QAbstractItemModel::layoutChanged() from within QML, 0068 // QQmlPropertyCache::createArgumentsObject() will leak. As a workaround, we 0069 // can put a proxy signal in between that is used instead and the leak won't 0070 // happen. 0071 // TODO KF6: Remove this as the bug doesn't exist in Qt 6. 0072 function onModelLayoutChanged() { 0073 tableView.modelLayoutHasChanged() 0074 } 0075 0076 onColumnWidthsChanged: tableView.forceLayout() 0077 0078 Kirigami.Theme.inherit: false 0079 Kirigami.Theme.colorSet: Kirigami.Theme.View 0080 0081 TableViewHeader { 0082 id: heading 0083 0084 view: tableView 0085 0086 width: scrollView.width 0087 onSort: root.sort(column, order) 0088 0089 onResize: root.setColumnWidth(column, width) 0090 0091 onContextMenuRequested: root.headerContextMenuRequested(column, position) 0092 0093 } 0094 0095 ScrollView { 0096 id: scrollView 0097 anchors.fill: parent 0098 anchors.topMargin: heading.height 0099 0100 property real innerWidth: LayoutMirroring.enabled ? width - leftPadding : width - rightPadding 0101 0102 background: Rectangle { color: Kirigami.Theme.backgroundColor; Kirigami.Theme.colorSet: Kirigami.Theme.View } 0103 0104 TableView { 0105 id: tableView 0106 anchors.left: parent.left 0107 property ItemSelectionModel selectionModel: ItemSelectionModel { 0108 id: selectionModel 0109 model: tableView.model 0110 } 0111 property int hoveredRow: -1 0112 property int sortColumn: root.sortColumn 0113 0114 signal modelLayoutHasChanged() 0115 0116 signal contextMenuRequested(var index, point position) 0117 onContextMenuRequested: root.contextMenuRequested(index, position) 0118 0119 onWidthChanged: forceLayout() 0120 0121 // FIXME Until Tableview correctly reverses its columns, see QTBUG-90547 0122 model: root.model 0123 Binding on model { 0124 when: scrollView.LayoutMirroring.enabled 0125 value: Table.ReverseColumnsProxyModel { 0126 sourceModel: root.model 0127 } 0128 } 0129 0130 activeFocusOnTab: true 0131 0132 clip: true 0133 boundsBehavior: Flickable.StopAtBounds 0134 0135 Keys.onPressed: { 0136 switch (event.key) { 0137 case Qt.Key_Up: 0138 selectRelative(-1) 0139 if (!atYBeginning) { 0140 contentY -= root.rowHeight 0141 returnToBounds() 0142 } 0143 event.accepted = true 0144 return; 0145 case Qt.Key_Down: 0146 selectRelative(1) 0147 if (!atYEnd) { 0148 contentY += root.rowHeight 0149 returnToBounds() 0150 } 0151 event.accepted = true 0152 return; 0153 case Qt.Key_PageUp: 0154 if (!atYBeginning) { 0155 if ((contentY - (tableView.height - root.rowHeight)) < 0) { 0156 contentY = 0 0157 } else { 0158 contentY -= tableView.height - root.rowHeight // subtracting root.rowHeight so the last row still visible 0159 } 0160 returnToBounds() 0161 } 0162 return; 0163 case Qt.Key_PageDown: 0164 if (!atYEnd) { 0165 if ((contentY + (tableView.height - root.rowHeight)) > contentHeight - height) { 0166 contentY = contentHeight - height 0167 } else { 0168 contentY += tableView.height - root.rowHeight // subtracting root.rowHeight so the last row still visible 0169 } 0170 returnToBounds() 0171 } 0172 return; 0173 case Qt.Key_Home: 0174 if (!atYBeginning) { 0175 contentY = 0 0176 returnToBounds() 0177 } 0178 return; 0179 case Qt.Key_End: 0180 if (!atYEnd) { 0181 contentY = contentHeight - height 0182 returnToBounds() 0183 } 0184 return; 0185 case Qt.Key_Menu: 0186 contextMenuRequested(selectionModel.currentIndex, mapToGlobal(0, 0)) 0187 return; 0188 default: 0189 break; 0190 } 0191 if (event.matches(StandardKey.SelectAll)) { 0192 selectionModel.select(model.index(0, 0), ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Columns); 0193 return; 0194 } 0195 } 0196 0197 onActiveFocusChanged: { 0198 if (activeFocus && !selectionModel.hasSelection) { 0199 selectionModel.setCurrentIndex(model.index(0, 0), ItemSelectionModel.ClearAndSelect) 0200 } 0201 } 0202 0203 function selectRelative(delta) { 0204 var nextRow = selectionModel.currentIndex.row + delta 0205 if (nextRow < 0) { 0206 nextRow = 0 0207 } 0208 if (nextRow >= rows) { 0209 nextRow = rows - 1 0210 } 0211 var index = model.index(nextRow, selectionModel.currentIndex.column) 0212 selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Rows) 0213 } 0214 0215 columnWidthProvider: function(index) { 0216 // FIXME Until Tableview correctly reverses its columns, see QTBUG-90547 0217 if (scrollView.LayoutMirroring.enabled) { 0218 var width = root.columnWidths[root.columnWidths.length - index - 1] 0219 } else { 0220 var width = root.columnWidths[index] 0221 } 0222 if (width === undefined || width === null) { 0223 width = root.defaultColumnWidth 0224 } else { 0225 width = width 0226 } 0227 width = Math.max(Math.floor(width * scrollView.innerWidth), root.minimumColumnWidth) 0228 return width 0229 } 0230 0231 rowHeightProvider: (index) => root.rowHeight 0232 0233 contentWidth: { 0234 var w = 0 0235 for (var i = 0; i < columns; i++) { 0236 w += columnWidthProvider(i) 0237 } 0238 return Math.max(w, scrollView.innerWidth) 0239 } 0240 // FIXME: because of the delay populating the model, TableView seems to not calculate a proper contentHeight automatically 0241 contentHeight : root.rowHeight * rows 0242 } 0243 } 0244 } 0245