Delegados de Form en sus páginas de preferencias

Cree elegantes páginas de preferencias personalizadas.

Los complementos de Kirigami son un conjunto adicional de componentes visuales que funcionan bien en el móvil y en el escritorio, con la garantía de ser multiplataforma. Usan Kirigami internamente para crear sus componentes.

Ha aprendido a añadir las páginas «Acerca de» y «Acerca de KDE» a su aplicación. Ahora podrá usar los mismos componentes internos para crear sus páginas de preferencias.

La estructura del proyecto debería parecerse a esto:

addonsexample
├── CMakeLists.txt
├── main.cpp
├── resources.qrc
└── contents/
    └── ui/
        ├── main.qml
        ├── MyAboutPage.qml
        └── SettingsPage.qml

Cambios necesarios

Añada una nueva línea a nuestro resources.qrc:

<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/">
    <file alias="main.qml">contents/ui/main.qml</file>
    <file alias="MyAboutPage.qml">contents/ui/MyAboutPage.qml</file>
    <file alias="SettingsPage.qml">contents/ui/SettingsPage.qml</file>
</qresource>
</RCC>

Y cambie main.qml para que incluya nuestra nueva página de preferencias:

import QtQuick 2.15
import QtQuick.Layouts 1.15

import org.kde.kirigami 2.20 as Kirigami
import org.kde.kirigamiaddons.formcard 1.0 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)
                }
            }
        }
    }
}

Ahora podemos comenzar a revisar los componentes usados para crear nuestra página de «Preferencias»: la tarjeta de formulario y sus delegados.

Delegados de Form

FormCard y FormCardPage

FormCard.FormCard es el componente principal que usaremos para agrupar todos sus componentes hijos, los «delegados».

Ya hemos usado una tarjeta de formulario en la introducción a los complementos de Kirigami. Su propósito principal es el de servir como contenedor para otros componentes con un color distinto al del fondo, de un modo similar a una Kirigami.Card .

Cree un nuevo archivo contents/ui/SettingsPage.qml:

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

FormCard.FormCardPage {
    FormCard.FormCard {
        // Aquí es donde van nuestros delegados.
    }

    FormCard.FormCard {
        // Aquí es donde van nuestros delegados.
    }
}

Como estamos creando un archivo QML distinto para nuestra página de «Preferencias», y como posiblemente necesitaremos prepararla para que permita usar desplazamiento en la página, usamos una FormCard.FormCardPage, que hereda de Kirigami.ScrollablePage .

Lo bueno de la página de la tarjeta de formulario es que viene con un diseño interno, por lo que no necesita ningún «ColumnLayout» adicional, y nuestros delegados se pueden añadir directamente al mismo.

FormHeader

Para cada FormCard que quiera crear, puede crear una FormHeader antes. La cabecera usa texto en negrita y se muestra justo encima de la tarjeta de formulario.

import org.kde.kirigamiaddons.formcard 1.0 as FormCard

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

    FormCard.FormCard {
        // Nuestros delegados van aquí...
    }

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

    FormCard.FormCard {
        // Nuestros delegados van aquí...
    }
}

FormTextDelegate y FormSectionText

Empecemos de forma sencilla, con texto sin formato.

FormSectionText añade un fino delegado que contiene una etiqueta. FormTextDelegate tiene texto y una descripción desactivada.

import QtQuick 2.15
import org.kde.kirigami 2.20 as Kirigami
import org.kde.kirigamiaddons.formcard 1.0 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 ™️")
        }
    }
}

Añadimos un texto de relleno para una hipotética detección de tema. Si queremos que se detecte realmente el esquema de color, se puede hacer posteriormente de forma similar a como se hace en Neochat (aquí tiene el código), que usa un modelo de C++ con KColorSchemeManager .

En la sección de «Cuentas en línea», vemos una propiedad adicional: leading. Podemos añadir un Item a ella para que aparezca antes del texto. La propiedad opuesta, trailing, permite mostrar un Item tras el texto, aunque no la usaremos en nuestro programa.

Aquí usamos un Kirigami.Icon por simplicidad, aunque también se puede usar un Kirigami.Avatar que obtiene la información de un modelo, como se hace en Neochat aquí.

Debería terminar pareciéndose a esto:

FormButtonDelegate

El FormButtonDelegate es visualmente similar a un FormTextDelegate, aunque se puede hacer clic sobre él y muestra una flecha que apunta hacia la derecha. Ya lo hemos usado en la introducción a los complementos de Kirigami.

Mientras que FormTextDelegate tiene las propiedades leading y trailing para mostrar un elemento antes y después del contenido principal, FormButtonDelegate solo tiene la propiedad leading, ya que la parte derecha está ocupada por la flecha.

import QtQuick 2.15
import org.kde.kirigami 2.20 as Kirigami
import org.kde.kirigamiaddons.formcard 1.0 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!")
        }
    }
}

Hemos usado la propiedad icon.name para hacer que aparezca un icono con el signo más (+) después del espacio donde aparecería leading y delante del contenido principal. Esto es un patrón común para indicar que el botón añadirá algo a una lista.

Dado que este ejemplo tiene fines ilustrativos sencillos, no profundizamos en lo que se haría tras pulsar el botón: solo muestra «¡Pulsado!» en la terminal. Podríamos crear una nueva página para crear una cuenta que añada otro usuario a un modelo y luego mostrar la página en la vista, de forma similar a lo que hicimos en main.qml.

FormRadioDelegate, FormCheckDelegate y FormSwitchDelegate

Los botones de opción, las casillas de verificación y los interruptores son componentes que se usan con mucha frecuencia en cualquier interfaz de usuario. Los complementos de Kirigami los proporcionan como FormRadioDelegate, FormCheckDelegate y FormSwitchDelegate.

Sus únicas propiedades principales son text y description. Se usan de forma diferente porque heredan de AbstractButton , por lo que se espera que use sus señales y manejadores: «checked» y «onChecked», «toggled» y «onToggled», «clicked» y «onClicked».

Queremos dotar de cierta funcionalidad para guardar automáticamente a nuestra aplicación, y solo queremos mostrar sus preferencias si el usuario ha activado dicha funcionalidad. Creamos una nueva sección usando una FormCard y una FormHeader, a la que añadiremos un FormSwitchDelegate y 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
    }
}

Vinculamos la visibilidad de cada botón de opción a un interruptor, por lo que solo aparecen cuando el interruptor está activado.

Para probar nuestra casilla de verificación, podemos añadir un nuevo FormCheckDelegate a nuestra sección «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í usamos el manejador de señal onToggled para mostrar un texto de relleno para simular un icono de la bandeja del sistema que aparece en el sistema. Si realmente lo necesita, podría implementar fácilmente un icono de la bandeja del sistema usando SystemTrayIcon.

Hasta ahora, nuestra aplicación debería parecerse a esto:

FormComboBoxDelegate

El componente común ComboBox se puede crear usando un FormComboBoxDelegate.

Esta lista desplegable tiene varias propiedades útiles que podemos usar: editable, displayText y displayMode.

Defina editable: true para permitir que el usuario pueda modificar el texto de la lista desplegable, que será de utilidad si necesita añadir nuevas opciones de la lista desplegable.

Siempre que necesite mostrar texto adicional antes de cada opción, puede usar algo semejante a displayText: "Perfil: " + textoActual:

Y la más interesante, que usaremos en nuestro ejemplo, es displayMode. Puede tener tres opciones:

  • FormComboBoxDelegate.ComboBox: el pequeño cuadro estándar que muestra una lista de opciones.
  • FormComboBoxDelegate.Dialog: un diálogo que muestra una lista de opciones en el centro de la ventana, como una Kirigami.OverlaySheet .
  • FormComboBoxDelegate.Page: una nueva página que contiene una lista de opciones que se muestran en una ventana separada.

Añada lo siguiente entre los delegados "Esquema de color actual" y "Mostrar bandeja del sistema" de la tarjeta "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"]
}

Con la casilla de verificación, nuestra página de «Preferencias» debería parecerse a esto:

FormDelegateSeparator

Nuestra página de «Preferencias» va tomando forma, aunque cada sección está empezando a ser demasiado larga. Podemos añadir unos cuantos FormDelegateSeparators para que la página quede más clara:

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

FormCard.FormCardPage {

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

    FormCard.FormCard {
        FormCard.FormTextDelegate {
            text: i18n("Current Color Scheme")
            description: "Breeze"
        }
        FormCard.FormComboBoxDelegate {
            id: combobox
            text: i18n("Default Profile")
            description: i18n("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: i18n("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: i18n("Autosave")
    }

    FormCard.FormCard {
        FormCard.FormSwitchDelegate {
            id: autosave
            text: i18n("Enabled")
        }
        FormCard.FormDelegateSeparator {
            above: autosave
            below: firstradio
            visible: autosave.checked
        }
        FormCard.FormRadioDelegate {
            id: firstradio
            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
        }
    }

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

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

Generalmente, puede usar separadores siempre que observe distinciones importantes entre los componentes, aunque la decisión de dónde colocarlos es, en última instancia, suya. Por ejemplo, en la sección «General», la casilla de verificación se diferencia de componentes anteriores en que no comienza con texto; en la sección «Guardar automáticamente», el separador agrupa los botones de opciones; y en la sección «Cuentas», si añade un separador entre la última cuenta y el botón, proporcionará un enfoque adicional para el botón.

Las propiedades above y below son casi autoexplicativas cuando se trata de su uso: se pasa el id de los componentes que hay por encima y por debajo del separador. Cuando se configuran, el separador desaparecerá rápidamente cada vez que se resalte o se coloque el cursor sobre el elemento de encima o de debajo. Son más útiles, por ejemplo, cuando necesita generar componentes dinámicamente y no puede asumir automáticamente el elemento que aparecerá inmediatamente antes o después del separador. Ese sería el caso en la sección «Cuentas» de nuestra aplicación una vez que se implementara la lógica para añadir nuevas cuentas, en cuyo caso siempre podríamos tomar el último elemento del modelo para hacerlo.

Observe cómo el separador sobre la preferencia del icono de la bandeja del sistema no aparece mientras está sobre él.