Contacts
We will need a handful of new UI components to manage our contacts. We’ve previously worked with an AddressEditor to look after our address details, so we’ll continue in that mold and create a ContactEditor component. This component will display our collection of contacts, each of which will be represented by a ContactDelegate. Upon initially creating a new Client object, there won’t be any contacts, so we also need some way for the user to add a new one. We’ll enable that with a button press, and we’ll create a new component for buttons we can add to a content view. Let’s do that first.
To support this new component, as usual, we’ll go ahead and add some properties to Style:
readonly property real widthFormButton: 240 readonly property real heightFormButton: 60 readonly property color colourFormButtonBackground: "#f36f24" readonly property color colourFormButtonFont: "#ffffff" readonly property int pixelSizeFormButtonIcon: 32 readonly property int pixelSizeFormButtonText: 22 readonly property int sizeFormButtonRadius: 5
Create FormButton.qml in cm-ui/components:
import QtQuick 2.9 import CM 1.0 import assets 1.0
Item { property alias iconCharacter: textIcon.text property alias description: textDescription.text signal formButtonClicked() width: Style.widthFormButton height: Style.heightFormButton
Rectangle { id: background anchors.fill: parent color: Style.colourFormButtonBackground radius: Style.sizeFormButtonRadius
Text { id: textIcon anchors { verticalCenter: parent.verticalCenter left: parent.left margins: Style.heightFormButton / 4 } font { family: Style.fontAwesome pixelSize: Style.pixelSizeFormButtonIcon } color: Style.colourFormButtonFont text: "uf11a" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter }
Text { id: textDescription anchors { left: textIcon.left bottom: parent.bottom top: parent.top right: parent.right } font.pixelSize: Style.pixelSizeFormButtonText color: Style.colourFormButtonFont text: "SET ME!!" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter }
MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor hoverEnabled: true onEntered: background.state = "hover" onExited: background.state = "" onClicked: formButtonClicked() }
states: [ State { name: "hover" PropertyChanges { target: background color: Qt.darker(Style.colourFormButtonBackground) } } ] } }
Here, we combine aspects of the NavigationButton and CommandButton controls we wrote earlier in the book. The only real difference is that it is intended for more free-form use in the main content frame rather than being constrained to one of the toolbars.
Next, let’s add the component we’ll use to display/edit a single Contact object. Create ContactDelegate.qml in cm-ui/components:
import QtQuick 2.9 import CM 1.0 import assets 1.0
Item { property Contact contact implicitWidth: flow.implicitWidth implicitHeight: flow.implicitHeight + borderBottom.implicitHeight + Style.sizeItemMargin height: width > selectorType.width + textAddress.width + Style.sizeScreenMargin ? selectorType.height + borderBottom.height + Style.sizeItemMargin : selectorType.height + textAddress.height + Style.sizeScreenMargin + borderBottom.height + Style.sizeItemMargin
Flow { id: flow width: parent.width spacing: Style.sizeScreenMargin
EnumeratorSelector { id: selectorType width: Style.widthDataControls dropDown: contact.ui_contactTypeDropDown enumeratorDecorator: contact.ui_contactType }
StringEditorSingleLine { id: textAddress width: Style.widthDataControls stringDecorator: contact.ui_address } }
Rectangle { id: borderBottom anchors { top: flow.bottom left: parent.left right: parent.right topMargin: Style.sizeItemMargin } height: 1 color: Style.colorItemBorder } }
This is much the same as the RssItemDelegate we added in Chapter 8, Web Requests. We add our new EnumeratorSelector and bind it to the ui_contactType property, using ui_contactTypeDropDown to provide the control with the drop-down information it needs.
Create ContactsEditor.qml in cm-ui/components:
import QtQuick 2.9 import CM 1.0 import assets 1.0
Panel { property Client client id: contactsEditorRoot contentComponent: Column { id: column spacing: Style.sizeControlSpacing
Repeater { id: contactsView model: client.ui_contacts delegate: ContactDelegate { width: contactsEditorRoot.width contact: modelData } }
FormButton { iconCharacter: "uf067" description: "Add Contact" onFormButtonClicked: { client.addContact(); } } } }
We’ve already done all the hard work in our ContactDelegate and FormButton controls, so this is really short and sweet. We add everything to a Panel so that the look and feel will be consistent with the rest of the views. We use another Repeater so that we can spin up a ContactDelegate for every contact in the collection and immediately after the contacts, we display a button to add a new contact to the list. In order to do this, we call the addContact() method we added earlier in this chapter.
Now, we just need to add instances of our ContactsEditor to the CreateClientView:
ContactsEditor { width: scrollView.width client: newClient headerText: "Contact Details" }
We can also use the same component in EditClientView:
ContactsEditor { width: scrollView.width client: selectedClient headerText: "Contact Details" }
That’s it. Build and Run, and you can add and edit contacts to your heart’s content:
Once you save a new client, if you take a look at the database, you will see that the contacts array has been updated accordingly, as highlighted in the following screenshot:
All that’s left now is the appointments collection, and we’ve already covered all the skills you need to tackle that, so we’ll leave that as an exercise for the reader and move on to the final topic—deploying our application to our end users.