diff --git a/src/controls/InlineMessage.qml b/src/controls/InlineMessage.qml index 4da6e543..2b3afe66 100644 --- a/src/controls/InlineMessage.qml +++ b/src/controls/InlineMessage.qml @@ -1,300 +1,118 @@ /* * Copyright 2018 Eike Hein * Copyright 2018 Marco Martin * Copyright 2018 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.7 -import QtGraphicalEffects 1.0 -import QtQuick.Layouts 1.0 -import QtQuick.Controls 2.0 as Controls import org.kde.kirigami 2.5 as Kirigami import "private" import "templates" as T /** * An inline message item with support for informational, positive, * warning and error types, and with support for associated actions. * * InlineMessage can be used to give information to the user or * interact with the user, without requiring the use of a dialog. * * The InlineMessage item is hidden by default. It also manages its * height (and implicitHeight) during an animated reveal when shown. * You should avoid setting height on an InlineMessage unless it is * already visible. * * Optionally an icon can be set, defaulting to an icon appropriate * to the message type otherwise. * * Optionally a close button can be shown. * * Actions are added from left to right. If more actions are set than * can fit, an overflow menu is provided. * * Example: * @code * InlineMessage { * type: Kirigami.MessageType.Error * * text: "My error message" * * actions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * } * @endcode * * @since 5.45 */ T.InlineMessage { id: root - implicitHeight: visible ? contentLayout.implicitHeight + (2 * (background.border.width + Kirigami.Units.smallSpacing)) : 0 - - property bool _animating: false - - leftPadding: background.border.width + Kirigami.Units.smallSpacing - topPadding: background.border.width + Kirigami.Units.smallSpacing - rightPadding: background.border.width + Kirigami.Units.smallSpacing - bottomPadding: background.border.width + Kirigami.Units.smallSpacing - - Behavior on implicitHeight { - enabled: !root.visible - - SequentialAnimation { - PropertyAction { targets: root; property: "_animating"; value: true } - NumberAnimation { duration: Kirigami.Units.longDuration } - } - } - - onVisibleChanged: { - if (!visible) { - contentLayout.opacity = 0.0; - } - } - - opacity: visible ? 1.0 : 0.0 - - Behavior on opacity { - enabled: !root.visible - - NumberAnimation { duration: Kirigami.Units.shortDuration } - } - - onOpacityChanged: { - if (opacity == 0.0) { - contentLayout.opacity = 0.0; - } else if (opacity == 1.0) { - contentLayout.opacity = 1.0; - } - } - - onImplicitHeightChanged: { - height = implicitHeight; - } - background: Rectangle { id: bgBorderRect color: { if (root.type == Kirigami.MessageType.Positive) { return Kirigami.Theme.positiveTextColor; } else if (root.type == Kirigami.MessageType.Warning) { return Kirigami.Theme.neutralTextColor; } else if (root.type == Kirigami.MessageType.Error) { return Kirigami.Theme.negativeTextColor; } return Kirigami.Theme.activeTextColor; } radius: Kirigami.Units.smallSpacing / 2 Rectangle { id: bgFillRect anchors.fill: parent anchors.margins: Kirigami.Units.devicePixelRatio color: Kirigami.Theme.backgroundColor radius: bgBorderRect.radius * 0.60 } Rectangle { anchors.fill: bgFillRect color: bgBorderRect.color opacity: 0.20 radius: bgFillRect.radius } - - layer.enabled: true - layer.effect: DropShadow { - horizontalOffset: 0 - verticalOffset: 1 - radius: 12 - samples: 32 - color: Qt.rgba(0, 0, 0, 0.5) - } - } - - contentItem: GridLayout { - id: contentLayout - - // Used to defer opacity animation until we know if InlineMessage was - // initialized visible. - property bool complete: false - - Behavior on opacity { - enabled: root.visible && contentLayout.complete - - SequentialAnimation { - NumberAnimation { duration: Kirigami.Units.shortDuration * 2 } - PropertyAction { targets: root; property: "_animating"; value: false } - } - } - - rowSpacing: Kirigami.Units.largeSpacing - columnSpacing: Kirigami.Units.smallSpacing - - Kirigami.Icon { - id: icon - - width: Kirigami.Units.iconSizes.smallMedium - height: width - - Layout.alignment: text.lineCount > 1 ? Qt.AlignTop : Qt.AlignVCenter - - Layout.minimumWidth: width - Layout.minimumHeight: height - - source: { - if (root.icon.source) { - return root.icon.source; - } - - if (root.type == Kirigami.MessageType.Positive) { - return "dialog-positive"; - } else if (root.type == Kirigami.MessageType.Warning) { - return "dialog-warning"; - } else if (root.type == Kirigami.MessageType.Error) { - return "dialog-error"; - } - - return "dialog-information"; - } - - color: root.icon.color - } - - MouseArea { - implicitHeight: text.implicitHeight - - Layout.fillWidth: true - Layout.alignment: text.lineCount > 1 ? Qt.AlignTop : Qt.AlignVCenter - Layout.row: 0 - Layout.column: 1 - - cursorShape: text.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor - - Controls.Label { - id: text - - width: parent.width - - color: Kirigami.Theme.textColor - wrapMode: Text.WordWrap - elide: Text.ElideRight - - text: root.text - - onLinkHovered: root.linkHovered(link) - onLinkActivated: root.linkActivated(link) - } - //this must be child of an item which doesn't try to resize it - TextMetrics { - id: messageTextMetrics - - font: text.font - text: text.text - } - } - - Kirigami.ActionToolBar { - id: actionsLayout - - flat: false - actions: root.actions - visible: root.actions.length - - Layout.alignment: Qt.AlignRight - - Layout.row: { - if (messageTextMetrics.width + Kirigami.Units.smallSpacing > - (contentLayout.width - icon.width - actionsLayout.width - - closeButton.width - (3 * contentLayout.columnSpacing))) { - return 1; - } - return 0; - } - Layout.column: Layout.row ? 0 : 2 - Layout.columnSpan: Layout.row ? (closeButton.visible ? 3 : 2) : 1 - } - - Controls.ToolButton { - id: closeButton - - visible: root.showCloseButton - - Layout.alignment: text.lineCount > 1 || actionsLayout.Layout.row ? Qt.AlignTop : Qt.AlignVCenter - Layout.row: 0 - Layout.column: actionsLayout.Layout.row ? 2 : 3 - - //TODO: use toolbuttons icons when we can depend from Qt 5.10 - Kirigami.Icon { - anchors.centerIn: parent - source: "dialog-close" - width: Kirigami.Units.iconSizes.smallMedium - height: width - } - - onClicked: root.visible = false - } - - Component.onCompleted: complete = true } } diff --git a/src/controls/templates/InlineMessage.qml b/src/controls/templates/InlineMessage.qml index cec0bbd8..f642536e 100644 --- a/src/controls/templates/InlineMessage.qml +++ b/src/controls/templates/InlineMessage.qml @@ -1,135 +1,306 @@ /* * Copyright 2018 Eike Hein * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.7 import QtQuick.Templates 2.0 as T2 -import org.kde.kirigami 2.4 as Kirigami +import QtQuick.Controls 2.0 as Controls +import QtQuick.Layouts 1.0 +import org.kde.kirigami 2.5 as Kirigami import "private" /** * An inline message item with support for informational, positive, * warning and error types, and with support for associated actions. * * InlineMessage can be used to give information to the user or * interact with the user, without requiring the use of a dialog. * * The InlineMessage item is hidden by default. It also manages its * height (and implicitHeight) during an animated reveal when shown. * You should avoid setting height on an InlineMessage unless it is * already visible. * * Optionally an icon can be set, defaulting to an icon appropriate * to the message type otherwise. * * Optionally a close button can be shown. * * Actions are added from left to right. If more actions are set than * can fit, an overflow menu is provided. * * Example: * @code * InlineMessage { * type: Kirigami.MessageType.Error * * text: "My error message" * * actions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * } * @endcode * * @since 5.45 */ T2.Control { id: root visible: false /** * Emitted when a link is hovered in the message text. * @param The hovered link. */ signal linkHovered(string link) /** * Emitted when a link is clicked or tapped in the message text. * @param The clicked or tapped link. */ signal linkActivated(string link) /** * type: int * The message type. One of Information, Positive, Warning or Error. * * The default is Kirigami.MessageType.Information. */ property int type: Kirigami.MessageType.Information /** * A grouped property describing an optional icon. * * source: The source of the icon, a freedesktop-compatible icon name is recommended. * * color: An optional tint color for the icon. * * If no custom icon is set, an icon appropriate to the message type * is shown. */ property IconPropertiesGroup icon: IconPropertiesGroup {} /** * text: string * The message text. */ property string text /** * showCloseButton: bool * When enabled, a close button is shown. * The default is false. */ property bool showCloseButton: false /** * actions: list * The list of actions to show. Actions are added from left to * right. If more actions are set than can fit, an overflow menu is * provided. */ property list actions /** * animating: bool * True while the message item is animating. */ readonly property bool animating: hasOwnProperty("_animating") && _animating + + implicitHeight: visible ? contentLayout.implicitHeight + (2 * (background.border.width + Kirigami.Units.smallSpacing)) : 0 + + property bool _animating: false + + leftPadding: background.border.width + Kirigami.Units.smallSpacing + topPadding: background.border.width + Kirigami.Units.smallSpacing + rightPadding: background.border.width + Kirigami.Units.smallSpacing + bottomPadding: background.border.width + Kirigami.Units.smallSpacing + + Behavior on implicitHeight { + enabled: !root.visible + + SequentialAnimation { + PropertyAction { targets: root; property: "_animating"; value: true } + NumberAnimation { duration: Kirigami.Units.longDuration } + } + } + + onVisibleChanged: { + if (!visible) { + contentLayout.opacity = 0.0; + } + } + + opacity: visible ? 1.0 : 0.0 + + Behavior on opacity { + enabled: !root.visible + + NumberAnimation { duration: Kirigami.Units.shortDuration } + } + + onOpacityChanged: { + if (opacity == 0.0) { + contentLayout.opacity = 0.0; + } else if (opacity == 1.0) { + contentLayout.opacity = 1.0; + } + } + + onImplicitHeightChanged: { + height = implicitHeight; + } + contentItem: GridLayout { + id: contentLayout + + // Used to defer opacity animation until we know if InlineMessage was + // initialized visible. + property bool complete: false + + Behavior on opacity { + enabled: root.visible && contentLayout.complete + + SequentialAnimation { + NumberAnimation { duration: Kirigami.Units.shortDuration * 2 } + PropertyAction { targets: root; property: "_animating"; value: false } + } + } + + rowSpacing: Kirigami.Units.largeSpacing + columnSpacing: Kirigami.Units.smallSpacing + + Kirigami.Icon { + id: icon + + width: Kirigami.Units.iconSizes.smallMedium + height: width + + Layout.alignment: text.lineCount > 1 ? Qt.AlignTop : Qt.AlignVCenter + + Layout.minimumWidth: width + Layout.minimumHeight: height + + source: { + if (root.icon.source) { + return root.icon.source; + } + + if (root.type == Kirigami.MessageType.Positive) { + return "dialog-positive"; + } else if (root.type == Kirigami.MessageType.Warning) { + return "dialog-warning"; + } else if (root.type == Kirigami.MessageType.Error) { + return "dialog-error"; + } + + return "dialog-information"; + } + + color: root.icon.color + } + + MouseArea { + implicitHeight: text.implicitHeight + + Layout.fillWidth: true + Layout.alignment: text.lineCount > 1 ? Qt.AlignTop : Qt.AlignVCenter + Layout.row: 0 + Layout.column: 1 + + cursorShape: text.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + + Controls.Label { + id: text + + width: parent.width + + color: Kirigami.Theme.textColor + wrapMode: Text.WordWrap + elide: Text.ElideRight + + text: root.text + + onLinkHovered: root.linkHovered(link) + onLinkActivated: root.linkActivated(link) + } + //this must be child of an item which doesn't try to resize it + TextMetrics { + id: messageTextMetrics + + font: text.font + text: text.text + } + } + + Kirigami.ActionToolBar { + id: actionsLayout + + flat: false + actions: root.actions + visible: root.actions.length + + Layout.alignment: Qt.AlignRight + + Layout.row: { + if (messageTextMetrics.width + Kirigami.Units.smallSpacing > + (contentLayout.width - icon.width - actionsLayout.width + - closeButton.width - (3 * contentLayout.columnSpacing))) { + return 1; + } + return 0; + } + Layout.column: Layout.row ? 0 : 2 + Layout.columnSpan: Layout.row ? (closeButton.visible ? 3 : 2) : 1 + } + + Controls.ToolButton { + id: closeButton + + visible: root.showCloseButton + + Layout.alignment: text.lineCount > 1 || actionsLayout.Layout.row ? Qt.AlignTop : Qt.AlignVCenter + Layout.row: 0 + Layout.column: actionsLayout.Layout.row ? 2 : 3 + + //TODO: use toolbuttons icons when we can depend from Qt 5.10 + Kirigami.Icon { + anchors.centerIn: parent + source: "dialog-close" + width: Kirigami.Units.iconSizes.smallMedium + height: width + } + + onClicked: root.visible = false + } + + Component.onCompleted: complete = true + } } diff --git a/src/controls/templates/InlineMessage.qml b/src/styles/Material/InlineMessage.qml similarity index 56% copy from src/controls/templates/InlineMessage.qml copy to src/styles/Material/InlineMessage.qml index cec0bbd8..a4b9eab1 100644 --- a/src/controls/templates/InlineMessage.qml +++ b/src/styles/Material/InlineMessage.qml @@ -1,135 +1,128 @@ /* * Copyright 2018 Eike Hein + * Copyright 2018 Marco Martin + * Copyright 2018 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.7 -import QtQuick.Templates 2.0 as T2 -import org.kde.kirigami 2.4 as Kirigami +import QtGraphicalEffects 1.0 +import org.kde.kirigami 2.5 as Kirigami import "private" +import "templates" as T + /** * An inline message item with support for informational, positive, * warning and error types, and with support for associated actions. * * InlineMessage can be used to give information to the user or * interact with the user, without requiring the use of a dialog. * * The InlineMessage item is hidden by default. It also manages its * height (and implicitHeight) during an animated reveal when shown. * You should avoid setting height on an InlineMessage unless it is * already visible. * * Optionally an icon can be set, defaulting to an icon appropriate * to the message type otherwise. * * Optionally a close button can be shown. * * Actions are added from left to right. If more actions are set than * can fit, an overflow menu is provided. * * Example: * @code * InlineMessage { * type: Kirigami.MessageType.Error * * text: "My error message" * * actions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * } * @endcode * * @since 5.45 */ -T2.Control { +T.InlineMessage { id: root - visible: false - - /** - * Emitted when a link is hovered in the message text. - * @param The hovered link. - */ - signal linkHovered(string link) - - /** - * Emitted when a link is clicked or tapped in the message text. - * @param The clicked or tapped link. - */ - signal linkActivated(string link) - - /** - * type: int - * The message type. One of Information, Positive, Warning or Error. - * - * The default is Kirigami.MessageType.Information. - */ - property int type: Kirigami.MessageType.Information - - /** - * A grouped property describing an optional icon. - * * source: The source of the icon, a freedesktop-compatible icon name is recommended. - * * color: An optional tint color for the icon. - * - * If no custom icon is set, an icon appropriate to the message type - * is shown. - */ - property IconPropertiesGroup icon: IconPropertiesGroup {} - - /** - * text: string - * The message text. - */ - property string text - - /** - * showCloseButton: bool - * When enabled, a close button is shown. - * The default is false. - */ - property bool showCloseButton: false - - /** - * actions: list - * The list of actions to show. Actions are added from left to - * right. If more actions are set than can fit, an overflow menu is - * provided. - */ - property list actions - - /** - * animating: bool - * True while the message item is animating. - */ - readonly property bool animating: hasOwnProperty("_animating") && _animating + background: Rectangle { + id: bgBorderRect + + color: { + if (root.type == Kirigami.MessageType.Positive) { + return Kirigami.Theme.positiveTextColor; + } else if (root.type == Kirigami.MessageType.Warning) { + return Kirigami.Theme.neutralTextColor; + } else if (root.type == Kirigami.MessageType.Error) { + return Kirigami.Theme.negativeTextColor; + } + + return Kirigami.Theme.activeTextColor; + } + + radius: Kirigami.Units.smallSpacing / 2 + + Rectangle { + id: bgFillRect + + anchors.fill: parent + anchors.margins: Kirigami.Units.devicePixelRatio + + color: Kirigami.Theme.backgroundColor + + radius: bgBorderRect.radius * 0.60 + } + + Rectangle { + anchors.fill: bgFillRect + + color: bgBorderRect.color + + opacity: 0.20 + + radius: bgFillRect.radius + } + + layer.enabled: true + layer.effect: DropShadow { + horizontalOffset: 0 + verticalOffset: 1 + radius: 12 + samples: 32 + color: Qt.rgba(0, 0, 0, 0.5) + } + } }