mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-30 00:05:37 +00:00
feat(StatusItemSelector): Component improvements
- Added `popupItem` property - Replaced `GridLayout` to `Flow`. - Added add item logic. - Added operators logic. - Added basic documentation. - Added to sandbox.
This commit is contained in:
parent
cd0e458ad2
commit
e106f93c4d
BIN
ui/StatusQ/doc/src/images/status_item_selector.png
Normal file
BIN
ui/StatusQ/doc/src/images/status_item_selector.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -20,6 +20,7 @@
|
|||||||
\li \l{StatusChatToolBar}
|
\li \l{StatusChatToolBar}
|
||||||
\li \l{StatusContactRequestsIndicatorListItem}
|
\li \l{StatusContactRequestsIndicatorListItem}
|
||||||
\li \l{StatusDescriptionListItem}
|
\li \l{StatusDescriptionListItem}
|
||||||
|
\li \l{StatusItemSelector}
|
||||||
\li \l{StatusLetterIdenticon}
|
\li \l{StatusLetterIdenticon}
|
||||||
\li \l{StatusListItem}
|
\li \l{StatusListItem}
|
||||||
\li \l{StatusListPicker}
|
\li \l{StatusListPicker}
|
||||||
|
@ -294,6 +294,11 @@ StatusWindow {
|
|||||||
selected: viewLoader.source.toString().includes(title)
|
selected: viewLoader.source.toString().includes(title)
|
||||||
onClicked: mainPageView.page(title);
|
onClicked: mainPageView.page(title);
|
||||||
}
|
}
|
||||||
|
StatusNavigationListItem {
|
||||||
|
title: "StatusItemSelector"
|
||||||
|
selected: viewLoader.source.toString().includes(title)
|
||||||
|
onClicked: mainPageView.page(title);
|
||||||
|
}
|
||||||
StatusListSectionHeadline { text: "StatusQ.Popup" }
|
StatusListSectionHeadline { text: "StatusQ.Popup" }
|
||||||
StatusNavigationListItem {
|
StatusNavigationListItem {
|
||||||
title: "StatusPopupMenu"
|
title: "StatusPopupMenu"
|
||||||
|
44
ui/StatusQ/sandbox/pages/StatusItemSelectorPage.qml
Normal file
44
ui/StatusQ/sandbox/pages/StatusItemSelectorPage.qml
Normal file
@ -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() }
|
||||||
|
}
|
||||||
|
}
|
@ -68,5 +68,6 @@
|
|||||||
<file>images/SuperRareCommunityBanner.png</file>
|
<file>images/SuperRareCommunityBanner.png</file>
|
||||||
<file>images/RARI.png</file>
|
<file>images/RARI.png</file>
|
||||||
<file>images/SRToken.png</file>
|
<file>images/SRToken.png</file>
|
||||||
|
<file>pages/StatusItemSelectorPage.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -1,32 +1,150 @@
|
|||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.14
|
||||||
|
import QtQuick.Controls 2.14 as QC
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Controls 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 {
|
Rectangle {
|
||||||
id: root
|
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
|
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
|
property int iconSize: 18
|
||||||
|
/*!
|
||||||
|
\qmlproperty string StatusItemSelector::title
|
||||||
|
This property holds the titel shown on top of the component.
|
||||||
|
*/
|
||||||
property string title
|
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
|
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
|
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
|
radius: 16
|
||||||
|
clip: true
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: column
|
id: columnLayout
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: 12
|
||||||
anchors.bottomMargin: anchors.topMargin
|
anchors.bottomMargin: anchors.topMargin
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 16
|
||||||
spacing: 12
|
spacing: 12
|
||||||
|
clip: true
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
id: headerRow
|
||||||
spacing: 8
|
spacing: 8
|
||||||
Image {
|
Image {
|
||||||
sourceSize.width: width || undefined
|
sourceSize.width: width || undefined
|
||||||
@ -44,28 +162,65 @@ Rectangle {
|
|||||||
color: Theme.palette.directColor1
|
color: Theme.palette.directColor1
|
||||||
font.pixelSize: 17
|
font.pixelSize: 17
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Next component iteration - model and selector
|
Flow {
|
||||||
GridLayout {
|
id: flow
|
||||||
rowSpacing: 6
|
Layout.fillWidth: true
|
||||||
columnSpacing: 12
|
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 {
|
Repeater {
|
||||||
model: 1
|
model: itemsModel
|
||||||
StatusListItemTag {
|
RowLayout {
|
||||||
title: root.defaultItemText
|
spacing: flow.spacing
|
||||||
color: Theme.palette.baseColor2
|
StatusBaseText {
|
||||||
closeButtonVisible: false
|
visible: model.operator !== Utils.Operators.None
|
||||||
titleText.color: Theme.palette.baseColor1
|
Layout.alignment: Qt.AlignVCenter
|
||||||
titleText.font.pixelSize: 15
|
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 {
|
StatusRoundButton {
|
||||||
|
id: addItemButton
|
||||||
implicitHeight: 32
|
implicitHeight: 32
|
||||||
implicitWidth: implicitHeight
|
implicitWidth: implicitHeight
|
||||||
height: width
|
height: width
|
||||||
type: StatusRoundButton.Type.Secondary
|
type: StatusRoundButton.Type.Secondary
|
||||||
icon.name: "add"
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,4 +37,4 @@ StatusImageCropPanel 0.1 StatusImageCropPanel.qml
|
|||||||
StatusColorSpace 0.0 StatusColorSpace.qml
|
StatusColorSpace 0.0 StatusColorSpace.qml
|
||||||
StatusCommunityCard 0.1 StatusCommunityCard.qml
|
StatusCommunityCard 0.1 StatusCommunityCard.qml
|
||||||
StatusCommunityTags 0.1 StatusCommunityTags.qml
|
StatusCommunityTags 0.1 StatusCommunityTags.qml
|
||||||
StatusItemSelector 0.1 StatusItemSelector.qml
|
StatusItemSelector 0.1 StatusItemSelector.qml
|
||||||
|
@ -3,6 +3,14 @@ pragma Singleton
|
|||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
|
||||||
|
// Logical operators
|
||||||
|
enum Operators {
|
||||||
|
None,
|
||||||
|
And,
|
||||||
|
Or
|
||||||
|
}
|
||||||
|
|
||||||
function getAbsolutePosition(node) {
|
function getAbsolutePosition(node) {
|
||||||
var returnPos = {};
|
var returnPos = {};
|
||||||
returnPos.x = 0;
|
returnPos.x = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user