Warning, /frameworks/kirigami/src/controls/templates/InlineMessage.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *  SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
0003  *  SPDX-FileCopyrightText: 2022 ivan tkachenko <me@ratijas.tk>
0004  *
0005  *  SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 import QtQuick
0009 import QtQuick.Layouts
0010 import QtQuick.Controls as QQC2
0011 import QtQuick.Templates as T
0012 import org.kde.kirigami as Kirigami
0013 import org.kde.kirigami.templates.private as TP
0014 
0015 /**
0016  * An inline message item with support for informational, positive,
0017  * warning and error types, and with support for associated actions.
0018  *
0019  * InlineMessage can be used to give information to the user or
0020  * interact with the user, without requiring the use of a dialog.
0021  *
0022  * The InlineMessage item is hidden by default. It also manages its
0023  * height (and implicitHeight) during an animated reveal when shown.
0024  * You should avoid setting height on an InlineMessage unless it is
0025  * already visible.
0026  *
0027  * Optionally an icon can be set, defaulting to an icon appropriate
0028  * to the message type otherwise.
0029  *
0030  * Optionally a close button can be shown.
0031  *
0032  * Actions are added from left to right. If more actions are set than
0033  * can fit, an overflow menu is provided.
0034  *
0035  * Example:
0036  * @code
0037  * InlineMessage {
0038  *     type: Kirigami.MessageType.Error
0039  *
0040  *     text: "My error message"
0041  *
0042  *     actions: [
0043  *         Kirigami.Action {
0044  *             icon.name: "edit"
0045  *             text: "Action text"
0046  *             onTriggered: {
0047  *                 // do stuff
0048  *             }
0049  *         },
0050  *         Kirigami.Action {
0051  *             icon.name: "edit"
0052  *             text: "Action text"
0053  *             onTriggered: {
0054  *                 // do stuff
0055  *             }
0056  *         }
0057  *     ]
0058  * }
0059  * @endcode
0060  *
0061  * @since 5.45
0062  * @inherit QtQuick.Templates.Control
0063  */
0064 T.Control {
0065     id: root
0066 
0067     visible: false
0068 
0069     /**
0070      * This signal is emitted when a link is hovered in the message text.
0071      * @param The hovered link.
0072      */
0073     signal linkHovered(string link)
0074 
0075     /**
0076      * This signal is emitted when a link is clicked or tapped in the message text.
0077      * @param The clicked or tapped link.
0078      */
0079     signal linkActivated(string link)
0080 
0081     /**
0082      * This property holds the link embedded in the message text that the user is hovering over.
0083      */
0084     readonly property alias hoveredLink: label.hoveredLink
0085 
0086     /**
0087      * This property holds the message type. One of Information, Positive, Warning or Error.
0088      *
0089      * The default is Kirigami.MessageType.Information.
0090      */
0091     property int type: Kirigami.MessageType.Information
0092 
0093     /**
0094      * This grouped property holds the description of an optional icon.
0095      *
0096      * * source: The source of the icon, a freedesktop-compatible icon name is recommended.
0097      * * color: An optional tint color for the icon.
0098      *
0099      * If no custom icon is set, an icon appropriate to the message type
0100      * is shown.
0101      */
0102     property TP.IconPropertiesGroup icon: TP.IconPropertiesGroup {}
0103 
0104     /**
0105      * This property holds the message text.
0106      */
0107     property string text
0108 
0109     /**
0110      * This property holds whether the close button is displayed.
0111      *
0112      * The default is false.
0113      */
0114     property bool showCloseButton: false
0115 
0116     /**
0117      * This property holds the list of actions to show. Actions are added from left to
0118      * right. If more actions are set than can fit, an overflow menu is
0119      * provided.
0120      */
0121     property list<T.Action> actions
0122 
0123     /**
0124      * This property holds whether the current message item is animating.
0125      */
0126     readonly property bool animating: _animating
0127 
0128     property bool _animating: false
0129 
0130     implicitHeight: visible ? (contentLayout.implicitHeight + topPadding + bottomPadding) : 0
0131 
0132     padding: Kirigami.Units.smallSpacing
0133 
0134     Behavior on implicitHeight {
0135         enabled: !root.visible
0136 
0137         SequentialAnimation {
0138             PropertyAction { targets: root; property: "_animating"; value: true }
0139             NumberAnimation { duration: Kirigami.Units.longDuration }
0140         }
0141     }
0142 
0143     onVisibleChanged: {
0144         if (!visible) {
0145             contentLayout.opacity = 0;
0146         }
0147     }
0148 
0149     opacity: visible ? 1 : 0
0150 
0151     Behavior on opacity {
0152         enabled: !root.visible
0153 
0154         NumberAnimation { duration: Kirigami.Units.shortDuration }
0155     }
0156 
0157     onOpacityChanged: {
0158         if (opacity === 0) {
0159             contentLayout.opacity = 0;
0160         } else if (opacity === 1) {
0161             contentLayout.opacity = 1;
0162         }
0163     }
0164 
0165     onImplicitHeightChanged: {
0166         height = implicitHeight;
0167     }
0168 
0169     contentItem: Item {
0170         id: contentLayout
0171 
0172         // Used to defer opacity animation until we know if InlineMessage was
0173         // initialized visible.
0174         property bool complete: false
0175 
0176         Behavior on opacity {
0177             enabled: root.visible && contentLayout.complete
0178 
0179             SequentialAnimation {
0180                 NumberAnimation { duration: Kirigami.Units.shortDuration * 2 }
0181                 PropertyAction { targets: root; property: "_animating"; value: false }
0182             }
0183         }
0184 
0185         implicitHeight: {
0186             if (atBottom) {
0187                 return label.implicitHeight + actionsLayout.implicitHeight + actionsLayout.anchors.topMargin
0188             } else {
0189                 return Math.max(icon.implicitHeight, label.implicitHeight, closeButton.implicitHeight, actionsLayout.implicitHeight)
0190             }
0191         }
0192 
0193         readonly property real remainingWidth: width - (
0194             icon.width
0195             + label.anchors.leftMargin + label.implicitWidth + label.anchors.rightMargin
0196             + (root.showCloseButton ? closeButton.width : 0)
0197         )
0198         readonly property bool multiline: remainingWidth <= 0 || atBottom
0199 
0200         readonly property bool atBottom: (root.actions.length > 0) && (label.lineCount > 1 || actionsLayout.implicitWidth > remainingWidth)
0201 
0202         Kirigami.Icon {
0203             id: icon
0204 
0205             width: Kirigami.Units.iconSizes.smallMedium
0206             height: Kirigami.Units.iconSizes.smallMedium
0207 
0208             anchors.left: parent.left
0209 
0210             source: {
0211                 if (root.icon.name) {
0212                     return root.icon.name;
0213                 } else if (root.icon.source) {
0214                     return root.icon.source;
0215                 }
0216 
0217                 switch (root.type) {
0218                 case Kirigami.MessageType.Positive:
0219                     return "emblem-positive";
0220                 case Kirigami.MessageType.Warning:
0221                     return "emblem-warning";
0222                 case Kirigami.MessageType.Error:
0223                     return "emblem-error";
0224                 default:
0225                     return "emblem-information";
0226                 }
0227             }
0228 
0229             color: root.icon.color
0230 
0231             states: [
0232                 State {
0233                     when: contentLayout.atBottom
0234                     AnchorChanges {
0235                         target: icon
0236                         anchors.top: contentLayout.top
0237                     }
0238                 },
0239                 // States are evaluated in the order they are declared.
0240                 // This is a fallback state.
0241                 State {
0242                     when: true
0243                     AnchorChanges {
0244                         target: icon
0245                         anchors.verticalCenter: contentLayout.verticalCenter
0246                     }
0247                 }
0248             ]
0249         }
0250 
0251         Kirigami.SelectableLabel {
0252             id: label
0253 
0254             anchors {
0255                 left: icon.right
0256                 leftMargin: Kirigami.Units.smallSpacing
0257                 right: root.showCloseButton ? closeButton.left : parent.right
0258                 rightMargin: root.showCloseButton ? Kirigami.Units.smallSpacing : 0
0259                 top: parent.top
0260             }
0261 
0262             color: Kirigami.Theme.textColor
0263             wrapMode: Text.WordWrap
0264 
0265             text: root.text
0266 
0267             verticalAlignment: Text.AlignVCenter
0268 
0269             // QTBUG-117667 TextEdit (super-type of SelectableLabel) needs
0270             // very specific state-management trick so it doesn't get stuck.
0271             // State names serve purely as a description.
0272             states: [
0273                 State {
0274                     name: "multi-line"
0275                     when: contentLayout.multiline
0276                     AnchorChanges {
0277                         target: label
0278                         anchors.bottom: undefined
0279                     }
0280                     PropertyChanges {
0281                         target: label
0282                         height: label.implicitHeight
0283                     }
0284                 },
0285                 // States are evaluated in the order they are declared.
0286                 // This is a fallback state.
0287                 State {
0288                     name: "single-line"
0289                     when: true
0290                     AnchorChanges {
0291                         target: label
0292                         anchors.bottom: label.parent.bottom
0293                     }
0294                 }
0295             ]
0296 
0297             onLinkHovered: link => root.linkHovered(link)
0298             onLinkActivated: link => root.linkActivated(link)
0299         }
0300 
0301         Kirigami.ActionToolBar {
0302             id: actionsLayout
0303 
0304             flat: false
0305             actions: root.actions
0306             visible: root.actions.length > 0
0307             alignment: Qt.AlignRight
0308 
0309             anchors {
0310                 left: parent.left
0311                 top: contentLayout.atBottom ? label.bottom : parent.top
0312                 topMargin: contentLayout.atBottom ? Kirigami.Units.largeSpacing : 0
0313                 right: (!contentLayout.atBottom && root.showCloseButton) ? closeButton.left : parent.right
0314                 rightMargin: !contentLayout.atBottom && root.showCloseButton ? Kirigami.Units.smallSpacing : 0
0315             }
0316         }
0317 
0318         QQC2.ToolButton {
0319             id: closeButton
0320 
0321             visible: root.showCloseButton
0322 
0323             anchors {
0324                 right: parent.right
0325                 top: contentLayout.atBottom ? parent.top : undefined
0326                 verticalCenter: contentLayout.atBottom ? undefined : parent.verticalCenter
0327             }
0328 
0329             height: contentLayout.atBottom ? implicitHeight : implicitHeight
0330 
0331             icon.name: "dialog-close"
0332 
0333             onClicked: root.visible = false
0334         }
0335 
0336         Component.onCompleted: complete = true
0337     }
0338 }