diff --git a/applets/pager/plugin/windowmodel.cpp b/applets/pager/plugin/windowmodel.cpp index 93273bb11..bcda333f7 100644 --- a/applets/pager/plugin/windowmodel.cpp +++ b/applets/pager/plugin/windowmodel.cpp @@ -1,147 +1,147 @@ /******************************************************************** Copyright 2016 Eike Hein 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) any later version. 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *********************************************************************/ #include "windowmodel.h" #include "pagermodel.h" #include #include #include #include #include #include using namespace TaskManager; class WindowModel::Private { public: Private(WindowModel *q); PagerModel *pagerModel = nullptr; private: WindowModel *q; }; WindowModel::Private::Private(WindowModel *q) : q(q) { } WindowModel::WindowModel(PagerModel *parent) : TaskFilterProxyModel(parent) , d(new Private(this)) { d->pagerModel = parent; } WindowModel::~WindowModel() { } QHash WindowModel::roleNames() const { QHash roles = TaskFilterProxyModel::roleNames(); QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("WindowModelRoles")); for (int i = 0; i < e.keyCount(); ++i) { roles.insert(e.value(i), e.key(i)); } return roles; } QVariant WindowModel::data(const QModelIndex &index, int role) const { if (role == AbstractTasksModel::Geometry) { QRect windowGeo = TaskFilterProxyModel::data(index, role).toRect(); QList screens = QGuiApplication::screens(); - const QRect desktopGeo = screens.at(0)->geometry(); + const QRect desktopGeo = screens.at(0)->virtualGeometry(); if (KWindowSystem::mapViewport()) { int x = windowGeo.center().x() % desktopGeo.width(); int y = windowGeo.center().y() % desktopGeo.height(); if (x < 0) { x = x + desktopGeo.width(); } if (y < 0) { y = y + desktopGeo.height(); } const QRect mappedGeo(x - windowGeo.width() / 2, y - windowGeo.height() / 2, windowGeo.width(), windowGeo.height()); if (filterByScreen() && screenGeometry().isValid()) { const QPoint &screenOffset = screenGeometry().topLeft(); windowGeo = mappedGeo.translated(0 - screenOffset.x(), 0 - screenOffset.y()); } } else if (filterByScreen() && screenGeometry().isValid()) { const QPoint &screenOffset = screenGeometry().topLeft(); windowGeo.translate(0 - screenOffset.x(), 0 - screenOffset.y()); } // Clamp to desktop rect. // TODO: Switch from qBound to std::clamp once we use C++17. windowGeo.setX(qBound(0, windowGeo.x(), desktopGeo.width())); windowGeo.setY(qBound(0, windowGeo.y(), desktopGeo.height())); if ((windowGeo.x() + windowGeo.width()) > desktopGeo.width()) { windowGeo.setWidth(desktopGeo.width() - windowGeo.x()); } if ((windowGeo.y() + windowGeo.height()) > desktopGeo.height()) { windowGeo.setHeight(desktopGeo.height() - windowGeo.y()); } return windowGeo; } else if (role == StackingOrder) { #if HAVE_X11 const QVariantList &winIds = TaskFilterProxyModel::data(index, AbstractTasksModel::WinIdList).toList(); if (winIds.count()) { const WId winId = winIds.at(0).toLongLong(); const int z = d->pagerModel->stackingOrder().indexOf(winId); if (z != -1) { return z; } } #endif return 0; } return TaskFilterProxyModel::data(index, role); } void WindowModel::refreshStackingOrder() { if (rowCount()) { emit dataChanged(index(0, 0), index(rowCount() - 1, 0), QVector{StackingOrder}); } } diff --git a/kcms/colors/package/contents/ui/main.qml b/kcms/colors/package/contents/ui/main.qml index 107d8e0e2..834356eaf 100644 --- a/kcms/colors/package/contents/ui/main.qml +++ b/kcms/colors/package/contents/ui/main.qml @@ -1,378 +1,378 @@ /* * 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.6 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.kconfig 1.0 // for KAuthorized import org.kde.kcm 1.1 as KCM import org.kde.private.kcms.colors 1.0 as Private KCM.GridViewKCM { id: root KCM.ConfigModule.quickHelp: i18n("This module lets you choose the color scheme.") view.model: kcm.filteredModel view.currentIndex: kcm.filteredModel.selectedSchemeIndex Binding { target: kcm.filteredModel property: "query" value: searchField.text } Binding { target: kcm.filteredModel property: "filter" value: filterCombo.model[filterCombo.currentIndex].filter } enabled: !kcm.downloadingFile && !kcm.colorsSettings.isImmutable("colorScheme") Component.onCompleted: { // The thumbnails are a bit more elaborate and need more room, especially when translated view.implicitCellWidth = Kirigami.Units.gridUnit * 13; - view.implicitCellHeight = Kirigami.Units.gridUnit * 11; + view.implicitCellHeight = Kirigami.Units.gridUnit * 12; } DropArea { anchors.fill: parent onEntered: { if (!drag.hasUrls) { drag.accepted = false; } } onDropped: { infoLabel.visible = false; kcm.installSchemeFromFile(drop.urls[0]); } } // putting the InlineMessage as header item causes it to show up initially despite visible false header: ColumnLayout { Kirigami.InlineMessage { id: notInstalledWarning Layout.fillWidth: true type: Kirigami.MessageType.Warning showCloseButton: true visible: false Connections { target: kcm onShowSchemeNotInstalledWarning: { notInstalledWarning.text = i18n("The color scheme '%1' is not installed. Selecting the default theme instead.", schemeName) notInstalledWarning.visible = true; } } } RowLayout { Layout.fillWidth: true QtControls.TextField { id: searchField Layout.fillWidth: true placeholderText: i18n("Search...") leftPadding: LayoutMirroring.enabled ? clearButton.width : undefined rightPadding: LayoutMirroring.enabled ? undefined : clearButton.width // this could be useful as a component MouseArea { id: clearButton anchors { top: parent.top topMargin: parent.topPadding right: parent.right // the TextField's padding is taking into account the clear button's size // so we just use the opposite one for positioning the clear button rightMargin: LayoutMirroring.enabled ? parent.rightPadding: parent.leftPadding bottom: parent.bottom bottomMargin: parent.bottomPadding } width: height opacity: searchField.length > 0 ? 1 : 0 onClicked: searchField.clear() Kirigami.Icon { anchors.fill: parent active: parent.pressed source: "edit-clear-locationbar-" + (LayoutMirroring.enabled ? "ltr" : "rtl") } Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } } } } QtControls.ComboBox { id: filterCombo textRole: "text" model: [ {text: i18n("All Schemes"), filter: Private.KCM.AllSchemes}, {text: i18n("Light Schemes"), filter: Private.KCM.LightSchemes}, {text: i18n("Dark Schemes"), filter: Private.KCM.DarkSchemes} ] // HACK QQC2 doesn't support icons, so we just tamper with the desktop style ComboBox's background // and inject a nice little filter icon. Component.onCompleted: { if (!background || !background.hasOwnProperty("properties")) { // not a KQuickStyleItem return; } var props = background.properties || {}; background.properties = Qt.binding(function() { var newProps = props; newProps.currentIcon = "view-filter"; newProps.iconColor = Kirigami.Theme.textColor; return newProps; }); } } } } view.delegate: KCM.GridDelegate { id: delegate text: model.display thumbnailAvailable: true thumbnail: Rectangle { anchors.fill: parent opacity: model.pendingDeletion ? 0.3 : 1 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } } color: model.palette.window Kirigami.Theme.highlightColor: model.palette.highlight Kirigami.Theme.highlightedTextColor: model.palette.highlightedText Kirigami.Theme.linkColor: model.palette.link Kirigami.Theme.textColor: model.palette.text Rectangle { id: windowTitleBar width: parent.width height: Math.round(Kirigami.Units.gridUnit * 1.5) gradient: Gradient { // from Breeze Decoration::paintTitleBar GradientStop { position: 0.0; color: Qt.lighter(model.activeTitleBarBackground, 1.2) } GradientStop { position: 0.8; color: model.activeTitleBarBackground } } color: model.activeTitleBarBackground QtControls.Label { anchors { fill: parent leftMargin: Kirigami.Units.smallSpacing rightMargin: Kirigami.Units.smallSpacing } horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter color: model.activeTitleBarForeground text: i18n("Window Title") elide: Text.ElideRight } } ColumnLayout { anchors { left: parent.left right: parent.right top: windowTitleBar.bottom bottom: parent.bottom margins: Kirigami.Units.smallSpacing } RowLayout { Layout.fillWidth: true QtControls.Label { Layout.fillWidth: true Layout.fillHeight: true verticalAlignment: Text.AlignVCenter text: i18n("Window text") elide: Text.ElideRight color: model.palette.windowText } QtControls.Button { Layout.alignment: Qt.AlignBottom text: i18n("Button") Kirigami.Theme.backgroundColor: model.palette.button Kirigami.Theme.textColor: model.palette.buttonText activeFocusOnTab: false } } QtControls.Frame { Layout.fillWidth: true Layout.fillHeight: true Kirigami.Theme.backgroundColor: model.palette.base // FIXME Make Frame still visible but without any inner padding padding: 1 activeFocusOnTab: false Column { id: listPreviewColumn readonly property string demoText: " %2 %4" .arg(i18nc("Hyperlink", "link")) .arg(model.palette.linkVisited) .arg(i18nc("Visited hyperlink", "visited")) width: parent.width QtControls.ItemDelegate { width: parent.width text: i18n("Normal text") + listPreviewColumn.demoText activeFocusOnTab: false } QtControls.ItemDelegate { width: parent.width highlighted: true // TODO use proper highlighted link color text: i18n("Highlighted text") + listPreviewColumn.demoText activeFocusOnTab: false } QtControls.ItemDelegate { width: parent.width enabled: false text: i18n("Disabled text") + listPreviewColumn.demoText activeFocusOnTab: false } } } } // Make the preview non-clickable but still reacting to hover MouseArea { anchors.fill: parent onClicked: delegate.clicked() onDoubleClicked: delegate.doubleClicked() } } actions: [ Kirigami.Action { iconName: "document-edit" tooltip: i18n("Edit Color Scheme...") enabled: !model.pendingDeletion onTriggered: kcm.editScheme(model.schemeName, root) }, Kirigami.Action { iconName: "edit-delete" tooltip: i18n("Remove Color Scheme") enabled: model.removable visible: !model.pendingDeletion onTriggered: model.pendingDeletion = true }, Kirigami.Action { iconName: "edit-undo" tooltip: i18n("Restore Color Scheme") visible: model.pendingDeletion onTriggered: model.pendingDeletion = false } ] onClicked: { kcm.model.selectedScheme = model.schemeName; view.forceActiveFocus(); } onDoubleClicked: { kcm.save(); } } 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; // Avoid dual message widgets notInstalledWarning.visible = false; } onShowErrorMessage: { infoLabel.type = Kirigami.MessageType.Error; infoLabel.text = message; infoLabel.visible = true; notInstalledWarning.visible = false; } } } 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 Color Schemes...") icon.name: "get-hot-new-stuff" onClicked: kcm.getNewStuff(this) visible: KAuthorized.authorize("ghns") } } } Loader { id: fileDialogLoader active: false sourceComponent: QtDialogs.FileDialog { title: i18n("Open Color Scheme") folder: shortcuts.home nameFilters: [ i18n("Color Scheme Files (*.colors)") ] Component.onCompleted: open() onAccepted: { infoLabel.visible = false; kcm.installSchemeFromFile(fileUrls[0]) fileDialogLoader.active = false } onRejected: { fileDialogLoader.active = false } } } }