Делегати форми на наших сторінках параметрів

Створіть елегантні нетипові сторінки параметрів.

Додатки Kirigami — це додатковий набір візуальних компонентів, які добре працюють на мобільних пристроях і комп'ютерах і гарантовано є багатоплатформовими. З лаштунками вони використовують Kirigami для створення своїх компонентів.

Ви навчилися додавати сторінки About та AboutKDE до вашої програми. Тепер ви зможете використовувати їхні внутрішні компоненти для створення сторінок налаштувань.

Структура проєкту має виглядати так:

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

Потрібні зміни

Додамо новий рядок до нашого 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>

І внесемо зміни до main.qml так, щоб включити до нього нашу нову сторінку 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)
                }
            }
        }
    }
}

Тепер ми можемо розпочати перевірку компонентів, які використовуються для створення сторінки налаштувань: картки форми та її делегатів.

Делегати форми

FormCard і FormCardPage

FormCard.FormCard є головним компонентом, яким ми користуватимемося для групування його дочірніх компонентів, делегатів.

Раніше ми скористалися карткою форми у вступі до додатків Kirigami. Її основним призначенням є робота контейнером для інших компонентів, маючи колір, який відрізняється від кольору тла, подібно до Kirigami.Card .

Створіть файл contents/ui/SettingsPage.qml:

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

FormCard.FormCardPage {
    FormCard.FormCard {
        // Ось куди ми впишемо усі делегати!
    }

    FormCard.FormCard {
        // Ось куди ми впишемо усі делегати!
    }
}

Оскільки ми створюємо окремий файл QML для нашої сторінки налаштувань і оскільки нам потрібно підготуватися до можливого гортання нашої сторінки, ми використовуємо FormCard.FormCardPage, який успадковує Kirigami.ScrollablePage .

Приємна особливість сторінки картки форми полягає у тому, що вона має внутрішній макет, тому додатковий ColumnLayout не потрібен, і наших делегатів можна додавати безпосередньо до нього.

FormHeader

Для кожної FormCard, яку ви хочете створити, ви можете створити [FormHeader](https://api.kde.org /frameworks/kirigami-addons/html/classFormHeader.html) безпосередньо перед ним. У заголовку використовується напівжирний текст, який буде показано безпосередньо над карткою форми.

import org.kde.kirigamiaddons.formcard as FormCard

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

    FormCard.FormCard {
        // Тут будуть наші делегати…
    }

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

    FormCard.FormCard {
        // Тут будуть наші делегати…
    }
}

FormTextDelegate і FormSectionText

Розпочнімо із простого — звичайного тексту.

FormSectionText просто додає тонкий делегат, що містить мітку. FormTextDelegate містить текст і показаний сірим опис.

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

Ми додаємо деякий фіктивний текст для виявлення гіпотетичної теми. Якби ми хотіли мати фактичне визначення схеми кольорів, у майбутньому це можна було б зробити подібно до Neochat (код тут), використовуючи модель C++ із KColorSchemeManager .

У розділі «Облікові записи в інтернеті» ми бачимо додаткову властивість leading. Ми можемо додати до нього Item , щоб він з'являвся перед текстом. Його протилежна властивість, trailing, надає можливість показувати елемент після тексту, але ми не будемо використовувати його у нашій програмі.

Ми використовуємо тут Kirigami.Icon для простоти, але це також можна реалізувати за допомогою Kirigami.Avatar , який збирає інформацію з моделі, як це робиться у Neochat тут.

Врешті, маємо отримати таке:

FormButtonDelegate

FormButtonDelegate візуально схожий на FormTextDelegate, але його можна натиснути, і на ньому показано стрілку, що вказує праворуч. Раніше ми використовували його у вступі до додатків Kirigami.

У той час як FormTextDelegate мав властивості leading і trailing для показу елемента до та після основного вмісту, FormButtonDelegate має лише властивість leading, оскільки права сторона зайнята стрілкою.

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

Ми використовуємо його властивість icon.name, щоб установити піктограму плюса (+), яка з'являється після місця, де з'являтиметься leading, і перед основним вмістом. Це загальний шаблон, який вказує, що ваша кнопка додасть щось до списку.

Оскільки цей приклад наведено для простої ілюстрації, ми не заглиблюємось у те, що буде зроблено після натискання кнопки: він просто друкує "Clicked!" до терміналу. Ми можемо створити нову сторінку для створення облікового запису, яка додає іншого користувача до моделі, а потім розмістимо сторінку в полі зору, подібно до того, що ми зробили в main.qml.

FormRadioDelegate, FormCheckDelegate і FormSwitchDelegate

RadioButton, CheckBox і Switch є дуже поширеними компонентами для будь-якого інтерфейсу користувача. Додатки Kirigami надають їх як FormRadioDelegate, FormCheckDelegate і FormSwitchDelegate.

Їх єдиними основними властивостями є text і description. Вони відрізняються у використанні, тому що всі вони успадковують AbstractButton , і тому ви повинні використовувати його сигнали та обробники: checked і onChecked, toggled і onToggled, clicked і onClicked.

Ми хочемо створити деякі функції автозбереження у нашій програмі, і ми хочемо показувати її налаштування, лише якщо користувач увімкнув цю функцію. Створіть новий розділ за допомогою FormCard і [FormHeader](https://api.kde.org/frameworks/ kirigami-addons/html/classFormHeader.html), потім додайте FormSwitchDelegate і [FormRadioDelegate](https:// api.kde.org/frameworks/kirigami-addons/html/classFormRadioDelegate.html).

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

Ми пов'яжемо видимість кожного пункту варіанта із перемикачем, тому їх буде показано, лише якщо увімкнено перемикач.

Щоб перевірити наш пункт варіанта, ми можемо додати новий FormCheckDelegate до нашого розділу «Загальне».

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

Тут ми використовуємо onToggled обробник сигналів, щоб показати деякий фіктивний текст для імітації піктограми у лотку, що з'являється у системі. Якщо ви справді захочете, ви можете легко додати піктограму у лотку за допомогою SystemTrayIcon.

На цьому кроці вікно нашої програми має виглядати так:

FormComboBoxDelegate

Типовий компонент ComboBox можна створити за допомогою FormComboBoxDelegate.

Цей спадний список має декілька корисних властивостей, якими ми можемо скористатися: editable, displayText and displayMode.

Налаштування editable: true надає змогу користувачеві редагувати текст спадного списку, що корисно, якщо потрібно додати нові пункти до спадного списку:

Щоразу, коли вам потрібно показати додатковий текст перед кожним пунктом, ви можете використати щось подібне до displayText: "Profile: " + currentText:

І найцікавішим, який ми будемо використовувати в нашому прикладі, є displayMode. Він може мати три варіанти:

  • FormComboBoxDelegate.ComboBox: стандартна мала панель зі списком пунктів.
  • FormComboBoxDelegate.Dialog: діалогове вікно, у якому буде показано список пунктів посередині вікна, подібне до Kirigami.OverlaySheet .
  • FormComboBoxDelegate.Page: нова сторінка, що містить список пунктів, які показано в окремому вікні.

Додайте таке між делегатами "Current Color Scheme" і "Show Tray Icon" у картці форми "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"]
}

З пунктом для позначки наша сторінка «Параметри» має виглядати так:

FormDelegateSeparator

Наша сторінка налаштувань набуває форми, але її розділи стають надто довгими. Ми можемо додати кілька FormDelegateSeparators, щоб зробити нашу сторінку більш охайною:

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

Як правило, ви можете використовувати роздільники щоразу, коли бачите великі відмінності між компонентами, хоча вибір місця їх розміщення залишається за вами. Наприклад, у розділі «Загальні» пункт варіанта відрізняється від попередніх компонентів тим, що він не починається з тексту; у розділі автозбереження роздільник об'єднує перемикачі; а в розділі «Облікові записи» додавання роздільника між останнім обліковим записом і кнопкою забезпечує додатковий акцент на кнопці.

Властивості above і below досить зрозумілі, коли йдеться про їхнє використання: ви передаєте id компонентів над і під роздільником. Коли їх установлено, роздільник швидко зникатиме, при підсвічуванні або наведенні вказівника миші на пункт вище або нижче. Вони найбільш корисні, наприклад, коли вам потрібно генерувати компоненти динамічно, а ви не можете автоматично спрогнозувати, який елемент буде безпосередньо перед роздільником або після нього. Так було б у розділі «Облікові записи» нашої програми, де було реалізовано логіку додавання нових облікових записів, коли ми завжди могли б отримати останній елемент у моделі, щоб зробити це.

Зверніть увагу на те, що роздільник над налаштуванням піктограми у лотку не з'являється, якщо на нього навести вказівник.