2022-03-05 22:41:29 +05:00

293 lines
9.7 KiB
QML

/*
SPDX-FileCopyrightText: 2018 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.0 as QtDialogs
import QtQuick.Controls 2.3 as QtControls
import org.kde.kirigami 2.14 as Kirigami
import org.kde.kquickcontrolsaddons 2.0 as KQCAddons
import org.kde.newstuff 1.81 as NewStuff
import org.kde.kcm 1.3 as KCM
import org.kde.private.kcms.icons 1.0 as Private
KCM.GridViewKCM {
id: root
KCM.ConfigModule.quickHelp: i18n("This module allows you to choose the icons for your desktop.")
view.model: kcm.iconsModel
view.currentIndex: kcm.pluginIndex(kcm.iconsSettings.theme)
enabled: !kcm.downloadingFile
KCM.SettingStateBinding {
configObject: kcm.iconsSettings
settingName: "Theme"
}
DropArea {
enabled: view.enabled
anchors.fill: parent
onEntered: {
if (!drag.hasUrls) {
drag.accepted = false;
}
}
onDropped: kcm.installThemeFromFile(drop.urls[0])
}
view.delegate: KCM.GridDelegate {
id: delegate
text: model.display
toolTip: model.description
thumbnailAvailable: typeof thumbFlow.previews === "undefined" || thumbFlow.previews.length > 0
thumbnail: MouseArea {
id: thumbArea
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
clip: thumbFlow.y < 0
opacity: model.pendingDeletion ? 0.3 : 1
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.longDuration }
}
Timer {
interval: 1000
repeat: true
running: thumbArea.containsMouse
onRunningChanged: {
if (!running) {
thumbFlow.currentPage = 0;
}
}
onTriggered: {
if (!thumbFlow.allPreviesLoaded) {
thumbFlow.loadPreviews(-1 /*no limit*/);
thumbFlow.allPreviesLoaded = true;
}
++thumbFlow.currentPage;
if (thumbFlow.currentPage >= thumbFlow.pageCount) {
stop();
}
}
}
Flow {
id: thumbFlow
// undefined is "didn't load preview yet"
// empty array is "no preview available"
property var previews
// initially we only load 6 and when the animation starts we'll load the rest
property bool allPreviesLoaded: false
property int currentPage
readonly property int pageCount: Math.ceil(thumbRepeater.count / (thumbFlow.columns * thumbFlow.rows))
readonly property int iconWidth: Math.floor(thumbArea.width / thumbFlow.columns)
readonly property int iconHeight: Math.floor(thumbArea.height / thumbFlow.rows)
readonly property int columns: 3
readonly property int rows: 2
function loadPreviews(limit) {
previews = kcm.previewIcons(model.themeName, Math.min(thumbFlow.iconWidth, thumbFlow.iconHeight), Screen.devicePixelRatio, limit);
}
width: parent.width
y: -currentPage * iconHeight * rows
Behavior on y {
NumberAnimation { duration: Kirigami.Units.longDuration }
}
Repeater {
id: thumbRepeater
model: thumbFlow.previews
Item {
width: thumbFlow.iconWidth
height: thumbFlow.iconHeight
KQCAddons.QPixmapItem {
anchors.centerIn: parent
width: Math.min(parent.width, nativeWidth)
height: Math.min(parent.height, nativeHeight)
// load on demand and avoid leaking a tiny corner of the icon
pixmap: thumbFlow.y < 0 || index < (thumbFlow.columns * thumbFlow.rows) ? modelData : undefined
smooth: true
fillMode: KQCAddons.QPixmapItem.PreserveAspectFit
}
}
}
Component.onCompleted: {
// avoid reloading it when icon sizes or dpr changes on startup
Qt.callLater(function() {
// We show 6 icons initially (3x2 grid), only load those
thumbFlow.loadPreviews(6 /*limit*/);
});
}
}
}
actions: [
Kirigami.Action {
iconName: "edit-delete"
tooltip: i18n("Remove Icon Theme")
enabled: model.removable
visible: !model.pendingDeletion
onTriggered: model.pendingDeletion = true
},
Kirigami.Action {
iconName: "edit-undo"
tooltip: i18n("Restore Icon Theme")
visible: model.pendingDeletion
onTriggered: model.pendingDeletion = false
}
]
onClicked: {
if (!model.pendingDeletion) {
kcm.iconsSettings.theme = model.themeName;
}
view.forceActiveFocus();
}
onDoubleClicked: {
kcm.save();
}
}
footer: ColumnLayout {
Kirigami.InlineMessage {
id: infoLabel
Layout.fillWidth: true
showCloseButton: true
Connections {
target: kcm
function onShowSuccessMessage(message) {
infoLabel.type = Kirigami.MessageType.Positive;
infoLabel.text = message;
infoLabel.visible = true;
}
function onShowErrorMessage(message) {
infoLabel.type = Kirigami.MessageType.Error;
infoLabel.text = message;
infoLabel.visible = true;
}
}
}
RowLayout {
id: progressRow
visible: false
QtControls.BusyIndicator {
id: progressBusy
}
QtControls.Label {
id: progressLabel
Layout.fillWidth: true
textFormat: Text.PlainText
wrapMode: Text.WordWrap
}
Connections {
target: kcm
onShowProgress: {
progressLabel.text = message;
progressBusy.running = true;
progressRow.visible = true;
}
onHideProgress: {
progressBusy.running = false;
progressRow.visible = false;
}
}
}
RowLayout {
Layout.fillWidth: true
// Using a non-flat toolbutton here, so it matches the items in the actiontoolbar
// (a Button is just ever so slightly smaller than a ToolButton, and it would look
// kind of silly if the buttons aren't the same size)
QtControls.ToolButton {
id: iconSizesButton
text: i18n("Configure Icon Sizes")
icon.name: "transform-scale" // proper icon?
display: QtControls.ToolButton.TextBesideIcon
flat: false
checkable: true
checked: iconSizePopupLoader.item && iconSizePopupLoader.item.opened
onClicked: {
iconSizePopupLoader.active = true;
iconSizePopupLoader.item.open();
}
}
Kirigami.ActionToolBar {
flat: false
alignment: Qt.AlignRight
actions: [
Kirigami.Action {
enabled: root.view.enabled
text: i18n("Install from File…")
icon.name: "document-import"
onTriggered: fileDialogLoader.active = true
},
NewStuff.Action {
text: i18n("Get New Icons…")
configFile: "icons.knsrc"
onEntryEvent: function (entry, event) {
if (event == 1) { // StatusChangedEvent
kcm.ghnsEntriesChanged();
} else if (event == 2) { // AdoptedEvent
kcm.reloadConfig();
}
}
}
]
}
}
}
Loader {
id: iconSizePopupLoader
active: false
sourceComponent: IconSizePopup {
parent: iconSizesButton
y: -height
}
}
Loader {
id: fileDialogLoader
active: false
sourceComponent: QtDialogs.FileDialog {
title: i18n("Open Theme")
folder: shortcuts.home
nameFilters: [ i18n("Theme Files (*.tar.gz *.tar.bz2)") ]
Component.onCompleted: open()
onAccepted: {
kcm.installThemeFromFile(fileUrls[0])
fileDialogLoader.active = false
}
onRejected: {
fileDialogLoader.active = false
}
}
}
}