fix(StatusPopupMenu): Removed custom properties

This commit is contained in:
Igor Sirotin 2022-08-10 15:01:31 +03:00
parent 7fc207f75f
commit 45d7d80755
6 changed files with 211 additions and 153 deletions

View File

@ -22,8 +22,8 @@ GridLayout {
onClicked: complexMenu.popup() onClicked: complexMenu.popup()
} }
StatusButton { StatusButton {
id: customPopupButton
text: "Menu with custom images and icons" text: "Menu with custom images and icons"
onClicked: customMenu.popup() onClicked: customMenu.popup()
} }
@ -51,7 +51,7 @@ GridLayout {
StatusPopupMenu { StatusPopupMenu {
id: complexMenu id: complexMenu
subMenuItemIcons: [{ icon: 'info' }] // subMenuItemIcons: [{ icon: 'info' }]
StatusMenuItem { StatusMenuItem {
text: "One" text: "One"
@ -68,10 +68,13 @@ GridLayout {
StatusMenuItem { StatusMenuItem {
text: "Three" text: "Three"
iconSettings.name: "info" iconSettings.name: "info"
enabled: false
} }
StatusPopupMenu { StatusPopupMenu {
title: "Four" title: "Four"
iconSettings.name: "info"
StatusMenuItem { StatusMenuItem {
text: "One" text: "One"
iconSettings.name: "info" iconSettings.name: "info"
@ -85,17 +88,24 @@ GridLayout {
StatusPopupMenu { StatusPopupMenu {
id: customMenu id: customMenu
width: customPopupButton.width
subMenuItemIcons: [ // subMenuItemIcons: [
{ icon: "chat" }, // {
{ // icon: "chat"
source: "qrc:/demoapp/data/profile-image-1.jpeg" // },
}, // {
{ // source: "qrc:/demoapp/data/profile-image-1.jpeg"
isLetterIdenticon: true, // },
color: "red" // {
} // isLetterIdenticon: true,
] // color: "red"
// }
// ]
MenuItem {
text: "Default MenuItem, action: " + action
}
StatusMenuItem { StatusMenuItem {
text: "Anywhere" text: "Anywhere"
@ -104,7 +114,8 @@ GridLayout {
StatusMenuSeparator {} StatusMenuSeparator {}
StatusPopupMenu { StatusPopupMenu {
title: "Chat" title: "Chat"
iconSettings.name: "chat"
StatusMenuItem { StatusMenuItem {
text: "vitalik.eth" text: "vitalik.eth"
@ -121,6 +132,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusPopupMenu { StatusPopupMenu {
title: "Cryptokitties" title: "Cryptokitties"
imageSettings.source: "qrc:/demoapp/data/profile-image-1.jpeg"
StatusMenuItem { StatusMenuItem {
text: "welcome" text: "welcome"
@ -144,6 +156,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusPopupMenu { StatusPopupMenu {
title: "Another community" title: "Another community"
iconSettings.isLetterIdenticon: true
iconSettings.color: "red"
StatusMenuItem { StatusMenuItem {
text: "welcome" text: "welcome"

View File

@ -41,7 +41,6 @@ Column {
model: commmonModel model: commmonModel
selectMenu.delegate: StatusMenuItemDelegate { selectMenu.delegate: StatusMenuItemDelegate {
statusPopupMenu: select
action: StatusMenuItem { action: StatusMenuItem {
iconSettings.name: "filled-account" iconSettings.name: "filled-account"
text: name text: name

View File

@ -9,19 +9,27 @@ Action {
Normal, Normal,
Danger Danger
} }
icon.color: "transparent"
property int type: StatusMenuItem.Type.Normal property int type: StatusMenuItem.Type.Normal
property real iconRotation: 0 property real iconRotation: 0
// TODO: Rename to "imageSettings"
property StatusImageSettings image: StatusImageSettings { property StatusImageSettings image: StatusImageSettings {
height: 16 height: 16
width: 16 width: 16
isIdenticon: false isIdenticon: false
} }
property StatusIconSettings iconSettings: StatusIconSettings { property StatusIconSettings iconSettings: StatusIconSettings {
width: 18
height: 18
rotation: 0
isLetterIdenticon: false isLetterIdenticon: false
background: StatusIconBackgroundSettings {} background: StatusIconBackgroundSettings {}
color: "transparent" color: "transparent"
} }
property StatusFontSettings fontSettings: StatusFontSettings {} property StatusFontSettings fontSettings: StatusFontSettings {}
icon.color: "transparent"
} }

View File

@ -7,140 +7,139 @@ import StatusQ.Components 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
MenuItem { MenuItem {
id: statusPopupMenuItem id: root
implicitWidth: parent ? parent.width : 0 implicitWidth: parent ? parent.width : 0
implicitHeight: action.enabled ? 38 : 0 implicitHeight: menu.hideDisabledItems && !enabled ? 0 : 38
objectName: action.objectName objectName: action ? action.objectName : "StatusMenuItemDelegate"
property int subMenuIndex // property int subMenuIndex
property var statusPopupMenu: null // property var statusPopupMenu: null
Component.onCompleted: { readonly property string logObjectName: "StatusMenuItemDelegate [%1, %2]".arg(this).arg(text)
if (!!subMenu) {
subMenuIndex = statusPopupMenu.menuItemCount // Component.onCompleted: {
statusPopupMenu.menuItemCount += 1 // console.log("<---", logObjectName, " completed:", statusPopupMenu, menu, subMenu, action)
} // }
}
// onMenuChanged: console.log("<--- ", logObjectName, " menu changed: ", menu)
// onActionChanged: console.log("<--- ", logObjectName, " action changed: ", action, action.text, text)
action: StatusMenuItem { action: StatusMenuItem {
onTriggered: { statusPopupMenu.menuItemClicked(statusPopupMenuItem.subMenuIndex); } // onTriggered: { statusPopupMenu.menuItemClicked(root.subMenuIndex); }
}
QtObject {
id: d
readonly property bool isSubMenu: !!root.subMenu
readonly property bool isStatusSubMenu: isSubMenu && (root.subMenu instanceof StatusPopupMenu)
readonly property bool hasAction: !!root.action
readonly property bool isStatusAction: d.hasAction && (root.action instanceof StatusMenuItem)
readonly property bool isDangerIcon: d.isStatusAction && root.action.type === StatusMenuItem.Type.Danger
readonly property StatusImageSettings imageSettings: d.isStatusSubMenu
? root.subMenu.imageSettings
: d.isStatusAction ? root.action.image : d.defaultImage
readonly property StatusIconSettings iconSettings: {
console.log("<<<--- Calling iconSettings", root.logObjectName)
return d.isStatusSubMenu
? root.subMenu.iconSettings
: d.isStatusAction ? root.action.iconSettings : d.defaultIcon
}
readonly property StatusFontSettings fontSettings: d.isStatusSubMenu
? root.subMenu.fontSettings
: d.isStatusAction ? root.action.fontSettings : d.defaultFontSettings
readonly property StatusImageSettings defaultImage: StatusImageSettings {
width: 16
height: 16
}
readonly property StatusIconSettings defaultIcon: StatusIconSettings {
width: 18
height: 18
rotation: 0
}
readonly property StatusFontSettings defaultFontSettings: StatusFontSettings {
pixelSize: 13
bold: false
italic: false
}
} }
Component { Component {
id: indicatorComponent id: indicatorIcon
Item {
implicitWidth: 24
implicitHeight: 24
StatusIcon {
anchors.centerIn: parent
width: {
let width = statusPopupMenuItem.action && statusPopupMenuItem.action.icon.width ||
statusPopupMenuItem.action.iconSettings && statusPopupMenuItem.action.iconSettings.width
return !!width ? width : 18
}
rotation: !!statusPopupMenuItem.action.iconRotation ? statusPopupMenuItem.action.iconRotation : 0
icon: {
if (statusPopupMenuItem.subMenu && !!statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] &&
statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon.toString() !== "") {
return statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon;
} else if (!!statusPopupMenuItem.action && statusPopupMenuItem.action.icon.name !== "") {
return statusPopupMenuItem.action.icon.name;
} else if (!!statusPopupMenuItem.action.iconSettings && statusPopupMenuItem.action.iconSettings.name !== "") {
return statusPopupMenuItem.action.iconSettings.name;
} else {
return "";
}
}
color: {
let c = !!statusPopupMenuItem.action.iconSettings && statusPopupMenuItem.action.iconSettings.color ||
!!statusPopupMenuItem.action && statusPopupMenuItem.action.icon.color
if (!Qt.colorEqual(c, "transparent")) { StatusIcon {
return c width: d.iconSettings.width // TODO: Also process action.icon.width?
} height: d.iconSettings.height // TODO: Also process action.icon.height?
switch (statusPopupMenuItem.action.type) { rotation: d.iconSettings.rotation // TODO: Also process action.icon.rotation? // !!root.action.iconRotation ? root.action.iconRotation : 0
case StatusMenuItem.Type.Danger: icon: d.iconSettings.name // TODO: Also process action.icon?
return Theme.palette.dangerColor1 color: {
default: const c = d.iconSettings.color;
return Theme.palette.primaryColor1 if (!Qt.colorEqual(c, "transparent"))
} return c;
} if (d.isDangerIcon)
return Theme.palette.dangerColor1;
return Theme.palette.primaryColor1;
} }
} }
} }
Component { Component {
id: statusLetterIdenticonCmp id: indicatorLetterIdenticon
Item {
implicitWidth: 24
implicitHeight: 24
StatusLetterIdenticon { StatusLetterIdenticon {
anchors.centerIn: parent width: d.imageSettings.width
width: 16 height: d.imageSettings.height
height: 16 color: d.iconSettings.color
color: { name: root.text
let subMenuItemIcon = statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] letterSize: 11
return subMenuItemIcon && subMenuItemIcon.color ? subMenuItemIcon.color : statusPopupMenuItem.action.iconSettings.background.color
}
name: statusPopupMenuItem.text
letterSize: 11
}
} }
} }
Component { Component {
id: statusRoundImageCmp id: indicatorImage
Item { StatusRoundedImage {
implicitWidth: 24 width: d.imageSettings.width
implicitHeight: 24 height: d.imageSettings.height
StatusRoundedImage { image.source: d.imageSettings.source
anchors.centerIn: parent border.width: d.isSubMenu && d.imageSettings.isIdenticon ? 1 : 0
width: statusPopupMenuItem.action.image.width border.color: Theme.palette.directColor7
height: statusPopupMenuItem.action.image.height
image.source: statusPopupMenuItem.subMenu ?
statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].source :
statusPopupMenuItem.action.image.source
border.width: (statusPopupMenuItem.subMenu && statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].isIdenticon) ||
statusPopupMenuItem.action.image.isIdenticon ? 1 : 0
border.color: Theme.palette.directColor7
}
} }
} }
indicator: Loader { indicator: Item {
sourceComponent: { implicitWidth: 24
let subMenuItemIcon = statusPopupMenu.subMenuItemIcons && statusPopupMenu.subMenuItemIcons[parent.subMenuIndex] implicitHeight: 24
Loader {
if ((parent.subMenu && subMenuItemIcon && subMenuItemIcon.source) || anchors.centerIn: parent
statusPopupMenuItem.action.image && !!statusPopupMenuItem.action.image.source.toString()) { // sourceComponent: {
return statusRoundImageCmp // if (!!d.imageSettings.source.toString())
} // return indicatorImage;
// if (d.iconSettings.isLetterIdenticon)
// return indicatorLetterIdenticon;
// return indicatorIcon;
// }
return (parent.subMenu && subMenuItemIcon && subMenuItemIcon.isLetterIdenticon) || // sourceComponent: indicatorIcon
(statusPopupMenuItem.action.iconsSettings && statusPopupMenuItem.action.iconSettings.isLetterIdenticon) ? // sourceComponent: indicatorLetterIdenticon
statusLetterIdenticonCmp : indicatorComponent // sourceComponent: indicatorImage
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 8
// active: enabled // TODO: Also process action.icon.name ?
// && (d.iconSettings.isLetterIdenticon
// || !!d.iconSettings.name
// || !!d.imageSettings.source.toString())
} }
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 8
active: {
if (enabled) {
let hasIconSettings = !!statusPopupMenuItem.action.icon.name ||
(statusPopupMenuItem.action.iconSettings &&
(!!statusPopupMenuItem.action.iconSettings.name || !!statusPopupMenuItem.action.iconSettings.isLetterIdenticon))
let hasImageSettings = statusPopupMenuItem.action.image && !!statusPopupMenuItem.action.image.source.toString()
return enabled && (parent.subMenu && !!statusPopupMenu.subMenuItemIcons[parent.subMenuIndex]) || hasIconSettings || hasImageSettings
}
return false
}
} }
contentItem: StatusBaseText { contentItem: StatusBaseText {
anchors.left: statusPopupMenuItem.indicator.right anchors.left: root.indicator.right
anchors.right: arrowIcon.visible ? arrowIcon.left : arrowIcon.right anchors.right: arrowIcon.visible ? arrowIcon.left : arrowIcon.right
anchors.rightMargin: 8 anchors.rightMargin: 8
anchors.leftMargin: 4 anchors.leftMargin: 4
@ -148,20 +147,13 @@ MenuItem {
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
text: statusPopupMenuItem.text text: root.text
color: { color: d.isDangerIcon ? Theme.palette.dangerColor1 : Theme.palette.directColor1
switch (statusPopupMenuItem.action.type) { font.pixelSize: d.fontSettings.pixelSize // !!root.action.fontSettings ? root.action.fontSettings.pixelSize : 13
case StatusMenuItem.Type.Danger: font.bold: d.fontSettings.bold // !!root.action.fontSettings ? root.action.fontSettings.bold : false
return Theme.palette.dangerColor1 font.italic: d.fontSettings.italic // !!root.action.fontSettings ? root.action.fontSettings.italic : false
default:
return Theme.palette.directColor1
}
}
font.pixelSize: !!statusPopupMenuItem.action.fontSettings ? statusPopupMenuItem.action.fontSettings.pixelSize : 13
font.bold: !!statusPopupMenuItem.action.fontSettings ? statusPopupMenuItem.action.fontSettings.bold : false
font.italic: !!statusPopupMenuItem.action.fontSettings ? statusPopupMenuItem.action.fontSettings.italic : false
elide: Text.ElideRight elide: Text.ElideRight
visible: statusPopupMenuItem.action.enabled visible: true // hideDisabledItems ? root.enabled : true
} }
arrow: StatusIcon { arrow: StatusIcon {
@ -170,25 +162,25 @@ MenuItem {
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 8 anchors.rightMargin: 8
height: 16 height: 16
visible: statusPopupMenuItem.subMenu visible: d.isSubMenu
icon: "next" icon: "next"
color: Theme.palette.directColor1 color: Theme.palette.directColor1
} }
background: Rectangle { background: Rectangle {
color: { color: {
if (statusPopupMenuItem.hovered) { if (!root.hovered)
return statusPopupMenuItem.action.type === StatusMenuItem.Type.Danger ? Theme.palette.dangerColor3 : Theme.palette.statusPopupMenu.hoverBackgroundColor return "transparent"
} if (root.action.type === StatusMenuItem.Type.Danger)
return "transparent" return Theme.palette.dangerColor3;
return Theme.palette.statusPopupMenu.hoverBackgroundColor;
} }
} }
MouseArea { MouseArea {
id: sensor
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
hoverEnabled: statusPopupMenuItem.action.enabled hoverEnabled: root.enabled // WARNING: use root.enabled ?
onPressed: mouse.accepted = false onPressed: mouse.accepted = false
} }
} }

View File

@ -10,20 +10,56 @@ import StatusQ.Popups 0.1
Menu { Menu {
id: root id: root
// Component.onCompleted: {
// let parents = "";
// let p = parent;
// while (p) {
// parents += " <- " + p;
// p = p.parent;
// }
//// console.log("<-- StatusPopupMenu created", this, parents);
// }
closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
topPadding: 8 topPadding: 8
bottomPadding: 8 bottomPadding: 8
property int menuItemCount: 0 // property int menuItemCount: 0
property var subMenuItemIcons: [] // property var subMenuItemIcons: []
// source: model.imageSource, // -> StatusRoundedImage.image.source
// icon: model.iconName, // -> StatusIcon.icon
// isIdenticon: model.isIdenticon, // -> StatusRoundImage.border.width
// color: model.iconColor, // -> StatusLetterIdenticon.color,
// isLetterIdenticon: !model.imageSource && !model.iconName // -> decide indicator component
property StatusImageSettings imageSettings: StatusImageSettings {
height: 16
width: 16
isIdenticon: false
}
property StatusIconSettings iconSettings: StatusIconSettings {
width: 18
height: 18
rotation: 0
isLetterIdenticon: false
background: StatusIconBackgroundSettings {}
color: "transparent"
}
property StatusFontSettings fontSettings: StatusFontSettings {}
property bool hideDisabledItems: false
property var openHandler property var openHandler
property var closeHandler property var closeHandler
dim: false
signal menuItemClicked(int menuIndex) signal menuItemClicked(int menuIndex)
dim: false
onOpened: { onOpened: {
if (typeof openHandler === "function") { if (typeof openHandler === "function") {
openHandler() openHandler()
@ -37,7 +73,7 @@ Menu {
} }
delegate: StatusMenuItemDelegate { delegate: StatusMenuItemDelegate {
statusPopupMenu: root // statusPopupMenu: root
} }
background: Item { background: Item {

View File

@ -28,6 +28,8 @@ StatusPopupMenu {
MenuItem { implicitHeight: 0.00001 } MenuItem { implicitHeight: 0.00001 }
Instantiator { Instantiator {
model: root.locationModel model: root.locationModel
// NOTE: Use DelegateChooser here
delegate: Loader { delegate: Loader {
sourceComponent: (!!model.subItems && model.subItems.count > 0) ? subMenus : subMenuItemComponent sourceComponent: (!!model.subItems && model.subItems.count > 0) ? subMenus : subMenuItemComponent
onLoaded: { onLoaded: {
@ -38,13 +40,20 @@ StatusPopupMenu {
item.parentIconName = model.iconName; item.parentIconName = model.iconName;
item.parentImageSource = model.imageSource; item.parentImageSource = model.imageSource;
item.parentIdenticonColor = !!model.iconColor ? model.iconColor : Theme.palette.primaryColor1; item.parentIdenticonColor = !!model.iconColor ? model.iconColor : Theme.palette.primaryColor1;
root.subMenuItemIcons.push({
source: model.imageSource, item.imageSettings.source = model.imageSource;
icon: model.iconName, item.imageSettings.isIdenticon = model.isIdenticon;
isIdenticon: model.isIdenticon, item.iconSettings.name = model.iconName;
color: model.iconColor, item.iconSettings.color = model.iconColor;
isLetterIdenticon: !model.imageSource && !model.iconName item.iconSettings.isLetterIdenticon = !model.imageSource && !model.iconName;
});
// root.subMenuItemIcons.push({
// source: model.imageSource, // -> StatusRoundedImage.image.source
// icon: model.iconName, // -> StatusIcon.icon
// isIdenticon: model.isIdenticon, // -> StatusRoundImage.border.width
// color: model.iconColor, // -> StatusLetterIdenticon.color,
// isLetterIdenticon: !model.imageSource && !model.iconName // -> decide indicator component
// });
root.insertMenu(index + numDefaultItems, item); root.insertMenu(index + numDefaultItems, item);
} else { } else {
item.value = model.value item.value = model.value