Warning, /plasma/kinfocenter/src/qml/CommandOutputKCM.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0003 SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org> 0004 */ 0005 0006 import QtQuick 2.15 0007 import QtQuick.Controls 2.15 as QQC2 0008 import QtQuick.Layouts 1.1 0009 0010 import org.kde.kirigami 2.20 as Kirigami 0011 import org.kde.kquickcontrolsaddons 2.0 0012 import org.kde.kcmutils as KCM 0013 0014 KCM.SimpleKCM { 0015 id: root 0016 0017 implicitWidth: Kirigami.Units.gridUnit * 20 0018 implicitHeight: Kirigami.Units.gridUnit * 20 0019 // Use a horizontal scrollbar if text wrapping is disabled. In all other cases we'll go with the defaults. 0020 horizontalScrollBarPolicy: wrapMode === TextEdit.NoWrap ? QQC2.ScrollBar.AsNeeded : QQC2.ScrollBar.AlwaysOff 0021 0022 Kirigami.Theme.colorSet: Kirigami.Theme.View 0023 Kirigami.Theme.inherit: false 0024 0025 // The CommandOutputContext object. 0026 required property QtObject output 0027 property int wrapMode: TextEdit.NoWrap 0028 property int textFormat: TextEdit.PlainText 0029 0030 Clipboard { id: clipboard } 0031 0032 Component { 0033 id: dataComponent 0034 0035 Kirigami.SelectableLabel { 0036 id: text 0037 text: output.text 0038 font.family: "monospace" 0039 wrapMode: root.wrapMode 0040 textFormat: root.textFormat 0041 onLinkActivated: link => Qt.openUrlExternally(link) 0042 } 0043 } 0044 0045 Component { 0046 id: loadingComponent 0047 0048 Item { 0049 width: parent.width 0050 implicitHeight: indicator.implicitHeight 0051 0052 QQC2.BusyIndicator { 0053 id: indicator 0054 0055 anchors.centerIn: parent 0056 0057 running: false 0058 // only show the indicator after a brief timeout otherwise we can have a situtation where loading takes a couple 0059 // milliseconds during which time the indicator flashes up for no good reason 0060 Timer { 0061 running: true 0062 repeat: false 0063 interval: 500 0064 onTriggered: indicator.running = true 0065 } 0066 } 0067 } 0068 } 0069 0070 Component { 0071 id: noDataComponent 0072 0073 Item { 0074 width: parent.width 0075 implicitHeight: placeholder.implicitHeight 0076 0077 Kirigami.PlaceholderMessage { 0078 id: placeholder 0079 readonly property bool errorNotFilter: output.filter === "" && output.error !== "" 0080 0081 width: parent.width - (Kirigami.Units.largeSpacing * 8) 0082 anchors.centerIn: parent 0083 0084 text: { 0085 if (output.filter !== "") { 0086 return i18ndc("kinfocenter", "@info", "No text matching the filter") 0087 } 0088 if (output.error !== "") { 0089 return output.error 0090 } 0091 return i18ndc("kinfocenter", "@info the KCM has no data to display", "No data available") 0092 } 0093 explanation: { 0094 if (errorNotFilter && output.explanation !== "") { 0095 return output.explanation 0096 } 0097 return "" 0098 } 0099 icon.name: "data-warning" 0100 0101 helpfulAction: Kirigami.Action { 0102 enabled: placeholder.errorNotFilter 0103 icon.name: "tools-report-bug" 0104 text: i18n("Report this issue") 0105 onTriggered: { 0106 Qt.openUrlExternally(output.bugReportUrl) 0107 } 0108 } 0109 } 0110 } 0111 } 0112 0113 // This is a bit flimsy but we want to switch the content of the KCM around, based on the data state. 0114 // We could switch around visiblity but a Loader seems neater over all. 0115 Loader { 0116 id: contentLoader 0117 anchors.fill: parent 0118 } 0119 0120 actions: [ 0121 Kirigami.Action { 0122 icon.name: "edit-copy" 0123 text: i18ndc("kinfocenter", "@action:button copies all displayed text", "Copy to Clipboard") 0124 onTriggered: clipboard.content = output.text 0125 }, 0126 Kirigami.Action { 0127 displayComponent: Kirigami.SearchField { 0128 visible: { 0129 const isVisibleState = (root.state === "" || !(root.state === "noData" && contentLoader.item.errorNotFilter)) 0130 return isVisibleState && root.textFormat === TextEdit.PlainText 0131 } 0132 0133 placeholderText: i18ndc("kinfocenter", "@label placeholder text to filter for something", "Filter…") 0134 0135 Accessible.name: i18ndc("kinfocenter", "accessible name for filter input", "Filter") 0136 Accessible.searchEdit: true 0137 0138 focusSequence: "Ctrl+I" 0139 0140 onAccepted: output.filter = text 0141 } 0142 } 0143 ] 0144 0145 states: [ 0146 State { 0147 name: "loading" 0148 when: !output.ready 0149 PropertyChanges { target: contentLoader; sourceComponent: loadingComponent } 0150 }, 0151 State { 0152 name: "noData" 0153 when: output.text === "" || output.error !== "" 0154 PropertyChanges { target: contentLoader; sourceComponent: noDataComponent } 0155 }, 0156 State { 0157 name: "" // default state 0158 PropertyChanges { target: contentLoader; sourceComponent: dataComponent } 0159 } 0160 ] 0161 }