diff --git a/doc/src/images/status_item_selector.png b/doc/src/images/status_item_selector.png
new file mode 100644
index 00000000..e0cbaac7
Binary files /dev/null and b/doc/src/images/status_item_selector.png differ
diff --git a/doc/src/statusqcomponents.qdoc b/doc/src/statusqcomponents.qdoc
index 781b769b..3425eaa4 100644
--- a/doc/src/statusqcomponents.qdoc
+++ b/doc/src/statusqcomponents.qdoc
@@ -20,6 +20,7 @@
\li \l{StatusChatToolBar}
\li \l{StatusContactRequestsIndicatorListItem}
\li \l{StatusDescriptionListItem}
+ \li \l{StatusItemSelector}
\li \l{StatusLetterIdenticon}
\li \l{StatusListItem}
\li \l{StatusListPicker}
diff --git a/sandbox/main.qml b/sandbox/main.qml
index c436414e..1d4a4b53 100644
--- a/sandbox/main.qml
+++ b/sandbox/main.qml
@@ -294,6 +294,11 @@ StatusWindow {
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
+ StatusNavigationListItem {
+ title: "StatusItemSelector"
+ selected: viewLoader.source.toString().includes(title)
+ onClicked: mainPageView.page(title);
+ }
StatusListSectionHeadline { text: "StatusQ.Popup" }
StatusNavigationListItem {
title: "StatusPopupMenu"
diff --git a/sandbox/pages/StatusItemSelectorPage.qml b/sandbox/pages/StatusItemSelectorPage.qml
new file mode 100644
index 00000000..2a346b0d
--- /dev/null
+++ b/sandbox/pages/StatusItemSelectorPage.qml
@@ -0,0 +1,44 @@
+import QtQuick 2.0
+import QtQuick.Layouts 1.14
+
+import StatusQ.Components 0.1
+import StatusQ.Controls 0.1
+import StatusQ.Core.Utils 0.1
+
+ColumnLayout {
+ spacing: 20
+ StatusItemSelector {
+ id: selector
+ icon: "qrc:/images/SNT.png"
+ iconSize: 24
+ title: "Item Selector Title"
+ defaultItemText: "Example: Empty items"
+ andOperatorText: "and"
+ orOperatorText: "or"
+ popupItem: StatusDropdown {
+ id: dropdown
+ width: 200
+ contentItem: ColumnLayout {
+ spacing: 10
+ StatusInput {
+ id: input
+ Layout.fillWidth: true
+ }
+ StatusButton {
+ Layout.alignment: Qt.AlignHCenter
+ text: "Add element"
+ onClicked: {
+ selector.addItem(input.text, "qrc:/images/SNT.png", selector.itemsModel.count > 0 ? Utils.Operators.Or : Utils.Operators.None)
+ dropdown.close()
+ }
+ }
+ }
+ }
+ }
+
+ StatusButton {
+ Layout.alignment: Qt.AlignHCenter
+ text: "Clear list"
+ onClicked: { selector.itemsModel.clear() }
+ }
+}
diff --git a/sandbox/qml.qrc b/sandbox/qml.qrc
index 082509d6..050d4d7b 100644
--- a/sandbox/qml.qrc
+++ b/sandbox/qml.qrc
@@ -68,5 +68,6 @@
images/SuperRareCommunityBanner.png
images/RARI.png
images/SRToken.png
+ pages/StatusItemSelectorPage.qml
diff --git a/src/StatusQ/Components/StatusItemSelector.qml b/src/StatusQ/Components/StatusItemSelector.qml
index be379be6..8d399f79 100644
--- a/src/StatusQ/Components/StatusItemSelector.qml
+++ b/src/StatusQ/Components/StatusItemSelector.qml
@@ -1,32 +1,150 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
+import QtQuick.Controls 2.14 as QC
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
+import StatusQ.Core.Utils 0.1
+/*!
+ \qmltype StatusItemSelector
+ \inherits Rectangle
+ \inqmlmodule StatusQ.Components
+ \since StatusQ.Components 0.1
+ \brief It allows to add items and display them as a tag item with an image and text. It also allows to store and display logical `and` / `or` operators into the list. Inherits \l{https://doc.qt.io/qt-6/qml-qtquick-rectangle.html}{Item}.
+
+ The \c StatusItemSelector is populated with a data model. The data model is commonly a JavaScript array or a ListModel object with specific expected roles.
+
+ Example of how the component looks like:
+ \image status_item_selector.png
+
+ Example of how to use it:
+ \qml
+ StatusItemSelector {
+ icon: Style.svg("contact_verified")
+ title: qsTr("Who holds")
+ defaultItemText: qsTr("Example: 10 SNT")
+ andOperatorText: qsTr("and")
+ orOperatorText: qsTr("or")
+ popupItem: CustomPopup {
+ id: customPopup
+ onAddItem: {
+ tokensSelector.addItem(itemText, itemImage, operator)
+ customPopup.close()
+ }
+ }
+ }
+ \endqml
+ For a list of components available see StatusQ.
+*/
Rectangle {
id: root
-
+ /*!
+ \qmlproperty string StatusItemSelector::icon
+ This property holds the icon name for the icon represented on top of the component as a title icon.
+ */
property string icon
+ /*!
+ \qmlproperty int StatusItemSelector::iconSize
+ This property holds the icon size for the icon represented on top of the component as a title icon.
+ */
property int iconSize: 18
+ /*!
+ \qmlproperty string StatusItemSelector::title
+ This property holds the titel shown on top of the component.
+ */
property string title
+ /*!
+ \qmlproperty string StatusItemSelector::defaultItemText
+ This property holds the default item text shown when the list of items is empty.
+ */
property string defaultItemText
+ /*!
+ \qmlproperty url StatusItemSelector::defaultItemImageSource
+ This property holds the default item icon shown when the list of items is empty.
+ */
+ property url defaultItemImageSource: ""
+ /*!
+ \qmlproperty QC.Popup StatusItemSelector::popupItem
+ This property holds a custom popup item to be opened near the `add` button in order to select new items.
+ */
+ property QC.Popup popupItem
+ /*!
+ \qmlproperty ListModel StatusItemSelector::itemsModel
+ This property holds the data that will be populated in the items selector.
- signal addItem()
+ Here an example of the model roles expected:
+ \qml
+ itemsModel: ListModel {
+ ListElement {
+ text: "Socks"
+ imageSource: "qrc:imports/assets/png/tokens/SOCKS.png"
+ operator: Utils.Operator.None
+ }
+ ListElement {
+ text: "ZRX"
+ imageSource: "qrc:imports/assets/png/tokens/ZRX.png"
+ operator: Utils.Operator.Or
+ }
+ }
+ \endqml
+ */
+ property ListModel itemsModel: ListModel { }
+ /*!
+ \qmlproperty string StatusItemSelector::andOperatorText
+ This property holds the string text representation for an `AND` logical operator.
+ */
+ property string andOperatorText: qsTr("and")
+ /*!
+ \qmlproperty string StatusItemSelector::orOperatorText
+ This property holds the string text representation for an `OR` logical operator.
+ */
+ property string orOperatorText: qsTr("or")
+ /*
+ \qmlmethod StatusItemSelector::addItem()
+ It is used to add new items into the selector control. The expected arguments are:
+ string `text`, url `imageSource` and int `operator` (None = 0, And = 1 and Or = 2)
+ */
+ function addItem(text, imageSource, operator) {
+ itemsModel.insert(itemsModel.count, { "text": text, "imageSource": imageSource.toString(), "operator": operator })
+ }
+
+ QtObject {
+ id: d
+
+ function operatorTextFormat(operator) {
+ switch(operator)
+ {
+ case Utils.Operators.And:
+ return root.andOperatorText
+ case Utils.Operators.Or:
+ return root.orOperatorText
+ case Utils.Operators.None:
+ return ""
+ }
+ }
+ }
color: Theme.palette.baseColor4
- height: column.implicitHeight + column.anchors.topMargin + column.anchors.bottomMargin
+ implicitHeight: columnLayout.implicitHeight + columnLayout.anchors.topMargin + columnLayout.anchors.bottomMargin
+ implicitWidth: 560
radius: 16
+ clip: true
+
ColumnLayout {
- id: column
+ id: columnLayout
anchors.top: parent.top
anchors.topMargin: 12
anchors.bottomMargin: anchors.topMargin
anchors.left: parent.left
anchors.leftMargin: 16
+ anchors.right: parent.right
+ anchors.rightMargin: 16
spacing: 12
+ clip: true
RowLayout {
+ id: headerRow
spacing: 8
Image {
sourceSize.width: width || undefined
@@ -44,28 +162,65 @@ Rectangle {
color: Theme.palette.directColor1
font.pixelSize: 17
}
- }
- // TODO: Next component iteration - model and selector
- GridLayout {
- rowSpacing: 6
- columnSpacing: 12
+ }
+ Flow {
+ id: flow
+ Layout.fillWidth: true
+ spacing: 6
+ StatusListItemTag {
+ visible: itemsModel.count === 0
+ title: root.defaultItemText
+ image.source: root.defaultItemImageSource
+ color: Theme.palette.baseColor2
+ closeButtonVisible: false
+ titleText.color: Theme.palette.baseColor1
+ titleText.font.pixelSize: 15
+ }
Repeater {
- model: 1
- StatusListItemTag {
- title: root.defaultItemText
- color: Theme.palette.baseColor2
- closeButtonVisible: false
- titleText.color: Theme.palette.baseColor1
- titleText.font.pixelSize: 15
+ model: itemsModel
+ RowLayout {
+ spacing: flow.spacing
+ StatusBaseText {
+ visible: model.operator !== Utils.Operators.None
+ Layout.alignment: Qt.AlignVCenter
+ text: d.operatorTextFormat(model.operator)
+ color: Theme.palette.primaryColor1
+ font.pixelSize: 17
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ // Switch operator
+ if(model.operator === Utils.Operators.And)
+ model.operator = Utils.Operators.Or
+ else
+ model.operator = Utils.Operators.And
+ }
+ }
+ }
+ StatusListItemTag {
+ title: model.text
+ image.source: model.imageSource
+ color: Theme.palette.primaryColor3
+ closeButtonVisible: false
+ titleText.color: Theme.palette.primaryColor1
+ titleText.font.pixelSize: 15
+ //onClicked: // TODO: Open remove or edit dialog
+ }
}
}
StatusRoundButton {
+ id: addItemButton
implicitHeight: 32
implicitWidth: implicitHeight
height: width
type: StatusRoundButton.Type.Secondary
icon.name: "add"
- onClicked: root.addItem()
+ onClicked: {
+ root.popupItem.x = addItemButton.x + addItemButton.width + 4 * flow.spacing
+ root.popupItem.y = addItemButton.y + addItemButton.height
+ root.popupItem.open()
+ }
}
}
}
diff --git a/src/StatusQ/Components/qmldir b/src/StatusQ/Components/qmldir
index e405e5e7..06ccf65a 100644
--- a/src/StatusQ/Components/qmldir
+++ b/src/StatusQ/Components/qmldir
@@ -37,4 +37,4 @@ StatusImageCropPanel 0.1 StatusImageCropPanel.qml
StatusColorSpace 0.0 StatusColorSpace.qml
StatusCommunityCard 0.1 StatusCommunityCard.qml
StatusCommunityTags 0.1 StatusCommunityTags.qml
-StatusItemSelector 0.1 StatusItemSelector.qml
\ No newline at end of file
+StatusItemSelector 0.1 StatusItemSelector.qml
diff --git a/src/StatusQ/Core/Utils/Utils.qml b/src/StatusQ/Core/Utils/Utils.qml
index 46afc422..2b8b6b0a 100644
--- a/src/StatusQ/Core/Utils/Utils.qml
+++ b/src/StatusQ/Core/Utils/Utils.qml
@@ -3,6 +3,14 @@ pragma Singleton
import QtQuick 2.13
QtObject {
+
+ // Logical operators
+ enum Operators {
+ None,
+ And,
+ Or
+ }
+
function getAbsolutePosition(node) {
var returnPos = {};
returnPos.x = 0;