2023-10-17 19:09:45 +00:00
|
|
|
import QtQuick 2.15
|
|
|
|
import QtQuick.Controls 2.15
|
|
|
|
import QtQuick.Layouts 1.15
|
|
|
|
import QtGraphicalEffects 1.15
|
|
|
|
|
|
|
|
import StatusQ.Core 0.1
|
|
|
|
import StatusQ.Controls 0.1
|
|
|
|
import StatusQ.Core.Theme 0.1
|
|
|
|
import StatusQ.Popups 0.1
|
|
|
|
|
|
|
|
import utils 1.0
|
|
|
|
|
|
|
|
ComboBox {
|
|
|
|
id: root
|
|
|
|
|
2023-12-06 10:54:36 +00:00
|
|
|
// expected model role names: text, value (enum TokenOrder), sortRoleName, icon (optional)
|
|
|
|
// text === "---" denotes a separator
|
|
|
|
|
|
|
|
property bool hasCustomOrderDefined
|
|
|
|
|
|
|
|
property int currentSortOrder: Qt.DescendingOrder
|
|
|
|
readonly property string currentSortRoleName: root.currentIndex !== -1 ? root.model[root.currentIndex].sortRoleName : ""
|
|
|
|
|
|
|
|
signal createOrEditRequested()
|
2023-10-17 19:09:45 +00:00
|
|
|
|
|
|
|
textRole: "text"
|
|
|
|
valueRole: "value"
|
|
|
|
|
2023-12-06 10:54:36 +00:00
|
|
|
displayText: root.currentValue === SortOrderComboBox.TokenOrderCustom ? currentText
|
|
|
|
: "%1 %2".arg(currentText).arg(currentSortOrder === Qt.DescendingOrder ? "↓" : "↑")
|
|
|
|
|
|
|
|
onActivated: {
|
|
|
|
if (index === indexOfValue(SortOrderComboBox.TokenOrderCreateCustom)) { // restore the previous sort role and signal we want create/edit
|
|
|
|
currentIndex = d.currentIndex
|
|
|
|
root.createOrEditRequested()
|
|
|
|
} else {
|
|
|
|
if (d.currentIndex === index) // just keep the same sort role and flip the up/down
|
|
|
|
currentSortOrder = currentSortOrder === Qt.AscendingOrder ? Qt.DescendingOrder : Qt.AscendingOrder
|
|
|
|
|
|
|
|
// update internal index
|
|
|
|
d.currentIndex = index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component.onCompleted: {
|
|
|
|
d.currentIndex = root.currentIndex // sync with settings which might arrive from the outside
|
|
|
|
}
|
2023-10-17 19:09:45 +00:00
|
|
|
|
|
|
|
enum TokenOrder {
|
|
|
|
TokenOrderNone = 0,
|
2023-12-06 10:54:36 +00:00
|
|
|
TokenOrderCurrencyBalance, // FIAT value of asset balance (enabledNetworkCurrencyBalance)
|
|
|
|
TokenOrderBalance, // Number of tokens (enabledNetworkBalance)
|
|
|
|
TokenOrderCurrencyPrice, // Value per token in FIAT (currencyPrice)
|
2024-03-07 13:47:17 +00:00
|
|
|
TokenOrder1DChange, // Level of change in asset balance value (in FIAT) comp. to 1 day earlier
|
2023-12-06 10:54:36 +00:00
|
|
|
TokenOrderAlpha, // Alphabetic by asset name (name)
|
|
|
|
TokenOrderDateAdded, // Date added descending (newest first)
|
|
|
|
TokenOrderGroupName, // Collection or Community name
|
|
|
|
TokenOrderCustom, // Custom (user created) order
|
|
|
|
TokenOrderCreateCustom // special menu entry to create/edit the custom sort order
|
2023-10-17 19:09:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
horizontalPadding: 12
|
2023-12-06 10:54:36 +00:00
|
|
|
verticalPadding: Style.current.halfPadding
|
|
|
|
spacing: Style.current.halfPadding
|
2023-10-17 19:09:45 +00:00
|
|
|
|
|
|
|
font.family: Theme.palette.baseFont.name
|
|
|
|
font.pixelSize: Style.current.additionalTextSize
|
|
|
|
|
|
|
|
QtObject {
|
|
|
|
id: d
|
|
|
|
|
|
|
|
readonly property int defaultDelegateHeight: 34
|
|
|
|
|
2023-12-06 10:54:36 +00:00
|
|
|
property int currentIndex: 0
|
2023-10-17 19:09:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
background: Rectangle {
|
|
|
|
border.width: 1
|
|
|
|
border.color: Theme.palette.directColor7
|
2023-12-06 10:54:36 +00:00
|
|
|
radius: Style.current.radius
|
2023-10-17 19:09:45 +00:00
|
|
|
color: root.down ? Theme.palette.baseColor2 : "transparent"
|
|
|
|
HoverHandler {
|
|
|
|
cursorShape: root.enabled ? Qt.PointingHandCursor : undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
contentItem: StatusBaseText {
|
|
|
|
leftPadding: root.horizontalPadding
|
|
|
|
rightPadding: root.horizontalPadding
|
|
|
|
font.pixelSize: root.font.pixelSize
|
|
|
|
font.weight: Font.Medium
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
elide: Text.ElideRight
|
|
|
|
text: root.displayText
|
|
|
|
color: Theme.palette.baseColor1
|
|
|
|
}
|
|
|
|
|
|
|
|
indicator: StatusIcon {
|
|
|
|
x: root.mirrored ? root.horizontalPadding : root.width - width - root.horizontalPadding
|
|
|
|
y: root.topPadding + (root.availableHeight - height) / 2
|
|
|
|
width: 16
|
|
|
|
height: width
|
|
|
|
icon: "chevron-down"
|
|
|
|
color: Theme.palette.baseColor1
|
|
|
|
}
|
|
|
|
|
|
|
|
popup: Popup {
|
|
|
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
|
|
|
y: root.height + 4
|
|
|
|
|
2023-12-06 10:54:36 +00:00
|
|
|
implicitWidth: 290
|
|
|
|
margins: Style.current.halfPadding
|
2023-10-17 19:09:45 +00:00
|
|
|
|
|
|
|
padding: 1
|
2023-12-06 10:54:36 +00:00
|
|
|
verticalPadding: Style.current.halfPadding
|
2023-10-17 19:09:45 +00:00
|
|
|
|
|
|
|
background: Rectangle {
|
|
|
|
color: Theme.palette.statusSelect.menuItemBackgroundColor
|
2023-12-06 10:54:36 +00:00
|
|
|
radius: Style.current.radius
|
2023-10-17 19:09:45 +00:00
|
|
|
layer.enabled: true
|
|
|
|
layer.effect: DropShadow {
|
|
|
|
horizontalOffset: 0
|
|
|
|
verticalOffset: 4
|
|
|
|
radius: 12
|
|
|
|
samples: 25
|
|
|
|
spread: 0.2
|
|
|
|
color: Theme.palette.dropShadow
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
contentItem: ColumnLayout {
|
2023-12-06 10:54:36 +00:00
|
|
|
spacing: 0
|
2023-10-17 19:09:45 +00:00
|
|
|
StatusBaseText {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.preferredHeight: d.defaultDelegateHeight
|
|
|
|
text: qsTr("Sort by")
|
|
|
|
font.pixelSize: Style.current.tertiaryTextFontSize
|
|
|
|
leftPadding: Style.current.padding
|
|
|
|
verticalAlignment: Qt.AlignVCenter
|
|
|
|
color: Theme.palette.baseColor1
|
|
|
|
}
|
|
|
|
StatusListView {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
implicitWidth: contentWidth
|
|
|
|
implicitHeight: contentHeight
|
|
|
|
|
|
|
|
model: root.popup.visible ? root.delegateModel : null
|
|
|
|
currentIndex: root.highlightedIndex
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: regularMenuComponent
|
|
|
|
RowLayout {
|
|
|
|
spacing: root.spacing
|
|
|
|
|
|
|
|
StatusIcon {
|
2023-12-06 10:54:36 +00:00
|
|
|
Layout.preferredWidth: 16
|
|
|
|
Layout.preferredHeight: 16
|
2023-10-17 19:09:45 +00:00
|
|
|
visible: !!icon
|
|
|
|
icon: iconName
|
|
|
|
color: root.enabled ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
|
|
|
|
}
|
|
|
|
|
|
|
|
StatusBaseText {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
text: menuText
|
|
|
|
elide: Text.ElideRight
|
2023-12-06 10:54:36 +00:00
|
|
|
color: isEditAction ? Theme.palette.primaryColor1 : root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
2023-10-17 19:09:45 +00:00
|
|
|
font.pixelSize: root.font.pixelSize
|
|
|
|
font.weight: root.currentIndex === menuIndex ? Font.DemiBold : Font.Normal
|
|
|
|
}
|
|
|
|
|
|
|
|
Item { Layout.fillWidth: true }
|
|
|
|
|
|
|
|
Row {
|
2023-12-06 10:54:36 +00:00
|
|
|
visible: showUpDownArrows
|
2023-10-17 19:09:45 +00:00
|
|
|
spacing: 4
|
|
|
|
StatusFlatRoundButton {
|
|
|
|
radius: 6
|
|
|
|
width: 24
|
|
|
|
height: 24
|
|
|
|
icon.name: "arrow-up"
|
|
|
|
icon.width: 18
|
|
|
|
icon.height: 18
|
|
|
|
opacity: root.highlightedIndex === menuIndex || highlighted // not "visible, we want the item to stay put
|
2023-12-06 10:54:36 +00:00
|
|
|
highlighted: root.currentIndex === menuIndex && root.currentSortOrder === Qt.AscendingOrder
|
2023-10-17 19:09:45 +00:00
|
|
|
onClicked: {
|
|
|
|
if (root.currentIndex !== menuIndex)
|
|
|
|
root.currentIndex = menuIndex
|
2023-12-06 10:54:36 +00:00
|
|
|
d.currentIndex = menuIndex
|
|
|
|
root.currentSortOrder = Qt.AscendingOrder
|
2023-10-17 19:09:45 +00:00
|
|
|
root.popup.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StatusFlatRoundButton {
|
|
|
|
radius: 6
|
|
|
|
width: 24
|
|
|
|
height: 24
|
|
|
|
icon.name: "arrow-down"
|
|
|
|
icon.width: 18
|
|
|
|
icon.height: 18
|
|
|
|
opacity: root.highlightedIndex === menuIndex || highlighted // not "visible, we want the item to stay put
|
2023-12-06 10:54:36 +00:00
|
|
|
highlighted: root.currentIndex === menuIndex && root.currentSortOrder === Qt.DescendingOrder
|
2023-10-17 19:09:45 +00:00
|
|
|
onClicked: {
|
|
|
|
if (root.currentIndex !== menuIndex)
|
|
|
|
root.currentIndex = menuIndex
|
2023-12-06 10:54:36 +00:00
|
|
|
d.currentIndex = menuIndex
|
|
|
|
root.currentSortOrder = Qt.DescendingOrder
|
2023-10-17 19:09:45 +00:00
|
|
|
root.popup.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: separatorMenuComponent
|
|
|
|
StatusMenuSeparator {}
|
|
|
|
}
|
|
|
|
|
|
|
|
delegate: ItemDelegate {
|
|
|
|
required property int index
|
|
|
|
required property var modelData
|
|
|
|
readonly property bool isSeparator: text === "---"
|
|
|
|
|
|
|
|
id: menuDelegate
|
2023-12-06 10:54:36 +00:00
|
|
|
width: ListView.view.width
|
2023-10-17 19:09:45 +00:00
|
|
|
highlighted: root.highlightedIndex === index
|
|
|
|
enabled: !isSeparator
|
2023-12-06 10:54:36 +00:00
|
|
|
visible: {
|
|
|
|
if (modelData["value"] === SortOrderComboBox.TokenOrderCustom) // hide "Custom order" menu entry if none defined
|
|
|
|
return root.hasCustomOrderDefined
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
height: visible ? implicitHeight : 0
|
2023-10-17 19:09:45 +00:00
|
|
|
leftPadding: isSeparator ? 0 : 14
|
|
|
|
rightPadding: isSeparator ? 0 : 8
|
|
|
|
verticalPadding: isSeparator ? 2 : 5
|
|
|
|
spacing: root.spacing
|
|
|
|
font: root.font
|
|
|
|
text: root.textRole ? (Array.isArray(root.model) ? modelData[root.textRole] : model[root.textRole])
|
|
|
|
: modelData
|
|
|
|
icon.name: modelData["icon"]
|
|
|
|
icon.color: Theme.palette.primaryColor1
|
|
|
|
background: Rectangle {
|
|
|
|
implicitHeight: parent.isSeparator ? 3 : d.defaultDelegateHeight
|
|
|
|
color: {
|
|
|
|
if (menuDelegate.index === root.currentIndex)
|
|
|
|
return Theme.palette.primaryColor3
|
|
|
|
if (menuDelegate.highlighted)
|
|
|
|
return Theme.palette.statusMenu.hoverBackgroundColor
|
|
|
|
|
|
|
|
return "transparent"
|
|
|
|
}
|
|
|
|
HoverHandler {
|
|
|
|
cursorShape: root.enabled ? Qt.PointingHandCursor : undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
contentItem: Loader {
|
|
|
|
readonly property int menuIndex: menuDelegate.index
|
|
|
|
readonly property string menuText: menuDelegate.text
|
|
|
|
readonly property string iconName: menuDelegate.icon.name
|
2023-12-06 10:54:36 +00:00
|
|
|
readonly property bool showUpDownArrows: menuDelegate.modelData["sortRoleName"] !== ""
|
|
|
|
readonly property bool isEditAction: modelData["value"] === SortOrderComboBox.TokenOrderCreateCustom
|
2023-10-17 19:09:45 +00:00
|
|
|
sourceComponent: menuDelegate.isSeparator ? separatorMenuComponent : regularMenuComponent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|