Delegats de formularis a les pàgines de configuració

Creació de pàgines elegants de configuració personalitzada.

Els complements del Kirigami són un conjunt addicional de components visuals que funcionen bé en el mòbil i l'escriptori i es garanteix que són multiplataforma. Utilitzen el Kirigami per sota per a crear els seus components.

Heu après a afegir pàgines «Quant al» i «Quant al KDE» a l'aplicació. Ara podreu utilitzar els seus mateixos components interns per a crear les pàgines de configuració.

L'estructura del projecte s'hauria de veure així:

addonsexample
├── CMakeLists.txt
├── main.cpp 
├── Main.qml
├── MyAboutPage.qml
└── SettingsPage.qml

Canvis necessaris

Canvieu el Main.qml per a incloure la pàgina nova Settings:

import QtQuick
import QtQuick.Layouts

import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard

import org.kde.about 1.0

Kirigami.ApplicationWindow {
    id: root
    width: 600
    height: 700

    Component {
        id: aboutkde
        FormCard.AboutKDE {}
    }

    Component {
        id: aboutpage
        MyAboutPage {}
    }

    Component {
        id: settingspage
        SettingsPage {}
    }

    pageStack.initialPage: Kirigami.ScrollablePage {
        ColumnLayout {
            FormCard.FormCard {
                FormCard.FormButtonDelegate {
                    id: aboutKDEButton
                    icon.name: "kde"
                    text: i18n("About KDE Page")
                    onClicked: root.pageStack.layers.push(aboutkde)
                }

                FormCard.FormButtonDelegate {
                    id: aboutPageButton
                    icon.name: "applications-utilities"
                    text: i18n("About Addons Example")
                    onClicked: root.pageStack.layers.push(aboutpage)
                }

                FormCard.FormButtonDelegate {
                    id: settingsButton
                    icon.name: "settings-configure"
                    text: i18n("Single Settings Page")
                    onClicked: root.pageStack.layers.push(settingspage)
                }
            }
        }
    }
}

Ara podem començar a consultar els components que s'utilitzen per a crear la pàgina de Configuració: la Targeta de Formulari i els seus Delegats.

Delegats de Formularis

FormCard i FormCardPage

FormCard.FormCard és el component principal que utilitzarem per a agrupar tots els seus components fills, els Delegats.

Hem utilitzat una targeta de formulari en la introducció dels complements del Kirigami abans. El seu propòsit principal és servir com a contenidor per a altres components alhora que segueix un color diferent del fons, de manera similar a un Kirigami.Card.

Crea un fitxer SettingsPage.qml nou:

import QtQuick
import org.kde.kirigamiaddons.formcard as FormCard

FormCard.FormCardPage {
    FormCard.FormCard {
        // Aquí és on van tots els nostres delegats!
    }

    FormCard.FormCard {
        // Aquí és on van tots els nostres delegats!
    }
}

Com que estem creant un fitxer QML separat per a la nostra pàgina de Configuració, i com que necessitem preparar el desplaçament potencial a la nostra pàgina, utilitzem un FormCard.FormCardPage, que hereta Kirigami.ScrollablePage.

El més agradable de la pàgina de la targeta de formulari és que ve amb una disposició interna, de manera que no es necessita cap ColumnLayout addicional i els nostres delegats poden afegir-se directament a ella.

FormHeader

Per a cada FormCard que vulgueu crear, podeu crear un FormHeader just abans. La capçalera utilitza text en negreta i es mostra just a sobre de la targeta de formulari.

import org.kde.kirigamiaddons.formcard as FormCard

FormCard.FormCardPage {
    FormCard.FormHeader {
        title: i18n("General")
    }

    FormCard.FormCard {
        // Els nostres delegats van aquí...
    }

    FormCard.FormHeader {
        title: i18n("Accounts")
    }

    FormCard.FormCard {
        // Els nostres delegats van aquí...
    }
}

FormTextDelegate i FormSectionText

Comencem de manera senzilla, amb text net.

FormSectionText simplement afegeix un delegat prim que conté una etiqueta.FormTextDelegate té text i una descripció en gris.

import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard

FormCard.FormCardPage {
    FormCard.FormHeader {
        title: i18n("General")
    }

    FormCard.FormCard {
        FormCard.FormTextDelegate {
            text: i18n("Current Color Scheme")
            description: "Breeze"
        }
    }

    FormCard.FormHeader {
        title: i18n("Accounts")
    }

    FormCard.FormCard {
        FormCard.FormSectionText {
            text: i18n("Online Account Settings")
        }
        FormCard.FormTextDelegate {
            leading: Kirigami.Icon {source: "user"}
            text: "John Doe"
            description: i18n("The Maintainer ™️")
        }
    }
}

Afegim algun text fictici per a la hipotètica detecció del tema. Si volíem tenir una detecció real de l'esquema de color, en el futur es podria fer de manera similar al Neochat (codi aquí), fent ús d'un model de C++ amb el KColorSchemeManager.

A l'apartat Comptes Online, veiem un immoble addicional, leading. Es pot afegir un element perquè aparegui abans del text. La seva propietat oposada, trailing, podria mostrar un element després del text, però no l'utilitzarem en el programa.

Fem servir un Kirigami.Icon aquí per a la simplicitat, però això també es podria implementar utilitzant un Kirigami.Avatar que captura la informació d'un model, com es fa a Neochat aquí.

Hauria d'acabar veient-se així:

FormButtonDelegate

El FormButtonDelegate és visualment similar a un FormTextDelegate, però s'hi pot fer clic i mostra una fletxa que apunta cap a la dreta. L'hem utilitzat abans a la introducció dels complements del Kirigami.

Mentre que el FormTextDelegate tenia les propietats leading i trailing per a mostrar un element abans i després del contingut principal, el FormButtonDelegate només té la propietat leading, perquè el costat dret està ocupat per la fletxa.

import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard

FormCard.FormCardPage {
    FormCard.FormHeader {
        title: i18n("General")
    }

    FormCard.FormCard {
        FormCard.FormTextDelegate {
            text: i18n("Current Color Scheme")
            description: "Breeze"
        }
    }

    FormCard.FormHeader {
        title: i18n("Accounts")
    }

    FormCard.FormCard {
        FormCard.FormSectionText {
            text: i18n("Online Account Settings")
        }
        FormCard.FormTextDelegate {
            leading: Kirigami.Icon {source: "user"}
            text: "John Doe"
            description: i18n("The Maintainer ™️")
        }
        FormCard.FormButtonDelegate {
            icon.name: "list-add"
            text: i18n("Add a new account")
            onClicked: console.info("Clicked!")
        }
    }
}

Utilitzem la seva propietat icon.name per a establir una icona de més (+) que apareixerà després de l'espai on apareixerà el leading, i abans del contingut principal. Aquest és un patró comú per a indicar que el botó afegirà alguna cosa a una llista.

Com que aquest exemple és per a propòsits il·lustratius senzills, no aprofundim en el que es faria una vegada que es clica el botó: només imprimeix «Clicked!» al terminal. Podríem crear una pàgina nova per a la creació de comptes que afegeixi un altre usuari a un model i després empenyi la pàgina a la vista, de manera similar al que vam fer a Main.qml.

FormRadioDelegate, FormCheckDelegate i FormSwitchDelegate

El RadioButton, el CheckBox i el Switch són components molt utilitzats en qualsevol interfície d'usuari. Els complements del Kirigami els proporcionen com a FormRadioDelegate, FormCheckDelegate i FormSwitchDelegate.

Les seves úniques propietats principals són text i description. Són diferents en ús perquè tots hereten AbstractButton, i per tant s'espera que utilitzin els seus senyals i controladors: «checked» i «onChecked», «toggled» i «onToggled», «clicked» i «onClicked».

Volem crear alguna funcionalitat de desament automàtic a la nostra aplicació, i només volem mostrar la seva configuració si l'usuari ha habilitat aquesta funcionalitat. Creeu una secció nova utilitzant un FormCard i un FormHeader i un FormRadioDelegate.

FormCard.FormHeader {
    title: i18n("Autosave")
}

FormCard.FormCard {
    FormCard.FormSwitchDelegate {
        id: autosave
        text: i18n("Enabled")
    }
    FormCard.FormRadioDelegate {
        text: i18n("After every change")
        visible: autosave.checked
    }
    FormCard.FormRadioDelegate {
        text: i18n("Every 10 minutes")
        visible: autosave.checked
    }
    FormCard.FormRadioDelegate {
        text: i18n("Every 30 minutes")
        visible: autosave.checked
    }
}

Vinculem la visibilitat de cada botó d'opció a un commutador, de manera que només apareixeran quan el commutador estigui habilitat.

Per a provar la nostra casella de selecció, podem afegir un FormCheckDelegate nou a la nostra secció General.

FormCard.FormHeader {
    title: i18n("General")
}

FormCard.FormCard {
    FormCard.FormTextDelegate {
        text: i18n("Current Color Scheme")
        description: "Breeze"
    }
    FormCard.FormCheckDelegate {
        text: i18n("Show Tray Icon")
        onToggled: {
            if (checkState) {
                console.info("A tray icon appears on your system!")
            } else {
                console.info("The tray icon disappears!")
            }
        }
    }
}

Aquí utilitzem el manipulador de senyals onToggled per a mostrar algun text fictici per a simular una icona de safata que apareix en el sistema. Si realment voleu, podeu implementar fàcilment una icona de la safata utilitzant SystemTrayIcon.

Finalment, la nostra aplicació s'hauria de veure així:

FormComboBoxDelegate

El component ComboBox comú es pot crear utilitzant un FormComboBoxDelegate.

Aquest quadre combinat té diverses propietats útils que podem fer servir: editable, displayText i displayMode.

Establir editable: true permet a l'usuari editar el text del quadre combinat, el qual és útil en cas que es necessitin opcions noves del quadre combinat:

Sempre que necessiteu mostrar text addicional abans de cada opció, podeu utilitzar alguna cosa com displayText: "Profile: " + currentText:

I el més interessant, que utilitzarem en el nostre exemple, és displayMode. Pot tenir tres opcions:

  • FormComboBoxDelegate.ComboBox: el quadre petit estàndard que mostra una llista d'opcions.
  • FormComboBoxDelegate.Dialog: un diàleg que mostra una llista d'opcions al mig de la finestra, com un Kirigami.OverlaySheet.
  • FormComboBoxDelegate.Page: una pàgina nova que conté una llista d'opcions mostrades en una finestra separada.

Afegiu el següent entre els delegats de «Current Color Scheme» i «Show Tray Icon» a la targeta del formulari «General».

FormCard.FormComboBoxDelegate {
    text: i18n("Default Profile")
    description: i18n("The profile to be loaded by default.")
    displayMode: FormCard.FormComboBoxDelegate.ComboBox
    currentIndex: 0
    editable: false
    model: ["Work", "Personal"]
}

Amb la casella de selecció, la pàgina Configuració s'hauria de veure així:

FormDelegateSeparator

La nostra pàgina de configuració està prenent forma, però cada secció està començant a fer-se llarga. Podem afegir alguns FormDelegateSeparators per a fer que la nostra pàgina sigui més ordenada:

import QtQuick 2.15
import org.kde.kirigami 2.20 as Kirigami
import org.kde.kirigamiaddons.formcard 1.0 as FormCard

FormCard.FormCardPage {
    id: root

    title: i18nc("@title", "Settings")

    FormCard.FormHeader {
        title: i18nc("@title:group", "General")
    }

    FormCard.FormCard {
        FormCard.FormTextDelegate {
            text: i18nc("@info", "Current Color Scheme")
            description: "Breeze"
        }

        FormCard.FormComboBoxDelegate {
            id: combobox
            text: i18nc("@label:listbox", "Default Profile")
            description: i18nc("@info:whatsthis", "The profile to be loaded by default.")
            displayMode: FormCard.FormComboBoxDelegate.ComboBox
            currentIndex: 0
            editable: false
            model: ["Work", "Personal"]
        }

        FormCard.FormDelegateSeparator {
            above: combobox
            below: checkbox
        }

        FormCard.FormCheckDelegate {
            id: checkbox
            text: i18nc("@option:check", "Show Tray Icon")
            onToggled: {
                if (checkState) {
                    console.info("A tray icon appears on your system!")
                } else {
                    console.info("The tray icon disappears!")
                }
            }
        }
    }

    FormCard.FormHeader {
        title: i18nc("@title:group", "Autosave")
    }

    FormCard.FormCard {
        FormCard.FormSwitchDelegate {
            id: autosave
            text: i18nc("@option:check", "Enabled")
        }
        FormCard.FormDelegateSeparator {
            above: autosave
            below: firstradio
            visible: autosave.checked
        }
        FormCard.FormRadioDelegate {
            id: firstradio
            text: i18nc("@option:radio", "After every change")
            visible: autosave.checked
        }
        FormCard.FormRadioDelegate {
            text: i18nc("@option:radio", "Every 10 minutes")
            visible: autosave.checked
        }
        FormCard.FormRadioDelegate {
            text: i18nc("@option:radio", "Every 30 minutes")
            visible: autosave.checked
        }
    }

    FormCard.FormHeader {
        title: i18nc("@title:group", "Accounts")
    }

    FormCard.FormCard {
        FormCard.FormSectionText {
            text: i18nc("@info:whatsthis", "Online Account Settings")
        }
        FormCard.FormTextDelegate {
            id: lastaccount
            leading: Kirigami.Icon {source: "user"}
            text: "John Doe"
            description: i18nc("@info:credit", "The Maintainer ™️")
        }
        FormCard.FormDelegateSeparator {
            above: lastaccount
            below: addaccount
        }
        FormCard.FormButtonDelegate {
            id: addaccount
            icon.name: "list-add"
            text: i18nc("@action:button", "Add a new account")
            onClicked: console.info("Clicked!")
        }
    }
}

Generalment, podeu utilitzar separadors sempre que veieu distincions importants entre components, encara que l'elecció d'on col·locar-los és en última instància vostra. Per exemple, a la secció General, la casella de selecció difereix dels seus components anteriors, ja que no comença per text; a la secció Desament automàtic, el separador agrupa els botons d'opció; i a la secció Comptes, afegir un separador entre l'últim compte i el botó proporciona algun focus addicional al botó.

Les propietats above i below són bastant autoexplicatives pel que fa al seu ús: es passa el id dels components per sobre i per sota del separador. Quan s'estableixin, el separador desapareixerà ràpidament cada vegada que es ressalti o es passi per sobre de l'element anterior o inferior. Són més útils, per exemple, quan necessiteu generar components dinàmicament i no podeu assumir automàticament quin element vindrà immediatament abans o després del separador. Aquest seria el cas a la secció de Comptes de la nostra aplicació una vegada que s'hagi implementat realment la lògica d'afegir comptes nous, i en aquest cas sempre podríem agafar l'últim element del model per a fer-ho.

Observeu com el separador que hi ha a sobre de la configuració de la icona de la safata no apareixerà mentre es passa per sobre.