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
0008 import QtQuick.Controls
0009 import QtQuick.Layouts
0010 import QtQml.Models
0011 
0012 import org.kde.kitemmodels as ItemModels
0013 
0014 import org.kde.kirigami as Kirigami
0015 import org.kde.ksysguard.table as Table
0016 
0017 FocusScope {
0018     id: root
0019 
0020     property var model
0021     property alias view: tableView
0022     property alias delegate: tableView.delegate
0023 
0024     property alias sortColumn: heading.sortColumn
0025     property alias sortOrder: heading.sortOrder
0026     property alias sortName: heading.sortName
0027     property alias idRole: heading.idRole
0028 
0029     // Column widths in fractions of the entire view width
0030     // Since column sizes are relative to a given view width, the widths of individual
0031     // columns need to be expressed as a fraction of the entire width. columnWidths
0032     // and defaultColumnWidth both store these fractions. Note that minimumColumnWidth
0033     // is expressed as a pixel value since we do not want that to scale with view width.
0034     property var columnWidths: []
0035     property real defaultColumnWidth: 0.1
0036     property real minimumColumnWidth: Kirigami.Units.gridUnit * 4
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     Kirigami.Theme.inherit: false
0053     Kirigami.Theme.colorSet: Kirigami.Theme.View
0054 
0055     TableViewHeader {
0056         id: heading
0057 
0058         view: tableView
0059 
0060         width: scrollView.width
0061 
0062         onSort: (column, order) => {
0063             root.sort(column, order)
0064         }
0065 
0066         onResize: (column, width) => {
0067             root.setColumnWidth(column, width)
0068         }
0069 
0070         onContextMenuRequested:(column, position) => {
0071             root.headerContextMenuRequested(column, position)
0072         }
0073     }
0074 
0075     ScrollView {
0076         id: scrollView
0077         anchors.fill: parent
0078         anchors.topMargin: heading.height
0079 
0080         property real innerWidth: LayoutMirroring.enabled ? width - leftPadding : width - rightPadding
0081 
0082         background: Rectangle { color: Kirigami.Theme.backgroundColor; Kirigami.Theme.colorSet: Kirigami.Theme.View }
0083 
0084         TreeView {
0085             id: tableView
0086             anchors.left: parent.left
0087             selectionModel: ItemSelectionModel {
0088                 id: selectionModel
0089                 model: tableView.model
0090             }
0091             property int hoveredRow: -1
0092             property int sortColumn: root.sortColumn
0093 
0094             signal contextMenuRequested(var index, point position)
0095             onContextMenuRequested: (index, position) => {
0096                 root.contextMenuRequested(index, position);
0097             }
0098 
0099             // FIXME Until Tableview correctly reverses its columns, see QTBUG-90547
0100             model: root.model
0101             Binding on model {
0102                 when: scrollView.LayoutMirroring.enabled
0103                 value: Table.ReverseColumnsProxyModel {
0104                     sourceModel: root.model
0105                 }
0106             }
0107 
0108             activeFocusOnTab: true
0109 
0110             clip: true
0111             boundsBehavior: Flickable.StopAtBounds
0112 
0113             Keys.onPressed: event => {
0114                 switch (event.key) {
0115                     case Qt.Key_Up:
0116                         selectRelative(-1)
0117                         if (!atYBeginning) {
0118                             contentY -= root.rowHeight
0119                             returnToBounds()
0120                         }
0121                         event.accepted = true
0122                         return;
0123                     case Qt.Key_Down:
0124                         selectRelative(1)
0125                         if (!atYEnd) {
0126                             contentY += root.rowHeight
0127                             returnToBounds()
0128                         }
0129                         event.accepted = true
0130                         return;
0131                     case Qt.Key_PageUp:
0132                         if (!atYBeginning) {
0133                             if ((contentY - (tableView.height - root.rowHeight)) < 0) {
0134                                 contentY = 0
0135                             } else {
0136                                 contentY -= tableView.height - root.rowHeight // subtracting root.rowHeight so the last row still visible
0137                             }
0138                             returnToBounds()
0139                         }
0140                         return;
0141                     case Qt.Key_PageDown:
0142                         if (!atYEnd) {
0143                             if ((contentY + (tableView.height - root.rowHeight)) > contentHeight - height) {
0144                                 contentY = contentHeight - height
0145                             } else {
0146                                 contentY += tableView.height - root.rowHeight // subtracting root.rowHeight so the last row still visible
0147                             }
0148                             returnToBounds()
0149                         }
0150                         return;
0151                     case Qt.Key_Home:
0152                         if (!atYBeginning) {
0153                             contentY = 0
0154                             returnToBounds()
0155                         }
0156                         return;
0157                     case Qt.Key_End:
0158                         if (!atYEnd) {
0159                             contentY = contentHeight - height
0160                             returnToBounds()
0161                         }
0162                         return;
0163                     case Qt.Key_Menu:
0164                         contextMenuRequested(selectionModel.currentIndex, mapToGlobal(0, 0))
0165                         return;
0166                     default:
0167                         break;
0168                 }
0169                 if (event.matches(StandardKey.SelectAll)) {
0170                     selectionModel.select(model.index(0, 0), ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Columns);
0171                     return;
0172                 }
0173             }
0174 
0175             onActiveFocusChanged: {
0176                 if (activeFocus && !selectionModel.hasSelection) {
0177                     selectionModel.setCurrentIndex(model.index(0, 0), ItemSelectionModel.ClearAndSelect)
0178                 }
0179             }
0180 
0181             function selectRelative(delta) {
0182                 var nextRow = selectionModel.currentIndex.row + delta
0183                 if (nextRow < 0) {
0184                     nextRow = 0
0185                 }
0186                 if (nextRow >= rows) {
0187                     nextRow = rows - 1
0188                 }
0189                 var index = model.index(nextRow, selectionModel.currentIndex.column)
0190                 selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Rows)
0191             }
0192 
0193             columnWidthProvider: function(index) {
0194                 let column = index
0195                 // FIXME Until Tableview correctly reverses its columns, see QTBUG-90547
0196                 if (LayoutMirroring.enabled) {
0197                     column = root.columnWidths.length - index - 1
0198                 }
0199 
0200                 // Resizing sets the explicit column width and has no other trigger. If
0201                 // we don't make use of that value we can't resize. So read the value,
0202                 // convert it to a fraction of total width and write it back to
0203                 // columnWidths, then clear the explicit column width again so that
0204                 // resizing updates the column width properly. This isn't the prettiest
0205                 // of solutions but at least makes things work the way we want.
0206                 let explicitWidth = explicitColumnWidth(index)
0207                 if (explicitWidth >= 0) {
0208                     let w = explicitWidth / width
0209                     root.columnWidths[column] = w
0210                     root.columnWidthsChanged()
0211                     clearColumnWidths()
0212                 }
0213 
0214                 let columnWidth = root.columnWidths[column]
0215                 return Math.max(Math.floor((columnWidth ?? root.defaultColumnWidth) * scrollView.innerWidth), root.minimumColumnWidth)
0216             }
0217         }
0218     }
0219 }
0220