Warning, /frameworks/kirigami/src/controls/AboutItem.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 * SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 import QtQuick 0009 import QtQuick.Controls as QQC2 0010 import QtQuick.Layouts 0011 import org.kde.kirigami as Kirigami 0012 0013 //TODO: Kf6: move somewhere else which can depend from KAboutData? 0014 /** 0015 * @brief An about item that displays the about data 0016 * 0017 * Allows to show the copyright notice of the application 0018 * together with the contributors and some information of which platform it's 0019 * running on. 0020 * 0021 * @since 5.87 0022 * @since org.kde.kirigami 2.19 0023 */ 0024 Item { 0025 id: aboutItem 0026 /** 0027 * @brief This property holds an object with the same shape as KAboutData. 0028 * 0029 * Example usage: 0030 * @code{json} 0031 * aboutData: { 0032 "displayName" : "KirigamiApp", 0033 "productName" : "kirigami/app", 0034 "componentName" : "kirigamiapp", 0035 "shortDescription" : "A Kirigami example", 0036 "homepage" : "", 0037 "bugAddress" : "submit@bugs.kde.org", 0038 "version" : "5.14.80", 0039 "otherText" : "", 0040 "authors" : [ 0041 { 0042 "name" : "...", 0043 "task" : "", 0044 "emailAddress" : "somebody@kde.org", 0045 "webAddress" : "", 0046 "ocsUsername" : "" 0047 } 0048 ], 0049 "credits" : [], 0050 "translators" : [], 0051 "licenses" : [ 0052 { 0053 "name" : "GPL v2", 0054 "text" : "long, boring, license text", 0055 "spdx" : "GPL-2.0" 0056 } 0057 ], 0058 "copyrightStatement" : "© 2010-2018 Plasma Development Team", 0059 "desktopFileName" : "org.kde.kirigamiapp" 0060 } 0061 @endcode 0062 * 0063 * @see KAboutData 0064 */ 0065 property var aboutData 0066 0067 /** 0068 * @brief This property holds a link to a "Get Involved" page. 0069 * 0070 * default: `"https://community.kde.org/Get_Involved" when application id starts with "org.kde.", otherwise it is empty.` 0071 */ 0072 property url getInvolvedUrl: aboutData.desktopFileName.startsWith("org.kde.") ? "https://community.kde.org/Get_Involved" : "" 0073 0074 /** 0075 * @brief This property holds a link to a "Donate" page. 0076 * 0077 * default: `"https://kde.org/community/donations" when application id starts with "org.kde.", otherwise it is empty.` 0078 */ 0079 property url donateUrl: aboutData.desktopFileName.startsWith("org.kde.") ? "https://kde.org/community/donations" : "" 0080 0081 /** @internal */ 0082 property bool _usePageStack: false 0083 0084 /** 0085 * @see org::kde::kirigami::FormLayout::wideMode 0086 * @property bool wideMode 0087 */ 0088 property alias wideMode: form.wideMode 0089 0090 /** @internal */ 0091 default property alias _content: form.data 0092 0093 // if aboutData is a native KAboutData object, avatarUrl should be a proper url instance, 0094 // otherwise if it was defined as a string in pure JavaScript it should work too. 0095 readonly property bool __hasAvatars: aboutItem.aboutData.authors.some(__hasAvatar) 0096 0097 function __hasAvatar(person): bool { 0098 return typeof person.avatarUrl !== "undefined" 0099 && person.avatarUrl.toString().length > 0; 0100 } 0101 0102 /** 0103 * @brief This property controls whether to load avatars by URL. 0104 * 0105 * If set to false, a fallback "user" icon will be displayed. 0106 * 0107 * default: ``false`` 0108 */ 0109 property bool loadAvatars: false 0110 0111 implicitHeight: form.implicitHeight 0112 implicitWidth: form.implicitWidth 0113 0114 Component { 0115 id: personDelegate 0116 0117 RowLayout { 0118 id: delegate 0119 0120 // type: KAboutPerson | { name?, task?, emailAddress?, webAddress?, avatarUrl? } 0121 required property var modelData 0122 0123 property bool hasAvatar: aboutItem.__hasAvatar(modelData) 0124 0125 Layout.fillWidth: true 0126 0127 spacing: Kirigami.Units.smallSpacing * 2 0128 0129 Kirigami.Icon { 0130 id: avatarIcon 0131 0132 implicitWidth: Kirigami.Units.iconSizes.medium 0133 implicitHeight: implicitWidth 0134 0135 fallback: "user" 0136 source: { 0137 if (delegate.hasAvatar && aboutItem.loadAvatars) { 0138 // Appending to the params of the url does not work, thus the search is set 0139 const url = new URL(modelData.avatarUrl); 0140 const params = new URLSearchParams(url.search); 0141 params.append("s", width); 0142 url.search = params.toString(); 0143 return url; 0144 } else { 0145 return "user" 0146 } 0147 } 0148 visible: status !== Kirigami.Icon.Loading 0149 } 0150 0151 // So it's clear that something is happening while avatar images are loaded 0152 QQC2.BusyIndicator { 0153 implicitWidth: Kirigami.Units.iconSizes.medium 0154 implicitHeight: implicitWidth 0155 0156 visible: avatarIcon.status === Kirigami.Icon.Loading 0157 running: visible 0158 } 0159 0160 QQC2.Label { 0161 Layout.fillWidth: true 0162 readonly property bool withTask: typeof(modelData.task) !== "undefined" && modelData.task.length > 0 0163 text: withTask ? qsTr("%1 (%2)").arg(modelData.name).arg(modelData.task) : modelData.name 0164 wrapMode: Text.WordWrap 0165 } 0166 0167 QQC2.ToolButton { 0168 visible: typeof(modelData.emailAddress) !== "undefined" && modelData.emailAddress.length > 0 0169 icon.name: "mail-sent" 0170 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay 0171 QQC2.ToolTip.visible: hovered 0172 QQC2.ToolTip.text: qsTr("Send an email to %1").arg(modelData.emailAddress) 0173 onClicked: Qt.openUrlExternally("mailto:%1".arg(modelData.emailAddress)) 0174 } 0175 0176 QQC2.ToolButton { 0177 visible: typeof(modelData.webAddress) !== "undefined" && modelData.webAddress.length > 0 0178 icon.name: "globe" 0179 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay 0180 QQC2.ToolTip.visible: hovered 0181 QQC2.ToolTip.text: (typeof(modelData.webAddress) === "undefined" && modelData.webAddress.length > 0) ? "" : modelData.webAddress 0182 onClicked: Qt.openUrlExternally(modelData.webAddress) 0183 } 0184 } 0185 } 0186 0187 Kirigami.FormLayout { 0188 id: form 0189 0190 anchors.fill: parent 0191 0192 GridLayout { 0193 columns: 2 0194 Layout.fillWidth: true 0195 0196 Kirigami.Icon { 0197 Layout.rowSpan: 3 0198 Layout.preferredHeight: Kirigami.Units.iconSizes.huge 0199 Layout.preferredWidth: height 0200 Layout.maximumWidth: aboutItem.width / 3; 0201 Layout.rightMargin: Kirigami.Units.largeSpacing 0202 source: Kirigami.Settings.applicationWindowIcon || aboutItem.aboutData.programLogo || aboutItem.aboutData.programIconName || aboutItem.aboutData.componentName 0203 } 0204 0205 Kirigami.Heading { 0206 Layout.fillWidth: true 0207 text: aboutItem.aboutData.displayName + " " + aboutItem.aboutData.version 0208 wrapMode: Text.WordWrap 0209 } 0210 0211 Kirigami.Heading { 0212 Layout.fillWidth: true 0213 level: 2 0214 wrapMode: Text.WordWrap 0215 text: aboutItem.aboutData.shortDescription 0216 } 0217 0218 RowLayout { 0219 spacing: Kirigami.Units.largeSpacing * 2 0220 0221 UrlButton { 0222 text: qsTr("Get Involved") 0223 url: aboutItem.getInvolvedUrl 0224 visible: url.toString().length > 0 0225 } 0226 0227 UrlButton { 0228 text: qsTr("Donate") 0229 url: aboutItem.donateUrl 0230 visible: url.toString().length > 0 0231 } 0232 0233 UrlButton { 0234 readonly property string theUrl: { 0235 if (aboutItem.aboutData.bugAddress !== "submit@bugs.kde.org") { 0236 return aboutItem.aboutData.bugAddress 0237 } 0238 const elements = aboutItem.aboutData.productName.split('/'); 0239 let url = `https://bugs.kde.org/enter_bug.cgi?format=guided&product=${elements[0]}&version=${aboutItem.aboutData.version}`; 0240 if (elements.length === 2) { 0241 url += "&component=" + elements[1]; 0242 } 0243 return url; 0244 } 0245 text: qsTr("Report a Bug") 0246 url: theUrl 0247 visible: theUrl.toString().length > 0 0248 } 0249 } 0250 } 0251 0252 Separator { 0253 Layout.fillWidth: true 0254 } 0255 0256 Kirigami.Heading { 0257 Kirigami.FormData.isSection: true 0258 text: qsTr("Copyright") 0259 } 0260 0261 QQC2.Label { 0262 Layout.leftMargin: Kirigami.Units.gridUnit 0263 text: aboutItem.aboutData.otherText 0264 visible: text.length > 0 0265 wrapMode: Text.WordWrap 0266 Layout.fillWidth: true 0267 } 0268 0269 QQC2.Label { 0270 Layout.leftMargin: Kirigami.Units.gridUnit 0271 text: aboutItem.aboutData.copyrightStatement 0272 visible: text.length > 0 0273 wrapMode: Text.WordWrap 0274 Layout.fillWidth: true 0275 } 0276 0277 UrlButton { 0278 Layout.leftMargin: Kirigami.Units.gridUnit 0279 url: aboutItem.aboutData.homepage 0280 visible: url.length > 0 0281 wrapMode: Text.WordWrap 0282 Layout.fillWidth: true 0283 } 0284 0285 OverlaySheet { 0286 id: licenseSheet 0287 property alias text: bodyLabel.text 0288 0289 contentItem: SelectableLabel { 0290 id: bodyLabel 0291 text: licenseSheet.text 0292 wrapMode: Text.Wrap 0293 } 0294 } 0295 0296 Component { 0297 id: licenseLinkButton 0298 0299 RowLayout { 0300 Layout.leftMargin: Kirigami.Units.smallSpacing 0301 0302 QQC2.Label { text: qsTr("License:") } 0303 0304 LinkButton { 0305 Layout.fillWidth: true 0306 wrapMode: Text.WordWrap 0307 text: modelData.name 0308 onClicked: mouse => { 0309 licenseSheet.text = modelData.text 0310 licenseSheet.title = modelData.name 0311 licenseSheet.open() 0312 } 0313 } 0314 } 0315 } 0316 0317 Component { 0318 id: licenseTextItem 0319 0320 QQC2.Label { 0321 Layout.leftMargin: Kirigami.Units.smallSpacing 0322 Layout.fillWidth: true 0323 wrapMode: Text.WordWrap 0324 text: qsTr("License: %1").arg(modelData.name) 0325 } 0326 } 0327 0328 Repeater { 0329 model: aboutItem.aboutData.licenses 0330 delegate: _usePageStack ? licenseLinkButton : licenseTextItem 0331 } 0332 0333 Kirigami.Heading { 0334 Kirigami.FormData.isSection: visible 0335 text: qsTr("Libraries in use") 0336 Layout.fillWidth: true 0337 wrapMode: Text.WordWrap 0338 visible: Kirigami.Settings.information 0339 } 0340 0341 Repeater { 0342 model: Kirigami.Settings.information 0343 delegate: QQC2.Label { 0344 Layout.leftMargin: Kirigami.Units.gridUnit 0345 Layout.fillWidth: true 0346 wrapMode: Text.WordWrap 0347 id: libraries 0348 text: modelData 0349 } 0350 } 0351 0352 Repeater { 0353 model: aboutItem.aboutData.components 0354 delegate: QQC2.Label { 0355 Layout.fillWidth: true 0356 wrapMode: Text.WordWrap 0357 Layout.leftMargin: Kirigami.Units.gridUnit 0358 text: modelData.name + (modelData.version.length === 0 ? "" : " %1".arg(modelData.version)) 0359 } 0360 } 0361 0362 Kirigami.Heading { 0363 Layout.fillWidth: true 0364 Kirigami.FormData.isSection: visible 0365 text: qsTr("Authors") 0366 wrapMode: Text.WordWrap 0367 visible: aboutItem.aboutData.authors.length > 0 0368 } 0369 0370 QQC2.CheckBox { 0371 id: remoteAvatars 0372 visible: aboutItem.__hasAvatars 0373 checked: aboutItem.loadAvatars 0374 onToggled: aboutItem.loadAvatars = checked 0375 text: qsTr("Show author photos") 0376 } 0377 0378 Repeater { 0379 id: authorsRepeater 0380 model: aboutItem.aboutData.authors 0381 delegate: personDelegate 0382 } 0383 0384 Kirigami.Heading { 0385 Kirigami.FormData.isSection: visible 0386 text: qsTr("Credits") 0387 visible: repCredits.count > 0 0388 } 0389 0390 Repeater { 0391 id: repCredits 0392 model: aboutItem.aboutData.credits 0393 delegate: personDelegate 0394 } 0395 0396 Kirigami.Heading { 0397 Kirigami.FormData.isSection: visible 0398 text: qsTr("Translators") 0399 visible: repTranslators.count > 0 0400 } 0401 0402 Repeater { 0403 id: repTranslators 0404 model: aboutItem.aboutData.translators 0405 delegate: personDelegate 0406 } 0407 } 0408 }