Warning, /plasma/plasma-workspace/kcms/soundtheme/ui/main.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2023 Ismael Asensio <isma.af@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 import QtQuick
0008 import QtQuick.Layouts
0009 import QtQuick.Controls as QQC2
0010 import org.kde.kirigami as Kirigami
0011 import org.kde.kcmutils as KCM
0012 
0013 
0014 KCM.GridViewKCM {
0015     implicitWidth: Kirigami.Units.gridUnit * 50
0016     implicitHeight: Kirigami.Units.gridUnit * 30
0017 
0018     KCM.SettingStateBinding {
0019         configObject: kcm.settings
0020         settingName: "theme"
0021     }
0022 
0023     view.implicitCellWidth: Kirigami.Units.gridUnit * 23
0024     view.implicitCellHeight: Kirigami.Units.gridUnit * 11
0025 
0026     actions: Kirigami.Action {
0027         id: enabledAction
0028         icon.name: "notification-active-symbolic"
0029         text: i18nc("@option:check", "Enable notification sounds")
0030         checkable: true
0031         checked: kcm.settings.soundsEnabled
0032 
0033         displayComponent: QQC2.CheckBox {
0034             text: enabledAction.text
0035             checked: enabledAction.checked
0036             onToggled: kcm.settings.soundsEnabled = checked
0037 
0038             // HACK: Kirigami.ToolBarPageHeader shows no padding otherwise
0039             rightPadding: Kirigami.Units.smallSpacing
0040 
0041             KCM.SettingStateBinding {
0042                 configObject: kcm.settings
0043                 settingName: "soundsEnabled"
0044             }
0045         }
0046     }
0047 
0048     view.enabled: kcm.settings.soundsEnabled
0049     view.model: kcm.themes
0050     view.currentIndex: kcm.currentIndex
0051 
0052     header: Kirigami.InlineMessage {
0053         id: errorMessage
0054         Layout.fillWidth: true
0055         showCloseButton: true
0056 
0057         function display(errorText, errorType) {
0058             text = errorText
0059             type = errorType ?? Kirigami.MessageType.Error;
0060             visible = true;
0061         }
0062     }
0063 
0064     view.delegate: KCM.GridDelegate {
0065         id: delegate
0066 
0067         readonly property var theme : modelData
0068         readonly property bool compactMode: width < (preview.implicitWidth + demoButton.width + 3 * Kirigami.Units.gridUnit)
0069 
0070         text: theme.name
0071 
0072         thumbnailAvailable: true
0073         thumbnail: GridLayout {
0074             columns: 2
0075             flow: GridLayout.TopToBottom
0076             anchors.margins: Kirigami.Units.largeSpacing
0077             anchors.fill: parent
0078 
0079             Kirigami.Heading {
0080                 text: theme.name
0081                 textFormat: Text.PlainText
0082                 level: 3
0083                 elide: Text.ElideRight
0084                 Layout.fillWidth: true
0085             }
0086             QQC2.Label {
0087                 text: theme.comment
0088                 textFormat: Text.PlainText
0089                 opacity: 0.6
0090                 wrapMode: Text.WordWrap
0091                 Layout.fillWidth: true
0092             }
0093             QQC2.Label {
0094                 visible: theme.inherits.length > 0
0095                 // We add a plural translation in case some language requires different strings
0096                 text: i18ncp("%2 is a theme name or a list of theme names that the current theme inherits from",
0097                              "Based on: %2", "Based on: %2", theme.inherits.length,
0098                             theme.inherits.map(themeId => kcm.nameFor(themeId)).join(', '))
0099                 textFormat: Text.PlainText
0100                 wrapMode: Text.WordWrap
0101                 Layout.fillWidth: true
0102             }
0103             Item {
0104                 Layout.fillHeight: true
0105             }
0106             RowLayout {
0107                 id: preview
0108                 QQC2.Label {
0109                     text: i18nc("@label Precedes a list of buttons which can be clicked to preview the theme's sounds. Keep it short", "Preview sounds:")
0110                     textFormat: Text.PlainText
0111                 }
0112                 Repeater {
0113                     model: [
0114                         {iconName: "preferences-desktop-notification-bell", sounds: ["bell-window-system"]},
0115                         {iconName: "dialog-warning", sounds: ["dialog-warning", "dialog-information"]},
0116                         {iconName: "message-new", sounds: ["message-new-instant", "message-new-email"]},
0117                         {iconName: "battery-low", sounds: ["battery-caution", "battery-low"]},
0118                         {iconName: "device-notifier", sounds: ["device-added", "device-removed"]},
0119                     ]
0120                     delegate: SoundButton {
0121                         themeId: theme.id
0122                         sounds: modelData.sounds
0123                         icon.name: modelData.iconName
0124                         text: i18nc("@info:tooltip", "Preview sound \"%1\"", sounds[0])
0125                     }
0126                 }
0127                 Layout.row: 4
0128                 Layout.columnSpan: delegate.compactMode ? 2 : 1
0129             }
0130 
0131             SoundButton {
0132                 id: demoButton
0133 
0134                 themeId: theme.id
0135                 sounds: {
0136                     // We try to play the demo sound specified by the theme, either in `index.theme`
0137                     // or as a named sound ("theme-demo"), but if none is provided let's fallback
0138                     // to other common descriptive sounds
0139                     const demoSounds = ["theme-demo", "desktop-login", "service-login"];
0140                     if (theme.example.length > 0) {
0141                         demoSounds.unshift(theme.example);
0142                     }
0143                     return demoSounds;
0144                 }
0145                 icon.name: isPlaying ? "media-playback-stop-symbolic": "media-playback-start-symbolic"
0146                 text: i18nc("@info:tooltip", "Preview the demo sound for the theme \"%1\"", theme.name)
0147 
0148                 Layout.column: 1
0149                 Layout.rowSpan: delegate.compactMode ? 4 : 5
0150                 Layout.preferredWidth: Kirigami.Units.iconSizes.large
0151                 Layout.fillHeight: true
0152             }
0153         }
0154 
0155         TapHandler {
0156             onTapped: kcm.settings.theme = theme.id
0157         }
0158     }
0159 
0160     component SoundButton: QQC2.ToolButton {
0161         property string themeId: ""
0162         property var sounds: []
0163         readonly property bool isPlaying: kcm.playingTheme === themeId && sounds.includes(kcm.playingSound)
0164 
0165         display: QQC2.AbstractButton.IconOnly
0166         down: isPlaying  // We just want the visual cue, not the checked state
0167         onClicked: {
0168             if (isPlaying) {
0169                 kcm.cancelSound();
0170                 return;
0171             }
0172 
0173             const result = kcm.playSound(themeId, sounds);
0174 
0175             switch (result) {
0176             case 0: /* CA_ERROR_SUCCESS */
0177                 errorMessage.visible = false;
0178                 break;
0179             case -9: /* CA_ERROR_NOTFOUND */
0180                 errorMessage.display(i18nc("%1 is a sound theme name. %2 is a sound name",
0181                                            "The %1 theme doesn't include the sound '%2'",
0182                                            kcm.nameFor(themeId), sounds[0]),
0183                                      Kirigami.MessageType.Information);
0184                 break;
0185             default:
0186                 errorMessage.display(i18n("Failed to preview sound: %1", kcm.errorString(result)));
0187             }
0188         }
0189 
0190         Layout.preferredWidth: Kirigami.Units.iconSizes.medium
0191         Layout.preferredHeight: Kirigami.Units.iconSizes.medium
0192 
0193         QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
0194         QQC2.ToolTip.text: text
0195         QQC2.ToolTip.visible: (hovered || activeFocus) && enabled
0196     }
0197 }