Warning, /plasma/plasma-systemmonitor/src/faces/applicationstable/contents/ui/FullRepresentation.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  * SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
0003  * SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
0004  * SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.0-or-later
0007  */
0008 
0009 import QtQuick
0010 import QtQuick.Controls
0011 import QtQuick.Layouts
0012 
0013 import org.kde.kirigami as Kirigami
0014 
0015 import org.kde.ksysguard.faces as Faces
0016 import org.kde.ksysguard.process as Process
0017 
0018 import org.kde.ksysguard.table as Table
0019 
0020 Faces.SensorFace {
0021     id: root
0022 
0023     readonly property var config: controller.faceConfiguration
0024 
0025     actions: [
0026         Kirigami.Action {
0027             icon.name: "search"
0028             text: i18nc("@action", "Search")
0029             displayHint: Kirigami.DisplayHint.KeepVisible
0030             displayComponent: Kirigami.SearchField {
0031                 text: table.filterString
0032                 onTextEdited: table.filterString = text;
0033                 onAccepted: table.filterString = text;
0034                 Component.onCompleted: forceActiveFocus()
0035             }
0036         },
0037         Kirigami.Action {
0038             icon.name: "application-exit"
0039             text: i18nc("@action", "Quit Application")
0040             displayHint: Kirigami.DisplayHint.KeepVisible
0041             onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.TerminateSignal)
0042             enabled: table.selection.hasSelection
0043         },
0044         Kirigami.Action {
0045             id: showDetailsAction
0046             icon.name: "documentinfo"
0047             text: i18nc("@action", "Show Details Sidebar")
0048             checkable: true
0049             checked: root.config.showDetails
0050             onToggled: root.config.showDetails = checked
0051         },
0052         Kirigami.Action {
0053             id: configureColumnsAction
0054             icon.name: "configure"
0055             text: i18nc("@action", "Configure columns…")
0056             onTriggered: columnDialog.open()
0057         }
0058     ]
0059 
0060     contentItem: Item {
0061         Layout.minimumHeight: table.Layout.minimumHeight
0062 
0063         ApplicationsTableView {
0064             id: table
0065 
0066             anchors {
0067                 left: parent.left
0068                 right: splitter.right
0069                 top: parent.top
0070                 bottom: parent.bottom
0071             }
0072 
0073             onContextMenuRequested: (index, position) => {
0074                 contextMenu.popup(null, position.x, position.y)
0075             }
0076 
0077             onHeaderContextMenuRequested: (column, position) => {
0078                 headerContextMenu.popup(null, position)
0079             }
0080 
0081             enabledColumns: columnDialog.visibleColumns
0082             columnDisplay: columnDialog.columnDisplay
0083 
0084             columnWidths: root.config.columnWidths
0085             onColumnWidthsChanged: root.config.columnWidths = columnWidths
0086             sortName: root.config.sortColumn
0087             onSortNameChanged: root.config.sortColumn = sortName
0088             sortOrder: root.config.sortDirection
0089             onSortOrderChanged: root.config.sortDirection = sortOrder
0090 
0091             Keys.onPressed: event => {
0092                 if (event.matches(StandardKey.Delete)) {
0093                     processHelper.sendSignalToSelection(Process.ProcessController.TerminateSignal);
0094                     event.accepted = true;
0095                 } else if ((event.modifiers & Qt.ShiftModifier) && (event.key == Qt.Key_Delete)) {
0096                     processHelper.sendSignalToSelection(Process.ProcessController.KillSignal);
0097                     event.accepted = true;
0098                 }
0099             }
0100         }
0101 
0102         Kirigami.Separator {
0103             id: splitter
0104             anchors {
0105                 top: parent.top
0106                 bottom: parent.bottom
0107                 right: details.left
0108             }
0109 
0110             z: 10
0111             enabled: root.config.showDetails
0112             visible: enabled
0113 
0114             Kirigami.Separator {
0115                 anchors.verticalCenter: parent.verticalCenter
0116                 anchors.left: parent.left
0117                 anchors.leftMargin: Kirigami.Units.smallSpacing
0118                 height: Kirigami.Units.gridUnit
0119                 width: 1
0120             }
0121 
0122             MouseArea {
0123                 anchors.fill: parent
0124                 anchors.margins: -Kirigami.Units.largeSpacing
0125                 cursorShape: enabled ? Qt.SplitHCursor : undefined
0126                 drag.target: this
0127 
0128                 property real startX
0129 
0130                 onPressed: mouse => {
0131                     startX = mouse.x
0132                 }
0133 
0134                 onPositionChanged: mouse => {
0135                     const change = LayoutMirroring.enabled ? startX - mouse.x : mouse.x - startX
0136                     const newWidth = details.width - change
0137                     if (newWidth > details.minimumWidth && newWidth < details.maximumWidth) {
0138                         details.width += -change
0139                     }
0140                 }
0141             }
0142         }
0143 
0144         Loader {
0145             id: details
0146 
0147             anchors.top: parent.top
0148             anchors.bottom: parent.bottom
0149             anchors.right: parent.right
0150 
0151             property real minimumWidth: Kirigami.Units.gridUnit * 8
0152             property real maximumWidth: root.width * 0.75
0153 
0154             width: root.config.detailsWidth
0155             onWidthChanged: root.config.detailsWidth = width
0156 
0157             active: root.config.showDetails
0158 
0159             state: root.config.showDetails ? "" : "closed"
0160 
0161             states: State {
0162                 name: "closed"
0163                 PropertyChanges { target: details; anchors.rightMargin: -width ; visible: false; enabled: false }
0164             }
0165             transitions: Transition {
0166                 SequentialAnimation {
0167                     NumberAnimation { properties: "x"; duration: Kirigami.Units.shortDuration }
0168                     PropertyAction { property: "visible" }
0169                 }
0170             }
0171 
0172             sourceComponent: Component {
0173                 ApplicationDetails {
0174                     headerHeight: table.headerHeight
0175                     onClose: root.config.showDetails = false
0176                     applications: table.selectedApplications
0177                 }
0178             }
0179         }
0180     }
0181 
0182     Menu {
0183         id: contextMenu
0184 
0185         MenuItem { text: i18nc("@action:inmenu", "Set priority…"); enabled: false }
0186 
0187         Menu {
0188             title: i18nc("@action:inmenu", "Send Signal")
0189 
0190             MenuItem {
0191                text: i18nc("@action:inmenu Send Signal", "Suspend (STOP)");
0192                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.StopSignal)
0193             }
0194             MenuItem {
0195                 text: i18nc("@action:inmenu Send Signal", "Continue (CONT)")
0196                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.ContinueSignal)
0197             }
0198             MenuItem {
0199                 text: i18nc("@action:inmenu Send Signal", "Hangup (HUP)")
0200                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.HangupSignal)
0201             }
0202             MenuItem {
0203                 text: i18nc("@action:inmenu Send Signal", "Interrupt (INT)")
0204                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.InterruptSignal)
0205             }
0206             MenuItem {
0207                 text: i18nc("@action:inmenu Send Signal", "Terminate (TERM)")
0208                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.TerminateSignal)
0209             }
0210             MenuItem {
0211                 text: i18nc("@action:inmenu Send Signal", "Kill (KILL)")
0212                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.KillSignal)
0213             }
0214             MenuItem {
0215                 text: i18nc("@action:inmenu Send Signal", "User 1 (USR1)")
0216                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.User1Signal)
0217             }
0218             MenuItem {
0219                 text: i18nc("@action:inmenu Send Signal", "User 2 (USR2)")
0220                 onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.User2Signal)
0221             }
0222         }
0223         MenuSeparator { }
0224         MenuItem {
0225             icon.name: "application-exit";
0226             text: i18ncp("@action:inmenu", "Quit Application", "Quit %1 Applications", killDialog.items.length);
0227             onTriggered: processHelper.sendSignalToSelection(Process.ProcessController.TerminateSignal)
0228         }
0229     }
0230 
0231     Menu {
0232         id: headerContextMenu
0233 
0234         MenuItem {
0235             action: configureColumnsAction
0236         }
0237     }
0238 
0239     Table.KillDialog {
0240         id: killDialog
0241 
0242         property int signalToSend
0243 
0244         title: i18ncp("@title:window", "Quit Application", "Quit %1 Applications", items.length)
0245         killButtonText: i18ncp("@action:button", "Quit Application", "Quit Applications", items.length)
0246         killButtonIcon: "application-exit"
0247         questionText: i18np("Are you sure you want to quit this application?\nAny unsaved work may be lost.",
0248                             "Are you sure you want to quit these %1 applications?\nAny unsaved work may be lost.", items.length)
0249 
0250         items: table.selectedApplications
0251 
0252         delegate: Kirigami.Padding {
0253             horizontalPadding: Kirigami.Units.largeSpacing
0254             verticalPadding: Kirigami.Units.smallSpacing
0255 
0256             contentItem: Kirigami.IconTitleSubtitle {
0257                 icon.name: modelData.iconName
0258                 icon.width: Kirigami.Units.iconSizes.large
0259                 icon.height: Kirigami.Units.iconSizes.large
0260                 title: modelData.name
0261                 subtitle: i18ncp("@item:intable", "%1 Process", "%1 Processes", modelData.pids.length)
0262             }
0263         }
0264 
0265         onAccepted: {
0266             root.config.askWhenKilling = !killDialog.doNotAskAgain
0267 
0268             for (var i in table.selectedApplications) {
0269                 processHelper.sendSignal(table.selectedApplications[i].pids, killDialog.signalToSend);
0270             }
0271         }
0272     }
0273 
0274     Process.ProcessController {
0275         id: processHelper
0276 
0277         readonly property var killSignals: [
0278             Process.ProcessController.TerminateSignal,
0279             Process.ProcessController.KillSignal
0280         ]
0281 
0282         function sendSignalToSelection(sig) {
0283             if (table.selectedApplications.length == 0) {
0284                 return
0285             }
0286 
0287             if (root.config.askWhenKilling && killSignals.includes(sig)) {
0288                 killDialog.signalToSend = sig
0289                 killDialog.open()
0290                 return
0291             }
0292 
0293             for (var i in table.selectedApplications) {
0294                 sendSignal(table.selectedApplications[i].pids, sig);
0295             }
0296         }
0297     }
0298 
0299     Table.ColumnConfigurationDialog {
0300         id: columnDialog
0301 
0302         sourceModel: table.sourceModel.attributesModel
0303 
0304         sortedColumns: root.config.sortedColumns
0305 
0306         fixedColumns: ["appName"]
0307 
0308         onAccepted: {
0309             root.config.sortedColumns = sortedColumns
0310             root.config.columnDisplay = JSON.stringify(columnDisplay)
0311         }
0312 
0313         Component.onCompleted: {
0314             setColumnDisplay(JSON.parse(root.config.columnDisplay))
0315         }
0316     }
0317 }