From 3c4c7f040ad04d00f0f1dfb7617d4db8b917bff6 Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Wed, 21 Jul 2021 15:09:11 +0200 Subject: [PATCH] feat(StatusPopupMenu): add support for letter identicons, identicons and images This extends the popup menu to accept image or icon configurations a la `StatusIconSettings` and `StatusImageSettings` in menu items, as well as nested menus. Usage: ```qml StatusPopupMenu { StatusMenuItem { text: "Custom Image icon" image.source: // image source } StatusMenuItem { text: "Custom identicon icon" image.source: // identicon source image.isIdenticon: true } StatusMenuItem { text: "Custom letter identicon" iconSettings.isLetterIdenticon: true iconSettings.background.color: "red" } } ``` Few things to note: - Because `StatusMenuItem` is an `Action` type, we can't extend its `icon` property, so we have to introduce our own (`iconSettings`) which can be of type `StatusIconSettings` - Where possible, `StatusPopupMenu` will prefer `iconSettings.[...]` over `icon.[...]`, which means, both would work: `icon.name` and `iconSettings.name`. This is for consistency's sake. Consumers can switch completely to `iconSettings` if desired. - When `isLetterIdenticon` is true, `iconSettings.background.color` must be set, similar to how it work in any other StatusQ component that makes use of this configuration type. Closes #263 --- sandbox/StatusPopupMenuPage.qml | 88 ++++++++++++++++++++++++-- src/StatusQ/Popups/StatusMenuItem.qml | 12 +++- src/StatusQ/Popups/StatusPopupMenu.qml | 83 +++++++++++++++++++++--- 3 files changed, 169 insertions(+), 14 deletions(-) diff --git a/sandbox/StatusPopupMenuPage.qml b/sandbox/StatusPopupMenuPage.qml index db6d50b5..70693f1d 100644 --- a/sandbox/StatusPopupMenuPage.qml +++ b/sandbox/StatusPopupMenuPage.qml @@ -22,6 +22,13 @@ GridLayout { onClicked: complexMenu.popup() } + + StatusButton { + text: "Menu with custom images and icons" + onClicked: customMenu.popup() + } + + StatusPopupMenu { id: simpleMenu StatusMenuItem { @@ -40,32 +47,103 @@ GridLayout { StatusPopupMenu { id: complexMenu subMenuItemIcons: ['info'] + StatusMenuItem { text: "One" - icon.name: "info" + iconSettings.name: "info" } StatusMenuSeparator {} StatusMenuItem { text: "Two" - icon.name: "info" + iconSettings.name: "info" } StatusMenuItem { text: "Three" - icon.name: "info" + iconSettings.name: "info" } StatusPopupMenu { title: "Four" StatusMenuItem { text: "One" - icon.name: "info" + iconSettings.name: "info" } StatusMenuItem { text: "Three" - icon.name: "info" + iconSettings.name: "info" + } + } + } + + StatusPopupMenu { + id: customMenu + + subMenuItemIcons: [ + "chat", + { + source: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg" + }, + { + isLetterIdenticon: true, + color: "red" + } + ] + + StatusMenuItem { + text: "Anywhere" + } + + StatusMenuSeparator {} + + StatusPopupMenu { + title: "Chat" + + StatusMenuItem { + text: "vitalik.eth" + image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh +CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC" + image.isIdenticon: true + } + + StatusMenuItem { + text: "Pascal" + image.source: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg" + } + } + + StatusPopupMenu { + title: "Cryptokitties" + + StatusMenuItem { + text: "welcome" + iconSettings.name: "channel" + iconSettings.color: Theme.palette.directColor1 + } + StatusMenuItem { + text: "support" + iconSettings.name: "channel" + iconSettings.color: Theme.palette.directColor1 + } + + StatusMenuHeadline { text: "Public" } + + StatusMenuItem { + text: "news" + iconSettings.name: "channel" + iconSettings.color: Theme.palette.directColor1 + } + } + + StatusPopupMenu { + title: "Another community" + + StatusMenuItem { + text: "welcome" + iconSettings.isLetterIdenticon: true + iconSettings.background.color: "red" } } } diff --git a/src/StatusQ/Popups/StatusMenuItem.qml b/src/StatusQ/Popups/StatusMenuItem.qml index 256906ae..7e3b0c88 100644 --- a/src/StatusQ/Popups/StatusMenuItem.qml +++ b/src/StatusQ/Popups/StatusMenuItem.qml @@ -9,7 +9,17 @@ Action { Normal, Danger } - + icon.color: "transparent" property int type: StatusMenuItem.Type.Normal property real iconRotation: 0 + property StatusImageSettings image: StatusImageSettings { + height: 16 + width: 16 + isIdenticon: false + } + property StatusIconSettings iconSettings: StatusIconSettings { + isLetterIdenticon: false + background: StatusIconBackgroundSettings {} + color: "transparent" + } } diff --git a/src/StatusQ/Popups/StatusPopupMenu.qml b/src/StatusQ/Popups/StatusPopupMenu.qml index 979a5fba..f1d8118a 100644 --- a/src/StatusQ/Popups/StatusPopupMenu.qml +++ b/src/StatusQ/Popups/StatusPopupMenu.qml @@ -4,6 +4,7 @@ import QtGraphicalEffects 1.13 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 import StatusQ.Popups 0.1 @@ -54,13 +55,27 @@ Menu { implicitHeight: 24 StatusIcon { anchors.centerIn: parent - width: !!statusPopupMenuItem.action.icon.width ? - statusPopupMenuItem.action.icon.width : 18 + width: { + let width = statusPopupMenuItem.action.icon.width || + statusPopupMenuItem.action.iconSettings.width + + return !!width ? width : 18 + } rotation: statusPopupMenuItem.action.iconRotation - icon: statusPopupMenuItem.subMenu ? - statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] : - statusPopupMenuItem.action.icon.name + icon: { + if (statusPopupMenuItem.subMenu) { + return statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] + } + return statusPopupMenuItem.action.icon.name || + statusPopupMenuItem.action.iconSettings.name + } color: { + let c = statusPopupMenuItem.action.iconSettings.color || + statusPopupMenuItem.action.icon.color + + if (!Qt.colorEqual(c, "transparent")) { + return c + } switch (statusPopupMenuItem.action.type) { case StatusMenuItem.Type.Danger: return Theme.palette.dangerColor1 @@ -73,13 +88,66 @@ Menu { } } + Component { + id: statusLetterIdenticonCmp + Item { + implicitWidth: 24 + implicitHeight: 24 + + StatusLetterIdenticon { + anchors.centerIn: parent + width: 16 + height: 16 + color: { + let subMenuItemIcon = statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] + return subMenuItemIcon && subMenuItemIcon.color ? subMenuItemIcon.color : statusPopupMenuItem.action.iconSettings.background.color + } + name: statusPopupMenuItem.text + letterSize: 11 + } + } + } + + Component { + id: statusRoundImageCmp + + Item { + implicitWidth: 24 + implicitHeight: 24 + StatusRoundedImage { + anchors.centerIn: parent + width: statusPopupMenuItem.action.image.width + 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 { - sourceComponent: indicatorComponent + sourceComponent: { + let subMenuItemIcon = statusPopupMenu.subMenuItemIcons[parent.subMenuIndex] + + if ((parent.subMenu && subMenuItemIcon && subMenuItemIcon.source) || !!statusPopupMenuItem.action.image.source.toString()) { + return statusRoundImageCmp + } + + return (parent.subMenu && subMenuItemIcon && subMenuItemIcon.isLetterIdenticon) || + statusPopupMenuItem.action.iconSettings.isLetterIdenticon ? + statusLetterIdenticonCmp : indicatorComponent + } anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.leftMargin: 8 active: (parent.subMenu && !!statusPopupMenu.subMenuItemIcons[parent.subMenuIndex] || - !!statusPopupMenuItem.action.icon.name) && + (!!statusPopupMenuItem.action.icon.name || + !!statusPopupMenuItem.action.iconSettings.name) || + !!statusPopupMenuItem.action.iconSettings.isLetterIdenticon || + !!statusPopupMenuItem.action.image.source.toString()) && statusPopupMenuItem.action.enabled } @@ -163,5 +231,4 @@ Menu { } } } - }