Skip to content

Add Dialog Components

Devin Lin requested to merge work/dialogs into master

To easily test this MR, you can use: sdk/kirigami-gallery!17 (merged)

Currently we have two options for making dialogs, either using the QQC2 dialogs or using OverlaySheet. Dialogs work but are not optimal; the way to specify standard buttons does not correspond at all to Plasma's button style, and also the appearance and animations don't really look consistent with elements on Plasma. OverlaySheet was meant to be for long content sheets, which applications have been repurposing as dialogs. This has caused inconsistent implementations of headers and footers.

Some of the dialog implementations around Plasma:

The Kirigami.Dialog component, along with sub-components allow for easy creation of dialogs, while also providing consistency as the sub-components help reduce boilerplate.

This is also a stepping stone for making convergent components in the future (ex. convergent menu that can swap between drawers, classic menus and dialogs, convergent ComboBox that can open a dialog with search bar for long lists).

Examples: sdk/kirigami-gallery!17 (merged)

output

TODO:

  • Create detailed documentation and code samples
  • Add a lot more samples and usecases to kirigami gallery
  • Figure out how to clone a list of actions to avoid binding loop
  • Add content header component to MenuDialog
  • Figure out why the scrollbar in ScrollableDialog causes segfaults
  • Figure out how to parent the dialog when used in kcms (where applicationWindow() doesn't work)
  • Maybe have separate event when dialog is dismissed by clicking outside of it (not triggered during accepted() or rejected(), dismissed()?) - [ ] Add proper vkbd support? #16
  • Perhaps drop ScrollableDialog and make all dialogs scrollable if content height > dialog height
  • Double check documentation so that it is consistent with dialog implementation

Subcomponents:

PromptDialog

  • Used for making simple confirmation dialogs or dialogs that just need to quickly display text and some actions
  • Footer buttons can still be customized or even removed (footerActions and customFooterActions)
  • TODO: Add header and footer, for usecases like textfield prompt

image

image

MenuDialog

  • Provides an easy way to make a dialog with a list of actions (similar to the mobile Elisa dialogs)
  • Can be used as a replacement for footer buttons in a prompt, if they are long
  • Footer buttons can still be customized or even removed (footerActions and customFooterActions)

image

Similar usecases on other platforms:

ScrollableDialog

* Create a dialog that allows for scrolling

Dialog now automatically adds scrolling when content overflows.

image

Code samples:

// quick prompt
Kirigami.PromptDialog {
    id: promptDialog
    title: "Reset settings?"
    subtitle: "The stored settings for the application will be deleted, with the defaults restored."
    standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
    onAccepted: console.log("Reset")
    onDismissed: console.log("Dismissed")
}

// custom actions (this is the info dialog in KirigamiGallery)
Kirigami.PromptDialog {
    id: root
    property Kirigami.Page page
    property url higUrl: infoData.higUrl
    property url sourceUrl: infoData.sourceUrl
    property url apiUrl: infoData.apiUrl
    property string text: infoData.text
    property alias component: infoData.component

    title: infoData.title
    subtitle: text
    preferredWidth: Kirigami.Units.gridUnit * 20
    onVisibleChanged: page.actions.main.checked = visible
    
    InfoData {
        id: infoData
    }
    
    standardButtons: Kirigami.Dialog.NoButton
    customFooterActions: [
        Kirigami.Action {
            text: qsTr("HIG...")
            enabled: higUrl != ""
            onTriggered: Qt.openUrlExternally(higUrl);
        },
        Kirigami.Action {
            text: qsTr("Source code...")
            enabled: sourceUrl != ""
            onTriggered: Qt.openUrlExternally(sourceUrl)
        },
        Kirigami.Action {
            text: qsTr("API...")
            enabled: apiUrl != ""
            onTriggered: Qt.openUrlExternally(apiUrl)
        }
    ]
}

// radio selection dialog
Kirigami.Dialog {
    id: selectDialog
    title: i18n("Alarm Snooze Length")
    padding: 0

    ColumnLayout {
        spacing: 0
        Repeater {
            model: ListModel {
                // we can't use i18n with ListElement
                Component.onCompleted: {
                    append({"name": i18n("1 minute"), "value": 1});
                    append({"name": i18n("2 minutes"), "value": 2});
                    append({"name": i18n("3 minutes"), "value": 3});
                    append({"name": i18n("4 minutes"), "value": 4});
                    append({"name": i18n("5 minutes"), "value": 5});
                    append({"name": i18n("10 minutes"), "value": 10});
                    append({"name": i18n("30 minutes"), "value": 30});
                    append({"name": i18n("1 hour"), "value": 60});
                }
            }
            delegate: Controls.RadioDelegate {
                topPadding: Kirigami.Units.smallSpacing * 2
                bottomPadding: Kirigami.Units.smallSpacing * 2
                implicitWidth: Kirigami.Units.gridUnit * 16
                
                text: name
                checked: value == 1
                onCheckedChanged: {
                    if (checked) {
                        showPassiveNotification("Selected " + name + " with value " + value);
                    }
                }
            }
        }
    }
}

// long sheet
Kirigami.Dialog {
    id: scrollableDialog
    title: i18n("Select Number")
    
    ListView {
        implicitWidth: Kirigami.Units.gridUnit * 16
        implicitHeight: Kirigami.Units.gridUnit * 16
        leftMargin: 0; rightMargin: 0; topMargin: 0; bottomMargin: 0;
        
        model: 100
        delegate: Controls.RadioDelegate {
            topPadding: Kirigami.Units.smallSpacing * 2
            bottomPadding: Kirigami.Units.smallSpacing * 2
            implicitWidth: Kirigami.Units.gridUnit * 16
            text: modelData
        }
    }
}

// context menu (elisa example)
Kirigami.MenuDialog {
    id: menuDialog
    title: i18n("Track Options")
    
    actions: [
        Kirigami.Action {
            iconName: "media-playback-start"
            text: i18nc("Start playback of the selected track", "Play")
            tooltip: i18n("Start playback of the selected track")
        },
        Kirigami.Action {
            enabled: false
            iconName: "document-open-folder"
            text: i18nc("Show the file for this song in the file manager", "Show in folder")
            tooltip: i18n("Show the file for this song in the file manager")
        },
        Kirigami.Action {
            iconName: "documentinfo"
            text: i18nc("Show track metadata", "View details")
            tooltip: i18n("Show track metadata")
        },
        Kirigami.Action {
            iconName: "list-add"
            text: i18nc("Add the track to the queue, right after the current track", "Play next")
            tooltip: i18n("Add the track to the queue, right after the current track")
        },
        Kirigami.Action {
            iconName: "list-add"
            text: i18nc("Enqueue current track", "Add to queue")
            tooltip: i18n("Enqueue current track")
        }
    ]
}
Edited by Devin Lin

Merge request reports