Kirigami-addons

AboutPage.qml
1// SPDX-FileCopyrightText: 2018 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
2// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
3// SPDX-License-Identifier: LGPL-2.0-or-later
4
5import QtQuick
6import QtQuick.Controls as QQC2
7import QtQuick.Window
8import QtQuick.Layouts
9import org.kde.kirigami as Kirigami
10import org.kde.kirigamiaddons.components as KirigamiComponents
11import org.kde.kirigamiaddons.formcard as FormCardModule
12import org.kde.coreaddons as Core
13
14import "private" as Private
15
16/**
17 * @brief An AboutPage that displays the about data using Form components.
18 *
19 * This component consists of an internationalized "About" page with the
20 * metadata of your program.
21 *
22 * It allows to show the copyright notice of the application together with
23 * the contributors and some information of which platform it's running on.
24 *
25 * @since KirigamiAddons 0.11.0
26 * @inherit org:kde::kirigami::ScrollablePage
27 */
29 id: page
30
31 /**
32 * @brief This property holds an object with the same shape as KAboutData.
33 *
34 * Set this property to either a KAboutData instance exposed from C++, or directly via a JSON object.
35 *
36 * Example usage:
37 * @code{json}
38 * aboutData: {
39 "displayName" : "KirigamiApp",
40 "productName" : "kirigami/app",
41 "componentName" : "kirigamiapp",
42 "shortDescription" : "A Kirigami example",
43 "homepage" : "",
44 "bugAddress" : "submit@bugs.kde.org",
45 "version" : "5.14.80",
46 "otherText" : "",
47 "authors" : [
48 {
49 "name" : "...",
50 "task" : "...",
51 "emailAddress" : "somebody@kde.org",
52 "webAddress" : "",
53 "ocsUsername" : ""
54 }
55 ],
56 "credits" : [],
57 "translators" : [],
58 "licenses" : [
59 {
60 "name" : "GPL v2",
61 "text" : "long, boring, license text",
62 "spdx" : "GPL-2.0"
63 }
64 ],
65 "copyrightStatement" : "© 2010-2018 Plasma Development Team",
66 "desktopFileName" : "org.kde.kirigamiapp"
67 }
68 @endcode
69 *
70 * @see KAboutData
71 */
72 property var aboutData: Core.AboutData
73
74 /**
75 * @brief This property holds a link to a "Get Involved" page.
76 *
77 * default: `"https://community.kde.org/Get_Involved" when the
78 * application ID starts with "org.kde.", otherwise empty.`
79 */
80 property url getInvolvedUrl: aboutData.desktopFileName.startsWith("org.kde.") ? "https://community.kde.org/Get_Involved" : ""
81
82 /**
83 * @brief This property holds a link to a "Donate" page.
84 *
85 * default: `"https://www.kde.org/donate" when the application ID starts with "org.kde.", otherwise empty.`
86 */
87 property url donateUrl: aboutData.desktopFileName.startsWith("org.kde.") ? "https://www.kde.org/donate" : ""
88
89 title: i18nd("kirigami-addons6", "About %1", page.aboutData.displayName)
90
91 FormCard {
92 Layout.topMargin: Kirigami.Units.largeSpacing * 4
93
95 id: generalDelegate
96 Layout.fillWidth: true
97 background: null
98 contentItem: RowLayout {
99 spacing: Kirigami.Units.smallSpacing * 2
100
101 Kirigami.Icon {
102 Layout.preferredHeight: Kirigami.Units.iconSizes.huge
103 Layout.preferredWidth: height
104 Layout.maximumWidth: page.width / 3;
105 Layout.rightMargin: Kirigami.Units.largeSpacing
106 source: Kirigami.Settings.applicationWindowIcon || page.aboutData.programLogo || page.aboutData.programIconName || page.aboutData.componentName
107 }
108
109 ColumnLayout {
110 Layout.fillWidth: true
111 spacing: Kirigami.Units.smallSpacing
112
113 Kirigami.Heading {
114 Layout.fillWidth: true
115 text: page.aboutData.displayName + " " + page.aboutData.version
116 wrapMode: Text.WordWrap
117 }
118
119 Kirigami.Heading {
120 Layout.fillWidth: true
121 level: 3
122 type: Kirigami.Heading.Type.Secondary
123 wrapMode: Text.WordWrap
124 text: page.aboutData.shortDescription
125 }
126 }
127 }
128 }
129
131
133 id: copyrightDelegate
134 text: i18nd("kirigami-addons6", "Copyright")
135 descriptionItem.textFormat: Text.PlainText
136 description: aboutData.copyrightStatement
137 }
138 }
139
140 FormHeader {
141 visible: aboutData.otherText.length > 0
142 title: i18nd("kirigami-addons6", "Description")
143 }
144
145 FormCard {
146 visible: aboutData.otherText.length > 0
148 Layout.fillWidth: true
149 textItem.wrapMode: Text.WordWrap
150 text: aboutData.otherText
151 }
152 }
153
154 FormHeader {
155 title: i18ndp("kirigami-addons6", "License", "Licenses", aboutData.licenses.length)
156 visible: aboutData.licenses.length
157 }
158
159 FormCard {
160 visible: aboutData.licenses.length
161
162 Repeater {
163 model: aboutData.licenses
164 delegate: FormButtonDelegate {
165 text: modelData.name
166 Layout.fillWidth: true
167 onClicked: {
168 licenseSheet.text = modelData.text;
169 licenseSheet.title = modelData.name;
170 licenseSheet.open();
171 }
172 }
173 }
174
175 data: KirigamiComponents.MessageDialog {
176 id: licenseSheet
177
178 property alias text: bodyLabel.text
179
180 parent: QQC2.Overlay.overlay
181
182 leftPadding: 0
183 rightPadding: 0
184 bottomPadding: 0
185 topPadding: 0
186
187 header: Kirigami.Heading {
188 text: licenseSheet.title
189 elide: QQC2.Label.ElideRight
190 padding: licenseSheet.padding
191 topPadding: Kirigami.Units.largeSpacing
192 bottomPadding: Kirigami.Units.largeSpacing
193
194 Kirigami.Separator {
195 anchors {
196 left: parent.left
197 right: parent.right
198 bottom: parent.bottom
199 }
200 }
201 }
202
203 contentItem: QQC2.ScrollView {
204 id: scrollView
205
206 Kirigami.SelectableLabel {
207 id: bodyLabel
208 text: licenseSheet.text
209 textMargin: Kirigami.Units.gridUnit
210 }
211 }
212
213 footer: null
214 }
215 }
216
217 FormCard {
218 Layout.topMargin: Kirigami.Units.gridUnit
219
221 id: getInvolvedDelegate
222 icon.name: "globe-symbolic"
223 text: i18nd("kirigami-addons6", "Homepage")
224 onClicked: Qt.openUrlExternally(aboutData.homepage)
225 visible: aboutData.homepage.length > 0
226 }
227
229 above: getInvolvedDelegate
230 below: donateDelegate
231 visible: aboutData.homepage.length > 0
232 }
233
235 id: donateDelegate
236 icon.name: "donate-symbolic"
237 text: i18nd("kirigami-addons6", "Donate")
238 onClicked: Qt.openUrlExternally(donateUrl + "?app=" + page.aboutData.componentName)
239 visible: donateUrl.toString().length > 0
240 }
241
243 above: donateDelegate
244 below: homepageDelegate
245 visible: donateUrl.toString().length > 0
246 }
247
249 id: homepageDelegate
250 icon.name: "applications-development-symbolic"
251 text: i18nd("kirigami-addons6", "Get Involved")
252 onClicked: Qt.openUrlExternally(page.getInvolvedUrl)
253 visible: page.getInvolvedUrl != ""
254 }
255
257 above: homepageDelegate
258 below: bugDelegate
259 visible: page.getInvolvedUrl != ""
260 }
261
263 id: bugDelegate
264 readonly property string theUrl: {
265 if (aboutData.bugAddress !== "submit@bugs.kde.org") {
266 return aboutData.bugAddress
267 }
268 const elements = aboutData.productName.split('/');
269 let url = `https://bugs.kde.org/enter_bug.cgi?format=guided&product=${elements[0]}&version=${aboutData.version}`;
270 if (elements.length === 2) {
271 url += "&component=" + elements[1];
272 }
273 return url;
274 }
275
276 icon.name: "tools-report-bug-symbolic"
277 text: i18nd("kirigami-addons6", "Report a Bug")
278 onClicked: Qt.openUrlExternally(theUrl)
279 visible: theUrl.length > 0
280 }
281 }
282
283 FormHeader {
284 title: i18nd("kirigami-addons6", "Libraries in use")
285
286 actions: QQC2.Action {
287 text: i18ndc("kirigami-addons6", "@action:button", "Copy to Clipboard")
288 icon.name: 'edit-copy-symbolic'
289 onTriggered: {
290 FormCardModule.AboutComponent.copyToClipboard();
291 page.QQC2.ApplicationWindow.window.showPassiveNotification(i18ndc("kirigami-addons6", "@info", "System information copied to clipboard."), 'short');
292 }
293 }
294 }
295
296 FormCard {
297 Repeater {
298 model: FormCardModule.AboutComponent.components
299 delegate: libraryDelegate
300 }
301 }
302
303 FormHeader {
304 title: i18nd("kirigami-addons6", "Authors")
305 visible: aboutData.authors !== undefined && aboutData.authors.length > 0
306 }
307
308 FormCard {
309 visible: aboutData.authors !== undefined && aboutData.authors.length > 0
310
311 Repeater {
312 id: authorsRepeater
313 model: aboutData.authors
314 delegate: personDelegate
315 }
316 }
317
318 FormHeader {
319 title: i18nd("kirigami-addons6", "Credits")
320 visible: aboutData.credits !== undefined && aboutData.credits.length > 0
321 }
322
323 FormCard {
324 visible: aboutData.credits !== undefined && aboutData.credits.length > 0
325
326 Repeater {
327 id: repCredits
328 model: aboutData.credits
329 delegate: personDelegate
330 }
331 }
332
333 FormHeader {
334 title: i18nd("kirigami-addons6", "Translators")
335 visible: aboutData.translators !== undefined && aboutData.translators.length > 0
336 }
337
338 FormCard {
339 visible: aboutData.translators !== undefined && aboutData.translators.length > 0
340
341 Repeater {
342 id: repTranslators
343 model: aboutData.translators
344 delegate: personDelegate
345 }
346 }
347
348 data: [
349 Component {
350 id: personDelegate
351
353 Layout.fillWidth: true
354 background: null
355 contentItem: RowLayout {
356 spacing: Private.FormCardUnits.horizontalSpacing
357
358 KirigamiComponents.Avatar {
359 id: avatarIcon
360
361 implicitWidth: Kirigami.Units.iconSizes.medium
362 implicitHeight: implicitWidth
363 name: modelData.name
364 source: if (!!modelData.avatarUrl && modelData.avatarUrl.toString().startsWith('https://')) {
365 const url = new URL(modelData.avatarUrl);
366 const params = new URLSearchParams(url.search);
367 params.append("s", width);
368 url.search = params.toString();
369 return url;
370 } else {
371 return '';
372 }
373
374 Layout.rightMargin: Private.FormCardUnits.horizontalSpacing
375 }
376
377 ColumnLayout {
378 Layout.fillWidth: true
379 spacing: Private.FormCardUnits.verticalSpacing
380
381 QQC2.Label {
382 Layout.fillWidth: true
383 text: modelData.name
384 elide: Text.ElideRight
385 }
386
387 QQC2.Label {
388 id: internalDescriptionItem
389 Layout.fillWidth: true
390 text: modelData.task
391 color: Kirigami.Theme.disabledTextColor
392 font: Kirigami.Theme.smallFont
393 elide: Text.ElideRight
394 visible: text.length > 0
395 }
396 }
397
398 QQC2.ToolButton {
399 visible: typeof(modelData.ocsUsername) !== "undefined" && modelData.ocsUsername.length > 0
400 icon.name: "get-hot-new-stuff"
401 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
402 QQC2.ToolTip.visible: hovered
403 QQC2.ToolTip.text: i18nd("kirigami-addons6", "Visit %1's KDE Store page", modelData.name)
404 onClicked: Qt.openUrlExternally("https://store.kde.org/u/%1".arg(modelData.ocsUsername))
405 }
406
407 QQC2.ToolButton {
408 visible: typeof(modelData.emailAddress) !== "undefined" && modelData.emailAddress.length > 0
409 icon.name: "mail-sent"
410 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
411 QQC2.ToolTip.visible: hovered
412 QQC2.ToolTip.text: i18nd("kirigami-addons6", "Send an email to %1", modelData.emailAddress)
413 onClicked: Qt.openUrlExternally("mailto:%1".arg(modelData.emailAddress))
414 }
415
416 QQC2.ToolButton {
417 visible: typeof(modelData.webAddress) !== "undefined" && modelData.webAddress.length > 0
418 icon.name: "globe"
419 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
420 QQC2.ToolTip.visible: hovered
421 QQC2.ToolTip.text: (typeof(modelData.webAddress) === "undefined" && modelData.webAddress.length > 0) ? "" : modelData.webAddress
422 onClicked: Qt.openUrlExternally(modelData.webAddress)
423 }
424 }
425 }
426 },
427 Component {
428 id: libraryDelegate
429
431 id: delegate
432
433 required property var modelData
434
435 Layout.fillWidth: true
436 background: null
437 contentItem: RowLayout {
438 spacing: Private.FormCardUnits.horizontalSpacing
439
440 ColumnLayout {
441 Layout.fillWidth: true
442 spacing: Private.FormCardUnits.verticalSpacing
443
444 QQC2.Label {
445 Layout.fillWidth: true
446 text: delegate.modelData.name + ' ' + delegate.modelData.version
447 elide: Text.ElideRight
448 }
449
450 QQC2.Label {
451 id: internalDescriptionItem
452 Layout.fillWidth: true
453 text: delegate.modelData.description
454 color: Kirigami.Theme.disabledTextColor
455 font: Kirigami.Theme.smallFont
456 elide: Text.ElideRight
457 visible: text.length > 0
458 }
459 }
460
461 QQC2.ToolButton {
462 id: licenseButton
463 visible: modelData.licenses !== 0
464 icon.name: "license"
465
466 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
467 QQC2.ToolTip.visible: hovered
468 QQC2.ToolTip.text: !visible ? "" : delegate.modelData.licenses.name
469
470 KirigamiComponents.MessageDialog {
471 id: licenseSheet
472
473 title: delegate.modelData.name
474
475 parent: licenseButton.QQC2.Overlay.overlay
476 implicitWidth: Math.min(parent.width - Kirigami.Units.gridUnit * 2, implicitContentWidth)
477
478 leftPadding: 0
479 rightPadding: 0
480 bottomPadding: 0
481 topPadding: 0
482
483 header: QQC2.Control {
484 padding: licenseSheet.padding
485 topPadding: Kirigami.Units.largeSpacing
486 bottomPadding: Kirigami.Units.largeSpacing
487
488 contentItem: RowLayout {
489 spacing: Kirigami.Units.largeSpacing
490
492 text: licenseSheet.title
493 elide: QQC2.Label.ElideRight
494 padding: 0
495 leftPadding: Kirigami.Units.largeSpacing
496 Layout.fillWidth: true
497 }
498
499 QQC2.ToolButton {
500 icon.name: hovered ? "window-close" : "window-close-symbolic"
501 text: i18ndc("kirigami-addons6", "@action:button", "Close")
502 display: QQC2.ToolButton.IconOnly
503 onClicked: licenseSheet.close()
504 }
505 }
506
508 anchors {
509 left: parent.left
510 right: parent.right
511 bottom: parent.bottom
512 }
513 }
514 }
515
516 contentItem: QQC2.ScrollView {
518 id: bodyLabel
519 text: delegate.modelData.licenses.text
520 textMargin: Kirigami.Units.gridUnit
521 }
522 }
523
524 footer: null
525 }
526
527 onClicked: licenseSheet.open()
528 }
529
530 QQC2.ToolButton {
531 visible: typeof(modelData.webAddress) !== "undefined" && modelData.webAddress.length > 0
532 icon.name: "globe"
533 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
534 QQC2.ToolTip.visible: hovered
535 QQC2.ToolTip.text: (typeof(modelData.webAddress) === "undefined" && modelData.webAddress.length > 0) ? "" : modelData.webAddress
536 onClicked: Qt.openUrlExternally(modelData.webAddress)
537 }
538 }
539 }
540 }
541 ]
542}
A base item for delegates to be used in a FormCard.
A Form delegate that corresponds to a clickable button.
A scrollable page used as a container for one or more FormCards.
A single card that follows a form style.
Definition FormCard.qml:35
A context-aware separator.
A header item for a form card.
A Form delegate that corresponds to a text label and a description.
A dialog to show a message.
QString i18ndc(const char *domain, const char *context, const char *text, const TYPE &arg...)
QString i18ndp(const char *domain, const char *singular, const char *plural, const TYPE &arg...)
QString i18nd(const char *domain, const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
KCOREADDONS_EXPORT unsigned int version()
QStringView level(QStringView ifopt)
QString name(StandardAction id)
const QList< QKeySequence > & close()
const QList< QKeySequence > & open()
ElideRight
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 Dec 21 2024 17:03:50 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.