[utilities/kdebugsettings] src/kcm/ui: Add page

Laurent Montel <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 52e3844c80cddb2b8527bb5f10d4a9bcbaca7ba3 by Laurent Montel.
Committed on 30/07/2026 at 11:53.
Pushed by mlaurent into branch 'master'.

Add page

A  +37   -0    src/kcm/ui/CategoryComboBox.qml     [License: LGPL(v2.0+)]
A  +112  -0    src/kcm/ui/CustomRulesPage.qml     [License: LGPL(v2.0+)]
A  +72   -0    src/kcm/ui/EditCustomRuleDialog.qml     [License: LGPL(v2.0+)]
A  +26   -0    src/kcm/ui/EnvironmentVariableRulesPage.qml     [License: LGPL(v2.0+)]
A  +69   -0    src/kcm/ui/KDEApplicationRulesPage.qml     [License: LGPL(v2.0+)]
M  +3    -3    src/kcm/ui/main.qml

https://invent.kde.org/utilities/kdebugsettings/-/commit/52e3844c80cddb2b8527bb5f10d4a9bcbaca7ba3

diff --git a/src/kcm/ui/CategoryComboBox.qml b/src/kcm/ui/CategoryComboBox.qml
new file mode 100644
index 00000000..4cc445f4
--- /dev/null
+++ b/src/kcm/ui/CategoryComboBox.qml
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: 2026 Laurent Montel <[email protected]>
+// SPDX-License-Identifier: LGPL-2.0-or-later
+
+import QtQuick.Controls as QQC2
+import org.kde.kdebugsettings
+
+QQC2.ComboBox {
+    id: categoryType
+
+    property int loggingType: -1
+    property bool showOffTypeValue: true
+    property bool syncLoggingTypeFromSelection: true
+
+    onLoggingTypeChanged: {
+        currentIndex = count > 0 ? indexOfValue(loggingType) : -1
+    }
+
+    onCountChanged: {
+        // Resolve initial selection once the proxy model is populated.
+        if (count > 0 && currentIndex < 0) {
+            currentIndex = indexOfValue(loggingType)
+        }
+    }
+
+    onCurrentIndexChanged: {
+        if (syncLoggingTypeFromSelection && currentIndex >= 0 && currentValue !== undefined) {
+            loggingType = currentValue
+        }
+    }
+
+    model: CategoryTypeProxyModel {
+        sourceModel: LoggingManager.categoryTypeModel
+        showOffType: showOffTypeValue
+    }
+    textRole: "display"
+    valueRole: "categoryType"
+}
\ No newline at end of file
diff --git a/src/kcm/ui/CustomRulesPage.qml b/src/kcm/ui/CustomRulesPage.qml
new file mode 100644
index 00000000..a27e1e19
--- /dev/null
+++ b/src/kcm/ui/CustomRulesPage.qml
@@ -0,0 +1,112 @@
+// SPDX-FileCopyrightText: 2023-2026 Laurent Montel <[email protected]>
+// SPDX-License-Identifier: LGPL-2.0-or-later
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls as QQC2
+import org.kde.kirigami as Kirigami
+import org.kde.kirigamiaddons.delegates 1.0 as Delegates
+
+import org.kde.kdebugsettings
+
+Kirigami.ScrollablePage {
+    id: page2
+    title: i18nc("@title", "Custom Rules")
+    leftPadding: 20
+    actions: [
+        Kirigami.Action {
+            displayComponent: Kirigami.SearchField {
+                onAccepted: LoggingManager.customLoggingCategoryProxyModel.filterText = text
+            }
+        }
+    ]
+    EditCustomRuleDialog {
+        id: editCustomRuleDialog
+    }
+
+    function editCustomRule(item, currentIndex) {
+        if (item) {
+            const categoryName = item.categoryName;
+            const categoryEnabled = item.enabled;
+            const categoryLoggingType = item.loggingType;
+            editCustomRuleDialog.editMode = true;
+            editCustomRuleDialog.editRowIndex = currentIndex;
+            editCustomRuleDialog.categoryName = categoryName;
+            editCustomRuleDialog.categoryEnabled = categoryEnabled;
+            editCustomRuleDialog.categoryType = categoryLoggingType;
+            editCustomRuleDialog.open();
+        }
+    }
+
+    ListView {
+        id: listviewRules
+        reuseItems: true
+        activeFocusOnTab: true // keyboard navigation
+        focus: true // keyboard navigation
+        model: LoggingManager.customLoggingCategoryProxyModel
+        delegate: Delegates.RoundedItemDelegate {
+            required property string displayRule
+            required property string categoryName
+            required property int index
+            required property bool enabled
+            required property int loggingType
+
+            text: displayRule
+            highlighted: ListView.isCurrentItem
+            onClicked: listviewRules.currentIndex = index
+            onDoubleClicked: {
+                editCustomRule(listviewRules.currentItem, listviewRules.currentIndex)
+            }
+        }
+        TapHandler {
+            acceptedButtons: Qt.RightButton
+            onTapped: contextMenu.popup()
+        }
+
+        QQC2.Menu {
+            id: contextMenu
+            QQC2.MenuItem {
+                icon.name: "list-add"
+                text: i18nc("@action add custom rule", "Add Rule…")
+                onTriggered: {
+                    editCustomRuleDialog.editMode = false;
+                    editCustomRuleDialog.categoryName = "";
+                    editCustomRuleDialog.categoryEnabled = false;
+                    editCustomRuleDialog.categoryType = 0;
+                    editCustomRuleDialog.open();
+                }
+            }
+            QQC2.MenuItem {
+                visible: listviewRules.currentIndex !== -1 && listviewRules.count !== 0
+                icon.name: "document-edit"
+                text: i18nc("@action edit custom rule", "Edit Rule…")
+                onTriggered: {
+                    editCustomRule(listviewRules.currentItem, listviewRules.currentIndex)
+                }
+            }
+            QQC2.MenuSeparator {
+                visible: listviewRules.currentIndex !== -1 && listviewRules.count !== 0
+            }
+            QQC2.MenuItem {
+                visible: listviewRules.currentIndex !== -1 && listviewRules.count !== 0
+                icon.name: "edit-delete"
+                text: i18nc("@action remove custom rule", "Remove Rule")
+                onTriggered: {
+                    removeRulePrompt.open();
+                }
+                Kirigami.PromptDialog {
+                    id: removeRulePrompt
+                    parent: QQC2.Overlay.overlay
+
+                    title: i18nc("@title:window", "Remove Rule")
+                    subtitle: i18n("Are you sure you want to remove rule ?")
+                    standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
+
+                    onAccepted: {
+                        LoggingManager.customLoggingCategoryProxyModel.removeCategory(listviewRules.currentIndex);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/kcm/ui/EditCustomRuleDialog.qml b/src/kcm/ui/EditCustomRuleDialog.qml
new file mode 100644
index 00000000..6d906310
--- /dev/null
+++ b/src/kcm/ui/EditCustomRuleDialog.qml
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: 2026 Laurent Montel <[email protected]>
+// SPDX-License-Identifier: LGPL-2.0-or-later
+import QtQuick
+import org.kde.kirigami as Kirigami
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+import org.kde.kdebugsettings
+
+Kirigami.Dialog {
+    id: dialog
+    title: editMode ? i18nc("@title:window", "Edit Custom Rule") : i18nc("@title:window", "Create Custom Rule")
+    clip: true
+    showCloseButton: false
+    property alias categoryName: categoryNameField.text
+    property alias categoryEnabled: categoryEnabled.checked
+    property alias categoryType: categoryType.loggingType
+    property bool editMode: false
+    property int editRowIndex: -1
+
+    footer: QQC2.DialogButtonBox {
+        standardButtons: saveButton | QQC2.DialogButtonBox.Cancel
+        onAccepted: {
+            dialog.accept();
+        }
+        QQC2.Button {
+            id: saveButton
+            icon.name: "document-save"
+            enabled: categoryNameField.text !== ""
+            text: i18nc("@label:button", "Save")
+            QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
+        }
+    }
+
+    RowLayout {
+        id: mainColumn
+        spacing: Kirigami.Units.smallSpacing
+
+        QQC2.Label {
+            Layout.leftMargin: 4
+            Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
+            verticalAlignment: Text.AlignVCenter
+            text: i18nc("@label:textbox", "Category:")
+        }
+        QQC2.TextField {
+            id: categoryNameField
+        }
+        QQC2.Label {
+            Layout.leftMargin: 4
+            Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
+            verticalAlignment: Text.AlignVCenter
+            text: i18nc("@label:textbox", "Type:")
+        }
+        CategoryComboBox {
+            id: categoryType
+            showOffTypeValue: false
+            syncLoggingTypeFromSelection: true
+            Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+        }
+        QQC2.CheckBox {
+            id: categoryEnabled
+            Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+            text: i18nc("@label:textbox", "Enabled")
+        }
+    }
+    onAccepted: {
+        if (editMode) {
+            LoggingManager.customCategoryModel.updateCategory(editRowIndex, categoryNameField.text, categoryEnabled.checked, categoryType.loggingType);
+        } else {
+            LoggingManager.customCategoryModel.addCategory(categoryNameField.text, categoryEnabled.checked, categoryType.loggingType);
+        }
+    }
+}
diff --git a/src/kcm/ui/EnvironmentVariableRulesPage.qml b/src/kcm/ui/EnvironmentVariableRulesPage.qml
new file mode 100644
index 00000000..30d0fb2a
--- /dev/null
+++ b/src/kcm/ui/EnvironmentVariableRulesPage.qml
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: 2023-2026 Laurent Montel <[email protected]>
+// SPDX-License-Identifier: LGPL-2.0-or-later
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls as QQC2
+import org.kde.kirigami as Kirigami
+import org.kde.kdebugsettings
+
+Kirigami.Page {
+    id: root
+    title: i18nc("@title", "Rules Settings with Environment Variable")
+
+    leftPadding: 20
+
+    ColumnLayout {
+        spacing: Kirigami.Units.gridUnit
+        width: parent.width - (Kirigami.Units.largeSpacing * 4)
+        anchors.centerIn: parent
+        TextEdit {
+            text: LoggingManager.environmentrules().length === 0 ? i18n("No rules have been defined in the environment variable \"QT_LOGGING_RULES\".") : LoggingManager.environmentrules()
+            readOnly: true
+            horizontalAlignment: Qt.AlignHCenter
+        }
+    }
+}
diff --git a/src/kcm/ui/KDEApplicationRulesPage.qml b/src/kcm/ui/KDEApplicationRulesPage.qml
new file mode 100644
index 00000000..0e1d5ab9
--- /dev/null
+++ b/src/kcm/ui/KDEApplicationRulesPage.qml
@@ -0,0 +1,69 @@
+// SPDX-FileCopyrightText: 2023-2026 Laurent Montel <[email protected]>
+// SPDX-License-Identifier: LGPL-2.0-or-later
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls as QQC2
+import org.kde.kirigami as Kirigami
+
+import org.kde.kdebugsettings
+import org.kde.kirigamiaddons.delegates as Delegates
+
+Kirigami.ScrollablePage {
+    id: page
+    title: i18nc("@title", "KDE Application Rules")
+
+    leftPadding: 20
+    actions: [
+        Kirigami.Action {
+            displayComponent: Kirigami.SearchField {
+                onAccepted: LoggingManager.kdeApplicationLoggingCategoryProxyModel.filterText = text
+            }
+        }
+    ]
+
+    ListView {
+        id: listviewRules
+        focus: true // keyboard navigation
+        activeFocusOnTab: true // keyboard navigation
+        reuseItems: true
+        clip: true
+        model: LoggingManager.kdeApplicationLoggingCategoryProxyModel
+        delegate: Delegates.RoundedItemDelegate {
+            id: ruleDelegate
+            required property int index
+            required property string description
+            required property string generatedToolTip
+            required property int loggingType
+
+            highlighted: ListView.isCurrentItem
+            onClicked: listviewRules.currentIndex = index
+
+            RowLayout {
+                width: parent.width
+
+                QQC2.Label {
+                    Layout.leftMargin: 4
+                    text: ruleDelegate.description
+                    Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
+                    verticalAlignment: Text.AlignVCenter
+
+                    QQC2.ToolTip.visible: hovered
+                    QQC2.ToolTip.text: ruleDelegate.generatedToolTip
+                }
+                Item {
+                    Layout.fillWidth: true
+                }
+                CategoryComboBox {
+                    id: categoryType
+                    Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+                    syncLoggingTypeFromSelection: false
+                    loggingType: ruleDelegate.loggingType
+                    onActivated: () => {
+                        listviewRules.model.setCategoryType(index, currentValue);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/kcm/ui/main.qml b/src/kcm/ui/main.qml
index 4df394c7..d018b62e 100644
--- a/src/kcm/ui/main.qml
+++ b/src/kcm/ui/main.qml
@@ -18,21 +18,21 @@ KCM.ScrollViewKCM {
             id: goToKdeApplicationCategories
             text: i18nc("@action", "Show KDE Application Categories")
             onTriggered: {
-                pageStack.layers.push(Qt.resolvedUrl("KDEApplicationRulesPage.qml"));
+                kcm.push("KDEApplicationRulesPage.qml");
             }
         },
         Kirigami.Action {
             id: goToCustomCategories
             text: i18nc("@action", "Show Custom Categories")
             onTriggered: {
-                pageStack.layers.push(Qt.resolvedUrl("CustomRulesPage.qml"));
+                kcm.push("CustomRulesPage.qml");
             }
         },
         Kirigami.Action {
             id: goToEnviromnentCategories
             text: i18nc("@action", "Show Environment Categories")
             onTriggered: {
-                pageStack.layers.push(Qt.resolvedUrl("EnvironmentVariableRulesPage.qml"));
+                kcm.push("EnvironmentVariableRulesPage.qml");
             }
         }
     ]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.