/* SPDX-FileCopyrightText: 2020 Kai Uwe Broulik SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL */ import QtQuick 2.6 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.3 as QQC2 import QtQml 2.15 import org.kde.kirigami 2.10 as Kirigami import org.kde.kcm 1.5 as KCM import org.kde.private.kcms.style 1.0 as Private KCM.ScrollViewKCM { id: root KCM.ConfigModule.quickHelp: i18n("

This module allows you to have an overview of all plugins of the KDE Daemon, also referred to as KDE Services. Generally, there are two types of service:

The latter are only listed for convenience. The startup services can be started and stopped. You can also define whether services should be loaded at startup.

Use this with care: some services are vital for Plasma; do not deactivate services if you do not know what you are doing.

") Binding { target: kcm.filteredModel property: "query" value: searchField.text restoreMode: Binding.RestoreBinding } Binding { target: kcm.filteredModel property: "statusFilter" value: filterCombo.model[filterCombo.currentIndex].statusFilter restoreMode: Binding.RestoreBinding } header: ColumnLayout { Kirigami.InlineMessage { Layout.fillWidth: true text: i18n("The background services manager (kded5) is currently not running. Make sure it is installed correctly."); type: Kirigami.MessageType.Error showCloseButton: false visible: !kcm.kdedRunning } Kirigami.InlineMessage { id: selfDisablingModulesHint Layout.fillWidth: true text: i18n("Some services disable themselves again when manually started if they are not useful in the current environment.") type: Kirigami.MessageType.Information showCloseButton: true visible: false } Kirigami.InlineMessage { id: runningModulesChangedAfterSaveHint Layout.fillWidth: true text: i18n("Some services were automatically started/stopped when the background services manager (kded5) was restarted to apply your changes.") type: Kirigami.MessageType.Information showCloseButton: true visible: false } Kirigami.InlineMessage { id: errorMessage Layout.fillWidth: true type: Kirigami.MessageType.Error showCloseButton: true visible: false Connections { target: kcm function onErrorMessage(errorString) { errorMessage.text = errorString; errorMessage.visible = true; } function onShowSelfDisablingModulesHint() { selfDisablingModulesHint.visible = true; } function onShowRunningModulesChangedAfterSaveHint() { runningModulesChangedAfterSaveHint.visible = true; } } } RowLayout { Layout.fillWidth: true Kirigami.SearchField { id: searchField Layout.fillWidth: true } QQC2.ComboBox { id: filterCombo textRole: "text" enabled: kcm.kdedRunning || currentIndex > 0 model: [ {text: i18n("All Services"), statusFilter: Private.KCM.UnknownStatus}, {text: i18nc("List running services", "Running"), statusFilter: Private.KCM.Running}, {text: i18nc("List not running services", "Not Running"), statusFilter: Private.KCM.NotRunning} ] // HACK QQC2 doesn't support icons, so we just tamper with the desktop style ComboBox's background // and inject a nice little filter icon. Component.onCompleted: { if (!background || !background.hasOwnProperty("properties")) { // not a KQuickStyleItem return; } var props = background.properties || {}; background.properties = Qt.binding(function() { var newProps = props; newProps.currentIcon = "view-filter"; newProps.iconColor = Kirigami.Theme.textColor; return newProps; }); } } } } view: ListView { id: list clip: true activeFocusOnTab: true model: kcm.filteredModel section.property: "type" section.delegate: Kirigami.ListSectionHeader { width: list.width label: { switch (Number(section)) { case Private.KCM.AutostartType: return i18n("Startup Services"); case Private.KCM.OnDemandType: return i18n("Load-on-Demand Services"); } } } Component { id: listDelegateComponent Kirigami.AbstractListItem { id: delegate // FIXME why does the padding logic to dodge the ScrollBars not work here? text: model.display enabled: !model.immutable checkable: model.type !== Private.KCM.OnDemandType checked: model.autoloadEnabled === true hoverEnabled: checkable focusPolicy: Qt.ClickFocus Accessible.description: i18n("Toggle automatically loading this service on startup") onClicked: { if (checkable) { model.autoloadEnabled = !model.autoloadEnabled; } } Component.onCompleted: { // Checkable Kirigami.ListItem has blue background which we don't want // as we have a dedicated CheckBox. Still using those properties for accessibility. background.color = Qt.binding(function() { return delegate.highlighted || (delegate.supportsMouseEvents && delegate.pressed) ? delegate.activeBackgroundColor : delegate.backgroundColor }); } contentItem: RowLayout { QQC2.CheckBox { id: autoloadCheck // Keep focus on the delegate focusPolicy: Qt.NoFocus checked: delegate.checked visible: delegate.checkable onToggled: model.autoloadEnabled = !model.autoloadEnabled QQC2.ToolTip { text: delegate.Accessible.description } KCM.SettingHighlighter { highlight: !model.autoloadEnabled } } ColumnLayout { Layout.fillWidth: true spacing: 0 QQC2.Label { id: displayLabel Layout.fillWidth: true text: delegate.text elide: Text.ElideRight textFormat: Text.PlainText color: (delegate.highlighted || (delegate.pressed && delegate.supportsMouseEvents)) ? delegate.activeTextColor : delegate.textColor } QQC2.Label { Layout.fillWidth: true text: model.description // FIXME do we have a descriptive label component? opacity: delegate.hovered ? 0.8 : 0.6 wrapMode: Text.WordWrap textFormat: Text.PlainText color: displayLabel.color } } QQC2.Label { id: statusLabel horizontalAlignment: Text.AlignRight opacity: model.status === Private.KCM.Running ? 1 : delegate.hovered ? 0.8 : 0.6 color: model.status === Private.KCM.Running ? Kirigami.Theme.positiveTextColor : displayLabel.color visible: kcm.kdedRunning && model.type !== Private.KCM.OnDemandType text: { switch (model.status) { case Private.KCM.NotRunning: return i18n("Not running"); case Private.KCM.Running: return i18n("Running"); } return ""; } } QQC2.Button { icon.name: model.status === Private.KCM.Running ? "media-playback-pause" : "media-playback-start" visible: kcm.kdedRunning && model.status !== Private.KCM.UnknownStatus && model.type !== Private.KCM.OnDemandType onClicked: { errorMessage.visible = false; console.log("DELEGATE", delegate) if (model.status === Private.KCM.Running) { kcm.stopModule(model.moduleName); } else { kcm.startModule(model.moduleName); } } Accessible.name: model.status === Private.KCM.Running ? i18n("Stop Service") : i18n("Start Service") QQC2.ToolTip { text: parent.Accessible.name } } } } } delegate: Kirigami.DelegateRecycler { width: list.width sourceComponent: listDelegateComponent } } }