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

KDE's Doxygen guidelines are available online.