Розподіл громіздкого коду між різними файлами і долучення сигналів до ваших компонентів.
Але чому?
Ми вперше відокремлюємо деякі з наших компонентів у окремі файли QML. Якщо ми продовжуватимемо додавати код до main.qml, розростання файла ускладнить розбір його частин і збільшить ризик помилок у нашому коді.
Спочатку нам слід додати наші нові файли до нашого resources.qrc, який ми створили у першій частині цього розділу підручника.
Нам слід знайти якийсь спосіб використання наших нових файлів у main.qml. На щастя, нам достатньо просто включити оголошення цих компонентів у наш main.qml ось так:
AddEditSheet{id: addEditSheet}
Розширюємо можливості нашого аркуша додавання так, щоб він став аркушем додавання-редагування
Хоча у останній частині підручника ми додали до кнопки додавання відліку дії, кнопка редагування наших карток відліку усе ще лишається неактивною. Нами також було створено аркуш додавання відліків, якими ми тепер можемо повторно скористатися як аркушем редагування... Але перш ніж ми перейдемо до цього, нам слід додати до нашого main.qml ще двійко додаткових речей.
importQtQuick2.15importQtQuick.Controls2.15asControlsimportQtQuick.Layouts1.15importorg.kde.kirigami2.20asKirigamiKirigami.ApplicationWindow{id: roottitle:i18nc("@title:window","Day Kountdown")globalDrawer:Kirigami.GlobalDrawer{isMenu:trueactions:[Kirigami.Action{text:i18n("Quit")icon.name:"gtk-quit"shortcut:StandardKey.QuitonTriggered:Qt.quit()}]}ListModel{id: kountdownModel}// Fetches item from addEditSheet.qml and does action on signal
AddEditSheet{id: addEditSheetonAdded:kountdownModel.append({"name":name,"description":description,"date":Date.parse(kdate)});onEdited:kountdownModel.set(index,{"name":name,"description":description,"date":Date.parse(kdate)});onRemoved:kountdownModel.remove(index,1)}// Function called by 'edit' button on card and by 'add'-Action
functionopenPopulatedSheet(mode,index=-1,listName="",listDesc="",listDate=""){addEditSheet.mode=modeaddEditSheet.index=index;addEditSheet.name=listNameaddEditSheet.description=listDescaddEditSheet.kdate=listDateaddEditSheet.open()}pageStack.initialPage:Kirigami.ScrollablePage{title:i18nc("@title","Kountdown")// Kirigami.Action encapsulates a UI action. Inherits from Controls.Action
actions.main:Kirigami.Action{id: addAction// Name of icon associated with the action
icon.name:"list-add"// Action text, i18n function returns translated string
text:i18nc("@action:button","Add kountdown")// What to do when triggering the action
onTriggered:openPopulatedSheet("add")}Kirigami.CardsListView{id: layoutmodel:kountdownModeldelegate:KountdownDelegate{}}}}
Ключовими внесеними змінами є додавання нашого визначення компонента AddEditSheet (і KountdownDelegate нижче) і нової функції із назвою openPopulatedSheet().
onAdded і onEdited є обробниками сигналів. Подібно до того, як onTriggered викликається, коли ми натискаємо пункт дії, ми можемо скористатися обробниками, які відповідають на наші нетипові сигнали.
AddEditSheet.qml
Поглянувши на наш новий AddEditSheet.qml — наш конвертований аркуш додавання — ми можемо бачити, як працюють ці сигнали:
importQtQuick2.15importQtQuick.Controls2.15asControlsimportQtQuick.Layouts1.15importorg.kde.kirigami2.20asKirigami// Overlay sheets appear over a part of the window
Kirigami.OverlaySheet{id: addEditSheet// Sheet mode
propertystringmode:"add"propertyintindex:-1propertyaliasname:nameField.textpropertyaliasdescription:descriptionField.textpropertyaliaskdate:dateField.text// Signals can be read and certain actions performed when these happen
signaladded(stringname,stringdescription,varkdate)signaledited(intindex,stringname,stringdescription,varkdate)signalremoved(intindex)header:Kirigami.Heading{// i18nc is useful for adding context for translators
text:mode==="add"?i18nc("@title:window","Add kountdown"):i18nc("@title:window","Edit kountdown")}// Form layouts help align and structure a layout with several inputs
Kirigami.FormLayout{// Textfields let you input text in a thin textbox
Controls.TextField{id: nameField// Provides label attached to the textfield
Kirigami.FormData.label:i18nc("@label:textbox","Name:")// Placeholder text is visible before you enter anything
placeholderText:i18n("Event name (required)")// What to do after input is accepted (i.e. pressed enter)
// In this case, it moves the focus to the next field
onAccepted:descriptionField.forceActiveFocus()}Controls.TextField{id: descriptionFieldKirigami.FormData.label:i18nc("@label:textbox","Description:")placeholderText:i18n("Optional")onAccepted:dateField.forceActiveFocus()}Controls.TextField{id: dateFieldKirigami.FormData.label:i18nc("@label:textbox","Date:")inputMask:"0000-00-00"placeholderText:i18n("YYYY-MM-DD")}// This is a button.
Controls.Button{id: deleteButtonLayout.fillWidth:truetext:i18nc("@action:button","Delete")visible:mode==="edit"onClicked:{addEditSheet.removed(addEditSheet.index)close();}}Controls.Button{id: doneButtonLayout.fillWidth:truetext:i18nc("@action:button","Done")// Button is only enabled if the user has entered something into the nameField
enabled:nameField.text.length>0onClicked:{// Add a listelement to the kountdownModel ListModel
if(mode==="add"){addEditSheet.added(nameField.text,descriptionField.text,dateField.text);}else{addEditSheet.edited(index,nameField.text,descriptionField.text,dateField.text);}close();}}}}
Сигнали викликають обробники при виклику. У нашому випадку, ми створили два сигнали, added та edited, які ми можемо викликати для отримання різних результатів, і з якими ми можемо пов'язати відомості щодо відліку, який ми додаємо або створюємо. Чудовою властивістю сигналів є те, що вони розкривають змінні, які у них визначено для функцій, які очікують на сигнали. Ось чому ми можемо просто викликати назви цих змінних у наших обробниках onEdited і onAdded у main.qml. Наші сигнали викликає кнопка «Done», залежно від значення, встановленого для властивості mode, визначеної у верхній частині нашого AddEditSheet.
Крім того, властивість mode керує декількома іншими речима: в основному, тим, який заголовок буде встановлено для нашого аркуша, і який текст буде включено до наших текстових полів. Втім, типово, для нашої властивості mode просто встановлено режим додавання...
Що повертає нас до main.qml і нашої нової функції openPopulatedSheet(). Ви могли помітити, що це саме те, що буде тепер викликано при вмиканні дії з додавання відліку. Ця функція приймає декілька аргументів, які мають типові значення. Це корисно, коли ми просто хочемо додати новий відлік, оскільки ми можемо скористатися скороченим викликом функції — openPopulatedSheet("add"). Що важливіше, ця функція встановлює значення усіх пов'язаних із її призначенням властивостей в AddEditSheet.
mode змінює аркуш додавання-редагування залежно від встановленого аргументу: «add» або «"edit"
Аргумент index потрібен для того, щоб при збереження нашого редагованого відліку було внесено зміни до належного запису
listName, listDesc і listDate — відповідні параметри відліків, які має бути вписано у поля аркуша
Звичайно, щоб справді скористатися нашим аркушем для чогось, окрім додавання відліків, нам спершу слід зробити працездатною кнопку редагування на наших картках. Але, якщо ви поглянете на нашу
Kirigami.CardsListView
у main.qml...
importQtQuick2.15importQtQuick.Controls2.15asControlsimportQtQuick.Layouts1.15importorg.kde.kirigami2.20asKirigamiKirigami.AbstractCard{id: kountdownDelegatecontentItem:Item{implicitWidth:delegateLayout.implicitWidthimplicitHeight:delegateLayout.implicitHeightGridLayout{id: delegateLayoutanchors{left:parent.lefttop:parent.topright:parent.right}rowSpacing:Kirigami.Units.largeSpacingcolumnSpacing:Kirigami.Units.largeSpacingcolumns:root.wideScreen?4:2Kirigami.Heading{Layout.fillHeight:truelevel:1text:i18n("%1 days",Math.round((date-Date.now())/86400000))}ColumnLayout{Kirigami.Heading{Layout.fillWidth:truelevel:2text:name}Kirigami.Separator{Layout.fillWidth:truevisible:description.length>0}Controls.Label{Layout.fillWidth:truewrapMode:Text.WordWraptext:descriptionvisible:description.length>0}}Controls.Button{Layout.alignment:Qt.AlignRight// Column spanning within grid layout (vertically in this case)
Layout.columnSpan:2text:i18n("Edit")onClicked:openPopulatedSheet("edit",index,name,description,newDate(date).toISOString().slice(0,10))}}}}
Тепер властивість
onClicked
кнопки «Edit» на наших картках викликає функцію openPopulateSheet() із отриманими карткою властивостями елементів списку як аргументами цієї функції. Ці дані надають змогу заповнити аркуш належними текстовими даними.
Тепер ми маємо повнофункціональний аркуш, за допомогою якого ми можемо додавати і редагувати наші відліки!