Skip to main content
Ir para o conteúdo

Formulário delegados em suas páginas de configurações

Crie páginas de configurações personalizadas e elegantes.

Os Addons do Kirigami é um conjunto adicional de componentes visuais que funcionam bem em dispositivos móveis e desktops, com garantia de compatibilidade entre plataformas. Ele utiliza Kirigami internamente para criar seus componentes.

Você aprendeu como adicionar as páginas About e AboutKDE ao seu aplicativo. Agora você poderá usar os mesmos componentes internos para criar suas páginas de configurações.

A estrutura do projeto deve ser semelhante a esta:

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

Alterações necessárias

Altere Main.qml para incluir nossa nova página de configurações:

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)
                }
            }
        }
    }
}

Agora podemos começar a verificar os componentes usados ​​para criar nossa página de Configurações: o Cartão de Formulário e seus Delegados.

Formulários delegados

FormCard e FormCardPage

FormCard.FormCard é o componente principal que usaremos para agrupar todos os seus componentes filhos, os Delegados.

Usamos um cartão de formulário na introdução aos Addons do Kirigami anteriormente. Seu principal objetivo é servir como um contêiner para outros componentes, seguindo uma cor diferente do fundo, de forma semelhante a um Kirigami.Card.

Crie um novo arquivo SettingsPage.qml:

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

FormCard.FormCardPage {
    FormCard.FormCard {
        // É aqui que todos os nossos delegados vão!
    }

    FormCard.FormCard {
        // É aqui que todos os nossos delegados vão!
    }
}

Como estamos criando um arquivo QML separado para nossa página de Configurações e como precisamos nos preparar para uma possível rolagem em nossa página, usamos um FormCard.FormCardPage, que herda Kirigami.ScrollablePage.

O interessante da página do cartão de formulário é que ela vem com um layout interno, portanto, nenhum ColumnLayout adicional é necessário e nossos delegados podem ser adicionados diretamente a ela.

FormHeader

Para cada FormCard que você deseja criar, você pode criar um FormHeader logo antes dele. O cabeçalho usa texto em negrito e aparece logo acima do cartão de formulário.

import org.kde.kirigamiaddons.formcard as FormCard

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

    FormCard.FormCard {
        // Nossos delegados vão aqui...
    }

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

    FormCard.FormCard {
        // Nossos delegados vão aqui...
    }
}

FormTextDelegate e FormSectionText

Vamos começar de forma simples, com texto simples.

FormSectionText simplesmente adiciona um delegado fino contendo um rótulo. FormTextDelegate tem texto e uma descrição em cinza.

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 ™️")
        }
    }
}

Adicionamos um texto fictício para a detecção hipotética do tema. Se quiséssemos ter uma detecção real do esquema de cores, no futuro isso poderia ser feito de forma semelhante ao Neochat (código aqui), utilizando um modelo C++ com KColorSchemeManager.

Na seção Contas Online, vemos uma propriedade adicional, leading. Podemos adicionar um Item a ela para que apareça antes do texto. Sua propriedade oposta, trailing, seria capaz de mostrar um Item após o texto, mas não a usaremos em nosso programa.

Usamos um Kirigami.Icon aqui para simplificar, mas isso também pode ser implementado usando um Avatar do Kirigami que obtém as informações de um modelo, como é feito no Neochat.

Deve ficar assim:

FormButtonDelegate

O FormButtonDelegate é visualmente semelhante a um FormTextDelegate, mas é clicável e exibe uma seta apontando para a direita. Já o usamos na introdução aos Addons do Kirigami anteriormente.

Enquanto o FormTextDelegate tinha as propriedades leading e trailing para mostrar um item antes e depois do conteúdo principal, o FormButtonDelegate possui apenas a propriedade leading, porque o lado direito é ocupado pela seta.

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!")
        }
    }
}

Usamos a propriedade icon.name para definir um ícone de mais (+) que aparecerá após o espaço onde o leading apareceria e antes do conteúdo principal. Este é um padrão comum para indicar que seu botão adicionará algo a uma lista.

Como este exemplo é apenas para fins ilustrativos, não nos aprofundamos no que seria feito quando o botão fosse clicado: ele apenas imprime "Clicado!" no terminal. Poderíamos criar uma nova página para criação de conta que adicionasse outro usuário a um modelo e, em seguida, colocasse a página na visualização, semelhantemente ao que fizemos em Main.qml.

FormRadioDelegate, FormCheckDelegate e FormSwitchDelegate

O RadioButton, o CheckBox e o Switch são componentes muito utilizados em qualquer interface de usuário. Os Addons do Kirigami os fornece como FormRadioDelegate, FormCheckDelegate e FormSwitchDelegate.

Suas únicas propriedades principais são text e description. Elas são diferentes no uso porque todas herdam AbstractButton, e portanto, espera-se que você use seus sinais e manipuladores: checked e onChecked, toggled e onToggled, clicked e onClicked.

Queremos criar uma funcionalidade de salvamento automático em nosso aplicativo e queremos mostrar suas configurações apenas se o usuário tiver habilitado essa funcionalidade. Crie uma nova seção usando um FormCard e um FormHeader, depois adicione um FormSwitchDelegate e um 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
    }
}

Nós vinculamos a visibilidade de cada botão de opção a um botão de opção, para que eles só apareçam quando o botão estiver habilitado.

Para testar nossa caixa de seleção, podemos adicionar um novo FormCheckDelegate à nossa seção Geral.

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!")
            }
        }
    }
}

Aqui, usamos o manipulador de sinais onToggled para exibir um texto fictício que simula um ícone de bandeja aparecendo no sistema. Se você realmente quisesse, poderia facilmente implementar um ícone de bandeja usando o KStatusNotifierItem do KDE ou o SystemTrayIcon do Qt.

Até agora, nossa aplicação deve ficar assim:

FormComboBoxDelegate

O componente ComboBox comum pode ser criado usando um FormComboBoxDelegate.

Esta combobox possui diversas propriedades úteis que podemos utilizar: editable, displayText e displayMode.

Definir editable: true permite que o usuário edite o texto do combobox, o que é útil caso seja necessário adicionar novas opções ao combobox:

Sempre que precisar mostrar texto adicional antes de cada opção, você pode usar algo como displayText: "Perfil: " + currentText:

E o mais interessante, que usaremos em nosso exemplo, é o displayMode. Ele pode ter três opções:

  • FormComboBoxDelegate.ComboBox: a pequena caixa padrão mostrando uma lista de opções.
  • FormComboBoxDelegate.Dialog: uma caixa de diálogo que mostra uma lista de opções no meio da janela, como uma Kirigami.OverlaySheet.
  • FormComboBoxDelegate.Page: uma nova página contendo uma lista de opções exibidas em uma janela separada.

Adicione o seguinte entre os delegados "Esquema de cores atual" e "Mostrar ícone da bandeja" no seu cartão de formulário "Geral".

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"]
}

Com a caixa de seleção, nossa página Configurações deve ficar assim:

FormDelegateSeparator

Nossa página de Configurações está tomando forma, mas cada seção está começando a ficar longa. Podemos adicionar alguns FormDelegateSeparator para deixar nossa página mais organizada:

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!")
        }
    }
}

Geralmente, você pode usar separadores sempre que notar grandes distinções entre componentes, embora a escolha de onde colocá-los seja, em última análise, sua. Por exemplo, na seção Geral, a caixa de seleção difere de seus componentes anteriores, pois não começa com texto; na seção Salvamento automático, o separador agrupa os botões de opção; e na seção Contas, adicionar um separador entre a última conta e o botão fornece algum foco adicional ao botão.

As propriedades above e below são bastante autoexplicativas quando se trata de seu uso: você passa o id dos componentes acima e abaixo do separador. Quando elas são definidas, o separador desaparece rapidamente sempre que o item acima ou abaixo é destacado/passado pelo mouse. Elas são mais úteis, por exemplo, quando você precisa gerar componentes dinamicamente e não pode presumir automaticamente qual item virá imediatamente antes ou depois do separador. Esse seria o caso na seção Contas da nossa aplicação uma vez que a lógica para adicionar novas contas fosse implementada, nesse caso sempre poderíamos pegar o último item do modelo para fazer isso.

Observe como o separador acima da configuração do ícone da bandeja não aparece enquanto o mouse passa por ele.