From c586b9be1e9337c54261ba67cf732f992778457c Mon Sep 17 00:00:00 2001 From: Noelia <97019400+noeliaSD@users.noreply.github.com> Date: Mon, 4 Apr 2022 12:16:47 +0200 Subject: [PATCH] feat(StatusQ.Components/Controls): New `StatusListPicker` and `StatusItemPicker` selector component / control (#583) It adds the `StatusItemPicker` control and `StatusListPicker` component and its corresponding documentation. The new selector component is composed by a `StatusButtonPicker` and a drop-down list. It adds sections in `ListView` by using `category` model property. It incorporates a searcher in header. The selector type can be customised as a `StatusRadioButton` or a `StatusCheckbox`. It adds dynamic selection mechanism. It adds a dynamic text fit between `name` and `shortName` text components. It adds a specific page in `sandbox` and some models to play with that. It extends `StatusPickerButton` to allow more than one type. Closes #563 --- .../doc/src/images/status_item_picker.png | Bin 0 -> 7635 bytes .../doc/src/images/status_list_picker.png | Bin 0 -> 40836 bytes ui/StatusQ/doc/src/statusqcomponents.qdoc | 1 + ui/StatusQ/doc/src/statusqcontrols.qdoc | 1 + ui/StatusQ/sandbox/demoapp/data/Models.qml | 305 +++++++++++++++++ ui/StatusQ/sandbox/main.qml | 5 + .../sandbox/pages/StatusListPickerPage.qml | 78 +++++ .../StatusQ/Components/StatusListPicker.qml | 324 ++++++++++++++++++ ui/StatusQ/src/StatusQ/Components/qmldir | 1 + .../src/StatusQ/Controls/StatusItemPicker.qml | 183 ++++++++++ .../StatusQ/Controls/StatusPickerButton.qml | 66 +++- ui/StatusQ/src/StatusQ/Controls/qmldir | 1 + ui/StatusQ/statusq.qrc | 2 + 13 files changed, 949 insertions(+), 18 deletions(-) create mode 100644 ui/StatusQ/doc/src/images/status_item_picker.png create mode 100644 ui/StatusQ/doc/src/images/status_list_picker.png create mode 100644 ui/StatusQ/sandbox/pages/StatusListPickerPage.qml create mode 100644 ui/StatusQ/src/StatusQ/Components/StatusListPicker.qml create mode 100644 ui/StatusQ/src/StatusQ/Controls/StatusItemPicker.qml diff --git a/ui/StatusQ/doc/src/images/status_item_picker.png b/ui/StatusQ/doc/src/images/status_item_picker.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e09161142e6aa3ddddf05fb7c25917b5acace4 GIT binary patch literal 7635 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 CsrSGD literal 0 HcmV?d00001 diff --git a/ui/StatusQ/doc/src/images/status_list_picker.png b/ui/StatusQ/doc/src/images/status_list_picker.png new file mode 100644 index 0000000000000000000000000000000000000000..f68fc422aa5546ad1fa027db6b605648db1936da GIT binary patch literal 40836 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 literal 0 HcmV?d00001 diff --git a/ui/StatusQ/doc/src/statusqcomponents.qdoc b/ui/StatusQ/doc/src/statusqcomponents.qdoc index ca394ecaa0..8a27a89436 100644 --- a/ui/StatusQ/doc/src/statusqcomponents.qdoc +++ b/ui/StatusQ/doc/src/statusqcomponents.qdoc @@ -22,6 +22,7 @@ \li \l{StatusDescriptionListItem} \li \l{StatusLetterIdenticon} \li \l{StatusListItem} + \li \l{StatusListPicker} \li \l{StatusListSectionHeadline} \li \l{StatusLoadingIndicator} \li \l{StatusMemberListItem} diff --git a/ui/StatusQ/doc/src/statusqcontrols.qdoc b/ui/StatusQ/doc/src/statusqcontrols.qdoc index fd022549bb..aee3af6737 100644 --- a/ui/StatusQ/doc/src/statusqcontrols.qdoc +++ b/ui/StatusQ/doc/src/statusqcontrols.qdoc @@ -32,6 +32,7 @@ \li \l{StatusBaseInput} \li \l{StatusIdenticonRing} \li \l{StatusInput} + \li \l{StatusItemPicker} \li \l{StatusPickerButton} \li \l{StatusPinInput} \li \l{StatusProgressBar} diff --git a/ui/StatusQ/sandbox/demoapp/data/Models.qml b/ui/StatusQ/sandbox/demoapp/data/Models.qml index 63828103b4..930120bd78 100644 --- a/ui/StatusQ/sandbox/demoapp/data/Models.qml +++ b/ui/StatusQ/sandbox/demoapp/data/Models.qml @@ -1052,4 +1052,309 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I notificationsCount: 0 } } + + property ListModel currencyPickerModel: ListModel { + ListElement { + key: 0 + name: "United States Dollar" + shortName: "USD" + symbol: "$" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "" + selected: false + } + ListElement { + key: 1 + name: "British Pound" + shortName: "GBP" + symbol: "£" + imageSource: "../../assets/twemoji/26x26/1f4b5.png" + category: "" + selected: false + } + ListElement { + key: 2 + name: "Euro" + shortName: "EUR" + symbol: "€" + imageSource: "../../assets/twemoji/26x26/1f4b6.png" + category: "" + selected: true + } + ListElement { + key: 3 + name: "Shout Korean Won" + shortName: "KRW" + symbol: "₩" + imageSource: "../../assets/twemoji/26x26/1f4b8.png" + category: "" + selected: false + } + ListElement { + key: 4 + name: "Ethereum" + shortName: "ETH" + symbol: "Ξ" + imageSource: "../../assets/twemoji/26x26/1f4b7.png" + category: "Tokens" + selected: true + } + ListElement { + key: 5 + name: "Bitcoin" + shortName: "BTC" + symbol: "฿" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "Tokens" + selected: false + } + ListElement { + key: 6 + name: "Status Network Token" + shortName: "SNT" + symbol: "" + imageSource: "../../assets/twemoji/26x26/1f4b8.png" + category: "Tokens" + selected: false + } + + ListElement { + key: 7 + name: "Emirati Dirham" + shortName: "AED" + symbol: "د.إ" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "Other Fiat" + selected: false + } + ListElement { + key: 8 + name: "Afghani" + shortName: "AFN" + symbol: "؋" + imageSource: "../../assets/twemoji/26x26/1f4b7.png" + category: "Other Fiat" + selected: false + } + ListElement { + key: 9 + name: "Argentine Peso" + shortName: "AFN" + symbol: "$" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "Other Fiat" + selected: false + } + } + + property ListModel currencyPickerModel2: ListModel { + ListElement { + key: 0 + name: "United States Dollar" + shortName: "USD" + symbol: "$" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "" + selected: false + } + ListElement { + key: 1 + name: "British Pound" + shortName: "GBP" + symbol: "£" + imageSource: "../../assets/twemoji/26x26/1f4b5.png" + category: "" + selected: false + } + ListElement { + key: 2 + name: "Euro" + shortName: "EUR" + symbol: "€" + imageSource: "../../assets/twemoji/26x26/1f4b6.png" + category: "" + selected: true + } + ListElement { + key: 3 + name: "Shout Korean Won" + shortName: "KRW" + symbol: "₩" + imageSource: "../../assets/twemoji/26x26/1f4b8.png" + category: "" + selected: false + } + ListElement { + key: 4 + name: "Ethereum" + shortName: "ETH" + symbol: "Ξ" + imageSource: "../../assets/twemoji/26x26/1f4b7.png" + category: "Tokens" + selected: true + } + ListElement { + key: 5 + name: "Bitcoin" + shortName: "BTC" + symbol: "฿" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "Tokens" + selected: false + } + ListElement { + key: 6 + name: "Status Network Token" + shortName: "SNT" + symbol: "" + imageSource: "../../assets/twemoji/26x26/1f4b8.png" + category: "Tokens" + selected: false + } + + ListElement { + key: 7 + name: "Emirati Dirham" + shortName: "AED" + symbol: "د.إ" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "Other Fiat" + selected: false + } + ListElement { + key: 8 + name: "Afghani" + shortName: "AFN" + symbol: "؋" + imageSource: "../../assets/twemoji/26x26/1f4b7.png" + category: "Other Fiat" + selected: false + } + ListElement { + key: 9 + name: "Argentine Peso" + shortName: "AFN" + symbol: "$" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "Other Fiat" + selected: false + } + } + + property ListModel languagePickerModel: ListModel { + ListElement { + key: 0 + name: "English" + shortName: "English" + imageSource: "../../assets/twemoji/26x26/1f1ec-1f1e7.png" + category: "" + selected: false + } + ListElement { + key: 1 + name: "Korean" + shortName: "한국어" + imageSource: "../../assets/twemoji/26x26/1f1f0-1f1f7.png" + category: "" + selected: false + } + ListElement { + key: 2 + name: "Portuguese (Brazilian)" + shortName: "Português" + imageSource: "../../assets/twemoji/26x26/1f1e7-1f1f7.png" + category: "" + selected: true + } + ListElement { + key: 3 + name: "Dutch" + shortName: "Nederlands" + imageSource: "../../assets/twemoji/26x26/1f1f3-1f1f1.png" + category: "Beta Languages" + selected: false + } + ListElement { + key: 4 + name: "Indonesian" + shortName: "Bahasa Indonesia" + imageSource: "../../assets/twemoji/26x26/1f1ee-1f1e9.png" + category: "Beta Languages" + selected: false + } + ListElement { + key: 5 + name: "Spanish" + shortName: "Español" + imageSource: "../../assets/twemoji/26x26/1f1ea-1f1e6.png" + category: "Beta Languages" + selected: false + } + } + + property ListModel languageNoImagePickerModel: ListModel { + ListElement { + key: 0 + name: "Chinese (Mainland China)" + shortName: "普通话" + category: "" + selected: true + } + ListElement { + key: 1 + name: "Russian" + shortName: "Русский Язык" + category: "" + selected: false + } + ListElement { + key: 2 + name: "Arabic" + shortName: "اَلْعَرَبِيَّةُ" + category: "Beta Languages" + selected: true + } + ListElement { + key: 3 + name: "Chinese (Taiwan)" + shortName: "臺灣華語" + category: "Beta Languages" + selected: false + } + ListElement { + key: 4 + name: "Filipino" + shortName: "Wikang Filipino" + category: "Beta Languages" + selected: false + } + ListElement { + key: 5 + name: "French" + shortName: "Français" + category: "Beta Languages" + selected: false + } + ListElement { + key: 6 + name: "Italian" + shortName: "Italiano" + category: "Beta Languages" + selected: false + } + ListElement { + key: 7 + name: "Turkish" + shortName: "Türkçe" + category: "Beta Languages" + selected: false + } + ListElement { + key: 8 + name: "Urdu" + shortName: "اُردُو" + category: "Beta Languages" + selected: false + } + } } diff --git a/ui/StatusQ/sandbox/main.qml b/ui/StatusQ/sandbox/main.qml index 608f01b564..0e75f1f731 100644 --- a/ui/StatusQ/sandbox/main.qml +++ b/ui/StatusQ/sandbox/main.qml @@ -275,6 +275,11 @@ StatusWindow { selected: viewLoader.source.toString().includes(title) onClicked: mainPageView.page(title); } + StatusNavigationListItem { + title: "StatusListPicker" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } StatusListSectionHeadline { text: "StatusQ.Popup" } StatusNavigationListItem { title: "StatusPopupMenu" diff --git a/ui/StatusQ/sandbox/pages/StatusListPickerPage.qml b/ui/StatusQ/sandbox/pages/StatusListPickerPage.qml new file mode 100644 index 0000000000..8c7cbc945b --- /dev/null +++ b/ui/StatusQ/sandbox/pages/StatusListPickerPage.qml @@ -0,0 +1,78 @@ +import QtQuick 2.0 +import QtQuick.Layouts 1.14 + +import StatusQ.Controls 0.1 +import StatusQ.Components 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Core 0.1 + +import "../demoapp/data" 1.0 + +GridLayout { + id: root + columns: 1 + rowSpacing: 150 + + GridLayout { + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + rows: 4 + columns: 2 + rowSpacing: 170 + columnSpacing: 150 + z: 100 + StatusListPicker { + id: languagePicker + z: 100 + inputList: Models.languagePickerModel + searchText: qsTr("Search Languages") + } + + StatusListPicker { + id: languagePicker2 + z: 100 + inputList: Models.languageNoImagePickerModel + searchText: qsTr("Search Languages") + } + + StatusListPicker { + id: currencyPicker + inputList: Models.currencyPickerModel + searchText: qsTr("Search Currencies") + multiSelection: true + } + + StatusListPicker { + id: currencyPicker2 + inputList: Models.currencyPickerModel2 + searchText: qsTr("Search Currencies") + multiSelection: true + printSymbol: true + } + } + + StatusBaseText { + id: pageDesc + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + height: 100 + width: 500 + text: "4 different configurations for the `StatusListPicker` component:\n + * Single selection. \n + * Single selection but dynamically changed to multiple selection (model provides multiple selected items).\n + * Multiple selection.\n + * Multiple selection and displayed name is the symbol + shortName\n" + color: Theme.palette.baseColor1 + font.pixelSize: 15 + } + + // Outsite area + MouseArea { + height: root.height + width: root.width + onClicked: { + languagePicker.close() + languagePicker2.close() + currencyPicker.close() + currencyPicker2.close() + } + } +} diff --git a/ui/StatusQ/src/StatusQ/Components/StatusListPicker.qml b/ui/StatusQ/src/StatusQ/Components/StatusListPicker.qml new file mode 100644 index 0000000000..48120e7966 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Components/StatusListPicker.qml @@ -0,0 +1,324 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.13 +import QtGraphicalEffects 1.13 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Controls 0.1 + +/*! + \qmltype StatusListPicker + \inherits Item + \inqmlmodule StatusQ.Components + \since StatusQ.Components 0.1 + \brief It is a combination of StatusPickerButton and a drop-down list component that provides a way of presenting a list of selectable options to the user. + + The \c StatusListPicker is populated with a data model. The data model is commonly a JavaScript array or a ListModel object. + + StatusListPicker can be made as a single or multiple options picker by setting its StatusListPicker::multiSelection property properly or will be auto-set if the model contains / provides more than one selected items. + The StatusPickerButton text holds the text of the current item selected in the list picker. If there is more than one item selected, a string composed will be displayed. + The drop-down list incorporates a searcher by the following model roles: `name` or / and `shortName`. + + NOTE: Make sure to set the appropriate z-index when instantiating the component in order to place it on top of your view in order to display the drop-down data properly. + Make sure to position the component inside its parent also when it is spanned in order to achieve a better user experience. + + Example of how the component looks like: + \image status_list_picker.png + Example of how to use it: + \qml + StatusListPicker { + id: currencyPicker + inputList: Models.currencyPickerModel + searchText: qsTr("Search Language") + multiSelection: true + printSymbol: true + } + \endqml + For a list of components available see StatusQ. +*/ +Item { + id: root + + /*! + \qmlproperty string StatusListPicker::inputList + This property holds the data that will be populated in the list picker. + + NOTE: This model property should not change so it is an in / out property where the selected role will be dynamically changed according to user actions. + + Here an example of the model roles expected: + \qml + inputList: ListModel { + ListElement { + key: 0 + name: "United States Dollar" + shortName: "USD" + symbol: "$" + imageSource: "../../assets/twemoji/26x26/1f4b4.png" + category: "fiat" + selected: true + } + ListElement { + key: 1 + name: "British Pound" + shortName: "GBP" + symbol: "£" + imageSource: "../../assets/twemoji/26x26/1f4b5.png" + category: "fiat" + selected: false + } + } + \endqml + */ + property ListModel inputList: ListModel { } + + /*! + \qmlproperty string StatusListPicker::searchText + This property holds the placeholder text the searcher input displays by default. + */ + property string searchText: qsTr("Search") + + /*! + \qmlproperty string StatusListPicker::multiSelection + This property holds whether the list picker is a single or a multiple picker option by displaying a StatusRadioButton or StatusCheckBox instead. + */ + property bool multiSelection: false + + /*! + \qmlproperty string StatusListPicker::printSymbol + This property holds whether the selected items will display a composition of the role `symbol` in the StatusPickerButton text or just only the role `shortName`. + */ + property bool printSymbol: false + + /*! + \qmlproperty string StatusListPicker::maxPickerHeight + This property holds the maximum drop-down list height allowed. The drop-down list height will be set as the minimum value between the list content height and the maxPickerHeight property. + */ + property int maxPickerHeight: 718 + + /* + \qmlmethod StatusListPicker::close() + It can be used to force to close the drop-down picker list whenever the consumer needs it. For example by adding an outside MouseArea to close the picker when user clicks outsite the component: + \qml + // Outsite area + MouseArea { + height: root.height + width: root.width + onClicked: { currencyPicker.close() } + } + \endqml + */ + function close() { if(picker.visible) picker.visible = false } + + QtObject { + id: d + property var filteredModel: ListModel { } + + // Used to set up component and the needed private properties + function initialize() { + if(filteredModel.count === 0) { + // It is necessary to load the model, not loaded yet! + var selected = 0 + var selectionText = "" + for(var i = 0; i < root.inputList.count; i++) { + var item = root.inputList.get(i) + d.filteredModel.append(item) + if(item.selected) selected++; + } + + // If the given model has more than one selected elements, the behaviour of the list picker will be as a multiple selector with checkboxes although it is + // set in the radiobutton mode. Radiobutton mode is only for mutial-exclusion. + if(selected > 1) + multiSelection = true + + // Update selected items text: + d.getSelectedItemsText() + } + } + + // Used to update model elements given a specific text by filtering them for its `name` and / or `shortName`. + function applyFilter(text) { + const input = text.toLowerCase() + filteredModel.clear() + for(var i = 0; i < root.inputList.count; i++) { + let item = root.inputList.get(i) + if(item.name.toLowerCase().includes(input) || item.shortName.toLowerCase().includes(input)) + filteredModel.append(item) + } + } + + function formatSymbolShortNameText(symbol, shortName) { + var formattedText = "" + if(root.printSymbol && symbol) + formattedText = symbol + shortName + else + formattedText = shortName + return formattedText + } + + function getSelectedItemsText() { + var res = "" + for(var i = 0; i < root.inputList.count; i++) { + var item = root.inputList.get(i) + if(item.selected) { + if(res != "") + res += ", " + res += d.formatSymbolShortNameText(item.symbol, item.shortName) + } + } + return res + } + + // Used to update the base input list model with the new selected property + function updateInputListModel(key, selected, isSingleSelection) { + // If it is a single selection we must ensure that when a new key is selected others are cleared. + // It must be done manually because as there is the option of filterning, the model visualized changes + // and it could be possible to have a filtered list without an element selected (but in the base model + // it is) so, the binding to not selected will not be executed, as in the current filtered model + // there are no changes to update, just only the selected one. + for(var i = 0; i < root.inputList.count; i++) { + if(root.inputList.get(i).key === key) { + root.inputList.get(i).selected = selected + } + else if(isSingleSelection && selected) { + // Clear all the list + root.inputList.get(i).selected = false + } + } + } + } + + width: 110 + height: 38 + + Component.onCompleted: d.initialize() + + StatusPickerButton { + id: btn + anchors.fill: parent + bgColor: Theme.palette.primaryColor3 + contentColor: Theme.palette.primaryColor1 + text: picker.selectedItemsText + type: StatusPickerButton.Type.Down + + onClicked: { + picker.visible = !picker.visible + + // Restart list position: + content.positionViewAtBeginning() + content.forceActiveFocus() + } + } + + Rectangle { + id: picker + + property string selectedItemsText: "" + + width: content.itemWidth + height: Math.min(content.contentHeight + content.anchors.topMargin + content.anchors.bottomMargin, root.maxPickerHeight) + anchors.left: btn.left + anchors.top: btn.bottom + anchors.topMargin: 4 + visible: false + color: Theme.palette.statusPopupMenu.backgroundColor + radius: 8 + layer.enabled: true + layer.effect: DropShadow { + source: picker + horizontalOffset: 0 + verticalOffset: 4 + radius: 12 + samples: 25 + spread: 0.2 + color: Theme.palette.dropShadow + } + + ListView { + id: content + + property int itemHeight: 40 + property int itemWidth: 360 + + model: d.filteredModel + width: itemWidth + anchors.top: parent.top + anchors.topMargin: 8 + anchors.bottom: parent.bottom + anchors.bottomMargin: 8 + currentIndex: -1 + clip: true + headerPositioning: ListView.OverlayHeader + header: Rectangle { + id: header + width: content.itemWidth + height: searchInput.height + 24 + color: Theme.palette.statusPopupMenu.backgroundColor + z: 3 // Above delegate (z=1) and above section.delegate (z = 2) + + StatusBaseInput { + id: searchInput + implicitHeight: 36 + width: content.itemWidth - 2 * 18 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + topPadding: 8 + bottomPadding: 0 + placeholderText: root.searchText + icon.name: "search" + + onTextChanged: { d.applyFilter(text) } + } + }// End of search input item + delegate: StatusItemPicker { + width: content.itemWidth + height: content.itemHeight + image: StatusImageSettings { + source: model.imageSource ? model.imageSource : "" + width: 15 + height: 15 + isIdenticon: false + } + name: model.name + shortName: model.shortName + selectorType: root.multiSelection ? StatusItemPicker.SelectorType.CheckBox : StatusItemPicker.SelectorType.RadioButton + selected: model.selected + radioGroup: radioBtnGroup + + onCheckedChanged: { + d.updateInputListModel(model.key, checked, selectorType === StatusItemPicker.SelectorType.RadioButton) + if(selectorType === StatusItemPicker.SelectorType.RadioButton && checked) { + // Update selected item text + picker.selectedItemsText = d.formatSymbolShortNameText(model.symbol, model.shortName) + } + else { + // Update selected items text (multiple selection, text chain). + picker.selectedItemsText = d.getSelectedItemsText() + } + } + } + section.property: "category" + section.criteria: ViewSection.FullString + section.delegate: Item { + width: content.itemWidth + height: content.itemHeight + + StatusBaseText { + anchors.leftMargin: 18 + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + text: section + color: Theme.palette.baseColor1 + font.pixelSize: 15 + elide: Text.ElideRight + } + }// End of Category item + + onActiveFocusChanged: { if(!activeFocus) root.close() } + + // Not visual element to control mutual-exclusion of radiobuttons that are not sharing the same parent (inside list view) + ButtonGroup { + id: radioBtnGroup + } + }// End of Content + }// End of Rectangle picker +} diff --git a/ui/StatusQ/src/StatusQ/Components/qmldir b/ui/StatusQ/src/StatusQ/Components/qmldir index c834d2f4cf..973bb37793 100644 --- a/ui/StatusQ/src/StatusQ/Components/qmldir +++ b/ui/StatusQ/src/StatusQ/Components/qmldir @@ -24,6 +24,7 @@ StatusRoundedImage 0.1 StatusRoundedImage.qml StatusMacWindowButtons 0.1 StatusMacWindowButtons.qml StatusListItemBadge 0.1 StatusListItemBadge.qml StatusListItemTag 0.1 StatusListItemTag.qml +StatusListPicker 0.1 StatusListPicker.qml StatusExpandableItem 0.1 StatusExpandableItem.qml StatusSmartIdenticon 0.1 StatusSmartIdenticon.qml StatusMessage 0.1 StatusMessage.qml diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusItemPicker.qml b/ui/StatusQ/src/StatusQ/Controls/StatusItemPicker.qml new file mode 100644 index 0000000000..c911289999 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Controls/StatusItemPicker.qml @@ -0,0 +1,183 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.13 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Controls 0.1 + +/*! + \qmltype StatusItemPicker + \inherits Item + \inqmlmodule StatusQ.Controls + \since StatusQ.Controls 0.1 + \brief It presents a selectable item to the user. + + The \c StatusItemPicker is populated with the given properties data. + + StatusItemPicker can be made as a RadioButton or CheckBox selectable item. + + Example of how the component looks like: + \image status_item_picker.png + Example of how to use it: + \qml + StatusItemPicker { + width: 300 + height: 40 + imageSource: model.imageSource + name: model.name + shortName: model.shortName + selectorType: root.multiSelection ? StatusItemPicker.SelectorType.CheckBox : StatusItemPicker.SelectorType.RadioButton + selected: model.selected + radioGroup: content.radioGroup + + onCheckedChanged: { // Some updates } + } + \endqml + For a list of components available see StatusQ. +*/ +Item { + id: root + + /*! + \qmlproperty string StatusItemPicker::image + This property holds the image settings information. + */ + property StatusImageSettings image + + /*! + \qmlproperty string StatusItemPicker::name + This property holds the main text or name to be displayed. + */ + property string name + + /*! + \qmlproperty string StatusItemPicker::shortName + This property holds the secondary text or short name to be displayed. + */ + property string shortName + + /*! + \qmlproperty string StatusItemPicker::selectorType + This property holds the selector type. Possible options are: + \qml + enum SelectorType { + RadioButton, + CheckBox + } + \endqml + By default, RadioButton. + */ + property int selectorType: StatusItemPicker.SelectorType.RadioButton + + /*! + \qmlproperty string StatusItemPicker::selected + This property holds if the item is selected. + */ + property bool selected + + /*! + \qmlproperty string StatusItemPicker::radioGroup + This property holds the button group object the radiobutton belongs to. + */ + property ButtonGroup radioGroup + + /*! + \qmlsignal StatusItemPicker::checkedChanged(bool checked) + This signal is emitted when the item is selected by pressing the radiobutton or the checkbox. + */ + signal checkedChanged(bool checked) + + enum SelectorType { + RadioButton, + CheckBox + } + + QtObject { + id: d + + property int minShortNameWidth: 50 + + function availableTextWidth() { + return root.width - imageItem.width - row.spacing - shortNameItem.anchors.rightMargin - selector.width - selector.anchors.rightMargin - 24/*Margin between both texts*/ + } + } + + Row { + id: row + anchors.left: parent.left + anchors.leftMargin: 18 + anchors.verticalCenter: parent.verticalCenter + spacing: 8 + + StatusIcon { + id: imageItem + anchors.verticalCenter: parent.verticalCenter + source: root.image.source ? root.image.source : "" + width: root.image.width + height: root.image.height + visible: root.image.source !== undefined + } + + StatusBaseText { + id: nameItem + anchors.verticalCenter: parent.verticalCenter + width: dummyNameItem.width > d.availableTextWidth() - d.minShortNameWidth ? + d.availableTextWidth() - d.minShortNameWidth : + dummyNameItem.width + text: root.name + color: Theme.palette.directColor1 + font.pixelSize: 15 + clip: true + elide: Text.ElideRight + } + // Dummy object just to exactly know the width needed by `name` and dynamically set a limit for nameItem and shortNameItem components + StatusBaseText { + id: dummyNameItem + visible: false + text: root.name + font.pixelSize: 15 + } + } + + StatusBaseText { + id: shortNameItem + width: d.availableTextWidth() - nameItem.width < d.minShortNameWidth ? + d.minShortNameWidth : + d.availableTextWidth() - nameItem.width + anchors.right: selector.left + anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + text: root.shortName + color: Theme.palette.baseColor1 + font.pixelSize: 15 + clip: true + elide: Text.ElideRight + horizontalAlignment: Text.AlignRight + } + + // 2 different options: Or with radio buttons or with checkboxes: + Loader { + id: selector + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.rightMargin: 18 + sourceComponent: root.selectorType === StatusItemPicker.SelectorType.RadioButton ? radioBtn : checkbox + } + + Component { + id: radioBtn + StatusRadioButton { + ButtonGroup.group: root.radioGroup + checked: root.selected + onCheckedChanged: root.checkedChanged(checked) + } + } + + Component { + id: checkbox + StatusCheckBox { + checked: root.selected + onCheckedChanged: root.checkedChanged(checked) + } + } +}// End of Content item diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusPickerButton.qml b/ui/StatusQ/src/StatusQ/Controls/StatusPickerButton.qml index 8bcf5a5670..c2395bb5d9 100644 --- a/ui/StatusQ/src/StatusQ/Controls/StatusPickerButton.qml +++ b/ui/StatusQ/src/StatusQ/Controls/StatusPickerButton.qml @@ -11,7 +11,13 @@ Button { property color bgColor: Theme.palette.baseColor2 property color contentColor: Theme.palette.baseColor1 - signal clicked() + property var type: StatusPickerButton.Type.Next + property int lateralMargins: 16 + + enum Type { + Next, + Down + } background: Item { anchors.fill: parent @@ -20,31 +26,57 @@ Button { anchors.fill: parent radius: 8 color: root.bgColor - } - StatusIcon { - id: nextIcon - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.verticalCenter: parent.verticalCenter - icon: "next" - color: !Qt.colorEqual(root.contentColor, Theme.palette.baseColor1) - ? root.contentColor : Theme.palette.directColor1 - } + } } contentItem: Item { anchors.fill: parent + state: root.type === StatusPickerButton.Type.Next ? "NEXT" : "DOWN" + StatusBaseText { id: textLabel - anchors { - fill: parent - leftMargin: 16 - } + anchors.verticalCenter: parent.verticalCenter + width: parent.width - icon.width - anchors.rightMargin - anchors.leftMargin - icon.anchors.rightMargin - icon.anchors.leftMargin verticalAlignment: Text.AlignVCenter font.pixelSize: 15 color: root.contentColor text: root.text + clip: true + elide: Text.ElideRight } + + StatusIcon { + id: icon + anchors.verticalCenter: parent.verticalCenter + color: !Qt.colorEqual(root.contentColor, Theme.palette.baseColor1) ? root.contentColor : Theme.palette.directColor1 + } + + states: [ + State { + name: "NEXT" + PropertyChanges {target: icon; icon: "next"} + PropertyChanges {target: icon; anchors.left: undefined } + PropertyChanges {target: icon; anchors.right: parent.right } + PropertyChanges {target: icon; anchors.rightMargin: root.lateralMargins / 2 } + PropertyChanges {target: icon; anchors.leftMargin: root.lateralMargins / 2 } + PropertyChanges {target: textLabel; anchors.left: parent.left } + PropertyChanges {target: textLabel; anchors.right: undefined } + PropertyChanges {target: textLabel; anchors.rightMargin: undefined } + PropertyChanges {target: textLabel; anchors.leftMargin: root.lateralMargins } + }, + State { + name: "DOWN" + PropertyChanges {target: icon; icon: "chevron-down"} + PropertyChanges {target: icon; anchors.left: parent.left } + PropertyChanges {target: icon; anchors.right: undefined } + PropertyChanges {target: icon; anchors.rightMargin: root.lateralMargins / 2 } + PropertyChanges {target: icon; anchors.leftMargin: root.lateralMargins } + PropertyChanges {target: textLabel; anchors.left: icon.right } + PropertyChanges {target: textLabel; anchors.right: undefined } + PropertyChanges {target: textLabel; anchors.rightMargin: root.lateralMargins / 2 } + PropertyChanges {target: textLabel; anchors.leftMargin: undefined } + } + ] } MouseArea { @@ -52,8 +84,6 @@ Button { anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: { - root.clicked(); - } + onClicked: { root.clicked() } } } diff --git a/ui/StatusQ/src/StatusQ/Controls/qmldir b/ui/StatusQ/src/StatusQ/Controls/qmldir index 8c677cf3f4..1c1afaf97e 100644 --- a/ui/StatusQ/src/StatusQ/Controls/qmldir +++ b/ui/StatusQ/src/StatusQ/Controls/qmldir @@ -9,6 +9,7 @@ StatusChatListCategoryItemButton 0.1 StatusChatListCategoryItemButton.qml StatusColorSelector 0.1 StatusColorSelector.qml StatusIconTabButton 0.1 StatusIconTabButton.qml StatusIdenticonRing 0.1 StatusIdenticonRing.qml +StatusItemPicker 0.1 StatusItemPicker.qml StatusNavBarTabButton 0.1 StatusNavBarTabButton.qml StatusTabBarIconButton 0.1 StatusTabBarIconButton.qml StatusToolTip 0.1 StatusToolTip.qml diff --git a/ui/StatusQ/statusq.qrc b/ui/StatusQ/statusq.qrc index b59f4be943..11d955ea7e 100644 --- a/ui/StatusQ/statusq.qrc +++ b/ui/StatusQ/statusq.qrc @@ -335,5 +335,7 @@ src/assets/img/icons/OMG.png src/assets/img/icons/ETH.png src/assets/img/icons/MANA.png + src/StatusQ/Components/StatusListPicker.qml + src/StatusQ/Controls/StatusItemPicker.qml