diff --git a/sandbox/pages/StatusPopupMenuPage.qml b/sandbox/pages/StatusPopupMenuPage.qml index 90c4d0f5..a0b35319 100644 --- a/sandbox/pages/StatusPopupMenuPage.qml +++ b/sandbox/pages/StatusPopupMenuPage.qml @@ -22,8 +22,8 @@ GridLayout { onClicked: complexMenu.popup() } - StatusButton { + id: customPopupButton text: "Menu with custom images and icons" onClicked: customMenu.popup() } @@ -51,7 +51,7 @@ GridLayout { StatusPopupMenu { id: complexMenu - subMenuItemIcons: [{ icon: 'info' }] +// subMenuItemIcons: [{ icon: 'info' }] StatusMenuItem { text: "One" @@ -68,10 +68,13 @@ GridLayout { StatusMenuItem { text: "Three" iconSettings.name: "info" + enabled: false } StatusPopupMenu { title: "Four" + iconSettings.name: "info" + StatusMenuItem { text: "One" iconSettings.name: "info" @@ -85,17 +88,24 @@ GridLayout { StatusPopupMenu { id: customMenu + width: customPopupButton.width - subMenuItemIcons: [ - { icon: "chat" }, - { - source: "qrc:/demoapp/data/profile-image-1.jpeg" - }, - { - isLetterIdenticon: true, - color: "red" - } - ] +// subMenuItemIcons: [ +// { +// icon: "chat" +// }, +// { +// source: "qrc:/demoapp/data/profile-image-1.jpeg" +// }, +// { +// isLetterIdenticon: true, +// color: "red" +// } +// ] + + MenuItem { + text: "Default MenuItem, action: " + action + } StatusMenuItem { text: "Anywhere" @@ -104,7 +114,8 @@ GridLayout { StatusMenuSeparator {} StatusPopupMenu { - title: "Chat" + title: "Chat" + iconSettings.name: "chat" StatusMenuItem { text: "vitalik.eth" @@ -121,6 +132,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I StatusPopupMenu { title: "Cryptokitties" + imageSettings.source: "qrc:/demoapp/data/profile-image-1.jpeg" StatusMenuItem { text: "welcome" @@ -144,6 +156,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I StatusPopupMenu { title: "Another community" + iconSettings.isLetterIdenticon: true + iconSettings.color: "red" StatusMenuItem { text: "welcome" diff --git a/sandbox/pages/StatusSelectPage.qml b/sandbox/pages/StatusSelectPage.qml index fc48c0ea..5fa9ec77 100644 --- a/sandbox/pages/StatusSelectPage.qml +++ b/sandbox/pages/StatusSelectPage.qml @@ -41,7 +41,6 @@ Column { model: commmonModel selectMenu.delegate: StatusMenuItemDelegate { - statusPopupMenu: select action: StatusMenuItem { iconSettings.name: "filled-account" text: name diff --git a/src/StatusQ/Popups/StatusMenuItem.qml b/src/StatusQ/Popups/StatusMenuItem.qml index 5c4c1036..333885eb 100644 --- a/src/StatusQ/Popups/StatusMenuItem.qml +++ b/src/StatusQ/Popups/StatusMenuItem.qml @@ -9,19 +9,27 @@ Action { Normal, Danger } - icon.color: "transparent" + property int type: StatusMenuItem.Type.Normal property real iconRotation: 0 + + // TODO: Rename to "imageSettings" property StatusImageSettings image: 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 {} + + icon.color: "transparent" } diff --git a/src/StatusQ/Popups/StatusMenuItemDelegate.qml b/src/StatusQ/Popups/StatusMenuItemDelegate.qml index aa1428aa..79067c0c 100644 --- a/src/StatusQ/Popups/StatusMenuItemDelegate.qml +++ b/src/StatusQ/Popups/StatusMenuItemDelegate.qml @@ -7,140 +7,139 @@ import StatusQ.Components 0.1 import StatusQ.Popups 0.1 MenuItem { - id: statusPopupMenuItem + id: root implicitWidth: parent ? parent.width : 0 - implicitHeight: action.enabled ? 38 : 0 - objectName: action.objectName + implicitHeight: menu.hideDisabledItems && !enabled ? 0 : 38 + objectName: action ? action.objectName : "StatusMenuItemDelegate" - property int subMenuIndex - property var statusPopupMenu: null +// property int subMenuIndex +// property var statusPopupMenu: null - Component.onCompleted: { - if (!!subMenu) { - subMenuIndex = statusPopupMenu.menuItemCount - statusPopupMenu.menuItemCount += 1 - } - } + readonly property string logObjectName: "StatusMenuItemDelegate [%1, %2]".arg(this).arg(text) + +// Component.onCompleted: { +// 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 { - 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 { - id: indicatorComponent - 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 + id: indicatorIcon - if (!Qt.colorEqual(c, "transparent")) { - return c - } - switch (statusPopupMenuItem.action.type) { - case StatusMenuItem.Type.Danger: - return Theme.palette.dangerColor1 - default: - return Theme.palette.primaryColor1 - } - } + StatusIcon { + width: d.iconSettings.width // TODO: Also process action.icon.width? + height: d.iconSettings.height // TODO: Also process action.icon.height? + rotation: d.iconSettings.rotation // TODO: Also process action.icon.rotation? // !!root.action.iconRotation ? root.action.iconRotation : 0 + icon: d.iconSettings.name // TODO: Also process action.icon? + color: { + const c = d.iconSettings.color; + if (!Qt.colorEqual(c, "transparent")) + return c; + if (d.isDangerIcon) + return Theme.palette.dangerColor1; + return Theme.palette.primaryColor1; } } } Component { - id: statusLetterIdenticonCmp - Item { - implicitWidth: 24 - implicitHeight: 24 + id: indicatorLetterIdenticon - 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 - } + StatusLetterIdenticon { + width: d.imageSettings.width + height: d.imageSettings.height + color: d.iconSettings.color + name: root.text + letterSize: 11 } } Component { - id: statusRoundImageCmp + id: indicatorImage - 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 - } + StatusRoundedImage { + width: d.imageSettings.width + height: d.imageSettings.height + image.source: d.imageSettings.source + border.width: d.isSubMenu && d.imageSettings.isIdenticon ? 1 : 0 + border.color: Theme.palette.directColor7 } } - indicator: Loader { - sourceComponent: { - let subMenuItemIcon = statusPopupMenu.subMenuItemIcons && statusPopupMenu.subMenuItemIcons[parent.subMenuIndex] - - if ((parent.subMenu && subMenuItemIcon && subMenuItemIcon.source) || - statusPopupMenuItem.action.image && !!statusPopupMenuItem.action.image.source.toString()) { - return statusRoundImageCmp - } + indicator: Item { + implicitWidth: 24 + implicitHeight: 24 + Loader { + anchors.centerIn: parent + // sourceComponent: { + // if (!!d.imageSettings.source.toString()) + // return indicatorImage; + // if (d.iconSettings.isLetterIdenticon) + // return indicatorLetterIdenticon; + // return indicatorIcon; + // } - return (parent.subMenu && subMenuItemIcon && subMenuItemIcon.isLetterIdenticon) || - (statusPopupMenuItem.action.iconsSettings && statusPopupMenuItem.action.iconSettings.isLetterIdenticon) ? - statusLetterIdenticonCmp : indicatorComponent + // sourceComponent: indicatorIcon + // sourceComponent: indicatorLetterIdenticon + // 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 { - anchors.left: statusPopupMenuItem.indicator.right + anchors.left: root.indicator.right anchors.right: arrowIcon.visible ? arrowIcon.left : arrowIcon.right anchors.rightMargin: 8 anchors.leftMargin: 4 @@ -148,20 +147,13 @@ MenuItem { horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter - text: statusPopupMenuItem.text - color: { - switch (statusPopupMenuItem.action.type) { - case StatusMenuItem.Type.Danger: - return Theme.palette.dangerColor1 - 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 + text: root.text + color: d.isDangerIcon ? Theme.palette.dangerColor1 : Theme.palette.directColor1 + font.pixelSize: d.fontSettings.pixelSize // !!root.action.fontSettings ? root.action.fontSettings.pixelSize : 13 + font.bold: d.fontSettings.bold // !!root.action.fontSettings ? root.action.fontSettings.bold : false + font.italic: d.fontSettings.italic // !!root.action.fontSettings ? root.action.fontSettings.italic : false elide: Text.ElideRight - visible: statusPopupMenuItem.action.enabled + visible: true // hideDisabledItems ? root.enabled : true } arrow: StatusIcon { @@ -170,25 +162,25 @@ MenuItem { anchors.right: parent.right anchors.rightMargin: 8 height: 16 - visible: statusPopupMenuItem.subMenu + visible: d.isSubMenu icon: "next" color: Theme.palette.directColor1 } background: Rectangle { color: { - if (statusPopupMenuItem.hovered) { - return statusPopupMenuItem.action.type === StatusMenuItem.Type.Danger ? Theme.palette.dangerColor3 : Theme.palette.statusPopupMenu.hoverBackgroundColor - } - return "transparent" + if (!root.hovered) + return "transparent" + if (root.action.type === StatusMenuItem.Type.Danger) + return Theme.palette.dangerColor3; + return Theme.palette.statusPopupMenu.hoverBackgroundColor; } } MouseArea { - id: sensor anchors.fill: parent cursorShape: Qt.PointingHandCursor - hoverEnabled: statusPopupMenuItem.action.enabled + hoverEnabled: root.enabled // WARNING: use root.enabled ? onPressed: mouse.accepted = false } } diff --git a/src/StatusQ/Popups/StatusPopupMenu.qml b/src/StatusQ/Popups/StatusPopupMenu.qml index c0613a78..873940ef 100644 --- a/src/StatusQ/Popups/StatusPopupMenu.qml +++ b/src/StatusQ/Popups/StatusPopupMenu.qml @@ -10,20 +10,56 @@ import StatusQ.Popups 0.1 Menu { 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 topPadding: 8 bottomPadding: 8 - property int menuItemCount: 0 - property var subMenuItemIcons: [] +// property int menuItemCount: 0 +// 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 closeHandler - dim: false - signal menuItemClicked(int menuIndex) + dim: false + onOpened: { if (typeof openHandler === "function") { openHandler() @@ -37,7 +73,7 @@ Menu { } delegate: StatusMenuItemDelegate { - statusPopupMenu: root +// statusPopupMenu: root } background: Item { diff --git a/src/StatusQ/Popups/StatusSearchLocationMenu.qml b/src/StatusQ/Popups/StatusSearchLocationMenu.qml index 907be886..7407e93e 100644 --- a/src/StatusQ/Popups/StatusSearchLocationMenu.qml +++ b/src/StatusQ/Popups/StatusSearchLocationMenu.qml @@ -28,6 +28,8 @@ StatusPopupMenu { MenuItem { implicitHeight: 0.00001 } Instantiator { model: root.locationModel + + // NOTE: Use DelegateChooser here delegate: Loader { sourceComponent: (!!model.subItems && model.subItems.count > 0) ? subMenus : subMenuItemComponent onLoaded: { @@ -38,13 +40,20 @@ StatusPopupMenu { item.parentIconName = model.iconName; item.parentImageSource = model.imageSource; item.parentIdenticonColor = !!model.iconColor ? model.iconColor : Theme.palette.primaryColor1; - root.subMenuItemIcons.push({ - source: model.imageSource, - icon: model.iconName, - isIdenticon: model.isIdenticon, - color: model.iconColor, - isLetterIdenticon: !model.imageSource && !model.iconName - }); + + item.imageSettings.source = model.imageSource; + item.imageSettings.isIdenticon = model.isIdenticon; + item.iconSettings.name = model.iconName; + item.iconSettings.color = model.iconColor; + 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); } else { item.value = model.value