diff --git a/src/controls/Action.qml b/src/controls/Action.qml --- a/src/controls/Action.qml +++ b/src/controls/Action.qml @@ -18,108 +18,38 @@ */ import QtQuick 2.7 +import QtQuick.Controls 2.5 as Controls import "private" /** * An item that represents an abstract Action * - * @inherit QtObject + * @inherit QtQuick.Controls.Action */ -QtObject { +Controls.Action { id: root /** - * Emitted whenever a action's checked property changes. - * This usually happens at the same time as triggered. - * @param checked - */ - signal toggled(bool checked) - - /** - * Emitted when either the menu item or its bound action have been activated. Includes the object that triggered the event if relevant (e.g. a Button). - * You shouldn't need to emit this signal, use trigger() instead. - * @param source Object that triggered the event if relevant, often null - */ - signal triggered(QtObject source) - - /** - * visible: bool - * True (default) when the graphic representation of the action - * is supposed to be visible. - * It's up to the action representation to honor this property. - */ - property bool visible: true - - /** - * checkable: bool - * Whether action can be checked, or toggled. Defaults to false. - */ - property bool checkable: false - - /** - * checked: bool - * Whether the action is checked. Defaults to false. - */ - property bool checked: false - - /** - * enabled: bool - * Whether the action is enabled, and can be triggered. Defaults to true. - */ - property bool enabled: true - + * visible: bool + * True (default) when the graphic representation of the action + * is supposed to be visible. + * It's up to the action representation to honor this property. + */ + property bool visible: true + /** * iconName: string * Sets the icon name for the action. This will pick the icon with the given name from the current theme. */ - property alias iconName: iconGroup.name + property alias iconName: root.icon.name /** * iconSource: string * Sets the icon file or resource url for the action. Defaults to the empty URL. Use this if you want a specific file rather than an icon from the theme */ - property alias iconSource: iconGroup.source + property alias iconSource: root.icon.source - /** - * metadata for the icon, such as width/height.name and source - * * name This property holds the name of the icon to use. - * The icon will be loaded from the platform theme. - * If the icon is found in the theme, it will always be used; - * even if icon.source is also set. If the icon is not found, - * icon.source will be used instead. - * For more information on theme icons, see QIcon::fromTheme(). - * - * * source This property holds the name of the icon to use. - * The icon will be loaded as a regular image. - * If icon.name is set and refers to a valid theme icon, - * it will always be used instead of this property. - * - * * width This property holds the width of the icon. - * The icon's width will never exceed this value, - * though it will shrink when necessary. - * height This property holds the height of the icon. - * The icon's height will never exceed this value, - * though it will shrink when necessary. - * - * *color This property holds the color of the icon. - * The icon is tinted with the specified color, unless the color is set to "transparent". - */ - property ActionIconGroup icon: ActionIconGroup { - id: iconGroup - } - - /** - * shortcut : keysequence - * Shortcut bound to the action. The keysequence can be a string or a Qt standard key. - */ - property alias shortcut: shortcutItem.sequence - - /** - * Text for the action. This text will show as the button text, or as title in a menu item, depending from the way the developer will choose to represent it - */ - property string text - - /** + /** * A tooltip text to be shown when hovering the control bound to this action. Not all controls support tooltips on all platforms */ property string tooltip @@ -184,23 +114,4 @@ } return visible; } - - property Shortcut __shortcut: Shortcut { - property bool checked: false - id: shortcutItem - enabled: root.enabled - onActivated: root.trigger(); - } - function trigger(source) { - if (!enabled) { - return; - } - root.triggered(source); - if (root.checkable) { - root.checked = !root.checked; - root.toggled(root.checked); - } - } - - onCheckedChanged: root.toggled(root.checked); } diff --git a/src/controls/ActionToolBar.qml b/src/controls/ActionToolBar.qml --- a/src/controls/ActionToolBar.qml +++ b/src/controls/ActionToolBar.qml @@ -17,9 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import QtQuick 2.6 +import QtQuick 2.7 import QtQuick.Layouts 1.2 -import QtQuick.Controls 2.2 as Controls +import QtQuick.Controls 2.5 as Controls import org.kde.kirigami 2.5 as Kirigami import "private" @@ -116,7 +116,7 @@ enabled: opacity display: root.display - visible: modelData.visible + visible: !modelData.hasOwnProperty("visible") || modelData.visible Layout.fillWidth: false Layout.alignment: Qt.AlignVCenter Layout.minimumWidth: implicitWidth @@ -126,15 +126,16 @@ var index = actionsLayout.findIndex(actionsLayout.overflowSet, function(act) { return act === modelData}); - if ((opacity > 0 || !modelData.visible) && index > -1) { + if ((opacity > 0 || (modelData.hasOwnProperty("visible") || !modelData.visible)) && index > -1) { actionsLayout.overflowSet.splice(index, 1); - } else if (opacity === 0 && modelData.visible && index === -1) { + } else if (opacity === 0 && (!modelData.hasOwnProperty("visible") || modelData.visible) && index === -1) { actionsLayout.overflowSet.push(modelData); } actionsLayout.overflowSetChanged(); } Connections { target: modelData + ignoreUnknownSignals: !modelData.hasOwnProperty("visible") onVisibleChanged: actionDelegate.updateOverflowSet(); } Component.onCompleted: { @@ -175,12 +176,12 @@ Binding { target: parentItem property: "visible" - value: actionsLayout.findIndex(actionsLayout.overflowSet, function(act) {return act === parentAction}) > -1 && (parentAction.visible === undefined || parentAction.visible) + value: actionsLayout.findIndex(actionsLayout.overflowSet, function(act) {return act === parentAction}) > -1 && (parentAction.hasOwnProperty("visible") ? parentAction.visible === undefined || parentAction.visible : !parentAction.hasOwnProperty("visible")) } } } itemDelegate: ActionMenuItem { - visible: actionsLayout.findIndex(actionsLayout.overflowSet, function(act) {return act === ourAction}) > -1 && (ourAction.visible === undefined || ourAction.visible) + visible: actionsLayout.findIndex(actionsLayout.overflowSet, function(act) {return act === ourAction}) > -1 && ( ourAction.hasOwnProperty("visible") ? ourAction.visible === undefined || ourAction.visible : !ourAction.hasOwnProperty("visible")) } Instantiator { diff --git a/src/controls/private/ActionButton.qml b/src/controls/private/ActionButton.qml --- a/src/controls/private/ActionButton.qml +++ b/src/controls/private/ActionButton.qml @@ -42,7 +42,7 @@ readonly property Page page: root.parent.page //either Action or QAction should work here - function isActionAvailable(action) { return action && (action.visible === undefined || action.visible); } + function isActionAvailable(action) { return action && (action.hasOwnProperty("visible") ? action.visible === undefined || action.visible : !action.hasOwnProperty("visible")); } readonly property QtObject action: root.page && isActionAvailable(root.page.mainAction) ? root.page.mainAction : null readonly property QtObject leftAction: root.page && isActionAvailable(root.page.leftAction) ? root.page.leftAction : null @@ -181,7 +181,7 @@ actionUnderMouse.trigger(); } - if (actionUnderMouse.children.length > 0) { + if (actionUnderMouse.hasOwnProperty("children") && actionUnderMouse.children.length > 0) { var subMenuUnderMouse; switch (actionUnderMouse) { case leftAction: @@ -254,7 +254,7 @@ id: mainActionSubMenu y: -height x: -width/2 + parent.width/2 - actions: root.action ? root.action.children : "" + actions: root.action && root.action.hasOwnProperty("children") ? root.action.children : "" submenuComponent: Component { ActionsMenu {} } @@ -264,7 +264,7 @@ anchors.centerIn: parent width: Units.iconSizes.smallMedium height: width - source: root.action && root.action.iconName ? root.action.iconName : "" + source: root.action && root.action.icon.name ? root.action.icon.name : "" selected: true color: root.action && root.action.color && root.action.color.a > 0 ? root.action.color : (selected ? Theme.highlightedTextColor : Theme.textColor) } @@ -309,13 +309,13 @@ id: leftActionSubMenu y: -height x: -width/2 + parent.width/2 - actions: root.leftAction ? root.leftAction.children : "" + actions: root.leftAction && root.leftAction.hasOwnProperty("children") ? root.leftAction.children : "" submenuComponent: Component { ActionsMenu {} } } Icon { - source: root.leftAction && root.leftAction.iconName ? root.leftAction.iconName : "" + source: root.leftAction && root.leftAction.icon.name ? root.leftAction.icon.name : "" width: Units.iconSizes.smallMedium height: width selected: leftButtonGraphics.pressed @@ -355,13 +355,13 @@ id: rightActionSubMenu y: -height x: -width/2 + parent.width/2 - actions: root.rightAction ? root.rightAction.children : "" + actions: root.rightAction && root.rightAction.hasOwnProperty("children") ? root.rightAction.children : "" submenuComponent: Component { ActionsMenu {} } } Icon { - source: root.rightAction && root.rightAction.iconName ? root.rightAction.iconName : "" + source: root.rightAction && root.rightAction.icon.name ? root.rightAction.icon.name : "" width: Units.iconSizes.smallMedium height: width selected: rightButtonGraphics.pressed diff --git a/src/controls/private/ActionsMenu.qml b/src/controls/private/ActionsMenu.qml --- a/src/controls/private/ActionsMenu.qml +++ b/src/controls/private/ActionsMenu.qml @@ -53,7 +53,7 @@ property QtObject item: null function create() { - if (!action.children || action.children.length === 0) { + if (!action.hasOwnProperty("children") && !action.children || action.children.length === 0) { if (action.hasOwnProperty("separator") && action.separator) { item = theMenu.separatorDelegate.createObject(null, {}); } @@ -69,7 +69,7 @@ } } function remove() { - if (!action.children || action.children.length === 0) { + if (!action.hasOwnProperty("children") && !action.children || action.children.length === 0) { theMenu.removeItem(item) } else if (theMenu.submenuComponent) { theMenu.removeMenu(item) diff --git a/src/controls/private/GlobalDrawerActionItem.qml b/src/controls/private/GlobalDrawerActionItem.qml --- a/src/controls/private/GlobalDrawerActionItem.qml +++ b/src/controls/private/GlobalDrawerActionItem.qml @@ -45,7 +45,7 @@ MnemonicData.label: modelData.text property ActionsMenu actionsMenu: ActionsMenu { x: Qt.application.layoutDirection === Qt.RightToLeft ? -width : listItem.width - actions: modelData.children + actions: modelData.hasOwnProperty("children") ? modelData.children : null submenuComponent: Component { ActionsMenu {} } @@ -95,12 +95,12 @@ selected: listItem.checked || listItem.pressed Layout.preferredWidth: Layout.preferredHeight source: (LayoutMirroring.enabled ? "go-next-symbolic-rtl" : "go-next-symbolic") - visible: (!isExpandible || root.collapsed) && !listItem.isSeparator && modelData.children!==undefined && modelData.children.length > 0 + visible: (!isExpandible || root.collapsed) && !listItem.isSeparator && modelData.hasOwnProperty("children") && modelData.children!==undefined && modelData.children.length > 0 } data: [ QQC2.ToolTip { - visible: !listItem.isSeparator && (modelData.tooltip.length || root.collapsed) && (!actionsMenu || !actionsMenu.visible) && listItem.hovered && text.length > 0 - text: modelData.tooltip.length ? modelData.tooltip : modelData.text + visible: !listItem.isSeparator && (modelData.hasOwnProperty("tooltip") && modelData.tooltip.length || root.collapsed) && (!actionsMenu || !actionsMenu.visible) && listItem.hovered && text.length > 0 + text: modelData.hasOwnProperty("tooltip") && modelData.tooltip.length ? modelData.tooltip : modelData.text delay: Units.toolTipDelay timeout: 5000 y: listItem.height/2 - height/2 @@ -128,8 +128,8 @@ if (!supportsMouseEvents) { return; } - modelData.trigger(); - if (modelData.children!==undefined && modelData.children.length > 0) { + modelData.trigger(); + if (modelData.hasOwnProperty("children") && modelData.children!==undefined && modelData.children.length > 0) { if (root.collapsed) { //fallbacks needed for Qt 5.9 if ((!listItem.actionsMenu.hasOwnProperty("count") || listItem.actionsMenu.count>0) && !listItem.actionsMenu.visible) { diff --git a/src/controls/private/PrivateActionToolButton.qml b/src/controls/private/PrivateActionToolButton.qml --- a/src/controls/private/PrivateActionToolButton.qml +++ b/src/controls/private/PrivateActionToolButton.qml @@ -17,109 +17,110 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import QtQuick 2.6 +import QtQuick 2.7 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.2 as Controls import org.kde.kirigami 2.4 Controls.ToolButton { - id: control - - signal menuAboutToShow - - implicitWidth: menuArrow.visible || (showText && ( kirigamiAction ? kirigamiAction.text.length > 0 : text.length > 0)) - ? Math.max(layout.implicitWidth + Units.largeSpacing*2, background.implicitWidth) - : implicitHeight - implicitHeight: background.implicitHeight - - Theme.colorSet: Theme.Button - Theme.inherit: kirigamiAction && kirigamiAction.icon.color.a === 0 - Theme.backgroundColor: kirigamiAction && kirigamiAction.icon.color.a ? kirigamiAction.icon.color : undefined - Theme.textColor: kirigamiAction && !flat && kirigamiAction.icon.color.a ? Theme.highlightedTextColor : undefined - - hoverEnabled: true - flat: !control.kirigamiAction || !control.kirigamiAction.icon.color.a - //TODO: replace with upstream action when we depend on Qt 5.10 - property Action kirigamiAction - property bool showText: true - property bool showMenuArrow: true - property alias menu: menu - - //we need our own text delegate - text: "" - checkable: kirigamiAction && kirigamiAction.checkable - checked: (kirigamiAction && kirigamiAction.checked) || menu.visible - enabled: kirigamiAction && kirigamiAction.enabled - opacity: enabled ? 1 : 0.4 - visible: kirigamiAction && kirigamiAction.visible - onClicked: { - if (kirigamiAction) { - kirigamiAction.trigger(); - } - if (kirigamiAction.children.length > 0 && !menu.visible) { - control.menuAboutToShow(); - menu.popup(control, 0, control.height) - } - } - - ActionsMenu { - id: menu - y: control.height - actions: control.kirigamiAction ? control.kirigamiAction.children : null - submenuComponent: Component { - ActionsMenu {} - } - } - - contentItem: MouseArea { - hoverEnabled: true - onPressed: mouse.accepted = false - Theme.colorSet: checked && (control.kirigamiAction && control.kirigamiAction.icon.color.a) ? Theme.Selection : control.Theme.colorSet - Theme.inherit: control.kirigamiAction && Theme.colorSet != Theme.Selection && control.kirigamiAction.icon.color.a === 0 - GridLayout { - id: layout - columns: control.display == Controls.ToolButton.TextUnderIcon ? 1 : 2 + (menuArrow.visible ? 1 : 0) - rows: control.display == Controls.ToolButton.TextUnderIcon ? 2 : 1 - - anchors.centerIn: parent - Icon { - id: mainIcon - Layout.alignment: Qt.AlignCenter - Layout.minimumWidth: Units.iconSizes.smallMedium - Layout.minimumHeight: Units.iconSizes.smallMedium - source: control.kirigamiAction ? (control.kirigamiAction.icon ? control.kirigamiAction.icon.name : control.kirigamiAction.iconName) : "" - visible: control.kirigamiAction && control.kirigamiAction.iconName != "" && control.display != Controls.ToolButton.TextOnly - color: control.flat && control.kirigamiAction && control.kirigamiAction.icon && control.kirigamiAction.icon.color.a > 0 ? control.kirigamiAction.icon.color : label.color - } - Controls.Label { - id: label - MnemonicData.enabled: control.enabled - MnemonicData.controlType: MnemonicData.ActionElement - MnemonicData.label: control.kirigamiAction ? control.kirigamiAction.text : "" - - text: MnemonicData.richTextLabel - visible: control.showText && text.length > 0 && control.display != Controls.ToolButton.IconOnly - - Shortcut { - sequence: label.MnemonicData.sequence - onActivated: control.clicked() - } - } - Icon { - id: menuArrow - Layout.minimumWidth: Units.iconSizes.small - Layout.minimumHeight: Units.iconSizes.small - color: mainIcon.color - source: "arrow-down" - visible: showMenuArrow && menu.actions && menu.actions.length > 0 - } - } - } - Controls.ToolTip { - visible: control.hovered && text.length > 0 && !menu.visible && !control.pressed - text: kirigamiAction ? (kirigamiAction.tooltip.length ? kirigamiAction.tooltip : kirigamiAction.text) : "" - delay: Units.toolTipDelay - timeout: 5000 - y: control.height - } + id: control + + signal menuAboutToShow + + implicitWidth: menuArrow.visible || (showText && ( kirigamiAction ? kirigamiAction.text.length > 0 : text.length > 0)) + ? Math.max(layout.implicitWidth + Units.largeSpacing*2, background.implicitWidth) + : implicitHeight + implicitHeight: background.implicitHeight + + Theme.colorSet: Theme.Button + Theme.inherit: kirigamiAction && kirigamiAction.icon.color.a === 0 + Theme.backgroundColor: kirigamiAction && kirigamiAction.icon.color.a ? kirigamiAction.icon.color : undefined + Theme.textColor: kirigamiAction && !flat && kirigamiAction.icon.color.a ? Theme.highlightedTextColor : undefined + + hoverEnabled: true + flat: !control.kirigamiAction || !control.kirigamiAction.icon.color.a + //TODO: replace with upstream action when we depend on Qt 5.10 + //TODO: upstream action makes the style to re-draw the content, it'd be ideal except for the custom dropDown icon needed for actionsMenu + property QtObject kirigamiAction + property bool showText: true + property bool showMenuArrow: true + property alias menu: menu + + //we need our own text delegate + text: "" + checkable: kirigamiAction && kirigamiAction.checkable + checked: (kirigamiAction && kirigamiAction.checked) || menu.visible + enabled: kirigamiAction && kirigamiAction.enabled + opacity: enabled ? 1 : 0.4 + visible: kirigamiAction && kirigamiAction.visible + onClicked: { + if (kirigamiAction) { + kirigamiAction.trigger(); + } + if (kirigamiAction.hasOwnProperty("children") && kirigamiAction.children.length > 0 && !menu.visible) { + control.menuAboutToShow(); + menu.popup(control, 0, control.height) + } + } + + ActionsMenu { + id: menu + y: control.height + actions: control.kirigamiAction && kirigamiAction.hasOwnProperty("children") ? control.kirigamiAction.children : null + submenuComponent: Component { + ActionsMenu {} + } + } + + contentItem: MouseArea { + hoverEnabled: true + onPressed: mouse.accepted = false + Theme.colorSet: checked && (control.kirigamiAction && control.kirigamiAction.icon.color.a) ? Theme.Selection : control.Theme.colorSet + Theme.inherit: control.kirigamiAction && Theme.colorSet != Theme.Selection && control.kirigamiAction.icon.color.a === 0 + GridLayout { + id: layout + columns: control.display == Controls.ToolButton.TextUnderIcon ? 1 : 2 + (menuArrow.visible ? 1 : 0) + rows: control.display == Controls.ToolButton.TextUnderIcon ? 2 : 1 + + anchors.centerIn: parent + Icon { + id: mainIcon + Layout.alignment: Qt.AlignCenter + Layout.minimumWidth: Units.iconSizes.smallMedium + Layout.minimumHeight: Units.iconSizes.smallMedium + source: control.kirigamiAction ? (control.kirigamiAction.icon ? control.kirigamiAction.icon.name : control.kirigamiAction.iconName) : "" + visible: control.kirigamiAction && control.kirigamiAction.iconName != "" && control.display != Controls.ToolButton.TextOnly + color: control.flat && control.kirigamiAction && control.kirigamiAction.icon && control.kirigamiAction.icon.color.a > 0 ? control.kirigamiAction.icon.color : label.color + } + Controls.Label { + id: label + MnemonicData.enabled: control.enabled + MnemonicData.controlType: MnemonicData.ActionElement + MnemonicData.label: control.kirigamiAction ? control.kirigamiAction.text : "" + + text: MnemonicData.richTextLabel + visible: control.showText && text.length > 0 && control.display != Controls.ToolButton.IconOnly + + Shortcut { + sequence: label.MnemonicData.sequence + onActivated: control.clicked() + } + } + Icon { + id: menuArrow + Layout.minimumWidth: Units.iconSizes.small + Layout.minimumHeight: Units.iconSizes.small + color: mainIcon.color + source: "arrow-down" + visible: showMenuArrow && menu.actions && menu.actions.length > 0 + } + } + } + Controls.ToolTip { + visible: control.hovered && text.length > 0 && !menu.visible && !control.pressed + text: kirigamiAction ? (kirigamiAction.tooltip.length ? kirigamiAction.tooltip : kirigamiAction.text) : "" + delay: Units.toolTipDelay + timeout: 5000 + y: control.height + } } diff --git a/src/controls/private/globaltoolbar/ToolBarPageHeader.qml b/src/controls/private/globaltoolbar/ToolBarPageHeader.qml --- a/src/controls/private/globaltoolbar/ToolBarPageHeader.qml +++ b/src/controls/private/globaltoolbar/ToolBarPageHeader.qml @@ -109,7 +109,7 @@ children: page && page.actions.contextualActions ? page.actions.contextualActions : null } - kirigamiAction: page && page.actions.contextualActions.length === 1 ? page.actions.contextualActions[0] : overflowAction + action: page && page.actions.contextualActions.length === 1 ? page.actions.contextualActions[0] : overflowAction } }