11import QtQuick.Controls
15import org.kde.kirigami as Kirigami
16import org.kde.kitemmodels as KItemModels
17import org.kde.ksysguard.sensors as Sensors
22 property bool supportsColors: true
23 property bool labelsEditable: true
24 property int maxAllowedSensors: -1
25 property var selected: []
26 property var colors: {}
27 property var labels: {}
29 signal selectColor(string sensorId)
30 signal colorForSensorGenerated(string sensorId, color color)
31 signal sensorLabelChanged(string sensorId, string label)
34 if (!control.selected) {
37 for (let i = 0; i < Math.min(control.selected.length, selectedModel.count); ++i) {
38 selectedModel.set(i, {
"sensor": control.selected[i]});
40 if (selectedModel.count > control.selected.length) {
41 selectedModel.remove(control.selected.length, selectedModel.count - control.selected.length);
42 }
else if (selectedModel.count < control.selected.length) {
43 for (let i = selectedModel.count; i < control.selected.length; ++i) {
44 selectedModel.append({
"sensor": control.selected[i]});
53 placeholderText: control.selected.length == 0 ?
i18ndc(
"KSysGuardSensorFaces",
"@label",
"Click to select a sensor…") :
""
56 if (focus && (maxAllowedSensors <= 0 || repeater.count < maxAllowedSensors)) {
63 if (focus && (maxAllowedSensors <= 0 || repeater.count < maxAllowedSensors)) {
75 duration:
Kirigami.Units.shortDuration
76 easing.type: Easing.InOutQuad
83 function writeSelectedSensors() {
85 for (let i = 0; i < count; ++i) {
86 newSelected.push(
get(i).sensor);
88 control.selected = newSelected;
89 control.selectedChanged();
95 implicitHeight: layout.implicitHeight +
Kirigami.Units.smallSpacing * 2
96 implicitWidth: Math.min(layout.implicitWidth +
Kirigami.Units.smallSpacing * 2,
97 control.width - control.leftPadding - control.rightPadding)
98 readonly
property int position: index
108 border.color:
Kirigami.Theme.highlightColor
110 opacity: (control.maxAllowedSensors <= 0 || index < control.maxAllowedSensors) ? 1 : 0.4
111 parent: drag.active ? control : delegate
113 width: delegate.width
114 height: delegate.height
119 enabled: selectedModel.count > 1
122 let pos = delegateContents.mapFromItem(control.contentItem, 0, 0);
123 delegateContents.x = pos.x;
124 delegateContents.y = pos.y;
126 let pos = delegate.mapFromItem(delegateContents, 0, 0);
127 delegateContents.x = pos.x;
128 delegateContents.y = pos.y;
130 selectedModel.writeSelectedSensors();
135 maximum: control.width - delegateContents.width
139 maximum: control.height - delegateContents.height
142 if (!active || control.contentItem.move.running) {
145 let pos = control.contentItem.mapFromItem(null, drag.centroid.scenePosition.x, drag.centroid.scenePosition.y);
146 pos.x = Math.max(0, Math.min(control.contentItem.width - 1, pos.x));
147 pos.y = Math.max(0, Math.min(control.contentItem.height - 1, pos.y));
149 let child = control.contentItem.childAt(pos.x, pos.y);
150 if (child === delegate) {
154 if (pos.x > child.x + child.width/2) {
155 newIndex = Math.min(child.position + 1, selectedModel.count - 1);
157 newIndex = child.position;
159 selectedModel.move(index, newIndex, 1);
166 target: delegateContents
167 from: delegateContents.x
169 duration:
Kirigami.Units.shortDuration
170 easing.type: Easing.InOutQuad
173 target: delegateContents
174 from: delegateContents.y
176 duration:
Kirigami.Units.shortDuration
177 easing.type: Easing.InOutQuad
181 Sensors.Sensor { id: sensor; sensorId: model.sensor }
183 Component.onCompleted: {
184 if (typeof control.colors ===
"undefined" ||
185 typeof control.colors[sensor.sensorId] ===
"undefined") {
186 let color =
Qt.hsva(Math.random(),
Kirigami.Theme.highlightColor.hsvSaturation,
Kirigami.Theme.highlightColor.hsvValue, 1);
187 control.colorForSensorGenerated(sensor.sensorId, color)
195 anchors.margins:
Kirigami.Units.smallSpacing
198 visible: control.supportsColors
199 Layout.preferredWidth:
Kirigami.Units.iconSizes.smallMedium
200 Layout.preferredHeight:
Kirigami.Units.iconSizes.smallMedium
202 padding:
Kirigami.Units.smallSpacing
205 contentItem: Rectangle {
206 color: typeof control.colors ===
"undefined" ?
"black" : control.colors[sensor.sensorId]
209 onClicked: control.selectColor(sensor.sensorId)
216 Layout.fillWidth:
true
218 if (!control.labels || !control.labels[sensor.sensorId]) {
221 return control.labels[sensor.sensorId]
223 elide:
Text.ElideRight
225 HoverHandler { id: handler }
233 visible: control.labelsEditable
234 icon.name:
"document-edit"
235 icon.width:
Kirigami.Units.iconSizes.small
236 icon.height:
Kirigami.Units.iconSizes.small
237 Layout.preferredWidth:
Kirigami.Units.iconSizes.smallMedium
238 Layout.preferredHeight:
Kirigami.Units.iconSizes.smallMedium
239 onClicked: layout.state =
"editing"
243 icon.name:
"edit-delete-remove"
244 icon.width:
Kirigami.Units.iconSizes.small
245 icon.height:
Kirigami.Units.iconSizes.small
246 Layout.preferredWidth:
Kirigami.Units.iconSizes.smallMedium
247 Layout.preferredHeight:
Kirigami.Units.iconSizes.smallMedium
250 if (control.selected === undefined || control.selected === null) {
251 control.selected = []
253 control.selected.splice(control.selected.indexOf(sensor.sensorId), 1)
254 control.selectedChanged()
264 Layout.fillWidth:
true
265 sourceComponent: RowLayout {
269 Layout.fillWidth:
true
274 if (text == sensor.name) {
277 sensorLabelChanged(sensor.sensorId, text)
282 icon.name:
"checkmark"
283 width:
Kirigami.Units.iconSizes.smallMedium
284 Layout.preferredHeight: textField.implicitHeight
285 Layout.preferredWidth: Layout.preferredHeight
286 onClicked: textField.accepted()
303 implicitWidth: control.availableWidth
306 transitions: Transition {
310 duration:
Kirigami.Units.shortDuration
311 easing.type: Easing.InOutQuad
320 width:
Kirigami.Units.iconSizes.smallMedium +
Kirigami.Units.smallSpacing * 2
322 visible: control.maxAllowedSensors <= 0 || control.selected.length < control.maxAllowedSensors
330 y: (control.Kirigami.ScenePosition.y + control.height + height > control.Window.height)
333 implicitHeight: Math.min(contentItem.implicitHeight + 2,
Kirigami.
Units.gridUnit * 20)
334 width: control.width + 2
341 closePolicy:
Popup.CloseOnEscape |
Popup.CloseOnPressOutside
346 if (control.Kirigami.ScenePosition.y + control.height + height > control.Window.height) {
352 searchField.forceActiveFocus();
354 onClosed: delegateModel.rootIndex = delegateModel.parentModelIndex()
356 contentItem: ColumnLayout {
359 Layout.fillWidth:
true
360 Layout.minimumHeight: implicitHeight
361 Layout.maximumHeight: implicitHeight
362 contentItem: ColumnLayout {
366 Layout.fillWidth:
true
367 Layout.fillHeight:
true
368 placeholderText:
i18nd(
"KSysGuardSensorFaces",
"Search...")
369 onTextEdited: listView.searchString = text
370 onAccepted: listView.searchString = text
371 KeyNavigation.down: listView
375 visible: delegateModel.rootIndex.valid
376 Layout.maximumHeight: visible ? implicitHeight : 0
378 Layout.fillHeight:
true
379 Layout.preferredWidth: height
380 icon.name:
"go-previous"
381 text:
i18ndc(
"KSysGuardSensorFaces",
"@action:button",
"Back")
383 onClicked: delegateModel.rootIndex = delegateModel.parentModelIndex()
387 text: delegateModel.rootIndex.model ? delegateModel.rootIndex.model.
data(delegateModel.rootIndex) :
""
394 Layout.fillWidth:
true
395 Layout.fillHeight:
true
407 property string searchString
409 implicitHeight: contentHeight
411 model: DelegateModel {
414 model: listView.searchString ? sensorsSearchableModel : treeModel
418 width: listView.width
422 leftPadding: mirrored ? indicator.implicitWidth +
Kirigami.Units.largeSpacing * 2 :
Kirigami.Units.largeSpacing
423 rightPadding: !mirrored ? indicator.implicitWidth +
Kirigami.Units.largeSpacing * 2 :
Kirigami.Units.largeSpacing
426 anchors.right: parent.right
427 anchors.rightMargin:
Kirigami.Units.largeSpacing
428 anchors.verticalCenter: parent.verticalCenter
430 width:
Kirigami.Units.iconSizes.small
432 source:
"go-next-symbolic"
433 opacity: model.SensorId.length == 0
437 if (model.SensorId.length == 0) {
438 delegateModel.rootIndex = delegateModel.modelIndex(index);
440 if (control.selected === undefined || control.selected === null) {
441 control.selected = []
443 const length = control.selected.push(model.SensorId)
444 control.selectedChanged()
445 if (control.maxAllowedSensors == length) {
453 Sensors.SensorTreeModel { id: treeModel }
455 KItemModels.KSortFilterProxyModel {
456 id: sensorsSearchableModel
457 filterCaseSensitivity:
Qt.CaseInsensitive
458 filterString: listView.searchString
459 sourceModel: KItemModels.KSortFilterProxyModel {
460 filterRowCallback: function(row, parent) {
461 var sensorId = sourceModel.data(sourceModel.index(row, 0), Sensors.SensorTreeModel.SensorId)
462 return sensorId.length > 0
464 sourceModel: KItemModels.KDescendantsProxyModel {
465 model: listView.searchString ? treeModel : null
470 highlightRangeMode: ListView.ApplyRange
471 highlightMoveDuration: 0
472 boundsBehavior: Flickable.StopAtBounds
491 color:
Kirigami.Theme.backgroundColor
493 property color borderColor:
Kirigami.Theme.textColor
494 border.color:
Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3)
499 shadow.color:
Qt.rgba(0, 0, 0, 0.3)
QString i18ndc(const char *domain, const char *context, const char *text, const TYPE &arg...)
QString i18nd(const char *domain, const char *text, const TYPE &arg...)
KIOCORE_EXPORT CopyJob * move(const QList< QUrl > &src, const QUrl &dest, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
QStringView level(QStringView ifopt)
QString name(StandardAction id)
QString label(StandardShortcut id)
const_pointer data() const const