Changeset View
Changeset View
Standalone View
Standalone View
src/qtquick/qml/NewStuffPage.qml
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Copyright (C) 2019 Dan Leinir Turthra Jensen <admin@leinir.dk> | ||||
3 | * | ||||
4 | * This library is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU Lesser General Public | ||||
6 | * License as published by the Free Software Foundation; either | ||||
7 | * version 2.1 of the License, or (at your option) version 3, or any | ||||
8 | * later version accepted by the membership of KDE e.V. (or its | ||||
9 | * successor approved by the membership of KDE e.V.), which shall | ||||
10 | * act as a proxy defined in Section 6 of version 3 of the license. | ||||
11 | * | ||||
12 | * This library is distributed in the hope that it will be useful, | ||||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
15 | * Lesser General Public License for more details. | ||||
16 | * | ||||
17 | * You should have received a copy of the GNU Lesser General Public | ||||
18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | * | ||||
20 | */ | ||||
21 | | ||||
22 | /** | ||||
23 | * @brief A Kirigami.Page component used for managing KNS entries | ||||
24 | * | ||||
25 | * This component is functionally equivalent to the old DownloadDialog | ||||
26 | * @see KNewStuff::DownloadDialog | ||||
27 | */ | ||||
28 | | ||||
29 | import QtQuick 2.7 | ||||
30 | import QtQuick.Controls 2.5 as QtControls | ||||
31 | import QtQuick.Layouts 1.12 as QtLayouts | ||||
32 | import QtGraphicalEffects 1.12 as QtEffects | ||||
33 | import org.kde.kcm 1.2 as KCM | ||||
34 | import org.kde.kirigami 2.7 as Kirigami | ||||
35 | import org.kde.newstuff 1.1 as NewStuff | ||||
36 | | ||||
37 | KCM.GridViewKCM { | ||||
38 | id: root; | ||||
39 | /** | ||||
40 | * @brief The configuration file which describes the application (knsrc) | ||||
41 | * | ||||
42 | * The format and location of this file is found in the documentation for | ||||
43 | * KNS3::DownloadDialog | ||||
44 | */ | ||||
45 | property alias configFile: newStuffEngine.configFile; | ||||
46 | readonly property alias engine: newStuffEngine; | ||||
47 | signal message(string message); | ||||
48 | signal idleMessage(string message); | ||||
49 | signal busyMessage(string message); | ||||
50 | signal errorMessage(string message); | ||||
51 | | ||||
52 | property string uninstallLabel: i18nc("Request uninstallation of this item", "Uninstall"); | ||||
53 | property string useLabel: i18nc("If a knsrc file defines an adoption command, the option to run this command and 'use' an item becomes available. This is the text for an action to do so.", "Use"); | ||||
54 | | ||||
55 | property int viewMode: NewStuffPage.ViewMode.Tiles | ||||
56 | enum ViewMode { | ||||
57 | Tiles, | ||||
58 | Icons, | ||||
59 | Preview | ||||
60 | } | ||||
61 | | ||||
62 | title: newStuffEngine.name | ||||
63 | NewStuff.Engine { | ||||
64 | id: newStuffEngine; | ||||
65 | onMessage: root.message(message); | ||||
66 | onIdleMessage: root.idleMessage(message); | ||||
67 | onBusyMessage: root.busyMessage(message); | ||||
68 | onErrorMessage: root.errorMessage(message); | ||||
69 | } | ||||
70 | NewStuffQuestionAsker {} | ||||
71 | | ||||
72 | titleDelegate: QtLayouts.RowLayout { | ||||
73 | Kirigami.Heading { | ||||
74 | id: title | ||||
75 | level: 1 | ||||
76 | | ||||
77 | QtLayouts.Layout.fillWidth: true; | ||||
78 | QtLayouts.Layout.preferredWidth: titleTextMetrics.width | ||||
79 | QtLayouts.Layout.minimumWidth: titleTextMetrics.width | ||||
80 | opacity: root.isCurrentPage ? 1 : 0.4 | ||||
81 | maximumLineCount: 1 | ||||
82 | elide: Text.ElideRight | ||||
83 | text: root.title | ||||
84 | TextMetrics { | ||||
85 | id: titleTextMetrics | ||||
86 | text: root.title | ||||
87 | font: title.font | ||||
88 | } | ||||
89 | } | ||||
90 | QtControls.ButtonGroup { | ||||
91 | id: displayModeGroup | ||||
92 | buttons: [displayModeTiles, displayModeIcons] | ||||
93 | } | ||||
94 | QtControls.ToolButton { | ||||
95 | id: displayModeTiles | ||||
96 | icon.name: "view-list-details" | ||||
97 | onClicked: { root.viewMode = NewStuffPage.ViewMode.Tiles; } | ||||
98 | checked: root.viewMode == NewStuffPage.ViewMode.Tiles | ||||
99 | } | ||||
100 | QtControls.ToolButton { | ||||
101 | id: displayModeIcons | ||||
102 | icon.name: "view-list-icons" | ||||
103 | onClicked: { root.viewMode = NewStuffPage.ViewMode.Icons; } | ||||
104 | checked: root.viewMode == NewStuffPage.ViewMode.Icons | ||||
105 | } | ||||
106 | QtControls.ToolButton { | ||||
107 | id: displayPreview | ||||
108 | icon.name: "view-preview" | ||||
109 | onClicked: { root.viewMode = NewStuffPage.ViewMode.Preview; } | ||||
110 | checked: root.viewMode == NewStuffPage.ViewMode.Preview | ||||
111 | } | ||||
112 | Kirigami.ActionTextField { | ||||
113 | id: searchField | ||||
114 | placeholderText: i18n("Search...") | ||||
115 | focusSequence: "Ctrl+F" | ||||
116 | rightActions: [ | ||||
117 | Kirigami.Action { | ||||
118 | iconName: "edit-clear" | ||||
119 | visible: searchField.text !== "" | ||||
120 | onTriggered: { | ||||
121 | searchField.text = ""; | ||||
122 | searchField.accepted(); | ||||
123 | } | ||||
124 | } | ||||
125 | ] | ||||
126 | onAccepted: { | ||||
127 | newStuffEngine.searchTerm = searchField.text; | ||||
128 | } | ||||
129 | } | ||||
130 | } | ||||
131 | | ||||
132 | footer: QtLayouts.RowLayout { | ||||
133 | QtControls.ComboBox { | ||||
134 | id: categoriesCombo | ||||
135 | QtLayouts.Layout.fillWidth: true | ||||
136 | model: newStuffEngine.categories | ||||
137 | textRole: "displayName" | ||||
138 | onCurrentIndexChanged: { | ||||
139 | newStuffEngine.categoriesFilter = model.data(currentIndex, NewStuff.CategoriesModel.NameRole); | ||||
140 | } | ||||
141 | } | ||||
142 | QtControls.ComboBox { | ||||
143 | id: filterCombo | ||||
144 | QtLayouts.Layout.fillWidth: true | ||||
145 | model: ListModel {} | ||||
146 | Component.onCompleted: { | ||||
147 | filterCombo.model.append({ text: i18nc("List option which will set the filter to show everything", "Show Everything") }); | ||||
148 | filterCombo.model.append({ text: i18nc("List option which will set the filter so only installed items are shown", "Installed Only") }); | ||||
149 | filterCombo.model.append({ text: i18nc("List option which will set the filter so only installed items with updates available are shown", "Updateable Only") }); | ||||
150 | filterCombo.currentIndex = newStuffEngine.filter; | ||||
151 | } | ||||
152 | onCurrentIndexChanged: { | ||||
153 | newStuffEngine.filter = currentIndex; | ||||
154 | } | ||||
155 | } | ||||
156 | QtControls.ComboBox { | ||||
157 | id: sortCombo | ||||
158 | QtLayouts.Layout.fillWidth: true | ||||
159 | model: ListModel { } | ||||
160 | Component.onCompleted: { | ||||
161 | sortCombo.model.append({ text: i18nc("List option which will set the sort order to based on when items were most recently updated", "Show most recent first") }); | ||||
162 | sortCombo.model.append({ text: i18nc("List option which will set the sort order to be alphabetical based on the name", "Sort alphabetically") }); | ||||
163 | sortCombo.model.append({ text: i18nc("List option which will set the sort order to based on user ratings", "Show highest rated first") }); | ||||
164 | sortCombo.model.append({ text: i18nc("List option which will set the sort order to based on number of downloads", "Show most downloaded first") }); | ||||
165 | sortCombo.currentIndex = newStuffEngine.sortOrder; | ||||
166 | } | ||||
167 | onCurrentIndexChanged: { | ||||
168 | newStuffEngine.sortOrder = currentIndex; | ||||
169 | } | ||||
170 | } | ||||
171 | } | ||||
172 | | ||||
173 | view.model: NewStuff.ItemsModel { | ||||
174 | id: newStuffModel; | ||||
175 | engine: newStuffEngine; | ||||
176 | } | ||||
177 | NewStuffDownloadItemsSheet { | ||||
178 | id: downloadItemsSheet | ||||
179 | onItemPicked: { | ||||
180 | var entryName = newStuffModel.data(entryId, NewStuff.ItemsModel.NameRole); | ||||
181 | applicationWindow().showPassiveNotification(i18nc("A passive notification shown when installation of an item is initiated", "Installing %1 from %2").arg(downloadName).arg(entryName), 1500); | ||||
182 | newStuffModel.installItem(entryId, downloadItemId); | ||||
183 | } | ||||
184 | } | ||||
185 | | ||||
186 | view.implicitCellWidth: root.viewMode == NewStuffPage.ViewMode.Tiles ? Kirigami.Units.gridUnit * 30 : (root.viewMode == NewStuffPage.ViewMode.Preview ? Kirigami.Units.gridUnit * 25 : Kirigami.Units.gridUnit * 10) | ||||
187 | view.implicitCellHeight: root.viewMode == NewStuffPage.ViewMode.Tiles ? Math.round(view.implicitCellWidth / 3) : (root.viewMode == NewStuffPage.ViewMode.Preview ? Kirigami.Units.gridUnit * 25 : Math.round(view.implicitCellWidth / 1.6) + Kirigami.Units.gridUnit*2) | ||||
188 | view.delegate: root.viewMode == NewStuffPage.ViewMode.Tiles ? tileDelegate : (root.viewMode == NewStuffPage.ViewMode.Preview ? bigPreviewDelegate : thumbDelegate) | ||||
189 | | ||||
190 | Component { | ||||
191 | id: bigPreviewDelegate | ||||
192 | GridTileDelegate { | ||||
193 | id: bigPreviewDelegateRoot | ||||
194 | actionsAnchors.topMargin: bigPreview.height + Kirigami.Units.smallSpacing * 2 | ||||
195 | function showDetails() { | ||||
196 | pageStack.push(detailsPage, { | ||||
197 | newStuffModel: root.view.model, | ||||
198 | index: model.index, | ||||
199 | name: model.name, | ||||
200 | author: model.author, | ||||
201 | previews: model.previews, | ||||
202 | shortSummary: model.shortSummary, | ||||
203 | summary: model.summary, | ||||
204 | homepage: model.homepage, | ||||
205 | donationLink: model.donationLink, | ||||
206 | status: model.status, | ||||
207 | commentsCount: model.numberOfComments, | ||||
208 | rating: model.rating, | ||||
209 | downloadCount: model.downloadCount, | ||||
210 | providerId: model.providerId | ||||
211 | }); | ||||
212 | } | ||||
213 | actions: [ | ||||
214 | Kirigami.Action { | ||||
215 | text: root.useLabel | ||||
216 | iconName: "dialog-ok-apply" | ||||
217 | onTriggered: { model.adopt(model.index); } | ||||
218 | enabled: (model.status == NewStuff.ItemsModel.InstalledStatus || model.status == NewStuff.ItemsModel.UpdateableStatus) && newStuffEngine.hasAdoptionCommand | ||||
219 | visible: enabled | ||||
220 | }, | ||||
221 | Kirigami.Action { | ||||
222 | text: model.downloadCount == 1 ? i18nc("Request installation of this item, available when there is exactly one downloadable item", "Install") : i18nc("Show installation options, where there is more than one downloadable item", "Install..."); | ||||
223 | iconName: "install" | ||||
224 | onTriggered: { | ||||
225 | if (model.downloadCount == 1) { | ||||
226 | newStuffModel.installItem(model.index, 1); | ||||
227 | } else { | ||||
228 | downloadItemsSheet.downloadLinks = model.downloadLinks; | ||||
229 | downloadItemsSheet.entryId = model.index; | ||||
230 | downloadItemsSheet.open(); | ||||
231 | } | ||||
232 | } | ||||
233 | enabled: model.status == NewStuff.ItemsModel.DownloadableStatus || model.status == NewStuff.ItemsModel.DeletedStatus; | ||||
234 | visible: enabled; | ||||
235 | }, | ||||
236 | Kirigami.Action { | ||||
237 | text: i18nc("Request updating of this item", "Update"); | ||||
238 | iconName: "update" | ||||
239 | onTriggered: { newStuffModel.installItem(model.index); } | ||||
240 | enabled: model.status == NewStuff.ItemsModel.UpdateableStatus; | ||||
241 | visible: enabled; | ||||
242 | }, | ||||
243 | Kirigami.Action { | ||||
244 | text: root.uninstallLabel | ||||
245 | iconName: "uninstall" | ||||
246 | onTriggered: { newStuffModel.uninstallItem(model.index); } | ||||
247 | enabled: model.status == NewStuff.ItemsModel.InstalledStatus | ||||
248 | visible: enabled; | ||||
249 | } | ||||
250 | ] | ||||
251 | thumbnailAvailable: model.previewsSmall.length > 0 | ||||
252 | tile: Item { | ||||
253 | anchors { | ||||
254 | fill: parent | ||||
255 | margins: Kirigami.Units.smallSpacing | ||||
256 | } | ||||
257 | QtLayouts.ColumnLayout { | ||||
258 | anchors.fill: parent; | ||||
259 | Item { | ||||
260 | QtLayouts.Layout.fillWidth: true | ||||
261 | QtLayouts.Layout.minimumHeight: width / 1.8 | ||||
262 | QtLayouts.Layout.maximumHeight: width / 1.8 | ||||
263 | Image { | ||||
264 | id: bigPreview | ||||
265 | asynchronous: true; | ||||
266 | fillMode: Image.PreserveAspectCrop; | ||||
267 | source: thumbnailAvailable ? model.previews[0] : ""; | ||||
268 | anchors.fill: parent | ||||
269 | } | ||||
270 | QtEffects.DropShadow { | ||||
271 | anchors.fill: bigPreview | ||||
272 | horizontalOffset: 0 | ||||
273 | verticalOffset: 0 | ||||
274 | radius: Kirigami.Units.largeSpacing | ||||
275 | samples: radius * 2 | ||||
276 | color: "#80000000" | ||||
277 | source: bigPreview | ||||
278 | } | ||||
279 | Kirigami.Icon { | ||||
280 | id: updateAvailableBadge; | ||||
281 | opacity: (model.status == NewStuff.ItemsModel.UpdateableStatus) ? 1 : 0; | ||||
282 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; } } | ||||
283 | anchors { | ||||
284 | top: parent.top; | ||||
285 | left: parent.left; | ||||
286 | margins: -Kirigami.Units.smallSpacing; | ||||
287 | } | ||||
288 | height: Kirigami.Units.iconSizes.medium; | ||||
289 | width: height; | ||||
290 | source: "package-installed-outdated"; | ||||
291 | } | ||||
292 | Kirigami.Icon { | ||||
293 | id: installedBadge; | ||||
294 | opacity: (model.status == NewStuff.ItemsModel.InstalledStatus) ? 1 : 0; | ||||
295 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; } } | ||||
296 | anchors { | ||||
297 | top: parent.top; | ||||
298 | left: parent.left; | ||||
299 | } | ||||
300 | height: Kirigami.Units.iconSizes.medium; | ||||
301 | width: height; | ||||
302 | source: "package-installed-updated"; | ||||
303 | } | ||||
304 | Item { | ||||
305 | anchors { | ||||
306 | top: parent.top; | ||||
307 | right: parent.right; | ||||
308 | } | ||||
309 | height: Kirigami.Units.iconSizes.large; | ||||
310 | width: height; | ||||
311 | Kirigami.Icon { | ||||
312 | id: infoIcon | ||||
313 | source: "documentinfo" | ||||
314 | anchors.fill: parent | ||||
315 | } | ||||
316 | MouseArea { | ||||
317 | anchors.fill: parent | ||||
318 | onClicked: { bigPreviewDelegateRoot.showDetails(); } | ||||
319 | } | ||||
320 | QtEffects.Glow { | ||||
321 | anchors.fill: infoIcon | ||||
322 | radius: 1 | ||||
323 | samples: 2 | ||||
324 | spread: 0.3 | ||||
325 | color: "white" | ||||
326 | source: infoIcon | ||||
327 | } | ||||
328 | } | ||||
329 | } | ||||
330 | Rating { | ||||
331 | QtLayouts.Layout.fillWidth: true | ||||
332 | rating: model.rating / 10 | ||||
333 | } | ||||
334 | Kirigami.Heading { | ||||
335 | QtLayouts.Layout.fillWidth: true | ||||
336 | level: 5 | ||||
337 | elide: Text.ElideRight | ||||
338 | text: i18nc("The number of times the item has been downloaded", "%1 downloads").arg(model.downloadCount) | ||||
339 | } | ||||
340 | Kirigami.Heading { | ||||
341 | QtLayouts.Layout.fillWidth: true | ||||
342 | elide: Text.ElideRight | ||||
343 | level: 3 | ||||
344 | text: model.name | ||||
345 | } | ||||
346 | Kirigami.Heading { | ||||
347 | QtLayouts.Layout.fillWidth: true | ||||
348 | elide: Text.ElideRight | ||||
349 | level: 4 | ||||
350 | textFormat: Text.StyledText | ||||
351 | text: i18nc("Subheading for the tile view, located immediately underneath the name of the item", "By <i>%1</i>").arg(model.author.name) | ||||
352 | } | ||||
353 | QtControls.Label { | ||||
354 | QtLayouts.Layout.fillWidth: true | ||||
355 | QtLayouts.Layout.fillHeight: true | ||||
356 | wrapMode: Text.Wrap | ||||
357 | text: model.shortSummary.length > 0 ? model.shortSummary : model.summary | ||||
358 | elide: Text.ElideRight | ||||
359 | } | ||||
360 | } | ||||
361 | Item { | ||||
362 | anchors.fill: parent | ||||
363 | opacity: (model.status == NewStuff.ItemsModel.InstallingStatus || model.status == NewStuff.ItemsModel.UpdatingStatus) ? 1 : 0 | ||||
364 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration; } } | ||||
365 | Rectangle { | ||||
366 | anchors.fill: parent | ||||
367 | color: Kirigami.Theme.backgroundColor | ||||
368 | opacity: 0.5; | ||||
369 | } | ||||
370 | QtControls.BusyIndicator { | ||||
371 | anchors.centerIn: parent | ||||
372 | running: parent.opacity > 0 | ||||
373 | } | ||||
374 | } | ||||
375 | MouseArea { | ||||
376 | anchors.fill: parent; | ||||
377 | onClicked: bigPreviewDelegateRoot.showDetails(); | ||||
378 | } | ||||
379 | } | ||||
380 | } | ||||
381 | } | ||||
382 | Component { | ||||
383 | id: tileDelegate | ||||
384 | GridTileDelegate { | ||||
385 | id: tileDelegateRoot | ||||
386 | function showDetails() { | ||||
387 | pageStack.push(detailsPage, { | ||||
388 | newStuffModel: root.view.model, | ||||
389 | index: model.index, | ||||
390 | name: model.name, | ||||
391 | author: model.author, | ||||
392 | previews: model.previews, | ||||
393 | shortSummary: model.shortSummary, | ||||
394 | summary: model.summary, | ||||
395 | homepage: model.homepage, | ||||
396 | donationLink: model.donationLink, | ||||
397 | status: model.status, | ||||
398 | commentsCount: model.numberOfComments, | ||||
399 | rating: model.rating, | ||||
400 | downloadCount: model.downloadCount, | ||||
401 | providerId: model.providerId | ||||
402 | }); | ||||
403 | } | ||||
404 | actions: [ | ||||
405 | Kirigami.Action { | ||||
406 | text: root.useLabel | ||||
407 | iconName: "dialog-ok-apply" | ||||
408 | onTriggered: { model.adopt(model.index); } | ||||
409 | enabled: (model.status == NewStuff.ItemsModel.InstalledStatus || model.status == NewStuff.ItemsModel.UpdateableStatus) && newStuffEngine.hasAdoptionCommand | ||||
410 | visible: enabled | ||||
411 | }, | ||||
412 | Kirigami.Action { | ||||
413 | text: model.downloadCount == 1 ? i18nc("Request installation of this item, available when there is exactly one downloadable item", "Install") : i18nc("Show installation options, where there is more than one downloadable item", "Install..."); | ||||
414 | iconName: "install" | ||||
415 | onTriggered: { | ||||
416 | if (model.downloadCount == 1) { | ||||
417 | newStuffModel.installItem(model.index, 1); | ||||
418 | } else { | ||||
419 | downloadItemsSheet.downloadLinks = model.downloadLinks; | ||||
420 | downloadItemsSheet.entryId = model.index; | ||||
421 | downloadItemsSheet.open(); | ||||
422 | } | ||||
423 | } | ||||
424 | enabled: model.status == NewStuff.ItemsModel.DownloadableStatus || model.status == NewStuff.ItemsModel.DeletedStatus; | ||||
425 | visible: enabled; | ||||
426 | }, | ||||
427 | Kirigami.Action { | ||||
428 | text: i18nc("Request updating of this item", "Update"); | ||||
429 | iconName: "update" | ||||
430 | onTriggered: { newStuffModel.installItem(model.index); } | ||||
431 | enabled: model.status == NewStuff.ItemsModel.UpdateableStatus; | ||||
432 | visible: enabled; | ||||
433 | }, | ||||
434 | Kirigami.Action { | ||||
435 | text: root.uninstallLabel | ||||
436 | iconName: "uninstall" | ||||
437 | onTriggered: { newStuffModel.uninstallItem(model.index); } | ||||
438 | enabled: model.status == NewStuff.ItemsModel.InstalledStatus | ||||
439 | visible: enabled; | ||||
440 | }, | ||||
441 | Kirigami.Action { | ||||
442 | text: i18nc("Show a page with details for this item", "Details...") | ||||
443 | iconName: "documentinfo" | ||||
444 | onTriggered: { tileDelegateRoot.showDetails(); } | ||||
445 | } | ||||
446 | ] | ||||
447 | thumbnailAvailable: model.previewsSmall.length > 0 | ||||
448 | tile: Item { | ||||
449 | anchors { | ||||
450 | fill: parent | ||||
451 | margins: Kirigami.Units.smallSpacing | ||||
452 | } | ||||
453 | QtLayouts.GridLayout { | ||||
454 | anchors.fill: parent; | ||||
455 | columns: 2 | ||||
456 | QtLayouts.ColumnLayout { | ||||
457 | QtLayouts.Layout.minimumWidth: view.implicitCellWidth / 5 | ||||
458 | QtLayouts.Layout.maximumWidth: view.implicitCellWidth / 5 | ||||
459 | Item { | ||||
460 | QtLayouts.Layout.fillWidth: true | ||||
461 | QtLayouts.Layout.minimumHeight: width | ||||
462 | QtLayouts.Layout.maximumHeight: width | ||||
463 | Image { | ||||
464 | id: tilePreview | ||||
465 | asynchronous: true; | ||||
466 | fillMode: Image.PreserveAspectFit; | ||||
467 | source: thumbnailAvailable ? model.previewsSmall[0] : ""; | ||||
468 | anchors { | ||||
469 | fill: parent | ||||
470 | margins: Kirigami.Units.smallSpacing | ||||
471 | } | ||||
472 | verticalAlignment: Image.AlignTop | ||||
473 | } | ||||
474 | QtEffects.DropShadow { | ||||
475 | anchors.fill: tilePreview | ||||
476 | horizontalOffset: 0 | ||||
477 | verticalOffset: 0 | ||||
478 | radius: Kirigami.Units.largeSpacing | ||||
479 | samples: radius * 2 | ||||
480 | color: "#80000000" | ||||
481 | source: tilePreview | ||||
482 | } | ||||
483 | Kirigami.Icon { | ||||
484 | id: updateAvailableBadge; | ||||
485 | opacity: (model.status == NewStuff.ItemsModel.UpdateableStatus) ? 1 : 0; | ||||
486 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; } } | ||||
487 | anchors { | ||||
488 | top: parent.top; | ||||
489 | left: parent.left; | ||||
490 | margins: -Kirigami.Units.smallSpacing; | ||||
491 | } | ||||
492 | height: Kirigami.Units.iconSizes.smallMedium; | ||||
493 | width: height; | ||||
494 | source: "package-installed-outdated"; | ||||
495 | } | ||||
496 | Kirigami.Icon { | ||||
497 | id: installedBadge; | ||||
498 | opacity: (model.status == NewStuff.ItemsModel.InstalledStatus) ? 1 : 0; | ||||
499 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; } } | ||||
500 | anchors { | ||||
501 | top: parent.top; | ||||
502 | left: parent.left; | ||||
503 | margins: -Kirigami.Units.smallSpacing; | ||||
504 | } | ||||
505 | height: Kirigami.Units.iconSizes.smallMedium; | ||||
506 | width: height; | ||||
507 | source: "package-installed-updated"; | ||||
508 | } | ||||
509 | } | ||||
510 | Item { | ||||
511 | QtLayouts.Layout.fillHeight: true | ||||
512 | } | ||||
513 | } | ||||
514 | QtLayouts.ColumnLayout { | ||||
515 | QtLayouts.Layout.fillWidth: true | ||||
516 | QtLayouts.Layout.fillHeight: true | ||||
517 | Kirigami.Heading { | ||||
518 | QtLayouts.Layout.fillWidth: true | ||||
519 | elide: Text.ElideRight | ||||
520 | level: 3 | ||||
521 | text: model.name | ||||
522 | } | ||||
523 | Kirigami.Heading { | ||||
524 | QtLayouts.Layout.fillWidth: true | ||||
525 | elide: Text.ElideRight | ||||
526 | level: 4 | ||||
527 | textFormat: Text.StyledText | ||||
528 | text: i18nc("Subheading for the tile view, located immediately underneath the name of the item", "By <i>%1</i>").arg(model.author.name) | ||||
529 | } | ||||
530 | QtControls.Label { | ||||
531 | QtLayouts.Layout.fillWidth: true | ||||
532 | QtLayouts.Layout.fillHeight: true | ||||
533 | wrapMode: Text.Wrap | ||||
534 | text: model.shortSummary.length > 0 ? model.shortSummary : model.summary | ||||
535 | elide: Text.ElideRight | ||||
536 | } | ||||
537 | } | ||||
538 | Rating { | ||||
539 | QtLayouts.Layout.fillWidth: true | ||||
540 | rating: model.rating / 10 | ||||
541 | } | ||||
542 | Kirigami.Heading { | ||||
543 | QtLayouts.Layout.fillWidth: true | ||||
544 | level: 5 | ||||
545 | elide: Text.ElideRight | ||||
546 | text: i18nc("The number of times the item has been downloaded", "%1 downloads").arg(model.downloadCount) | ||||
547 | } | ||||
548 | } | ||||
549 | Item { | ||||
550 | anchors.fill: parent | ||||
551 | opacity: (model.status == NewStuff.ItemsModel.InstallingStatus || model.status == NewStuff.ItemsModel.UpdatingStatus) ? 1 : 0 | ||||
552 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration; } } | ||||
553 | Rectangle { | ||||
554 | anchors.fill: parent | ||||
555 | color: Kirigami.Theme.backgroundColor | ||||
556 | opacity: 0.5; | ||||
557 | } | ||||
558 | QtControls.BusyIndicator { | ||||
559 | anchors.centerIn: parent | ||||
560 | running: parent.opacity > 0 | ||||
561 | } | ||||
562 | } | ||||
563 | MouseArea { | ||||
564 | anchors.fill: parent; | ||||
565 | onClicked: tileDelegateRoot.showDetails(); | ||||
566 | } | ||||
567 | } | ||||
568 | } | ||||
569 | } | ||||
570 | Component { | ||||
571 | id: thumbDelegate | ||||
572 | KCM.GridDelegate { | ||||
573 | text: model.name | ||||
574 | // onClicked: pageStack.push(detailsPage, { | ||||
575 | // name: model.name, | ||||
576 | // author: model.author, | ||||
577 | // previews: model.previews, | ||||
578 | // shortSummary: model.shortSummary, | ||||
579 | // summary: model.summary, | ||||
580 | // homepage: model.homepage, | ||||
581 | // donationLink: model.donationLink | ||||
582 | // }); | ||||
583 | actions: [ | ||||
584 | Kirigami.Action { | ||||
585 | text: root.useLabel | ||||
586 | iconName: "dialog-ok-apply" | ||||
587 | onTriggered: { model.adopt(model.index); } | ||||
588 | enabled: (model.status == NewStuff.ItemsModel.InstalledStatus || model.status == NewStuff.ItemsModel.UpdateableStatus) && newStuffEngine.hasAdoptionCommand | ||||
589 | visible: enabled | ||||
590 | }, | ||||
591 | Kirigami.Action { | ||||
592 | text: model.downloadCount == 1 ? i18nc("Request installation of this item, available when there is exactly one downloadable item", "Install") : i18nc("Show installation options, where there is more than one downloadable item", "Install..."); | ||||
593 | iconName: "install" | ||||
594 | onTriggered: { | ||||
595 | if (model.downloadCount == 1) { | ||||
596 | newStuffModel.installItem(model.index); | ||||
597 | } else { | ||||
598 | downloadItemsSheet.downloadLinks = model.downloadLinks; | ||||
599 | downloadItemsSheet.entryId = model.index; | ||||
600 | downloadItemsSheet.open(); | ||||
601 | } | ||||
602 | } | ||||
603 | enabled: model.status == NewStuff.ItemsModel.DownloadableStatus || model.status == NewStuff.ItemsModel.DeletedStatus; | ||||
604 | visible: enabled; | ||||
605 | }, | ||||
606 | Kirigami.Action { | ||||
607 | text: i18nc("Request updating of this item", "Update"); | ||||
608 | iconName: "update" | ||||
609 | onTriggered: { newStuffModel.installItem(model.index); } | ||||
610 | enabled: model.status == NewStuff.ItemsModel.UpdateableStatus; | ||||
611 | visible: enabled; | ||||
612 | }, | ||||
613 | Kirigami.Action { | ||||
614 | text: root.uninstallLabel | ||||
615 | iconName: "uninstall" | ||||
616 | onTriggered: { newStuffModel.uninstallItem(model.index); } | ||||
617 | enabled: model.status == NewStuff.ItemsModel.InstalledStatus | ||||
618 | visible: enabled; | ||||
619 | } | ||||
620 | ] | ||||
621 | thumbnailAvailable: model.previewsSmall.length > 0 | ||||
622 | thumbnail: Image { | ||||
623 | anchors { | ||||
624 | fill: parent; | ||||
625 | margins: Kirigami.Units.smallSpacing; | ||||
626 | } | ||||
627 | asynchronous: true; | ||||
628 | fillMode: Image.PreserveAspectFit; | ||||
629 | source: thumbnailAvailable ? model.previewsSmall[0] : ""; | ||||
630 | Kirigami.Icon { | ||||
631 | id: updateAvailableBadge; | ||||
632 | opacity: (model.status == NewStuff.ItemsModel.UpdateableStatus) ? 1 : 0; | ||||
633 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; } } | ||||
634 | anchors { | ||||
635 | top: parent.top; | ||||
636 | right: parent.right; | ||||
637 | margins: -Kirigami.Units.smallSpacing; | ||||
638 | } | ||||
639 | height: Kirigami.Units.iconSizes.smallMedium; | ||||
640 | width: height; | ||||
641 | source: "package-installed-outdated"; | ||||
642 | } | ||||
643 | Kirigami.Icon { | ||||
644 | id: installedBadge; | ||||
645 | opacity: (model.status == NewStuff.ItemsModel.InstalledStatus) ? 1 : 0; | ||||
646 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; } } | ||||
647 | anchors { | ||||
648 | top: parent.top; | ||||
649 | right: parent.right; | ||||
650 | margins: -Kirigami.Units.smallSpacing; | ||||
651 | } | ||||
652 | height: Kirigami.Units.iconSizes.smallMedium; | ||||
653 | width: height; | ||||
654 | source: "package-installed-updated"; | ||||
655 | } | ||||
656 | Item { | ||||
657 | anchors.fill: parent | ||||
658 | opacity: (model.status == NewStuff.ItemsModel.InstallingStatus || model.status == NewStuff.ItemsModel.UpdatingStatus) ? 1 : 0 | ||||
659 | Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration; } } | ||||
660 | Rectangle { | ||||
661 | anchors.fill: parent | ||||
662 | color: Kirigami.Theme.backgroundColor | ||||
663 | opacity: 0.5; | ||||
664 | } | ||||
665 | QtControls.BusyIndicator { | ||||
666 | anchors.centerIn: parent | ||||
667 | running: parent.opacity > 0 | ||||
668 | } | ||||
669 | } | ||||
670 | MouseArea { | ||||
671 | anchors.fill: parent; | ||||
672 | onClicked: pageStack.push(detailsPage, { | ||||
673 | newStuffModel: root.view.model, | ||||
674 | index: model.index, | ||||
675 | name: model.name, | ||||
676 | author: model.author, | ||||
677 | previews: model.previews, | ||||
678 | shortSummary: model.shortSummary, | ||||
679 | summary: model.summary, | ||||
680 | homepage: model.homepage, | ||||
681 | donationLink: model.donationLink, | ||||
682 | status: model.status, | ||||
683 | commentsCount: model.numberOfComments, | ||||
684 | rating: model.rating, | ||||
685 | downloadCount: model.downloadCount, | ||||
686 | providerId: model.providerId | ||||
687 | }); | ||||
688 | } | ||||
689 | } | ||||
690 | } | ||||
691 | } | ||||
692 | | ||||
693 | Component { | ||||
694 | id: detailsPage; | ||||
695 | NewStuffEntryDetails { } | ||||
696 | } | ||||
697 | } |