Kirigami2

controls/templates/InlineMessage.qml
1/*
2 * SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org>
3 * SPDX-FileCopyrightText: 2022 ivan tkachenko <me@ratijas.tk>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8import QtQuick
9import QtQuick.Layouts
10import QtQuick.Controls as QQC2
11import QtQuick.Templates as T
12import org.kde.kirigami as Kirigami
13import org.kde.kirigami.templates.private as TP
14
15/**
16 * An inline message item with support for informational, positive,
17 * warning and error types, and with support for associated actions.
18 *
19 * InlineMessage can be used to give information to the user or
20 * interact with the user, without requiring the use of a dialog.
21 *
22 * The InlineMessage item is hidden by default. It also manages its
23 * height (and implicitHeight) during an animated reveal when shown.
24 * You should avoid setting height on an InlineMessage unless it is
25 * already visible.
26 *
27 * Optionally an icon can be set, defaulting to an icon appropriate
28 * to the message type otherwise.
29 *
30 * Optionally a close button can be shown.
31 *
32 * Actions are added from left to right. If more actions are set than
33 * can fit, an overflow menu is provided.
34 *
35 * Example:
36 * @code
37 * InlineMessage {
38 * type: Kirigami.MessageType.Error
39 *
40 * text: "My error message"
41 *
42 * actions: [
43 * Kirigami.Action {
44 * icon.name: "edit"
45 * text: "Action text"
46 * onTriggered: {
47 * // do stuff
48 * }
49 * },
50 * Kirigami.Action {
51 * icon.name: "edit"
52 * text: "Action text"
53 * onTriggered: {
54 * // do stuff
55 * }
56 * }
57 * ]
58 * }
59 * @endcode
60 *
61 * @since 5.45
62 * @inherit QtQuick.Templates.Control
63 */
64T.Control {
65 id: root
66
67 visible: false
68
69 /**
70 * Defines a position for the message: whether it's to be used as an inline component inside the page,
71 * a page header, or a page footer.
72 */
73 enum Position {
74 Inline,
75 Header,
76 Footer
77 }
78
79 /**
80 * Adjust the look of the message based upon the position.
81 * If a message is positioned in the header area or in the footer area
82 * of a page, it might be desirable to not have borders but just a line
83 * separating it from the content area. In this case, use the Header or
84 * Footer position.
85 * Default is InlineMessage.Position.Inline
86 */
87 property int position: InlineMessage.Position.Inline
88
89 /**
90 * This signal is emitted when a link is hovered in the message text.
91 * @param The hovered link.
92 */
93 signal linkHovered(string link)
94
95 /**
96 * This signal is emitted when a link is clicked or tapped in the message text.
97 * @param The clicked or tapped link.
98 */
99 signal linkActivated(string link)
101 /**
102 * This property holds the link embedded in the message text that the user is hovering over.
103 */
104 readonly property alias hoveredLink: label.hoveredLink
105
106 /**
107 * This property holds the message type. One of Information, Positive, Warning or Error.
108 *
109 * The default is Kirigami.MessageType.Information.
110 */
111 property int type: Kirigami.MessageType.Information
112
113 /**
114 * This grouped property holds the description of an optional icon.
115 *
116 * * source: The source of the icon, a freedesktop-compatible icon name is recommended.
117 * * color: An optional tint color for the icon.
118 *
119 * If no custom icon is set, an icon appropriate to the message type
120 * is shown.
121 */
122 property TP.IconPropertiesGroup icon: TP.IconPropertiesGroup {}
123
124 /**
125 * This property holds the message text.
126 */
127 property string text
128
129 /**
130 * This property holds whether the close button is displayed.
131 *
132 * The default is false.
133 */
134 property bool showCloseButton: false
135
136 /**
137 * This property holds the list of actions to show. Actions are added from left to
138 * right. If more actions are set than can fit, an overflow menu is
139 * provided.
140 */
141 property list<T.Action> actions
142
143 /**
144 * This property holds whether the current message item is animating.
145 */
146 readonly property bool animating: _animating
147
148 property bool _animating: false
149
150 implicitHeight: visible ? (contentLayout.implicitHeight + topPadding + bottomPadding) : 0
151
152 padding: Kirigami.Units.smallSpacing
153
154 Behavior on implicitHeight {
155 enabled: !root.visible
156
157 SequentialAnimation {
158 PropertyAction { targets: root; property: "_animating"; value: true }
159 NumberAnimation { duration: Kirigami.Units.longDuration }
160 }
161 }
162
163 onVisibleChanged: {
164 if (!visible) {
165 contentLayout.opacity = 0;
166 }
167 }
168
169 opacity: visible ? 1 : 0
170
171 Behavior on opacity {
172 enabled: !root.visible
173
174 NumberAnimation { duration: Kirigami.Units.shortDuration }
175 }
176
177 onOpacityChanged: {
178 if (opacity === 0) {
179 contentLayout.opacity = 0;
180 } else if (opacity === 1) {
181 contentLayout.opacity = 1;
182 }
183 }
184
185 onImplicitHeightChanged: {
186 height = implicitHeight;
187 }
188
189 contentItem: Item {
190 id: contentLayout
191
192 // Used to defer opacity animation until we know if InlineMessage was
193 // initialized visible.
194 property bool complete: false
195
196 Behavior on opacity {
197 enabled: root.visible && contentLayout.complete
198
199 SequentialAnimation {
200 NumberAnimation { duration: Kirigami.Units.shortDuration * 2 }
201 PropertyAction { targets: root; property: "_animating"; value: false }
202 }
203 }
204
205 implicitHeight: {
206 if (atBottom) {
207 return label.implicitHeight + actionsLayout.implicitHeight + actionsLayout.anchors.topMargin
208 } else {
209 return Math.max(icon.implicitHeight, label.implicitHeight, closeButton.implicitHeight, actionsLayout.implicitHeight)
210 }
211 }
212
213 readonly property real remainingWidth: width - (
214 icon.width
215 + label.anchors.leftMargin + label.implicitWidth + label.anchors.rightMargin
216 + (root.showCloseButton ? closeButton.width : 0)
217 )
218 readonly property bool multiline: remainingWidth <= 0 || atBottom
219
220 readonly property bool atBottom: (root.actions.length > 0) && (label.lineCount > 1 || actionsLayout.implicitWidth > remainingWidth)
221
222 Kirigami.Icon {
223 id: icon
224
225 width: Kirigami.Units.iconSizes.smallMedium
226 height: Kirigami.Units.iconSizes.smallMedium
227
228 anchors.left: parent.left
229
230 source: {
231 if (root.icon.name) {
232 return root.icon.name;
233 } else if (root.icon.source) {
234 return root.icon.source;
235 }
236
237 switch (root.type) {
238 case Kirigami.MessageType.Positive:
239 return "emblem-positive";
240 case Kirigami.MessageType.Warning:
241 return "emblem-warning";
242 case Kirigami.MessageType.Error:
243 return "emblem-error";
244 default:
245 return "emblem-information";
246 }
247 }
248
249 color: root.icon.color
250
251 states: [
252 State {
253 when: contentLayout.atBottom
254 AnchorChanges {
255 target: icon
256 anchors.top: contentLayout.top
257 }
258 },
259 // States are evaluated in the order they are declared.
260 // This is a fallback state.
261 State {
262 when: true
263 AnchorChanges {
264 target: icon
265 anchors.verticalCenter: contentLayout.verticalCenter
266 }
267 }
268 ]
269 }
270
271 Kirigami.SelectableLabel {
272 id: label
273
274 anchors {
275 left: icon.right
276 leftMargin: Kirigami.Units.smallSpacing
277 right: root.showCloseButton ? closeButton.left : parent.right
278 rightMargin: root.showCloseButton ? Kirigami.Units.smallSpacing : 0
279 top: parent.top
280 }
281
282 color: Kirigami.Theme.textColor
283 wrapMode: Text.WordWrap
284
285 text: root.text
286
287 verticalAlignment: Text.AlignVCenter
288
289 // QTBUG-117667 TextEdit (super-type of SelectableLabel) needs
290 // very specific state-management trick so it doesn't get stuck.
291 // State names serve purely as a description.
292 states: [
293 State {
294 name: "multi-line"
295 when: contentLayout.multiline
296 AnchorChanges {
297 target: label
298 anchors.bottom: undefined
299 }
300 PropertyChanges {
301 target: label
302 height: label.implicitHeight
303 }
304 },
305 // States are evaluated in the order they are declared.
306 // This is a fallback state.
307 State {
308 name: "single-line"
309 when: true
310 AnchorChanges {
311 target: label
312 anchors.bottom: label.parent.bottom
313 }
314 }
315 ]
316
317 onLinkHovered: link => root.linkHovered(link)
318 onLinkActivated: link => root.linkActivated(link)
319 }
320
321 Kirigami.ActionToolBar {
322 id: actionsLayout
323
324 flat: false
325 actions: root.actions
326 visible: root.actions.length > 0
327 alignment: Qt.AlignRight
328
329 anchors {
330 left: parent.left
331 top: contentLayout.atBottom ? label.bottom : parent.top
332 topMargin: contentLayout.atBottom ? Kirigami.Units.largeSpacing : 0
333 right: (!contentLayout.atBottom && root.showCloseButton) ? closeButton.left : parent.right
334 rightMargin: !contentLayout.atBottom && root.showCloseButton ? Kirigami.Units.smallSpacing : 0
335 }
336 }
337
338 QQC2.ToolButton {
339 id: closeButton
340
341 visible: root.showCloseButton
342
343 anchors.right: parent.right
344
345 // Incompatible anchors need to be evaluated in a given order,
346 // which simple declarative bindings cannot assure
347 states: [
348 State {
349 name: "onTop"
350 when: contentLayout.atBottom
351 AnchorChanges {
352 target: closeButton
353 anchors.top: parent.top
354 anchors.verticalCenter: undefined
355 }
356 } ,
357 State {
358 name: "centered"
359 AnchorChanges {
360 target: closeButton
361 anchors.top: undefined
362 anchors.verticalCenter: parent.verticalCenter
363 }
364 }
365 ]
366
367 height: contentLayout.atBottom ? implicitHeight : implicitHeight
368
369 icon.name: "dialog-close"
370
371 onClicked: root.visible = false
372 }
373
374 Component.onCompleted: complete = true
375 }
376}
QVariant source
KIOCORE_EXPORT CopyJob * link(const QList< QUrl > &src, const QUrl &destDir, JobFlags flags=DefaultFlags)
QString label(StandardShortcut id)
QString name(StandardShortcut id)
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Apr 27 2024 22:13:10 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.