chore(HoldingsDropdown): Component refactor and split into smaller files

- decomposed into set of separate components
- reduced number of magic numbers
- minor adjustments with design
This commit is contained in:
Michał Cieślak 2022-08-30 18:27:00 +02:00 committed by Michał
parent 255341e228
commit b2d678c2c4
9 changed files with 528 additions and 329 deletions

View File

@ -0,0 +1,79 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Controls.Validators 0.1
ColumnLayout {
id: root
property alias specificAmount: specificAmountSwitch.checked
property alias collectibleName: pickerButton.text
property url collectibleImage
property alias amount: amountInput.text
signal pickerClicked
spacing: 0
StatusPickerButton {
id: pickerButton
Layout.fillWidth: true
Layout.preferredHeight: 36
bgColor: Theme.palette.baseColor5
contentColor: Theme.palette.directColor1
text: root.collectibleName
font.pixelSize: 13
asset.name: root.collectibleImage
onClicked: pickerClicked()
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: 16
Layout.rightMargin: 6
Layout.topMargin: 8
StatusBaseText {
Layout.fillWidth: true
text: qsTr("Specific amount")
font.pixelSize: 13
wrapMode: Text.WordWrap
elide: Text.ElideRight
}
StatusSwitch { id: specificAmountSwitch }
}
StatusInput {
id: amountInput
Layout.fillWidth: true
Layout.topMargin: 8
visible: specificAmountSwitch.checked
minimumHeight: 36
maximumHeight: 36
topPadding: 0
bottomPadding: 0
font.pixelSize: 13
rightPadding: amountText.implicitWidth + amountText.anchors.rightMargin + leftPadding
input.placeholderText: "0"
validationMode: StatusInput.ValidationMode.IgnoreInvalidInput
validators: StatusFloatValidator { bottom: 0 }
StatusBaseText {
id: amountText
anchors.right: parent.right
anchors.rightMargin: 13
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Amount")
color: Theme.palette.baseColor1
font.pixelSize: 13
}
}
}

View File

@ -0,0 +1,5 @@
import QtQuick 2.14
Item {
}

View File

@ -9,13 +9,14 @@ import StatusQ.Core 0.1
import shared.panels 1.0
ColumnLayout {
Item {
id: root
property var store
property int type: ExtendedDropdownContent.Type.Tokens
signal goBack()
readonly property bool canGoBack: root.state !== d.listView_depth1_State
signal itemClicked(string key, string name, url iconSource)
enum Type{
@ -23,6 +24,10 @@ ColumnLayout {
Collectibles
}
function goBack() {
root.state = d.listView_depth1_State
}
QtObject {
id: d
readonly property int filterItemsHeight: 36
@ -48,7 +53,6 @@ ColumnLayout {
}
}
spacing: 0
state: d.listView_depth1_State
states: [
State {
@ -71,138 +75,113 @@ ColumnLayout {
}
]
// Header
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 8
Layout.topMargin: 5
StatusFlatRoundButton {
id: filterButton
implicitWidth: 32
implicitHeight: 32
visible: d.isFilterOptionVisible
type: StatusFlatRoundButton.Type.Secondary
icon.name: "filter"
StatusIconTextButton {
Layout.alignment: Qt.AlignVCenter
spacing: 0
statusIcon: "next"
icon.width: 12
icon.height: 12
iconRotation: 180
text: qsTr("Back")
onClicked: {
if(root.state == d.listView_depth1_State) {
root.goBack()
}
else {
root.state = d.listView_depth1_State
}
}
anchors.right: parent.right
anchors.bottom: parent.top
anchors.bottomMargin: 3
onClicked: {
filterOptionsPopup.x = filterButton.x + filterButton.width - filterOptionsPopup.width
filterOptionsPopup.y = filterButton.y + filterButton.height + 8
filterOptionsPopup.open()
}
}
// Just a filler to fit layout
Item { Layout.fillWidth: true; height: filterButton.implicitHeight }
// Filter options popup:
StatusDropdown {
id: filterOptionsPopup
width: d.filterPopupWidth
height: d.filterPopupHeight
contentItem: ColumnLayout {
anchors.fill: parent
anchors.topMargin: 8
anchors.bottomMargin: 8
ListView {
Layout.fillWidth: true
Layout.preferredHeight: model.count * d.filterItemsHeight
model: ListModel {
ListElement { text: qsTr("Most viewed"); selected: true }
ListElement { text: qsTr("Newest first"); selected: false }
ListElement { text: qsTr("Oldest first"); selected: false }
}
delegate: StatusItemPicker {
width: ListView.view.width
height: d.filterItemsHeight
color: sensor1.containsMouse ? Theme.palette.baseColor4 : "transparent"
name: model.text
namePixelSize: 13
selectorType: StatusItemPicker.SelectorType.RadioButton
radioGroup: filterRadioBtnGroup
radioButtonSize: StatusRadioButton.Size.Small
selected: model.selected
StatusFlatRoundButton {
id: filterButton
implicitWidth: 32
implicitHeight: 32
visible: d.isFilterOptionVisible
type: StatusFlatRoundButton.Type.Secondary
icon.name: "filter"
onClicked: {
filterOptionsPopup.x = filterButton.x + filterButton.width - filterOptionsPopup.width
filterOptionsPopup.y = filterButton.y + filterButton.height + 8
filterOptionsPopup.open()
}
}
// Filter options popup:
StatusDropdown {
id: filterOptionsPopup
width: d.filterPopupWidth
height: d.filterPopupHeight
contentItem: ColumnLayout {
anchors.fill: parent
anchors.topMargin: 8
anchors.bottomMargin: 8
ListView {
Layout.fillWidth: true
Layout.preferredHeight: model.count * d.filterItemsHeight
model: ListModel {
ListElement { text: qsTr("Most viewed"); selected: true }
ListElement { text: qsTr("Newest first"); selected: false }
ListElement { text: qsTr("Oldest first"); selected: false }
}
delegate: StatusItemPicker {
width: ListView.view.width
height: d.filterItemsHeight
color: sensor1.containsMouse ? Theme.palette.baseColor4 : "transparent"
name: model.text
namePixelSize: 13
selectorType: StatusItemPicker.SelectorType.RadioButton
radioGroup: filterRadioBtnGroup
radioButtonSize: StatusRadioButton.Size.Small
selected: model.selected
MouseArea {
id: sensor1
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
selected = !selected
console.log("TODO: Clicked filter option: " + model.text)
filterOptionsPopup.close()
}
MouseArea {
id: sensor1
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
selected = !selected
console.log("TODO: Clicked filter option: " + model.text)
filterOptionsPopup.close()
}
}
}
// Not visual element to control filter options
ButtonGroup {
id: filterRadioBtnGroup
// Not visual element to control filter options
ButtonGroup {
id: filterRadioBtnGroup
}
}
Separator { Layout.fillWidth: true }
ListView {
Layout.fillWidth: true
Layout.preferredHeight: model.count * d.filterItemsHeight
model: ListModel {
ListElement { key: "LIST"; text: qsTr("List"); selected: true }
ListElement { key: "THUMBNAILS"; text: qsTr("Thumbnails"); selected: false }
}
delegate: StatusItemPicker {
width: ListView.view.width
height: d.filterItemsHeight
color: sensor2.containsMouse ? Theme.palette.baseColor4 : "transparent"
name: model.text
namePixelSize: 13
selectorType: StatusItemPicker.SelectorType.RadioButton
radioGroup: visualizationRadioBtnGroup
radioButtonSize: StatusRadioButton.Size.Small
selected: model.selected
MouseArea {
id: sensor2
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
selected = !selected
if(model.key === "LIST") {
root.state = d.listView_depth2_State
}
else if(model.key === "THUMBNAILS") {
root.state = d.thumbnailsViewState
}
filterOptionsPopup.close()
}
}
}
Separator { Layout.fillWidth: true }
ListView {
Layout.fillWidth: true
Layout.preferredHeight: model.count * d.filterItemsHeight
model: ListModel {
ListElement { key: "LIST"; text: qsTr("List"); selected: true }
ListElement { key: "THUMBNAILS"; text: qsTr("Thumbnails"); selected: false }
}
delegate: StatusItemPicker {
width: ListView.view.width
height: d.filterItemsHeight
color: sensor2.containsMouse ? Theme.palette.baseColor4 : "transparent"
name: model.text
namePixelSize: 13
selectorType: StatusItemPicker.SelectorType.RadioButton
radioGroup: visualizationRadioBtnGroup
radioButtonSize: StatusRadioButton.Size.Small
selected: model.selected
MouseArea {
id: sensor2
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
selected = !selected
if(model.key === "LIST") {
root.state = d.listView_depth2_State
}
else if(model.key === "THUMBNAILS") {
root.state = d.thumbnailsViewState
}
filterOptionsPopup.close()
}
}
}
// Not visual element to control visualization options
ButtonGroup {
id: visualizationRadioBtnGroup
}
// Not visual element to control visualization options
ButtonGroup {
id: visualizationRadioBtnGroup
}
}
}
@ -211,9 +190,8 @@ ColumnLayout {
// List elements content
Loader {
id: contentLoader
Layout.preferredWidth: 289 // by design
Layout.bottomMargin: 5
Layout.preferredHeight: (item != null && typeof(item) !== 'undefined') ? item.implicitHeight : 0
anchors.fill: parent
}
Component {
@ -267,6 +245,9 @@ ColumnLayout {
ThumbnailsDropdownContent {
title: d.currentItemName
titleImage: d.currentItemSource
padding: 0
model: d.currentModel
onItemClicked: {
d.reset()

View File

@ -1,17 +1,12 @@
import QtQuick 2.13
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.13
import QtGraphicalEffects 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Controls.Validators 0.1
import StatusQ.Core.Utils 0.1 as SQ
import utils 1.0
StatusDropdown {
id: root
@ -23,6 +18,8 @@ StatusDropdown {
property url tokenImage: ""
property real collectibleAmount: 1
property string collectibleName: d.defaultCollectibleNameText
property bool collectiblesSpecificAmount: false
property url collectibleImage: ""
property int operator: SQ.Utils.Operators.None
property bool withOperatorSelector: true
@ -38,107 +35,118 @@ StatusDropdown {
root.collectibleAmount = 1
root.collectibleName = d.defaultCollectibleNameText
root.collectibleImage = ""
root.collectiblesSpecificAmount = false
root.operator = SQ.Utils.Operators.None
}
padding: d.padding
onOpened: d.selectInitState()
onClosed: root.reset()
onWithOperatorSelectorChanged: d.selectInitState()
QtObject {
id: d
// Internal management properties:
readonly property bool tokensReady: root.tokenAmount > 0 && root.tokenName !== d.defaultTokenNameText
readonly property bool collectiblesReady: root.collectibleAmount > 0 && root.collectibleName !== d.defaultCollectibleNameText
readonly property string operatorsState: "OPERATORS"
readonly property string tabsState: "TABS"
readonly property string extendedState: "EXTENDED"
readonly property string tokensState: "TOKENS"
readonly property string collectiblesState: "COLLECTIBLES"
readonly property string ensState: "ENS"
property bool isTokensLayout: true
property int extendedDropdownType: ExtendedDropdownContent.Type.Tokens
property int currentTabIndex: 0
// By design values:
readonly property int initialHeight: 232
readonly property int mainHeight: 256
readonly property int mainExtendedHeight: 276
readonly property int operatorsHeight: 96
readonly property int extendedHeight: 417
readonly property int defaultWidth: 289
readonly property int padding: 8
readonly property int topPaddingWithBack: 12
readonly property int extendedTopPadding: 16
readonly property int operatorsWidth: 159
readonly property int operatorsHeight: 96
readonly property int defaultWidth: 289
readonly property int defaultHeight: 232
readonly property int enlargedHeight: 276
readonly property int extendedHeight: 417
readonly property int backButtonExtraLeftMargin: 4
property string defaultTokenNameText: qsTr("Choose token")
property string defaultCollectibleNameText: qsTr("Choose collectible")
signal addClicked
function selectInitState() {
if(root.withOperatorSelector)
loader.sourceComponent = operatorsSelectorView
content.state = d.operatorsState
else
loader.sourceComponent = tabsView
content.state = d.tabsState
}
}
implicitWidth: d.defaultWidth
implicitHeight: loader.implicitHeight
contentItem: ColumnLayout {
id: content
contentItem: Loader {
id: loader
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
height: (item != null && typeof(item) !== 'undefined') ? item.implicitHeight : 0
sourceComponent: root.withOperatorSelector ? operatorsSelectorView : tabsView
onSourceComponentChanged: {
if(sourceComponent == operatorsSelectorView) {
root.width = d.operatorsWidth
}
else {
root.width = d.defaultWidth
}
spacing: 10
StatusIconTextButton {
id: backButton
Layout.leftMargin: d.backButtonExtraLeftMargin
spacing: 0
statusIcon: "next"
icon.width: 12
icon.height: 12
iconRotation: 180
text: qsTr("Back")
}
}
onOpened: d.selectInitState()
onClosed: root.reset()
onWithOperatorSelectorChanged: d.selectInitState()
Loader {
id: loader
Layout.fillWidth: true
Layout.fillHeight: true
}
states: [
State {
name: d.operatorsState
PropertyChanges {target: loader; sourceComponent: operatorsSelectorView}
PropertyChanges {target: backButton; visible: false}
PropertyChanges {target: root; width: d.operatorsWidth; height: d.operatorsHeight }
},
State {
name: d.tabsState
PropertyChanges {target: loader; sourceComponent: tabsView}
PropertyChanges {target: backButton; visible: root.withOperatorSelector}
PropertyChanges {
target: root; topPadding: root.withOperatorSelector ? d.topPaddingWithBack : d.extendedTopPadding
width: d.defaultWidth
height: (loader.item.state === d.collectiblesState && root.collectiblesSpecificAmount) ? d.enlargedHeight : d.defaultHeight
}
},
State {
name: d.extendedState
PropertyChanges {target: loader; sourceComponent: extendedView}
PropertyChanges {target: backButton; visible: true}
PropertyChanges {target: root; topPadding: d.topPaddingWithBack; width: d.defaultWidth; height: d.extendedHeight}
}
]
}
Component {
id: operatorsSelectorView
ColumnLayout {
StatusPickerButton {
Layout.margins: 8
Layout.bottomMargin: 0
Layout.preferredWidth: 143 // by design
Layout.preferredHeight: 36
horizontalPadding: 12
spacing: 10
bgColor: Theme.palette.primaryColor3
contentColor: Theme.palette.primaryColor1
asset.name: Style.svg("add")
asset.isImage: true
text: qsTr("And...")
asset.height: 12
asset.width: 12
font.pixelSize: 13
onClicked: {
root.operator = SQ.Utils.Operators.And
loader.sourceComponent = tabsView
}
}
StatusPickerButton {
Layout.margins: 8
Layout.topMargin: 0
Layout.fillWidth: true
Layout.preferredHeight: 36
horizontalPadding: 12
spacing: 10
bgColor: Theme.palette.primaryColor3
contentColor: Theme.palette.primaryColor1
asset.name: Style.svg("condition-Or")
asset.isImage: true
asset.height: 12
asset.width: 12
text: qsTr("Or...")
font.pixelSize: 13
onClicked: {
root.operator = SQ.Utils.Operators.Or
loader.sourceComponent = tabsView
}
OperatorsSelector {
onOperatorSelected: {
root.operator = operator
content.state = d.tabsState
}
}
}
@ -146,146 +154,92 @@ StatusDropdown {
Component {
id: tabsView
ColumnLayout {
spacing: 0
state: d.currentTabIndex === 0 ? d.tokensState : (d.currentTabIndex === 1 ? d.collectiblesState : d.ensState)
HoldingsTabs {
id: holdingsTabs
states: [
State {
name: d.tokensState
PropertyChanges {target: tabsLoader; sourceComponent: tokensCollectiblesLayout}
PropertyChanges {target: d; isTokensLayout: true}
PropertyChanges {target: holdingsTabs; sourceComponent: tokensLayout; addButtonEnabled: d.tokensReady}
},
State {
name: d.collectiblesState
PropertyChanges {target: tabsLoader; sourceComponent: tokensCollectiblesLayout}
PropertyChanges {target: d; isTokensLayout: false}
PropertyChanges {target: holdingsTabs; sourceComponent: collectiblesLayout; addButtonEnabled: d.collectiblesReady}
},
State {
name: d.ensState
PropertyChanges {target: tabsLoader; sourceComponent: ensLayout}
PropertyChanges {target: holdingsTabs; sourceComponent: ensLayout; addButtonEnabled: false}
}
]
StatusIconTextButton {
visible: root.withOperatorSelector
Layout.leftMargin: 16
Layout.topMargin: 12
spacing: 0
statusIcon: "next"
icon.width: 12
icon.height: 12
iconRotation: 180
text: qsTr("Back")
onClicked: loader.sourceComponent = operatorsSelectorView
}
StatusSwitchTabBar {
id: tabBar
Layout.preferredWidth: 273 // by design
Layout.margins: 8
Layout.topMargin: root.withOperatorSelector ? 12 : 16
Layout.preferredHeight: 36 // by design
currentIndex: d.currentTabIndex
onCurrentIndexChanged: d.currentTabIndex = currentIndex
StatusSwitchTabButton {
text: qsTr("Token")
fontPixelSize: 13
tabLabels: [qsTr("Token"), qsTr("Collectible"), qsTr("ENS")]
state: [d.tokensState, d.collectiblesState, d.ensState][currentIndex]
currentIndex: d.currentTabIndex
onCurrentIndexChanged: d.currentTabIndex = currentIndex
onAddClicked: d.addClicked()
Connections {
target: backButton
function onClicked() {
content.state = d.operatorsState
}
StatusSwitchTabButton {
text: qsTr("Collectible")
fontPixelSize: 13
}
StatusSwitchTabButton {
text: qsTr("ENS")
fontPixelSize: 13
enabled: false // TODO
}
}
Loader {
id: tabsLoader
Layout.fillWidth: true
Layout.margins: 8
}
}
}
Component {
id: tokensCollectiblesLayout
id: tokensLayout
ColumnLayout {
spacing: 0
StatusPickerButton {
Layout.fillWidth: true
Layout.preferredHeight: 36
bgColor: Theme.palette.baseColor5
contentColor: Theme.palette.directColor1
text: d.isTokensLayout ? root.tokenName : root.collectibleName
font.pixelSize: 13
asset.name: d.isTokensLayout ? root.tokenImage : root.collectibleImage
onClicked: loader.sourceComponent = extendedView
TokensPanel {
id: tokensPanel
tokenName: root.tokenName
tokenImage: root.tokenImage
amount: root.tokenAmount === 0 ? "" : root.tokenAmount.toString()
onAmountChanged: root.tokenAmount = Number(amount)
onPickerClicked: {
d.extendedDropdownType = ExtendedDropdownContent.Type.Tokens
content.state = d.extendedState
}
RowLayout {
visible: !d.isTokensLayout
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: 16
Layout.rightMargin: 6
Layout.topMargin: 8
StatusBaseText {
Layout.fillWidth: true
text: qsTr("Specific amount")
font.pixelSize: 13
wrapMode: Text.WordWrap
elide: Text.ElideRight
clip: true
}
StatusSwitch { id: specificAmountSwitch }
}
Connections {
target: d
StatusInput {
Layout.fillWidth: true
Layout.topMargin: 8
visible: d.isTokensLayout ? true : specificAmountSwitch.checked
minimumHeight: 36
maximumHeight: 36
topPadding: 0
bottomPadding: 0
text: d.isTokensLayout ? (root.tokenAmount === 0 ? "" : root.tokenAmount.toString()) :
(root.collectibleAmount === 0 ? "" : root.collectibleAmount.toString())
font.pixelSize: 13
rightPadding: amountText.implicitWidth + amountText.anchors.rightMargin + leftPadding
input.placeholderText: "0"
validationMode: StatusInput.ValidationMode.IgnoreInvalidInput
validators: StatusFloatValidator { bottom: 0 }
StatusBaseText {
id: amountText
anchors.right: parent.right
anchors.rightMargin: 13
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Amount")
color: Theme.palette.baseColor1
font.pixelSize: 13
}
onTextChanged: {
if(d.isTokensLayout)
root.tokenAmount = Number(text)
else
root.collectibleAmount = Number(text)
function onAddClicked() {
root.addItem(root.itemKey, qsTr("%1 %2").arg(root.tokenAmount.toString()).arg(root.tokenName),
root.tokenImage, root.operator)
}
}
}
}
StatusButton {
enabled: d.isTokensLayout ? d.tokensReady : d.collectiblesReady
text: qsTr("Add")
height: 44
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.topMargin: 32
onClicked: {
if(d.isTokensLayout)
root.addItem(root.itemKey, root.tokenAmount.toString() + " " + root.tokenName, root.tokenImage, root.operator)
else
root.addItem(root.itemKey, root.collectibleAmount.toString() + " " + root.collectibleName, root.collectibleImage, root.operator)
Component {
id: collectiblesLayout
CollectiblesPanel {
collectibleName: root.collectibleName
collectibleImage: root.collectibleImage
amount: root.collectibleAmount === 0 ? "" : root.collectibleAmount.toString()
onAmountChanged: root.collectibleAmount = Number(amount)
specificAmount: root.collectiblesSpecificAmount
onSpecificAmountChanged: root.collectiblesSpecificAmount = specificAmount
onPickerClicked: {
d.extendedDropdownType = ExtendedDropdownContent.Type.Collectibles
content.state = d.extendedState
}
Connections {
target: d
function onAddClicked() {
root.addItem(root.itemKey, qsTr("%1 %2").arg(root.collectibleAmount.toString()).arg(root.collectibleName),
root.tokenImage, root.operator)
}
}
}
@ -294,21 +248,23 @@ StatusDropdown {
// TODO
Component {
id: ensLayout
Item {}
}
EnsPanel {}
}
Component {
id: extendedView
ExtendedDropdownContent {
id: extendedDropdown
store: root.store
type: d.isTokensLayout ? ExtendedDropdownContent.Type.Tokens : ExtendedDropdownContent.Type.Collectibles
onGoBack: loader.sourceComponent = tabsView
type: d.extendedDropdownType
onItemClicked: {
// Go back
loader.sourceComponent = tabsView
content.state = d.tabsState
if(d.isTokensLayout) {
if(d.extendedDropdownType === ExtendedDropdownContent.Type.Tokens) {
// Update new token item info
root.tokenName = name
root.tokenImage = iconSource
@ -318,8 +274,20 @@ StatusDropdown {
root.collectibleName = name
root.collectibleImage = iconSource
}
root.itemKey = key
}
Connections {
target: backButton
function onClicked() {
if (extendedDropdown.canGoBack)
extendedDropdown.goBack()
else
content.state = d.tabsState
}
}
}
}
}

View File

@ -0,0 +1,59 @@
import QtQuick 2.14
import StatusQ.Core 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
Item {
property alias addButtonEnabled: addButton.enabled
property alias tabLabels: tabLabelsRepeater.model
property alias currentIndex: tabBar.currentIndex
property alias sourceComponent: tabsLoader.sourceComponent
readonly property alias item: tabsLoader.item
signal addClicked
StatusSwitchTabBar {
id: tabBar
anchors.top: parent.top
anchors.right: parent.right
anchors.left: parent.left
height: 36 // by design
Repeater {
id: tabLabelsRepeater
StatusSwitchTabButton {
text: modelData
fontPixelSize: 13
}
}
}
Loader {
id: tabsLoader
anchors.top: tabBar.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.topMargin: 16
}
StatusButton {
id: addButton
text: qsTr("Add")
height: 44
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
onClicked: addClicked()
}
}

View File

@ -33,7 +33,7 @@ StatusListView {
id: columnHeader
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: 16
anchors.leftMargin: 6
anchors.rightMargin: anchors.leftMargin
anchors.topMargin: 8
anchors.bottomMargin: 2 * anchors.topMargin
@ -59,7 +59,7 @@ StatusListView {
color: mouseArea.containsMouse ? Theme.palette.baseColor4 : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 14
anchors.leftMargin: 6
spacing: 8
StatusRoundedImage {
Layout.alignment: Qt.AlignVCenter
@ -114,7 +114,7 @@ StatusListView {
width: ListView.view.width
height: 34 // by design
StatusBaseText {
anchors.leftMargin: 18
anchors.leftMargin: 8
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: section

View File

@ -0,0 +1,48 @@
import QtQuick.Layouts 1.14
import QtQuick 2.14
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQ
import utils 1.0
ColumnLayout {
id: root
signal operatorSelected(int operator)
spacing: 8
Repeater {
model: [
{
icon: "add",
text: qsTr("And..."),
operator: SQ.Utils.Operators.And
},
{
icon: "condition-Or",
text: qsTr("Or..."),
operator: SQ.Utils.Operators.Or
}
]
delegate: StatusPickerButton {
Layout.fillWidth: true
Layout.preferredHeight: 36
horizontalPadding: 12
spacing: 10
bgColor: Theme.palette.primaryColor3
contentColor: Theme.palette.primaryColor1
asset.name: Style.svg(modelData.icon)
asset.isImage: true
asset.height: 12
asset.width: 12
text: modelData.text
font.pixelSize: 13
onClicked: root.operatorSelected(modelData.operator)
}
}
}

View File

@ -0,0 +1,59 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Controls.Validators 0.1
ColumnLayout {
id: root
property alias tokenName: pickerButton.text
property url tokenImage
property alias amount: amountInput.text
signal pickerClicked
spacing: 0
StatusPickerButton {
id: pickerButton
Layout.fillWidth: true
Layout.preferredHeight: 36
bgColor: Theme.palette.baseColor5
contentColor: Theme.palette.directColor1
font.pixelSize: 13
asset.name: root.tokenImage
onClicked: pickerClicked()
}
StatusInput {
id: amountInput
Layout.fillWidth: true
Layout.topMargin: 8
minimumHeight: 36
maximumHeight: 36
topPadding: 0
bottomPadding: 0
font.pixelSize: 13
rightPadding: amountText.implicitWidth + amountText.anchors.rightMargin + leftPadding
input.placeholderText: "0"
validationMode: StatusInput.ValidationMode.IgnoreInvalidInput
validators: StatusFloatValidator { bottom: 0 }
StatusBaseText {
id: amountText
anchors.right: parent.right
anchors.rightMargin: 13
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Amount")
color: Theme.palette.baseColor1
font.pixelSize: 13
}
}
}

View File

@ -90,7 +90,7 @@ Item {
}
active: root.dirty
flickable: root.contentItem
saveChangesButtonEnabled: root.contentItem && root.contentItem.saveChangesButtonEnabled
saveChangesButtonEnabled: !!root.contentItem && !!root.contentItem.saveChangesButtonEnabled
onResetChangesClicked: root.resetChangesClicked()
onSaveChangesClicked: root.saveChangesClicked()
}