Kirigami2

AboutItem.qml
1 /*
2  * SPDX-FileCopyrightText: 2018 Aleix Pol Gonzalez <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 import QtQuick 2.1
8 import QtQuick.Controls 2.4 as QQC2
9 import QtQuick.Window 2.15
10 import QtQuick.Layouts 1.3
11 import org.kde.kirigami 2.20 as Kirigami
12 
13 //TODO: Kf6: move somewhere else which can depend from KAboutData?
14 /**
15  * @brief An about item that displays the about data
16  *
17  * Allows to show the copyright notice of the application
18  * together with the contributors and some information of which platform it's
19  * running on.
20  *
21  * @since 5.87
22  * @since org.kde.kirigami 2.19
23  */
24 Item {
25  id: aboutItem
26  /**
27  * @brief This property holds an object with the same shape as KAboutData.
28  *
29  * Example usage:
30  * @code{json}
31  * aboutData: {
32  "displayName" : "KirigamiApp",
33  "productName" : "kirigami/app",
34  "componentName" : "kirigamiapp",
35  "shortDescription" : "A Kirigami example",
36  "homepage" : "",
37  "bugAddress" : "[email protected]",
38  "version" : "5.14.80",
39  "otherText" : "",
40  "authors" : [
41  {
42  "name" : "...",
43  "task" : "",
44  "emailAddress" : "[email protected]",
45  "webAddress" : "",
46  "ocsUsername" : ""
47  }
48  ],
49  "credits" : [],
50  "translators" : [],
51  "licenses" : [
52  {
53  "name" : "GPL v2",
54  "text" : "long, boring, license text",
55  "spdx" : "GPL-2.0"
56  }
57  ],
58  "copyrightStatement" : "© 2010-2018 Plasma Development Team",
59  "desktopFileName" : "org.kde.kirigamiapp"
60  }
61  @endcode
62  *
63  * @see KAboutData
64  */
65  property var aboutData
66 
67  /**
68  * @brief This property holds a link to a "Get Involved" page.
69  *
70  * default: `"https://community.kde.org/Get_Involved" when application id starts with "org.kde.", otherwise it is empty.`
71  */
72  property url getInvolvedUrl: aboutData.desktopFileName.startsWith("org.kde.") ? "https://community.kde.org/Get_Involved" : ""
73 
74  /**
75  * @brief This property holds a link to a "Donate" page.
76  *
77  * default: `"https://kde.org/community/donations" when application id starts with "org.kde.", otherwise it is empty.`
78  */
79  property url donateUrl: aboutData.desktopFileName.startsWith("org.kde.") ? "https://kde.org/community/donations" : ""
80 
81  /** @internal */
82  property bool _usePageStack: false
83 
84  /**
85  * @see org::kde::kirigami::FormLayout::wideMode
86  * @property bool wideMode
87  */
88  property alias wideMode: form.wideMode
89 
90  /** @internal */
91  default property alias _content: form.data
92 
93  implicitHeight: form.implicitHeight
94  implicitWidth: form.implicitWidth
95 
96  Component {
97  id: personDelegate
98 
99  RowLayout {
100  Layout.fillWidth: true
101  property bool hasRemoteAvatar: (typeof(modelData.ocsUsername) !== "undefined" && modelData.ocsUsername.length > 0)
102 
103  spacing: Kirigami.Units.smallSpacing * 2
104 
105  Kirigami.Icon {
106  id: avatarIcon
107 
108  implicitWidth: Kirigami.Units.iconSizes.medium
109  implicitHeight: implicitWidth
110 
111  fallback: "user"
112  source: hasRemoteAvatar && remoteAvatars.checked ? "https://store.kde.org/avatar/%1?s=%2".arg(modelData.ocsUsername).arg(width) : "user"
113  visible: status !== Kirigami.Icon.Loading
114  }
115 
116  // So it's clear that something is happening while avatar images are loaded
117  QQC2.BusyIndicator {
118  implicitWidth: Kirigami.Units.iconSizes.medium
119  implicitHeight: implicitWidth
120 
121  visible: avatarIcon.status === Kirigami.Icon.Loading
122  running: visible
123  }
124 
125  QQC2.Label {
126  Layout.fillWidth: true
127  readonly property bool withTask: typeof(modelData.task) !== "undefined" && modelData.task.length > 0
128  text: withTask ? qsTr("%1 (%2)").arg(modelData.name).arg(modelData.task) : modelData.name
129  wrapMode: Text.WordWrap
130  }
131 
132  QQC2.ToolButton {
133  visible: typeof(modelData.ocsUsername) !== "undefined" && modelData.ocsUsername.length > 0
134  icon.name: "get-hot-new-stuff"
135  QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
136  QQC2.ToolTip.visible: hovered
137  QQC2.ToolTip.text: qsTr("Visit %1's KDE Store page").arg(modelData.name)
138  onClicked: Qt.openUrlExternally("https://store.kde.org/u/%1".arg(modelData.ocsUsername))
139  }
140 
141  QQC2.ToolButton {
142  visible: typeof(modelData.emailAddress) !== "undefined" && modelData.emailAddress.length > 0
143  icon.name: "mail-sent"
144  QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
145  QQC2.ToolTip.visible: hovered
146  QQC2.ToolTip.text: qsTr("Send an email to %1").arg(modelData.emailAddress)
147  onClicked: Qt.openUrlExternally("mailto:%1".arg(modelData.emailAddress))
148  }
149 
150  QQC2.ToolButton {
151  visible: typeof(modelData.webAddress) !== "undefined" && modelData.webAddress.length > 0
152  icon.name: "globe"
153  QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
154  QQC2.ToolTip.visible: hovered
155  QQC2.ToolTip.text: (typeof(modelData.webAddress) === "undefined" && modelData.webAddress.length > 0) ? "" : modelData.webAddress
156  onClicked: Qt.openUrlExternally(modelData.webAddress)
157  }
158  }
159  }
160 
161  Kirigami.FormLayout {
162  id: form
163 
164  anchors.fill: parent
165 
166  GridLayout {
167  columns: 2
168  Layout.fillWidth: true
169 
170  Kirigami.Icon {
171  Layout.rowSpan: 3
172  Layout.preferredHeight: Kirigami.Units.iconSizes.huge
173  Layout.preferredWidth: height
174  Layout.maximumWidth: aboutItem.width / 3;
175  Layout.rightMargin: Kirigami.Units.largeSpacing
176  source: Kirigami.Settings.applicationWindowIcon || aboutItem.aboutData.programLogo || aboutItem.aboutData.programIconName || aboutItem.aboutData.componentName
177  }
178 
179  Kirigami.Heading {
180  Layout.fillWidth: true
181  text: aboutItem.aboutData.displayName + " " + aboutItem.aboutData.version
182  wrapMode: Text.WordWrap
183  }
184 
185  Kirigami.Heading {
186  Layout.fillWidth: true
187  level: 2
188  wrapMode: Text.WordWrap
189  text: aboutItem.aboutData.shortDescription
190  }
191 
192  RowLayout {
193  spacing: Kirigami.Units.largeSpacing * 2
194 
195  UrlButton {
196  text: qsTr("Get Involved")
197  url: aboutItem.getInvolvedUrl
198  visible: url !== ""
199  }
200 
201  UrlButton {
202  text: qsTr("Donate")
203  url: aboutItem.donateUrl
204  visible: url !== ""
205  }
206 
207  UrlButton {
208  readonly property string theUrl: {
209  if (page.aboutData.bugAddress !== "[email protected]") {
210  return page.aboutData.bugAddress
211  }
212  const elements = page.aboutData.productName.split('/');
213  let url = `https://bugs.kde.org/enter_bug.cgi?format=guided&product=${elements[0]}&version=${page.aboutData.version}`;
214  if (elements.length === 2) {
215  url += "&component=" + elements[1];
216  }
217  return url;
218  }
219  text: qsTr("Report a Bug")
220  url: theUrl
221  visible: theUrl !== ""
222  }
223  }
224  }
225 
226  Separator {
227  Layout.fillWidth: true
228  }
229 
230  Kirigami.Heading {
231  Kirigami.FormData.isSection: true
232  text: qsTr("Copyright")
233  }
234 
235  QQC2.Label {
236  Layout.leftMargin: Kirigami.Units.gridUnit
237  text: aboutData.otherText
238  visible: text.length > 0
239  wrapMode: Text.WordWrap
240  Layout.fillWidth: true
241  }
242 
243  QQC2.Label {
244  Layout.leftMargin: Kirigami.Units.gridUnit
245  text: aboutData.copyrightStatement
246  visible: text.length > 0
247  wrapMode: Text.WordWrap
248  Layout.fillWidth: true
249  }
250 
251  UrlButton {
252  Layout.leftMargin: Kirigami.Units.gridUnit
253  url: aboutData.homepage
254  visible: url.length > 0
255  wrapMode: Text.WordWrap
256  Layout.fillWidth: true
257  }
258 
259  OverlaySheet {
260  id: licenseSheet
261  property alias text: bodyLabel.text
262 
263  contentItem: SelectableLabel {
264  id: bodyLabel
265  text: licenseSheet.text
266  wrapMode: Text.Wrap
267  }
268  }
269 
270  Component {
271  id: licenseLinkButton
272 
273  RowLayout {
274  Layout.leftMargin: Kirigami.Units.smallSpacing
275 
276  QQC2.Label { text: qsTr("License:") }
277 
278  LinkButton {
279  Layout.fillWidth: true
280  wrapMode: Text.WordWrap
281  text: modelData.name
282  onClicked: mouse => {
283  licenseSheet.text = modelData.text
284  licenseSheet.title = modelData.name
285  licenseSheet.open()
286  }
287  }
288  }
289  }
290 
291  Component {
292  id: licenseTextItem
293 
294  QQC2.Label {
295  Layout.leftMargin: Kirigami.Units.smallSpacing
296  Layout.fillWidth: true
297  wrapMode: Text.WordWrap
298  text: qsTr("License: %1").arg(modelData.name)
299  }
300  }
301 
302  Repeater {
303  model: aboutData.licenses
304  delegate: _usePageStack ? licenseLinkButton : licenseTextItem
305  }
306 
307  Kirigami.Heading {
308  Kirigami.FormData.isSection: visible
309  text: qsTr("Libraries in use")
310  Layout.fillWidth: true
311  wrapMode: Text.WordWrap
312  visible: Kirigami.Settings.information
313  }
314 
315  Repeater {
316  model: Kirigami.Settings.information
317  delegate: QQC2.Label {
318  Layout.leftMargin: Kirigami.Units.gridUnit
319  Layout.fillWidth: true
320  wrapMode: Text.WordWrap
321  id: libraries
322  text: modelData
323  }
324  }
325 
326  Repeater {
327  model: aboutData.components
328  delegate: QQC2.Label {
329  Layout.fillWidth: true
330  wrapMode: Text.WordWrap
331  Layout.leftMargin: Kirigami.Units.gridUnit
332  text: modelData.name + (modelData.version === "" ? "" : " %1".arg(modelData.version))
333  }
334  }
335 
336  Kirigami.Heading {
337  Layout.fillWidth: true
338  Kirigami.FormData.isSection: visible
339  text: qsTr("Authors")
340  wrapMode: Text.WordWrap
341  visible: aboutData.authors.length > 0
342  }
343 
344  QQC2.CheckBox {
345  id: remoteAvatars
346  visible: authorsRepeater.hasAnyRemoteAvatars
347  checked: false
348  text: qsTr("Show author photos")
349 
350  Timer {
351  id: remotesThrottle
352  repeat: false
353  interval: 1
354  onTriggered: {
355  let hasAnyRemotes = false;
356  for (let i = 0; i < authorsRepeater.count; ++i) {
357  const itm = authorsRepeater.itemAt(i);
358  if (itm.hasRemoteAvatar) {
359  hasAnyRemotes = true;
360  break;
361  }
362  }
363  authorsRepeater.hasAnyRemoteAvatars = hasAnyRemotes;
364  }
365  }
366  }
367 
368  Repeater {
369  id: authorsRepeater
370  model: aboutData.authors
371  property bool hasAnyRemoteAvatars
372  delegate: personDelegate
373  onCountChanged: remotesThrottle.start()
374  }
375 
376  Kirigami.Heading {
377  height: visible ? implicitHeight : 0
378  Kirigami.FormData.isSection: visible
379  text: qsTr("Credits")
380  visible: repCredits.count > 0
381  }
382 
383  Repeater {
384  id: repCredits
385  model: aboutData.credits
386  delegate: personDelegate
387  }
388 
389  Kirigami.Heading {
390  height: visible ? implicitHeight : 0
391  Kirigami.FormData.isSection: visible
392  text: qsTr("Translators")
393  visible: repTranslators.count > 0
394  }
395 
396  Repeater {
397  id: repTranslators
398  model: aboutData.translators
399  delegate: personDelegate
400  }
401  }
402 }
This class contains global kirigami settings about the current device setup It is exposed to QML as t...
Definition: settings.h:16
A button that looks like a link.
Definition: LinkButton.qml:22
A link button that contains a URL.
Definition: UrlButton.qml:21
A visual separator.
Definition: Separator.qml:17
QAction * repeat(const QObject *recvr, const char *slot, QObject *parent)
Q_SCRIPTABLE CaptureState status()
An overlay sheet that covers the current Page content.
This is a label which supports text selection.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Jan 29 2023 04:11:03 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.