diff --git a/kcms/cursortheme/package/contents/ui/main.qml b/kcms/cursortheme/package/contents/ui/main.qml index 51a99aae1..124ff3662 100644 --- a/kcms/cursortheme/package/contents/ui/main.qml +++ b/kcms/cursortheme/package/contents/ui/main.qml @@ -1,179 +1,181 @@ /* Copyright (c) 2015 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Window 2.2 // for Screen import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 as QtControls import QtQuick.Dialogs 1.1 as QtDialogs import org.kde.kirigami 2.4 as Kirigami +import org.kde.kconfig 1.0 // for KAuthorized import org.kde.kcm 1.1 as KCM import org.kde.private.kcm_cursortheme 1.0 KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module lets you configure the mouse cursor theme used.") view.model: kcm.cursorsModel view.delegate: Delegate {} view.onCurrentIndexChanged: { kcm.selectedThemeRow = view.currentIndex; view.positionViewAtIndex(view.currentIndex, view.GridView.Beginning); } DropArea { anchors.fill: parent onEntered: { if (!drag.hasUrls) { drag.accepted = false; } } onDropped: kcm.installThemeFromFile(drop.urls[0]) } Connections { target: kcm onSelectedThemeRowChanged: view.currentIndex = kcm.selectedThemeRow; } footer: ColumnLayout { id: footerLayout Kirigami.InlineMessage { id: infoLabel Layout.fillWidth: true showCloseButton: true Connections { target: kcm onShowSuccessMessage: { infoLabel.type = Kirigami.MessageType.Positive; infoLabel.text = message; infoLabel.visible = true; } onShowInfoMessage: { infoLabel.type = Kirigami.MessageType.Information; infoLabel.text = message; infoLabel.visible = true; } onShowErrorMessage: { infoLabel.type = Kirigami.MessageType.Error; infoLabel.text = message; infoLabel.visible = true; } } } RowLayout { id: row1 //spacer Item { Layout.fillWidth: true Layout.fillHeight: true } RowLayout { id: comboLayout enabled: kcm.canResize QtControls.Label { text: i18n("Size:") } QtControls.ComboBox { id: sizeCombo currentIndex: 0 onCountChanged: currentIndex = 0 model: kcm.sizesModel textRole: "display" onCurrentTextChanged: { kcm.preferredSize = isNaN(parseInt(sizeCombo.currentText)) ? 0 : parseInt(sizeCombo.currentText); } delegate: QtControls.ItemDelegate { id: sizeComboDelegate readonly property int size: parseInt(model.display) width: parent.width highlighted: ListView.isCurrentItem text: model.display contentItem: RowLayout { Kirigami.Icon { source: model.decoration smooth: true width: sizeComboDelegate.size / Screen.devicePixelRatio height: sizeComboDelegate.size / Screen.devicePixelRatio visible: valid && sizeComboDelegate.size > 0 } QtControls.Label { Layout.fillWidth: true color: sizeComboDelegate.highlighted ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor text: model[sizeCombo.textRole] } } } } } RowLayout { parent: footerLayout.x + footerLayout.width - comboLayout.width > width ? row1 : row2 QtControls.Button { icon.name: "document-import" text: i18n("&Install From File...") onClicked: fileDialogLoader.active = true; enabled: kcm.canInstall } QtControls.Button { icon.name: "get-hot-new-stuff" text: i18n("&Get New Theme...") onClicked: kcm.getNewClicked(); enabled: kcm.canInstall + visible: KAuthorized.authorize("ghns") } } } RowLayout { id: row2 visible: children.length > 1 //spacer Item { Layout.fillWidth: true Layout.fillHeight: true } } } Loader { id: fileDialogLoader active: false sourceComponent: QtDialogs.FileDialog { title: i18n("Open Theme") folder: shortcuts.home nameFilters: [ i18n("Cursor Theme Files (*.tar.gz *.tar.bz2)") ] Component.onCompleted: open() onAccepted: { kcm.installThemeFromFile(fileUrls[0]) fileDialogLoader.active = false } onRejected: { fileDialogLoader.active = false } } } } diff --git a/kcms/desktoptheme/package/contents/ui/main.qml b/kcms/desktoptheme/package/contents/ui/main.qml index bd00d12b9..af613fb69 100644 --- a/kcms/desktoptheme/package/contents/ui/main.qml +++ b/kcms/desktoptheme/package/contents/ui/main.qml @@ -1,162 +1,164 @@ /* Copyright (c) 2014 Marco Martin Copyright (c) 2016 David Rosca Copyright (c) 2018 Kai Uwe Broulik This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.0 import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami +import org.kde.kconfig 1.0 // for KAuthorized import org.kde.kcm 1.1 as KCM KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module lets you configure the desktop theme.") view.model: kcm.desktopThemeModel view.currentIndex: kcm.selectedPluginIndex DropArea { anchors.fill: parent onEntered: { if (!drag.hasUrls) { drag.accepted = false; } } onDropped: kcm.installThemeFromFile(drop.urls[0]) } view.remove: Transition { ParallelAnimation { NumberAnimation { property: "scale"; to: 0.5; duration: Kirigami.Units.longDuration } NumberAnimation { property: "opacity"; to: 0.0; duration: Kirigami.Units.longDuration } } } view.removeDisplaced: Transition { SequentialAnimation { // wait for the "remove" animation to finish PauseAnimation { duration: Kirigami.Units.longDuration } NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration } } } view.delegate: KCM.GridDelegate { id: delegate text: model.themeName toolTip: model.description || model.themeName opacity: model.pendingDeletion ? 0.3 : 1 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } } thumbnailAvailable: true thumbnail: ThemePreview { id: preview anchors.fill: parent themeName: model.pluginName } actions: [ Kirigami.Action { iconName: "document-edit" tooltip: i18n("Edit Theme") enabled: !model.pendingDeletion visible: kcm.canEditThemes onTriggered: kcm.editTheme(model.pluginName) }, Kirigami.Action { iconName: "edit-delete" tooltip: i18n("Remove Theme") enabled: model.isLocal visible: !model.pendingDeletion onTriggered: kcm.setPendingDeletion(model.index, true); }, Kirigami.Action { iconName: "edit-undo" tooltip: i18n("Restore Theme") visible: model.pendingDeletion onTriggered: kcm.setPendingDeletion(model.index, false); } ] onClicked: { kcm.selectedPlugin = model.pluginName; view.forceActiveFocus(); } } footer: ColumnLayout { Kirigami.InlineMessage { id: infoLabel Layout.fillWidth: true showCloseButton: true Connections { target: kcm onShowSuccessMessage: { infoLabel.type = Kirigami.MessageType.Positive; infoLabel.text = message; infoLabel.visible = true; } onShowErrorMessage: { infoLabel.type = Kirigami.MessageType.Error; infoLabel.text = message; infoLabel.visible = true; } } } RowLayout { Layout.alignment: Qt.AlignRight QtControls.Button { text: i18n("Install from File...") icon.name: "document-import" onClicked: fileDialogLoader.active = true; } QtControls.Button { text: i18n("Get New Themes...") icon.name: "get-hot-new-stuff" onClicked: kcm.getNewStuff(this) + visible: KAuthorized.authorize("ghns") } } } Loader { id: fileDialogLoader active: false sourceComponent: FileDialog { title: i18n("Open Theme") folder: shortcuts.home nameFilters: [ i18n("Theme Files (*.zip *.tar.gz *.tar.bz2)") ] Component.onCompleted: open() onAccepted: { kcm.installThemeFromFile(fileUrls[0]) fileDialogLoader.active = false } onRejected: { fileDialogLoader.active = false } } } } diff --git a/kcms/icons/package/contents/ui/main.qml b/kcms/icons/package/contents/ui/main.qml index 642d06636..85c2eba71 100644 --- a/kcms/icons/package/contents/ui/main.qml +++ b/kcms/icons/package/contents/ui/main.qml @@ -1,298 +1,300 @@ /* * Copyright 2018 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ 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.4 as Kirigami import org.kde.kquickcontrolsaddons 2.0 as KQCAddons +import org.kde.kconfig 1.0 // for KAuthorized import org.kde.kcm 1.1 as KCM import org.kde.private.kcms.icons 1.0 as Private KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module allows you to choose the icons for your desktop.") view.model: kcm.iconsModel view.currentIndex: kcm.iconsModel.selectedThemeIndex DropArea { anchors.fill: parent onEntered: { if (!drag.hasUrls) { drag.accepted = false; } } onDropped: kcm.installThemeFromFile(drop.urls[0]) } view.remove: Transition { ParallelAnimation { NumberAnimation { property: "scale"; to: 0.5; duration: Kirigami.Units.longDuration } NumberAnimation { property: "opacity"; to: 0.0; duration: Kirigami.Units.longDuration } } } view.removeDisplaced: Transition { SequentialAnimation { // wait for the "remove" animation to finish PauseAnimation { duration: Kirigami.Units.longDuration } NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration } } } 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.round(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.iconsModel.selectedTheme = model.themeName; } view.forceActiveFocus(); } } footer: ColumnLayout { Kirigami.InlineMessage { id: infoLabel Layout.fillWidth: true showCloseButton: true Connections { target: kcm onShowSuccessMessage: { infoLabel.type = Kirigami.MessageType.Positive; infoLabel.text = message; infoLabel.visible = true; } onShowErrorMessage: { 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 QtControls.Button { id: iconSizesButton text: i18n("Configure Icon Sizes") icon.name: "transform-scale" // proper icon? checkable: true checked: iconSizePopupLoader.item && iconSizePopupLoader.item.opened onClicked: { iconSizePopupLoader.active = true; iconSizePopupLoader.item.open(); } } Item { Layout.fillWidth: true } QtControls.Button { id: installFromFileButton text: i18n("Install from File...") icon.name: "document-import" onClicked: fileDialogLoader.active = true } QtControls.Button { text: i18n("Get New Themes...") icon.name: "get-hot-new-stuff" onClicked: kcm.getNewStuff(this) + visible: KAuthorized.authorize("ghns") } } } 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 } } } } diff --git a/kcms/ksplash/package/contents/ui/main.qml b/kcms/ksplash/package/contents/ui/main.qml index 66460d027..1ae852a21 100644 --- a/kcms/ksplash/package/contents/ui/main.qml +++ b/kcms/ksplash/package/contents/ui/main.qml @@ -1,66 +1,68 @@ /* Copyright (c) 2014 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.0 as QtControls import org.kde.kirigami 2.4 as Kirigami +import org.kde.kconfig 1.0 // for KAuthorized import org.kde.kcm 1.1 as KCM KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module lets you configure the splash screen theme.") view.model: kcm.splashModel //NOTE: pay attention to never break this binding view.currentIndex: kcm.selectedPluginIndex view.delegate: KCM.GridDelegate { id: delegate text: model.display toolTip: model.description thumbnailAvailable: !!model.screenshot thumbnail: Image { anchors.fill: parent source: model.screenshot || "" } actions: [ Kirigami.Action { visible: model.pluginName != "None" iconName: "media-playback-start" tooltip: i18n("Test Splashscreen") onTriggered: kcm.test(model.pluginName) } ] onClicked: { kcm.selectedPlugin = model.pluginName; view.forceActiveFocus(); } } footer: RowLayout { Item { Layout.fillWidth: true } QtControls.Button { iconName: "get-hot-new-stuff" text: i18n("&Get New Theme...") onClicked: kcm.getNewClicked(); + visible: KAuthorized.authorize("ghns") } } } diff --git a/kcms/lookandfeel/package/contents/ui/main.qml b/kcms/lookandfeel/package/contents/ui/main.qml index 168948b0c..dd2edcca8 100644 --- a/kcms/lookandfeel/package/contents/ui/main.qml +++ b/kcms/lookandfeel/package/contents/ui/main.qml @@ -1,116 +1,118 @@ /* Copyright (c) 2018 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.6 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami +import org.kde.kconfig 1.0 // for KAuthorized import org.kde.kcm 1.1 as KCM KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module lets you configure the look and feel theme.") view.model: kcm.lookAndFeelModel view.currentIndex: kcm.selectedPluginIndex view.delegate: KCM.GridDelegate { id: delegate text: model.display toolTip: model.description thumbnailAvailable: model.screenshot thumbnail: Image { anchors.fill: parent source: model.screenshot || "" } actions: [ Kirigami.Action { visible: model.fullScreenPreview != "" iconName: "media-playback-start" tooltip: i18n("Preview Theme") onTriggered: { previewWindow.url = model.fullScreenPreview; previewWindow.showFullScreen(); } } ] onClicked: { kcm.selectedPlugin = model.pluginName; view.forceActiveFocus(); resetCheckbox.checked = false; } } footer: ColumnLayout { Kirigami.InlineMessage { Layout.fillWidth: true type: Kirigami.MessageType.Warning text: i18n("Your desktop layout will be lost and reset to the default layout provided by the selected theme.") visible: resetCheckbox.checked } RowLayout { Layout.fillWidth: true QtControls.CheckBox { id: resetCheckbox checked: kcm.resetDefaultLayout text: i18n("Use Desktop Layout from theme") onCheckedChanged: kcm.resetDefaultLayout = checked; } Item { Layout.fillWidth: true } QtControls.Button { text: i18n("Get New Looks...") icon.name: "get-hot-new-stuff" onClicked: kcm.getNewStuff(this); + visible: KAuthorized.authorize("ghns") } } } Window { id: previewWindow property alias url: previewImage.source color: Qt.rgba(0, 0, 0, 0.7) MouseArea { anchors.fill: parent Image { id: previewImage anchors.centerIn: parent fillMode: Image.PreserveAspectFit width: Math.min(parent.width, sourceSize.width) height: Math.min(parent.height, sourceSize.height) } onClicked: previewWindow.visible = false; QtControls.ToolButton { anchors { top: parent.top right: parent.right } icon.name: "window-close" onClicked: previewWindow.visible = false; } Shortcut { onActivated: previewWindow.visible = false; sequence: "Esc" } } } }