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 0000000000..b2e0916114
Binary files /dev/null and b/ui/StatusQ/doc/src/images/status_item_picker.png differ
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 0000000000..f68fc422aa
Binary files /dev/null and b/ui/StatusQ/doc/src/images/status_list_picker.png differ
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