diff --git a/applets/kicker/package/contents/ui/ActionMenu.qml b/applets/kicker/package/contents/ui/ActionMenu.qml index 5109aef67..7163b7489 100644 --- a/applets/kicker/package/contents/ui/ActionMenu.qml +++ b/applets/kicker/package/contents/ui/ActionMenu.qml @@ -1,138 +1,138 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents Item { id: root property QtObject menu property Item visualParent property variant actionList - property bool opened: menu ? (menu.status != PlasmaComponents.DialogStatus.Closed) : false + property bool opened: menu ? (menu.status !== PlasmaComponents.DialogStatus.Closed) : false signal actionClicked(string actionId, variant actionArgument) signal closed onActionListChanged: refreshMenu(); onOpenedChanged: { if (!opened) { closed(); } } function open(x, y) { if (!actionList) { return; } if (x && y) { menu.open(x, y); } else { menu.open(); } } function refreshMenu() { if (menu) { menu.destroy(); } if (!actionList) { return; } menu = contextMenuComponent.createObject(root); fillMenu(menu, actionList); } function fillMenu(menu, items) { items.forEach(function(actionItem) { if (actionItem.subActions) { // This is a menu var submenuItem = contextSubmenuItemComponent.createObject( menu, { "actionItem" : actionItem }); fillMenu(submenuItem.submenu, actionItem.subActions); } else { var item = contextMenuItemComponent.createObject( menu, { "actionItem": actionItem, } ); } }); } Component { id: contextMenuComponent PlasmaComponents.ContextMenu { visualParent: root.visualParent } } Component { id: contextSubmenuItemComponent PlasmaComponents.MenuItem { id: submenuItem property variant actionItem text: actionItem.text ? actionItem.text : "" icon: actionItem.icon ? actionItem.icon : null property variant submenu : submenu_ PlasmaComponents.ContextMenu { id: submenu_ visualParent: submenuItem.action } } } Component { id: contextMenuItemComponent PlasmaComponents.MenuItem { property variant actionItem text : actionItem.text ? actionItem.text : "" - enabled : actionItem.type != "title" && ("enabled" in actionItem ? actionItem.enabled : true) - separator : actionItem.type == "separator" - section : actionItem.type == "title" + enabled : actionItem.type !== "title" && ("enabled" in actionItem ? actionItem.enabled : true) + separator : actionItem.type === "separator" + section : actionItem.type === "title" icon : actionItem.icon ? actionItem.icon : null checkable : actionItem.checkable ? actionItem.checkable : false checked : actionItem.checked ? actionItem.checked : false onClicked: { actionClicked(actionItem.actionId, actionItem.actionArgument); } } } } diff --git a/applets/kicker/package/contents/ui/CompactRepresentation.qml b/applets/kicker/package/contents/ui/CompactRepresentation.qml index 2e5b285a0..fde5a9af3 100644 --- a/applets/kicker/package/contents/ui/CompactRepresentation.qml +++ b/applets/kicker/package/contents/ui/CompactRepresentation.qml @@ -1,130 +1,130 @@ /*************************************************************************** * Copyright (C) 2013-2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore Item { id: root - readonly property bool inPanel: (plasmoid.location == PlasmaCore.Types.TopEdge - || plasmoid.location == PlasmaCore.Types.RightEdge - || plasmoid.location == PlasmaCore.Types.BottomEdge - || plasmoid.location == PlasmaCore.Types.LeftEdge) - readonly property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) + readonly property bool inPanel: (plasmoid.location === PlasmaCore.Types.TopEdge + || plasmoid.location === PlasmaCore.Types.RightEdge + || plasmoid.location === PlasmaCore.Types.BottomEdge + || plasmoid.location === PlasmaCore.Types.LeftEdge) + readonly property bool vertical: (plasmoid.formFactor === PlasmaCore.Types.Vertical) readonly property bool useCustomButtonImage: (plasmoid.configuration.useCustomButtonImage - && plasmoid.configuration.customButtonImage.length != 0) + && plasmoid.configuration.customButtonImage.length !== 0) property QtObject dashWindow: null onWidthChanged: updateSizeHints() onHeightChanged: updateSizeHints() onDashWindowChanged: { if (dashWindow) { dashWindow.visualParent = root; } } function updateSizeHints() { if (useCustomButtonImage) { if (vertical) { var scaledHeight = Math.floor(parent.width * (buttonIcon.implicitHeight / buttonIcon.implicitWidth)); root.Layout.minimumHeight = scaledHeight; root.Layout.maximumHeight = scaledHeight; root.Layout.minimumWidth = units.iconSizes.small; root.Layout.maximumWidth = inPanel ? units.iconSizeHints.panel : -1; } else { var scaledWidth = Math.floor(parent.height * (buttonIcon.implicitWidth / buttonIcon.implicitHeight)); root.Layout.minimumWidth = scaledWidth; root.Layout.maximumWidth = scaledWidth; root.Layout.minimumHeight = units.iconSizes.small; root.Layout.maximumHeight = inPanel ? units.iconSizeHints.panel : -1; } } else { root.Layout.minimumWidth = units.iconSizes.small; root.Layout.maximumWidth = inPanel ? units.iconSizeHints.panel : -1; root.Layout.minimumHeight = units.iconSizes.small; root.Layout.maximumHeight = inPanel ? units.iconSizeHints.panel : -1; } } Connections { target: units.iconSizeHints onPanelChanged: updateSizeHints() } PlasmaCore.IconItem { id: buttonIcon anchors.fill: parent readonly property double aspectRatio: (vertical ? implicitHeight / implicitWidth : implicitWidth / implicitHeight) source: useCustomButtonImage ? plasmoid.configuration.customButtonImage : plasmoid.configuration.icon active: mouseArea.containsMouse && !justOpenedTimer.running smooth: true // A custom icon could also be rectangular. However, if a square, custom, icon is given, assume it // to be an icon and round it to the nearest icon size again to avoid scaling artifacts. roundToIconSize: !useCustomButtonImage || aspectRatio === 1 onSourceChanged: updateSizeHints() } MouseArea { id: mouseArea property bool wasExpanded: false; anchors.fill: parent hoverEnabled: !dashWindow || !dashWindow.visible onPressed: { if (!isDash) { wasExpanded = plasmoid.expanded } } onClicked: { if (isDash) { dashWindow.toggle(); justOpenedTimer.start(); } else { plasmoid.expanded = !wasExpanded; } } } Component.onCompleted: { if (isDash) { dashWindow = Qt.createQmlObject("DashboardRepresentation {}", root); plasmoid.activated.connect(function() { dashWindow.toggle() justOpenedTimer.start() }) } } } diff --git a/applets/kicker/package/contents/ui/ConfigGeneral.qml b/applets/kicker/package/contents/ui/ConfigGeneral.qml index 7fc3bebed..c0e13d4f3 100644 --- a/applets/kicker/package/contents/ui/ConfigGeneral.qml +++ b/applets/kicker/package/contents/ui/ConfigGeneral.qml @@ -1,275 +1,275 @@ /*************************************************************************** * Copyright (C) 2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Controls 1.0 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons import org.kde.draganddrop 2.0 as DragDrop import org.kde.plasma.private.kicker 0.1 as Kicker Item { id: configGeneral width: childrenRect.width height: childrenRect.height - property bool isDash: (plasmoid.pluginName == "org.kde.plasma.kickerdash") + property bool isDash: (plasmoid.pluginName === "org.kde.plasma.kickerdash") property string cfg_icon: plasmoid.configuration.icon property bool cfg_useCustomButtonImage: plasmoid.configuration.useCustomButtonImage property string cfg_customButtonImage: plasmoid.configuration.customButtonImage property alias cfg_appNameFormat: appNameFormat.currentIndex property alias cfg_limitDepth: limitDepth.checked property alias cfg_alphaSort: alphaSort.checked property alias cfg_recentOrdering: recentOrdering.currentIndex property alias cfg_showRecentApps: showRecentApps.checked property alias cfg_showRecentDocs: showRecentDocs.checked property alias cfg_showRecentContacts: showRecentContacts.checked property alias cfg_useExtraRunners: useExtraRunners.checked property alias cfg_alignResultsToBottom: alignResultsToBottom.checked ColumnLayout { anchors.left: parent.left RowLayout { spacing: units.smallSpacing Label { text: i18n("Icon:") } Button { id: iconButton Layout.minimumWidth: previewFrame.width + units.smallSpacing * 2 Layout.maximumWidth: Layout.minimumWidth Layout.minimumHeight: previewFrame.height + units.smallSpacing * 2 Layout.maximumHeight: Layout.minimumWidth DragDrop.DropArea { id: dropArea property bool containsAcceptableDrag: false anchors.fill: parent onDragEnter: { // Cannot use string operations (e.g. indexOf()) on "url" basic type. var urlString = event.mimeData.url.toString(); // This list is also hardcoded in KIconDialog. var extensions = [".png", ".xpm", ".svg", ".svgz"]; containsAcceptableDrag = urlString.indexOf("file:///") === 0 && extensions.some(function (extension) { return urlString.indexOf(extension) === urlString.length - extension.length; // "endsWith" }); if (!containsAcceptableDrag) { event.ignore(); } } onDragLeave: containsAcceptableDrag = false onDrop: { if (containsAcceptableDrag) { // Strip file:// prefix, we already verified in onDragEnter that we have only local URLs. iconDialog.setCustomButtonImage(event.mimeData.url.toString().substr("file://".length)); } containsAcceptableDrag = false; } } KQuickAddons.IconDialog { id: iconDialog function setCustomButtonImage(image) { cfg_customButtonImage = image || cfg_icon || "start-here-kde" cfg_useCustomButtonImage = true; } onIconNameChanged: setCustomButtonImage(iconName); } // just to provide some visual feedback, cannot have checked without checkable enabled checkable: true checked: dropArea.containsAcceptableDrag onClicked: { checked = Qt.binding(function() { // never actually allow it being checked return iconMenu.status === PlasmaComponents.DialogStatus.Open || dropArea.containsAcceptableDrag; }) iconMenu.open(0, height) } PlasmaCore.FrameSvgItem { id: previewFrame anchors.centerIn: parent imagePath: plasmoid.location === PlasmaCore.Types.Vertical || plasmoid.location === PlasmaCore.Types.Horizontal ? "widgets/panel-background" : "widgets/background" width: units.iconSizes.large + fixedMargins.left + fixedMargins.right height: units.iconSizes.large + fixedMargins.top + fixedMargins.bottom PlasmaCore.IconItem { anchors.centerIn: parent width: units.iconSizes.large height: width source: cfg_useCustomButtonImage ? cfg_customButtonImage : cfg_icon } } } // QQC Menu can only be opened at cursor position, not a random one PlasmaComponents.ContextMenu { id: iconMenu visualParent: iconButton PlasmaComponents.MenuItem { text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...") icon: "document-open-folder" onClicked: iconDialog.open() } PlasmaComponents.MenuItem { text: i18nc("@item:inmenu Reset icon to default", "Clear Icon") icon: "edit-clear" onClicked: { cfg_useCustomButtonImage = false; } } } } GroupBox { Layout.fillWidth: true title: i18n("Behavior") flat: true ColumnLayout { RowLayout { Label { text: i18n("Show applications as:") } ComboBox { id: appNameFormat Layout.fillWidth: true model: [i18n("Name only"), i18n("Description only"), i18n("Name (Description)"), i18n("Description (Name)")] } } CheckBox { id: limitDepth visible: !isDash text: i18n("Flatten menu to a single level") } CheckBox { id: alphaSort text: i18n("Sort alphabetically") } } } GroupBox { Layout.fillWidth: true title: i18n("Categories") flat: true ColumnLayout { RowLayout { Label { text: i18n("Show:") } ComboBox { id: recentOrdering Layout.fillWidth: true model: [i18n("Recently used"), i18n("Often used")] } } CheckBox { id: showRecentApps text: recentOrdering.currentIndex == 0 ? i18n("Show recent applications") : i18n("Show often used applications") } CheckBox { id: showRecentDocs text: recentOrdering.currentIndex == 0 ? i18n("Show recent documents") : i18n("Show often used documents") } CheckBox { id: showRecentContacts text: recentOrdering.currentIndex == 0 ? i18n("Show recent contacts") : i18n("Show often used contacts") } } } GroupBox { Layout.fillWidth: true title: i18n("Search") flat: true ColumnLayout { CheckBox { id: useExtraRunners text: i18n("Expand search to bookmarks, files and emails") } CheckBox { id: alignResultsToBottom visible: !isDash text: i18n("Align search results to bottom") } } } } } diff --git a/applets/kicker/package/contents/ui/DashboardRepresentation.qml b/applets/kicker/package/contents/ui/DashboardRepresentation.qml index 7f1afa283..20a086618 100644 --- a/applets/kicker/package/contents/ui/DashboardRepresentation.qml +++ b/applets/kicker/package/contents/ui/DashboardRepresentation.qml @@ -1,1070 +1,1070 @@ /*************************************************************************** * Copyright (C) 2015 by 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 . * ***************************************************************************/ import QtQuick 2.4 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.1 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 import org.kde.kwindowsystem 1.0 import org.kde.plasma.private.shell 2.0 import org.kde.plasma.private.kicker 0.1 as Kicker import "code/tools.js" as Tools /* TODO * Reverse middleRow layout + keyboard nav + filter list text alignment in rtl locales. * Keep cursor column when arrow'ing down past non-full trailing rows into a lower grid. * Make DND transitions cleaner by performing an item swap instead of index reinsertion. */ Kicker.DashboardWindow { id: root property bool smallScreen: ((Math.floor(width / units.iconSizes.huge) <= 22) || (Math.floor(height / units.iconSizes.huge) <= 14)) property int iconSize: smallScreen ? units.iconSizes.large : units.iconSizes.huge property int cellSize: iconSize + theme.mSize(theme.defaultFont).height + (2 * units.smallSpacing) + (2 * Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom, highlightItemSvg.margins.left + highlightItemSvg.margins.right)) property int columns: Math.floor(((smallScreen ? 85 : 80)/100) * Math.ceil(width / cellSize)) property bool searching: (searchField.text != "") property var widgetExplorer: null keyEventProxy: searchField backgroundColor: Qt.rgba(0, 0, 0, 0.737) onKeyEscapePressed: { if (searching) { searchField.clear(); } else { root.toggle(); } } onVisibleChanged: { tabBar.activeTab = 0; reset(); if (visible) { preloadAllAppsTimer.restart(); } } onSearchingChanged: { if (!searching) { reset(); } else { filterList.currentIndex = -1; if (tabBar.activeTab == 1) { widgetExplorer.widgetsModel.filterQuery = ""; widgetExplorer.widgetsModel.filterType = ""; } } } function reset() { searchField.clear(); globalFavoritesGrid.currentIndex = -1; systemFavoritesGrid.currentIndex = -1; filterList.currentIndex = 0; funnelModel.sourceModel = rootModel.modelForRow(0); mainGrid.model = (tabBar.activeTab == 0) ? funnelModel : root.widgetExplorer.widgetsModel; mainGrid.currentIndex = -1; filterListScrollArea.focus = true; filterList.model = (tabBar.activeTab == 0) ? rootModel : root.widgetExplorer.filterModel; } function updateWidgetExplorer() { if (tabBar.activeTab == 1 /* Widgets */ || tabBar.hoveredTab == 1) { if (!root.widgetExplorer) { root.widgetExplorer = widgetExplorerComponent.createObject(root, { containment: containmentInterface.screenContainment(plasmoid) }); } } else if (root.widgetExplorer) { root.widgetExplorer.destroy(); root.widgetExplorer = null; } } mainItem: MouseArea { id: rootItem anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft LayoutMirroring.childrenInherit: true Connections { target: kicker onReset: { if (!searching) { filterList.applyFilter(); if (tabBar.activeTab == 0) { funnelModel.reset(); } } } onDragSourceChanged: { if (!dragSource) { // FIXME TODO HACK: Reset all views post-DND to work around // mouse grab bug despite QQuickWindow::mouseGrabberItem==0x0. // Needs a more involved hunt through Qt Quick sources later since // it's not happening with near-identical code in the menu repr. rootModel.refresh(); } else if (tabBar.activeTab == 1) { root.toggle(); containmentInterface.ensureMutable(containmentInterface.screenContainment(plasmoid)); kwindowsystem.showingDesktop = true; } } } KWindowSystem { id: kwindowsystem } Component { id: widgetExplorerComponent WidgetExplorer { showSpecialFilters: false } } Connections { target: plasmoid onUserConfiguringChanged: { if (plasmoid.userConfiguring) { root.hide() } } } PlasmaComponents.Menu { id: contextMenu PlasmaComponents.MenuItem { action: plasmoid.action("configure") } } PlasmaExtras.Heading { id: dummyHeading visible: false width: 0 level: 1 } TextMetrics { id: headingMetrics font: dummyHeading.font } Kicker.FunnelModel { id: funnelModel onSourceModelChanged: { if (mainColumn.visible) { mainGrid.currentIndex = -1; mainGrid.forceLayout(); } } } Timer { id: preloadAllAppsTimer property bool done: false interval: 1000 repeat: false onTriggered: { if (done || searching) { return; } for (var i = 0; i < rootModel.count; ++i) { var model = rootModel.modelForRow(i); - if (model.description == "KICKER_ALL_MODEL") { + if (model.description === "KICKER_ALL_MODEL") { allAppsGrid.model = model; done = true; break; } } } function defer() { if (running && !done) { restart(); } } } Kicker.ContainmentInterface { id: containmentInterface } DashboardTabBar { id: tabBar y: 0 anchors.horizontalCenter: parent.horizontalCenter visible: (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) onActiveTabChanged: { updateWidgetExplorer(); reset(); } onHoveredTabChanged: updateWidgetExplorer() Keys.onDownPressed: { mainColumn.tryActivate(0, 0); } } PlasmaComponents.TextField { id: searchField width: 0 height: 0 visible: false onTextChanged: { if (tabBar.activeTab == 0) { runnerModel.query = searchField.text; } else { widgetExplorer.widgetsModel.searchTerm = searchField.text; } } function clear() { text = ""; } } PlasmaExtras.Heading { id: searchHeading anchors { horizontalCenter: parent.horizontalCenter } y: (middleRow.anchors.topMargin / 2) - (smallScreen ? (height/10) : 0) font.pointSize: dummyHeading.font.pointSize * 1.5 elide: Text.ElideRight wrapMode: Text.NoWrap opacity: 1.0 color: "white" level: 1 text: searching ? i18n("Searching for '%1'", searchField.text) : i18n("Type to search.") } PlasmaComponents.ToolButton { id: cancelSearchButton anchors { left: searchHeading.right leftMargin: units.largeSpacing verticalCenter: searchHeading.verticalCenter } width: units.iconSizes.large height: width visible: (searchField.text != "") iconName: "dialog-close" flat: false onClicked: searchField.clear(); Keys.onPressed: { - if (event.key == Qt.Key_Tab) { + if (event.key === Qt.Key_Tab) { event.accepted = true; if (runnerModel.count) { mainColumn.tryActivate(0, 0); } else { systemFavoritesGrid.tryActivate(0, 0); } - } else if (event.key == Qt.Key_Backtab) { + } else if (event.key === Qt.Key_Backtab) { event.accepted = true; if (tabBar.visible) { tabBar.focus = true; } else if (globalFavoritesGrid.enabled) { globalFavoritesGrid.tryActivate(0, 0); } else { systemFavoritesGrid.tryActivate(0, 0); } } } } Row { id: middleRow anchors { top: parent.top topMargin: units.gridUnit * (smallScreen ? 8 : 10) bottom: parent.bottom bottomMargin: (units.gridUnit * 2) horizontalCenter: parent.horizontalCenter } width: (root.columns * cellSize) + (2 * spacing) spacing: units.gridUnit * 2 Item { id: favoritesColumn anchors { top: parent.top bottom: parent.bottom } width: (columns * cellSize) + units.gridUnit property int columns: 3 PlasmaExtras.Heading { id: favoritesColumnLabel enabled: (tabBar.activeTab == 0) anchors { top: parent.top } x: units.smallSpacing width: parent.width - x elide: Text.ElideRight wrapMode: Text.NoWrap color: "white" level: 1 text: i18n("Favorites") opacity: (enabled ? 1.0 : 0.3) Behavior on opacity { SmoothedAnimation { duration: units.longDuration; velocity: 0.01 } } } PlasmaCore.SvgItem { id: favoritesColumnLabelUnderline enabled: (tabBar.activeTab == 0) anchors { top: favoritesColumnLabel.bottom } width: parent.width - units.gridUnit height: lineSvg.horLineHeight svg: lineSvg elementId: "horizontal-line" opacity: (enabled ? 1.0 : 0.3) Behavior on opacity { SmoothedAnimation { duration: units.longDuration; velocity: 0.01 } } } ItemGridView { id: globalFavoritesGrid enabled: (tabBar.activeTab == 0) anchors { top: favoritesColumnLabelUnderline.bottom topMargin: units.largeSpacing } property int rows: (Math.floor((parent.height - favoritesColumnLabel.height - favoritesColumnLabelUnderline.height - units.largeSpacing) / cellSize) - systemFavoritesGrid.rows) width: parent.width height: rows * cellSize cellWidth: cellSize cellHeight: cellSize iconSize: root.iconSize model: globalFavorites dropEnabled: true usesPlasmaTheme: false opacity: (enabled ? 1.0 : 0.3) Behavior on opacity { SmoothedAnimation { duration: units.longDuration; velocity: 0.01 } } onCurrentIndexChanged: { preloadAllAppsTimer.defer(); } onKeyNavRight: { mainColumn.tryActivate(currentRow(), 0); } onKeyNavDown: { systemFavoritesGrid.tryActivate(0, currentCol()); } Keys.onPressed: { - if (event.key == Qt.Key_Tab) { + if (event.key === Qt.Key_Tab) { event.accepted = true; if (tabBar.visible) { tabBar.focus = true; } else if (searching) { cancelSearchButton.focus = true; } else { mainColumn.tryActivate(0, 0); } - } else if (event.key == Qt.Key_Backtab) { + } else if (event.key === Qt.Key_Backtab) { event.accepted = true; systemFavoritesGrid.tryActivate(0, 0); } } Binding { target: globalFavorites property: "iconSize" value: root.iconSize } } ItemGridView { id: systemFavoritesGrid anchors { top: globalFavoritesGrid.bottom } property int rows: Math.ceil(count / Math.floor(width / cellSize)) width: parent.width height: rows * cellSize cellWidth: cellSize cellHeight: cellSize iconSize: root.iconSize model: systemFavorites dropEnabled: true usesPlasmaTheme: true onCurrentIndexChanged: { preloadAllAppsTimer.defer(); } onKeyNavRight: { mainColumn.tryActivate(globalFavoritesGrid.rows + currentRow(), 0); } onKeyNavUp: { globalFavoritesGrid.tryActivate(globalFavoritesGrid.rows - 1, currentCol()); } Keys.onPressed: { - if (event.key == Qt.Key_Tab) { + if (event.key === Qt.Key_Tab) { event.accepted = true; if (globalFavoritesGrid.enabled) { globalFavoritesGrid.tryActivate(0, 0); } else if (tabBar.visible) { tabBar.focus = true; } else if (searching && !runnerModel.count) { cancelSearchButton.focus = true; } else { mainColumn.tryActivate(0, 0); } - } else if (event.key == Qt.Key_Backtab) { + } else if (event.key === Qt.Key_Backtab) { event.accepted = true; if (filterList.enabled) { filterList.forceActiveFocus(); } else if (searching && !runnerModel.count) { cancelSearchButton.focus = true; } else { mainColumn.tryActivate(0, 0); } } } } } Item { id: mainColumn anchors.top: parent.top width: (columns * cellSize) + units.gridUnit height: Math.floor(parent.height / cellSize) * cellSize + mainGridContainer.headerHeight property int columns: root.columns - favoritesColumn.columns - filterListColumn.columns property Item visibleGrid: mainGrid function tryActivate(row, col) { if (visibleGrid) { visibleGrid.tryActivate(row, col); } } Item { id: mainGridContainer anchors.fill: parent z: (opacity == 1.0) ? 1 : 0 enabled: (opacity == 1.0) ? 1 : 0 property int headerHeight: mainColumnLabel.height + mainColumnLabelUnderline.height + units.largeSpacing opacity: { if (tabBar.activeTab == 0 && searching) { return 0.0; } if (filterList.allApps) { return 0.0; } return 1.0; } onOpacityChanged: { if (opacity == 1.0) { mainColumn.visibleGrid = mainGrid; } } PlasmaExtras.Heading { id: mainColumnLabel anchors { top: parent.top } x: units.smallSpacing width: parent.width - x elide: Text.ElideRight wrapMode: Text.NoWrap opacity: 1.0 color: "white" level: 1 text: (tabBar.activeTab == 0) ? funnelModel.description : i18n("Widgets") } PlasmaCore.SvgItem { id: mainColumnLabelUnderline visible: mainGrid.count anchors { top: mainColumnLabel.bottom } width: parent.width - units.gridUnit height: lineSvg.horLineHeight svg: lineSvg elementId: "horizontal-line" } ItemGridView { id: mainGrid anchors { top: mainColumnLabelUnderline.bottom topMargin: units.largeSpacing } width: parent.width height: systemFavoritesGrid.y + systemFavoritesGrid.height - mainGridContainer.headerHeight cellWidth: (tabBar.activeTab == 0 ? cellSize : cellSize * 2) cellHeight: cellWidth iconSize: (tabBar.activeTab == 0 ? root.iconSize : cellWidth - (units.largeSpacing * 2)) model: funnelModel onCurrentIndexChanged: { preloadAllAppsTimer.defer(); } onKeyNavLeft: { if (tabBar.activeTab == 0) { var row = currentRow(); var target = row + 1 > globalFavoritesGrid.rows ? systemFavoritesGrid : globalFavoritesGrid; var targetRow = row + 1 > globalFavoritesGrid.rows ? row - globalFavoritesGrid.rows : row; target.tryActivate(targetRow, favoritesColumn.columns - 1); } } onKeyNavRight: { filterListScrollArea.focus = true; } onKeyNavUp: { if (tabBar.visible) { tabBar.focus = true; } } onItemActivated: { if (tabBar.activeTab == 1) { containmentInterface.ensureMutable(containmentInterface.screenContainment(plasmoid)); root.widgetExplorer.addApplet(currentItem.m.pluginName); root.toggle(); kwindowsystem.showingDesktop = true; } } } } ItemMultiGridView { id: allAppsGrid anchors { top: parent.top } z: (opacity == 1.0) ? 1 : 0 width: parent.width height: systemFavoritesGrid.y + systemFavoritesGrid.height enabled: (opacity == 1.0) ? 1 : 0 opacity: filterList.allApps ? 1.0 : 0.0 onOpacityChanged: { if (opacity == 1.0) { allAppsGrid.flickableItem.contentY = 0; mainColumn.visibleGrid = allAppsGrid; } } onKeyNavLeft: { var row = 0; for (var i = 0; i < subGridIndex; i++) { row += subGridAt(i).lastRow() + 2; // Header counts as one. } row += subGridAt(subGridIndex).currentRow(); var target = row + 1 > globalFavoritesGrid.rows ? systemFavoritesGrid : globalFavoritesGrid; var targetRow = row + 1 > globalFavoritesGrid.rows ? row - globalFavoritesGrid.rows : row; target.tryActivate(targetRow, favoritesColumn.columns - 1); } onKeyNavRight: { filterListScrollArea.focus = true; } } ItemMultiGridView { id: runnerGrid anchors { top: parent.top } z: (opacity == 1.0) ? 1 : 0 width: parent.width height: Math.min(implicitHeight, systemFavoritesGrid.y + systemFavoritesGrid.height) enabled: (opacity == 1.0) ? 1 : 0 model: runnerModel grabFocus: true opacity: (tabBar.activeTab == 0 && searching) ? 1.0 : 0.0 onOpacityChanged: { if (opacity == 1.0) { mainColumn.visibleGrid = runnerGrid; } } onKeyNavLeft: { var row = 0; for (var i = 0; i < subGridIndex; i++) { row += subGridAt(i).lastRow() + 2; // Header counts as one. } row += subGridAt(subGridIndex).currentRow(); var target = row + 1 > globalFavoritesGrid.rows ? systemFavoritesGrid : globalFavoritesGrid; var targetRow = row + 1 > globalFavoritesGrid.rows ? row - globalFavoritesGrid.rows : row; target.tryActivate(targetRow, favoritesColumn.columns - 1); } } Keys.onPressed: { - if (event.key == Qt.Key_Tab) { + if (event.key === Qt.Key_Tab) { event.accepted = true; if (filterList.enabled) { filterList.forceActiveFocus(); } else { systemFavoritesGrid.tryActivate(0, 0); } - } else if (event.key == Qt.Key_Backtab) { + } else if (event.key === Qt.Key_Backtab) { event.accepted = true; if (searching) { cancelSearchButton.focus = true; } else if (tabBar.visible) { tabBar.focus = true; } else if (globalFavoritesGrid.enabled) { globalFavoritesGrid.tryActivate(0, 0); } else { systemFavoritesGrid.tryActivate(0, 0); } } } } Item { id: filterListColumn anchors { top: parent.top topMargin: mainColumnLabelUnderline.y + mainColumnLabelUnderline.height + units.largeSpacing bottom: parent.bottom } width: columns * cellSize property int columns: 3 PlasmaExtras.ScrollArea { id: filterListScrollArea x: root.visible ? 0 : units.gridUnit Behavior on x { SmoothedAnimation { duration: units.longDuration; velocity: 0.01 } } width: parent.width height: mainGrid.height enabled: !searching property alias currentIndex: filterList.currentIndex opacity: root.visible ? (searching ? 0.30 : 1.0) : 0.3 Behavior on opacity { SmoothedAnimation { duration: units.longDuration; velocity: 0.01 } } verticalScrollBarPolicy: (opacity == 1.0) ? Qt.ScrollBarAsNeeded : Qt.ScrollBarAlwaysOff onEnabledChanged: { if (!enabled) { filterList.currentIndex = -1; } } onCurrentIndexChanged: { focus = (currentIndex != -1); } ListView { id: filterList focus: true property bool allApps: false property int eligibleWidth: width property int hItemMargins: Math.max(highlightItemSvg.margins.left + highlightItemSvg.margins.right, listItemSvg.margins.left + listItemSvg.margins.right) model: rootModel boundsBehavior: Flickable.StopAtBounds snapMode: ListView.SnapToItem spacing: 0 keyNavigationWraps: true delegate: MouseArea { id: item signal actionTriggered(string actionId, variant actionArgument) signal aboutToShowActionMenu(variant actionMenu) property var m: model property int textWidth: label.contentWidth property int mouseCol - property bool hasActionList: ((model.favoriteId != null) - || (("hasActionList" in model) && (model.hasActionList == true))) + property bool hasActionList: ((model.favoriteId !== null) + || (("hasActionList" in model) && (model.hasActionList === true))) property Item menu: actionMenu width: parent.width height: Math.ceil((label.paintedHeight + Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom, listItemSvg.margins.top + listItemSvg.margins.bottom)) / 2) * 2 Accessible.role: Accessible.MenuItem Accessible.name: model.display acceptedButtons: Qt.LeftButton | Qt.RightButton hoverEnabled: true onContainsMouseChanged: { if (!containsMouse) { updateCurrentItemTimer.stop(); } } onPositionChanged: { // Lazy menu implementation. mouseCol = mouse.x; - if (justOpenedTimer.running || ListView.view.currentIndex == 0 || index == ListView.view.currentIndex) { + if (justOpenedTimer.running || ListView.view.currentIndex === 0 || index === ListView.view.currentIndex) { updateCurrentItem(); } else if ((index == ListView.view.currentIndex - 1) && mouse.y < (height - 6) || (index == ListView.view.currentIndex + 1) && mouse.y > 5) { if (mouse.x > ListView.view.eligibleWidth - 5) { updateCurrentItem(); } } else if (mouse.x > ListView.view.eligibleWidth) { updateCurrentItem(); } updateCurrentItemTimer.restart(); } onPressed: { if (mouse.buttons & Qt.RightButton) { if (hasActionList) { openActionMenu(item, mouse.x, mouse.y); } } } onClicked: { if (mouse.button == Qt.LeftButton) { updateCurrentItem(); } } onAboutToShowActionMenu: { var actionList = hasActionList ? model.actionList : []; Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId); } onActionTriggered: { if (Tools.triggerAction(ListView.view.model, model.index, actionId, actionArgument) === true) { plasmoid.expanded = false; } } function openActionMenu(visualParent, x, y) { aboutToShowActionMenu(actionMenu); actionMenu.visualParent = visualParent; actionMenu.open(x, y); } function updateCurrentItem() { ListView.view.currentIndex = index; ListView.view.eligibleWidth = Math.min(width, mouseCol); } ActionMenu { id: actionMenu onActionClicked: { actionTriggered(actionId, actionArgument); } } Timer { id: updateCurrentItemTimer interval: 50 repeat: false onTriggered: parent.updateCurrentItem() } PlasmaExtras.Heading { id: label anchors { fill: parent leftMargin: highlightItemSvg.margins.left rightMargin: highlightItemSvg.margins.right } elide: Text.ElideRight wrapMode: Text.NoWrap opacity: 1.0 color: "white" level: 1 text: model.display } } highlight: PlasmaComponents.Highlight { anchors { top: filterList.currentItem ? filterList.currentItem.top : undefined left: filterList.currentItem ? filterList.currentItem.left : undefined bottom: filterList.currentItem ? filterList.currentItem.bottom : undefined } opacity: filterListScrollArea.focus ? 1.0 : 0.7 width: (highlightItemSvg.margins.left + filterList.currentItem.textWidth + highlightItemSvg.margins.right + units.smallSpacing) visible: filterList.currentItem } highlightFollowsCurrentItem: false highlightMoveDuration: 0 highlightResizeDuration: 0 onCurrentIndexChanged: applyFilter() onCountChanged: { var width = 0; for (var i = 0; i < rootModel.count; ++i) { headingMetrics.text = rootModel.labelForRow(i); if (headingMetrics.width > width) { width = headingMetrics.width; } } filterListColumn.columns = Math.ceil(width / cellSize); filterListScrollArea.width = width + hItemMargins + (units.gridUnit * 2); } function applyFilter() { if (!searching && currentIndex >= 0) { if (tabBar.activeTab == 1) { root.widgetExplorer.widgetsModel.filterQuery = currentItem.m.filterData; root.widgetExplorer.widgetsModel.filterType = currentItem.m.filterType; allApps = false; funnelModel.sourceModel = model; return; } if (preloadAllAppsTimer.running) { preloadAllAppsTimer.stop(); } var model = rootModel.modelForRow(currentIndex); - if (model.description == "KICKER_ALL_MODEL") { + if (model.description === "KICKER_ALL_MODEL") { allAppsGrid.model = model; allApps = true; funnelModel.sourceModel = null; preloadAllAppsTimer.done = true; } else { funnelModel.sourceModel = model; allApps = false; } } else { funnelModel.sourceModel = null; allApps = false; } } Keys.onPressed: { - if (event.key == Qt.Key_Left) { + if (event.key === Qt.Key_Left) { event.accepted = true; var currentRow = Math.max(0, Math.ceil(currentItem.y / mainGrid.cellHeight) - 1); mainColumn.tryActivate(currentRow, mainColumn.columns - 1); - } else if (event.key == Qt.Key_Tab) { + } else if (event.key === Qt.Key_Tab) { event.accepted = true; systemFavoritesGrid.tryActivate(0, 0); - } else if (event.key == Qt.Key_Backtab) { + } else if (event.key === Qt.Key_Backtab) { event.accepted = true; mainColumn.tryActivate(0, 0); } } } } } } onPressed: { if (mouse.button == Qt.RightButton) { contextMenu.open(mouse.x, mouse.y); } } onClicked: { if (mouse.button == Qt.LeftButton) { root.toggle(); } } } } diff --git a/applets/kicker/package/contents/ui/DashboardTabBar.qml b/applets/kicker/package/contents/ui/DashboardTabBar.qml index 66dc4cf8e..6d7a9b99f 100644 --- a/applets/kicker/package/contents/ui/DashboardTabBar.qml +++ b/applets/kicker/package/contents/ui/DashboardTabBar.qml @@ -1,93 +1,93 @@ /*************************************************************************** * Copyright (C) 2016 by 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 . * ***************************************************************************/ import QtQuick 2.4 Row { id: tabBar property int activeTab: 0 property int hoveredTab: -1 Accessible.role: Accessible.PageTabList signal containsMouseChanged(int index, bool containsMouse) onContainsMouseChanged: { if (containsMouse) { hoveredTab = index; } else { hoveredTab = -1; } } DashboardTabButton { id: appsdocs index: 0 text: i18n("Apps & Docs") active: (tabBar.activeTab == 0) focus: parent.focus & active } DashboardTabButton { id: widgets index: 1 text: i18n("Widgets") active: (tabBar.activeTab == 1) focus: parent.focus & active } Keys.onLeftPressed: { if (activeTab == 1) { activeTab = 0; } } Keys.onRightPressed: { if (activeTab == 0) { activeTab = 1; } } Keys.onPressed: { - if (event.key == Qt.Key_Tab) { + if (event.key === Qt.Key_Tab) { event.accepted = true; if (searching) { cancelSearchButton.focus = true; } else { mainColumn.tryActivate(0, 0); } - } else if (event.key == Qt.Key_Backtab) { + } else if (event.key === Qt.Key_Backtab) { event.accepted = true; if (globalFavoritesGrid.enabled) { globalFavoritesGrid.tryActivate(0, 0); } else { systemFavoritesGrid.tryActivate(0, 0); } } } } diff --git a/applets/kicker/package/contents/ui/ItemGridDelegate.qml b/applets/kicker/package/contents/ui/ItemGridDelegate.qml index 8c5aad07b..17b9ae885 100644 --- a/applets/kicker/package/contents/ui/ItemGridDelegate.qml +++ b/applets/kicker/package/contents/ui/ItemGridDelegate.qml @@ -1,130 +1,130 @@ /*************************************************************************** * Copyright (C) 2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import "code/tools.js" as Tools Item { id: item width: GridView.view.cellWidth height: width property bool showLabel: true property int itemIndex: model.index - property string favoriteId: model.favoriteId != undefined ? model.favoriteId : "" - property url url: model.url != undefined ? model.url : "" - property variant icon: model.decoration != undefined ? model.decoration : "" + property string favoriteId: model.favoriteId !== undefined ? model.favoriteId : "" + property url url: model.url !== undefined ? model.url : "" + property variant icon: model.decoration !== undefined ? model.decoration : "" property var m: model - property bool hasActionList: ((model.favoriteId != null) - || (("hasActionList" in model) && (model.hasActionList == true))) + property bool hasActionList: ((model.favoriteId !== null) + || (("hasActionList" in model) && (model.hasActionList === true))) Accessible.role: Accessible.MenuItem Accessible.name: model.display function openActionMenu(x, y) { var actionList = hasActionList ? model.actionList : []; Tools.fillActionMenu(i18n, actionMenu, actionList, GridView.view.model.favoritesModel, model.favoriteId); actionMenu.visualParent = item; actionMenu.open(x, y); } function actionTriggered(actionId, actionArgument) { var close = (Tools.triggerAction(GridView.view.model, model.index, actionId, actionArgument) === true); if (close) { root.toggle(); } } PlasmaCore.IconItem { id: icon y: showLabel ? (2 * highlightItemSvg.margins.top) : undefined anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: showLabel ? undefined : parent.verticalCenter width: iconSize height: width colorGroup: PlasmaCore.Theme.ComplementaryColorGroup animated: false usesPlasmaTheme: item.GridView.view.usesPlasmaTheme source: model.decoration } PlasmaComponents.Label { id: label visible: showLabel anchors { top: icon.bottom topMargin: units.smallSpacing left: parent.left leftMargin: highlightItemSvg.margins.left right: parent.right rightMargin: highlightItemSvg.margins.right } horizontalAlignment: Text.AlignHCenter maximumLineCount: 2 elide: Text.ElideRight wrapMode: Text.Wrap color: "white" // FIXME TODO: Respect theming? text: ("name" in model ? model.name : model.display) } PlasmaCore.ToolTipArea { id: toolTip property string text: model.display anchors.fill: parent active: root.visible && label.truncated mainItem: toolTipDelegate } Keys.onPressed: { - if (event.key == Qt.Key_Menu && hasActionList) { + if (event.key === Qt.Key_Menu && hasActionList) { event.accepted = true; openActionMenu(item); - } else if ((event.key == Qt.Key_Enter || event.key == Qt.Key_Return)) { + } else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) { event.accepted = true; if ("trigger" in GridView.view.model) { GridView.view.model.trigger(index, "", null); root.toggle(); } itemGrid.itemActivated(index, "", null); } } } diff --git a/applets/kicker/package/contents/ui/ItemGridView.qml b/applets/kicker/package/contents/ui/ItemGridView.qml index 8a6e2cc76..1a0d4a47b 100644 --- a/applets/kicker/package/contents/ui/ItemGridView.qml +++ b/applets/kicker/package/contents/ui/ItemGridView.qml @@ -1,465 +1,465 @@ /*************************************************************************** * Copyright (C) 2015 by 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 . * ***************************************************************************/ import QtQuick 2.4 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 import org.kde.draganddrop 2.0 FocusScope { id: itemGrid signal keyNavLeft signal keyNavRight signal keyNavUp signal keyNavDown signal itemActivated(int index, string actionId, string argument) property bool dragEnabled: true property bool dropEnabled: false property bool showLabels: true property alias usesPlasmaTheme: gridView.usesPlasmaTheme property alias currentIndex: gridView.currentIndex property alias currentItem: gridView.currentItem property alias contentItem: gridView.contentItem property alias count: gridView.count property alias model: gridView.model property alias cellWidth: gridView.cellWidth property alias cellHeight: gridView.cellHeight property alias iconSize: gridView.iconSize property alias horizontalScrollBarPolicy: scrollArea.horizontalScrollBarPolicy property alias verticalScrollBarPolicy: scrollArea.verticalScrollBarPolicy onDropEnabledChanged: { if (!dropEnabled && "dropPlaceHolderIndex" in model) { model.dropPlaceHolderIndex = -1; } } onFocusChanged: { if (!focus && !root.keyEventProxy.activeFocus) { currentIndex = -1; } } function currentRow() { if (currentIndex == -1) { return -1; } return Math.floor(currentIndex / Math.floor(width / cellWidth)); } function currentCol() { if (currentIndex == -1) { return -1; } return currentIndex - (currentRow() * Math.floor(width / cellWidth)); } function lastRow() { var columns = Math.floor(width / cellWidth); return Math.ceil(count / columns) - 1; } function tryActivate(row, col) { if (count) { var columns = Math.floor(width / cellWidth); var rows = Math.ceil(count / columns); row = Math.min(row, rows - 1); col = Math.min(col, columns - 1); currentIndex = Math.min(row ? ((Math.max(1, row) * columns) + col) : col, count - 1); focus = true; } } function forceLayout() { gridView.forceLayout(); } ActionMenu { id: actionMenu onActionClicked: { visualParent.actionTriggered(actionId, actionArgument); } } DropArea { id: dropArea anchors.fill: parent onDragMove: { if (!dropEnabled || gridView.animating || !kicker.dragSource) { return; } var x = Math.max(0, event.x - (width % cellWidth)); var cPos = mapToItem(gridView.contentItem, x, event.y); var item = gridView.itemAt(cPos.x, cPos.y); if (item) { - if (kicker.dragSource.parent == gridView.contentItem) { - if (item != kicker.dragSource) { + if (kicker.dragSource.parent === gridView.contentItem) { + if (item !== kicker.dragSource) { item.GridView.view.model.moveRow(dragSource.itemIndex, item.itemIndex); } - } else if (kicker.dragSource.view.model.favoritesModel == model + } else if (kicker.dragSource.view.model.favoritesModel === model && !model.isFavorite(kicker.dragSource.favoriteId)) { - var hasPlaceholder = (model.dropPlaceholderIndex != -1); + var hasPlaceholder = (model.dropPlaceholderIndex !== -1); model.dropPlaceholderIndex = item.itemIndex; if (!hasPlaceholder) { gridView.currentIndex = (item.itemIndex - 1); } } - } else if (kicker.dragSource.parent != gridView.contentItem - && kicker.dragSource.view.model.favoritesModel == model + } else if (kicker.dragSource.parent !== gridView.contentItem + && kicker.dragSource.view.model.favoritesModel === model && !model.isFavorite(kicker.dragSource.favoriteId)) { - var hasPlaceholder = (model.dropPlaceholderIndex != -1); + var hasPlaceholder = (model.dropPlaceholderIndex !== -1); model.dropPlaceholderIndex = hasPlaceholder ? model.count - 1 : model.count; if (!hasPlaceholder) { gridView.currentIndex = (model.count - 1); } } else { model.dropPlaceholderIndex = -1; gridView.currentIndex = -1; } } onDragLeave: { if ("dropPlaceholderIndex" in model) { model.dropPlaceholderIndex = -1; gridView.currentIndex = -1; } } onDrop: { - if (kicker.dragSource && kicker.dragSource.parent != gridView.contentItem && kicker.dragSource.view.model.favoritesModel == model) { + if (kicker.dragSource && kicker.dragSource.parent !== gridView.contentItem && kicker.dragSource.view.model.favoritesModel === model) { model.addFavorite(kicker.dragSource.favoriteId, model.dropPlaceholderIndex); gridView.currentIndex = -1; } } Timer { id: resetAnimationDurationTimer interval: 120 repeat: false onTriggered: { gridView.animationDuration = interval - 20; } } PlasmaExtras.ScrollArea { id: scrollArea anchors.fill: parent focus: true horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff GridView { id: gridView property bool usesPlasmaTheme: false property int iconSize: units.iconSizes.huge property bool animating: false property int animationDuration: dropEnabled ? resetAnimationDurationTimer.interval : 0 focus: true currentIndex: -1 move: Transition { enabled: itemGrid.dropEnabled SequentialAnimation { PropertyAction { target: gridView; property: "animating"; value: true } NumberAnimation { duration: gridView.animationDuration properties: "x, y" easing.type: Easing.OutQuad } PropertyAction { target: gridView; property: "animating"; value: false } } } moveDisplaced: Transition { enabled: itemGrid.dropEnabled SequentialAnimation { PropertyAction { target: gridView; property: "animating"; value: true } NumberAnimation { duration: gridView.animationDuration properties: "x, y" easing.type: Easing.OutQuad } PropertyAction { target: gridView; property: "animating"; value: false } } } keyNavigationWraps: false boundsBehavior: Flickable.StopAtBounds delegate: ItemGridDelegate { showLabel: showLabels } highlight: Item { - property bool isDropPlaceHolder: "dropPlaceholderIndex" in model && currentIndex == model.dropPlaceholderIndex + property bool isDropPlaceHolder: "dropPlaceholderIndex" in model && currentIndex === model.dropPlaceholderIndex PlasmaComponents.Highlight { visible: gridView.currentItem && !isDropPlaceHolder anchors.fill: parent } PlasmaCore.FrameSvgItem { visible: gridView.currentItem && isDropPlaceHolder anchors.fill: parent imagePath: "widgets/viewitem" prefix: "selected" opacity: 0.5 PlasmaCore.IconItem { anchors { right: parent.right rightMargin: parent.margins.right bottom: parent.bottom bottomMargin: parent.margins.bottom } width: units.iconSizes.smallMedium height: width source: "list-add" active: false } } } highlightFollowsCurrentItem: true highlightMoveDuration: 0 onCurrentIndexChanged: { if (currentIndex != -1) { focus = true; } } onCountChanged: { animationDuration = 0; resetAnimationDurationTimer.start(); } onModelChanged: { currentIndex = -1; } Keys.onLeftPressed: { - if (currentCol() != 0) { + if (currentCol() !== 0) { event.accepted = true; moveCurrentIndexLeft(); } else { itemGrid.keyNavLeft(); } } Keys.onRightPressed: { var columns = Math.floor(width / cellWidth); - if (currentCol() != columns - 1 && currentIndex != count -1) { + if (currentCol() !== columns - 1 && currentIndex != count -1) { event.accepted = true; moveCurrentIndexRight(); } else { itemGrid.keyNavRight(); } } Keys.onUpPressed: { - if (currentRow() != 0) { + if (currentRow() !== 0) { event.accepted = true; moveCurrentIndexUp(); positionViewAtIndex(currentIndex, GridView.Contain); } else { itemGrid.keyNavUp(); } } Keys.onDownPressed: { if (currentRow() < itemGrid.lastRow()) { // Fix moveCurrentIndexDown()'s lack of proper spatial nav down // into partial columns. event.accepted = true; var columns = Math.floor(width / cellWidth); var newIndex = currentIndex + columns; currentIndex = Math.min(newIndex, count - 1); positionViewAtIndex(currentIndex, GridView.Contain); } else { itemGrid.keyNavDown(); } } } } MouseArea { id: hoverArea anchors.fill: parent property int pressX: -1 property int pressY: -1 property int lastX: -1 property int lastY: -1 property Item pressedItem: null acceptedButtons: Qt.LeftButton | Qt.RightButton hoverEnabled: true function updatePositionProperties(x, y) { // Prevent hover event synthesis in QQuickWindow interfering // with keyboard navigation by ignoring repeated events with // identical coordinates. As the work done here would be re- // dundant in any case, these are safe to ignore. - if (lastX == x && lastY == y) { + if (lastX === x && lastY === y) { return; } lastX = x; lastY = y; var cPos = mapToItem(gridView.contentItem, x, y); var item = gridView.itemAt(cPos.x, cPos.y); if (!item) { gridView.currentIndex = -1; pressedItem = null; } else { gridView.currentIndex = item.itemIndex; itemGrid.focus = (currentIndex != -1) } return item; } onPressed: { mouse.accepted = true; updatePositionProperties(mouse.x, mouse.y); pressX = mouse.x; pressY = mouse.y; if (mouse.button == Qt.RightButton) { if (gridView.currentItem) { if (gridView.currentItem.hasActionList) { var mapped = mapToItem(gridView.currentItem, mouse.x, mouse.y); gridView.currentItem.openActionMenu(mapped.x, mapped.y); } } else { var mapped = mapToItem(rootItem, mouse.x, mouse.y); contextMenu.open(mapped.x, mapped.y); } } else { pressedItem = gridView.currentItem; } } onReleased: { mouse.accepted = true; if (gridView.currentItem && gridView.currentItem == pressedItem) { if ("trigger" in gridView.model) { gridView.model.trigger(pressedItem.itemIndex, "", null); root.toggle(); } itemGrid.itemActivated(pressedItem.itemIndex, "", null); } else if (!pressedItem && mouse.button == Qt.LeftButton) { root.toggle(); } pressX = -1; pressY = -1; pressedItem = null; } onPositionChanged: { var item = updatePositionProperties(mouse.x, mouse.y); if (gridView.currentIndex != -1) { if (dragEnabled && pressX != -1 && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { if ("pluginName" in item.m) { dragHelper.startDrag(kicker, item.url, item.icon, "text/x-plasmoidservicename", item.m.pluginName); } else { dragHelper.startDrag(kicker, item.url, item.icon); } kicker.dragSource = item; pressX = -1; pressY = -1; } } } onContainsMouseChanged: { if (!containsMouse) { if (!actionMenu.opened) { gridView.currentIndex = -1; } pressX = -1; pressY = -1; lastX = -1; lastY = -1; pressedItem = null; } } } } } diff --git a/applets/kicker/package/contents/ui/ItemListDelegate.qml b/applets/kicker/package/contents/ui/ItemListDelegate.qml index 306cbd56d..1ca1bd37f 100644 --- a/applets/kicker/package/contents/ui/ItemListDelegate.qml +++ b/applets/kicker/package/contents/ui/ItemListDelegate.qml @@ -1,284 +1,284 @@ /*************************************************************************** * Copyright (C) 2013-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import "code/tools.js" as Tools Item { id: item height: isSeparator ? separatorHeight : itemHeight width: ListView.view.width enabled: !isSeparator signal actionTriggered(string actionId, variant actionArgument) signal aboutToShowActionMenu(variant actionMenu) readonly property real fullTextWidth: Math.ceil(icon.width + label.implicitWidth + arrow.width + row.anchors.leftMargin + row.anchors.rightMargin + row.actualSpacing) - property bool isSeparator: (model.isSeparator == true) - property bool hasChildren: (model.hasChildren == true) - property bool hasActionList: ((model.favoriteId != null) - || (("hasActionList" in model) && (model.hasActionList == true))) + property bool isSeparator: (model.isSeparator === true) + property bool hasChildren: (model.hasChildren === true) + property bool hasActionList: ((model.favoriteId !== null) + || (("hasActionList" in model) && (model.hasActionList === true))) property QtObject childDialog: null property Item menu: actionMenu Accessible.role: isSeparator ? Accessible.Separator: Accessible.MenuItem Accessible.name: label.text onHasChildrenChanged: { - if (!hasChildren && ListView.view.currentItem == item) { + if (!hasChildren && ListView.view.currentItem === item) { ListView.view.currentIndex = -1; } } onAboutToShowActionMenu: { var actionList = hasActionList ? model.actionList : []; Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId); } onActionTriggered: { if (Tools.triggerAction(ListView.view.model, model.index, actionId, actionArgument) === true) { plasmoid.expanded = false; } } function openActionMenu(visualParent, x, y) { aboutToShowActionMenu(actionMenu); actionMenu.visualParent = visualParent; actionMenu.open(x, y); } ActionMenu { id: actionMenu onActionClicked: { actionTriggered(actionId, actionArgument); } } MouseArea { id: mouseArea anchors { left: parent.left right: parent.right verticalCenter: parent.verticalCenter } height: parent.height property int mouseCol property bool pressed: false property int pressX: -1 property int pressY: -1 hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: { if (mouse.buttons & Qt.RightButton) { if (hasActionList) { openActionMenu(mouseArea, mouse.x, mouse.y); } } else { pressed = true; pressX = mouse.x; pressY = mouse.y; } } onReleased: { if (pressed && !hasChildren) { item.ListView.view.model.trigger(index, "", null); plasmoid.expanded = false; } pressed = false; pressX = -1; pressY = -1; } onPositionChanged: { if (pressX != -1 && model.url && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { dragHelper.startDrag(kicker, model.url, model.decoration); pressed = false; pressX = -1; pressY = -1; return; } // FIXME: Correct escape angle calc for right screen edge. if (justOpenedTimer.running || !hasChildren) { item.ListView.view.currentIndex = index; } else { mouseCol = mouse.x; - if (index == item.ListView.view.currentIndex) { + if (index === item.ListView.view.currentIndex) { updateCurrentItem(); } else if ((index == item.ListView.view.currentIndex - 1) && mouse.y < (itemHeight - 6) || (index == item.ListView.view.currentIndex + 1) && mouse.y > 5) { if ((childDialog != null && childDialog.facingLeft) ? mouse.x > item.ListView.view.eligibleWidth - 5 : mouse.x < item.ListView.view.eligibleWidth + 5) { updateCurrentItem(); } } else if ((childDialog != null && childDialog.facingLeft) ? mouse.x > item.ListView.view.eligibleWidth : mouse.x < item.ListView.view.eligibleWidth) { updateCurrentItem(); } updateCurrentItemTimer.start(); } } onContainsMouseChanged: { if (!containsMouse) { pressed = false; pressX = -1; pressY = -1; updateCurrentItemTimer.stop(); } } function updateCurrentItem() { item.ListView.view.currentIndex = index; item.ListView.view.eligibleWidth = Math.min(width, mouseCol); } Timer { id: updateCurrentItemTimer interval: 50 repeat: false onTriggered: parent.updateCurrentItem() } } Row { id: row anchors.left: parent.left anchors.leftMargin: highlightItemSvg.margins.left anchors.right: parent.right anchors.rightMargin: highlightItemSvg.margins.right height: parent.height spacing: units.smallSpacing * 2 readonly property real actualSpacing: ((icon.visible ? 1 : 0) * spacing) + ((arrow.visible ? 1 : 0) * spacing) LayoutMirroring.enabled: (Qt.application.layoutDirection == Qt.RightToLeft) PlasmaCore.IconItem { id: icon anchors.verticalCenter: parent.verticalCenter width: visible ? units.iconSizes.small : 0 height: width visible: iconsEnabled animated: false usesPlasmaTheme: false source: model.decoration } PlasmaComponents.Label { id: label enabled: !isParent || (isParent && hasChildren) anchors.verticalCenter: parent.verticalCenter width: parent.width - icon.width - arrow.width - parent.actualSpacing verticalAlignment: Text.AlignVCenter textFormat: Text.PlainText wrapMode: Text.NoWrap elide: Text.ElideRight text: model.display } PlasmaCore.SvgItem { id: arrow anchors.verticalCenter: parent.verticalCenter width: visible ? units.iconSizes.small : 0 height: width visible: hasChildren - opacity: (item.ListView.view.currentIndex == index) ? 1.0 : 0.4 + opacity: (item.ListView.view.currentIndex === index) ? 1.0 : 0.4 svg: arrows elementId: (Qt.application.layoutDirection == Qt.RightToLeft) ? "left-arrow" : "right-arrow" } } Component { id: separatorComponent PlasmaCore.SvgItem { width: parent.width height: lineSvg.horLineHeight svg: lineSvg elementId: "horizontal-line" } } Loader { id: separatorLoader anchors.left: parent.left anchors.leftMargin: highlightItemSvg.margins.left anchors.right: parent.right anchors.rightMargin: highlightItemSvg.margins.right anchors.verticalCenter: parent.verticalCenter active: isSeparator asynchronous: false sourceComponent: separatorComponent } Keys.onPressed: { - if (event.key == Qt.Key_Menu && hasActionList) { + if (event.key === Qt.Key_Menu && hasActionList) { event.accepted = true; openActionMenu(mouseArea); - } else if ((event.key == Qt.Key_Enter || event.key == Qt.Key_Return) && !hasChildren) { + } else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && !hasChildren) { if (!hasChildren) { event.accepted = true; item.ListView.view.model.trigger(index, "", null); plasmoid.expanded = false; } } } } diff --git a/applets/kicker/package/contents/ui/ItemListDialog.qml b/applets/kicker/package/contents/ui/ItemListDialog.qml index 7e3d89675..a50471bf9 100644 --- a/applets/kicker/package/contents/ui/ItemListDialog.qml +++ b/applets/kicker/package/contents/ui/ItemListDialog.qml @@ -1,90 +1,90 @@ /*************************************************************************** * Copyright (C) 2013-2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.private.kicker 0.1 as Kicker Kicker.SubMenu { id: itemDialog property alias focusParent: itemListView.focusParent property alias model: funnelModel.sourceModel property bool aboutToBeDestroyed: false visible: false hideOnWindowDeactivate: plasmoid.hideOnWindowDeactivate location: PlasmaCore.Types.Floating offset: units.smallSpacing onWindowDeactivated: { if (!aboutToBeDestroyed) { plasmoid.expanded = false; } } mainItem: ItemListView { id: itemListView - height: model != undefined ? Math.min(((Math.floor((itemDialog.availableScreenRectForItem(itemListView).height + height: model !== undefined ? Math.min(((Math.floor((itemDialog.availableScreenRectForItem(itemListView).height - itemDialog.margins.top - itemDialog.margins.bottom) / itemHeight) - 1) * itemHeight) - (model.separatorCount * itemHeight) + (model.separatorCount * separatorHeight), ((model.count - model.separatorCount) * itemHeight) + (model.separatorCount * separatorHeight)) : 0 iconsEnabled: true dialog: itemDialog model: funnelModel Kicker.FunnelModel { id: funnelModel Component.onCompleted: { kicker.reset.connect(funnelModel.reset); } onCountChanged: { if (sourceModel && count == 0) { itemDialog.delayedDestroy(); } } onSourceModelChanged: { itemListView.currentIndex = -1; } } } function delayedDestroy() { aboutToBeDestroyed = true; plasmoid.hideOnWindowDeactivate = false; visible = false; Qt.callLater(function() { itemDialog.destroy(); }); } } diff --git a/applets/kicker/package/contents/ui/ItemListView.qml b/applets/kicker/package/contents/ui/ItemListView.qml index dd78191b0..9400c27f8 100644 --- a/applets/kicker/package/contents/ui/ItemListView.qml +++ b/applets/kicker/package/contents/ui/ItemListView.qml @@ -1,266 +1,266 @@ /*************************************************************************** * Copyright (C) 2013-2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 FocusScope { id: itemList property real minimumWidth: units.gridUnit * 14 property real maximumWidth: minimumWidth * 2 width: minimumWidth height: listView.contentHeight signal exited signal keyNavigationAtListEnd signal appendSearchText(string text) property Item focusParent: null property QtObject dialog: null property QtObject childDialog: null property bool iconsEnabled: false property int itemHeight: Math.ceil((Math.max(theme.mSize(theme.defaultFont).height, units.iconSizes.small) + Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom, listItemSvg.margins.top + listItemSvg.margins.bottom)) / 2) * 2 property int separatorHeight: lineSvg.horLineHeight + (2 * units.smallSpacing) property alias currentIndex: listView.currentIndex property alias currentItem: listView.currentItem property alias keyNavigationWraps: listView.keyNavigationWraps property alias showChildDialogs: listView.showChildDialogs property alias model: listView.model property alias count: listView.count property alias containsMouse: listener.containsMouse property alias resetOnExitDelay: resetIndexTimer.interval onFocusParentChanged: { appendSearchText.connect(focusParent.appendSearchText); } Timer { id: dialogSpawnTimer property bool focusOnSpawn: false interval: 70 repeat: false onTriggered: { - if (!plasmoid.expanded || model == undefined || currentIndex == -1) { + if (!plasmoid.expanded || model === undefined || currentIndex == -1) { return; } if (childDialog != null) { childDialog.delayedDestroy(); } // Gets reenabled after the dialog spawn causes a focus-in on the dialog window. plasmoid.hideOnWindowDeactivate = false; childDialog = itemListDialogComponent.createObject(itemList); childDialog.focusParent = itemList; childDialog.visualParent = listView.currentItem; childDialog.model = model.modelForRow(listView.currentIndex); childDialog.visible = true; windowSystem.forceActive(childDialog.mainItem); childDialog.mainItem.focus = true; if (focusOnSpawn) { childDialog.mainItem.showChildDialogs = false; childDialog.mainItem.currentIndex = 0; childDialog.mainItem.showChildDialogs = true; } } } Timer { id: resetIndexTimer interval: (dialog != null) ? 50 : 150 repeat: false onTriggered: { if (focus && (!childDialog || !childDialog.mainItem.containsMouse)) { currentIndex = -1; itemList.exited(); } } } MouseEventListener { id: listener anchors.fill: parent hoverEnabled: true onContainsMouseChanged: { listView.eligibleWidth = listView.width; if (containsMouse) { resetIndexTimer.stop(); itemList.forceActiveFocus(); } else if ((!childDialog || !dialog) && (!currentItem || !currentItem.menu.opened)) { resetIndexTimer.start(); } } PlasmaExtras.ScrollArea { anchors.fill: parent focus: true ListView { id: listView property bool showChildDialogs: true property int eligibleWidth: width currentIndex: -1 boundsBehavior: Flickable.StopAtBounds snapMode: ListView.SnapToItem spacing: 0 keyNavigationWraps: (dialog != null) delegate: ItemListDelegate { onFullTextWidthChanged: { if (fullTextWidth > itemList.width) itemList.width = Math.min(fullTextWidth, itemList.maximumWidth); } } highlight: PlasmaComponents.Highlight { visible: listView.currentItem && !listView.currentItem.isSeparator } highlightMoveDuration: 0 onCountChanged: { currentIndex = -1; } onCurrentIndexChanged: { if (currentIndex != -1) { if (childDialog) { if (currentItem && currentItem.hasChildren) { childDialog.mainItem.width = itemList.minimumWidth; childDialog.model = model.modelForRow(currentIndex); childDialog.visualParent = listView.currentItem; } else { childDialog.delayedDestroy(); } return; } if (currentItem == null || !currentItem.hasChildren || !plasmoid.expanded) { dialogSpawnTimer.stop(); return; } if (showChildDialogs) { dialogSpawnTimer.focusOnSpawn = false; dialogSpawnTimer.restart(); } } else if (childDialog != null) { childDialog.delayedDestroy(); childDialog = null; } } onCurrentItemChanged: { if (currentItem) { currentItem.menu.closed.connect(resetIndexTimer.restart); } } Keys.onPressed: { - if (event.key == Qt.Key_Up) { + if (event.key === Qt.Key_Up) { event.accepted = true; if (!keyNavigationWraps && currentIndex == 0) { itemList.keyNavigationAtListEnd(); return; } showChildDialogs = false; decrementCurrentIndex(); if (currentItem.isSeparator) { decrementCurrentIndex(); } showChildDialogs = true; - } else if (event.key == Qt.Key_Down) { + } else if (event.key === Qt.Key_Down) { event.accepted = true; if (!keyNavigationWraps && currentIndex == count - 1) { itemList.keyNavigationAtListEnd(); return; } showChildDialogs = false; incrementCurrentIndex(); if (currentItem.isSeparator) { incrementCurrentIndex(); } showChildDialogs = true; - } else if ((event.key == Qt.Key_Right || event.key == Qt.Key_Return || event.key == Qt.Key_Enter) && childDialog != null) { + } else if ((event.key === Qt.Key_Right || event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && childDialog != null) { windowSystem.forceActive(childDialog.mainItem); childDialog.mainItem.focus = true; childDialog.mainItem.currentIndex = 0; - } else if ((event.key == Qt.Key_Right || event.key == Qt.Key_Return || event.key == Qt.Key_Enter) && childDialog == null + } else if ((event.key === Qt.Key_Right || event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && childDialog == null && currentItem != null && currentItem.hasChildren) { dialogSpawnTimer.focusOnSpawn = true; dialogSpawnTimer.restart(); - } else if (event.key == Qt.Key_Left && dialog != null) { + } else if (event.key === Qt.Key_Left && dialog != null) { dialog.destroy(); - } else if (event.key == Qt.Key_Escape) { + } else if (event.key === Qt.Key_Escape) { plasmoid.expanded = false; - } else if (event.key == Qt.Key_Tab) { + } else if (event.key === Qt.Key_Tab) { //do nothing, and skip appending text - } else if (event.text != "") { + } else if (event.text !== "") { appendSearchText(event.text); } } } } } Component.onCompleted: { windowSystem.monitorWindowFocus(itemList); if (dialog == null) { appendSearchText.connect(root.appendSearchText); } } } diff --git a/applets/kicker/package/contents/ui/ItemMultiGridView.qml b/applets/kicker/package/contents/ui/ItemMultiGridView.qml index e31708672..d2adf0a1b 100644 --- a/applets/kicker/package/contents/ui/ItemMultiGridView.qml +++ b/applets/kicker/package/contents/ui/ItemMultiGridView.qml @@ -1,239 +1,239 @@ /*************************************************************************** * Copyright (C) 2015 by 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 . * ***************************************************************************/ import QtQuick 2.4 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.private.kicker 0.1 as Kicker PlasmaExtras.ScrollArea { id: itemMultiGrid anchors { top: parent.top } width: parent.width implicitHeight: itemColumn.implicitHeight signal keyNavLeft(int subGridIndex) signal keyNavRight(int subGridIndex) signal keyNavUp() signal keyNavDown() property bool grabFocus: false property alias model: repeater.model property alias count: repeater.count flickableItem.flickableDirection: Flickable.VerticalFlick onFocusChanged: { if (!focus) { for (var i = 0; i < repeater.count; i++) { subGridAt(i).focus = false; } } } function subGridAt(index) { return repeater.itemAt(index).itemGrid; } function tryActivate(row, col) { // FIXME TODO: Cleanup messy algo. if (flickableItem.contentY > 0) { row = 0; } var target = null; var rows = 0; for (var i = 0; i < repeater.count; i++) { var grid = subGridAt(i); if (rows <= row) { target = grid; rows += grid.lastRow() + 2; // Header counts as one. } else { break; } } if (target) { rows -= (target.lastRow() + 2); target.tryActivate(row - rows, col); } } Column { id: itemColumn width: itemMultiGrid.width - units.gridUnit Repeater { id: repeater delegate: Item { width: itemColumn.width - units.gridUnit height: headerHeight + gridView.height + (index == repeater.count - 1 ? 0 : footerHeight) property int headerHeight: (gridViewLabel.height + gridViewLabelUnderline.height + units.largeSpacing) property int footerHeight: (Math.ceil(headerHeight / cellSize) * cellSize) - headerHeight property Item itemGrid: gridView PlasmaExtras.Heading { id: gridViewLabel anchors.top: parent.top x: units.smallSpacing width: parent.width - x height: dummyHeading.height elide: Text.ElideRight wrapMode: Text.NoWrap opacity: 1.0 color: "white" // FIXME TODO: Respect theming? level: 1 text: repeater.model.modelForRow(index).description } PlasmaCore.SvgItem { id: gridViewLabelUnderline anchors.top: gridViewLabel.bottom width: parent.width - units.gridUnit height: lineSvg.horLineHeight svg: lineSvg elementId: "horizontal-line" } MouseArea { width: parent.width height: parent.height onClicked: root.toggle() } ItemGridView { id: gridView anchors { top: gridViewLabelUnderline.bottom topMargin: units.largeSpacing } width: parent.width height: Math.ceil(count / Math.floor(width / cellSize)) * cellSize cellWidth: cellSize cellHeight: cellSize iconSize: root.iconSize verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff model: repeater.model.modelForRow(index) onFocusChanged: { if (focus) { itemMultiGrid.focus = true; } } onCountChanged: { if (itemMultiGrid.grabFocus && index == 0 && count > 0) { currentIndex = 0; focus = true; } } onCurrentItemChanged: { if (!currentItem) { return; } - if (index == 0 && currentRow() == 0) { + if (index == 0 && currentRow() === 0) { itemMultiGrid.flickableItem.contentY = 0; return; } var y = currentItem.y; y = contentItem.mapToItem(itemMultiGrid.flickableItem.contentItem, 0, y).y; if (y < itemMultiGrid.flickableItem.contentY) { itemMultiGrid.flickableItem.contentY = y; } else { y += cellSize; y -= itemMultiGrid.flickableItem.contentY; y -= itemMultiGrid.viewport.height; if (y > 0) { itemMultiGrid.flickableItem.contentY += y; } } } onKeyNavLeft: { itemMultiGrid.keyNavLeft(index); } onKeyNavRight: { itemMultiGrid.keyNavRight(index); } onKeyNavUp: { if (index > 0) { var prevGrid = subGridAt(index - 1); prevGrid.tryActivate(prevGrid.lastRow(), currentCol()); } else { itemMultiGrid.keyNavUp(); } } onKeyNavDown: { if (index < repeater.count - 1) { subGridAt(index + 1).tryActivate(0, currentCol()); } else { itemMultiGrid.keyNavDown(); } } } // HACK: Steal wheel events from the nested grid view and forward them to // the ScrollView's internal WheelArea. Kicker.WheelInterceptor { anchors.fill: gridView z: 1 destination: findWheelArea(itemMultiGrid.flickableItem) } } } } } diff --git a/applets/kicker/package/contents/ui/MenuRepresentation.qml b/applets/kicker/package/contents/ui/MenuRepresentation.qml index 10f3dfa38..62a606962 100644 --- a/applets/kicker/package/contents/ui/MenuRepresentation.qml +++ b/applets/kicker/package/contents/ui/MenuRepresentation.qml @@ -1,458 +1,458 @@ /*************************************************************************** * Copyright (C) 2013-2015 by 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 . * ***************************************************************************/ import QtQuick 2.2 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents FocusScope { id: root focus: true Layout.minimumWidth: (sideBar.width + (sideBar.width ? mainRow.spacing : 0) + Math.max(searchField.defaultWidth, runnerColumns.width)) Layout.maximumWidth: Math.max(mainRow.width, Layout.minimumWidth); // mainRow.width is constrained by rootList.maximumWidth Layout.minimumHeight: Math.max(((rootModel.count - rootModel.separatorCount) * rootList.itemHeight) + (rootModel.separatorCount * rootList.separatorHeight) + searchField.height + (2 * units.smallSpacing), sideBar.margins.top + sideBar.margins.bottom + favoriteApps.contentHeight + favoriteSystemActions.contentHeight + sidebarSeparator.height + (4 * units.smallSpacing)) Layout.maximumHeight: Layout.minimumHeight signal appendSearchText(string text) function reset() { plasmoid.hideOnWindowDeactivate = true; rootList.currentIndex = -1; searchField.text = ""; searchField.focus = true; } Row { id: mainRow height: parent.height spacing: units.smallSpacing - LayoutMirroring.enabled: ((plasmoid.location == PlasmaCore.Types.RightEdge) - || (Qt.application.layoutDirection == Qt.RightToLeft && plasmoid.location != PlasmaCore.Types.LeftEdge)) + LayoutMirroring.enabled: ((plasmoid.location === PlasmaCore.Types.RightEdge) + || (Qt.application.layoutDirection == Qt.RightToLeft && plasmoid.location !== PlasmaCore.Types.LeftEdge)) PlasmaCore.FrameSvgItem { id: sideBar visible: width > 0 width: (globalFavorites && systemFavorites && (globalFavorites.count + systemFavorites.count) ? units.iconSizes.medium + margins.left + margins.right : 0) height: parent.height imagePath: "widgets/frame" prefix: "plain" SideBarSection { id: favoriteApps anchors.top: parent.top anchors.topMargin: sideBar.margins.top height: (sideBar.height - sideBar.margins.top - sideBar.margins.bottom - favoriteSystemActions.height - sidebarSeparator.height - (4 * units.smallSpacing)) model: globalFavorites states: [ State { name: "top" - when: (plasmoid.location == PlasmaCore.Types.TopEdge) + when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: favoriteApps anchors.top: undefined anchors.bottom: parent.bottom } PropertyChanges { target: favoriteApps anchors.topMargin: undefined anchors.bottomMargin: sideBar.margins.bottom } }] Binding { target: globalFavorites property: "iconSize" value: units.iconSizes.medium } } PlasmaCore.SvgItem { id: sidebarSeparator anchors.bottom: favoriteSystemActions.top anchors.bottomMargin: (2 * units.smallSpacing) anchors.horizontalCenter: parent.horizontalCenter width: units.iconSizes.medium height: lineSvg.horLineHeight visible: (favoriteApps.model && favoriteApps.model.count && favoriteSystemActions.model && favoriteSystemActions.model.count) svg: lineSvg elementId: "horizontal-line" states: [ State { name: "top" - when: (plasmoid.location == PlasmaCore.Types.TopEdge) + when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: sidebarSeparator anchors.top: favoriteSystemActions.bottom anchors.bottom: undefined } PropertyChanges { target: sidebarSeparator anchors.topMargin: (2 * units.smallSpacing) anchors.bottomMargin: undefined } }] } SideBarSection { id: favoriteSystemActions anchors.bottom: parent.bottom anchors.bottomMargin: sideBar.margins.bottom model: systemFavorites usesPlasmaTheme: true states: [ State { name: "top" - when: (plasmoid.location == PlasmaCore.Types.TopEdge) + when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: favoriteSystemActions anchors.top: parent.top anchors.bottom: undefined } PropertyChanges { target: favoriteSystemActions anchors.topMargin: sideBar.margins.top anchors.bottomMargin: undefined } }] } } ItemListView { id: rootList anchors.top: parent.top minimumWidth: root.Layout.minimumWidth - sideBar.width - mainRow.spacing height: ((rootModel.count - rootModel.separatorCount) * itemHeight) + (rootModel.separatorCount * separatorHeight) visible: (searchField.text == "") iconsEnabled: plasmoid.configuration.showIconsRootLevel model: rootModel onKeyNavigationAtListEnd: { searchField.focus = true; } states: [ State { name: "top" - when: (plasmoid.location == PlasmaCore.Types.TopEdge) + when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: rootList anchors.top: undefined anchors.bottom: parent.bottom } }] Component.onCompleted: { rootList.exited.connect(root.reset); } } Row { id: runnerColumns height: parent.height signal focusChanged() visible: (searchField.text != "" && runnerModel.count > 0) Repeater { id: runnerColumnsRepeater model: runnerModel delegate: RunnerResultsList { id: runnerMatches onKeyNavigationAtListEnd: { searchField.focus = true; } onContainsMouseChanged: { if (containsMouse) { runnerMatches.focus = true; } } onFocusChanged: { if (focus) { runnerColumns.focusChanged(); } } function focusChanged() { if (!runnerMatches.focus && runnerMatches.currentIndex != -1) { runnerMatches.currentIndex = -1; } } Keys.onPressed: { var target = null; - if (event.key == Qt.Key_Right) { + if (event.key === Qt.Key_Right) { var targets = new Array(); for (var i = index + 1; i < runnerModel.count; ++i) { targets[targets.length] = i; } for (var i = 0; i < index; ++i) { targets[targets.length] = i; } for (var i = 0; i < targets.length; ++i) { if (runnerModel.modelForRow(targets[i]).count) { target = runnerColumnsRepeater.itemAt(targets[i]); break; } } - } else if (event.key == Qt.Key_Left) { + } else if (event.key === Qt.Key_Left) { var targets = new Array(); for (var i = index - 1; i >= 0; --i) { targets[targets.length] = i; } for (var i = runnerModel.count - 1; i > index; --i) { targets[targets.length] = i; } for (var i = 0; i < targets.length; ++i) { if (runnerModel.modelForRow(targets[i]).count) { target = runnerColumnsRepeater.itemAt(targets[i]); break; } } } if (target) { event.accepted = true; currentIndex = -1; target.currentIndex = 0; target.focus = true; } } Component.onCompleted: { runnerColumns.focusChanged.connect(focusChanged); } Component.onDestruction: { runnerColumns.focusChanged.disconnect(focusChanged); } } } } } PlasmaComponents.TextField { id: searchField anchors.bottom: mainRow.bottom anchors.left: parent.left anchors.leftMargin: sideBar.width + (sideBar.width ? mainRow.spacing : 0) + units.smallSpacing readonly property real defaultWidth: units.gridUnit * 14 width: (runnerColumnsRepeater.count != 0 ? runnerColumnsRepeater.itemAt(0).width : (rootList.visible ? rootList.width : defaultWidth)) - units.smallSpacing focus: true placeholderText: i18n("Search...") clearButtonShown: true onTextChanged: { runnerModel.query = text; } onFocusChanged: { if (focus) { // FIXME: Cleanup arbitration between rootList/runnerCols here and in Keys. if (rootList.visible) { rootList.currentIndex = -1; } if (runnerColumns.visible) { runnerColumnsRepeater.itemAt(0).currentIndex = -1; } } } states: [ State { name: "top" - when: plasmoid.location == PlasmaCore.Types.TopEdge + when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges { target: searchField anchors.top: mainRow.top anchors.bottom: undefined anchors.left: parent.left anchors.right: undefined } PropertyChanges { target: searchField anchors.leftMargin: sideBar.width + mainRow.spacing + units.smallSpacing anchors.rightMargin: undefined } }, State { name: "right" - when: (plasmoid.location == PlasmaCore.Types.RightEdge && Qt.application.layoutDirection == Qt.LeftToRight) - || (plasmoid.location == PlasmaCore.Types.LeftEdge && Qt.application.layoutDirection == Qt.RightToLeft) + when: (plasmoid.location === PlasmaCore.Types.RightEdge && Qt.application.layoutDirection == Qt.LeftToRight) + || (plasmoid.location === PlasmaCore.Types.LeftEdge && Qt.application.layoutDirection == Qt.RightToLeft) AnchorChanges { target: searchField anchors.top: undefined anchors.bottom: mainRow.bottom anchors.left: undefined anchors.right: parent.right } PropertyChanges { target: searchField anchors.leftMargin: undefined anchors.rightMargin: sideBar.width + mainRow.spacing + units.smallSpacing } }] Keys.onPressed: { - if (event.key == Qt.Key_Up) { + if (event.key === Qt.Key_Up) { if (rootList.visible) { rootList.showChildDialogs = false; rootList.currentIndex = rootList.model.count - 1; rootList.forceActiveFocus(); rootList.showChildDialogs = true; } if (runnerColumns.visible) { for (var i = 0; i < runnerModel.count; ++i) { if (runnerModel.modelForRow(i).count) { var targetList = runnerColumnsRepeater.itemAt(i); targetList.currentIndex = runnerModel.modelForRow(i).count - 1; targetList.forceActiveFocus(); break; } } } - } else if (event.key == Qt.Key_Down) { + } else if (event.key === Qt.Key_Down) { if (rootList.visible) { rootList.showChildDialogs = false; rootList.currentIndex = Math.min(1, rootList.count); rootList.forceActiveFocus(); rootList.showChildDialogs = true; } if (runnerColumns.visible) { for (var i = 0; i < runnerModel.count; ++i) { if (runnerModel.modelForRow(i).count) { var targetList = runnerColumnsRepeater.itemAt(i); targetList.currentIndex = Math.min(1, targetList.count); targetList.forceActiveFocus(); break; } } } - } else if (event.key == Qt.Key_Left && cursorPosition == 0) { + } else if (event.key === Qt.Key_Left && cursorPosition == 0) { for (var i = runnerModel.count; i >= 0; --i) { if (runnerModel.modelForRow(i).count) { var targetList = runnerColumnsRepeater.itemAt(i); targetList.currentIndex = 0; targetList.forceActiveFocus(); break; } } - } else if (event.key == Qt.Key_Right && cursorPosition == length) { + } else if (event.key === Qt.Key_Right && cursorPosition == length) { for (var i = 1; i < runnerModel.count; ++i) { if (runnerModel.modelForRow(i).count) { var targetList = runnerColumnsRepeater.itemAt(i); targetList.currentIndex = 0; targetList.forceActiveFocus(); break; } } - } else if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) { + } else if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { if (runnerColumns.visible && runnerModel.modelForRow(0).count) { runnerModel.modelForRow(0).trigger(0, "", null); plasmoid.expanded = false; } } } function appendText(newText) { focus = true; text = text + newText; } } Keys.onPressed: { - if (event.key == Qt.Key_Escape) { + if (event.key === Qt.Key_Escape) { plasmoid.expanded = false; } } Component.onCompleted: { appendSearchText.connect(searchField.appendText); kicker.reset.connect(reset); windowSystem.hidden.connect(reset); } } diff --git a/applets/kicker/package/contents/ui/RunnerResultsList.qml b/applets/kicker/package/contents/ui/RunnerResultsList.qml index 4e6dc2f08..6b767d743 100644 --- a/applets/kicker/package/contents/ui/RunnerResultsList.qml +++ b/applets/kicker/package/contents/ui/RunnerResultsList.qml @@ -1,118 +1,118 @@ /*************************************************************************** * Copyright (C) 2013-2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents FocusScope { width: runnerMatches.width + vertLine.width + vertLine.anchors.leftMargin + runnerMatches.anchors.leftMargin height: parent.height signal keyNavigationAtListEnd property alias currentIndex: runnerMatches.currentIndex property alias count: runnerMatches.count property alias containsMouse: runnerMatches.containsMouse Accessible.name: header.text Accessible.role: Accessible.MenuItem PlasmaCore.SvgItem { id: vertLine anchors.left: parent.left anchors.leftMargin: (index > 0 ) ? units.smallSpacing : 0 width: (index > 0 ) ? lineSvg.vertLineWidth : 0 height: parent.height visible: (index > 0) svg: lineSvg elementId: "vertical-line" } PlasmaComponents.Label { id: header anchors.left: vertLine.right width: runnerMatches.width height: runnerMatches.itemHeight horizontalAlignment: Text.AlignHCenter textFormat: Text.PlainText wrapMode: Text.NoWrap elide: Text.ElideRight font.weight: Font.Bold - text: (runnerMatches.model != null) ? runnerMatches.model.name : "" + text: (runnerMatches.model !== null) ? runnerMatches.model.name : "" } ItemListView { id: runnerMatches anchors.top: plasmoid.configuration.alignResultsToBottom ? undefined : header.bottom anchors.bottom: plasmoid.configuration.alignResultsToBottom ? parent.bottom : undefined - anchors.bottomMargin: (index == 0 && anchors.bottom != undefined) ? searchField.height + (2 * units.smallSpacing) : undefined + anchors.bottomMargin: (index == 0 && anchors.bottom !== undefined) ? searchField.height + (2 * units.smallSpacing) : undefined anchors.left: vertLine.right anchors.leftMargin: (index > 0) ? units.smallSpacing : 0 height: { var listHeight = (((index == 0) ? rootList.height : runnerColumns.height) - header.height); if (model && model.count) { return Math.min(listHeight, model.count * itemHeight); } return listHeight; } focus: true iconsEnabled: true keyNavigationWraps: (index != 0) resetOnExitDelay: 0 model: runnerModel.modelForRow(index) onModelChanged: { - if (model == undefined || model == null) { + if (model === undefined || model === null) { enabled: false; visible: false; } } onCountChanged: { if (index == 0 && searchField.focus) { currentIndex = 0; } } } Component.onCompleted: { runnerMatches.keyNavigationAtListEnd.connect(keyNavigationAtListEnd); } } diff --git a/applets/kicker/package/contents/ui/SideBarItem.qml b/applets/kicker/package/contents/ui/SideBarItem.qml index d67d24cea..95539dda5 100644 --- a/applets/kicker/package/contents/ui/SideBarItem.qml +++ b/applets/kicker/package/contents/ui/SideBarItem.qml @@ -1,156 +1,156 @@ /*************************************************************************** * Copyright (C) 2013-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.kquickcontrolsaddons 2.0 import "code/tools.js" as Tools Item { id: item width: root.width height: root.width signal actionTriggered(string actionId, variant actionArgument) signal aboutToShowActionMenu(variant actionMenu) - property bool hasActionList: ((model.favoriteId != null) - || (("hasActionList" in model) && (model.hasActionList != null))) + property bool hasActionList: ((model.favoriteId !== null) + || (("hasActionList" in model) && (model.hasActionList !== null))) property int itemIndex: model.index onAboutToShowActionMenu: { - var actionList = (model.hasActionList != null) ? model.actionList : []; + var actionList = (model.hasActionList !== null) ? model.actionList : []; Tools.fillActionMenu(i18n, actionMenu, actionList, repeater.model, model.favoriteId); } onActionTriggered: { if (Tools.triggerAction(repeater.model, model.index, actionId, actionArgument) === true) { plasmoid.expanded = false; } } function openActionMenu(visualParent, x, y) { aboutToShowActionMenu(actionMenu); actionMenu.visualParent = visualParent; actionMenu.open(x, y); } ActionMenu { id: actionMenu onActionClicked: { actionTriggered(actionId, actionArgument); } } PlasmaCore.IconItem { anchors.fill: parent active: toolTip.containsMouse source: model.decoration usesPlasmaTheme: repeater.usesPlasmaTheme } MouseEventListener { id: listener anchors { fill: parent leftMargin: - sideBar.margins.left rightMargin: - sideBar.margins.right } enabled: (item.parent && !item.parent.animating) property bool pressed: false property int pressX: -1 property int pressY: -1 hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: { if (mouse.buttons & Qt.RightButton) { if (item.hasActionList) { item.openActionMenu(item, mouse.x, mouse.y); } } else { pressed = true; pressX = mouse.x; pressY = mouse.y; } } onReleased: { if (pressed) { repeater.model.trigger(index, "", null); plasmoid.expanded = false; } pressed = false; pressX = -1; pressY = -1; } onContainsMouseChanged: { if (!containsMouse) { pressed = false; pressX = -1; pressY = -1; } } onPositionChanged: { if (pressX != -1 && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { kicker.dragSource = item; dragHelper.startDrag(kicker, model.url, model.icon); pressed = false; pressX = -1; pressY = -1; return; } } } PlasmaCore.ToolTipArea { id: toolTip property string text: model.display anchors { fill: parent leftMargin: - sideBar.margins.left rightMargin: - sideBar.margins.right } interactive: false location: (((plasmoid.location == PlasmaCore.Types.RightEdge) || (Qt.application.layoutDirection == Qt.RightToLeft)) ? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge) mainItem: toolTipDelegate } } diff --git a/applets/kicker/package/contents/ui/SideBarSection.qml b/applets/kicker/package/contents/ui/SideBarSection.qml index 9aa6a2eb9..31fac3ab9 100644 --- a/applets/kicker/package/contents/ui/SideBarSection.qml +++ b/applets/kicker/package/contents/ui/SideBarSection.qml @@ -1,99 +1,99 @@ /*************************************************************************** * Copyright (C) 2013-2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.draganddrop 2.0 DropArea { id: root width: units.iconSizes.medium height: contentHeight anchors.horizontalCenter: parent.horizontalCenter property int contentHeight: model ? (model.count * units.iconSizes.medium) + ((model.count - 1) * flow.spacing) : 0 property alias model: repeater.model property alias usesPlasmaTheme: repeater.usesPlasmaTheme onDragMove: { if (flow.animating) { return; } var above = flow.childAt(event.x, event.y); - if (above && above != kicker.dragSource && dragSource.parent == flow) { + if (above && above !== kicker.dragSource && dragSource.parent == flow) { repeater.model.moveRow(dragSource.itemIndex, above.itemIndex); } } Flow { id: flow anchors.fill: parent property bool animating: false property int animationDuration: resetAnimationDurationTimer.interval move: Transition { SequentialAnimation { PropertyAction { target: flow; property: "animating"; value: true } NumberAnimation { duration: flow.animationDuration properties: "x, y" easing.type: Easing.OutQuad } PropertyAction { target: flow; property: "animating"; value: false } } } spacing: (2 * units.smallSpacing) Repeater { id: repeater property bool usesPlasmaTheme: false delegate: SideBarItem {} onCountChanged: { flow.animationDuration = 0; resetAnimationDurationTimer.start(); } } } Timer { id: resetAnimationDurationTimer interval: 150 repeat: false onTriggered: { flow.animationDuration = interval - 20; } } } diff --git a/applets/kicker/package/contents/ui/main.qml b/applets/kicker/package/contents/ui/main.qml index 4f20924ea..8a9092453 100644 --- a/applets/kicker/package/contents/ui/main.qml +++ b/applets/kicker/package/contents/ui/main.qml @@ -1,281 +1,281 @@ /*************************************************************************** * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.private.kicker 0.1 as Kicker Item { id: kicker anchors.fill: parent signal reset - property bool isDash: (plasmoid.pluginName == "org.kde.plasma.kickerdash") + property bool isDash: (plasmoid.pluginName === "org.kde.plasma.kickerdash") Plasmoid.switchWidth: isDash || !Plasmoid.fullRepresentationItem ? 0 : Plasmoid.fullRepresentationItem.Layout.minimumWidth Plasmoid.switchHeight: isDash || !Plasmoid.fullRepresentationItem ? 0 : Plasmoid.fullRepresentationItem.Layout.minimumHeight // this is a bit of a hack to prevent Plasma from spawning a dialog on its own when we're Dash Plasmoid.preferredRepresentation: isDash ? Plasmoid.fullRepresentation : null Plasmoid.compactRepresentation: isDash ? null : compactRepresentation Plasmoid.fullRepresentation: isDash ? compactRepresentation : menuRepresentation property QtObject itemListDialogComponent: Qt.createComponent("ItemListDialog.qml"); property Item dragSource: null property QtObject globalFavorites: rootModel.favoritesModel property QtObject systemFavorites: rootModel.systemFavoritesModel Plasmoid.icon: plasmoid.configuration.useCustomButtonImage ? plasmoid.configuration.customButtonImage : plasmoid.configuration.icon onSystemFavoritesChanged: { systemFavorites.favorites = plasmoid.configuration.favoriteSystemActions; } function action_menuedit() { processRunner.runMenuEditor(); } function updateSvgMetrics() { lineSvg.horLineHeight = lineSvg.elementSize("horizontal-line").height; lineSvg.vertLineWidth = lineSvg.elementSize("vertical-line").width; } Component { id: compactRepresentation CompactRepresentation {} } Component { id: menuRepresentation MenuRepresentation {} } Kicker.RootModel { id: rootModel autoPopulate: false appNameFormat: plasmoid.configuration.appNameFormat flat: isDash ? true : plasmoid.configuration.limitDepth sorted: plasmoid.configuration.alphaSort showSeparators: !isDash appletInterface: plasmoid showAllApps: isDash showTopLevelItems: !isDash showRecentApps: plasmoid.configuration.showRecentApps showRecentDocs: plasmoid.configuration.showRecentDocs showRecentContacts: plasmoid.configuration.showRecentContacts recentOrdering: plasmoid.configuration.recentOrdering onShowRecentAppsChanged: { plasmoid.configuration.showRecentApps = showRecentApps; } onShowRecentDocsChanged: { plasmoid.configuration.showRecentDocs = showRecentDocs; } onShowRecentContactsChanged: { plasmoid.configuration.showRecentContacts = showRecentContacts; } onRecentOrderingChanged: { plasmoid.configuration.recentOrdering = recentOrdering; } Component.onCompleted: { favoritesModel.initForClient("org.kde.plasma.kicker.favorites.instance-" + plasmoid.id) if (!plasmoid.configuration.favoritesPortedToKAstats) { favoritesModel.portOldFavorites(plasmoid.configuration.favoriteApps); plasmoid.configuration.favoritesPortedToKAstats = true; } rootModel.refresh(); } } Connections { target: globalFavorites onFavoritesChanged: { plasmoid.configuration.favoriteApps = target.favorites; } } Connections { target: systemFavorites onFavoritesChanged: { plasmoid.configuration.favoriteSystemActions = target.favorites; } } Connections { target: plasmoid.configuration onFavoriteAppsChanged: { globalFavorites.favorites = plasmoid.configuration.favoriteApps; } onFavoriteSystemActionsChanged: { systemFavorites.favorites = plasmoid.configuration.favoriteSystemActions; } } Kicker.RunnerModel { id: runnerModel appletInterface: plasmoid favoritesModel: globalFavorites runners: { var runners = new Array("services"); if (isDash) { runners = runners.concat(new Array("desktopsessions", "PowerDevil")); } if (plasmoid.configuration.useExtraRunners) { runners = runners.concat(plasmoid.configuration.extraRunners); } return runners; } deleteWhenEmpty: isDash } Kicker.DragHelper { id: dragHelper dragIconSize: units.iconSizes.medium } Kicker.ProcessRunner { id: processRunner; } Kicker.WindowSystem { id: windowSystem; } PlasmaCore.FrameSvgItem { id : highlightItemSvg visible: false imagePath: "widgets/viewitem" prefix: "hover" } PlasmaCore.FrameSvgItem { id : listItemSvg visible: false imagePath: "widgets/listitem" prefix: "normal" } PlasmaCore.Svg { id: arrows imagePath: "widgets/arrows" size: "16x16" } PlasmaCore.Svg { id: lineSvg imagePath: "widgets/line" property int horLineHeight property int vertLineWidth } PlasmaComponents.Label { id: toolTipDelegate width: contentWidth height: undefined property Item toolTip text: (toolTip != null) ? toolTip.text : "" } Timer { id: justOpenedTimer repeat: false interval: 600 } Connections { target: plasmoid onExpandedChanged: { if (expanded) { windowSystem.monitorWindowVisibility(plasmoid.fullRepresentationItem); justOpenedTimer.start(); } else { kicker.reset(); } } } function resetDragSource() { dragSource = null; } function enableHideOnWindowDeactivate() { plasmoid.hideOnWindowDeactivate = true; } Component.onCompleted: { if (plasmoid.hasOwnProperty("activationTogglesExpanded")) { plasmoid.activationTogglesExpanded = !isDash } windowSystem.focusIn.connect(enableHideOnWindowDeactivate); plasmoid.hideOnWindowDeactivate = true; if (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) { plasmoid.setAction("menuedit", i18n("Edit Applications..."), "kmenuedit"); } updateSvgMetrics(); theme.themeChanged.connect(updateSvgMetrics); rootModel.refreshed.connect(reset); dragHelper.dropped.connect(resetDragSource); } } diff --git a/applets/kickoff/package/contents/ui/ActionMenu.qml b/applets/kickoff/package/contents/ui/ActionMenu.qml index 3f624c14b..2d244e501 100644 --- a/applets/kickoff/package/contents/ui/ActionMenu.qml +++ b/applets/kickoff/package/contents/ui/ActionMenu.qml @@ -1,144 +1,144 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents Item { id: root property QtObject menu property Item visualParent property variant actionList - property bool opened: menu ? (menu.status != PlasmaComponents.DialogStatus.Closed) : false + property bool opened: menu ? (menu.status !== PlasmaComponents.DialogStatus.Closed) : false signal actionClicked(string actionId, variant actionArgument) signal closed onActionListChanged: refreshMenu(); onOpenedChanged: { if (!opened) { closed(); } } function open(x, y) { if (!actionList || !actionList.length) { return; } if (x && y) { menu.open(x, y); } else { menu.open(); } } function refreshMenu() { if (menu) { menu.destroy(); } if (!actionList) { return; } menu = contextMenuComponent.createObject(root); // actionList.forEach(function(actionItem) { // var item = contextMenuItemComponent.createObject(menu, { // "actionItem": actionItem, // }); // }); fillMenu(menu, actionList); } function fillMenu(menu, items) { items.forEach(function(actionItem) { if (actionItem.subActions) { // This is a menu var submenuItem = contextSubmenuItemComponent.createObject( menu, { "actionItem" : actionItem }); fillMenu(submenuItem.submenu, actionItem.subActions); } else { var item = contextMenuItemComponent.createObject( menu, { "actionItem": actionItem, } ); } }); } Component { id: contextMenuComponent PlasmaComponents.ContextMenu { visualParent: root.visualParent } } Component { id: contextSubmenuItemComponent PlasmaComponents.MenuItem { id: submenuItem property variant actionItem text: actionItem.text ? actionItem.text : "" icon: actionItem.icon ? actionItem.icon : null property variant submenu : submenu_ PlasmaComponents.ContextMenu { id: submenu_ visualParent: submenuItem.action } } } Component { id: contextMenuItemComponent PlasmaComponents.MenuItem { property variant actionItem text : actionItem.text ? actionItem.text : "" - enabled : actionItem.type != "title" && ("enabled" in actionItem ? actionItem.enabled : true) - separator : actionItem.type == "separator" - section : actionItem.type == "title" + enabled : actionItem.type !== "title" && ("enabled" in actionItem ? actionItem.enabled : true) + separator : actionItem.type === "separator" + section : actionItem.type === "title" icon : actionItem.icon ? actionItem.icon : null checkable : actionItem.checkable ? actionItem.checkable : false checked : actionItem.checked ? actionItem.checked : false onClicked: { actionClicked(actionItem.actionId, actionItem.actionArgument); } } } } diff --git a/applets/kickoff/package/contents/ui/ConfigButtons.qml b/applets/kickoff/package/contents/ui/ConfigButtons.qml index b8e93cc8d..88a808f49 100644 --- a/applets/kickoff/package/contents/ui/ConfigButtons.qml +++ b/applets/kickoff/package/contents/ui/ConfigButtons.qml @@ -1,212 +1,212 @@ /* * Copyright 2016 John Salatas * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.0 as Layouts import QtQuick.Controls 1.0 as Controls import QtQml.Models 2.1 import org.kde.plasma.core 2.0 as PlasmaCore GridView { id: configButtons cellHeight: units.gridUnit * 5 cellWidth: units.gridUnit * 6 width: cellWidth * 5 height: cellHeight * 2 property var items: { "bookmark": { icon: "bookmarks", text: i18n("Favorites")}, "application": { icon: "applications-other", text: i18n("Applications")}, "computer": { icon: "pm", text: i18n("Computer")}, "used": { icon: "view-history", text: i18n("History")}, "oftenUsed": { icon: "office-chart-pie", text: i18n("Often Used")}, "leave": { icon: "system-log-out", text: i18n("Leave")} } property var menuItems property var previousCell: [-1, -1] property alias listModel: visualModel.model property int sourceIndex: -1 Component.onCompleted: { menuItems = plasmoid.configuration.menuItems; resetModel(); } function updateModel() { var enabledItems = []; var disabledItems = []; for(var i = 0; i < menuItems.length; i++) { var confItemName = menuItems[i].substring(0, menuItems[i].indexOf(":")); - var confItemEnabled = menuItems[i].substring(menuItems[i].length-1) == "t"; + var confItemEnabled = menuItems[i].substring(menuItems[i].length-1) === "t"; var listItem = items[confItemName]; listItem['name'] = confItemName; listItem['enabled'] = confItemEnabled; if(confItemEnabled) { enabledItems.push(listItem); } else { disabledItems.push(listItem); } } fillEmpty(enabledItems); fillEmpty(disabledItems); return enabledItems.concat(disabledItems); } function fillEmpty(list) { var emptyItem = { icon: undefined, text: undefined, name: 'empty', enabled: undefined}; var itemsToAdd = 5 - list.length; for(var j = 0; j < itemsToAdd; j++) { list.push(emptyItem); } } function updateConfiguration() { menuItems = []; for(var i = 0; i < visualModel.items.count; i++) { var itemName = visualModel.items.get(i).model['name']; - if(itemName != 'empty') { + if(itemName !== 'empty') { var configItem = itemName +":" +(i<5?"t":"f"); menuItems.push(configItem); } } resetModel(); } function resetModel() { listModel.clear(); var items = updateModel(); for(var i = 0; i< items.length; i++) { listModel.append(items[i]); } } displaced: Transition { NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } } PlasmaCore.DataSource { id: pmSource engine: "powermanagement" connectedSources: ["PowerDevil"] } model: DelegateModel { id: visualModel model: ListModel { id: listModel } delegate: MouseArea { id: delegateRoot width: units.gridUnit * 6 height: units.gridUnit * 5 property int visualIndex: DelegateModel.itemsIndex drag.target: button onReleased: { button.Drag.drop() } KickoffConfigurationButton { id: button - icon: model.icon == "pm" ? (pmSource.data["PowerDevil"] && pmSource.data["PowerDevil"]["Is Lid Present"] ? "computer-laptop" : "computer") : model.icon + icon: model.icon === "pm" ? (pmSource.data["PowerDevil"] && pmSource.data["PowerDevil"]["Is Lid Present"] ? "computer-laptop" : "computer") : model.icon text: model.text || "" name: model.name anchors { horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter } Drag.active: delegateRoot.drag.active && name != 'empty' Drag.source: delegateRoot Drag.hotSpot.x: 36 Drag.hotSpot.y: 36 onStateChanged: { if(!Drag.active && sourceIndex != -1) { sourceIndex = -1; updateConfiguration(); } } states: [ State { when: button.Drag.active ParentChange { target: button; parent: root; } AnchorChanges { target: button; anchors.horizontalCenter: undefined; anchors.verticalCenter: undefined; } } ] } DropArea { anchors { fill: parent; margins: 15 } onEntered: { var source = drag.source.visualIndex; var target = delegateRoot.visualIndex; sourceIndex = drag.source.visualIndex; - if(!(previousCell[0] == source && previousCell[1] == target)) { + if(!(previousCell[0] === source && previousCell[1] === target)) { previousCell = [source, target]; if(source < 5 && target >= 5) { visualModel.items.move(source, target); - visualModel.items.move(target == 9 ? 8 : 9, 4); + visualModel.items.move(target === 9 ? 8 : 9, 4); } else if (source >= 5 && target < 5) { visualModel.items.move(source, target); visualModel.items.move(5, 9); } else { visualModel.items.move(source, target); } } } onDropped: { var targetIndex = drag.source.visualIndex; updateConfiguration(); sourceIndex = -1; previousCell = [-1, -1]; } } } } } diff --git a/applets/kickoff/package/contents/ui/FullRepresentation.qml b/applets/kickoff/package/contents/ui/FullRepresentation.qml index 6cfaa0671..6b393a159 100644 --- a/applets/kickoff/package/contents/ui/FullRepresentation.qml +++ b/applets/kickoff/package/contents/ui/FullRepresentation.qml @@ -1,820 +1,820 @@ /* Copyright (C) 2011 Martin Gräßlin Copyright (C) 2012 Gregor Taetzner Copyright (C) 2012 Marco Martin Copyright (C) 2013 2014 David Edmundson Copyright 2014 Sebastian Kügler 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. */ import QtQuick 2.3 import org.kde.plasma.plasmoid 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.private.kicker 0.1 as Kicker Item { id: root Layout.minimumWidth: units.gridUnit * 26 Layout.maximumWidth: Layout.minimumWidth Layout.minimumHeight: units.gridUnit * 34 Layout.maximumHeight: Layout.minimumHeight property string previousState property bool switchTabsOnHover: plasmoid.configuration.switchTabsOnHover property Item currentView: mainTabGroup.currentTab.decrementCurrentIndex ? mainTabGroup.currentTab : mainTabGroup.currentTab.item property KickoffButton firstButton: null property var configMenuItems property QtObject globalFavorites: rootModelFavorites state: "Normal" onFocusChanged: { header.input.forceActiveFocus(); } function switchToInitial() { if (firstButton != null) { root.state = "Normal"; mainTabGroup.currentTab = firstButton.tab; tabBar.currentTab = firstButton; header.query = "" } } Kicker.DragHelper { id: dragHelper dragIconSize: units.iconSizes.medium onDropped: kickoff.dragSource = null } Kicker.AppsModel { id: rootModel autoPopulate: false appletInterface: plasmoid appNameFormat: plasmoid.configuration.showAppsByName ? 0 : 1 flat: false sorted: plasmoid.configuration.alphaSort showSeparators: false showTopLevelItems: true favoritesModel: Kicker.KAStatsFavoritesModel { id: rootModelFavorites favorites: plasmoid.configuration.favorites onFavoritesChanged: { plasmoid.configuration.favorites = favorites; } } Component.onCompleted: { favoritesModel.initForClient("org.kde.plasma.kickoff.favorites.instance-" + plasmoid.id) if (!plasmoid.configuration.favoritesPortedToKAstats) { favoritesModel.portOldFavorites(plasmoid.configuration.favorites); plasmoid.configuration.favoritesPortedToKAstats = true; } rootModel.refresh(); } } PlasmaCore.DataSource { id: pmSource engine: "powermanagement" connectedSources: ["PowerDevil"] } PlasmaCore.Svg { id: arrowsSvg imagePath: "widgets/arrows" size: "16x16" } Header { id: header } Rectangle { id: headerSeparator height: Math.floor(units.devicePixelRatio) color: Qt.tint(PlasmaCore.ColorScope.textColor, Qt.rgba(PlasmaCore.ColorScope.backgroundColor.r, PlasmaCore.ColorScope.backgroundColor.g, PlasmaCore.ColorScope.backgroundColor.b, 0.7)) opacity: 0.6 width: root.width - 2 * units.gridUnit anchors { top: header.top horizontalCenter: header.horizontalCenter } } Item { id: mainArea anchors.topMargin: mainTabGroup.state == "top" ? units.smallSpacing : 0 PlasmaComponents.TabGroup { id: mainTabGroup currentTab: favoritesPage anchors { fill: parent } //pages FavoritesView { id: favoritesPage } PlasmaExtras.ConditionalLoader { id: applicationsPage when: mainTabGroup.currentTab == applicationsPage source: Qt.resolvedUrl("ApplicationsView.qml") } PlasmaExtras.ConditionalLoader { id: systemPage when: mainTabGroup.currentTab == systemPage source: Qt.resolvedUrl("ComputerView.qml") } PlasmaExtras.ConditionalLoader { id: recentlyUsedPage when: mainTabGroup.currentTab == recentlyUsedPage source: Qt.resolvedUrl("RecentlyUsedView.qml") } PlasmaExtras.ConditionalLoader { id: oftenUsedPage when: mainTabGroup.currentTab == oftenUsedPage source: Qt.resolvedUrl("OftenUsedView.qml") } PlasmaExtras.ConditionalLoader { id: leavePage when: mainTabGroup.currentTab == leavePage source: Qt.resolvedUrl("LeaveView.qml") } PlasmaExtras.ConditionalLoader { id: searchPage when: root.state == "Search" //when: mainTabGroup.currentTab == searchPage || root.state == "Search" source: Qt.resolvedUrl("SearchView.qml") } state: { switch (plasmoid.location) { case PlasmaCore.Types.LeftEdge: return LayoutMirroring.enabled ? "right" : "left"; case PlasmaCore.Types.TopEdge: return "top"; case PlasmaCore.Types.RightEdge: return LayoutMirroring.enabled ? "left" : "right"; case PlasmaCore.Types.BottomEdge: default: return "bottom"; } } states: [ State { name: "left" AnchorChanges { target: header anchors { left: root.left top: undefined right: root.right bottom: root.bottom } } PropertyChanges { target: header width: header.implicitWidth } AnchorChanges { target: mainArea anchors { left: tabBar.right top: root.top right: root.right bottom: header.top } } AnchorChanges { target: tabBar anchors { left: root.left top: root.top right: undefined bottom: header.top } } PropertyChanges { target:tabBarSeparator width: Math.floor(units.devicePixelRatio) height: root.height } AnchorChanges { target: tabBarSeparator anchors { left: tabBar.right top: tabBar.top right: undefined bottom: tabBar.bottom } } }, State { name: "top" AnchorChanges { target: header anchors { left: root.left top: undefined right: root.right bottom: root.bottom } } PropertyChanges { target: header height: header.implicitHeight } AnchorChanges { target: mainArea anchors { left: root.left top: tabBar.bottom right: root.right bottom: header.top } } AnchorChanges { target: tabBar anchors { left: root.left top: root.top right: root.right bottom: undefined } } PropertyChanges { target:tabBarSeparator width: root.width height: Math.floor(units.devicePixelRatio) } AnchorChanges { target: tabBarSeparator anchors { left: root.left top: tabBar.bottom right: root.right bottom: undefined } } }, State { name: "right" AnchorChanges { target: header anchors { left: root.left top: undefined right: root.right bottom: root.bottom } } PropertyChanges { target: header width: header.implicitWidth } AnchorChanges { target: mainArea anchors { left: root.left top: root.top right: tabBar.left bottom: header.top } } AnchorChanges { target: tabBar anchors { left: undefined top: root.top right: root.right bottom: header.top } } PropertyChanges { target:tabBarSeparator width: Math.floor(units.devicePixelRatio) height: root.height } AnchorChanges { target: tabBarSeparator anchors { left: undefined top: tabBar.top right: tabBar.left bottom: tabBar.bottom } } }, State { name: "bottom" AnchorChanges { target: header anchors { left: root.left top: root.top right: root.right bottom: undefined } } PropertyChanges { target: header height: header.implicitHeight } AnchorChanges { target: headerSeparator anchors { top: undefined bottom: header.bottom horizontalCenter: header.horizontalCenter } } AnchorChanges { target: mainArea anchors { left: root.left top: header.bottom right: root.right bottom: tabBar.top } } AnchorChanges { target: tabBar anchors { left: root.left top: undefined right: root.right bottom: root.bottom } } PropertyChanges { target:tabBarSeparator width: root.width height: Math.floor(units.devicePixelRatio) } AnchorChanges { target: tabBarSeparator anchors { left: root.left top: undefined right: root.right bottom: tabBar.top } } } ] } // mainTabGroup } PlasmaComponents.TabBar { id: tabBar property int count: 5 // updated in createButtons() width: { if (opacity == 0) { return 0; } switch (plasmoid.location) { case PlasmaCore.Types.LeftEdge: case PlasmaCore.Types.RightEdge: return units.gridUnit * 5; default: return 0; } } height: { if (opacity == 0) { return 0; } switch (plasmoid.location) { case PlasmaCore.Types.LeftEdge: case PlasmaCore.Types.RightEdge: return 0; default: return units.gridUnit * 5; } } Behavior on width { NumberAnimation { duration: units.longDuration; easing.type: Easing.InQuad; } enabled: plasmoid.expanded } Behavior on height { NumberAnimation { duration: units.longDuration; easing.type: Easing.InQuad; } enabled: plasmoid.expanded } tabPosition: { switch (plasmoid.location) { case PlasmaCore.Types.TopEdge: return Qt.TopEdge; case PlasmaCore.Types.LeftEdge: return Qt.LeftEdge; case PlasmaCore.Types.RightEdge: return Qt.RightEdge; default: return Qt.BottomEdge; } } onCurrentTabChanged: header.input.forceActiveFocus(); Connections { target: plasmoid onExpandedChanged: { if(menuItemsChanged()) { createButtons(); } if (!expanded) { switchToInitial(); } } } } // tabBar Rectangle { id: tabBarSeparator width: root.width height: Math.floor(units.devicePixelRatio) color: Qt.tint(PlasmaCore.ColorScope.textColor, Qt.rgba(PlasmaCore.ColorScope.backgroundColor.r, PlasmaCore.ColorScope.backgroundColor.g, PlasmaCore.ColorScope.backgroundColor.b, 0.7)) opacity: 0.6 anchors { top: header.top left: root.left right: root.right } } MouseArea { anchors.fill: tabBar property var oldPos: null hoverEnabled: root.switchTabsOnHover onExited: { // Reset so we switch immediately when MouseArea is entered // freshly, e.g. from the panel. oldPos = null; clickTimer.stop(); } onPositionChanged: { var button = tabBar.layout.childAt(mouse.x, mouse.y); - if (!button || button.objectName != "KickoffButton") { + if (!button || button.objectName !== "KickoffButton") { clickTimer.stop(); return; } // Switch immediately when MouseArea was freshly entered, e.g. // from the panel. if (oldPos === null) { oldPos = Qt.point(mouse.x, mouse.y); clickTimer.stop(); button.clicked(); return; } var dx = (mouse.x - oldPos.x); var dy = (mouse.y - oldPos.y); // Check Manhattan length against drag distance to get a decent // pointer motion vector. if ((Math.abs(dx) + Math.abs(dy)) > Qt.styleHints.startDragDistance) { - if (tabBar.currentTab != button) { + if (tabBar.currentTab !== button) { var tabBarPos = mapToItem(tabBar, oldPos.x, oldPos.y); oldPos = Qt.point(mouse.x, mouse.y); var angleMouseMove = Math.atan2(dy, dx) * 180 / Math.PI; var angleToCornerA = 0; var angleToCornerB = 0; switch (plasmoid.location) { case PlasmaCore.Types.TopEdge: { angleToCornerA = Math.atan2(tabBar.height - tabBarPos.y, 0 - tabBarPos.x); angleToCornerB = Math.atan2(tabBar.height - tabBarPos.y, tabBar.width - tabBarPos.x); break; } case PlasmaCore.Types.LeftEdge: { angleToCornerA = Math.atan2(0 - tabBarPos.y, tabBar.width - tabBarPos.x); angleToCornerB = Math.atan2(tabBar.height - tabBarPos.y, tabBar.width - tabBarPos.x); break; } case PlasmaCore.Types.RightEdge: { angleToCornerA = Math.atan2(0 - tabBarPos.y, 0 - tabBarPos.x); angleToCornerB = Math.atan2(tabBar.height - tabBarPos.y, 0 - tabBarPos.x); break; } // PlasmaCore.Types.BottomEdge default: { angleToCornerA = Math.atan2(0 - tabBarPos.y, 0 - tabBarPos.x); angleToCornerB = Math.atan2(0 - tabBarPos.y, tabBar.width - tabBarPos.x); } } // Degrees are nicer to debug than radians. angleToCornerA = angleToCornerA * 180 / Math.PI; angleToCornerB = angleToCornerB * 180 / Math.PI; var lower = Math.min(angleToCornerA, angleToCornerB); var upper = Math.max(angleToCornerA, angleToCornerB); // If the motion vector is outside the angle range from oldPos to the // relevant tab bar corners, switch immediately. Otherwise start the // timer, which gets aborted should the pointer exit the tab bar // early. var inRange = (lower < angleMouseMove == angleMouseMove < upper); // Mirror-flip. - if (plasmoid.location == PlasmaCore.Types.RightEdge ? inRange : !inRange) { + if (plasmoid.location === PlasmaCore.Types.RightEdge ? inRange : !inRange) { clickTimer.stop(); button.clicked(); return; } else { clickTimer.pendingButton = button; clickTimer.start(); } } else { oldPos = Qt.point(mouse.x, mouse.y); } } } onClicked: { clickTimer.stop(); var button = tabBar.layout.childAt(mouse.x, mouse.y); - if (!button || button.objectName != "KickoffButton") { + if (!button || button.objectName !== "KickoffButton") { return; } button.clicked(); } Timer { id: clickTimer property Item pendingButton: null interval: 250 onTriggered: { if (pendingButton) { pendingButton.clicked(); } } } } Keys.forwardTo: [tabBar.layout] Keys.onPressed: { if (mainTabGroup.currentTab == applicationsPage) { - if (event.key != Qt.Key_Tab) { + if (event.key !== Qt.Key_Tab) { root.state = "Applications"; } } switch(event.key) { case Qt.Key_Up: { currentView.decrementCurrentIndex(); event.accepted = true; break; } case Qt.Key_Down: { currentView.incrementCurrentIndex(); event.accepted = true; break; } case Qt.Key_Left: { if (header.input.focus && header.state == "query") { break; } if (!currentView.deactivateCurrentIndex()) { if (root.state == "Applications") { mainTabGroup.currentTab = firstButton.tab; tabBar.currentTab = firstButton; } root.state = "Normal" } event.accepted = true; break; } case Qt.Key_Right: { if (header.input.focus && header.state == "query") { break; } currentView.activateCurrentIndex(); event.accepted = true; break; } case Qt.Key_Tab: { root.state == "Applications" ? root.state = "Normal" : root.state = "Applications"; event.accepted = true; break; } case Qt.Key_Enter: case Qt.Key_Return: { currentView.activateCurrentIndex(1); event.accepted = true; break; } case Qt.Key_Escape: { if (header.state != "query") { plasmoid.expanded = false; } else { header.query = ""; } event.accepted = true; break; } case Qt.Key_Menu: { currentView.openContextMenu(); event.accepted = true; break; } default: if (!header.input.focus) { header.input.forceActiveFocus(); } } } states: [ State { name: "Normal" PropertyChanges { target: root Keys.forwardTo: [tabBar.layout] } PropertyChanges { target: tabBar //Set the opacity and NOT the visibility, as visibility is recursive //and this binding would be executed also on popup show/hide //as recommended by the docs: http://doc.qt.io/qt-5/qml-qtquick-item.html#visible-prop //plus, it triggers https://bugreports.qt.io/browse/QTBUG-66907 //in which a mousearea may think it's under the mouse while it isn't opacity: tabBar.count > 1 ? 1 : 0 } }, State { name: "Applications" PropertyChanges { target: root Keys.forwardTo: [root] } PropertyChanges { target: tabBar opacity: tabBar.count > 1 ? 1 : 0 } }, State { name: "Search" PropertyChanges { target: tabBar opacity: 0 } PropertyChanges { target: mainTabGroup currentTab: searchPage } PropertyChanges { target: root Keys.forwardTo: [root] } } ] // states function getButtonDefinition(name) { switch(name) { case "bookmark": return {id: "bookmarkButton", tab: favoritesPage, iconSource: "bookmarks", text: i18n("Favorites")}; case "application": return {id: "applicationButton", tab: applicationsPage, iconSource: "applications-other", text: i18n("Applications")}; case "computer": return {id: "computerButton", tab: systemPage, iconSource: pmSource.data["PowerDevil"] && pmSource.data["PowerDevil"]["Is Lid Present"] ? "computer-laptop" : "computer", text: i18n("Computer")}; case "used": return {id: "usedButton", tab: recentlyUsedPage, iconSource: "view-history", text: i18n("History")}; case "oftenUsed": return {id: "usedButton", tab: oftenUsedPage, iconSource: "office-chart-pie", text: i18n("Often Used")}; case "leave": return {id: "leaveButton", tab: leavePage, iconSource: "system-log-out", text: i18n("Leave")}; } } Component { id: kickoffButton KickoffButton {} } Component.onCompleted: { createButtons(); } function getEnabled(configuration) { var res = []; for(var i = 0; i < configuration.length; i++) { var confItemName = configuration[i].substring(0, configuration[i].indexOf(":")); - var confItemEnabled = configuration[i].substring(configuration[i].length-1) == "t"; + var confItemEnabled = configuration[i].substring(configuration[i].length-1) === "t"; if(confItemEnabled) { res.push(confItemName); } } return res; } function createButtons() { configMenuItems = plasmoid.configuration.menuItems; var menuItems = getEnabled(plasmoid.configuration.menuItems); tabBar.count = menuItems.length // remove old menu items for(var i = tabBar.layout.children.length -1; i >= 0; i--) { - if(tabBar.layout.children[i].objectName == "KickoffButton") { + if(tabBar.layout.children[i].objectName === "KickoffButton") { tabBar.layout.children[i].destroy(); } } for (var i = 0; i < menuItems.length; i++) { var props = getButtonDefinition(menuItems[i]); var button = kickoffButton.createObject(tabBar.layout, props); - if(i == 0) { + if(i === 0) { firstButton = button; switchToInitial(); } } } function menuItemsChanged() { - if(configMenuItems.length != plasmoid.configuration.menuItems.length) { + if(configMenuItems.length !== plasmoid.configuration.menuItems.length) { return true; } for(var i = 0; i < configMenuItems.length; i++) { - if(configMenuItems[i] != plasmoid.configuration.menuItems[i]) { + if(configMenuItems[i] !== plasmoid.configuration.menuItems[i]) { return true; } } return false; } } diff --git a/applets/kickoff/package/contents/ui/Header.qml b/applets/kickoff/package/contents/ui/Header.qml index 0f1c7aca7..c3d4d6acf 100644 --- a/applets/kickoff/package/contents/ui/Header.qml +++ b/applets/kickoff/package/contents/ui/Header.qml @@ -1,188 +1,188 @@ /* * Copyright 2014 Sebastian Kügler * * 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. */ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kcoreaddons 1.0 as KCoreAddons import org.kde.kquickcontrolsaddons 2.0 Item { id: header implicitHeight: units.gridUnit * 5 property alias query: queryField.text property Item input: queryField KCoreAddons.KUser { id: kuser } state: "name" states: [ State { name: "name" PropertyChanges { target: nameLabel opacity: 1 } PropertyChanges { target: infoLabel opacity: 0 } }, State { name: "info" PropertyChanges { target: nameLabel opacity: 0 } PropertyChanges { target: infoLabel opacity: 1 } } ] // states Image { id: faceIcon source: kuser.faceIconUrl cache: false visible: source !== "" width: units.gridUnit * 3 height: width sourceSize.width: width sourceSize.height: height fillMode: Image.PreserveAspectFit anchors { top: parent.top left: parent.left topMargin: units.gridUnit leftMargin: units.gridUnit } } PlasmaCore.IconItem { source: "user-identity" visible: faceIcon.status !== Image.Ready width: units.gridUnit * 3 height: width anchors { top: faceIcon.top right: faceIcon.right rightMargin: -units.gridUnit/2 } usesPlasmaTheme: false } MouseArea { anchors.fill: faceIcon acceptedButtons: Qt.LeftButton cursorShape: Qt.PointingHandCursor onClicked: { KCMShell.open("user_manager") } visible: KCMShell.authorize("user_manager.desktop").length > 0 } PlasmaExtras.Heading { id: nameLabel level: 2 text: kuser.fullName elide: Text.ElideRight horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignBottom Behavior on opacity { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutQuad; } } anchors { left: faceIcon.right bottom: queryField.top right: parent.right leftMargin: units.gridUnit rightMargin: units.gridUnit } } PlasmaExtras.Heading { id: infoLabel level: 5 opacity: 0 - text: kuser.os != "" ? i18n("%2@%3 (%1)", kuser.os, kuser.loginName, kuser.host) : i18n("%1@%2", kuser.loginName, kuser.host) + text: kuser.os !== "" ? i18n("%2@%3 (%1)", kuser.os, kuser.loginName, kuser.host) : i18n("%1@%2", kuser.loginName, kuser.host) elide: Text.ElideRight horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignBottom Behavior on opacity { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutQuad; } } anchors { left: faceIcon.right bottom: queryField.top right: parent.right leftMargin: units.gridUnit rightMargin: units.gridUnit } } // Show the info instead of the user's name when hovering over it MouseArea { anchors.fill: nameLabel hoverEnabled: true onEntered: { header.state = "info" } onExited: { header.state = "name" } } PlasmaComponents.TextField { id: queryField placeholderText: i18n("Search...") clearButtonShown: true onTextChanged: { if (root.state != "Search") { root.previousState = root.state; root.state = "Search"; } if (text == "") { root.state = root.previousState; } } anchors { left: faceIcon.right bottom: faceIcon.bottom right: parent.right leftMargin: units.gridUnit rightMargin: units.gridUnit } } } diff --git a/applets/kickoff/package/contents/ui/Kickoff.qml b/applets/kickoff/package/contents/ui/Kickoff.qml index 960f21756..706323e96 100644 --- a/applets/kickoff/package/contents/ui/Kickoff.qml +++ b/applets/kickoff/package/contents/ui/Kickoff.qml @@ -1,148 +1,148 @@ /* Copyright (C) 2011 Martin Gräßlin Copyright (C) 2012 Gregor Taetzner Copyright (C) 2012 Marco Martin Copyright (C) 2013 David Edmundson Copyright (C) 2015 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. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.private.kicker 0.1 as Kicker Item { id: kickoff - readonly property bool inPanel: (plasmoid.location == PlasmaCore.Types.TopEdge - || plasmoid.location == PlasmaCore.Types.RightEdge - || plasmoid.location == PlasmaCore.Types.BottomEdge - || plasmoid.location == PlasmaCore.Types.LeftEdge) - readonly property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) + readonly property bool inPanel: (plasmoid.location === PlasmaCore.Types.TopEdge + || plasmoid.location === PlasmaCore.Types.RightEdge + || plasmoid.location === PlasmaCore.Types.BottomEdge + || plasmoid.location === PlasmaCore.Types.LeftEdge) + readonly property bool vertical: (plasmoid.formFactor === PlasmaCore.Types.Vertical) Plasmoid.switchWidth: units.gridUnit * 20 Plasmoid.switchHeight: units.gridUnit * 30 Plasmoid.fullRepresentation: FullRepresentation {} Plasmoid.icon: plasmoid.configuration.icon Plasmoid.compactRepresentation: MouseArea { id: compactRoot Layout.minimumWidth: { if (!inPanel) { return units.iconSizeHints.panel; } if (vertical) { return -1; } else { return Math.min(units.iconSizeHints.panel, parent.height) * buttonIcon.aspectRatio; } } Layout.minimumHeight: { if (!inPanel) { return units.iconSizeHints.panel; } if (vertical) { return Math.min(units.iconSizeHints.panel, parent.width) * buttonIcon.aspectRatio; } else { return -1; } } Layout.maximumWidth: { if (!inPanel) { return -1; } if (vertical) { return units.iconSizeHints.panel; } else { return Math.min(units.iconSizeHints.panel, parent.height) * buttonIcon.aspectRatio; } } Layout.maximumHeight: { if (!inPanel) { return -1; } if (vertical) { return Math.min(units.iconSizeHints.panel, parent.width) * buttonIcon.aspectRatio; } else { return units.iconSizeHints.panel; } } hoverEnabled: true onClicked: plasmoid.expanded = !plasmoid.expanded DropArea { id: compactDragArea anchors.fill: parent } Timer { id: expandOnDragTimer interval: 250 running: compactDragArea.containsDrag onTriggered: plasmoid.expanded = true } PlasmaCore.IconItem { id: buttonIcon readonly property double aspectRatio: (vertical ? implicitHeight / implicitWidth : implicitWidth / implicitHeight) anchors.fill: parent source: plasmoid.icon active: parent.containsMouse || compactDragArea.containsDrag smooth: true roundToIconSize: aspectRatio === 1 } } property Item dragSource: null Kicker.ProcessRunner { id: processRunner; } function action_menuedit() { processRunner.runMenuEditor(); } Component.onCompleted: { if (plasmoid.hasOwnProperty("activationTogglesExpanded")) { plasmoid.activationTogglesExpanded = true } if (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) { plasmoid.setAction("menuedit", i18n("Edit Applications..."), "kmenuedit"); } } } // root diff --git a/applets/kickoff/package/contents/ui/KickoffItem.qml b/applets/kickoff/package/contents/ui/KickoffItem.qml index 283877b79..83225a9a4 100644 --- a/applets/kickoff/package/contents/ui/KickoffItem.qml +++ b/applets/kickoff/package/contents/ui/KickoffItem.qml @@ -1,180 +1,180 @@ /* Copyright (C) 2011 Martin Gräßlin Copyright (C) 2012 Gregor Taetzner Copyright 2014 Sebastian Kügler Copyright (C) 2015-2018 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. */ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.draganddrop 2.0 import "code/tools.js" as Tools Item { id: listItem width: ListView.view.width height: (units.smallSpacing * 2) + Math.max(elementIcon.height, titleElement.implicitHeight + subTitleElement.implicitHeight) signal reset signal actionTriggered(string actionId, variant actionArgument) signal aboutToShowActionMenu(variant actionMenu) signal addBreadcrumb(var model, string title) readonly property int itemIndex: model.index readonly property string url: model.url || "" readonly property var decoration: model.decoration || "" property bool dropEnabled: false property bool appView: false property bool modelChildren: model.hasChildren || false property bool isCurrent: listItem.ListView.view.currentIndex === index; property bool showAppsByName: plasmoid.configuration.showAppsByName - property bool hasActionList: ((model.favoriteId != null) - || (("hasActionList" in model) && (model.hasActionList == true))) + property bool hasActionList: ((model.favoriteId !== null) + || (("hasActionList" in model) && (model.hasActionList === true))) property Item menu: actionMenu onAboutToShowActionMenu: { var actionList = hasActionList ? model.actionList : []; Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId); } onActionTriggered: { if (Tools.triggerAction(ListView.view.model, model.index, actionId, actionArgument) === true) { plasmoid.expanded = false; } if (actionId.indexOf("_kicker_favorite_") === 0) { switchToInitial(); } } function activate() { var view = listItem.ListView.view; if (model.hasChildren) { var childModel = view.model.modelForRow(index); listItem.addBreadcrumb(childModel, display); view.model = childModel; } else { view.model.trigger(index, "", null); plasmoid.expanded = false; listItem.reset(); } } function openActionMenu(x, y) { aboutToShowActionMenu(actionMenu); actionMenu.visualParent = listItem; actionMenu.open(x, y); } ActionMenu { id: actionMenu onActionClicked: { actionTriggered(actionId, actionArgument); } } PlasmaCore.IconItem { id: elementIcon anchors { left: parent.left leftMargin: (units.gridUnit * 4) - units.iconSizes.medium verticalCenter: parent.verticalCenter } width: units.iconSizes.medium height: width animated: false usesPlasmaTheme: false source: model.decoration } PlasmaComponents.Label { id: titleElement y: Math.round((parent.height - titleElement.height - ( (subTitleElement.text != "") ? subTitleElement.implicitHeight : 0) ) / 2) anchors { //bottom: elementIcon.verticalCenter left: elementIcon.right right: arrow.left leftMargin: units.gridUnit rightMargin: units.gridUnit * 2 } height: implicitHeight //undo PC2 height override, remove when porting to PC3 // TODO: games should always show the by name! text: model.display elide: Text.ElideRight horizontalAlignment: Text.AlignLeft } PlasmaComponents.Label { id: subTitleElement anchors { left: titleElement.left right: arrow.left rightMargin: units.gridUnit * 2 top: titleElement.bottom } height: implicitHeight text: model.description opacity: isCurrent ? 0.8 : 0.6 font.pointSize: theme.smallestFont.pointSize elide: Text.ElideMiddle horizontalAlignment: Text.AlignLeft } PlasmaCore.SvgItem { id: arrow anchors { right: parent.right rightMargin: units.gridUnit * 2 verticalCenter: parent.verticalCenter } width: visible ? units.iconSizes.small : 0 height: width - visible: (model.hasChildren == true) - opacity: (listItem.ListView.view.currentIndex == index) ? 1.0 : 0.4 + visible: (model.hasChildren === true) + opacity: (listItem.ListView.view.currentIndex === index) ? 1.0 : 0.4 svg: arrowsSvg elementId: (Qt.application.layoutDirection == Qt.RightToLeft) ? "left-arrow" : "right-arrow" } Keys.onPressed: { - if (event.key == Qt.Key_Menu && hasActionList) { + if (event.key === Qt.Key_Menu && hasActionList) { event.accepted = true; openActionMenu(); - } else if ((event.key == Qt.Key_Enter || event.key == Qt.Key_Return) && !modelChildren) { + } else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && !modelChildren) { if (!modelChildren) { event.accepted = true; listItem.activate(); } } } } // listItem diff --git a/applets/kimpanel/package/contents/ui/ActionMenu.qml b/applets/kimpanel/package/contents/ui/ActionMenu.qml index 2fe064549..132073c3f 100644 --- a/applets/kimpanel/package/contents/ui/ActionMenu.qml +++ b/applets/kimpanel/package/contents/ui/ActionMenu.qml @@ -1,110 +1,110 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.plasmoid 2.0 Item { id: root property QtObject menu property Item visualParent property variant actionList signal actionClicked(string actionId) onActionListChanged: refreshMenu(); function open() { menu.openRelative(); } function refreshMenu() { if (menu) { menu.destroy(); } menu = contextMenuComponent.createObject(root); - if (!actionList || actionList.length == 0) { + if (!actionList || actionList.length === 0) { var item = emptyMenuItemComponent.createObject(menu); menu.addMenuItem(item); return; } actionList.forEach(function(actionItem) { var item = contextMenuItemComponent.createObject(menu, { "actionItem": actionItem, }); menu.addMenuItem(item); }); } Component { id: contextMenuComponent PlasmaComponents.ContextMenu { visualParent: root.visualParent placement: { - if (plasmoid.location == PlasmaCore.Types.LeftEdge) { + if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return PlasmaCore.Types.RightPosedTopAlignedPopup; - } else if (plasmoid.location == PlasmaCore.Types.TopEdge) { + } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { return PlasmaCore.Types.BottomPosedLeftAlignedPopup; - } else if (plasmoid.location == PlasmaCore.Types.RightEdge) { + } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return PlasmaCore.Types.LeftPosedTopAlignedPopup; } else { return PlasmaCore.Types.TopPosedLeftAlignedPopup; } } } } Component { id: contextMenuItemComponent PlasmaComponents.MenuItem { property variant actionItem text: actionItem.text ? actionItem.text : "" icon: actionItem.icon ? actionItem.icon : null - checkable: actionItem.hint == "checked" - checked: actionItem.hint == "checked" + checkable: actionItem.hint === "checked" + checked: actionItem.hint === "checked" onClicked: { actionClicked(actionItem.actionId); } } } Component { id: emptyMenuItemComponent PlasmaComponents.MenuItem { text: i18n("(Empty)") enabled: false } } } diff --git a/applets/kimpanel/package/contents/ui/ConfigAppearance.qml b/applets/kimpanel/package/contents/ui/ConfigAppearance.qml index 71a8af026..397d6f7f4 100644 --- a/applets/kimpanel/package/contents/ui/ConfigAppearance.qml +++ b/applets/kimpanel/package/contents/ui/ConfigAppearance.qml @@ -1,92 +1,92 @@ /* * Copyright 2014 Weng Xuetian * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 1.0 as QtControls import QtQuick.Dialogs 1.1 as QtDialogs import QtQuick.Layouts 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras Item { id: iconsPage implicitWidth: pageColumn.implicitWidth implicitHeight: pageColumn.implicitHeight property alias cfg_vertical_lookup_table: verticalLookupTable.checked property alias cfg_use_default_font: useDefaultFont.checked property font cfg_font onCfg_fontChanged: { - if (cfg_font.family == '') { + if (cfg_font.family === '') { cfg_font = theme.defaultFont } fontDialog.font = cfg_font } ColumnLayout { id: pageColumn width: parent.width QtControls.CheckBox { id: verticalLookupTable text: i18n("Vertical List") } QtControls.CheckBox { id: useDefaultFont text: i18n("Use Default Font") } RowLayout { width: parent.width QtControls.Label { text: i18n("Custom Font:") } QtControls.TextField { id: fontPreviewLabel Layout.fillWidth: true enabled: !cfg_use_default_font anchors.verticalCenter: parent.verticalCenter readOnly: true font: cfg_font text: cfg_font.family + ' ' + cfg_font.pointSize } QtControls.Button { id: fontButton enabled: !cfg_use_default_font text: i18n("Select Font") onClicked: fontDialog.open(); } } } QtDialogs.FontDialog { id: fontDialog title: i18nc("@title:window", "Select Font") onAccepted: { cfg_font = font } } } diff --git a/applets/kimpanel/package/contents/ui/ContextMenu.qml b/applets/kimpanel/package/contents/ui/ContextMenu.qml index 7e919c425..e00ea8439 100644 --- a/applets/kimpanel/package/contents/ui/ContextMenu.qml +++ b/applets/kimpanel/package/contents/ui/ContextMenu.qml @@ -1,157 +1,157 @@ /*************************************************************************** * Copyright (C) 2013 by Aurélien Gâteau * * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.plasmoid 2.0 Item { id: root property QtObject menu property Item visualParent property variant actionList function open(item, actionItem) { visualParent = item; refreshMenu(actionItem); menu.openRelative(); } function refreshMenu(actionItem) { if (menu) { menu.destroy(); } menu = contextMenuComponent.createObject(root, {"actionItem": actionItem}); if (actionList && actionList.length > 0) { menu.separator.visible = true; actionList.forEach(function(actionItem) { var item = contextMenuItemComponent.createObject(menu.showMenu, { "actionItem": actionItem, }); }); } } Component { id: contextMenuItemComponent PlasmaComponents.MenuItem { property variant actionItem text: actionItem.label icon: actionItem.icon onClicked: { kimpanel.showAction(actionItem.key); } } } Component { id: contextMenuComponent PlasmaComponents.ContextMenu { visualParent: root.visualParent property variant actionItem property Item separator: separatorItem property QtObject showMenu: subShowMenu placement: { - if (plasmoid.location == PlasmaCore.Types.LeftEdge) { + if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return PlasmaCore.Types.RightPosedTopAlignedPopup; - } else if (plasmoid.location == PlasmaCore.Types.TopEdge) { + } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { return PlasmaCore.Types.BottomPosedLeftAlignedPopup; - } else if (plasmoid.location == PlasmaCore.Types.RightEdge) { + } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return PlasmaCore.Types.LeftPosedTopAlignedPopup; } else { return PlasmaCore.Types.TopPosedLeftAlignedPopup; } } PlasmaComponents.MenuItem { id: showItem visible: separatorItem.visible text: i18n("Show") PlasmaComponents.ContextMenu { id: subShowMenu visualParent: showItem.action } } PlasmaComponents.MenuItem { id: separatorItem separator: true visible: false } PlasmaComponents.MenuItem { text: i18n("Hide %1", actionItem.label); onClicked: { kimpanel.hideAction(actionItem.key); } enabled: kimpanel.visibleButtons > 1 visible: kimpanel.visibleButtons > 1 } PlasmaComponents.MenuItem { text: i18n("Configure Input Method") icon: "configure" onClicked: { kimpanel.action("Configure"); } } PlasmaComponents.MenuItem { text: i18n("Reload Config") icon: "view-refresh" onClicked: { kimpanel.action("ReloadConfig"); } } PlasmaComponents.MenuItem { text: i18n("Exit Input Method") icon: "application-exit" onClicked: { kimpanel.action("Exit"); } } PlasmaComponents.MenuItem { property QtObject configureAction: null enabled: configureAction && configureAction.enabled text: configureAction ? configureAction.text : "" icon: configureAction ? configureAction.icon : "" onClicked: configureAction.trigger() Component.onCompleted: configureAction = plasmoid.action("configure") } } } } diff --git a/applets/kimpanel/package/contents/ui/InputPanel.qml b/applets/kimpanel/package/contents/ui/InputPanel.qml index bea129ca9..17a0f5691 100644 --- a/applets/kimpanel/package/contents/ui/InputPanel.qml +++ b/applets/kimpanel/package/contents/ui/InputPanel.qml @@ -1,309 +1,309 @@ /* * Copyright 2014-2017 Weng Xuetian * * 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 2.010-1301, USA. */ import QtQuick 2.6 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.private.kimpanel 0.1 as Kimpanel PlasmaCore.Dialog { id: inputpanel type: PlasmaCore.Dialog.PopupMenu flags: Qt.Popup | Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus location: PlasmaCore.Types.Floating property bool verticalLayout: false property int highlightCandidate: -1 property int hoveredCandidate: -1 property font preferredFont: plasmoid.configuration.use_default_font ? theme.defaultFont : plasmoid.configuration.font property int baseSize: theme.mSize(preferredFont).height property rect position onPositionChanged : updatePosition(); onWidthChanged : updatePosition(); onHeightChanged : updatePosition(); mainItem: Item { Layout.minimumWidth: childrenRect.width Layout.minimumHeight: childrenRect.height Layout.maximumWidth: childrenRect.width Layout.maximumHeight: childrenRect.height Column { Row { id: textLabel width: auxLabel.width + preedit.width height: Math.max(preedit.height, auxLabel.height) PlasmaComponents.Label { id: auxLabel font: preferredFont } Item { id: preedit width: preeditLabel1.width + preeditLabel2.width + 2 height: Math.max(preeditLabel1.height, preeditLabel2.height) clip: true PlasmaComponents.Label { id: preeditLabel1 anchors.top: parent.top anchors.left: parent.left font: preferredFont } Rectangle { color: theme.textColor height: baseSize width: 2 opacity: 0.8 z: 1 anchors.verticalCenter: parent.verticalCenter anchors.left: preeditLabel1.right } PlasmaComponents.Label { id: preeditLabel2 anchors.top: parent.top anchors.left: preeditLabel1.right font: preferredFont } } } GridLayout { flow: inputpanel.verticalLayout ? GridLayout.TopToBottom : GridLayout.LeftToRight columns: inputpanel.verticalLayout ? 1 : tableList.count + 1 rows: inputpanel.verticalLayout ? tableList.count + 1 : 1 columnSpacing: units.smallSpacing / 2 rowSpacing: units.smallSpacing / 2 Repeater { model: ListModel { id: tableList dynamicRoles: true } delegate: Item { width: candidate.width + highlight.marginHints.left + highlight.marginHints.right height: candidate.height + highlight.marginHints.top + highlight.marginHints.bottom Layout.minimumWidth: width Layout.minimumHeight: height Layout.maximumWidth: width Layout.maximumHeight: height Row { id: candidate width: childrenRect.width height: childrenRect.height x: highlight.marginHints.left y: highlight.marginHints.top PlasmaComponents.Label { id: tableLabel text: model.label font: preferredFont opacity: highlight.visible ? 0.8 : 0.6 } PlasmaComponents.Label { id: textLabel text: model.text font: preferredFont } } MouseArea { id: candidateMouseArea anchors.fill: parent hoverEnabled: true onReleased: selectCandidate(model.index) onContainsMouseChanged: { inputpanel.hoveredCandidate = containsMouse ? model.index : -1; } } CandidateHighlight { id: highlight z: -1 - visible: inputpanel.highlightCandidate == model.index || inputpanel.hoveredCandidate == model.index + visible: inputpanel.highlightCandidate === model.index || inputpanel.hoveredCandidate === model.index hover: candidateMouseArea.containsMouse - selected: inputpanel.highlightCandidate == model.index || candidateMouseArea.pressed + selected: inputpanel.highlightCandidate === model.index || candidateMouseArea.pressed anchors { fill: parent } } } } Row { id: button width: inputpanel.baseSize * 2 height: inputpanel.baseSize Layout.minimumWidth: width Layout.minimumHeight: height Layout.maximumWidth: width Layout.maximumHeight: height PlasmaCore.IconItem { id: prevButton source: "arrow-left" width: inputpanel.baseSize height: width scale: prevButtonMouseArea.pressed ? 0.9 : 1 active: prevButtonMouseArea.containsMouse MouseArea { id: prevButtonMouseArea anchors.fill: parent hoverEnabled: true onReleased: action("LookupTablePageUp") } } PlasmaCore.IconItem { id: nextButton source: "arrow-right" width: inputpanel.baseSize height: width scale: nextButtonMouseArea.pressed ? 0.9 : 1 active: nextButtonMouseArea.containsMouse MouseArea { id: nextButtonMouseArea anchors.fill: parent hoverEnabled: true onReleased: action("LookupTablePageDown") } } } } } PlasmaCore.DataSource { id: inputPanelEngine engine: "kimpanel" connectedSources: ["inputpanel"] onDataChanged: timer.restart() } Kimpanel.Screen { id: screen } // Kimpanel's update may come in with in several DBus message. Use // timer to delegate the update so we get less flicker. Timer { id: timer interval: 1 onTriggered: updateUI() } } function updateUI() { var data = inputPanelEngine.data["inputpanel"]; if (!data) { return; } var auxVisible = data["AuxVisible"] ? true : false; var preeditVisible = data["PreeditVisible"] ? true : false; var lookupTableVisible = data["LookupTableVisible"] ? true : false; var pos = data["Position"] ? { 'x': data["Position"].x, 'y': data["Position"].y, 'w': data["Position"].width, 'h': data["Position"].height } : {'x' : 0, 'y': 0, 'w': 0, 'h': 0 }; inputpanel.position = Qt.rect(pos.x, pos.y, pos.w, pos.h); var newVisibility = auxVisible || preeditVisible || lookupTableVisible; if (!newVisibility) { // If we gonna hide anyway, don't do the update. inputpanel.hide(); return; } textLabel.visible = auxVisible || preeditVisible; auxLabel.text = (auxVisible && data["AuxText"]) ? data["AuxText"] : "" var preeditText = (preeditVisible && data["PreeditText"]) ? data["PreeditText"] : "" var caret = data["CaretPos"] ? data["CaretPos"] : 0; preeditLabel1.text = preeditText.substring(0, caret); preeditLabel2.text = preeditText.substring(caret); preedit.visible = preeditVisible; var layout = data["LookupTableLayout"] !== undefined ? data["LookupTableLayout"] : 0; inputpanel.highlightCandidate = data["LookupTableCursor"] !== undefined ? data["LookupTableCursor"] : -1; inputpanel.hoveredCandidate = -1; - inputpanel.verticalLayout = (layout === 1) || (layout == 0 && plasmoid.configuration.vertical_lookup_table); + inputpanel.verticalLayout = (layout === 1) || (layout === 0 && plasmoid.configuration.vertical_lookup_table); button.visible = lookupTableVisible if (data["LookupTable"]) { var table = data["LookupTable"]; if (lookupTableVisible) { if (table.length < tableList.count) { tableList.remove(table.length, tableList.count - table.length); } for (var i = 0; i < table.length; i ++) { if (i >= tableList.count) { tableList.append({'label' : table[i].label, 'text': table[i].text, 'index': i}); } else { tableList.set(i, {'label' : table[i].label, 'text': table[i].text, 'index': i}); } } } else { tableList.clear(); } } // If we gonna show, do that after everything is ready. if (newVisibility) { inputpanel.show(); } } function updatePosition() { var rect = screen.geometryForPoint(position.x, position.y); var devicePerPixelRatio = screen.devicePixelRatioForPoint(position.x, position.y); var x, y; var width = inputpanel.width * devicePerPixelRatio; var height = inputpanel.height * devicePerPixelRatio; if (position.x < rect.x) { x = rect.x; } else { x = position.x; } if (position.y < rect.y) { y = rect.y; } else { y = position.y + position.height; } if (x + width > rect.x + rect.width) { x = rect.x + rect.width - width; } if (y + height > rect.y + rect.height) { if (y > rect.y + rect.height) { y = rect.y + rect.height - height - 40; } else { - y = y - height - (position.height == 0 ? 40 : position.height); + y = y - height - (position.height === 0 ? 40 : position.height); } } var newRect = screen.geometryForPoint(x, y); devicePerPixelRatio = screen.devicePixelRatioForPoint(x, y); inputpanel.x = newRect.x + (x - newRect.x) / devicePerPixelRatio; inputpanel.y = newRect.y + (y - newRect.y) / devicePerPixelRatio; } function action(key) { var service = inputPanelEngine.serviceForSource("inputpanel"); var operation = service.operationDescription(key); service.startOperationCall(operation); } function selectCandidate(index) { var service = inputPanelEngine.serviceForSource("inputpanel"); var operation = service.operationDescription("SelectCandidate"); operation.candidate = index; service.startOperationCall(operation); } } diff --git a/applets/kimpanel/package/contents/ui/StatusIcon.qml b/applets/kimpanel/package/contents/ui/StatusIcon.qml index 0493cd67a..a334aef6c 100644 --- a/applets/kimpanel/package/contents/ui/StatusIcon.qml +++ b/applets/kimpanel/package/contents/ui/StatusIcon.qml @@ -1,99 +1,99 @@ /* * Copyright 2014 Weng Xuetian * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 Item { id: statusIcon property string icon; property string label; property string tip; property string hint; signal triggered(variant button); property int iconSize: units.roundToIconSize(Math.min(parent.width, parent.height)) opacity: 'disable' == hint ? 0.3 : 1 function extractLabelString(l) { if (l.length >= 2 && l.charCodeAt(0) < 127 && l.charCodeAt(1) < 127) { return l.substring(0, 2); } else { return l.substring(0, 1); } } function iconPath(p) { if (p.length > 0) { - if (p[0] == '/') { + if (p[0] === '/') { return p; } else { return "image://icon/" + p; } } return p; } PlasmaCore.IconItem { id: imageIcon anchors.centerIn: parent width: iconSize height: iconSize scale: mouseArea.pressed ? 0.9 : 1 source: statusIcon.icon visible: statusIcon.icon.length > 0 animated: false // active: mouseArea.containsMouse } PlasmaComponents.Label { id: textIcon anchors.centerIn: parent width: iconSize height: iconSize scale: (mouseArea.pressed ? 0.9 : 1) // a reasonable large size to make Text.Fit work minimumPointSize: 0 font.pointSize: 1024 fontSizeMode: Text.Fit verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: extractLabelString(label) visible: icon.length == 0 } MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: { statusIcon.triggered(mouse.button); } PlasmaCore.ToolTipArea { anchors.fill: parent mainText: statusIcon.label subText: statusIcon.tip icon: statusIcon.icon } } } diff --git a/applets/kimpanel/package/contents/ui/main.qml b/applets/kimpanel/package/contents/ui/main.qml index 60154540b..da5d0a43f 100644 --- a/applets/kimpanel/package/contents/ui/main.qml +++ b/applets/kimpanel/package/contents/ui/main.qml @@ -1,214 +1,214 @@ /* * Copyright 2014 Weng Xuetian * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 Item { id: kimpanel property int visibleButtons: 0 - property bool vertical: plasmoid.formFactor == PlasmaCore.Types.Vertical + property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical LayoutMirroring.enabled: !vertical && Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true Layout.minimumWidth: vertical ? units.iconSizes.small : items.implicitWidth Layout.minimumHeight: !vertical ? units.iconSizes.small : items.implicitHeight Layout.preferredHeight: Layout.minimumHeight Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation InputPanel { } Flow { id: items width: parent.width height: parent.height x: (parent.width - childrenRect.width) / 2 y: (parent.height - childrenRect.height) / 2 flow: kimpanel.vertical ? Flow.LeftToRight : Flow.TopToBottom property int iconSize: Math.min(units.iconSizeHints.panel, units.roundToIconSize(Math.min(width, height))) Repeater { model: ListModel { id: list dynamicRoles: true } delegate: Item { id: iconDelegate width: items.iconSize height: items.iconSize StatusIcon { id: statusIcon anchors.centerIn: parent width: items.iconSize height: items.iconSize label: model.label tip: model.tip icon: model.icon hint: model.hint onTriggered : { - if (button == Qt.LeftButton) { + if (button === Qt.LeftButton) { clickHandler(model.key); // clickHandler will trigger the menu, but we have to wait for // the menu data. So we have to set the visual parent ahead. actionMenu.visualParent = statusIcon; } else { contextMenu.open(statusIcon, {key: model.key, label: model.label}); } } } } } } function clickHandler(key) { var service = dataEngine.serviceForSource("statusbar"); var operation = service.operationDescription("TriggerProperty"); operation.key = key; service.startOperationCall(operation); } function action(key) { var service = dataEngine.serviceForSource("statusbar"); var operation = service.operationDescription(key); service.startOperationCall(operation); } function hideAction(key) { // We must use assignment to change the configuration property, // otherwise it won't get notified. var hiddenList = plasmoid.configuration.hiddenList; if (hiddenList.indexOf(key) === -1) { hiddenList.push(key); plasmoid.configuration.hiddenList = hiddenList; } timer.restart(); } function showAction(key) { // We must use assignment to change the configuration property, // otherwise it won't get notified. var hiddenList = plasmoid.configuration.hiddenList; var index = hiddenList.indexOf(key); if (index !== -1) { hiddenList.splice(index, 1); plasmoid.configuration.hiddenList = hiddenList; } timer.restart(); } function showMenu(menu, menuData) { if (!menuData) { return; } if (menuData["timestamp"] > menu.timestamp) { menu.timestamp = menuData["timestamp"]; var actionList = []; for (var i = 0; i < menuData["props"].length; i++ ) { actionList.push({"actionId": menuData["props"][i].key, "icon": menuData["props"][i].icon, "text": menuData["props"][i].label, hint: menuData["props"][i].hint}); } if (actionList.length > 0) { menu.actionList = actionList; menu.open(); } } } ActionMenu { property var timestamp: 0; id: actionMenu onActionClicked: { clickHandler(actionId); } } ContextMenu { id: contextMenu } Timer { id: timer interval: 50 onTriggered: { var data = dataEngine.data["statusbar"]["Properties"]; if (!data) { return; } var count = list.count; var c = 0, i; var hiddenActions = []; for (i = 0; i < data.length; i ++) { if (plasmoid.configuration.hiddenList.indexOf(data[i].key) !== -1) { hiddenActions.push({'key': data[i].key, 'icon': data[i].icon, 'label': data[i].label}); } else { c = c + 1; } } if (c < count) { list.remove(c, count - c); } kimpanel.visibleButtons = c; c = 0; for (i = 0; i < data.length; i ++) { if (plasmoid.configuration.hiddenList.indexOf(data[i].key) !== -1) { continue; } var itemData = {'key': data[i].key, 'icon': data[i].icon, 'label': data[i].label, 'tip': data[i].tip, 'hint': data[i].hint }; if (c < count) { list.set(c, itemData); } else { list.append(itemData); } c = c + 1; } contextMenu.actionList = hiddenActions; } } PlasmaCore.DataSource { id: dataEngine engine: "kimpanel" connectedSources: ["statusbar"] onDataChanged: { showMenu(actionMenu, dataEngine.data["statusbar"]["Menu"]); var data = dataEngine.data["statusbar"]["Properties"]; if (!data) { kimpanel.visibleButtons = 0; return; } timer.restart(); } } } diff --git a/applets/pager/package/contents/ui/configGeneral.qml b/applets/pager/package/contents/ui/configGeneral.qml index fb8234586..ff6622c85 100644 --- a/applets/pager/package/contents/ui/configGeneral.qml +++ b/applets/pager/package/contents/ui/configGeneral.qml @@ -1,181 +1,181 @@ /* * Copyright 2013 David Edmundson * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 1.0 as QtControls import QtQuick.Layouts 1.0 as Layouts //FIXME this causes a crash in Oxygen style //QtControls.GroupBox { Item { width: childrenRect.width height: childrenRect.height //FIXME enable when we're back to being a group box // flat: true // title: i18n("Appearance") - property bool isActivityPager: (plasmoid.pluginName == "org.kde.plasma.activitypager") + property bool isActivityPager: (plasmoid.pluginName === "org.kde.plasma.activitypager") property int cfg_displayedText property alias cfg_showWindowIcons: showWindowIcons.checked property int cfg_currentDesktopSelected property alias cfg_pagerLayout: pagerLayout.currentIndex property alias cfg_showOnlyCurrentScreen: showOnlyCurrentScreen.checked property alias cfg_wrapPage: wrapPage.checked onCfg_displayedTextChanged: { switch (cfg_displayedText) { case 0: displayedTextGroup.current = desktopNumberRadio; break; case 1: displayedTextGroup.current = desktopNameRadio; break; default: case 2: displayedTextGroup.current = noTextRadio; break; } } onCfg_currentDesktopSelectedChanged: { switch (cfg_currentDesktopSelected) { case 0: currentDesktopSelectedGroup.current = doesNothingRadio; break; case 1: currentDesktopSelectedGroup.current = showsDesktopRadio; break; default: break; } } Component.onCompleted: { cfg_currentDesktopSelectedChanged(); cfg_displayedTextChanged(); } QtControls.ExclusiveGroup { id: displayedTextGroup } QtControls.ExclusiveGroup { id: currentDesktopSelectedGroup } Layouts.GridLayout { anchors.left: parent.left columns: 2 QtControls.Label { text: i18n("Display:") Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } QtControls.RadioButton { id: desktopNumberRadio exclusiveGroup: displayedTextGroup text: isActivityPager ? i18n("Activity number") : i18n("Desktop number") onCheckedChanged: if (checked) cfg_displayedText = 0; } Item { width: 2 height: 2 Layouts.Layout.rowSpan: 2 } QtControls.RadioButton { id: desktopNameRadio exclusiveGroup: displayedTextGroup text: isActivityPager ? i18n("Activity name") : i18n("Desktop name") onCheckedChanged: if (checked) cfg_displayedText = 1; } QtControls.RadioButton { id: noTextRadio exclusiveGroup: displayedTextGroup text: i18n("No text") onCheckedChanged: if (checked) cfg_displayedText = 2; } Item { width: 2 height: 2 } //spacer QtControls.CheckBox { id: showWindowIcons text: i18n("Icons") } Item { width: 2 height: 2 } //spacer QtControls.CheckBox { id: showOnlyCurrentScreen text: i18n("Only the current screen") } Item { width: 2 height: 2 } //spacer QtControls.CheckBox { id: wrapPage text: i18n("Page navigation wraps around") } QtControls.Label { text: i18n("Layout:") Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight visible: isActivityPager } QtControls.ComboBox { id: pagerLayout model: [i18nc("The pager layout", "Default"), i18n("Horizontal"), i18n("Vertical")] visible: isActivityPager } QtControls.Label { text: i18n("Selecting current desktop:") Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight } QtControls.RadioButton { id: doesNothingRadio exclusiveGroup: currentDesktopSelectedGroup text: i18n("Does nothing") onCheckedChanged: if (checked) cfg_currentDesktopSelected = 0; } Item { width: 2 height: 2 Layouts.Layout.rowSpan: 2 } QtControls.RadioButton { id: showsDesktopRadio exclusiveGroup: currentDesktopSelectedGroup text: i18n("Shows desktop") onCheckedChanged: if (checked) cfg_currentDesktopSelected = 1; } } } diff --git a/applets/pager/package/contents/ui/main.qml b/applets/pager/package/contents/ui/main.qml index e3b036d73..9f38c977d 100644 --- a/applets/pager/package/contents/ui/main.qml +++ b/applets/pager/package/contents/ui/main.qml @@ -1,546 +1,546 @@ /* * Copyright 2012 Luís Gabriel Lima * Copyright 2016 Kai Uwe Broulik * 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, see . */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddonsComponents import org.kde.draganddrop 2.0 import org.kde.plasma.private.pager 2.0 MouseArea { id: root - property bool isActivityPager: (plasmoid.pluginName == "org.kde.plasma.activitypager") - property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) + property bool isActivityPager: (plasmoid.pluginName === "org.kde.plasma.activitypager") + property bool vertical: (plasmoid.formFactor === PlasmaCore.Types.Vertical) property var activityDataSource: null readonly property real aspectRatio: (((pagerModel.pagerItemSize.width * pagerItemGrid.effectiveColumns) + ((pagerItemGrid.effectiveColumns * pagerItemGrid.spacing) - pagerItemGrid.spacing)) / ((pagerModel.pagerItemSize.height * pagerItemGrid.effectiveRows) + ((pagerItemGrid.effectiveRows * pagerItemGrid.spacing) - pagerItemGrid.spacing))) Layout.minimumWidth: !root.vertical ? Math.floor(height * aspectRatio) : 1 Layout.minimumHeight: root.vertical ? Math.floor(width / aspectRatio) : 1 Layout.maximumWidth: !root.vertical ? Math.floor(height * aspectRatio) : Infinity Layout.maximumHeight: root.vertical ? Math.floor(width / aspectRatio) : Infinity Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.status: pagerModel.shouldShowPager ? PlasmaCore.Types.ActiveStatus : PlasmaCore.Types.HiddenStatus Layout.fillWidth: root.vertical Layout.fillHeight: !root.vertical property bool dragging: false property string dragId property string dragSwitchDesktopId property int wheelDelta: 0 anchors.fill: parent acceptedButtons: Qt.NoButton hoverEnabled: true function colorWithAlpha(color, alpha) { return Qt.rgba(color.r, color.g, color.b, alpha) } readonly property color windowActiveOnActiveDesktopColor: colorWithAlpha(theme.textColor, 0.6) readonly property color windowInactiveOnActiveDesktopColor: colorWithAlpha(theme.textColor, 0.35) readonly property color windowActiveColor: colorWithAlpha(theme.textColor, 0.5) readonly property color windowActiveBorderColor: theme.textColor readonly property color windowInactiveColor: colorWithAlpha(theme.textColor, 0.17) readonly property color windowInactiveBorderColor: colorWithAlpha(theme.textColor, 0.5) function action_addDesktop() { pagerModel.addDesktop(); } function action_removeDesktop() { pagerModel.removeDesktop(); } function action_openKCM() { KQuickControlsAddonsComponents.KCMShell.open("kcm_kwin_virtualdesktops"); } function action_showActivityManager() { if (!activityDataSource) { activityDataSource = Qt.createQmlObject('import org.kde.plasma.core 2.0 as PlasmaCore; \ PlasmaCore.DataSource { id: dataSource; engine: "org.kde.activities"; \ connectedSources: ["Status"] }', root); } var service = activityDataSource.serviceForSource("Status") var operation = service.operationDescription("toggleActivityManager") service.startOperationCall(operation) } onContainsMouseChanged: { if (!containsMouse && dragging) { // Somewhat heavy-handed way to clean up after a window delegate drag // exits the window. pagerModel.refresh(); dragging = false; } } onWheel: { // Magic number 120 for common "one click, see: // http://qt-project.org/doc/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop wheelDelta += wheel.angleDelta.y || wheel.angleDelta.x; var increment = 0; while (wheelDelta >= 120) { wheelDelta -= 120; increment++; } while (wheelDelta <= -120) { wheelDelta += 120; increment--; } - while (increment != 0) { + while (increment !== 0) { if (increment < 0) { var nextPage = plasmoid.configuration.wrapPage? (pagerModel.currentPage + 1) % repeater.count : Math.min(pagerModel.currentPage + 1, repeater.count - 1); pagerModel.changePage(nextPage); } else { var previousPage = plasmoid.configuration.wrapPage ? (repeater.count + pagerModel.currentPage - 1) % repeater.count : Math.max(pagerModel.currentPage - 1, 0); pagerModel.changePage(previousPage); } increment += (increment < 0) ? 1 : -1; } } PagerModel { id: pagerModel enabled: root.visible - showDesktop: (plasmoid.configuration.currentDesktopSelected == 1) + showDesktop: (plasmoid.configuration.currentDesktopSelected === 1) showOnlyCurrentScreen: plasmoid.configuration.showOnlyCurrentScreen screenGeometry: plasmoid.screenGeometry pagerType: isActivityPager ? PagerModel.Activities : PagerModel.VirtualDesktops } Connections { target: plasmoid.configuration onShowWindowIconsChanged: { // Causes the model to reset; Component.onCompleted in the // window delegate now gets a chance to create the icon item, // which it otherwise will not do. pagerModel.refresh(); } onDisplayedTextChanged: { // Causes the model to reset; Component.onCompleted in the // desktop delegate now gets a chance to create the label item, // which it otherwise will not do. pagerModel.refresh(); } } Component { id: desktopLabelComponent PlasmaComponents.Label { anchors { fill: parent topMargin: desktopFrame.margins.top bottomMargin: desktopFrame.margins.bottom leftMargin: desktopFrame.margins.left rightMargin: desktopFrame.margins.right } property int index: 0 property var model: null property Item desktopFrame: null text: plasmoid.configuration.displayedText ? model.display : index + 1 wrapMode: Text.NoWrap elide: Text.ElideRight horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter z: 0 // Below windows and FrameSvg } } Component { id: windowIconComponent PlasmaCore.IconItem { anchors.centerIn: parent height: Math.min(units.iconSizes.small, parent.height - (units.smallSpacing * 2)) width: Math.min(units.iconSizes.small, parent.width - (units.smallSpacing * 2)) property var model: null source: model ? model.decoration : undefined usesPlasmaTheme: false animated: false } } Timer { id: dragTimer interval: 1000 onTriggered: { - if (dragSwitchDesktopId != -1 && dragSwitchDesktopId !== pagerModel.currentPage) { + if (dragSwitchDesktopId !== -1 && dragSwitchDesktopId !== pagerModel.currentPage) { pagerModel.changePage(dragSwitchDesktopId); } } } Grid { id: pagerItemGrid spacing: units.devicePixelRatio rows: effectiveRows columns: effectiveColumns z: 1 readonly property int effectiveRows: { if (!pagerModel.count) { return 1; } var rows = 1; if (isActivityPager && plasmoid.configuration.pagerLayout !== 0 /*No Default*/) { if (plasmoid.configuration.pagerLayout === 1 /*Horizontal*/) { rows = 1; } else if (plasmoid.configuration.pagerLayout === 2 /*Vertical*/) { rows = pagerModel.count; } } else { var columns = Math.floor(pagerModel.count / pagerModel.layoutRows); if (pagerModel.count % pagerModel.layoutRows > 0) { columns += 1; } rows = Math.floor(pagerModel.count / columns); if (pagerModel.count % columns > 0) { rows += 1; } } return rows; } readonly property int effectiveColumns: { if (!pagerModel.count) { return 1; } return Math.ceil(pagerModel.count / effectiveRows); } readonly property real pagerItemSizeRatio: pagerModel.pagerItemSize.width / pagerModel.pagerItemSize.height readonly property real widthScaleFactor: columnWidth / pagerModel.pagerItemSize.width readonly property real heightScaleFactor: rowHeight / pagerModel.pagerItemSize.height states: [ State { name: "vertical" when: vertical PropertyChanges { target: pagerItemGrid innerSpacing: effectiveColumns rowHeight: Math.floor(columnWidth / pagerItemSizeRatio) columnWidth: Math.floor((root.width - innerSpacing) / effectiveColumns) } } ] property int innerSpacing: (effectiveRows - 1) * spacing property int rowHeight: Math.floor((root.height - innerSpacing) / effectiveRows) property int columnWidth: Math.floor(rowHeight * pagerItemSizeRatio) Repeater { id: repeater model: pagerModel PlasmaCore.ToolTipArea { id: desktop property string desktopId: isActivityPager ? model.TasksModel.activity : model.TasksModel.virtualDesktop - property bool active: (index == pagerModel.currentPage) + property bool active: (index === pagerModel.currentPage) mainText: model.display // our ToolTip has maximumLineCount of 8 which doesn't fit but QML doesn't // respect that in RichText so we effectively can put in as much as we like :) // it also gives us more flexibility when it comes to styling the
  • textFormat: Text.RichText function updateSubText() { var generateWindowList = function windowList(windows) { // if we have 5 windows, we would show "4 and another one" with the // hint that there's 1 more taking the same amount of space than just showing it var maximum = windows.length === 5 ? 5 : 4 var text = "
    • " + windows.slice(0, maximum).join("
    • ") + "
    " if (windows.length > maximum) { text += i18np("...and %1 other window", "...and %1 other windows", windows.length - maximum) } return text } var text = "" var visibleWindows = [] var minimizedWindows = [] for (var i = 0, length = windowRectRepeater.count; i < length; ++i) { var window = windowRectRepeater.itemAt(i) if (window) { if (window.minimized) { minimizedWindows.push(window.visibleName) } else { visibleWindows.push(window.visibleName) } } } if (visibleWindows.length === 1) { text += visibleWindows[0] } else if (visibleWindows.length > 1) { text += i18np("%1 Window:", "%1 Windows:", visibleWindows.length) + generateWindowList(visibleWindows) } if (visibleWindows.length && minimizedWindows.length) { text += "
    " } if (minimizedWindows.length > 0) { text += i18np("%1 Minimized Window:", "%1 Minimized Windows:", minimizedWindows.length) + generateWindowList(minimizedWindows) } if (text.length) { // Get rid of the spacing
      would cause text = "" + text } subText = text } width: pagerItemGrid.columnWidth height: pagerItemGrid.rowHeight PlasmaCore.FrameSvgItem { id: desktopFrame anchors.fill: parent z: 2 // Above optional label item and windows imagePath: "widgets/pager" prefix: (desktopMouseArea.enabled && desktopMouseArea.containsMouse) || (root.dragging && root.dragId == desktopId) ? "hover" : (desktop.active ? "active" : "normal") } DropArea { id: droparea anchors.fill: parent preventStealing: true onDragEnter: { root.dragSwitchDesktopId = desktop.desktopId; dragTimer.start(); } onDragLeave: { root.dragSwitchDesktopId = ""; dragTimer.stop(); } onDrop: { pagerModel.drop(event.mimeData, desktop.desktopId); root.dragSwitchDesktopId = -1; dragTimer.stop(); } } MouseArea { id: desktopMouseArea anchors.fill: parent hoverEnabled : true onClicked: pagerModel.changePage(index); } Item { id: clipRect x: Math.round(units.devicePixelRatio) y: Math.round(units.devicePixelRatio) width: desktop.width - 2 * x height: desktop.height - 2 * y z: 1 // Between optional label item and FrameSvg Repeater { id: windowRectRepeater model: TasksModel onCountChanged: desktop.updateSubText() Rectangle { id: windowRect z: 1 + model.StackingOrder property rect geometry: model.Geometry property int windowId: model.WinIdList[0] property string visibleName: model.display property bool minimized: (model.IsMinimized === true) onMinimizedChanged: desktop.updateSubText() onVisibleNameChanged: desktop.updateSubText() /* since we move clipRect with 1, move it back */ x: (geometry.x * pagerItemGrid.widthScaleFactor) - Math.round(units.devicePixelRatio) y: (geometry.y * pagerItemGrid.heightScaleFactor) - Math.round(units.devicePixelRatio) width: geometry.width * pagerItemGrid.widthScaleFactor height: geometry.height * pagerItemGrid.heightScaleFactor visible: model.IsMinimized !== true color: { if (desktop.active) { if (model.IsActive === true) return windowActiveOnActiveDesktopColor; else return windowInactiveOnActiveDesktopColor; } else { if (model.IsActive === true) return windowActiveColor; else return windowInactiveColor; } } border.width: Math.round(units.devicePixelRatio) border.color: (model.IsActive === true) ? windowActiveBorderColor : windowInactiveBorderColor MouseArea { id: windowMouseArea anchors.fill: parent drag.target: windowRect drag.axis: Drag.XandYAxis drag.minimumX: -windowRect.width/2 drag.maximumX: root.width - windowRect.width/2 drag.minimumY: -windowRect.height/2 drag.maximumY: root.height - windowRect.height/2 drag.onActiveChanged: { root.dragging = drag.active; root.dragId = desktop.desktopId; desktopMouseArea.enabled = !drag.active; if (drag.active) { // Reparent to allow drags outside of this desktop. var value = root.mapFromItem(clipRect, windowRect.x, windowRect.y); windowRect.parent = root; windowRect.x = value.x; windowRect.y = value.y } } onReleased: { if (root.dragging) { windowRect.visible = false; var windowCenter = Qt.point(windowRect.x + windowRect.width / 2, windowRect.y + windowRect.height / 2); var pagerItem = pagerItemGrid.childAt(windowCenter.x, windowCenter.y); if (pagerItem) { var relativeTopLeft = root.mapToItem(pagerItem, windowRect.x, windowRect.y); pagerModel.moveWindow(windowRect.windowId, relativeTopLeft.x, relativeTopLeft.y, pagerItem.desktopId, root.dragId, pagerItemGrid.widthScaleFactor, pagerItemGrid.heightScaleFactor); } // Will reset the model, destroying the reparented drag delegate that // is no longer bound to model.Geometry. root.dragging = false; pagerModel.refresh(); } else { // When there is no dragging (just a click), the event is passed // to the desktop MouseArea. desktopMouseArea.clicked(mouse); } } } Component.onCompleted: { if (plasmoid.configuration.showWindowIcons) { windowIconComponent.createObject(windowRect, {"model": model}); } } } } } Component.onCompleted: { if (plasmoid.configuration.displayedText < 2) { desktopLabelComponent.createObject(desktop, {"index": index, "model": model, "desktopFrame": desktopFrame}); } } } } } Component.onCompleted: { if (isActivityPager) { plasmoid.setAction("showActivityManager", i18n("Show Activity Manager..."), "preferences-activities"); } else { if (KQuickControlsAddonsComponents.KCMShell.authorize("kcm_kwin_virtualdesktops.desktop").length > 0) { plasmoid.setAction("addDesktop", i18n("Add Virtual Desktop"), "list-add"); plasmoid.setAction("removeDesktop", i18n("Remove Virtual Desktop"), "list-remove"); plasmoid.action("removeDesktop").enabled = Qt.binding(function() { return repeater.count > 1; }); plasmoid.setAction("openKCM", i18n("Configure Virtual Desktops..."), "configure"); } } } } diff --git a/applets/showActivityManager/package/contents/ui/main.qml b/applets/showActivityManager/package/contents/ui/main.qml index 3091555a6..477f06422 100644 --- a/applets/showActivityManager/package/contents/ui/main.qml +++ b/applets/showActivityManager/package/contents/ui/main.qml @@ -1,68 +1,68 @@ /* * Copyright 2012 Gregor Taetzner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library 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. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore MouseArea { id: iconContainer property string activeSource: "Status" height: units.iconSizes.large width: units.iconSizes.large - readonly property bool inPanel: (plasmoid.location == PlasmaCore.Types.TopEdge - || plasmoid.location == PlasmaCore.Types.RightEdge - || plasmoid.location == PlasmaCore.Types.BottomEdge - || plasmoid.location == PlasmaCore.Types.LeftEdge) + readonly property bool inPanel: (plasmoid.location === PlasmaCore.Types.TopEdge + || plasmoid.location === PlasmaCore.Types.RightEdge + || plasmoid.location === PlasmaCore.Types.BottomEdge + || plasmoid.location === PlasmaCore.Types.LeftEdge) Layout.maximumWidth: inPanel ? units.iconSizeHints.panel : -1 Layout.maximumHeight: inPanel ? units.iconSizeHints.panel : -1 Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation onClicked: { var service = dataSource.serviceForSource(activeSource) var operation = service.operationDescription("toggleActivityManager") service.startOperationCall(operation) } PlasmaCore.DataSource { id: dataSource engine: "org.kde.activities" connectedSources: [activeSource] } PlasmaCore.ToolTipArea { id: tooltip mainText: i18n("Show Activity Manager") subText: i18n("Click to show the activity manager") anchors.fill: parent icon: "preferences-activities" } PlasmaCore.IconItem { id: icon source: "preferences-activities" width: parent.width height: parent.height } } diff --git a/applets/taskmanager/package/contents/ui/ConfigAppearance.qml b/applets/taskmanager/package/contents/ui/ConfigAppearance.qml index d08e058f7..2df3d4a93 100644 --- a/applets/taskmanager/package/contents/ui/ConfigAppearance.qml +++ b/applets/taskmanager/package/contents/ui/ConfigAppearance.qml @@ -1,121 +1,121 @@ /*************************************************************************** * Copyright (C) 2013 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.12 import org.kde.kirigami 2.4 as Kirigami import org.kde.plasma.core 2.0 as PlasmaCore Item { width: childrenRect.width height: childrenRect.height readonly property bool plasmaPaAvailable: Qt.createComponent("PulseAudio.qml").status === Component.Ready - property bool plasmoidVertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) + property bool plasmoidVertical: (plasmoid.formFactor === PlasmaCore.Types.Vertical) property alias cfg_showToolTips: showToolTips.checked property alias cfg_highlightWindows: highlightWindows.checked property alias cfg_smartLaunchersEnabled: smartLaunchers.checked property bool cfg_indicateAudioStreams property alias cfg_iconSize: iconSize.value property alias cfg_maxStripes: maxStripes.value property alias cfg_forceStripes: forceStripes.checked Kirigami.FormLayout { anchors.left: parent.left anchors.right: parent.right CheckBox { id: showToolTips Kirigami.FormData.label: i18n ("General:") text: i18n("Show tooltips") } CheckBox { id: highlightWindows text: i18n("Highlight windows when hovering over tasks") } CheckBox { id: smartLaunchers text: i18n("Show progress and status information in task buttons") } CheckBox { id: indicateAudioStreams text: i18n("Mark applications that play audio") checked: cfg_indicateAudioStreams && plasmaPaAvailable onCheckedChanged: cfg_indicateAudioStreams = checked enabled: plasmaPaAvailable } Item { Kirigami.FormData.isSection: true visible: plasmoidVertical } Slider { id: iconSize visible: plasmoidVertical Kirigami.FormData.label: i18n("Icon size:") Layout.fillWidth: true from: 0 to: 5 stepSize: 1 } RowLayout { visible: plasmoidVertical Layout.fillWidth: true Label { text: i18n("Small") Layout.alignment: Qt.AlignLeft } Item { Layout.fillWidth: true } Label { text: i18n("Large") Layout.alignment: Qt.AlignRight } } Item { Kirigami.FormData.isSection: true } SpinBox { id: maxStripes Kirigami.FormData.label: plasmoidVertical ? i18n("Maximum columns:") : i18n("Maximum rows:") from: 1 } CheckBox { id: forceStripes text: plasmoidVertical ? i18n("Always arrange tasks in as many rows as columns") : i18n("Always arrange tasks in as many columns as rows") enabled: maxStripes.value > 1 } } } diff --git a/applets/taskmanager/package/contents/ui/ConfigBehavior.qml b/applets/taskmanager/package/contents/ui/ConfigBehavior.qml index af0d2e15b..37ad7c3e3 100644 --- a/applets/taskmanager/package/contents/ui/ConfigBehavior.qml +++ b/applets/taskmanager/package/contents/ui/ConfigBehavior.qml @@ -1,150 +1,150 @@ /*************************************************************************** * Copyright (C) 2013 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Controls 1.4 as QQC1 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.12 import org.kde.kirigami 2.4 as Kirigami import org.kde.plasma.core 2.0 as PlasmaCore Item { width: childrenRect.width height: childrenRect.height property alias cfg_groupingStrategy: groupingStrategy.currentIndex property alias cfg_groupPopups: groupPopups.checked property alias cfg_onlyGroupWhenFull: onlyGroupWhenFull.checked property alias cfg_sortingStrategy: sortingStrategy.currentIndex property alias cfg_separateLaunchers: separateLaunchers.checked property alias cfg_middleClickAction: middleClickAction.currentIndex property alias cfg_wheelEnabled: wheelEnabled.checked property alias cfg_showOnlyCurrentScreen: showOnlyCurrentScreen.checked property alias cfg_showOnlyCurrentDesktop: showOnlyCurrentDesktop.checked property alias cfg_showOnlyCurrentActivity: showOnlyCurrentActivity.checked property alias cfg_showOnlyMinimized: showOnlyMinimized.checked Kirigami.FormLayout { anchors.left: parent.left anchors.right: parent.right // TODO: port to QQC2 version once we've fixed https://bugs.kde.org/show_bug.cgi?id=403153 QQC1.ComboBox { id: groupingStrategy - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") Kirigami.FormData.label: i18n("Group:") Layout.fillWidth: true model: [i18n("Do not group"), i18n("By program name")] } CheckBox { id: groupPopups - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") text: i18n("Open groups in popups") enabled: groupingStrategy.currentIndex > 0 } RowLayout { - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") // Indent the option as it depends on the previous one Item { width: units.largeSpacing } CheckBox { id: onlyGroupWhenFull text: i18n("Group only when the Task Manager is full") enabled: groupingStrategy.currentIndex > 0 && groupPopups.checked } } Item { Kirigami.FormData.isSection: true - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") } // TODO: port to QQC2 version once we've fixed https://bugs.kde.org/show_bug.cgi?id=403153 QQC1.ComboBox { id: sortingStrategy - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") Kirigami.FormData.label: i18n("Sort:") Layout.fillWidth: true model: [i18n("Do not sort"), i18n("Manually"), i18n("Alphabetically"), i18n("By desktop"), i18n("By activity")] } CheckBox { id: separateLaunchers - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") text: i18n("Keep launchers separate") enabled: sortingStrategy.currentIndex == 1 } Item { Kirigami.FormData.isSection: true - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") } // TODO: port to QQC2 version once we've fixed https://bugs.kde.org/show_bug.cgi?id=403153 QQC1.ComboBox { id: middleClickAction Kirigami.FormData.label: i18n("On middle-click:") Layout.fillWidth: true model: [ i18nc("The click action", "None"), i18n("Close window or group"), i18n("New instance"), i18n("Minimize/Restore window or group"), i18nc("When clicking it would toggle grouping windows of a specific app", "Group/Ungroup") ] } CheckBox { id: wheelEnabled text: i18n("Cycle through tasks with mouse wheel") } Item { Kirigami.FormData.isSection: true } CheckBox { id: showOnlyCurrentScreen Kirigami.FormData.label: i18n("Filter:") text: i18n("Show only tasks from the current screen") } CheckBox { id: showOnlyCurrentDesktop text: i18n("Show only tasks from the current desktop") } CheckBox { id: showOnlyCurrentActivity text: i18n("Show only tasks from the current activity") } CheckBox { id: showOnlyMinimized - visible: (plasmoid.pluginName != "org.kde.plasma.icontasks") + visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks") text: i18n("Show only tasks that are minimized") } } } diff --git a/applets/taskmanager/package/contents/ui/ContextMenu.qml b/applets/taskmanager/package/contents/ui/ContextMenu.qml index d73e959b4..bc88d9266 100644 --- a/applets/taskmanager/package/contents/ui/ContextMenu.qml +++ b/applets/taskmanager/package/contents/ui/ContextMenu.qml @@ -1,719 +1,719 @@ /*************************************************************************** * Copyright (C) 2012-2016 by Eike Hein * * Copyright (C) 2016 by 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) 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.taskmanager 0.1 as TaskManager import "code/layout.js" as LayoutManager PlasmaComponents.ContextMenu { id: menu property QtObject backend property QtObject mpris2Source property var modelIndex readonly property var atm: TaskManager.AbstractTasksModel property bool showAllPlaces: false placement: { - if (plasmoid.location == PlasmaCore.Types.LeftEdge) { + if (plasmoid.location === PlasmaCore.Types.LeftEdge) { return PlasmaCore.Types.RightPosedTopAlignedPopup; - } else if (plasmoid.location == PlasmaCore.Types.TopEdge) { + } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { return PlasmaCore.Types.BottomPosedLeftAlignedPopup; - } else if (plasmoid.location == PlasmaCore.Types.RightEdge) { + } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { return PlasmaCore.Types.LeftPosedTopAlignedPopup; } else { return PlasmaCore.Types.TopPosedLeftAlignedPopup; } } minimumWidth: visualParent.width onStatusChanged: { - if (visualParent && get(atm.LauncherUrlWithoutIcon) != "" && status == PlasmaComponents.DialogStatus.Open) { - launcherToggleAction.checked = (tasksModel.launcherPosition(get(atm.LauncherUrlWithoutIcon)) != -1); + if (visualParent && get(atm.LauncherUrlWithoutIcon) !== "" && status == PlasmaComponents.DialogStatus.Open) { + launcherToggleAction.checked = (tasksModel.launcherPosition(get(atm.LauncherUrlWithoutIcon)) !== -1); activitiesDesktopsMenu.refresh(); } else if (status == PlasmaComponents.DialogStatus.Closed) { menu.destroy(); backend.ungrabMouse(visualParent); } } Component.onCompleted: { // Cannot have "Connections" as child of PlasmaCoponents.ContextMenu. backend.showAllPlaces.connect(function() { visualParent.showContextMenu({showAllPlaces: true}); }); } function get(modelProp) { return tasksModel.data(modelIndex, modelProp) } function show() { loadDynamicLaunchActions(get(atm.LauncherUrlWithoutIcon)); openRelative(); } function newMenuItem(parent) { return Qt.createQmlObject( "import org.kde.plasma.components 2.0 as PlasmaComponents;" + "PlasmaComponents.MenuItem {}", parent); } function newSeparator(parent) { return Qt.createQmlObject( "import org.kde.plasma.components 2.0 as PlasmaComponents;" + "PlasmaComponents.MenuItem { separator: true }", parent); } function loadDynamicLaunchActions(launcherUrl) { var lists = [ backend.jumpListActions(launcherUrl, menu), backend.placesActions(launcherUrl, showAllPlaces, menu), backend.recentDocumentActions(launcherUrl, menu) ] // QMenu does not limit its width automatically. Even if we set a maximumWidth // it would just cut off text rather than eliding. So we do this manually. var textMetrics = Qt.createQmlObject("import QtQuick 2.4; TextMetrics {}", menu); var maximumWidth = LayoutManager.maximumContextMenuTextWidth(); lists.forEach(function (list) { for (var i = 0; i < list.length; ++i) { var item = newMenuItem(menu); item.action = list[i]; // Crude way of manually eliding... var elided = false; textMetrics.text = Qt.binding(function() { return item.action.text; }); while (textMetrics.width > maximumWidth) { item.action.text = item.action.text.slice(0, -1); elided = true; } if (elided) { item.action.text += "..."; } menu.addMenuItem(item, virtualDesktopsMenuItem); } if (list.length > 0) { menu.addMenuItem(newSeparator(menu), virtualDesktopsMenuItem); } }); // Add Media Player control actions var sourceName = mpris2Source.sourceNameForLauncherUrl(launcherUrl, get(atm.AppPid)); - if (sourceName && !(get(atm.WinIdList) != undefined && get(atm.WinIdList).length > 1)) { + if (sourceName && !(get(atm.WinIdList) !== undefined && get(atm.WinIdList).length > 1)) { var playerData = mpris2Source.data[sourceName] if (playerData.CanControl) { var playing = (playerData.PlaybackStatus === "Playing"); var menuItem = menu.newMenuItem(menu); menuItem.text = i18nc("Play previous track", "Previous Track"); menuItem.icon = "media-skip-backward"; menuItem.enabled = Qt.binding(function() { return playerData.CanGoPrevious; }); menuItem.clicked.connect(function() { mpris2Source.goPrevious(sourceName); }); menu.addMenuItem(menuItem, virtualDesktopsMenuItem); menuItem = menu.newMenuItem(menu); // PlasmaCore Menu doesn't actually handle icons or labels changing at runtime... menuItem.text = Qt.binding(function() { // if CanPause, toggle the menu entry between Play & Pause, otherwise always use Play return playing && playerData.CanPause ? i18nc("Pause playback", "Pause") : i18nc("Start playback", "Play"); }); menuItem.icon = Qt.binding(function() { return playing && playerData.CanPause ? "media-playback-pause" : "media-playback-start"; }); menuItem.enabled = Qt.binding(function() { return playing ? playerData.CanPause : playerData.CanPlay; }); menuItem.clicked.connect(function() { if (playing) { mpris2Source.pause(sourceName); } else { mpris2Source.play(sourceName); } }); menu.addMenuItem(menuItem, virtualDesktopsMenuItem); menuItem = menu.newMenuItem(menu); menuItem.text = i18nc("Play next track", "Next Track"); menuItem.icon = "media-skip-forward"; menuItem.enabled = Qt.binding(function() { return playerData.CanGoNext; }); menuItem.clicked.connect(function() { mpris2Source.goNext(sourceName); }); menu.addMenuItem(menuItem, virtualDesktopsMenuItem); menuItem = menu.newMenuItem(menu); menuItem.text = i18nc("Stop playback", "Stop"); menuItem.icon = "media-playback-stop"; menuItem.enabled = Qt.binding(function() { return playerData.PlaybackStatus !== "Stopped"; }); menuItem.clicked.connect(function() { mpris2Source.stop(sourceName); }); menu.addMenuItem(menuItem, virtualDesktopsMenuItem); // Technically media controls and audio streams are separate but for the user they're // semantically related, don't add a separator inbetween. if (!menu.visualParent.hasAudioStream) { menu.addMenuItem(newSeparator(menu), virtualDesktopsMenuItem); } // If we don't have a window associated with the player but we can quit // it through MPRIS we'll offer a "Quit" option instead of "Close" if (!closeWindowItem.visible && playerData.CanQuit) { menuItem = menu.newMenuItem(menu); menuItem.text = i18nc("Quit media player app", "Quit"); menuItem.icon = "application-exit"; menuItem.visible = Qt.binding(function() { return !closeWindowItem.visible; }); menuItem.clicked.connect(function() { mpris2Source.quit(sourceName); }); menu.addMenuItem(menuItem); } // If we don't have a window associated with the player but we can raise // it through MPRIS we'll offer a "Restore" option if (!startNewInstanceItem.visible && playerData.CanRaise) { menuItem = menu.newMenuItem(menu); menuItem.text = i18nc("Open or bring to the front window of media player app", "Restore"); menuItem.icon = playerData["Desktop Icon Name"]; menuItem.visible = Qt.binding(function() { return !startNewInstanceItem.visible; }); menuItem.clicked.connect(function() { mpris2Source.raise(sourceName); }); menu.addMenuItem(menuItem, startNewInstanceItem); } } } // We allow mute/unmute whenever an application has a stream, regardless of whether it // is actually playing sound. // This way you can unmute, e.g. a telephony app, even after the conversation has ended, // so you still have it ringing later on. if (menu.visualParent.hasAudioStream) { var muteItem = menu.newMenuItem(menu); muteItem.checkable = true; muteItem.checked = Qt.binding(function() { return menu.visualParent && menu.visualParent.muted; }); muteItem.clicked.connect(function() { menu.visualParent.toggleMuted(); }); muteItem.text = i18n("Mute"); muteItem.icon = "audio-volume-muted"; menu.addMenuItem(muteItem, virtualDesktopsMenuItem); menu.addMenuItem(newSeparator(menu), virtualDesktopsMenuItem); } } PlasmaComponents.MenuItem { id: virtualDesktopsMenuItem visible: virtualDesktopInfo.numberOfDesktops > 1 && (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true && get(atm.IsVirtualDesktopsChangeable) === true) enabled: visible text: i18n("Move To &Desktop") Connections { target: virtualDesktopInfo onNumberOfDesktopsChanged: Qt.callLater(virtualDesktopsMenu.refresh) onDesktopIdsChanged: Qt.callLater(virtualDesktopsMenu.refresh) onDesktopNamesChanged: Qt.callLater(virtualDesktopsMenu.refresh) } PlasmaComponents.ContextMenu { id: virtualDesktopsMenu visualParent: virtualDesktopsMenuItem.action function refresh() { clearMenuItems(); if (virtualDesktopInfo.numberOfDesktops <= 1) { return; } var menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18n("Move &To Current Desktop"); menuItem.enabled = Qt.binding(function() { - return menu.visualParent && menu.get(atm.VirtualDesktops).indexOf(virtualDesktopInfo.currentDesktop) == -1; + return menu.visualParent && menu.get(atm.VirtualDesktops).indexOf(virtualDesktopInfo.currentDesktop) === -1; }); menuItem.clicked.connect(function() { tasksModel.requestVirtualDesktops(menu.modelIndex, [virtualDesktopInfo.currentDesktop]); }); menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18n("&All Desktops"); menuItem.checkable = true; menuItem.checked = Qt.binding(function() { return menu.visualParent && menu.get(atm.IsOnAllVirtualDesktops) === true; }); menuItem.clicked.connect(function() { tasksModel.requestVirtualDesktops(menu.modelIndex, []); }); backend.setActionGroup(menuItem.action); menu.newSeparator(virtualDesktopsMenu); for (var i = 0; i < virtualDesktopInfo.desktopNames.length; ++i) { menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18nc("1 = number of desktop, 2 = desktop name", "&%1 %2", i + 1, virtualDesktopInfo.desktopNames[i]); menuItem.checkable = true; menuItem.checked = Qt.binding((function(i) { return function() { return menu.visualParent && menu.get(atm.VirtualDesktops).indexOf(virtualDesktopInfo.desktopIds[i]) > -1 }; })(i)); menuItem.clicked.connect((function(i) { return function() { return tasksModel.requestVirtualDesktops(menu.modelIndex, [virtualDesktopInfo.desktopIds[i]]); }; })(i)); backend.setActionGroup(menuItem.action); } menu.newSeparator(virtualDesktopsMenu); menuItem = menu.newMenuItem(virtualDesktopsMenu); menuItem.text = i18n("&New Desktop"); menuItem.clicked.connect(function() { tasksModel.requestNewVirtualDesktop(menu.modelIndex); }); } Component.onCompleted: refresh() } } PlasmaComponents.MenuItem { id: activitiesDesktopsMenuItem visible: activityInfo.numberOfRunningActivities > 1 && (visualParent && !get(atm.IsLauncher) && !get(atm.IsStartup)) enabled: visible text: i18n("Move To &Activity") Connections { target: activityInfo onNumberOfRunningActivitiesChanged: activitiesDesktopsMenu.refresh() } PlasmaComponents.ContextMenu { id: activitiesDesktopsMenu visualParent: activitiesDesktopsMenuItem.action function refresh() { clearMenuItems(); if (activityInfo.numberOfRunningActivities <= 1) { return; } var menuItem = menu.newMenuItem(activitiesDesktopsMenu); menuItem.text = i18n("Add To Current Activity"); menuItem.enabled = Qt.binding(function() { return menu.visualParent && menu.get(atm.Activities).length > 0 && menu.get(atm.Activities).indexOf(activityInfo.currentActivity) < 0; }); menuItem.clicked.connect(function() { tasksModel.requestActivities(menu.modelIndex, menu.get(atm.Activities).concat(activityInfo.currentActivity)); }); menuItem = menu.newMenuItem(activitiesDesktopsMenu); menuItem.text = i18n("All Activities"); menuItem.checkable = true; menuItem.checked = Qt.binding(function() { return menu.visualParent && menu.get(atm.Activities).length === 0; }); menuItem.toggled.connect(function(checked) { var newActivities = undefined; // will cast to an empty QStringList i.e all activities if (!checked) { newActivities = new Array(activityInfo.currentActivity); } tasksModel.requestActivities(menu.modelIndex, newActivities); }); menu.newSeparator(activitiesDesktopsMenu); var runningActivities = activityInfo.runningActivities(); for (var i = 0; i < runningActivities.length; ++i) { var activityId = runningActivities[i]; menuItem = menu.newMenuItem(activitiesDesktopsMenu); menuItem.text = activityInfo.activityName(runningActivities[i]); menuItem.checkable = true; menuItem.checked = Qt.binding( (function(activityId) { return function() { return menu.visualParent && menu.get(atm.Activities).indexOf(activityId) >= 0; }; })(activityId)); menuItem.toggled.connect((function(activityId) { return function (checked) { var newActivities = menu.get(atm.Activities); if (checked) { newActivities = newActivities.concat(activityId); } else { var index = newActivities.indexOf(activityId) if (index < 0) { return; } newActivities.splice(index, 1); } return tasksModel.requestActivities(menu.modelIndex, newActivities); }; })(activityId)); } menu.newSeparator(activitiesDesktopsMenu); } Component.onCompleted: refresh() } } PlasmaComponents.MenuItem { visible: (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) enabled: visualParent && get(atm.IsMinimizable) === true checkable: true checked: visualParent && get(atm.IsMinimized) === true text: i18n("Mi&nimize") onClicked: tasksModel.requestToggleMinimized(modelIndex) } PlasmaComponents.MenuItem { visible: (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) enabled: visualParent && get(atm.IsMaximizable) === true checkable: true checked: visualParent && get(atm.IsMaximized) === true text: i18n("Ma&ximize") onClicked: tasksModel.requestToggleMaximized(modelIndex) } PlasmaComponents.MenuItem { id: startNewInstanceItem visible: (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) - enabled: visualParent && get(atm.LauncherUrlWithoutIcon) != "" + enabled: visualParent && get(atm.LauncherUrlWithoutIcon) !== "" text: i18n("Start New Instance") icon: "system-run" onClicked: tasksModel.requestNewInstance(modelIndex) } PlasmaComponents.MenuItem { id: launcherToggleAction visible: visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable && (activityInfo.numberOfRunningActivities < 2) - enabled: visualParent && get(atm.LauncherUrlWithoutIcon) != "" + enabled: visualParent && get(atm.LauncherUrlWithoutIcon) !== "" checkable: true text: i18nc("Toggle action for showing a launcher button while the application is not running", "&Pin") onClicked: { - if (tasksModel.launcherPosition(get(atm.LauncherUrlWithoutIcon)) != -1) { + if (tasksModel.launcherPosition(get(atm.LauncherUrlWithoutIcon)) !== -1) { tasksModel.requestRemoveLauncher(get(atm.LauncherUrlWithoutIcon)); } else { tasksModel.requestAddLauncher(get(atm.LauncherUrl)); } } } PlasmaComponents.MenuItem { id: showLauncherInActivitiesItem text: i18n("&Pin") visible: visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable && (activityInfo.numberOfRunningActivities >= 2) Connections { target: activityInfo onNumberOfRunningActivitiesChanged: activitiesDesktopsMenu.refresh() } PlasmaComponents.ContextMenu { id: activitiesLaunchersMenu visualParent: showLauncherInActivitiesItem.action function refresh() { clearMenuItems(); if (menu.visualParent === null) return; var createNewItem = function(id, title, url, activities) { var result = menu.newMenuItem(activitiesLaunchersMenu); result.text = title; result.visible = true; result.checkable = true; result.checked = activities.some(function(activity) { return activity === id }); result.clicked.connect( function() { if (result.checked) { tasksModel.requestAddLauncherToActivity(url, id); } else { tasksModel.requestRemoveLauncherFromActivity(url, id); } } ); return result; } if (menu.visualParent === null) return; var url = menu.get(atm.LauncherUrlWithoutIcon); var activities = tasksModel.launcherActivities(url); var NULL_UUID = "00000000-0000-0000-0000-000000000000"; createNewItem(NULL_UUID, i18n("On All Activities"), url, activities); if (activityInfo.numberOfRunningActivities <= 1) { return; } createNewItem(activityInfo.currentActivity, i18n("On The Current Activity"), url, activities); menu.newSeparator(activitiesLaunchersMenu); var runningActivities = activityInfo.runningActivities(); runningActivities.forEach(function(id) { createNewItem(id, activityInfo.activityName(id), url, activities); }); } Component.onCompleted: { menu.onVisualParentChanged.connect(refresh); refresh(); } } } PlasmaComponents.MenuItem { visible: (visualParent && get(atm.IsLauncher) === true) && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable text: i18nc("Remove launcher button for application shown while it is not running", "Unpin") onClicked: { tasksModel.requestRemoveLauncher(get(atm.LauncherUrlWithoutIcon)); } } PlasmaComponents.MenuItem { id: moreActionsMenuItem visible: (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) enabled: visible text: i18n("More Actions") PlasmaComponents.ContextMenu { visualParent: moreActionsMenuItem.action PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.get(atm.IsMovable) === true text: i18n("&Move") icon: "transform-move" onClicked: tasksModel.requestMove(menu.modelIndex) } PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.get(atm.IsResizable) === true text: i18n("Re&size") onClicked: tasksModel.requestResize(menu.modelIndex) } PlasmaComponents.MenuItem { checkable: true checked: menu.visualParent && menu.get(atm.IsKeepAbove) === true text: i18n("Keep &Above Others") icon: "go-up" onClicked: tasksModel.requestToggleKeepAbove(menu.modelIndex) } PlasmaComponents.MenuItem { checkable: true checked: menu.visualParent && menu.get(atm.IsKeepBelow) === true text: i18n("Keep &Below Others") icon: "go-down" onClicked: tasksModel.requestToggleKeepBelow(menu.modelIndex) } PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.get(atm.IsFullScreenable) === true checkable: true checked: menu.visualParent && menu.get(atm.IsFullScreen) === true text: i18n("&Fullscreen") icon: "view-fullscreen" onClicked: tasksModel.requestToggleFullScreen(menu.modelIndex) } PlasmaComponents.MenuItem { enabled: menu.visualParent && menu.get(atm.IsShadeable) === true checkable: true checked: menu.visualParent && menu.get(atm.IsShaded) === true text: i18n("&Shade") onClicked: tasksModel.requestToggleShaded(menu.modelIndex) } PlasmaComponents.MenuItem { separator: true } PlasmaComponents.MenuItem { - visible: (plasmoid.configuration.groupingStrategy != 0) && menu.get(atm.IsWindow) === true + visible: (plasmoid.configuration.groupingStrategy !== 0) && menu.get(atm.IsWindow) === true checkable: true checked: menu.visualParent && menu.get(atm.IsGroupable) === true text: i18n("Allow this program to be grouped") onClicked: tasksModel.requestToggleGrouping(menu.modelIndex) } } } PlasmaComponents.MenuItem { separator: true } PlasmaComponents.MenuItem { property QtObject configureAction: null enabled: configureAction && configureAction.enabled visible: configureAction && configureAction.visible text: configureAction ? configureAction.text : "" icon: configureAction ? configureAction.icon : "" onClicked: configureAction.trigger() Component.onCompleted: configureAction = plasmoid.action("configure") } PlasmaComponents.MenuItem { property QtObject alternativesAction: null enabled: alternativesAction && alternativesAction.enabled visible: alternativesAction && alternativesAction.visible text: alternativesAction ? alternativesAction.text : "" icon: alternativesAction ? alternativesAction.icon : "" onClicked: alternativesAction.trigger() Component.onCompleted: alternativesAction = plasmoid.action("alternatives") } PlasmaComponents.MenuItem { separator: true } PlasmaComponents.MenuItem { id: closeWindowItem visible: (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) enabled: visualParent && get(atm.IsClosable) === true text: i18n("&Close") icon: "window-close" onClicked: tasksModel.requestClose(modelIndex) } } diff --git a/applets/taskmanager/package/contents/ui/GroupDialog.qml b/applets/taskmanager/package/contents/ui/GroupDialog.qml index 362e6ce88..5c2796849 100644 --- a/applets/taskmanager/package/contents/ui/GroupDialog.qml +++ b/applets/taskmanager/package/contents/ui/GroupDialog.qml @@ -1,299 +1,299 @@ /*************************************************************************** * Copyright (C) 2012-2013 by 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 . * ***************************************************************************/ import QtQuick 2.4 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.draganddrop 2.0 import "code/layout.js" as LayoutManager PlasmaCore.Dialog { id: groupDialog visible: false type: PlasmaCore.Dialog.PopupMenu flags: Qt.WindowStaysOnTopHint hideOnWindowDeactivate: true location: plasmoid.location readonly property int preferredWidth: Screen.width / (3 * Screen.devicePixelRatio) readonly property int preferredHeight: Screen.height / (2 * Screen.devicePixelRatio) readonly property int contentWidth: scrollArea.overflowing ? mainItem.width - (units.smallSpacing * 3) : mainItem.width readonly property TextMetrics textMetrics: TextMetrics {} property alias overflowing: scrollArea.overflowing property alias activeTask: focusActiveTaskTimer.targetIndex property var _oldAppletStatus: PlasmaCore.Types.UnknownStatus function selectTask(task) { if (!task) { return; } task.forceActiveFocus(); scrollArea.ensureItemVisible(task); } mainItem: MouseHandler { id: mouseHandler target: taskList handleWheelEvents: !scrollArea.overflowing Timer { id: focusActiveTaskTimer property var targetIndex: null interval: 0 repeat: false onTriggered: { // Now we can home in on the previously active task // collected in groupDialog.onVisibleChanged. if (targetIndex != null) { for (var i = 0; i < groupRepeater.count; ++i) { var task = groupRepeater.itemAt(i); - if (task.modelIndex() == targetIndex) { + if (task.modelIndex() === targetIndex) { selectTask(task); return; } } } } } PlasmaExtras.ScrollArea { id: scrollArea anchors.fill: parent readonly property bool overflowing: (viewport.height < contentItem.height) horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff function ensureItemVisible(item) { var itemTop = item.y; var itemBottom = (item.y + item.height); if (itemTop < flickableItem.contentY) { flickableItem.contentY = itemTop; } if ((itemBottom - flickableItem.contentY) > viewport.height) { flickableItem.contentY = Math.abs(viewport.height - itemBottom); } } TaskList { id: taskList width: parent.width add: Transition { // We trigger a null-interval timer in the first add // transition after setting the model so onTriggered // will run after the Flow has positioned items. ScriptAction { script: { if (groupRepeater.aboutToPopulate) { focusActiveTaskTimer.restart(); groupRepeater.aboutToPopulate = false; } } } } onAnimatingChanged: { if (!animating) { Qt.callLater(updateSize); } } Repeater { id: groupRepeater property bool aboutToPopulate: false function currentIndex() { for (var i = 0; i < count; ++i) { if (itemAt(i).activeFocus) { return i; } } return -1; } onItemAdded: Qt.callLater(updateSize) onItemRemoved: { if (groupDialog.visible && index > 0 && index == count) { Qt.callLater(updateSize); } } } } Component.onCompleted: { flickableItem.boundsBehavior = Flickable.StopAtBounds; } } Keys.onUpPressed: { var currentIndex = groupRepeater.currentIndex(); // In doubt focus the last item, so we start at the bottom when user // initially presses up. if (currentIndex === -1) { selectTask(groupRepeater.itemAt(groupRepeater.count - 1)); return; } var previousIndex = currentIndex - 1; if (previousIndex < 0) { previousIndex = groupRepeater.count - 1; } selectTask(groupRepeater.itemAt(previousIndex)); } Keys.onDownPressed: { var currentIndex = groupRepeater.currentIndex(); // In doubt focus the first item, also wrap around. if (currentIndex === -1 || currentIndex + 1 >= groupRepeater.count) { selectTask(groupRepeater.itemAt(0)); return; } selectTask(groupRepeater.itemAt(currentIndex + 1)); } Keys.onEscapePressed: groupDialog.visible = false; } data: [ VisualDataModel { id: groupFilter delegate: Task { visible: true inPopup: true } } ] onVisualParentChanged: { if (visible && visualParent) { attachModel(); } else { visible = false; } } onVisibleChanged: { if (visible && visualParent) { _oldAppletStatus = plasmoid.status; plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus; attachModel(); groupDialog.requestActivate(); mouseHandler.forceActiveFocus(); } else { plasmoid.status = _oldAppletStatus; visualParent = null; groupRepeater.model = undefined; groupFilter.model = undefined; groupFilter.rootIndex = undefined; } } function attachModel() { if (!visualParent) { return; } if (!groupFilter.model) { groupFilter.model = tasksModel; } groupRepeater.aboutToPopulate = true; groupFilter.rootIndex = tasksModel.makeModelIndex(visualParent.itemIndex); if (!groupRepeater.model) { groupRepeater.model = groupFilter; } } function updateSize() { if (!visible) { return; } if (!visualParent) { visible = false; return; } if (!visualParent.childCount) { visible = false; // Setting VisualDataModel.rootIndex drops groupRepeater.count to 0 // before the actual row count. updateSize is therefore invoked twice; // only update size once the repeater count matches the model role. - } else if (!groupRepeater.aboutToPopulate || visualParent.childCount == groupRepeater.count) { + } else if (!groupRepeater.aboutToPopulate || visualParent.childCount === groupRepeater.count) { var task; var maxWidth = 0; var maxHeight = 0; backend.cancelHighlightWindows(); for (var i = 0; i < taskList.children.length - 1; ++i) { task = taskList.children[i]; textMetrics.text = task.labelText; var textWidth = textMetrics.boundingRect.width; if (textWidth > maxWidth) { maxWidth = textWidth; } task.labelTextChanged.connect(updateSize); } maxHeight = groupRepeater.count * (LayoutManager.verticalMargins() + Math.max(theme.mSize(theme.defaultFont).height, units.iconSizes.medium)); maxWidth += LayoutManager.horizontalMargins() + units.iconSizes.medium + 2 * units.smallSpacing; // Add horizontal space for scrollbar if needed. // FIXME TODO HACK: Use actual scrollbar width instead of a good guess. if (maxHeight > preferredHeight) { maxWidth += (units.smallSpacing * 3); } mainItem.height = Math.min(preferredHeight, maxHeight); mainItem.width = Math.min(preferredWidth, (tasks.vertical ? Math.max(maxWidth, tasks.width) : Math.min(maxWidth, tasks.width))); } } } diff --git a/applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml b/applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml index 00f764d3e..7ddec7921 100644 --- a/applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml +++ b/applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml @@ -1,95 +1,95 @@ /*************************************************************************** * Copyright (C) 2012-2013 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore PlasmaCore.SvgItem { id: arrow anchors { bottom: arrow.parent.bottom horizontalCenter: iconBox.horizontalCenter } visible: parent.m.IsGroupParent === true states: [ State { name: "top" - when: plasmoid.location == PlasmaCore.Types.TopEdge + when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges { target: arrow anchors.top: arrow.parent.top anchors.left: undefined anchors.right: undefined anchors.bottom: undefined anchors.horizontalCenter: iconBox.horizontalCenter anchors.verticalCenter: undefined } }, State { name: "left" - when: plasmoid.location == PlasmaCore.Types.LeftEdge + when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges { target: arrow anchors.top: undefined anchors.left: arrow.parent.left anchors.right: undefined anchors.bottom: undefined anchors.horizontalCenter: undefined anchors.verticalCenter: iconBox.verticalCenter } }, State { name: "right" - when: plasmoid.location == PlasmaCore.Types.RightEdge + when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges { target: arrow anchors.top: undefined anchors.left: undefined anchors.right: arrow.parent.right anchors.bottom: undefined anchors.horizontalCenter: undefined anchors.verticalCenter: iconBox.verticalCenter } } ] implicitWidth: Math.min(naturalSize.width, iconBox.width) implicitHeight: Math.min(naturalSize.height, iconBox.width) svg: taskSvg elementId: elementForLocation() function elementForLocation() { switch (plasmoid.location) { case PlasmaCore.Types.LeftEdge: return "group-expander-left"; case PlasmaCore.Types.TopEdge: return "group-expander-top"; case PlasmaCore.Types.RightEdge: return "group-expander-right"; case PlasmaCore.Types.BottomEdge: default: return "group-expander-bottom"; } } } diff --git a/applets/taskmanager/package/contents/ui/MouseHandler.qml b/applets/taskmanager/package/contents/ui/MouseHandler.qml index db6d397d1..cb0695a9a 100644 --- a/applets/taskmanager/package/contents/ui/MouseHandler.qml +++ b/applets/taskmanager/package/contents/ui/MouseHandler.qml @@ -1,194 +1,194 @@ /*************************************************************************** * Copyright (C) 2012-2016 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.draganddrop 2.0 import org.kde.taskmanager 0.1 as TaskManager import "code/tools.js" as TaskTools Item { signal urlsDropped(var urls) property Item target property Item ignoredItem property bool moved: false property alias hoveredItem: dropHandler.hoveredItem property alias handleWheelEvents: wheelHandler.active Timer { id: ignoreItemTimer repeat: false interval: 750 onTriggered: { ignoredItem = null; } } Connections { target: tasks onDragSourceChanged: { if (!dragSource) { ignoredItem = null; ignoreItemTimer.stop(); } } } DropArea { id: dropHandler anchors.fill: parent preventStealing: true; property Item hoveredItem //ignore anything that is neither internal to TaskManager or a URL list onDragEnter: { if (event.mimeData.formats.indexOf("text/x-plasmoidservicename") >= 0) { event.ignore(); } } onDragMove: { if (target.animating) { return; } var above = target.childAt(event.x, event.y); if (!above) { hoveredItem = null; activationTimer.stop(); return; } // If we're mixing launcher tasks with other tasks and are moving // a (small) launcher task across a non-launcher task, don't allow // the latter to be the move target twice in a row for a while, as // it will naturally be moved underneath the cursor as result of the // initial move, due to being far larger than the launcher delegate. // TODO: This restriction (minus the timer, which improves things) // has been proven out in the EITM fork, but could be improved later // by tracking the cursor movement vector and allowing the drag if // the movement direction has reversed, etablishing user intent to // move back. if (!plasmoid.configuration.separateLaunchers && tasks.dragSource != null && tasks.dragSource.m.IsLauncher === true && above.m.IsLauncher !== true - && above == ignoredItem) { + && above= == ignoredItem) { return; } else { ignoredItem = null; } - if (tasksModel.sortMode == TaskManager.TasksModel.SortManual && tasks.dragSource) { + if (tasksModel.sortMode === TaskManager.TasksModel.SortManual && tasks.dragSource) { // Reject drags between different TaskList instances. - if (tasks.dragSource.parent != above.parent) { + if (tasks.dragSource.parent !== above.parent) { return; } var insertAt = TaskTools.insertIndexAt(above, event.x, event.y); - if (tasks.dragSource != above && tasks.dragSource.itemIndex != insertAt) { + if (tasks.dragSource !== above && tasks.dragSource.itemIndex !== insertAt) { if (groupDialog.visible && groupDialog.visualParent) { tasksModel.move(tasks.dragSource.itemIndex, insertAt, tasksModel.makeModelIndex(groupDialog.visualParent.itemIndex)); } else { tasksModel.move(tasks.dragSource.itemIndex, insertAt); } ignoredItem = above; ignoreItemTimer.restart(); } - } else if (!tasks.dragSource && hoveredItem != above) { + } else if (!tasks.dragSource && hoveredItem !== above) { hoveredItem = above; activationTimer.restart(); } } onDragLeave: { hoveredItem = null; activationTimer.stop(); } onDrop: { // Reject internal drops. if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") >= 0) { event.ignore(); return; } // Reject plasmoid drops. if (event.mimeData.formats.indexOf("text/x-plasmoidservicename") >= 0) { event.ignore(); return; } if (event.mimeData.hasUrls) { parent.urlsDropped(event.mimeData.urls); return; } } Timer { id: activationTimer interval: 250 repeat: false onTriggered: { if (parent.hoveredItem.m.IsGroupParent === true) { groupDialog.visualParent = parent.hoveredItem; groupDialog.visible = true; } else if (parent.hoveredItem.m.IsLauncher !== true) { tasksModel.requestActivate(parent.hoveredItem.modelIndex()); } } } } MouseArea { id: wheelHandler anchors.fill: parent enabled: active && plasmoid.configuration.wheelEnabled property bool active: true property int wheelDelta: 0; onWheel: { if (!active) { wheel.accepted = false; return; } wheelDelta = TaskTools.wheelActivateNextPrevTask(null, wheelDelta, wheel.angleDelta.y); } } } diff --git a/applets/taskmanager/package/contents/ui/PulseAudio.qml b/applets/taskmanager/package/contents/ui/PulseAudio.qml index 81f4e3c83..84c7a95c4 100644 --- a/applets/taskmanager/package/contents/ui/PulseAudio.qml +++ b/applets/taskmanager/package/contents/ui/PulseAudio.qml @@ -1,93 +1,93 @@ /*************************************************************************** * Copyright (C) 2017 by 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) 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 . * ***************************************************************************/ import QtQuick 2.2 import org.kde.plasma.private.volume 0.1 QtObject { id: pulseAudio signal streamsChanged // It's a JS object so we can do key lookup and don't need to take care of filtering duplicates. property var pidMatches: ({}) // TODO Evict cache at some point, preferably if all instances of an application closed. function registerPidMatch(appName) { if (!hasPidMatch(appName)) { pidMatches[appName] = true; // In case this match is new, notify that streams might have changed. // This way we also catch the case when the non-playing instance // shows up first. // Only notify if we changed to avoid infinite recursion. streamsChanged(); } } function hasPidMatch(appName) { return pidMatches[appName] === true; } function findStreams(key, value) { var streams = [] for (var i = 0, length = instantiator.count; i < length; ++i) { var stream = instantiator.objectAt(i); - if (stream[key] == value) { + if (stream[key] === value) { streams.push(stream); } } return streams } function streamsForAppName(appName) { return findStreams("appName", appName); } function streamsForPid(pid) { return findStreams("pid", pid); } // QtObject has no default property, hence adding the Instantiator to one explicitly. property var instantiator: Instantiator { model: PulseObjectFilterModel { filters: [ { role: "VirtualStream", value: false } ] sourceModel: SinkInputModel {} } delegate: QtObject { readonly property int pid: Client ? Client.properties["application.process.id"] : 0 readonly property string appName: Client ? Client.properties["application.name"] : "" readonly property bool muted: Muted // whether there is nothing actually going on on that stream readonly property bool corked: Corked function mute() { Muted = true } function unmute() { Muted = false } } onObjectAdded: pulseAudio.streamsChanged() onObjectRemoved: pulseAudio.streamsChanged() } } diff --git a/applets/taskmanager/package/contents/ui/Task.qml b/applets/taskmanager/package/contents/ui/Task.qml index 46faa66f0..1c8525dca 100644 --- a/applets/taskmanager/package/contents/ui/Task.qml +++ b/applets/taskmanager/package/contents/ui/Task.qml @@ -1,585 +1,585 @@ /*************************************************************************** * Copyright (C) 2012-2013 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.draganddrop 2.0 import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import "code/layout.js" as LayoutManager import "code/tools.js" as TaskTools MouseArea { id: task width: groupDialog.contentWidth height: Math.max(theme.mSize(theme.defaultFont).height, units.iconSizes.medium) + LayoutManager.verticalMargins() visible: false LayoutMirroring.enabled: (Qt.application.layoutDirection == Qt.RightToLeft) LayoutMirroring.childrenInherit: (Qt.application.layoutDirection == Qt.RightToLeft) readonly property var m: model - readonly property int pid: model.AppPid != undefined ? model.AppPid : 0 + readonly property int pid: model.AppPid !== undefined ? model.AppPid : 0 readonly property string appName: model.AppName property int itemIndex: index property bool inPopup: false property bool isWindow: model.IsWindow === true - property int childCount: model.ChildCount != undefined ? model.ChildCount : 0 + property int childCount: model.ChildCount !== undefined ? model.ChildCount : 0 property int previousChildCount: 0 property alias labelText: label.text property bool pressed: false property int pressX: -1 property int pressY: -1 property QtObject contextMenu: null property int wheelDelta: 0 readonly property bool smartLauncherEnabled: plasmoid.configuration.smartLaunchersEnabled && !inPopup && model.IsStartup !== true property QtObject smartLauncherItem: null property alias toolTipAreaItem: toolTipArea property Item audioStreamOverlay property var audioStreams: [] property bool delayAudioStreamIndicator: false readonly property bool hasAudioStream: plasmoid.configuration.indicateAudioStreams && audioStreams.length > 0 readonly property bool playingAudio: hasAudioStream && audioStreams.some(function (item) { return !item.corked }) readonly property bool muted: hasAudioStream && audioStreams.every(function (item) { return item.muted }) readonly property bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaComponents.DialogStatus.Open) || (groupDialog.visible && groupDialog.visualParent === task) function hideToolTipTemporarily() { toolTipArea.hideToolTip(); } acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MidButton | Qt.BackButton | Qt.ForwardButton onPidChanged: updateAudioStreams({delay: false}) onAppNameChanged: updateAudioStreams({delay: false}) onIsWindowChanged: { if (isWindow) { taskInitComponent.createObject(task); } } onChildCountChanged: { if (!childCount && groupDialog.visualParent == task) { groupDialog.visible = false; return; } if (containsMouse) { groupDialog.activeTask = null; } if (childCount > previousChildCount) { tasksModel.requestPublishDelegateGeometry(modelIndex(), backend.globalRect(task), task); } previousChildCount = childCount; } onItemIndexChanged: { hideToolTipTemporarily(); if (!inPopup && !tasks.vertical && (LayoutManager.calculateStripes() > 1 || !plasmoid.configuration.separateLaunchers)) { tasks.requestLayout(); } } onContainsMouseChanged: { if (containsMouse) { if (inPopup) { forceActiveFocus(); } } else { pressed = false; } if (model.IsWindow === true) { tasks.windowsHovered(model.WinIdList, containsMouse); } } onPressed: { if (mouse.button == Qt.LeftButton || mouse.button == Qt.MidButton || mouse.button === Qt.BackButton || mouse.button === Qt.ForwardButton) { pressed = true; pressX = mouse.x; pressY = mouse.y; } else if (mouse.button == Qt.RightButton) { // When we're a launcher, there's no window controls, so we can show all // places without the menu getting super huge. if (model.IsLauncher === true) { showContextMenu({showAllPlaces: true}) } else { showContextMenu(); } } } onReleased: { if (pressed) { if (mouse.button == Qt.MidButton) { - if (plasmoid.configuration.middleClickAction == TaskManagerApplet.Backend.NewInstance) { + if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.NewInstance) { tasksModel.requestNewInstance(modelIndex()); - } else if (plasmoid.configuration.middleClickAction == TaskManagerApplet.Backend.Close) { + } else if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.Close) { tasksModel.requestClose(modelIndex()); - } else if (plasmoid.configuration.middleClickAction == TaskManagerApplet.Backend.ToggleMinimized) { + } else if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.ToggleMinimized) { tasksModel.requestToggleMinimized(modelIndex()); - } else if (plasmoid.configuration.middleClickAction == TaskManagerApplet.Backend.ToggleGrouping) { + } else if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.ToggleGrouping) { tasksModel.requestToggleGrouping(modelIndex()); } } else if (mouse.button == Qt.LeftButton) { TaskTools.activateTask(modelIndex(), model, mouse.modifiers, task); if (plasmoid.configuration.showToolTips) { hideToolTipTemporarily(); } } else if (mouse.button === Qt.BackButton || mouse.button === Qt.ForwardButton) { var sourceName = mpris2Source.sourceNameForLauncherUrl(model.LauncherUrlWithoutIcon, model.AppPid); if (sourceName) { if (mouse.button === Qt.BackButton) { mpris2Source.goPrevious(sourceName); } else { mpris2Source.goNext(sourceName); } } else { mouse.accepted = false; } } backend.cancelHighlightWindows(); } pressed = false; pressX = -1; pressY = -1; } onPositionChanged: { // mouse.button is always 0 here, hence checking with mouse.buttons if (pressX != -1 && mouse.buttons == Qt.LeftButton && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { tasks.dragSource = task; dragHelper.startDrag(task, model.MimeType, model.MimeData, model.LauncherUrlWithoutIcon, model.decoration); pressX = -1; pressY = -1; return; } } onWheel: { if (plasmoid.configuration.wheelEnabled && (!inPopup || !groupDialog.overflowing)) { wheelDelta = TaskTools.wheelActivateNextPrevTask(task, wheelDelta, wheel.angleDelta.y); } else { wheel.accepted = false; } } onSmartLauncherEnabledChanged: { if (smartLauncherEnabled && !smartLauncherItem) { var smartLauncher = Qt.createQmlObject(" import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet; TaskManagerApplet.SmartLauncherItem { }", task); smartLauncher.launcherUrl = Qt.binding(function() { return model.LauncherUrlWithoutIcon; }); smartLauncherItem = smartLauncher; } } onHasAudioStreamChanged: { if (hasAudioStream) { audioStreamIconLoader.active = true } } Keys.onReturnPressed: TaskTools.activateTask(modelIndex(), model, event.modifiers, task) Keys.onEnterPressed: Keys.onReturnPressed(event); function modelIndex() { return (inPopup ? tasksModel.makeModelIndex(groupDialog.visualParent.itemIndex, index) : tasksModel.makeModelIndex(index)); } function showContextMenu(args) { contextMenu = tasks.createContextMenu(task, modelIndex(), args); contextMenu.show(); } function updateAudioStreams(args) { if (args) { // When the task just appeared (e.g. virtual desktop switch), show the audio indicator // right away. Only when audio streams change during the lifetime of this task, delay // showing that to avoid distraction. delayAudioStreamIndicator = !!args.delay; } var pa = pulseAudio.item; if (!pa) { task.audioStreams = []; return; } var streams = pa.streamsForPid(task.pid); if (streams.length) { pa.registerPidMatch(task.appName); } else { // We only want to fall back to appName matching if we never managed to map // a PID to an audio stream window. Otherwise if you have two instances of // an application, one playing and the other not, it will look up appName // for the non-playing instance and erroneously show an indicator on both. if (!pa.hasPidMatch(task.appName)) { streams = pa.streamsForAppName(task.appName); } } task.audioStreams = streams; } function toggleMuted() { if (muted) { task.audioStreams.forEach(function (item) { item.unmute(); }); } else { task.audioStreams.forEach(function (item) { item.mute(); }); } } Connections { target: pulseAudio.item ignoreUnknownSignals: true // Plasma-PA might not be available onStreamsChanged: task.updateAudioStreams({delay: true}) } Component { id: taskInitComponent Timer { id: timer interval: units.longDuration * 2 repeat: false onTriggered: { parent.hoverEnabled = true; if (parent.isWindow) { tasksModel.requestPublishDelegateGeometry(parent.modelIndex(), backend.globalRect(parent), parent); } timer.destroy(); } Component.onCompleted: timer.start() } } PlasmaCore.FrameSvgItem { id: frame anchors { fill: parent topMargin: (!tasks.vertical && taskList.rows > 1) ? units.smallSpacing / 4 : 0 bottomMargin: (!tasks.vertical && taskList.rows > 1) ? units.smallSpacing / 4 : 0 leftMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? units.smallSpacing / 4 : 0 rightMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? units.smallSpacing / 4 : 0 } imagePath: "widgets/tasks" property string basePrefix: "normal" prefix: TaskTools.taskPrefix(basePrefix) PlasmaCore.ToolTipArea { id: toolTipArea anchors.fill: parent location: plasmoid.location active: !inPopup && !groupDialog.visible && plasmoid.configuration.showToolTips interactive: true mainItem: toolTipDelegate onContainsMouseChanged: { if (containsMouse) { toolTipDelegate.parentTask = task; toolTipDelegate.rootIndex = tasksModel.makeModelIndex(itemIndex, -1); toolTipDelegate.appName = Qt.binding(function() { return model.AppName; }); toolTipDelegate.pidParent = Qt.binding(function() { return model.AppPid; }); toolTipDelegate.windows = Qt.binding(function() { return model.WinIdList; }); toolTipDelegate.isGroup = Qt.binding(function() { - return model.IsGroupParent == true; + return model.IsGroupParent === true; }); toolTipDelegate.icon = Qt.binding(function() { return model.decoration; }); toolTipDelegate.launcherUrl = Qt.binding(function() { return model.LauncherUrlWithoutIcon; }); toolTipDelegate.isLauncher = Qt.binding(function() { - return model.IsLauncher == true; + return model.IsLauncher === true; }); toolTipDelegate.isMinimizedParent = Qt.binding(function() { - return model.IsMinimized == true; + return model.IsMinimized === true; }); toolTipDelegate.displayParent = Qt.binding(function() { return model.display; }); toolTipDelegate.genericName = Qt.binding(function() { return model.GenericName; }); toolTipDelegate.virtualDesktopParent = Qt.binding(function() { - return model.VirtualDesktop != undefined ? model.VirtualDesktop : 0; + return model.VirtualDesktop !== undefined ? model.VirtualDesktop : 0; }); toolTipDelegate.isOnAllVirtualDesktopsParent = Qt.binding(function() { - return model.IsOnAllVirtualDesktops == true; + return model.IsOnAllVirtualDesktops === true; }); toolTipDelegate.activitiesParent = Qt.binding(function() { return model.Activities; }); toolTipDelegate.smartLauncherCountVisible = Qt.binding(function() { return plasmoid.configuration.smartLaunchersEnabled && task.smartLauncherItem && task.smartLauncherItem.countVisible; }); toolTipDelegate.smartLauncherCount = Qt.binding(function() { return toolTipDelegate.smartLauncherCountVisible ? task.smartLauncherItem.count : 0; }); } } } } Loader { anchors.fill: frame asynchronous: true source: "TaskProgressOverlay.qml" active: plasmoid.configuration.smartLaunchersEnabled && task.smartLauncherItem && task.smartLauncherItem.progressVisible } Item { id: iconBox anchors { left: parent.left leftMargin: adjustMargin(true, parent.width, taskFrame.margins.left) top: parent.top topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } width: height height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) function adjustMargin(vert, size, margin) { if (!size) { return margin; } var margins = vert ? LayoutManager.horizontalMargins() : LayoutManager.verticalMargins(); if ((size - margins) < units.iconSizes.small) { return Math.ceil((margin * (units.iconSizes.small / size)) / 2); } return margin; } //width: inPopup ? units.iconSizes.small : Math.min(height, parent.width - LayoutManager.horizontalMargins()) PlasmaCore.IconItem { id: icon anchors.fill: parent active: task.highlighted enabled: true usesPlasmaTheme: false source: model.decoration } Loader { // QTBUG anchors.fill in conjunction with the Loader doesn't reliably work on creation: // have a window with a badge, move it from one screen to another, the new task item on the // other screen will now have a glitched out badge mask. width: parent.width height: parent.height asynchronous: true source: "TaskBadgeOverlay.qml" active: plasmoid.configuration.smartLaunchersEnabled && height >= units.iconSizes.small && task.smartLauncherItem && task.smartLauncherItem.countVisible } states: [ // Using a state transition avoids a binding loop between label.visible and // the text label margin, which derives from the icon width. State { name: "standalone" when: !label.visible && !audioStreamIconLoader.shown AnchorChanges { target: iconBox anchors.left: undefined anchors.horizontalCenter: parent.horizontalCenter } PropertyChanges { target: iconBox anchors.leftMargin: 0 width: parent.width - adjustMargin(true, task.width, taskFrame.margins.left) - adjustMargin(true, task.width, taskFrame.margins.right) } } ] Loader { anchors.fill: parent active: model.IsStartup === true sourceComponent: busyIndicator } Component { id: busyIndicator PlasmaComponents.BusyIndicator { anchors.fill: parent } } } Loader { id: audioStreamIconLoader readonly property bool shown: item && item.visible source: "AudioStream.qml" width: units.roundToIconSize(Math.min(Math.min(iconBox.width, iconBox.height), units.iconSizes.smallMedium)) height: width anchors { right: parent.right rightMargin: iconBox.adjustMargin(true, parent.width, taskFrame.margins.right) verticalCenter: parent.verticalCenter } } PlasmaComponents.Label { id: label visible: (inPopup || !iconsOnly && model.IsLauncher !== true && (parent.width - iconBox.height - units.smallSpacing) >= (theme.mSize(theme.defaultFont).width * LayoutManager.minimumMColumns())) anchors { fill: parent leftMargin: taskFrame.margins.left + iconBox.width + units.smallSpacing topMargin: taskFrame.margins.top rightMargin: taskFrame.margins.right + (audioStreamIconLoader.shown ? (audioStreamIconLoader.width + units.smallSpacing) : 0) bottomMargin: taskFrame.margins.bottom } text: model.display wrapMode: (maximumLineCount == 1) ? Text.NoWrap : Text.Wrap elide: Text.ElideRight textFormat: Text.PlainText verticalAlignment: Text.AlignVCenter maximumLineCount: plasmoid.configuration.maxTextLines || undefined } states: [ State { name: "launcher" when: model.IsLauncher === true PropertyChanges { target: frame basePrefix: "" } }, State { name: "hovered" when: task.highlighted && frame.hasElementPrefix("hover") && plasmoid.configuration.taskHoverEffect PropertyChanges { target: frame basePrefix: "hover" } }, State { name: "attention" when: model.IsDemandingAttention === true || (task.smartLauncherItem && task.smartLauncherItem.urgent) PropertyChanges { target: frame basePrefix: "attention" } }, State { name: "minimized" when: model.IsMinimized === true PropertyChanges { target: frame basePrefix: "minimized" } }, State { name: "active" when: model.IsActive === true PropertyChanges { target: frame basePrefix: "focus" } } ] Component.onCompleted: { if (!inPopup && model.IsWindow === true) { var component = Qt.createComponent("GroupExpanderOverlay.qml"); component.createObject(task); } if (!inPopup && model.IsWindow !== true) { taskInitComponent.createObject(task); } updateAudioStreams({delay: false}) } } diff --git a/applets/taskmanager/package/contents/ui/ToolTipDelegate.qml b/applets/taskmanager/package/contents/ui/ToolTipDelegate.qml index 942670e87..fd49706fc 100644 --- a/applets/taskmanager/package/contents/ui/ToolTipDelegate.qml +++ b/applets/taskmanager/package/contents/ui/ToolTipDelegate.qml @@ -1,125 +1,125 @@ /* * Copyright 2013 by Sebastian Kügler * Copyright 2014 by Martin Gräßlin * Copyright 2016 by Kai Uwe Broulik * Copyright 2017 by Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.6 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import QtQml.Models 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.taskmanager 0.1 as TaskManager PlasmaExtras.ScrollArea { id: toolTipDelegate property Item parentTask property var rootIndex property string appName property int pidParent property bool isGroup property var windows readonly property bool isWin: windows !== undefined property variant icon property url launcherUrl property bool isLauncher property bool isMinimizedParent // Needed for generateSubtext() property string displayParent property string genericName property int virtualDesktopParent property bool isOnAllVirtualDesktopsParent property var activitiesParent // property bool smartLauncherCountVisible property int smartLauncherCount - readonly property bool isVerticalPanel: plasmoid.formFactor == PlasmaCore.Types.Vertical + readonly property bool isVerticalPanel: plasmoid.formFactor === PlasmaCore.Types.Vertical Layout.minimumWidth: contentItem.width Layout.maximumWidth: Layout.minimumWidth Layout.minimumHeight: contentItem.height Layout.maximumHeight: Layout.minimumHeight LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true property int textWidth: theme.mSize(theme.defaultFont).width * 20 verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff Component.onCompleted: { flickableItem.interactive = Qt.binding(function() { return isVerticalPanel ? contentItem.height > viewport.height : contentItem.width > viewport.width }); } Loader { id: contentItem - active: toolTipDelegate.rootIndex != undefined + active: toolTipDelegate.rootIndex !== undefined asynchronous: true sourceComponent: isGroup ? groupToolTip : singleTooltip Component { id: singleTooltip ToolTipInstance { submodelIndex: toolTipDelegate.rootIndex } } Component { id: groupToolTip Grid { rows: !isVerticalPanel columns: isVerticalPanel flow: isVerticalPanel ? Grid.TopToBottom : Grid.LeftToRight spacing: units.largeSpacing Repeater { id: groupRepeater model: DelegateModel { model: toolTipDelegate.rootIndex ? tasksModel : null rootIndex: toolTipDelegate.rootIndex delegate: ToolTipInstance { submodelIndex: tasksModel.makeModelIndex(toolTipDelegate.rootIndex.row, index) } } } } } } } diff --git a/applets/taskmanager/package/contents/ui/ToolTipInstance.qml b/applets/taskmanager/package/contents/ui/ToolTipInstance.qml index d776f0195..960225cbd 100644 --- a/applets/taskmanager/package/contents/ui/ToolTipInstance.qml +++ b/applets/taskmanager/package/contents/ui/ToolTipInstance.qml @@ -1,487 +1,487 @@ /* * Copyright 2013 by Sebastian Kügler * Copyright 2014 by Martin Gräßlin * Copyright 2016 by Kai Uwe Broulik * Copyright 2017 by Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.6 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import QtQml.Models 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.taskmanager 0.1 as TaskManager Column { property var submodelIndex property int flatIndex: isGroup && index != undefined ? index : 0 spacing: units.smallSpacing readonly property string mprisSourceName: mpris2Source.sourceNameForLauncherUrl(toolTipDelegate.launcherUrl, isGroup ? AppPid : pidParent) readonly property var playerData: mprisSourceName != "" ? mpris2Source.data[mprisSourceName] : 0 readonly property bool hasPlayer: !!mprisSourceName && !!playerData readonly property bool playing: hasPlayer && playerData.PlaybackStatus === "Playing" readonly property bool canControl: hasPlayer && playerData.CanControl readonly property bool canPlay: hasPlayer && playerData.CanPlay readonly property bool canPause: hasPlayer && playerData.CanPause readonly property bool canGoBack: hasPlayer && playerData.CanGoPrevious readonly property bool canGoNext: hasPlayer && playerData.CanGoNext readonly property bool canRaise: hasPlayer && playerData.CanRaise readonly property var currentMetadata: hasPlayer ? playerData.Metadata : ({}) readonly property string track: { var xesamTitle = currentMetadata["xesam:title"] if (xesamTitle) { return xesamTitle; } // if no track title is given, print out the file name var xesamUrl = currentMetadata["xesam:url"] ? currentMetadata["xesam:url"].toString() : "" if (!xesamUrl) { return ""; } var lastSlashPos = xesamUrl.lastIndexOf('/') if (lastSlashPos < 0) { return ""; } var lastUrlPart = xesamUrl.substring(lastSlashPos + 1) return decodeURIComponent(lastUrlPart); } readonly property string artist: currentMetadata["xesam:artist"] || "" readonly property string albumArt: currentMetadata["mpris:artUrl"] || "" // // launcher icon + text labels + close button RowLayout { id: header Layout.minimumWidth: childrenRect.width Layout.maximumWidth: Layout.minimumWidth Layout.minimumHeight: childrenRect.height Layout.maximumHeight: Layout.minimumHeight anchors.horizontalCenter: parent.horizontalCenter // launcher icon PlasmaCore.IconItem { Layout.preferredWidth: units.iconSizes.medium Layout.preferredHeight: units.iconSizes.medium source: !isWin ? icon : "" animated: false usesPlasmaTheme: false visible: !isWin } // all textlabels Column { PlasmaExtras.Heading { level: 3 width: isWin ? textWidth : undefined height: undefined maximumLineCount: 1 elide: Text.ElideRight text: appName opacity: flatIndex == 0 textFormat: Text.PlainText visible: text !== "" } // window title PlasmaExtras.Heading { level: 5 width: isWin ? textWidth : undefined height: undefined maximumLineCount: 1 elide: Text.ElideRight text: generateTitle() textFormat: Text.PlainText opacity: 0.75 } // subtext PlasmaExtras.Heading { level: 6 width: isWin ? textWidth : undefined height: undefined maximumLineCount: 1 elide: Text.ElideRight text: isWin ? generateSubText() : "" textFormat: Text.PlainText opacity: 0.6 visible: text !== "" } } // Count badge. Badge { Layout.alignment: Qt.AlignRight | Qt.AlignTop height: units.iconSizes.smallMedium visible: flatIndex === 0 && smartLauncherCountVisible number: smartLauncherCount } // close button MouseArea { Layout.alignment: Qt.AlignRight | Qt.AlignTop height: units.iconSizes.smallMedium width: height visible: isWin acceptedButtons: Qt.LeftButton hoverEnabled: true onClicked: { backend.cancelHighlightWindows(); tasksModel.requestClose(submodelIndex); } PlasmaCore.IconItem { anchors.fill: parent active: parent.containsMouse source: "window-close" animated: false } } } // thumbnail container Item { id: thumbnail width: header.width // similar to 0.5625 = 1 / (16:9) as most screens are // round necessary, otherwise shadow mask for players has gap! height: Math.round(0.5 * width) anchors.horizontalCenter: parent.horizontalCenter visible: isWin Item { id: thumbnailSourceItem anchors.fill: parent readonly property bool isMinimized: isGroup ? IsMinimized == true : isMinimizedParent // TODO: this causes XCB error message when being visible the first time - property int winId: isWin && windows[flatIndex] != undefined ? windows[flatIndex] : 0 + property int winId: isWin && windows[flatIndex] !== undefined ? windows[flatIndex] : 0 PlasmaCore.WindowThumbnail { anchors.fill: parent visible: !albumArtImage.visible && !thumbnailSourceItem.isMinimized winId: thumbnailSourceItem.winId ToolTipWindowMouseArea { anchors.fill: parent rootTask: parentTask modelIndex: submodelIndex winId: thumbnailSourceItem.winId } } Image { id: albumArtImage // also Image.Loading to prevent loading thumbnails just because the album art takes a split second to load readonly property bool available: status === Image.Ready || status === Image.Loading anchors.fill: parent sourceSize: Qt.size(parent.width, parent.height) asynchronous: true source: albumArt fillMode: Image.PreserveAspectCrop visible: available ToolTipWindowMouseArea { anchors.fill: parent rootTask: parentTask modelIndex: submodelIndex winId: thumbnailSourceItem.winId } } // when minimized, we don't have a preview, so show the icon PlasmaCore.IconItem { anchors.fill: parent source: thumbnailSourceItem.isMinimized && !albumArtImage.visible ? icon : "" animated: false usesPlasmaTheme: false visible: valid ToolTipWindowMouseArea { anchors.fill: parent rootTask: parentTask modelIndex: submodelIndex winId: thumbnailSourceItem.winId } } } Loader { anchors.fill: thumbnail sourceComponent: hasPlayer ? playerControlsComp : undefined } Component { id: playerControlsComp Item { anchors.fill: parent // TODO: When could this really be the case? A not-launcher-task always has a window!? // if there's no window associated with this task, we might still be able to raise the player // MouseArea { // id: raisePlayerArea // anchors.fill: parent // visible: !isWin || !windows[0] && canRaise // onClicked: mpris2Source.raise(mprisSourceName) // } Item { id: playerControlsFrostedGlass anchors.fill: parent visible: false // OpacityMask would render it Rectangle { width: parent.width height: parent.height - playerControlsRow.height opacity: 0 } Rectangle { anchors.bottom: parent.bottom width: parent.width height: playerControlsRow.height color: theme.backgroundColor opacity: 0.8 } } OpacityMask { id: playerControlsOpacityMask anchors.fill: parent source: playerControlsFrostedGlass maskSource: thumbnailSourceItem } // prevent accidental click-through when a control is disabled MouseArea { anchors.fill: playerControlsRow } RowLayout { id: playerControlsRow anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom } width: parent.width spacing: 0 enabled: canControl ColumnLayout { Layout.fillWidth: true spacing: 0 PlasmaExtras.Heading { Layout.fillWidth: true level: 4 wrapMode: Text.NoWrap elide: Text.ElideRight text: track || "" } PlasmaExtras.Heading { Layout.fillWidth: true level: 5 wrapMode: Text.NoWrap elide: Text.ElideRight text: artist || "" } } MouseArea { height: units.iconSizes.smallMedium width: height enabled: canGoBack acceptedButtons: Qt.LeftButton hoverEnabled: true onClicked: mpris2Source.goPrevious(mprisSourceName) PlasmaCore.IconItem { anchors.fill: parent enabled: canGoBack active: parent.containsMouse source: LayoutMirroring.enabled ? "media-skip-forward" : "media-skip-backward" animated: false } } MouseArea { height: units.iconSizes.medium width: height enabled: playing ? canPause : canPlay acceptedButtons: Qt.LeftButton hoverEnabled: true onClicked: { if (!playing) { mpris2Source.play(mprisSourceName); } else { mpris2Source.pause(mprisSourceName); } } PlasmaCore.IconItem { anchors.fill: parent enabled: playing ? canPause : canPlay active: parent.containsMouse source: playing ? "media-playback-pause" : "media-playback-start" animated: false } } MouseArea { height: units.iconSizes.smallMedium width: height enabled: canGoNext acceptedButtons: Qt.LeftButton hoverEnabled: true onClicked: mpris2Source.goNext(mprisSourceName) PlasmaCore.IconItem { anchors.fill: parent enabled: canGoNext active: parent.containsMouse source: LayoutMirroring.enabled ? "media-skip-backward" : "media-skip-forward" animated: false } } } } } } function generateTitle() { if (!isWin) { return genericName != undefined ? genericName : ""; } var text; if (isGroup) { - if (model.display == undefined) { + if (model.display === undefined) { return ""; } text = model.display.toString(); } else { text = displayParent; } // KWin appends increasing integers in between pointy brackets to otherwise equal window titles. // In this case save <#number> as counter and delete it at the end of text. var counter = text.match(/<\d+>\W*$/); text = text.replace(/\s*<\d+>\W*$/, ""); // Remove appName from the end of text. var appNameRegex = new RegExp(appName + "$", "i"); text = text.replace(appNameRegex, ""); text = text.replace(/\s*(?:-|—)*\s*$/, ""); // Add counter back at the end. - if (counter != null) { - if (text == "") { + if (counter !== null) { + if (text === "") { text = counter; } else { text = text + " " + counter; } } // In case the window title had only redundant information (i.e. appName), text is now empty. // Add a hyphen to indicate that and avoid empty space. - if (text == "") { + if (text === "") { text = "—"; } return text.toString(); } function generateSubText() { - if (activitiesParent == undefined) { + if (activitiesParent === undefined) { return ""; } var subTextEntries = []; var vd = isGroup ? VirtualDesktop : virtualDesktopParent; if (!plasmoid.configuration.showOnlyCurrentDesktop && virtualDesktopInfo.numberOfDesktops > 1 && (isGroup ? IsOnAllVirtualDesktops : isOnAllVirtualDesktopsParent) !== true - && vd != -1 - && vd != undefined - && virtualDesktopInfo.desktopNames[vd - 1] != undefined) { + && vd !== -1 + && vd !== undefined + && virtualDesktopInfo.desktopNames[vd - 1] !== undefined) { subTextEntries.push(i18n("On %1", virtualDesktopInfo.desktopNames[vd - 1])); } var act = isGroup ? Activities : activitiesParent; - if (act == undefined) { + if (act === undefined) { return subTextEntries.join("\n"); } - if (act.length == 0 && activityInfo.numberOfRunningActivities > 1) { + if (act.length === 0 && activityInfo.numberOfRunningActivities > 1) { subTextEntries.push(i18nc("Which virtual desktop a window is currently on", "Available on all activities")); } else if (act.length > 0) { var activityNames = []; for (var i = 0; i < act.length; i++) { var activity = act[i]; var activityName = activityInfo.activityName(act[i]); - if (activityName == "") { + if (activityName === "") { continue; } if (plasmoid.configuration.showOnlyCurrentActivity) { - if (activity != activityInfo.currentActivity) { + if (activity !== activityInfo.currentActivity) { activityNames.push(activityName); } - } else if (activity != activityInfo.currentActivity) { + } else if (activity !== activityInfo.currentActivity) { activityNames.push(activityName); } } if (plasmoid.configuration.showOnlyCurrentActivity) { if (activityNames.length > 0) { subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)", "Also available on %1", activityNames.join(", "))); } } else if (activityNames.length > 0) { subTextEntries.push(i18nc("Which activities a window is currently on", "Available on %1", activityNames.join(", "))); } } return subTextEntries.join("\n"); } } diff --git a/applets/taskmanager/package/contents/ui/main.qml b/applets/taskmanager/package/contents/ui/main.qml index 97a9c0138..b8cd4ac9d 100644 --- a/applets/taskmanager/package/contents/ui/main.qml +++ b/applets/taskmanager/package/contents/ui/main.qml @@ -1,491 +1,491 @@ /*************************************************************************** * Copyright (C) 2012-2016 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.taskmanager 0.1 as TaskManager import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import "code/layout.js" as LayoutManager import "code/tools.js" as TaskTools Item { id: tasks anchors.fill: parent - property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) - property bool iconsOnly: (plasmoid.pluginName == "org.kde.plasma.icontasks") + property bool vertical: (plasmoid.formFactor === PlasmaCore.Types.Vertical) + property bool iconsOnly: (plasmoid.pluginName === "org.kde.plasma.icontasks") property QtObject contextMenuComponent: Qt.createComponent("ContextMenu.qml"); Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.onUserConfiguringChanged: { if (plasmoid.userConfiguring) { groupDialog.visible = false; } } Layout.fillWidth: true Layout.fillHeight:true Layout.minimumWidth: tasks.vertical ? 0 : LayoutManager.preferredMinWidth() Layout.minimumHeight: !tasks.vertical ? 0 : LayoutManager.preferredMinHeight() //BEGIN TODO: this is not precise enough: launchers are smaller than full tasks Layout.preferredWidth: tasks.vertical ? units.gridUnit * 10 : ((LayoutManager.logicalTaskCount() * LayoutManager.preferredMaxWidth()) / LayoutManager.calculateStripes()); Layout.preferredHeight: tasks.vertical ? ((LayoutManager.logicalTaskCount() * LayoutManager.preferredMaxHeight()) / LayoutManager.calculateStripes()) : units.gridUnit * 2; //END TODO property Item dragSource: null signal requestLayout signal windowsHovered(variant winIds, bool hovered) signal presentWindows(variant winIds) onWidthChanged: { taskList.width = LayoutManager.layoutWidth(); if (plasmoid.configuration.forceStripes) { taskList.height = LayoutManager.layoutHeight(); } } onHeightChanged: { if (plasmoid.configuration.forceStripes) { taskList.width = LayoutManager.layoutWidth(); } taskList.height = LayoutManager.layoutHeight(); } onDragSourceChanged: { if (dragSource == null) { tasksModel.syncLaunchers(); } } TaskManager.TasksModel { id: tasksModel readonly property int logicalLauncherCount: { if (plasmoid.configuration.separateLaunchers) { return launcherCount; } var startupsWithLaunchers = 0; for (var i = 0; i < taskRepeater.count; ++i) { var item = taskRepeater.itemAt(i); if (item && item.m.IsStartup === true && item.m.HasLauncher === true) { ++startupsWithLaunchers; } } return launcherCount + startupsWithLaunchers; } virtualDesktop: virtualDesktopInfo.currentDesktop screenGeometry: plasmoid.screenGeometry activity: activityInfo.currentActivity filterByVirtualDesktop: plasmoid.configuration.showOnlyCurrentDesktop filterByScreen: plasmoid.configuration.showOnlyCurrentScreen filterByActivity: plasmoid.configuration.showOnlyCurrentActivity filterNotMinimized: plasmoid.configuration.showOnlyMinimized sortMode: iconsOnly ? TaskManager.TasksModel.SortManual : sortModeEnumValue(plasmoid.configuration.sortingStrategy) launchInPlace: iconsOnly separateLaunchers: { if (!iconsOnly && !plasmoid.configuration.separateLaunchers - && plasmoid.configuration.sortingStrategy == 1) { + && plasmoid.configuration.sortingStrategy === 1) { return false; } return true; } groupMode: iconsOnly ? TaskManager.TasksModel.GroupApplications : groupModeEnumValue(plasmoid.configuration.groupingStrategy) groupInline: !plasmoid.configuration.groupPopups groupingWindowTasksThreshold: (plasmoid.configuration.onlyGroupWhenFull && !iconsOnly ? LayoutManager.optimumCapacity(width, height) + 1 : -1) onLauncherListChanged: { layoutTimer.restart(); plasmoid.configuration.launchers = launcherList; } onGroupingAppIdBlacklistChanged: { plasmoid.configuration.groupingAppIdBlacklist = groupingAppIdBlacklist; } onGroupingLauncherUrlBlacklistChanged: { plasmoid.configuration.groupingLauncherUrlBlacklist = groupingLauncherUrlBlacklist; } function sortModeEnumValue(index) { switch (index) { case 0: return TaskManager.TasksModel.SortDisabled; case 1: return TaskManager.TasksModel.SortManual; case 2: return TaskManager.TasksModel.SortAlpha; case 3: return TaskManager.TasksModel.SortVirtualDesktop; case 4: return TaskManager.TasksModel.SortActivity; default: return TaskManager.TasksModel.SortDisabled; } } function groupModeEnumValue(index) { switch (index) { case 0: return TaskManager.TasksModel.GroupDisabled; case 1: return TaskManager.TasksModel.GroupApplications; } } Component.onCompleted: { launcherList = plasmoid.configuration.launchers; groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; // Only hook up view only after the above churn is done. taskRepeater.model = tasksModel; } } Connections { target: tasksModel onActiveTaskChanged: { if (!plasmoid.configuration.groupPopups) { return; } if (tasksModel.activeTask.parent.valid) { groupDialog.activeTask = tasksModel.activeTask; } } } TaskManager.VirtualDesktopInfo { id: virtualDesktopInfo } TaskManager.ActivityInfo { id: activityInfo } TaskManagerApplet.Backend { id: backend taskManagerItem: tasks toolTipItem: toolTipDelegate groupDialog: groupDialog highlightWindows: plasmoid.configuration.highlightWindows onAddLauncher: { tasks.addLauncher(url); } } PlasmaCore.DataSource { id: mpris2Source engine: "mpris2" connectedSources: sources function sourceNameForLauncherUrl(launcherUrl, pid) { - if (!launcherUrl || launcherUrl == "") { + if (!launcherUrl || launcherUrl === "") { return ""; } // MPRIS spec explicitly mentions that "DesktopEntry" is with .desktop extension trimmed // Moreover, remove URL parameters, like wmClass (part after the question mark) var desktopFileName = launcherUrl.toString().split('/').pop().split('?')[0].replace(".desktop", "") if (desktopFileName.indexOf("applications:") === 0) { desktopFileName = desktopFileName.substr(13) } for (var i = 0, length = connectedSources.length; i < length; ++i) { var source = connectedSources[i]; // we intend to connect directly, otherwise the multiplexer steals the connection away if (source === "@multiplex") { continue; } var sourceData = data[source]; if (!sourceData || sourceData.DesktopEntry !== desktopFileName) { continue; } if (pid === undefined || sourceData.InstancePid === pid) { return source; } var metadata = sourceData.Metadata; if (metadata) { var kdePid = metadata["kde:pid"]; if (kdePid && pid === kdePid) { return source; } } } return "" } function startOperation(source, op) { var service = serviceForSource(source) var operation = service.operationDescription(op) return service.startOperationCall(operation) } function goPrevious(source) { startOperation(source, "Previous"); } function goNext(source) { startOperation(source, "Next"); } function play(source) { startOperation(source, "Play"); } function pause(source) { startOperation(source, "Pause"); } function playPause(source) { startOperation(source, "PlayPause"); } function stop(source) { startOperation(source, "Stop"); } function raise(source) { startOperation(source, "Raise"); } function quit(source) { startOperation(source, "Quit"); } } Loader { id: pulseAudio source: "PulseAudio.qml" active: plasmoid.configuration.indicateAudioStreams } Timer { id: iconGeometryTimer interval: 500 repeat: false onTriggered: { TaskTools.publishIconGeometries(taskList.children); } } Binding { target: plasmoid property: "status" value: (tasksModel.anyTaskDemandsAttention ? PlasmaCore.Types.NeedsAttentionStatus : PlasmaCore.Types.PassiveStatus) } Connections { target: plasmoid onLocationChanged: { // This is on a timer because the panel may not have // settled into position yet when the location prop- // erty updates. iconGeometryTimer.start(); } } Connections { target: plasmoid.configuration onLaunchersChanged: tasksModel.launcherList = plasmoid.configuration.launchers onGroupingAppIdBlacklistChanged: tasksModel.groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; onGroupingLauncherUrlBlacklistChanged: tasksModel.groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; } TaskManagerApplet.DragHelper { id: dragHelper dragIconSize: units.iconSizes.medium } PlasmaCore.FrameSvgItem { id: taskFrame visible: false; imagePath: "widgets/tasks"; prefix: "normal" } PlasmaCore.Svg { id: taskSvg imagePath: "widgets/tasks" } MouseHandler { id: mouseHandler anchors.fill: parent target: taskList onUrlsDropped: { // If all dropped URLs point to application desktop files, we'll add a launcher for each of them. var createLaunchers = urls.every(function (item) { return backend.isApplication(item) }); if (createLaunchers) { urls.forEach(function (item) { addLauncher(item); }); return; } if (!hoveredItem) { return; } // DeclarativeMimeData urls is a QJsonArray but requestOpenUrls expects a proper QList. var urlsList = backend.jsonArrayToUrlList(urls); // Otherwise we'll just start a new instance of the application with the URLs as argument, // as you probably don't expect some of your files to open in the app and others to spawn launchers. tasksModel.requestOpenUrls(hoveredItem.modelIndex(), urlsList); } } ToolTipDelegate { id: toolTipDelegate visible: false } TaskList { id: taskList anchors { left: parent.left top: parent.top } onWidthChanged: LayoutManager.layout(taskRepeater) onHeightChanged: LayoutManager.layout(taskRepeater) flow: { if (tasks.vertical) { return plasmoid.configuration.forceStripes ? Flow.LeftToRight : Flow.TopToBottom } return plasmoid.configuration.forceStripes ? Flow.TopToBottom : Flow.LeftToRight } onAnimatingChanged: { if (!animating) { TaskTools.publishIconGeometries(children); } } function layout() { taskList.width = LayoutManager.layoutWidth(); taskList.height = LayoutManager.layoutHeight(); LayoutManager.layout(taskRepeater); } Timer { id: layoutTimer interval: 0 repeat: false onTriggered: taskList.layout() } Repeater { id: taskRepeater delegate: Task {} onItemAdded: taskList.layout() onItemRemoved: taskList.layout() } } GroupDialog { id: groupDialog } function hasLauncher(url) { return tasksModel.launcherPosition(url) != -1; } function addLauncher(url) { if (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) { tasksModel.requestAddLauncher(url); } } // This is called by plasmashell in response to a Meta+number shortcut. function activateTaskAtIndex(index) { if (typeof index !== "number") { return; } var task = taskRepeater.itemAt(index); if (task) { TaskTools.activateTask(task.modelIndex(), task.m, null, task); } } function resetDragSource() { dragSource = null; } function createContextMenu(rootTask, modelIndex, args) { var initialArgs = args || {} initialArgs.visualParent = rootTask; initialArgs.modelIndex = modelIndex; initialArgs.mpris2Source = mpris2Source; initialArgs.backend = backend; return tasks.contextMenuComponent.createObject(rootTask, initialArgs); } Component.onCompleted: { tasks.requestLayout.connect(layoutTimer.restart); tasks.requestLayout.connect(iconGeometryTimer.restart); tasks.windowsHovered.connect(backend.windowsHovered); tasks.presentWindows.connect(backend.presentWindows); dragHelper.dropped.connect(resetDragSource); } } diff --git a/containments/desktop/package/contents/config/config.qml b/containments/desktop/package/contents/config/config.qml index 6d33e922f..3cc30c2ff 100644 --- a/containments/desktop/package/contents/config/config.qml +++ b/containments/desktop/package/contents/config/config.qml @@ -1,55 +1,55 @@ /*************************************************************************** * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.configuration 2.0 ConfigModel { - property bool isFolder: (plasmoid.pluginName == "org.kde.plasma.folder") + property bool isFolder: (plasmoid.pluginName === "org.kde.plasma.folder") ConfigCategory { name: i18n("Location") icon: "folder" source: "ConfigLocation.qml" visible: isFolder } ConfigCategory { name: i18n("Icons") icon: "preferences-desktop-icons" source: "ConfigIcons.qml" visible: isFolder } ConfigCategory { name: i18n("Filter") icon: "view-filter" source: "ConfigFilter.qml" visible: isFolder } ConfigCategory { name: i18n("Tweaks") icon: "preferences-other" source: "ConfigTweaks.qml" visible: plasmoid.configuration.showTweaks && ("containmentType" in plasmoid) } } diff --git a/containments/desktop/package/contents/ui/AppletAppearance.qml b/containments/desktop/package/contents/ui/AppletAppearance.qml index d09ccc568..cd51b2b6c 100644 --- a/containments/desktop/package/contents/ui/AppletAppearance.qml +++ b/containments/desktop/package/contents/ui/AppletAppearance.qml @@ -1,733 +1,733 @@ /* * Copyright 2011-2013 Sebastian Kügler * Copyright 2011 Marco Martin * Copyright 2014 David Edmundson * Copyright 2015 Eike Hein * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.plasma.plasmoid 2.0 Item { id: appletItem property int handleWidth: iconSize property int minimumHandleHeight: 7 * (root.iconSize + 7) + margins.top + margins.bottom property int handleHeight: (height < minimumHandleHeight) ? minimumHandleHeight : height property string category property bool showAppletHandle: temporaryShowAppletHandle || plasmoid.editMode property bool temporaryShowAppletHandle: false property real controlsOpacity: (plasmoid.immutable || !showAppletHandle) ? 0 : 1 property string backgroundHints: "NoBackground" property bool hasBackground: false property bool handleMerged: (height > minimumHandleHeight && !appletHandle.forceFloating) property bool animationsEnabled: false property bool floating: true // turns off layoutManagment space handling for appletItem property alias innerEndHeight: mouseListener.endHeight property alias innerEndWidth: mouseListener.endWidth property alias innerHeight: mouseListener.height property alias innerWidth: mouseListener.width property int minimumWidth: Math.max(root.layoutManager.cellSize.width, appletContainer.minimumWidth + margins.left + margins.right); property int minimumHeight: Math.max(root.layoutManager.cellSize.height, appletContainer.minimumHeight + margins.top + margins.bottom); property int maximumWidth: appletContainer.maximumWidth + margins.left + margins.right; property int maximumHeight: appletContainer.maximumHeight + margins.top + margins.bottom; property alias applet: appletContainer.applet property Item contents: appletContainer property alias margins: plasmoidBackground.margins property alias imagePath: plasmoidBackground.imagePath property int lastX: 0 property int lastY: 0 visible: false Timer { id: positionTimer repeat: false running: false interval: 100 onTriggered: { releasePosition(); positionItem(); if (showAppletHandle && !handleMerged) appletHandle.positionHandle(); } } onMinimumWidthChanged: { if (width < minimumWidth) { width = minimumWidth; positionTimer.restart(); } } onMinimumHeightChanged: { if (height < minimumHeight) { height = minimumHeight; positionTimer.restart(); } } onMaximumWidthChanged: { if (width > maximumWidth) { width = maximumWidth; positionTimer.restart(); } } onMaximumHeightChanged: { if (height > maximumHeight) { height = maximumHeight; positionTimer.restart(); } } onHeightChanged: { if (height > maximumHeight) innerEndHeight = maximumHeight; else if (height < minimumHeight) innerEndHeight = minimumHeight; else innerEndHeight = height; } onWidthChanged: { if (width > maximumWidth) innerEndWidth = maximumWidth; else if (width < minimumWidth) innerEndWidth = minimumWidth; else innerEndWidth = width; } onXChanged: { if (animationsEnabled) { animationsEnabled = false; mouseListener.x += lastX - x; animationsEnabled = true; } mouseListener.x = mouseListener.endX = (width - innerEndWidth)/2; lastX = x; } onYChanged: { if (animationsEnabled) { animationsEnabled = false; mouseListener.y += lastY - y; animationsEnabled = true; } mouseListener.y = mouseListener.endY = (height - innerEndHeight)/2; lastY = y; } // use this function to position appletItem instead of root.layoutManager.positionItem(appletItem) function positionItem() { if (floating) return; root.layoutManager.positionItem(appletItem); } // use this function to free appletItem position instead of // root.layoutManager.setSpaceAvailable(appletItem.x, appletItem.y, appletItem.width, appletItem.height, true) function releasePosition() { if (!floating) root.layoutManager.setSpaceAvailable(x, y, width, height, true); } function updateBackgroundHints() { - hasBackground = (applet.backgroundHints != "NoBackground"); - if (applet.backgroundHints == 1) { + hasBackground = (applet.backgroundHints !== "NoBackground"); + if (applet.backgroundHints === 1) { appletItem.imagePath = "widgets/background"; backgroundHints = "StandardBackground"; - } else if (applet.backgroundHints == 2) { + } else if (applet.backgroundHints === 2) { appletItem.imagePath = "widgets/translucentbackground" backgroundHints = "TranslucentBackground"; - } else if (applet.backgroundHints == 0) { + } else if (applet.backgroundHints === 0) { appletItem.imagePath = "" backgroundHints = "NoBackground"; } else { backgroundHints = "DefaultBackground"; appletItem.imagePath = "widgets/background"; } //print("Backgroundhints changed: " + appletItem.imagePath); } KQuickControlsAddons.MouseEventListener { id: mouseListener // used as inner applet (which would not be sized over or under size limits ) // centered in appletItem.onXChanged and onYChanged due to allow animations on X and Y property int pressX: -1 property int pressY: -1 // for animations property int endHeight: minimumHeight property int endWidth: minimumWidth property int endX: 0 property int endY: 0 function startDrag(mouse) { dragMouseArea.dragging = true; eventGenerator.sendGrabEventRecursive(appletItem, KQuickControlsAddons.EventGenerator.UngrabMouse); eventGenerator.sendGrabEvent(dragMouseArea, KQuickControlsAddons.EventGenerator.GrabMouse); eventGenerator.sendMouseEvent(dragMouseArea, KQuickControlsAddons.EventGenerator.MouseButtonPress, mouse.x, mouse.y, Qt.LeftButton, Qt.LeftButton, 0); } height: endHeight width: endWidth z: 10 hoverEnabled: true onPressed: { - if (!plasmoid.immutable && mouse.modifiers == Qt.AltModifier) { + if (!plasmoid.immutable && mouse.modifiers === Qt.AltModifier) { if (!dragMouseArea.dragging) { startDrag(mouse) } return; } pressX = mouse.x; pressY = mouse.y; } onPressAndHold: { if (!plasmoid.immutable && plasmoid.configuration.pressToMove) { if (!dragMouseArea.dragging && !root.isDrag(pressX, pressY, mouse.x, mouse.y)) { temporaryShowAppletHandle = true; startDrag(mouse) } } pressX = -1; pressY = -1; } onContainsMouseChanged: { animationsEnabled = true; if (!plasmoid.immutable && (!plasmoid.configuration.pressToMove || !containsMouse)) { hoverTracker.restart(); } } Timer { id: hoverTracker repeat: false interval: root.handleDelay onTriggered: { if (mouseListener.containsMouse || (appletHandle.item && (appletHandle.item.containsMouse || appletHandle.item.pressed))) { if (!plasmoid.configuration.pressToMove) { temporaryShowAppletHandle = true; } } else if (!dragMouseArea.dragging) { temporaryShowAppletHandle = false; } } } Item { anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } width: parent.width+handleWidth; z: mouseListener.z + 4 PlasmaCore.FrameSvgItem { id: plasmoidBackground - visible: backgroundHints != PlasmaCore.Types.NoBackground + visible: backgroundHints !== PlasmaCore.Types.NoBackground imagePath: "widgets/background" anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } width: parent.width - _handleWidth smooth: true property real _handleWidth: (showAppletHandle && handleMerged) ? 0 : handleWidth Behavior on _handleWidth { enabled: animationsEnabled NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } Connections { target: plasmoid onImmutableChanged: { // print(" TB dragMouseArea.visible: " + plasmoid.immutable) dragMouseArea.visible = !plasmoid.immutable; temporaryShowAppletHandle = false; } onAppletRemoved: { // print("Applet removed Applet-" + applet.id) - if (applet.id == appletItem.applet.id) { + if (applet.id === appletItem.applet.id) { // print("Destroying Applet-" + applet.id) root.layoutManager.saveRotation(appletItem); appletItem.releasePosition(); //applet.action("remove").trigger(); //appletItem.destroy() appletItem.destroy(); } } } Connections { target: applet onBackgroundHintsChanged: { // print("plasmoid.backgroundHintsChanged"); updateBackgroundHints(); } } MouseArea { id: dragMouseArea anchors.fill: parent z: appletContainer.z - 2 visible: !plasmoid.immutable property int zoffset: 1000 drag.target: appletItem property bool dragging: false // Set by mouseListener.onPressAndHold -- drag.active only becomes true on movement. function endDrag() { appletItem.z = appletItem.z - zoffset; repositionTimer.running = false; placeHolderPaint.opacity = 0; animationsEnabled = true; appletItem.floating = false; appletItem.positionItem(); root.layoutManager.save(); dragging = false; } onDraggingChanged: { cursorShape = dragging ? Qt.DragMoveCursor : Qt.ArrowCursor; } onPressed: { appletItem.z = appletItem.z + zoffset; animationsEnabled = false; mouse.accepted = true; appletItem.releasePosition(); appletItem.floating = true; placeHolder.syncWithItem(appletItem); placeHolderPaint.opacity = root.haloOpacity; } onPositionChanged: { var pos = mapToItem(root.parent, mouse.x, mouse.y); var newCont = plasmoid.containmentAt(pos.x, pos.y); - if (newCont && newCont != plasmoid) { + if (newCont && newCont !== plasmoid) { var newPos = newCont.mapFromApplet(plasmoid, pos.x, pos.y); newCont.addApplet(appletItem.applet, newPos.x, newPos.y); placeHolderPaint.opacity = 0; } else { placeHolder.syncWithItem(appletItem); } } onCanceled: { endDrag(); appletHandle.positionHandle(); } onReleased: { endDrag(); appletHandle.positionHandle(); } } Item { id: appletContainer anchors { fill: parent leftMargin: plasmoidBackground.margins.left rightMargin: plasmoidBackground.margins.right + handleWidth topMargin: plasmoidBackground.margins.top bottomMargin: plasmoidBackground.margins.bottom } z: mouseListener.z+1 property QtObject applet readonly property int maxInt: 1000000 // dirty hack to convert js number to qml int property var minimumSize: { var size; if (applet && applet.Layout) { var layout = applet.Layout size = { 'width': layout.minimumWidth, 'height': layout.minimumHeight }; } else { size = { 'width': 0, 'height': 0 }; } return size; } property var maximumSize: { var size; if (applet && applet.Layout) { var layout = applet.Layout size = { 'width': layout.maximumWidth, 'height': layout.maximumHeight }; } else { size = { 'width': Number.POSITIVE_INFINITY, 'height': Number.POSITIVE_INFINITY }; } if (size.width > maxInt) size.width = maxInt; if (size.height > maxInt) size.height = maxInt; return size; } onMinimumSizeChanged: { minimumHeight = minimumSize.height if (minimumHeight > maximumSize.height) maximumHeight = minimumHeight else if (maximumHeight !== maximumSize.height) maximumHeight = maximumSize.height minimumWidth = minimumSize.width if (minimumWidth > maximumSize.width) maximumWidth = minimumWidth else if (maximumWidth !== maximumSize.width) maximumWidth = maximumSize.width } onMaximumSizeChanged: { maximumHeight = maximumSize.height if (maximumHeight < minimumSize.height) minimumHeight = maximumHeight else if (minimumHeight !== minimumSize.height) minimumHeight = minimumSize.height maximumWidth = maximumSize.width if (maximumWidth < minimumSize.width) minimumWidth = maximumWidth else if (minimumWidth !== minimumSize.width) minimumWidth = minimumSize.width } property int minimumWidth: 0 property int minimumHeight: 0 property int maximumWidth: maxInt property int maximumHeight: maxInt function appletDestroyed() { // print("Applet DESTROYED."); appletItem.releasePosition(); applet.action("remove").trigger(); appletItem.destroy() } onAppletChanged: { if (!applet) { return; } applet.parent = appletContainer; applet.anchors.fill = appletContainer; updateBackgroundHints(); } Connections { target: appletHandle.item onRemoveApplet: { killAnim.running = true; } } Behavior on opacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } SequentialAnimation { id: killAnim PlasmaExtras.DisappearAnimation { targetItem: appletItem } ScriptAction { script: { appletItem.scale = 1; appletContainer.appletDestroyed(); } } } Loader { id: busyLoader anchors.centerIn: parent z: appletContainer.z + 1 active: applet && applet.busy source: "BusyOverlay.qml" asynchronous: true } Component.onCompleted: PlasmaExtras.AppearAnimation { targetItem: appletItem } } Loader { id: appletHandle z: appletContainer.z + 1 property bool forceFloating : false anchors { verticalCenter: parent.verticalCenter right: plasmoidBackground.right } Connections { target: appletItem onShowAppletHandleChanged: { if (appletItem.showAppletHandle) { appletItem.z += dragMouseArea.zoffset; appletHandle.positionHandle(); if (appletHandle.source == "") { appletHandle.source = "AppletHandle.qml"; } } else { appletItem.z -= dragMouseArea.zoffset; } } onHandleMergedChanged: { if (appletItem.handleMerged) { appletHandle.anchors.verticalCenterOffset = 0; } else { appletHandle.positionHandle(); } } } Connections { target: appletHandle.item onMoveFinished: { appletHandle.positionHandle(); } } function positionHandle() { // Don't show handle outside of desktop var available = plasmoid.availableScreenRect; var x = Math.min(Math.max(0, appletItem.x + mouseListener.endX), available.width - appletItem.width + mouseListener.endX); var y = Math.min(Math.max(0, appletItem.y + mouseListener.endY), available.height - appletItem.height + mouseListener.endY); var verticalCenter = (y + mouseListener.endHeight / 2); var topOutside = (verticalCenter - minimumHandleHeight / 2); var bottomOutside = verticalCenter + minimumHandleHeight / 2 - available.height; if (bottomOutside > 0) { anchors.verticalCenterOffset = -bottomOutside; } else if (topOutside < 0) { anchors.verticalCenterOffset = -topOutside; } else { anchors.verticalCenterOffset = 0; } var rightOutside = x + mouseListener.endWidth + handleWidth - available.width; appletHandle.anchors.rightMargin = appletItem.margins.right + Math.max(0, rightOutside); appletHandle.forceFloating = rightOutside > 0; } } } Behavior on x { enabled: animationsEnabled NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on y { enabled: animationsEnabled NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on width { enabled: animationsEnabled NumberAnimation { id: widthAnimation duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on height { enabled: animationsEnabled NumberAnimation { id: heightAnimation duration: units.longDuration easing.type: Easing.InOutQuad } } } Behavior on controlsOpacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } //sides ResizeHandle { anchors { left: parent.left top: parent.top right: parent.right leftMargin: units.gridUnit rightMargin: units.gridUnit } cursorShape: Qt.SizeVerCursor moveX: false moveY: true resizeWidth: false resizeHeight: true } ResizeHandle { anchors { left: parent.left bottom: parent.bottom right: parent.right leftMargin: units.gridUnit rightMargin: units.gridUnit } cursorShape: Qt.SizeVerCursor moveX: false moveY: false resizeWidth: false resizeHeight: true } ResizeHandle { anchors { left: parent.left top: parent.top bottom: parent.bottom topMargin: units.gridUnit bottomMargin: units.gridUnit } enabled: !parent.LayoutMirroring.enabled || !showAppletHandle cursorShape: Qt.SizeHorCursor moveX: true moveY: false resizeWidth: true resizeHeight: false } ResizeHandle { anchors { right: parent.right top: parent.top bottom: parent.bottom topMargin: units.gridUnit bottomMargin: units.gridUnit } enabled: parent.LayoutMirroring.enabled || !showAppletHandle cursorShape: Qt.SizeHorCursor moveX: false moveY: false resizeWidth: true resizeHeight: false } //corners ResizeHandle { anchors { left: parent.left top: parent.top } enabled: !parent.LayoutMirroring.enabled || !showAppletHandle cursorShape: Qt.SizeFDiagCursor moveX: true moveY: true resizeWidth: true resizeHeight: true } ResizeHandle { anchors { right: parent.right top: parent.top } enabled: parent.LayoutMirroring.enabled || !showAppletHandle cursorShape: Qt.SizeBDiagCursor moveX: false moveY: true resizeWidth: true resizeHeight: true } ResizeHandle { anchors { left: parent.left bottom: parent.bottom } enabled: !parent.LayoutMirroring.enabled || !showAppletHandle cursorShape: Qt.SizeBDiagCursor moveX: true moveY: false resizeWidth: true resizeHeight: true } ResizeHandle { anchors { right: parent.right bottom: parent.bottom } enabled: parent.LayoutMirroring.enabled || !showAppletHandle cursorShape: Qt.SizeFDiagCursor moveX: false moveY: false resizeWidth: true resizeHeight: true } Component.onCompleted: { floating = false; layoutTimer.running = true layoutTimer.restart() visible = false } } diff --git a/containments/desktop/package/contents/ui/AppletHandle.qml b/containments/desktop/package/contents/ui/AppletHandle.qml index 5493ae8bf..245378ed7 100644 --- a/containments/desktop/package/contents/ui/AppletHandle.qml +++ b/containments/desktop/package/contents/ui/AppletHandle.qml @@ -1,310 +1,310 @@ /* * Copyright 2011-2013 Sebastian Kügler * Copyright 2011 Marco Martin * Copyright 2014 David Edmundson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.plasma.components 2.0 as PlasmaComponents KQuickControlsAddons.MouseEventListener { id: appletHandle opacity: appletItem.controlsOpacity visible: opacity > 0 width: appletItem.handleWidth height: Math.max(appletItem.innerHeight - appletItem.margins.top - appletItem.margins.bottom, buttonColumn.implicitHeight) hoverEnabled: true onContainsMouseChanged: { if (!containsMouse && !pressed) { hoverTracker.restart() } } onReleased: { if (!containsMouse) { hoverTracker.restart() } } //z: dragMouseArea.z + 1 property int buttonMargin: 6 property int minimumHeight: 6 * (root.iconSize + buttonMargin) signal removeApplet signal moveFinished transform: Translate { x: (handleMerged ? 0 : controlsOpacity * appletHandle.width) * (appletHandle.LayoutMirroring.enabled ? -1 : 1) } PlasmaCore.FrameSvgItem { id: noBackgroundHandle visible: controlsOpacity > 0 z: plasmoidBackground.z - 10 anchors { top: parent.top bottom: parent.bottom left: parent.left right: parent.right // verticalCenter: parent.verticalCenter leftMargin: -margins.left topMargin: -margins.top rightMargin: -margins.right bottomMargin: -margins.bottom } smooth: true imagePath: (backgroundHints == "NoBackground" || !handleMerged) ? "widgets/background" : "" } PlasmaComponents.Label { id: toolTipDelegate width: contentWidth height: undefined property Item toolTip text: (toolTip != null) ? toolTip.mainText : "" } ColumnLayout { id: buttonColumn width: appletItem.handleWidth anchors { top: parent.top bottom: parent.bottom right: parent.right } spacing: buttonMargin*2 ActionButton { svg: configIconsSvg elementId: "size-diagonal-tr2bl" iconSize: root.iconSize mainText: i18n("Resize") active: !resizeHandle.pressed ResizeHandle { id: resizeHandle anchors { fill: parent margins: -buttonMargin } onPressed: parent.hideToolTip(); cursorShape: parent.LayoutMirroring.enabled ? Qt.SizeFDiagCursor : Qt.SizeBDiagCursor moveX: parent.LayoutMirroring.enabled moveY: true resizeWidth: true resizeHeight: true visible: true } } ActionButton { id: rotateButton svg: configIconsSvg elementId: "rotate" mainText: i18n("Rotate") iconSize: root.iconSize action: (applet) ? applet.action("rotate") : null active: !rotateHandle.pressed Component.onCompleted: { if (action && typeof(action) != "undefined") { action.enabled = true } } MouseArea { id: rotateHandle anchors { fill: parent margins: -buttonMargin } property int startRotation property real startCenterRelativeAngle; function pointAngle(pos) { var r = Math.sqrt(pos.x * pos.x + pos.y * pos.y); var cosine = pos.x / r; if (pos.y >= 0) { return Math.acos(cosine) * (180/Math.PI); } else { return -Math.acos(cosine) * (180/Math.PI); } } function centerRelativePos(x, y) { var mousePos = appletItem.parent.mapFromItem(rotateButton, x, y); var centerPos = appletItem.parent.mapFromItem(appletItem, appletItem.width/2, appletItem.height/2); mousePos.x -= centerPos.x; mousePos.y -= centerPos.y; return mousePos; } onPressed: { parent.hideToolTip(); mouse.accepted = true animationsEnabled = false; startRotation = appletItem.rotation; startCenterRelativeAngle = pointAngle(centerRelativePos(mouse.x, mouse.y)); } onPositionChanged: { var rot = startRotation%360; var snap = 4; var newRotation = Math.round(pointAngle(centerRelativePos(mouse.x, mouse.y)) - startCenterRelativeAngle + startRotation); if (newRotation < 0) { newRotation = newRotation + 360; } else if (newRotation >= 360) { newRotation = newRotation % 360; } snapIt(0); snapIt(90); snapIt(180); snapIt(270); function snapIt(snapTo) { if (newRotation > (snapTo - snap) && newRotation < (snapTo + snap)) { newRotation = snapTo; } } //print("Start: " + startRotation + " new: " + newRotation); appletItem.rotation = newRotation; } onReleased: { // save rotation // print("saving..."); root.layoutManager.saveItem(appletItem); } } } ActionButton { svg: configIconsSvg elementId: "configure" iconSize: root.iconSize visible: (action && typeof(action) != "undefined") ? action.enabled : false action: (applet) ? applet.action("configure") : null Component.onCompleted: { if (action && typeof(action) != "undefined") { action.enabled = true } } } ActionButton { svg: configIconsSvg elementId: "maximize" iconSize: root.iconSize visible: (action && typeof(action) != "undefined") ? action.enabled : false action: (applet) ? applet.action("run associated application") : null Component.onCompleted: { if (action && typeof(action) != "undefined") { action.enabled = true } } } //spacer MouseArea { id: dragMouseArea implicitHeight: root.iconSize * 2 Layout.fillWidth: true Layout.fillHeight: true property int zoffset: 1000 drag.target: appletItem cursorShape: Qt.DragMoveCursor onPressed: { appletItem.z = appletItem.z + zoffset; animationsEnabled = false mouse.accepted = true appletItem.releasePosition(); appletItem.floating = true; placeHolder.syncWithItem(appletItem) placeHolderPaint.opacity = root.haloOpacity; } onPositionChanged: { var pos = mapToItem(root.parent, mouse.x, mouse.y); var newCont = plasmoid.containmentAt(pos.x, pos.y); - if (newCont && newCont != plasmoid) { + if (newCont && newCont !== plasmoid) { var newPos = newCont.mapFromApplet(plasmoid, pos.x, pos.y); newCont.addApplet(appletItem.applet, newPos.x, newPos.y); placeHolderPaint.opacity = 0; } else { placeHolder.syncWithItem(appletItem); } } onReleased: { appletItem.z = appletItem.z - zoffset; repositionTimer.running = false placeHolderPaint.opacity = 0 animationsEnabled = true appletItem.floating = false; appletItem.positionItem(); root.layoutManager.save() appletHandle.moveFinished() } } Item { Layout.minimumWidth: closeButton.width Layout.minimumHeight: closeButton.height ActionButton { id: closeButton svg: configIconsSvg elementId: "delete" mainText: i18n("Remove") iconSize: root.iconSize visible: { if (!applet) { return false; } var a = applet.action("remove"); return (a && typeof(a) != "undefined") ? a.enabled : false; } // we don't set action, since we want to catch the button click, // animate, and then trigger the "remove" action // Triggering the action is handled in the appletItem, we just // emit a signal here to avoid the applet-gets-removed-before-we- // can-animate it race condition. onClicked: { appletHandle.removeApplet(); } Component.onCompleted: { var a = applet.action("remove"); if (a && typeof(a) != "undefined") { a.enabled = true } } } } } } diff --git a/containments/desktop/package/contents/ui/BackButtonItem.qml b/containments/desktop/package/contents/ui/BackButtonItem.qml index 3a5e3bac7..2f2f7719f 100644 --- a/containments/desktop/package/contents/ui/BackButtonItem.qml +++ b/containments/desktop/package/contents/ui/BackButtonItem.qml @@ -1,138 +1,138 @@ /*************************************************************************** * Copyright (C) 2011-2013 Sebastian Kügler * * Copyright (C) 2011 Marco Martin * * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents PlasmaCore.FrameSvgItem { id: upButton width: gridView.cellWidth height: visible ? gridView.cellHeight : 0 - visible: history.length != 0 + visible: history.length !== 0 property bool ignoreClick: false property bool containsDrag: false imagePath: "widgets/viewitem" function handleDragMove() { containsDrag = true; hoverActivateTimer.restart(); } function endDragMove() { containsDrag = false; hoverActivateTimer.stop(); } MouseArea { id: mouseArea anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.BackButton hoverEnabled: true onContainsMouseChanged: { gridView.hoveredItem = null; } onPressed: { if (mouse.buttons & Qt.BackButton) { - if (root.isPopup && dir.resolvedUrl != dir.resolve(plasmoid.configuration.url)) { + if (root.isPopup && dir.resolvedUrl !== dir.resolve(plasmoid.configuration.url)) { doBack(); ignoreClick = true; } } } onClicked: { if (ignoreClick) { ignoreClick = false; return; } doBack(); } } PlasmaCore.IconItem { id: icon anchors { left: parent.left leftMargin: units.smallSpacing verticalCenter: parent.verticalCenter } width: gridView.iconSize height: gridView.iconSize source: "arrow-left" } PlasmaComponents.Label { id: label anchors { left: icon.right leftMargin: units.smallSpacing * 2 verticalCenter: parent.verticalCenter } width: parent.width - icon.width - (units.smallSpacing * 4); height: undefined // Unset PlasmaComponents.Label's default. textFormat: Text.PlainText maximumLineCount: root.isPopup ? 1 : plasmoid.configuration.textLines wrapMode: Text.Wrap elide: Text.ElideRight text: i18n("Back") } Timer { id: hoverActivateTimer interval: root.hoverActivateDelay onTriggered: doBack() } states: [ State { name: "hover" when: mouseArea.containsMouse || containsDrag PropertyChanges { target: upButton prefix: "hover" } } ] } diff --git a/containments/desktop/package/contents/ui/CompactRepresentation.qml b/containments/desktop/package/contents/ui/CompactRepresentation.qml index 91111082e..d58bbe02d 100644 --- a/containments/desktop/package/contents/ui/CompactRepresentation.qml +++ b/containments/desktop/package/contents/ui/CompactRepresentation.qml @@ -1,83 +1,83 @@ /*************************************************************************** * Copyright (C) 2013-2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.draganddrop 2.0 as DragDrop DragDrop.DropArea { - readonly property bool inPanel: (plasmoid.location == PlasmaCore.Types.TopEdge - || plasmoid.location == PlasmaCore.Types.RightEdge - || plasmoid.location == PlasmaCore.Types.BottomEdge - || plasmoid.location == PlasmaCore.Types.LeftEdge) + readonly property bool inPanel: (plasmoid.location === PlasmaCore.Types.TopEdge + || plasmoid.location === PlasmaCore.Types.RightEdge + || plasmoid.location === PlasmaCore.Types.BottomEdge + || plasmoid.location === PlasmaCore.Types.LeftEdge) Layout.minimumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? height : units.iconSizes.small Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Vertical ? width : (units.iconSizes.small + 2 * theme.mSize(theme.defaultFont).height) - Layout.maximumWidth: inPanel && plasmoid.formFactor != PlasmaCore.Types.Vertical ? units.iconSizeHints.panel : -1 - Layout.maximumHeight: inPanel && plasmoid.formFactor != PlasmaCore.Types.Vertical ? units.iconSizeHints.panel : -1 + Layout.maximumWidth: inPanel && plasmoid.formFactor !== PlasmaCore.Types.Vertical ? units.iconSizeHints.panel : -1 + Layout.maximumHeight: inPanel && plasmoid.formFactor !== PlasmaCore.Types.Vertical ? units.iconSizeHints.panel : -1 property Item folderView: null onContainsDragChanged: { if (containsDrag) { hoverActivateTimer.restart(); } else { hoverActivateTimer.stop(); } } onDrop: folderView.model.dropCwd(event) preventStealing: true function toggle() { plasmoid.expanded = !plasmoid.expanded; } PlasmaCore.IconItem { id: icon anchors.fill: parent active: mouseArea.containsMouse source: plasmoid.configuration.useCustomIcon ? plasmoid.configuration.icon : folderView.model.iconName } MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true onClicked: toggle() } Timer { id: hoverActivateTimer interval: root.hoverActivateDelay onTriggered: toggle() } } diff --git a/containments/desktop/package/contents/ui/ConfigIcons.qml b/containments/desktop/package/contents/ui/ConfigIcons.qml index b8d05aae8..99dda679a 100644 --- a/containments/desktop/package/contents/ui/ConfigIcons.qml +++ b/containments/desktop/package/contents/ui/ConfigIcons.qml @@ -1,318 +1,318 @@ /*************************************************************************** * Copyright (C) 2014 by Eike Hein * * Copyright (C) 2015 by 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) 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 . * ***************************************************************************/ import QtQuick 2.4 import QtQuick.Controls 1.0 import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.kconfig 1.0 // for KAuthorized import org.kde.kirigami 2.4 as Kirigami import org.kde.private.desktopcontainment.desktop 0.1 as Desktop import org.kde.private.desktopcontainment.folder 0.1 as Folder Item { id: configIcons width: childrenRect.width height: childrenRect.height - property bool isPopup: (plasmoid.location != PlasmaCore.Types.Floating) + property bool isPopup: (plasmoid.location !== PlasmaCore.Types.Floating) property string cfg_icon: plasmoid.configuration.icon property alias cfg_useCustomIcon: useCustomIcon.checked property alias cfg_arrangement: arrangement.currentIndex property alias cfg_alignment: alignment.currentIndex property bool cfg_locked property alias cfg_sortMode: sortMode.mode property alias cfg_sortDesc: sortDesc.checked property alias cfg_sortDirsFirst: sortDirsFirst.checked property alias cfg_toolTips: toolTips.checked property alias cfg_selectionMarkers: selectionMarkers.checked property alias cfg_popups: popups.checked property alias cfg_previews: previews.checked property alias cfg_previewPlugins: previewPluginsDialog.previewPlugins property alias cfg_viewMode: viewMode.currentIndex property alias cfg_iconSize: iconSize.value property alias cfg_textLines: textLines.value readonly property bool lockedByKiosk: !KAuthorized.authorize("editable_desktop_icons") IconDialog { id: iconDialog onIconNameChanged: cfg_icon = iconName || "folder" } Kirigami.FormLayout { anchors.horizontalCenter: parent.horizontalCenter // Panel button RowLayout { spacing: units.smallSpacing visible: isPopup Kirigami.FormData.label: i18n("Panel button:") CheckBox { id: useCustomIcon visible: isPopup checked: cfg_useCustomIcon text: i18n("Use a custom icon") } Button { id: iconButton Layout.minimumWidth: units.iconSizes.large + units.smallSpacing * 2 Layout.maximumWidth: Layout.minimumWidth Layout.minimumHeight: Layout.minimumWidth Layout.maximumHeight: Layout.minimumWidth checkable: true enabled: useCustomIcon.checked onClicked: { checked = Qt.binding(function() { return iconMenu.status === PlasmaComponents.DialogStatus.Open; }) iconMenu.open(0, height); } PlasmaCore.IconItem { anchors.centerIn: parent width: units.iconSizes.large height: width source: cfg_icon } } PlasmaComponents.ContextMenu { id: iconMenu visualParent: iconButton PlasmaComponents.MenuItem { text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...") icon: "document-open-folder" onClicked: iconDialog.open() } PlasmaComponents.MenuItem { text: i18nc("@item:inmenu Reset icon to default", "Clear Icon") icon: "edit-clear" onClicked: cfg_icon = "folder" } } } Item { visible: isPopup Kirigami.FormData.isSection: true } // Arrangement section ComboBox { id: arrangement Layout.fillWidth: true Kirigami.FormData.label: i18n("Arrangement:") model: [i18n("Rows"), i18n("Columns")] } ComboBox { id: alignment Layout.fillWidth: true model: [i18n("Align Left"), i18n("Align Right")] } CheckBox { id: locked visible: ("containmentType" in plasmoid) checked: cfg_locked || lockedByKiosk enabled: !lockedByKiosk onCheckedChanged: { if (!lockedByKiosk) { cfg_locked = checked; } } text: i18n("Lock in place") } Item { Kirigami.FormData.isSection: true } // Sorting section ComboBox { id: sortMode Layout.fillWidth: true Kirigami.FormData.label: i18n("Sorting:") property int mode // FIXME TODO HACK: This maps the combo box list model to the KDirModel::ModelColumns // enum, which should be done in C++. property variant indexToMode: [-1, 0, 1, 6, 2] property variant modeToIndex: {'-1' : '0', '0' : '1', '1' : '2', '6' : '3', '2' : '4'} model: [i18n("Manual"), i18n("Name"), i18n("Size"), i18n("Type"), i18n("Date")] Component.onCompleted: currentIndex = modeToIndex[mode] onActivated: mode = indexToMode[index] } CheckBox { id: sortDesc enabled: (sortMode.currentIndex != 0) text: i18n("Descending") } CheckBox { id: sortDirsFirst enabled: (sortMode.currentIndex != 0) text: i18n("Folders first") } Item { Kirigami.FormData.isSection: true } // View Mode section (only if we're a pop-up) ComboBox { id: viewMode visible: isPopup Layout.fillWidth: true Kirigami.FormData.label: i18nc("whether to use icon or list view", "View mode:") model: [i18n("List"), i18n("Icons")] } // Size section Slider { id: iconSize visible: !isPopup || viewMode.currentIndex === 1 Kirigami.FormData.label: i18n("Size:") minimumValue: 0 maximumValue: 5 stepSize: 1 tickmarksEnabled: true } RowLayout { Layout.fillWidth: true Label { Layout.alignment: Qt.AlignLeft visible: !isPopup || viewMode.currentIndex === 1 text: i18n("Small") } Item { Layout.fillWidth: true } Label { Layout.alignment: Qt.AlignRight visible: !isPopup || viewMode.currentIndex === 1 text: i18n("Large") } } SpinBox { id: textLines visible: !isPopup || viewMode.currentIndex === 1 Kirigami.FormData.label: i18n("Text lines:") minimumValue: 1 maximumValue: 10 stepSize: 1 } Item { Kirigami.FormData.isSection: true } // Features section CheckBox { id: toolTips Kirigami.FormData.label: i18n("Features:") text: i18n("Tooltips") } CheckBox { id: selectionMarkers visible: Qt.styleHints.singleClickActivation text: i18n("Selection markers") } CheckBox { id: popups visible: !isPopup text: i18n("Folder preview popups") } CheckBox { id: previews text: i18n("Preview thumbnails") } Button { id: previewSettings text: i18n("More Preview Options...") onClicked: { previewPluginsDialog.visible = true; } } } FolderItemPreviewPluginsDialog { id: previewPluginsDialog } } diff --git a/containments/desktop/package/contents/ui/ConfigLocation.qml b/containments/desktop/package/contents/ui/ConfigLocation.qml index 0eb1636af..84668a44b 100644 --- a/containments/desktop/package/contents/ui/ConfigLocation.qml +++ b/containments/desktop/package/contents/ui/ConfigLocation.qml @@ -1,227 +1,227 @@ /*************************************************************************** * Copyright (C) 2014 by 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Controls 1.0 import QtQuick.Layouts 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.kirigami 2.4 as Kirigami import org.kde.private.desktopcontainment.folder 0.1 as Folder Item { id: configLocation width: childrenRect.width height: childrenRect.height property string cfg_url property alias cfg_labelMode: labelMode.currentIndex property alias cfg_labelText: labelText.text property bool titleVisible: !("containmentType" in plasmoid) onCfg_urlChanged: applyConfig() function applyConfig(force) { if (!force && locationGroup.current != null) { return; } if (cfg_url == "desktop:/") { locationDesktop.checked = true; locationCustomValue.text = ""; } else if (cfg_url == "activities:/current/") { locationCurrentActivity.checked = true; locationCustomValue.text = ""; } else { var placeForUrl = placesModel.indexForUrl(cfg_url); - if (placeForUrl != -1) { + if (placeForUrl !== -1) { locationPlace.checked = true; locationPlaceValue.currentIndex = placeForUrl; locationCustomValue.text = ""; } else { locationCustom.checked = true; locationCustomValue.text = cfg_url; } } locationPlaceValue.enabled = locationPlace.checked; } Folder.PlacesModel { id: placesModel showDesktopEntry: false onPlacesChanged: applyConfig(true) } ExclusiveGroup { id: locationGroup onCurrentChanged: { if (current == locationDesktop) { cfg_url = "desktop:/"; } else if (current == locationCurrentActivity) { cfg_url = "activities:/current/"; } } } Kirigami.FormLayout { anchors.horizontalCenter: parent.horizontalCenter RadioButton { id: locationDesktop Kirigami.FormData.label: i18n("Show:") text: i18n("Desktop folder") exclusiveGroup: locationGroup } RadioButton { id: locationCurrentActivity visible: placesModel.activityLinkingEnabled text: i18n("Files linked to the current activity") exclusiveGroup: locationGroup } RadioButton { id: locationPlace text: i18n("Places panel item:") exclusiveGroup: locationGroup onCheckedChanged: { locationPlaceValue.enabled = checked; } } RowLayout { Layout.fillWidth: true Item { width: units.largeSpacing } ComboBox { id: locationPlaceValue Layout.fillWidth: true model: placesModel textRole: "display" enabled: true onEnabledChanged: { if (enabled && currentIndex != -1) { cfg_url = placesModel.urlForIndex(currentIndex); } } onActivated: { cfg_url = placesModel.urlForIndex(index); } } } RadioButton { id: locationCustom exclusiveGroup: locationGroup text: i18n("Custom location:") } RowLayout { Layout.fillWidth: true Item { width: units.largeSpacing } TextField { id: locationCustomValue enabled: locationCustom.checked Layout.fillWidth: true placeholderText: i18n("Type a path or a URL here") onEnabledChanged: { if (enabled && text != "") { cfg_url = text; } } onTextChanged: { if (enabled) { cfg_url = text; } } } Button { iconName: "document-open" enabled: locationCustom.checked onClicked: { directoryPicker.open(); } } Folder.DirectoryPicker { id: directoryPicker onUrlChanged: { locationCustomValue.text = url; } } } Item { visible: titleVisible Kirigami.FormData.isSection: true } ComboBox { id: labelMode visible: titleVisible Layout.fillWidth: true Kirigami.FormData.label: i18n("Title:") model: [i18n("None"), i18n("Default"), i18n("Full path"), i18n("Custom title")] } RowLayout { Layout.fillWidth: true visible: titleVisible Item { width: units.largeSpacing } TextField { id: labelText Layout.fillWidth: true enabled: (labelMode.currentIndex == 3) placeholderText: i18n("Enter custom title here") } } } } diff --git a/containments/desktop/package/contents/ui/FolderItemDelegate.qml b/containments/desktop/package/contents/ui/FolderItemDelegate.qml index 18b7c0e0c..a2c0f1683 100644 --- a/containments/desktop/package/contents/ui/FolderItemDelegate.qml +++ b/containments/desktop/package/contents/ui/FolderItemDelegate.qml @@ -1,501 +1,501 @@ /*************************************************************************** * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.8 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 Item { id: main property int index: model.index property string name: model.blank ? "" : model.display property bool blank: model.blank property bool isDir: loader.item ? loader.item.isDir : false property QtObject popupDialog: loader.item ? loader.item.popupDialog : null property Item iconArea: loader.item ? loader.item.iconArea : null property Item label: loader.item ? loader.item.label : null property Item labelArea: loader.item ? loader.item.labelArea : null property Item actionsOverlay: loader.item ? loader.item.actionsOverlay : null property Item hoverArea: loader.item ? loader.item.hoverArea : null property Item frame: loader.item ? loader.item.frame : null property Item toolTip: loader.item ? loader.item.toolTip : null Accessible.name: name Accessible.role: Accessible.Canvas function openPopup() { if (isDir) { loader.item.openPopup(); } } function closePopup() { if (popupDialog) { popupDialog.requestDestroy(); loader.item.popupDialog = null; } } Loader { id: loader // On the desktop we pad our cellSize to avoid a gap at the right/bottom of the screen. // The padding per item is quite small and causes the delegate to be positioned on fractional pixels // leading to blurry rendering. The Loader is offset to account for this. x: -main.x % 1 y: -main.y % 1 width: parent.width height: parent.height visible: status === Loader.Ready active: !model.blank sourceComponent: delegateImplementation asynchronous: true } Component { id: delegateImplementation Item { id: impl anchors.fill: parent property bool blank: model.blank property bool selected: model.blank ? false : model.selected property bool isDir: model.blank ? false : model.isDir - property bool hovered: (main.GridView.view.hoveredItem == main) + property bool hovered: (main.GridView.view.hoveredItem === main) property QtObject popupDialog: null property Item iconArea: icon property Item label: label property Item labelArea: frameLoader.textShadow || label property Item actionsOverlay: actions property Item hoverArea: toolTip property Item frame: frameLoader property Item toolTip: toolTip property Item selectionButton: null property Item popupButton: null onSelectedChanged: { if (selected && !blank) { frameLoader.grabToImage(function(result) { dir.addItemDragImage(positioner.map(index), main.x + frameLoader.x, main.y + frameLoader.y, frameLoader.width, frameLoader.height, result.image); }); } } onHoveredChanged: { if (hovered) { if (plasmoid.configuration.selectionMarkers && Qt.styleHints.singleClickActivation) { selectionButton = selectionButtonComponent.createObject(actions); } if (model.isDir) { if (!main.GridView.view.isRootView || root.containsDrag) { hoverActivateTimer.restart(); } if (plasmoid.configuration.popups && !root.useListViewMode) { popupButton = popupButtonComponent.createObject(actions); } } } else if (!hovered) { if (popupDialog != null) { closePopup(); } if (selectionButton) { selectionButton.destroy(); selectionButton = null; } if (popupButton) { popupButton.destroy(); popupButton = null; } } } function openPopup() { if (folderViewDialogComponent.status == Component.Ready) { impl.popupDialog = folderViewDialogComponent.createObject(impl); impl.popupDialog.visualParent = icon; impl.popupDialog.url = model.linkDestinationUrl; impl.popupDialog.visible = true; } } PlasmaCore.ToolTipArea { id: toolTip active: (plasmoid.configuration.toolTips && popupDialog == null && !model.blank) interactive: false - location: root.useListViewMode ? (plasmoid.location == PlasmaCore.Types.LeftEdge ? PlasmaCore.Types.LeftEdge : PlasmaCore.Types.RightEdge) : plasmoid.location + location: root.useListViewMode ? (plasmoid.location === PlasmaCore.Types.LeftEdge ? PlasmaCore.Types.LeftEdge : PlasmaCore.Types.RightEdge) : plasmoid.location onContainsMouseChanged: { if (containsMouse && !model.blank) { toolTip.icon = model.decoration; toolTip.mainText = model.display; - if (model.size != undefined) { + if (model.size !== undefined) { toolTip.subText = model.type + "\n" + model.size; } else { toolTip.subText = model.type; } main.GridView.view.hoveredItem = main; } } states: [ State { // icon view when: !root.useListViewMode AnchorChanges { target: toolTip anchors.horizontalCenter: parent.horizontalCenter } PropertyChanges { target: toolTip y: frameLoader.y + icon.y width: Math.max(icon.paintedWidth, label.paintedWidth) height: (label.y + label.paintedHeight) - y } }, State { // list view when: root.useListViewMode AnchorChanges { target: toolTip anchors.horizontalCenter: undefined } PropertyChanges { target: toolTip x: frameLoader.x y: frameLoader.y width: frameLoader.width height: frameLoader.height } } ] } Loader { id: frameLoader x: root.useListViewMode ? 0 : units.smallSpacing y: root.useListViewMode ? 0 : units.smallSpacing property Item textShadow: null property string prefix: "" sourceComponent: frameComponent active: state !== "" asynchronous: true width: { if (root.useListViewMode) { if (main.GridView.view.overflowing) { return parent.width - units.smallSpacing; } else { return parent.width; } } return parent.width - (units.smallSpacing * 2); } height: { if (root.useListViewMode) { return parent.height; } // Note: frameLoader.y = units.smallSpacing (acts as top margin) return (units.smallSpacing // icon.anchors.topMargin (acts as top padding) + icon.height + units.smallSpacing // label.anchors.topMargin (acts as spacing between icon and label) + (label.lineCount * theme.mSize(theme.defaultFont).height) + units.smallSpacing); // leftover (acts as bottom padding) } PlasmaCore.IconItem { id: icon z: 2 states: [ State { // icon view when: !root.useListViewMode AnchorChanges { target: icon anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter } }, State { // list view when: root.useListViewMode AnchorChanges { target: icon anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter } } ] anchors { topMargin: units.smallSpacing leftMargin: units.smallSpacing } width: root.useListViewMode ? main.GridView.view.iconSize : (parent.width - 2 * units.smallSpacing) height: main.GridView.view.iconSize opacity: { if (root.useListViewMode && selectionButton) { return 0.3; } if (model.isHidden) { return 0.6; } return 1.0; } animated: false usesPlasmaTheme: false smooth: true source: model.decoration overlays: model.overlays } PlasmaComponents.Label { id: label z: 2 // So we can position a textShadowComponent below if needed. states: [ State { // icon view when: !root.useListViewMode AnchorChanges { target: label anchors.top: icon.bottom anchors.horizontalCenter: parent.horizontalCenter } PropertyChanges { target: label anchors.topMargin: units.smallSpacing width: Math.round(Math.min(label.implicitWidth + units.smallSpacing, parent.width - units.smallSpacing)) maximumLineCount: plasmoid.configuration.textLines horizontalAlignment: Text.AlignHCenter } }, State { // list view when: root.useListViewMode AnchorChanges { target: label anchors.left: icon.right anchors.verticalCenter: parent.verticalCenter } PropertyChanges { target: label anchors.leftMargin: units.smallSpacing * 2 anchors.rightMargin: units.smallSpacing * 2 width: parent.width - icon.width - (units.smallSpacing * 4) maximumLineCount: 1 horizontalAlignment: Text.AlignLeft } } ] height: undefined // Unset PlasmaComponents.Label's default. textFormat: Text.PlainText wrapMode: (maximumLineCount == 1) ? Text.NoWrap : Text.Wrap elide: Text.ElideRight color: (frameLoader.textShadow && frameLoader.textShadow.visible ? "#fff" : PlasmaCore.ColorScope.textColor) opacity: model.isHidden ? 0.6 : 1 text: model.blank ? "" : model.display font.italic: model.isLink visible: { if (editor && editor.targetItem === main) { return false; } // DropShadow renders the Label already. if (frameLoader.textShadow && frameLoader.textShadow.visible) { return false; } return true; } } Component { id: frameComponent PlasmaCore.FrameSvgItem { prefix: frameLoader.prefix imagePath: "widgets/viewitem" } } Component { id: selectionButtonComponent FolderItemActionButton { element: model.selected ? "remove" : "add" onClicked: dir.toggleSelected(positioner.map(index)) } } Component { id: popupButtonComponent FolderItemActionButton { visible: main.GridView.view.isRootView && (popupDialog == null) element: "open" onClicked: { dir.setSelected(positioner.map(index)) openPopup(); } } } Component { id: textShadowComponent DropShadow { anchors.fill: label z: 1 horizontalOffset: 1 verticalOffset: 1 radius: 4 samples: 9 spread: 0.35 color: "black" opacity: model.isHidden ? 0.6 : 1 source: label visible: !editor || editor.targetItem != main } } states: [ State { name: "selected" when: model.selected PropertyChanges { target: frameLoader prefix: "selected" } }, State { name: "hover" when: hovered && !model.selected && plasmoid.configuration.iconHoverEffect PropertyChanges { target: frameLoader prefix: "hover" } }, State { name: "selected+hover" when: hovered && model.selected && plasmoid.configuration.iconHoverEffect PropertyChanges { target: frameLoader prefix: "selected+hover" } } ] } Column { id: actions visible: { if (main.GridView.view.isRootView && root.containsDrag) { return false; } if (!main.GridView.view.isRootView && main.GridView.view.dialog.containsDrag) { return false; } if (popupDialog) { return false; } return true; } anchors { left: frameLoader.left top: frameLoader.top leftMargin: root.useListViewMode ? (icon.x + (icon.width / 2)) - (width / 2) : 0 topMargin: root.useListViewMode ? (icon.y + (icon.height / 2)) - (height / 2) : 0 } width: implicitWidth height: implicitHeight } Component.onCompleted: { if (root.isContainment && main.GridView.view.isRootView && root.GraphicsInfo.api === GraphicsInfo.OpenGL) { frameLoader.textShadow = textShadowComponent.createObject(frameLoader); } } } } } diff --git a/containments/desktop/package/contents/ui/FolderView.qml b/containments/desktop/package/contents/ui/FolderView.qml index a15e9639a..2b54bcb74 100644 --- a/containments/desktop/package/contents/ui/FolderView.qml +++ b/containments/desktop/package/contents/ui/FolderView.qml @@ -1,1396 +1,1396 @@ /*************************************************************************** * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.4 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 import org.kde.private.desktopcontainment.folder 0.1 as Folder import "code/FolderTools.js" as FolderTools FocusScope { id: main signal pressed property QtObject model: dir property Item rubberBand: null property alias isRootView: gridView.isRootView property alias currentIndex: gridView.currentIndex property alias url: dir.url property alias status: dir.status property alias positions: positioner.positions property alias errorString: dir.errorString property alias dragging: dir.dragging property alias locked: dir.locked property alias sortMode: dir.sortMode property alias filterMode: dir.filterMode property alias filterPattern: dir.filterPattern property alias filterMimeTypes: dir.filterMimeTypes property alias flow: gridView.flow property alias layoutDirection: gridView.layoutDirection property alias cellWidth: gridView.cellWidth property alias cellHeight: gridView.cellHeight property alias overflowing: gridView.overflowing property alias scrollLeft: gridView.scrollLeft property alias scrollRight: gridView.scrollRight property alias scrollUp: gridView.scrollUp property alias scrollDown: gridView.scrollDown property alias hoveredItem: gridView.hoveredItem property var history: [] property var lastPosition: null property bool goingBack: false property Item backButton: null property var dialog: null property Item editor: null function positionViewAtBeginning() { gridView.positionViewAtBeginning(); } function rename() { if (gridView.currentIndex != -1) { var renameAction = folderView.model.action("rename"); if (renameAction && !renameAction.enabled) { return; } if (!editor) { editor = editorComponent.createObject(listener); } editor.targetItem = gridView.currentItem; } } function cancelRename() { if (editor) { editor.targetItem = null; } } function linkHere(sourceUrl) { dir.linkHere(sourceUrl); } function handleDragMove(x, y) { var child = childAt(x, y); - if (child != null && child == backButton) { + if (child !== null && child === backButton) { hoveredItem = null; backButton.handleDragMove(); } else { if (backButton && backButton.containsDrag) { backButton.endDragMove(); } var pos = mapToItem(gridView.contentItem, x, y); var item = gridView.itemAt(pos.x, pos.y); if (item && item.isDir) { hoveredItem = item; } else { hoveredItem = null; } } } function endDragMove() { if (backButton && backButton.active) { backButton.endDragMove(); } else if (hoveredItem && !hoveredItem.popupDialog) { hoveredItem = null; } } function dropItemAt(pos) { var item = gridView.itemAt(pos.x, pos.y); if (item) { if (item.blank) { return -1; } var hOffset = Math.abs(Math.min(gridView.contentX, gridView.originX)); var hPos = mapToItem(item.hoverArea, pos.x + hOffset, pos.y); if ((hPos.x < 0 || hPos.y < 0 || hPos.x > item.hoverArea.width || hPos.y > item.hoverArea.height)) { return -1; } else { return positioner.map(item.index); } } return -1; } function drop(target, event, pos) { var dropPos = mapToItem(gridView.contentItem, pos.x, pos.y); var dropIndex = gridView.indexAt(dropPos.x, dropPos.y); var dragPos = mapToItem(gridView.contentItem, listener.dragX, listener.dragY); var dragIndex = gridView.indexAt(dragPos.x, dragPos.y); - if (listener.dragX == -1 || dragIndex != dropIndex) { + if (listener.dragX == -1 || dragIndex !== dropIndex) { dir.drop(target, event, dropItemAt(dropPos)); } } Connections { target: dir onPopupMenuAboutToShow: { if (!plasmoid.immutable) { plasmoid.processMimeData(mimeData, x, y, dropJob); } } } Connections { target: plasmoid onExpandedChanged: { if (plasmoid.expanded && dir.status === Folder.FolderModel.Ready && !gridView.model) { gridView.model = positioner; } } } // Lower the toolBox when an item is hovered, so it doesn't interfere with // its interaction (e.g. the selection button in the top left, cf. Bug 337060) Binding { target: toolBox property: "z" // 999 is the default "z" for desktop ToolBoxRoot value: main.hoveredItem ? -100 : 999 when: toolBox } Binding { target: plasmoid property: "busy" value: !gridView.model && dir.status === Folder.FolderModel.Listing } function makeBackButton() { return Qt.createQmlObject("BackButtonItem {}", main); } function doCd(row) { history.push({"url": url, "index": gridView.currentIndex, "yPosition": gridView.visibleArea.yPosition}); updateHistory(); dir.cd(row); gridView.currentIndex = -1; } function doBack() { goingBack = true; gridView.currentIndex = -1; lastPosition = history.pop(); url = lastPosition.url; updateHistory(); } // QML doesn't detect change in the array(history) property, so update it explicitly. function updateHistory() { history = history; } Connections { target: root onIsPopupChanged: { if (backButton == null && root.useListViewMode) { backButton = makeBackButton(); } else if (backButton != null) { backButton.destroy(); } } } MouseEventListener { id: listener anchors { topMargin: backButton != null ? backButton.height : undefined fill: parent } property alias hoveredItem: gridView.hoveredItem property Item pressedItem: null property int pressX: -1 property int pressY: -1 property int dragX: -1 property int dragY: -1 property variant cPress: null property bool doubleClickInProgress: false acceptedButtons: { if (hoveredItem == null && main.isRootView) { return root.isPopup ? (Qt.LeftButton | Qt.MiddleButton | Qt.BackButton) : Qt.LeftButton; } return root.isPopup ? (Qt.LeftButton | Qt.MiddleButton | Qt.RightButton | Qt.BackButton) : (Qt.LeftButton | Qt.RightButton); } hoverEnabled: true onPressXChanged: { cPress = mapToItem(gridView.contentItem, pressX, pressY); } onPressYChanged: { cPress = mapToItem(gridView.contentItem, pressX, pressY); } onPressed: { // Ignore press events outside the viewport (i.e. on scrollbars). if (!scrollArea.viewport.contains(Qt.point(mouse.x,mouse.y))) { return; } scrollArea.focus = true; if (mouse.buttons & Qt.BackButton) { - if (root.isPopup && dir.resolvedUrl != dir.resolve(plasmoid.configuration.url)) { + if (root.isPopup && dir.resolvedUrl !== dir.resolve(plasmoid.configuration.url)) { doBack(); mouse.accepted = true; } return; } - if (editor && childAt(mouse.x, mouse.y) != editor) { + if (editor && childAt(mouse.x, mouse.y) !== editor) { editor.commit(); } pressX = mouse.x; pressY = mouse.y; if (!hoveredItem || hoveredItem.blank) { if (!gridView.ctrlPressed) { gridView.currentIndex = -1; dir.clearSelection(); } if (mouse.buttons & Qt.RightButton) { clearPressState(); dir.openContextMenu(null, mouse.modifiers); mouse.accepted = true; } } else { pressedItem = hoveredItem; var pos = mapToItem(hoveredItem.actionsOverlay, mouse.x, mouse.y); if (!(pos.x <= hoveredItem.actionsOverlay.width && pos.y <= hoveredItem.actionsOverlay.height)) { if (gridView.shiftPressed && gridView.currentIndex != -1) { positioner.setRangeSelected(gridView.anchorIndex, hoveredItem.index); } else { // FIXME TODO: Clicking one item with others selected should deselect the others, // which doesn't happen right now because initiating a drag after the press should // still drag all of them: The deselect needs to happen on release instead so we // can distinguish. if (!gridView.ctrlPressed && !dir.isSelected(positioner.map(hoveredItem.index))) { dir.clearSelection(); } if (gridView.ctrlPressed) { dir.toggleSelected(positioner.map(hoveredItem.index)); } else { dir.setSelected(positioner.map(hoveredItem.index)); } } gridView.currentIndex = hoveredItem.index; if (mouse.buttons & Qt.RightButton) { if (pressedItem.toolTip && pressedItem.toolTip.active) { pressedItem.toolTip.hideToolTip(); } clearPressState(); dir.openContextMenu(null, mouse.modifiers); mouse.accepted = true; } } } main.pressed(); } onCanceled: pressCanceled() onReleased: pressCanceled() onClicked: { clearPressState(); if (mouse.button === Qt.RightButton || (editor && childAt(mouse.x, mouse.y) === editor)) { return; } if (!hoveredItem || hoveredItem.blank || gridView.currentIndex == -1 || gridView.ctrlPressed || gridView.shiftPressed) { // Bug 357367: Replay mouse event, so containment actions assigned to left mouse button work. eventGenerator.sendMouseEvent(plasmoid, EventGenerator.MouseButtonPress, mouse.x, mouse.y, mouse.button, mouse.buttons, mouse.modifiers); return; } var pos = mapToItem(hoveredItem, mouse.x, mouse.y); // Moving from an item to its preview popup dialog doesn't unset hoveredItem // even though the cursor has left it, so we need to check whether the click // actually occurred inside the item we expect it in before going ahead. If it // didn't, clean up (e.g. dismissing the dialog as a side-effect of unsetting // hoveredItem) and abort. if (pos.x < 0 || pos.x > hoveredItem.width || pos.y < 0 || pos.y > hoveredItem.height) { hoveredItem = null; dir.clearSelection(); return; // If the hoveredItem is clicked while having a preview popup dialog open, // only dismiss the dialog and abort. } else if (hoveredItem.popupDialog) { hoveredItem.closePopup(); return; } pos = mapToItem(hoveredItem.actionsOverlay, mouse.x, mouse.y); if (!(pos.x <= hoveredItem.actionsOverlay.width && pos.y <= hoveredItem.actionsOverlay.height)) { if (Qt.styleHints.singleClickActivation || doubleClickInProgress) { - var func = root.useListViewMode && (mouse.button == Qt.LeftButton) && hoveredItem.isDir ? doCd : dir.run; + var func = root.useListViewMode && (mouse.button === Qt.LeftButton) && hoveredItem.isDir ? doCd : dir.run; func(positioner.map(gridView.currentIndex)); hoveredItem = null; } else { doubleClickInProgress = true; doubleClickTimer.interval = Qt.styleHints.mouseDoubleClickInterval; doubleClickTimer.start(); } } } onPositionChanged: { gridView.ctrlPressed = (mouse.modifiers & Qt.ControlModifier); gridView.shiftPressed = (mouse.modifiers & Qt.ShiftModifier); var cPos = mapToItem(gridView.contentItem, mouse.x, mouse.y); var item = gridView.itemAt(cPos.x, cPos.y); var leftEdge = Math.min(gridView.contentX, gridView.originX); if (!item || item.blank) { if (gridView.hoveredItem && !root.containsDrag && (!dialog || !dialog.containsDrag) && !gridView.hoveredItem.popupDialog) { gridView.hoveredItem = null; } } else { var fPos = mapToItem(item.frame, mouse.x, mouse.y); if (fPos.x < 0 || fPos.y < 0 || fPos.x > item.frame.width || fPos.y > item.frame.height) { gridView.hoveredItem = null; } } // Trigger autoscroll. if (pressX != -1) { gridView.scrollLeft = (mouse.x <= 0 && gridView.contentX > leftEdge); gridView.scrollRight = (mouse.x >= gridView.width && gridView.contentX < gridView.contentItem.width - gridView.width); gridView.scrollUp = (mouse.y <= 0 && gridView.contentY > 0); gridView.scrollDown = (mouse.y >= gridView.height && gridView.contentY < gridView.contentItem.height - gridView.height); } // Update rubberband geometry. if (main.rubberBand) { var rB = main.rubberBand; if (cPos.x < cPress.x) { rB.x = Math.max(leftEdge, cPos.x); rB.width = Math.abs(rB.x - cPress.x); } else { rB.x = cPress.x; var ceil = Math.max(gridView.width, gridView.contentItem.width) + leftEdge; rB.width = Math.min(ceil - rB.x, Math.abs(rB.x - cPos.x)); } if (cPos.y < cPress.y) { rB.y = Math.max(0, cPos.y); rB.height = Math.abs(rB.y - cPress.y); } else { rB.y = cPress.y; var ceil = Math.max(gridView.height, gridView.contentItem.height); rB.height = Math.min(ceil - rB.y, Math.abs(rB.y - cPos.y)); } // Ensure rubberband is at least 1px in size or else it will become // invisible and not match any items. rB.width = Math.max(1, rB.width); rB.height = Math.max(1, rB.height); gridView.rectangleSelect(rB.x, rB.y, rB.width, rB.height); return; } // Drag initiation. if (pressX != -1 && root.isDrag(pressX, pressY, mouse.x, mouse.y)) { if (pressedItem != null && dir.isSelected(positioner.map(pressedItem.index))) { pressedItem.toolTip.hideToolTip(); dragX = mouse.x; dragY = mouse.y; gridView.verticalDropHitscanOffset = pressedItem.iconArea.y + (pressedItem.iconArea.height / 2) dir.dragSelected(mouse.x, mouse.y); dragX = -1; dragY = -1; clearPressState(); } else { // Disable rubberband in popup list view mode. if (root.useListViewMode) { return; } dir.pinSelection(); main.rubberBand = Qt.createQmlObject("import QtQuick 2.0; import org.kde.private.desktopcontainment.folder 0.1 as Folder;" + "Folder.RubberBand { x: " + cPress.x + "; y: " + cPress.y + "; width: 0; height: 0; z: 99999; }", gridView.contentItem); gridView.interactive = false; } } } onContainsMouseChanged: { if (!containsMouse && !main.rubberBand) { clearPressState(); if (gridView.hoveredItem && !gridView.hoveredItem.popupDialog) { gridView.hoveredItem = null; } } } onHoveredItemChanged: { doubleClickInProgress = false; if (!hoveredItem) { hoverActivateTimer.stop(); } } function pressCanceled() { if (main.rubberBand) { main.rubberBand.visible = false; main.rubberBand.enabled = false; main.rubberBand.destroy(); main.rubberBand = null; gridView.interactive = true; gridView.cachedRectangleSelection = null; dir.unpinSelection(); } clearPressState(); gridView.cancelAutoscroll(); } function clearPressState() { pressedItem = null; pressX = -1; pressY = -1; } Timer { id: doubleClickTimer onTriggered: { listener.doubleClickInProgress = false; } } Timer { id: hoverActivateTimer interval: root.hoverActivateDelay onTriggered: { if (!hoveredItem) { return; } if (root.useListViewMode) { doCd(index); } else { hoveredItem.openPopup(); } } } PlasmaExtras.ScrollArea { id: scrollArea anchors.fill: parent focus: true property bool ready: false readonly property int viewportWidth: scrollArea.ready && viewport ? Math.ceil(viewport.width) : 0 readonly property int viewportHeight: scrollArea.ready && viewport ? Math.ceil(viewport.height) : 0 Component.onCompleted: { scrollArea.ready = true; } GridView { id: gridView property bool isRootView: false property int iconSize: makeIconSize() property int verticalDropHitscanOffset: 0 property Item hoveredItem: null property int anchorIndex: 0 property bool ctrlPressed: false property bool shiftPressed: false property bool overflowing: (visibleArea.heightRatio < 1.0 || visibleArea.widthRatio < 1.0) property bool scrollLeft: false property bool scrollRight: false property bool scrollUp: false property bool scrollDown: false property variant cachedRectangleSelection: null currentIndex: -1 keyNavigationWraps: false boundsBehavior: Flickable.StopAtBounds function calcExtraSpacing(cellSize, containerSize) { var availableColumns = Math.floor(containerSize / cellSize); var extraSpacing = 0; if (availableColumns > 0) { var allColumnSize = availableColumns * cellSize; var extraSpace = Math.max(containerSize - allColumnSize, 0); extraSpacing = extraSpace / availableColumns; } return extraSpacing; } cellWidth: { if (root.useListViewMode) { return gridView.width; } else { var iconWidth = iconSize + (2 * units.largeSpacing) + (2 * units.smallSpacing); if (root.isContainment && isRootView && scrollArea.viewportWidth > 0) { var minIconWidth = Math.max(iconWidth, units.iconSizes.small * 8); var extraWidth = calcExtraSpacing(minIconWidth, scrollArea.viewportWidth); return minIconWidth + extraWidth; } else { return iconWidth; } } } cellHeight: { if (root.useListViewMode) { return Math.ceil((Math.max(theme.mSize(theme.defaultFont).height, iconSize) + Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom, listItemSvg.margins.top + listItemSvg.margins.bottom)) / 2) * 2; } else { var iconHeight = iconSize + (theme.mSize(theme.defaultFont).height * plasmoid.configuration.textLines) + (4 * units.smallSpacing); if (root.isContainment && isRootView && scrollArea.viewportHeight > 0) { var extraHeight = calcExtraSpacing(iconHeight, scrollArea.viewportHeight); return iconHeight + extraHeight; } else { return iconHeight; } } } delegate: FolderItemDelegate { width: gridView.cellWidth height: gridView.cellHeight } onContentXChanged: { if (hoveredItem) { hoverActivateTimer.stop(); } cancelRename(); dir.setDragHotSpotScrollOffset(contentX, contentY); if (contentX == 0) { scrollLeft = false; } if (contentX == contentItem.width - width) { scrollRight = false; } // Update rubberband geometry. if (main.rubberBand) { var rB = main.rubberBand; if (scrollLeft) { rB.x = Math.min(gridView.contentX, gridView.originX); rB.width = listener.cPress.x; } if (scrollRight) { var lastCol = gridView.contentX + gridView.width; rB.width = lastCol - rB.x; } gridView.rectangleSelect(rB.x, rB.y, rB.width, rB.height); } } onContentYChanged: { if (hoveredItem) { hoverActivateTimer.stop(); } cancelRename(); dir.setDragHotSpotScrollOffset(contentX, contentY); if (contentY == 0) { scrollUp = false; } if (contentY == contentItem.height - height) { scrollDown = false; } // Update rubberband geometry. if (main.rubberBand) { var rB = main.rubberBand; if (scrollUp) { rB.y = 0; rB.height = listener.cPress.y; } if (scrollDown) { var lastRow = gridView.contentY + gridView.height; rB.height = lastRow - rB.y; } gridView.rectangleSelect(rB.x, rB.y, rB.width, rB.height); } } onScrollLeftChanged: { if (scrollLeft && gridView.visibleArea.widthRatio < 1.0) { smoothX.enabled = true; contentX = (gridView.flow == GridView.FlowLeftToRight) ? gridView.contentX : gridView.originX; } else { contentX = contentX; smoothX.enabled = false; } } onScrollRightChanged: { if (scrollRight && gridView.visibleArea.widthRatio < 1.0) { smoothX.enabled = true; contentX = ((gridView.flow == GridView.FlowLeftToRight) ? gridView.contentX : gridView.originX) + (contentItem.width - width); } else { contentX = contentX; smoothX.enabled = false; } } onScrollUpChanged: { if (scrollUp && gridView.visibleArea.heightRatio < 1.0) { smoothY.enabled = true; contentY = 0; } else { contentY = contentY; smoothY.enabled = false; } } onScrollDownChanged: { if (scrollDown && gridView.visibleArea.heightRatio < 1.0) { smoothY.enabled = true; contentY = contentItem.height - height; } else { contentY = contentY; smoothY.enabled = false; } } onFlowChanged: { // FIXME TODO: Preserve positions. if (positioner.enabled) { positioner.reset(); } } onLayoutDirectionChanged: { // FIXME TODO: Preserve positions. if (positioner.enabled) { positioner.reset(); } } onCurrentIndexChanged: { positionViewAtIndex(currentIndex, GridView.Contain); } onCachedRectangleSelectionChanged: { if (cachedRectangleSelection == null) { return; } if (cachedRectangleSelection.length) { // Set current index to start of selection. // cachedRectangleSelection is pre-sorted. currentIndex = cachedRectangleSelection[0]; } dir.updateSelection(cachedRectangleSelection.map(positioner.map), gridView.ctrlPressed); } function makeIconSize() { if (root.useListViewMode) { return units.iconSizes.small; } return FolderTools.iconSizeFromTheme(plasmoid.configuration.iconSize); } function updateSelection(modifier) { if (modifier & Qt.ShiftModifier) { positioner.setRangeSelected(anchorIndex, currentIndex); } else { dir.clearSelection(); dir.setSelected(positioner.map(currentIndex)); } } function cancelAutoscroll() { scrollLeft = false; scrollRight = false; scrollUp = false; scrollDown = false; } function rectangleSelect(x, y, width, height) { var rows = (gridView.flow == GridView.FlowLeftToRight); var axis = rows ? gridView.width : gridView.height; var step = rows ? cellWidth : cellHeight; var perStripe = Math.floor(axis / step); var stripes = Math.ceil(gridView.count / perStripe); var cWidth = gridView.cellWidth - (2 * units.smallSpacing); var cHeight = gridView.cellHeight - (2 * units.smallSpacing); var midWidth = gridView.cellWidth / 2; var midHeight = gridView.cellHeight / 2; var indices = []; for (var s = 0; s < stripes; s++) { for (var i = 0; i < perStripe; i++) { var index = (s * perStripe) + i; if (index >= gridView.count) { break; } if (positioner.isBlank(index)) { continue; } var itemX = ((rows ? i : s) * gridView.cellWidth); var itemY = ((rows ? s : i) * gridView.cellHeight); if (gridView.effectiveLayoutDirection == Qt.RightToLeft) { itemX -= (rows ? gridView.contentX : gridView.originX); itemX += cWidth; itemX = (rows ? gridView.width : gridView.contentItem.width) - itemX; } // Check if the rubberband intersects this cell first to avoid doing more // expensive work. if (main.rubberBand.intersects(Qt.rect(itemX + units.smallSpacing, itemY + units.smallSpacing, cWidth, cHeight))) { var item = gridView.contentItem.childAt(itemX + midWidth, itemY + midHeight); // If this is a visible item, check for intersection with the actual // icon or label rects for better feel. if (item && item.iconArea) { var iconRect = Qt.rect(itemX + item.iconArea.x, itemY + item.iconArea.y, item.iconArea.width, item.iconArea.height); if (main.rubberBand.intersects(iconRect)) { indices.push(index); continue; } var labelRect = Qt.rect(itemX + item.labelArea.x, itemY + item.labelArea.y, item.labelArea.width, item.labelArea.height); if (main.rubberBand.intersects(labelRect)) { indices.push(index); continue; } } else { // Otherwise be content with the cell intersection. indices.push(index); } } } } gridView.cachedRectangleSelection = indices; } function runOrCdSelected() { if (currentIndex != -1 && dir.hasSelection()) { if (root.useListViewMode && currentItem.isDir) { doCd(positioner.map(currentIndex)); } else { dir.runSelected(); } } } Behavior on contentX { id: smoothX; enabled: false; SmoothedAnimation { velocity: 700 } } Behavior on contentY { id: smoothY; enabled: false; SmoothedAnimation { velocity: 700 } } Keys.onReturnPressed: { if (event.modifiers === Qt.AltModifier) { dir.openPropertiesDialog(); } else { runOrCdSelected(); } } Keys.onEnterPressed: Keys.returnPressed(event) Keys.onMenuPressed: { if (currentIndex != -1 && dir.hasSelection() && currentItem) { dir.setSelected(positioner.map(currentIndex)); dir.openContextMenu(currentItem.frame, event.modifiers); } else { // Otherwise let the containment handle it. event.accepted = false; } } Keys.onEscapePressed: { if (!editor || !editor.targetItem) { dir.clearSelection(); event.accepted = false; } } Folder.ShortCut { Component.onCompleted: { installAsEventFilterFor(gridView); } onDeleteFile: { dir.deleteSelected(); } onRenameFile: { rename(); } } Keys.onPressed: { event.accepted = true; if (event.matches(StandardKey.Delete)) { if (dir.hasSelection()) { dir.action("trash").trigger(); } - } else if (event.key == Qt.Key_Control) { + } else if (event.key === Qt.Key_Control) { ctrlPressed = true; - } else if (event.key == Qt.Key_Shift) { + } else if (event.key === Qt.Key_Shift) { shiftPressed = true; if (currentIndex != -1) { anchorIndex = currentIndex; } - } else if (event.key == Qt.Key_Home) { + } else if (event.key === Qt.Key_Home) { currentIndex = 0; updateSelection(event.modifiers); - } else if (event.key == Qt.Key_End) { + } else if (event.key === Qt.Key_End) { currentIndex = count - 1; updateSelection(event.modifiers); } else if (event.matches(StandardKey.Copy)) { dir.copy(); } else if (event.matches(StandardKey.Paste)) { dir.paste(); } else if (event.matches(StandardKey.Cut)) { dir.cut(); } else if (event.matches(StandardKey.Undo)) { dir.undo(); } else if (event.matches(StandardKey.Refresh)) { dir.refresh(); } else if (event.matches(StandardKey.SelectAll)) { positioner.setRangeSelected(0, count - 1); } else { event.accepted = false; } } Keys.onReleased: { - if (event.key == Qt.Key_Control) { + if (event.key === Qt.Key_Control) { ctrlPressed = false; - } else if (event.key == Qt.Key_Shift) { + } else if (event.key === Qt.Key_Shift) { shiftPressed = false; anchorIndex = 0; } } Keys.onLeftPressed: { if (root.isPopup && root.useListViewMode) { - if (dir.resolvedUrl != dir.resolve(plasmoid.configuration.url)) { + if (dir.resolvedUrl !== dir.resolve(plasmoid.configuration.url)) { doBack(); } } else if (positioner.enabled) { var newIndex = positioner.nearestItem(currentIndex, FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.LeftArrow)); - if (newIndex != -1) { + if (newIndex !== -1) { currentIndex = newIndex; updateSelection(event.modifiers); } } else { var oldIndex = currentIndex; moveCurrentIndexLeft(); - if (oldIndex == currentIndex) { + if (oldIndex === currentIndex) { return; } updateSelection(event.modifiers); } } Keys.onRightPressed: { if (root.isPopup && root.useListViewMode) { if (currentIndex != -1 && dir.hasSelection() && currentItem.isDir) { doCd(positioner.map(currentIndex)); } } else if (positioner.enabled) { var newIndex = positioner.nearestItem(currentIndex, FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.RightArrow)); - if (newIndex != -1) { + if (newIndex !== -1) { currentIndex = newIndex; updateSelection(event.modifiers); } } else { var oldIndex = currentIndex; moveCurrentIndexRight(); - if (oldIndex == currentIndex) { + if (oldIndex === currentIndex) { return; } updateSelection(event.modifiers); } } Keys.onUpPressed: { if (positioner.enabled) { var newIndex = positioner.nearestItem(currentIndex, FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.UpArrow)); - if (newIndex != -1) { + if (newIndex !== -1) { currentIndex = newIndex; updateSelection(event.modifiers); } } else { var oldIndex = currentIndex; moveCurrentIndexUp(); - if (oldIndex == currentIndex) { + if (oldIndex === currentIndex) { return; } updateSelection(event.modifiers); } } Keys.onDownPressed: { if (positioner.enabled) { var newIndex = positioner.nearestItem(currentIndex, FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.DownArrow)); - if (newIndex != -1) { + if (newIndex !== -1) { currentIndex = newIndex; updateSelection(event.modifiers); } } else { var oldIndex = currentIndex; moveCurrentIndexDown(); - if (oldIndex == currentIndex) { + if (oldIndex === currentIndex) { return; } updateSelection(event.modifiers); } } Keys.onBackPressed: { - if (root.isPopup && dir.resolvedUrl != dir.resolve(plasmoid.configuration.url)) { + if (root.isPopup && dir.resolvedUrl !== dir.resolve(plasmoid.configuration.url)) { doBack(); } } Connections { target: units onIconSizesChanged: { gridView.iconSize = gridView.makeIconSize(); } } Connections { target: plasmoid.configuration onIconSizeChanged: { gridView.iconSize = gridView.makeIconSize(); } } Connections { target: plasmoid.configuration onUrlChanged: { history = []; updateHistory(); } } } } Folder.WheelInterceptor { anchors.fill: parent enabled: root.isContainment && !gridView.overflowing destination: plasmoid } Folder.FolderModel { id: dir usedByContainment: root.isContainment && main.isRootView sortDesc: plasmoid.configuration.sortDesc sortDirsFirst: plasmoid.configuration.sortDirsFirst - parseDesktopFiles: (plasmoid.configuration.url == "desktop:/") + parseDesktopFiles: (plasmoid.configuration.url === "desktop:/") previews: plasmoid.configuration.previews previewPlugins: plasmoid.configuration.previewPlugins appletInterface: plasmoid onListingCompleted: { if (!gridView.model && plasmoid.expanded) { gridView.model = positioner; gridView.currentIndex = isPopup ? 0 : -1; } else if (goingBack) { goingBack = false; gridView.currentIndex = Math.min(lastPosition.index, gridView.count - 1); setSelected(positioner.map(gridView.currentIndex)); gridView.contentY = lastPosition.yPosition * gridView.contentHeight; } } onMove: { var rows = (gridView.flow == GridView.FlowLeftToRight); var axis = rows ? gridView.width : gridView.height; var step = rows ? cellWidth : cellHeight; var perStripe = Math.floor(axis / step); var dropPos = mapToItem(gridView.contentItem, x, y); var leftEdge = Math.min(gridView.contentX, gridView.originX); var moves = [] var itemX = -1; var itemY = -1; var col = -1; var row = -1; var from = -1; var to = -1; for (var i = 0; i < urls.length; i++) { from = positioner.indexForUrl(urls[i]); to = -1; - if (from == -1) { + if (from === -1) { continue; } var offset = dir.dragCursorOffset(positioner.map(from)); - if (offset.x == -1) { + if (offset.x === -1) { continue; } itemX = dropPos.x + offset.x + (listener.dragX % cellWidth) + (cellWidth / 2); itemY = dropPos.y + offset.y + (listener.dragY % cellHeight) + gridView.verticalDropHitscanOffset; if (gridView.effectiveLayoutDirection == Qt.RightToLeft) { itemX -= (rows ? gridView.contentX : gridView.originX); itemX = (rows ? gridView.width : gridView.contentItem.width) - itemX; } col = Math.floor(itemX / gridView.cellWidth); row = Math.floor(itemY / gridView.cellHeight); if ((rows ? col : row) < perStripe) { to = ((rows ? row : col) * perStripe) + (rows ? col : row); if (to < 0) { return; } } - if (from != to) { + if (from !== to) { moves.push(from); moves.push(to); } } if (moves.length) { positioner.move(moves); gridView.forceLayout(); } dir.clearSelection(); } } Folder.Positioner { id: positioner enabled: isContainment && sortMode === -1 folderModel: dir perStripe: Math.floor(((gridView.flow == GridView.FlowLeftToRight) ? gridView.width : gridView.height) / ((gridView.flow == GridView.FlowLeftToRight) ? gridView.cellWidth : gridView.cellHeight)); } Folder.ItemViewAdapter { id: viewAdapter adapterView: gridView adapterModel: positioner adapterIconSize: gridView.iconSize * 2 adapterVisibleArea: Qt.rect(gridView.contentX, gridView.contentY, gridView.contentWidth, gridView.contentHeight) Component.onCompleted: { gridView.movementStarted.connect(viewAdapter.viewScrolled); dir.viewAdapter = viewAdapter; } } Component { id: editorComponent PlasmaComponents.TextArea { id: editor visible: false wrapMode: root.useListViewMode ? TextEdit.NoWrap : TextEdit.Wrap textMargin: 0 horizontalAlignment: root.useListViewMode ? TextEdit.AlignHLeft : TextEdit.AlignHCenter property Item targetItem: null onTargetItemChanged: { if (targetItem != null) { var xy = getXY(); x = xy[0]; y = xy[1]; width = getWidth(); height = getInitHeight(); text = targetItem.label.text; adjustSize(); editor.select(0, dir.fileExtensionBoundary(positioner.map(targetItem.index))); if(isPopup) { flickableItem.contentX = Math.max(flickableItem.contentWidth - contentItem.width, 0); } else { flickableItem.contentY = Math.max(flickableItem.contentHeight - contentItem.height, 0); } visible = true; } else { x: 0 y: 0 visible = false; } } onVisibleChanged: { if (visible) { focus = true; } else { scrollArea.focus = true; } } Keys.onPressed: { switch(event.key) { case Qt.Key_Return: case Qt.Key_Enter: commit(); break; case Qt.Key_Escape: if (targetItem) { targetItem = null; event.accepted = true; } break; case Qt.Key_Home: if (event.modifiers & Qt.ShiftModifier) { editor.select(0, cursorPosition); } else { editor.select(0, 0); } event.accepted = true; break; case Qt.Key_End: if (event.modifiers & Qt.ShiftModifier) { editor.select(cursorPosition, text.length); } else { editor.select(text.length, text.length); } event.accepted = true; break; default: adjustSize(); break; } } Keys.onReleased: { adjustSize(); } function getXY() { var pos = main.mapFromItem(targetItem, targetItem.labelArea.x, targetItem.labelArea.y); var _x, _y; if (root.useListViewMode) { _x = targetItem.labelArea.x - __style.padding.left; _y = pos.y - __style.padding.top; } else { _x = targetItem.x + Math.abs(Math.min(gridView.contentX, gridView.originX)); _x += __style.padding.left; _x += scrollArea.viewport.x; if (verticalScrollBarPolicy == Qt.ScrollBarAlwaysOn && gridView.effectiveLayoutDirection == Qt.RightToLeft) { _x -= __verticalScrollBar.parent.verticalScrollbarOffset; } _y = pos.y + units.smallSpacing - __style.padding.top; } return([ _x, _y ]); } function getWidth(addWidthVerticalScroller) { return(targetItem.label.parent.width - units.smallSpacing + (root.useListViewMode ? -(__style.padding.left + __style.padding.right + units.smallSpacing) : 0) + (addWidthVerticalScroller ? __verticalScrollBar.parent.verticalScrollbarOffset : 0)); } function getHeight(addWidthHoriozontalScroller, init) { var _height; if(isPopup || init) { _height = targetItem.labelArea.height + __style.padding.top + __style.padding.bottom; } else { var realHeight = contentHeight + __style.padding.top + __style.padding.bottom; var maxHeight = theme.mSize(theme.defaultFont).height * (plasmoid.configuration.textLines + 1) + __style.padding.top + __style.padding.bottom; _height = Math.min(realHeight, maxHeight); } return(_height + (addWidthHoriozontalScroller ? __horizontalScrollBar.parent.horizontalScrollbarOffset : 0)); } function getInitHeight() { return(getHeight(false, true)); } function adjustSize() { if(isPopup) { if(contentWidth + __style.padding.left + __style.padding.right > width) { visible = true; horizontalScrollBarPolicy = Qt.ScrollBarAlwaysOn; height = getHeight(true); } else { horizontalScrollBarPolicy = Qt.ScrollBarAlwaysOff; height = getHeight(); } } else { height = getHeight(); if(contentHeight + __style.padding.top + __style.padding.bottom > height) { visible = true; verticalScrollBarPolicy = Qt.ScrollBarAlwaysOn; width = getWidth(true); } else { verticalScrollBarPolicy = Qt.ScrollBarAlwaysOff; width = getWidth(); } } var xy = getXY(); x = xy[0]; y = xy[1]; } function commit() { if (targetItem) { dir.rename(positioner.map(targetItem.index), text); targetItem = null; } } } } Component.onCompleted: { dir.requestRename.connect(rename); } } Component.onCompleted: { if (backButton == null && root.useListViewMode) { backButton = makeBackButton(); } } } diff --git a/containments/desktop/package/contents/ui/FolderViewLayer.qml b/containments/desktop/package/contents/ui/FolderViewLayer.qml index d9c2ad468..286f0ed52 100644 --- a/containments/desktop/package/contents/ui/FolderViewLayer.qml +++ b/containments/desktop/package/contents/ui/FolderViewLayer.qml @@ -1,434 +1,434 @@ /*************************************************************************** * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kconfig 1.0 // for KAuthorized import org.kde.private.desktopcontainment.folder 0.1 as Folder FocusScope { id: folderViewLayerComponent property variant sharedActions: ["newMenu", "paste", "undo", "refresh", "emptyTrash"] property Component folderViewDialogComponent: Qt.createComponent("FolderViewDialog.qml", Qt.Asynchronous, root) property Item view: folderView property Item label: null property int labelHeight: theme.mSize(theme.defaultFont).height + (root.isPopup ? (units.smallSpacing * 2) : 0) property alias model: folderView.model property alias overflowing: folderView.overflowing property alias flow: folderView.flow readonly property bool lockedByKiosk: !KAuthorized.authorize("editable_desktop_icons") focus: true function updateContextualActions() { folderView.model.updateActions(); var actionName = ""; var appletAction = null; var modelAction = null; for (var i = 0; i < sharedActions.length; i++) { actionName = sharedActions[i]; appletAction = plasmoid.action(actionName); modelAction = folderView.model.action(actionName); appletAction.text = modelAction.text; appletAction.enabled = modelAction.enabled; appletAction.visible = modelAction.visible; } } function cancelRename() { folderView.cancelRename(); } function goHome() { - if (folderView.url != plasmoid.configuration.url) { + if (folderView.url !== plasmoid.configuration.url) { folderView.url = Qt.binding(function() { return plasmoid.configuration.url; }); folderView.history = []; folderView.updateHistory(); } } PlasmaCore.Svg { id: actionOverlays imagePath: "widgets/action-overlays" multipleImages: true size: "16x16" } Binding { target: plasmoid property: "title" value: labelGenerator.displayLabel } Folder.LabelGenerator { id: labelGenerator folderModel: folderView.model rtl: (Qt.application.layoutDirection == Qt.RightToLeft) labelMode: plasmoid.configuration.labelMode || (isContainment ? 0 : 1) labelText: plasmoid.configuration.labelText } Folder.ViewPropertiesMenu { id: viewPropertiesMenu showLayoutActions: !isPopup showLockAction: isContainment showIconSizeActions: !root.useListViewMode lockedEnabled: !lockedByKiosk onArrangementChanged: { plasmoid.configuration.arrangement = arrangement; } onAlignmentChanged: { plasmoid.configuration.alignment = alignment; } onPreviewsChanged: { plasmoid.configuration.previews = previews; } onLockedChanged: { if (!lockedByKiosk) { plasmoid.configuration.locked = locked; } } onSortModeChanged: { plasmoid.configuration.sortMode = sortMode; } onSortDescChanged: { plasmoid.configuration.sortDesc = sortDesc; } onSortDirsFirstChanged: { plasmoid.configuration.sortDirsFirst = sortDirsFirst; } onIconSizeChanged: { plasmoid.configuration.iconSize = iconSize; } Component.onCompleted: { arrangement = plasmoid.configuration.arrangement; alignment = plasmoid.configuration.alignment; previews = plasmoid.configuration.previews; locked = plasmoid.configuration.locked || lockedByKiosk; sortMode = plasmoid.configuration.sortMode; sortDesc = plasmoid.configuration.sortDesc; sortDirsFirst = plasmoid.configuration.sortDirsFirst; iconSize = plasmoid.configuration.iconSize; } } PlasmaComponents.Label { anchors.fill: parent text: folderView.errorString horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.Wrap } Connections { target: plasmoid onExpandedChanged: { if (root.isPopup) { if (plasmoid.expanded) { folderView.currentIndex = -1; folderView.forceActiveFocus(); folderView.positionViewAtBeginning(); } else { goHome(); folderView.currentIndex = -1; folderView.model.clearSelection(); folderView.cancelRename(); } } } onExternalData: { plasmoid.configuration.url = data } } Connections { target: plasmoid.configuration onArrangementChanged: { viewPropertiesMenu.arrangement = plasmoid.configuration.arrangement; } onAlignmentChanged: { viewPropertiesMenu.alignment = plasmoid.configuration.alignment; } onLockedChanged: { viewPropertiesMenu.locked = plasmoid.configuration.locked; } onSortModeChanged: { folderView.sortMode = plasmoid.configuration.sortMode; viewPropertiesMenu.sortMode = plasmoid.configuration.sortMode; } onSortDescChanged: { viewPropertiesMenu.sortDesc = plasmoid.configuration.sortDesc; } onSortDirsFirstChanged: { viewPropertiesMenu.sortDirsFirst = plasmoid.configuration.sortDirsFirst; } onIconSizeChanged: { viewPropertiesMenu.iconSize = plasmoid.configuration.iconSize; } onPositionsChanged: { folderView.positions = plasmoid.configuration.positions; } } PlasmaCore.ColorScope { id: colorScope anchors.left: parent.left anchors.top: parent.top anchors.topMargin: folderViewLayerComponent.label != null ? folderViewLayerComponent.label.height : 0 anchors.right: parent.right anchors.bottom: parent.bottom // If containment always complementary, otherwise inherit (usually normal). colorGroup: (root.isContainment ? PlasmaCore.Theme.ComplementaryColorGroup : PlasmaCore.ColorScope.colorGroup) FolderView { id: folderView anchors.fill: parent focus: true isRootView: true url: plasmoid.configuration.url locked: (plasmoid.configuration.locked || !isContainment || lockedByKiosk) filterMode: plasmoid.configuration.filterMode filterPattern: plasmoid.configuration.filterPattern filterMimeTypes: plasmoid.configuration.filterMimeTypes - flow: (plasmoid.configuration.arrangement == 0) ? GridView.FlowLeftToRight : GridView.FlowTopToBottom - layoutDirection: (plasmoid.configuration.alignment == 0) ? Qt.LeftToRight : Qt.RightToLeft + flow: (plasmoid.configuration.arrangement === 0) ? GridView.FlowLeftToRight : GridView.FlowTopToBottom + layoutDirection: (plasmoid.configuration.alignment === 0) ? Qt.LeftToRight : Qt.RightToLeft onSortModeChanged: { plasmoid.configuration.sortMode = sortMode; } onPositionsChanged: { plasmoid.configuration.positions = folderView.positions; } Component.onCompleted: { folderView.sortMode = plasmoid.configuration.sortMode; folderView.positions = plasmoid.configuration.positions; } } } Component { id: labelComponent Item { id: label // If we bind height to visible, it will be invisible initially (since "visible" // propagates recursively) and that confuses the Label, hence the temp property. - readonly property bool active: (plasmoid.configuration.labelMode != 0) + readonly property bool active: (plasmoid.configuration.labelMode !== 0) readonly property bool showPin: root.isPopup && plasmoid.compactRepresentationItem && plasmoid.compactRepresentationItem.visible width: parent.width height: active ? labelHeight : 0 visible: active property Item windowPin: null property Item homeButton: null onVisibleChanged: { if (root.isPopup && !visible) { plasmoid.hideOnWindowDeactivate = true; } } onShowPinChanged: { if (!windowPin && showPin) { windowPin = windowPinComponent.createObject(label); } else if (windowPin) { windowPin.destroy(); windowPin = null; } } Connections { target: folderView onUrlChanged: { - if (!label.homeButton && folderView.url != plasmoid.configuration.url) { + if (!label.homeButton && folderView.url !== plasmoid.configuration.url) { label.homeButton = homeButtonComponent.createObject(label); - } else if (label.homeButton && folderView.url == plasmoid.configuration.url) { + } else if (label.homeButton && folderView.url === plasmoid.configuration.url) { label.homeButton.destroy(); } } } PlasmaComponents.Label { id: text anchors { left: label.homeButton ? label.homeButton.right : parent.left right: label.windowPin ? label.windowPin.left : parent.right margins: units.smallSpacing } height: parent.height horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignTop elide: Text.ElideMiddle text: labelGenerator.displayLabel font.underline: labelMouseArea.containsMouse } MouseArea { id: labelMouseArea anchors { top: text.top horizontalCenter: text.horizontalCenter } width: text.contentWidth height: text.contentHeight hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { var action = plasmoid.action("run associated application"); if (action) { action.trigger(); } } } Component { id: windowPinComponent PlasmaComponents.ToolButton { id: windowPin anchors.right: parent.right visible: label.showPin width: root.isPopup ? Math.round(units.gridUnit * 1.25) : 0 height: width checkable: true iconSource: "window-pin" onCheckedChanged: plasmoid.hideOnWindowDeactivate = !checked } } Component { id: homeButtonComponent PlasmaComponents.ToolButton { id: homeButton anchors.left: parent.left - visible: root.isPopup && folderView.url != plasmoid.configuration.url + visible: root.isPopup && folderView.url !== plasmoid.configuration.url width: root.isPopup ? Math.round(units.gridUnit * 1.25) : 0 height: width iconSource: "go-home" onClicked: goHome() } } Component.onCompleted: { if (root.showPin) { windowPin = windowPinComponent.createObject(label); } } } } Component.onCompleted: { if (!isContainment) { label = labelComponent.createObject(folderViewLayerComponent); } var actionName = ""; var modelAction = null; for (var i = 0; i < sharedActions.length; i++) { actionName = sharedActions[i]; modelAction = folderView.model.action(actionName); plasmoid.setAction(actionName, modelAction.text, Folder.MenuHelper.iconName(modelAction)); var plasmoidAction = plasmoid.action(actionName); plasmoidAction.shortcut = modelAction.shortcut; plasmoidAction.shortcutContext = Qt.WidgetShortcut; - if (actionName == "newMenu") { + if (actionName === "newMenu") { Folder.MenuHelper.setMenu(plasmoidAction, folderView.model.newMenu); plasmoid.setActionSeparator("separator1"); plasmoid.setAction("viewProperties", i18n("Icons"), "preferences-desktop-icons"); Folder.MenuHelper.setMenu(plasmoid.action("viewProperties"), viewPropertiesMenu.menu); } else { plasmoidAction.triggered.connect(modelAction.trigger); } } plasmoid.setActionSeparator("separator2"); plasmoid.contextualActionsAboutToShow.connect(updateContextualActions); plasmoid.contextualActionsAboutToShow.connect(folderView.model.clearSelection); } } diff --git a/containments/desktop/package/contents/ui/ResizeHandle.qml b/containments/desktop/package/contents/ui/ResizeHandle.qml index 48143df55..3fef5debe 100644 --- a/containments/desktop/package/contents/ui/ResizeHandle.qml +++ b/containments/desktop/package/contents/ui/ResizeHandle.qml @@ -1,93 +1,93 @@ /* * Copyright 2011-2013 Sebastian Kügler * Copyright 2011 Marco Martin * Copyright 2014 David Edmundson * Copyright 2015 Eike Hein * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.plasma.plasmoid 2.0 MouseArea { width: units.gridUnit height: units.gridUnit cursorShape: Qt.SizeVerCursor z: 99999 //to controls the resize/move behavior property bool moveX property bool moveY property bool resizeWidth property bool resizeHeight //internal property int startX property int startY property int startWidth property int startHeight - visible: applet && applet.backgroundHints != PlasmaCore.Types.NoBackground && enabled && !plasmoid.immutable && showAppletHandle + visible: applet && applet.backgroundHints !== PlasmaCore.Types.NoBackground && enabled && !plasmoid.immutable && showAppletHandle LayoutMirroring.enabled: false onPressed: { mouse.accepted = true animationsEnabled = false; var pos = mapToItem(root, mouse.x, mouse.y); startX = pos.x; startY = pos.y; startWidth = appletItem.width; startHeight = appletItem.height; appletItem.releasePosition(); appletItem.floating = true; appletContainer.clip = true } onPositionChanged: { var pos = mapToItem(root, mouse.x, mouse.y); var xDelta = moveX ? pos.x - startX : startX - pos.x; var yDelta = moveY ? startY - pos.y : pos.y - startY; var oldRight = appletItem.x + appletItem.width; if (resizeWidth) { appletItem.width = Math.min(Math.max(appletItem.minimumWidth, startWidth - xDelta), appletItem.maximumWidth); } var oldBottom = appletItem.y + appletItem.height; if (resizeHeight) { appletItem.height = Math.min(Math.max(appletItem.minimumHeight, startHeight + yDelta), appletItem.maximumHeight); } if (moveX) { appletItem.x = oldRight - appletItem.width; } if (moveY) { appletItem.y = oldBottom - appletItem.height; } } onReleased: { animationsEnabled = true appletItem.floating = false; appletItem.positionItem(); root.layoutManager.save() appletContainer.clip = false } } diff --git a/containments/desktop/package/contents/ui/main.qml b/containments/desktop/package/contents/ui/main.qml index ba84e9349..2bdbbb5df 100644 --- a/containments/desktop/package/contents/ui/main.qml +++ b/containments/desktop/package/contents/ui/main.qml @@ -1,618 +1,618 @@ /*************************************************************************** * Copyright (C) 2011-2013 Sebastian Kügler * * Copyright (C) 2011 Marco Martin * * Copyright (C) 2014-2015 by 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 . * ***************************************************************************/ import QtQuick 2.4 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.draganddrop 2.0 as DragDrop import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.private.desktopcontainment.desktop 0.1 as Desktop import org.kde.private.desktopcontainment.folder 0.1 as Folder import "code/LayoutManager.js" as LayoutManager import "code/FolderTools.js" as FolderTools FolderViewDropArea { id: root objectName: isFolder ? "folder" : "desktop" width: isPopup ? undefined : preferredWidth(false) // Initial size when adding to e.g. desktop. height: isPopup ? undefined : preferredHeight(false) // Initial size when adding to e.g. desktop. Layout.minimumWidth: preferredWidth(!isPopup) Layout.minimumHeight: preferredHeight(!isPopup) Layout.preferredWidth: preferredWidth(false) Layout.preferredHeight: preferredHeight(false) Layout.maximumWidth: isPopup ? preferredWidth(false) : -1 Layout.maximumHeight: isPopup ? preferredHeight(false) : -1 Plasmoid.switchWidth: { // Support expanding into the full representation only on vertical panels. - if (isPopup && plasmoid.formFactor == PlasmaCore.Types.Vertical) { + if (isPopup && plasmoid.formFactor === PlasmaCore.Types.Vertical) { return units.iconSizeHints.panel; } return 0; } Plasmoid.switchHeight: { // Support expanding into the full representation only on vertical panels. - if (isPopup && plasmoid.formFactor == PlasmaCore.Types.Vertical) { + if (isPopup && plasmoid.formFactor === PlasmaCore.Types.Vertical) { return units.iconSizeHints.panel; } return 0; } LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true - property bool isFolder: (plasmoid.pluginName == "org.kde.plasma.folder") + property bool isFolder: (plasmoid.pluginName === "org.kde.plasma.folder") property bool isContainment: ("containmentType" in plasmoid) - property bool isPopup: (plasmoid.location != PlasmaCore.Types.Floating) + property bool isPopup: (plasmoid.location !== PlasmaCore.Types.Floating) property bool useListViewMode: isPopup && plasmoid.configuration.viewMode === 0 property Component appletAppearanceComponent property Item toolBox property var layoutManager: LayoutManager property int handleDelay: 800 property real haloOpacity: 0.5 property int iconSize: units.iconSizes.small property int iconWidth: iconSize property int iconHeight: iconWidth readonly property int hoverActivateDelay: 750 // Magic number that matches Dolphin's auto-expand folders delay. preventStealing: true // Plasmoid.title is set by a Binding {} in FolderViewLayer Plasmoid.toolTipSubText: "" Plasmoid.icon: (!plasmoid.configuration.useCustomIcon && folderViewLayer.ready) ? folderViewLayer.view.model.iconName : plasmoid.configuration.icon Plasmoid.compactRepresentation: (isFolder && !isContainment) ? compactRepresentation : null Plasmoid.associatedApplicationUrls: folderViewLayer.ready ? folderViewLayer.model.resolvedUrl : null onIconHeightChanged: updateGridSize() anchors { leftMargin: (isContainment && plasmoid.availableScreenRect) ? plasmoid.availableScreenRect.x : 0 topMargin: (isContainment && plasmoid.availableScreenRect) ? plasmoid.availableScreenRect.y : 0 rightMargin: (isContainment && plasmoid.availableScreenRect) && parent ? parent.width - (plasmoid.availableScreenRect.x + plasmoid.availableScreenRect.width) : 0 bottomMargin: (isContainment && plasmoid.availableScreenRect) && parent ? parent.height - (plasmoid.availableScreenRect.y + plasmoid.availableScreenRect.height) : 0 } Behavior on anchors.topMargin { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutQuad } } Behavior on anchors.leftMargin { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutQuad } } Behavior on anchors.rightMargin { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutQuad } } Behavior on anchors.bottomMargin { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutQuad } } function updateGridSize() { LayoutManager.cellSize.width = root.iconWidth + toolBoxSvg.elementSize("left").width + toolBoxSvg.elementSize("right").width LayoutManager.cellSize.height = root.iconHeight + toolBoxSvg.elementSize("top").height + toolBoxSvg.elementSize("bottom").height; LayoutManager.defaultAppletSize.width = LayoutManager.cellSize.width * 6; LayoutManager.defaultAppletSize.height = LayoutManager.cellSize.height * 6; layoutTimer.restart(); } function addLauncher(desktopUrl) { if (!isFolder) { return; } folderViewLayer.view.linkHere(desktopUrl); } function addApplet(applet, x, y) { if (!appletAppearanceComponent) { appletAppearanceComponent = Qt.createComponent("AppletAppearance.qml"); } if (appletAppearanceComponent.status !== Component.Ready) { console.warn("Error loading AppletAppearance.qml:", appletAppearanceComponent.errorString()); return; } var category = "Applet-" + applet.id; var container = appletAppearanceComponent.createObject(resultsFlow, { category: category }); applet.parent = container applet.visible = true; var config = LayoutManager.itemsConfig[category]; // We have it in the config. if (config !== undefined && config.width !== undefined && config.height !== undefined && config.width > 0 && config.height > 0) { container.width = config.width; container.height = config.height; // We have a default. } else if (applet.width > 0 && applet.height > 0) { container.width = applet.width; container.height = applet.height; // The container needs to be bigger than applet of margins factor. - if (applet.backgroundHints != PlasmaCore.Types.NoBackground) { + if (applet.backgroundHints !== PlasmaCore.Types.NoBackground) { container.width += container.margins.left + container.margins.right; container.height += container.margins.top + container.margins.bottom; } // Give up, assign the global default. } else { container.width = LayoutManager.defaultAppletSize.width; container.height = LayoutManager.defaultAppletSize.height; } container.applet = applet; // Coordinated passed by param? if ( x >= 0 && y >= 0) { if (x + container.width > root.width) { x = root.width - container.width - 10; } if (y + container.height > root.height) { x = root.height - container.height; } // On applet undo or via scripting, the applet position will be saved // in applet's scene coordinates so remap it to resultsflow's coordinates. var pos = root.parent.mapToItem(resultsFlow, x, y); container.x = pos.x; container.y = pos.y; // To be sure it's restored at the same position, take margins into account // if there is a background. - if (applet.backgroundHints != PlasmaCore.Types.NoBackground) { + if (applet.backgroundHints !== PlasmaCore.Types.NoBackground) { container.x -= container.margins.left; container.y -= container.margins.top; } // Coordinates stored? } else if (config !== undefined && config.x !== undefined && config.y !== undefined && config.x >= 0 && config.y >= 0) { container.x = config.x; container.y = config.y; } // Rotation stored and significant? if (config !== undefined && config.rotation !== undefined && (config.rotation > 5 || config.rotation < -5)) { container.rotation = config.rotation; } else { LayoutManager.restoreRotation(container); } LayoutManager.itemGroups[container.category] = container; if (container.x >= 0 && container.y >= 0) { LayoutManager.positionItem(container); } } function preferredWidth(minimum) { if (isContainment || !folderViewLayer.ready) { return -1; } else if (useListViewMode) { return (minimum ? folderViewLayer.view.cellHeight * 4 : units.gridUnit * 16); } return (folderViewLayer.view.cellWidth * (minimum ? 1 : 3)) + (units.largeSpacing * 2); } function preferredHeight(minimum) { if (isContainment || !folderViewLayer.ready) { return -1; } else if (useListViewMode) { var height = (folderViewLayer.view.cellHeight * (minimum ? 1 : 15)) + units.smallSpacing; } else { var height = (folderViewLayer.view.cellHeight * (minimum ? 1 : 2)) + units.largeSpacing } - if (plasmoid.configuration.labelMode != 0) { + if (plasmoid.configuration.labelMode !== 0) { height += folderViewLayer.item.labelHeight; } return height; } function isDrag(fromX, fromY, toX, toY) { var length = Math.abs(fromX - toX) + Math.abs(fromY - toY); return length >= Qt.styleHints.startDragDistance; } onFocusChanged: { if (focus && isFolder) { folderViewLayer.item.forceActiveFocus(); } } onDragEnter: { if (isContainment && plasmoid.immutable && !(isFolder && FolderTools.isFileDrag(event))) { event.ignore(); } // Don't allow any drops while listing. if (isFolder && folderViewLayer.view.status === Folder.FolderModel.Listing) { event.ignore(); } // Firefox tabs are regular drags. Since all of our drop handling is asynchronous // we would accept this drop and have Firefox not spawn a new window. (Bug 337711) if (event.mimeData.formats.indexOf("application/x-moz-tabbrowser-tab") > -1) { event.ignore(); } } onDragMove: { // TODO: We should reject drag moves onto file items that don't accept drops // (cf. QAbstractItemModel::flags() here, but DeclarativeDropArea currently // is currently incapable of rejecting drag events. // Trigger autoscroll. if (isFolder && FolderTools.isFileDrag(event)) { handleDragMove(folderViewLayer.view, mapToItem(folderViewLayer.view, event.x, event.y)); } else if (isContainment) { placeHolder.width = LayoutManager.defaultAppletSize.width; placeHolder.height = LayoutManager.defaultAppletSize.height; placeHolder.minimumWidth = placeHolder.minimumHeight = 0; placeHolder.x = event.x - placeHolder.width / 2; placeHolder.y = event.y - placeHolder.width / 2; LayoutManager.positionItem(placeHolder); LayoutManager.setSpaceAvailable(placeHolder.x, placeHolder.y, placeHolder.width, placeHolder.height, true); placeHolderPaint.opacity = root.haloOpacity; } } onDragLeave: { // Cancel autoscroll. if (isFolder) { handleDragEnd(folderViewLayer.view); } if (isContainment) { placeHolderPaint.opacity = 0; } } onDrop: { if (isFolder && FolderTools.isFileDrag(event)) { handleDragEnd(folderViewLayer.view); folderViewLayer.view.drop(root, event, mapToItem(folderViewLayer.view, event.x, event.y)); } else if (isContainment) { placeHolderPaint.opacity = 0; var pos = root.parent.mapFromItem(resultsFlow, event.x - placeHolder.width / 2, event.y - placeHolder.height / 2); plasmoid.processMimeData(event.mimeData, pos.x, pos.y); event.accept(event.proposedAction); } } Component { id: compactRepresentation CompactRepresentation { folderView: folderViewLayer.view } } Connections { target: plasmoid ignoreUnknownSignals: true onAppletAdded: { addApplet(applet, x, y); // Clean any eventual invalid chunks in the config. LayoutManager.save(); } onAppletRemoved: { // Clean any eventual invalid chunks in the config. LayoutManager.removeApplet(applet); LayoutManager.save(); } onImmutableChanged: { if (root.isContainment && !plasmoid.immutable) { pressToMoveHelp.show(); } } onAvailableScreenRegionChanged: layoutTimer.restart(); } Connections { target: plasmoid.configuration onPressToMoveChanged: { if (plasmoid.configuration.pressToMove && plasmoid.configuration.pressToMoveHelp && !plasmoid.immutable) { pressToMoveHelp.show(); } } } Binding { target: toolBox property: "visible" value: plasmoid.configuration.showToolbox } Desktop.InfoNotification { id: pressToMoveHelp enabled: plasmoid.configuration.pressToMove && plasmoid.configuration.pressToMoveHelp iconName: "plasma" titleText: i18n("Widgets unlocked") text: i18n("You can press and hold widgets to move them and reveal their handles.") acknowledgeActionText: i18n("Got it") onAcknowledged: { plasmoid.configuration.pressToMoveHelp = false; } } PlasmaCore.FrameSvgItem { id : highlightItemSvg visible: false imagePath: isPopup ? "widgets/viewitem" : "" prefix: "hover" } PlasmaCore.FrameSvgItem { id : listItemSvg visible: false imagePath: isPopup ? "widgets/viewitem" : "" prefix: "normal" } PlasmaCore.Svg { id: toolBoxSvg imagePath: "widgets/toolbox" property int rightBorder: elementSize("right").width property int topBorder: elementSize("top").height property int bottomBorder: elementSize("bottom").height property int leftBorder: elementSize("left").width } PlasmaCore.Svg { id: configIconsSvg imagePath: "widgets/configuration-icons" } KQuickControlsAddons.EventGenerator { id: eventGenerator } MouseArea { // unfocus any plasmoid when clicking empty desktop area anchors.fill: parent onPressed: { root.forceActiveFocus(); mouse.accepted = false // Bug 351277 if (toolBox && toolBox.open) { toolBox.open = false; } } } Loader { id: folderViewLayer anchors.fill: parent property bool ready: status == Loader.Ready property Item view: item ? item.view : null property QtObject model: item ? item.model : null focus: true active: isFolder asynchronous: false source: "FolderViewLayer.qml" onFocusChanged: { if (!focus && model) { model.clearSelection(); } } Connections { target: folderViewLayer.view // `FolderViewDropArea` is not a FocusScope. We need to forward manually. onPressed: { folderViewLayer.forceActiveFocus(); } } } Item { id: resultsFlow anchors.fill: parent anchors { top: parent.top topMargin: 5 horizontalCenter: parent.horizontalCenter } visible: isContainment enabled: isContainment // This is just for event compression when a lot of boxes are created one after the other. Timer { id: layoutTimer repeat: false running: false interval: 100 onTriggered: { LayoutManager.resetPositions() for (var i=0; i 0 Behavior on opacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } } Component.onCompleted: { if (!isContainment) { return; } // Customize the icon and text to improve discoverability plasmoid.setAction("configure", i18n("Configure Desktop..."), "preferences-desktop-wallpaper") // WORKAROUND: that's the only place where we can inject a sensible size. // if root has width defined, it will override the value we set before // the component completes root.width = plasmoid.width; LayoutManager.resultsFlow = resultsFlow; LayoutManager.plasmoid = plasmoid; updateGridSize(); LayoutManager.restore(); for (var i = 0; i < plasmoid.applets.length; ++i) { var applet = plasmoid.applets[i]; addApplet(applet, -1, -1); } // Clean any eventual invalid chunks in the config. LayoutManager.save(); } } diff --git a/containments/panel/contents/ui/ConfigOverlay.qml b/containments/panel/contents/ui/ConfigOverlay.qml index c585944d8..c743f250a 100644 --- a/containments/panel/contents/ui/ConfigOverlay.qml +++ b/containments/panel/contents/ui/ConfigOverlay.qml @@ -1,400 +1,400 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 MouseArea { id: configurationArea z: 1000 anchors.fill: currentLayout hoverEnabled: true property bool isResizingLeft: false property bool isResizingRight: false property Item currentApplet property int lastX property int lastY readonly property int spacerHandleSize: units.smallSpacing onHeightChanged: tooltip.visible = false; onWidthChanged: tooltip.visible = false; onPositionChanged: { if (currentApplet && currentApplet.applet && - currentApplet.applet.pluginName == "org.kde.plasma.panelspacer") { + currentApplet.applet.pluginName === "org.kde.plasma.panelspacer") { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { if ((mouse.y - handle.y) < spacerHandleSize || (mouse.y - handle.y) > (handle.height - spacerHandleSize)) { configurationArea.cursorShape = Qt.SizeVerCursor; } else { configurationArea.cursorShape = Qt.ArrowCursor; } } else { if ((mouse.x - handle.x) < spacerHandleSize || (mouse.x - handle.x) > (handle.width - spacerHandleSize)) { configurationArea.cursorShape = Qt.SizeHorCursor; } else { configurationArea.cursorShape = Qt.ArrowCursor; } } } else { configurationArea.cursorShape = Qt.ArrowCursor; } if (pressed) { - if (currentApplet && currentApplet.applet.pluginName == "org.kde.plasma.panelspacer") { + if (currentApplet && currentApplet.applet.pluginName === "org.kde.plasma.panelspacer") { if (isResizingLeft) { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { handle.y += (mouse.y - lastY); handle.height = currentApplet.height + (currentApplet.y - handle.y); } else { handle.x += (mouse.x - lastX); handle.width = currentApplet.width + (currentApplet.x - handle.x); } lastX = mouse.x; lastY = mouse.y; return; } else if (isResizingRight) { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { handle.height = mouse.y - handle.y; } else { handle.width = mouse.x - handle.x; } lastX = mouse.x; lastY = mouse.y; return; } } var padding = units.gridUnit * 3; if (currentApplet && (mouse.x < -padding || mouse.y < -padding || mouse.x > width + padding || mouse.y > height + padding)) { var newCont = plasmoid.containmentAt(mouse.x, mouse.y); - if (newCont && newCont != plasmoid) { + if (newCont && newCont !== plasmoid) { var newPos = newCont.mapFromApplet(plasmoid, mouse.x, mouse.y); newCont.addApplet(currentApplet.applet, newPos.x, newPos.y); root.dragOverlay.currentApplet = null; return; } } if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { currentApplet.y += (mouse.y - lastY); handle.y = currentApplet.y; } else { currentApplet.x += (mouse.x - lastX); handle.x = currentApplet.x; } lastX = mouse.x; lastY = mouse.y; var item = currentLayout.childAt(mouse.x, mouse.y); if (item && item !== placeHolder) { placeHolder.width = item.width; placeHolder.height = item.height; placeHolder.parent = configurationArea; var posInItem = mapToItem(item, mouse.x, mouse.y); if ((plasmoid.formFactor === PlasmaCore.Types.Vertical && posInItem.y < item.height/2) || (plasmoid.formFactor !== PlasmaCore.Types.Vertical && posInItem.x < item.width/2)) { root.layoutManager.insertBefore(item, placeHolder); } else { root.layoutManager.insertAfter(item, placeHolder); } } } else { var item = currentLayout.childAt(mouse.x, mouse.y); if (root.dragOverlay && item && item !== lastSpacer) { root.dragOverlay.currentApplet = item; } else { root.dragOverlay.currentApplet = null; } } if (root.dragOverlay.currentApplet) { hideTimer.stop(); tooltip.visible = true; tooltip.raise(); } } onExited: hideTimer.restart(); onCurrentAppletChanged: { if (!currentApplet || !root.dragOverlay.currentApplet) { hideTimer.start(); return; } handle.x = currentApplet.x; handle.y = currentApplet.y; handle.width = currentApplet.width; handle.height = currentApplet.height; } onPressed: { if (!root.dragOverlay.currentApplet) { return; } - if (currentApplet.applet.pluginName == "org.kde.plasma.panelspacer") { + if (currentApplet.applet.pluginName === "org.kde.plasma.panelspacer") { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { if ((mouse.y - handle.y) < spacerHandleSize) { configurationArea.isResizingLeft = true; configurationArea.isResizingRight = false; } else if ((mouse.y - handle.y) > (handle.height - spacerHandleSize)) { configurationArea.isResizingLeft = false; configurationArea.isResizingRight = true; } else { configurationArea.isResizingLeft = false; configurationArea.isResizingRight = false; } } else { if ((mouse.x - handle.x) < spacerHandleSize) { configurationArea.isResizingLeft = true; configurationArea.isResizingRight = false; } else if ((mouse.x - handle.x) > (handle.width - spacerHandleSize)) { configurationArea.isResizingLeft = false; configurationArea.isResizingRight = true; } else { configurationArea.isResizingLeft = false; configurationArea.isResizingRight = false; } } } lastX = mouse.x; lastY = mouse.y; placeHolder.width = currentApplet.width; placeHolder.height = currentApplet.height; root.layoutManager.insertBefore(currentApplet, placeHolder); currentApplet.parent = moveAppletLayer; currentApplet.z = 900; } onReleased: { if (!root.dragOverlay.currentApplet) { return; } if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { currentApplet.applet.configuration.length = handle.height; } else { currentApplet.applet.configuration.length = handle.width; } configurationArea.isResizingLeft = false; configurationArea.isResizingRight = false; root.layoutManager.insertBefore(placeHolder, currentApplet); placeHolder.parent = configurationArea; currentApplet.z = 1; handle.x = currentApplet.x; handle.y = currentApplet.y; handle.width = currentApplet.width; handle.height = currentApplet.height; root.layoutManager.save(); } Item { id: placeHolder visible: configurationArea.containsMouse Layout.fillWidth: currentApplet ? currentApplet.Layout.fillWidth : false Layout.fillHeight: currentApplet ? currentApplet.Layout.fillHeight : false } Timer { id: hideTimer interval: units.longDuration * 3 onTriggered: tooltip.visible = false; } Connections { target: currentApplet onXChanged: handle.x = currentApplet.x onYChanged: handle.y = currentApplet.y onWidthChanged: handle.width = currentApplet.width onHeightChanged: handle.height = currentApplet.height } Rectangle { id: handle visible: configurationArea.containsMouse color: theme.backgroundColor radius: 3 opacity: currentApplet ? 0.5 : 0 PlasmaCore.IconItem { source: "transform-move" width: Math.min(parent.width, parent.height) height: width anchors.centerIn: parent } Rectangle { anchors { left: parent.left top: parent.top bottom: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? parent.bottom : undefined right: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? undefined : parent.right } - visible: currentApplet && currentApplet.applet.pluginName == "org.kde.plasma.panelspacer" + visible: currentApplet && currentApplet.applet.pluginName === "org.kde.plasma.panelspacer" opacity: visible && !xAnim.running && !yAnim.running ? 1.0 : 0 width: configurationArea.spacerHandleSize height: configurationArea.spacerHandleSize color: theme.textColor Behavior on opacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } Rectangle { anchors { right: parent.right top: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? parent.top : undefined bottom: parent.bottom left: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? undefined : parent.left } - visible: currentApplet && currentApplet.applet.pluginName == "org.kde.plasma.panelspacer" + visible: currentApplet && currentApplet.applet.pluginName === "org.kde.plasma.panelspacer" opacity: visible && !xAnim.running && !yAnim.running ? 1.0 : 0 width: configurationArea.spacerHandleSize height: configurationArea.spacerHandleSize color: theme.textColor Behavior on opacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } Behavior on x { enabled: !configurationArea.pressed NumberAnimation { id: xAnim duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on y { id: yAnim enabled: !configurationArea.pressed NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on width { enabled: !configurationArea.pressed NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on height { enabled: !configurationArea.pressed NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on opacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } PlasmaCore.Dialog { id: tooltip visualParent: currentApplet type: PlasmaCore.Dialog.Dock flags: Qt.WindowStaysOnTopHint|Qt.WindowDoesNotAcceptFocus|Qt.BypassWindowManagerHint location: plasmoid.location onVisualParentChanged: { if (visualParent) { configureButton.visible = currentApplet.applet.action("configure") && currentApplet.applet.action("configure").enabled; closeButton.visible = currentApplet.applet.action("remove") && currentApplet.applet.action("remove").enabled; label.text = currentApplet.applet.title; } } mainItem: MouseArea { enabled: currentApplet width: handleButtons.width height: handleButtons.height hoverEnabled: true onEntered: hideTimer.stop(); onExited: hideTimer.restart(); ColumnLayout { id: handleButtons spacing: units.smallSpacing PlasmaExtras.Heading { id: label level: 3 Layout.fillWidth: true Layout.leftMargin: units.smallSpacing * 2 Layout.rightMargin: units.smallSpacing * 2 } PlasmaComponents.ToolButton { id: configureButton Layout.fillWidth: true iconSource: "configure" text: i18n("Configure...") onClicked: { tooltip.visible = false; currentApplet.applet.action("configure").trigger() } } PlasmaComponents.ToolButton { id: closeButton Layout.fillWidth: true iconSource: "delete" text: i18n("Remove") onClicked: { tooltip.visible = false; currentApplet.applet.action("remove").trigger(); } } } } } } diff --git a/containments/panel/contents/ui/main.qml b/containments/panel/contents/ui/main.qml index 4f3d81e51..cc263f208 100644 --- a/containments/panel/contents/ui/main.qml +++ b/containments/panel/contents/ui/main.qml @@ -1,444 +1,444 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.draganddrop 2.0 as DragDrop import "LayoutManager.js" as LayoutManager DragDrop.DropArea { id: root width: 640 height: 48 //BEGIN properties Layout.minimumWidth: fixedWidth > 0 ? fixedWidth : (currentLayout.Layout.minimumWidth + (isHorizontal && toolBox ? toolBox.width : 0)) Layout.maximumWidth: fixedWidth > 0 ? fixedWidth : (currentLayout.Layout.maximumWidth + (isHorizontal && toolBox ? toolBox.width : 0)) Layout.preferredWidth: fixedWidth > 0 ? fixedWidth : (currentLayout.Layout.preferredWidth + (isHorizontal && toolBox ? toolBox.width : 0)) Layout.minimumHeight: fixedHeight > 0 ? fixedHeight : (currentLayout.Layout.minimumHeight + (!isHorizontal && toolBox ? toolBox.height : 0)) Layout.maximumHeight: fixedHeight > 0 ? fixedHeight : (currentLayout.Layout.maximumHeight + (!isHorizontal && toolBox ? toolBox.height : 0)) Layout.preferredHeight: fixedHeight > 0 ? fixedHeight : (currentLayout.Layout.preferredHeight + (!isHorizontal && toolBox? toolBox.height : 0)) property Item toolBox property var layoutManager: LayoutManager property Item dragOverlay - property bool isHorizontal: plasmoid.formFactor != PlasmaCore.Types.Vertical + property bool isHorizontal: plasmoid.formFactor !== PlasmaCore.Types.Vertical property int fixedWidth: 0 property int fixedHeight: 0 //END properties //BEGIN functions function addApplet(applet, x, y) { // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller // Due to the nature of how "visible" propagates in QML, we need to // explicitly set it on the container (so the Layout ignores it) // as well as the applet (so it reliably knows about), otherwise it can // happen that an applet erroneously thinks it's visible, or suddenly // starts thinking that way on teardown (virtual desktop pager) // leading to crashes var visibleBinding = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && plasmoid.userConfiguring); }) var container = appletContainerComponent.createObject(root, { applet: applet, visible: visibleBinding }); applet.parent = container; applet.anchors.fill = container; applet.visible = visibleBinding; // Is there a DND placeholder? Replace it! if (dndSpacer.parent === currentLayout) { LayoutManager.insertBefore(dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = lastSpacer; container.animationsEnabled = false; // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. - if (!startupTimer.running && applet.pluginName == "org.kde.plasma.icon") { + if (!startupTimer.running && applet.pluginName === "org.kde.plasma.icon") { var middle = currentLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // lastSpacer is here, enqueue before it. } LayoutManager.insertBefore(before, container); //event compress the enable of animations startupTimer.restart(); } } function checkLastSpacer() { var flexibleFound = false; for (var i = 0; i < currentLayout.children.length; ++i) { var applet = currentLayout.children[i].applet; if (!applet) { continue; } if (!applet.visible || !applet.Layout) { continue; } if ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) { flexibleFound = true; break } } lastSpacer.visible= !flexibleFound; } //END functions //BEGIN connections Component.onCompleted: { currentLayout.isLayoutHorizontal = isHorizontal LayoutManager.plasmoid = plasmoid; LayoutManager.root = root; LayoutManager.layout = currentLayout; LayoutManager.lastSpacer = lastSpacer; LayoutManager.restore(); containmentSizeSyncTimer.restart(); plasmoid.action("configure").visible = Qt.binding(function() { return !plasmoid.immutable; }); plasmoid.action("configure").enabled = Qt.binding(function() { return !plasmoid.immutable; }); } onDragEnter: { if (plasmoid.immutable) { event.ignore(); return; } //during drag operations we disable panel auto resize if (root.isHorizontal) { root.fixedWidth = root.width } else { root.fixedHeight = root.height } LayoutManager.insertAtCoordinates(dndSpacer, event.x, event.y) } onDragMove: { LayoutManager.insertAtCoordinates(dndSpacer, event.x, event.y) } onDragLeave: { dndSpacer.parent = root; root.fixedWidth = 0; root.fixedHeight = 0; } onDrop: { plasmoid.processMimeData(event.mimeData, event.x, event.y); event.accept(event.proposedAction); root.fixedWidth = 0; root.fixedHeight = 0; containmentSizeSyncTimer.restart(); } Containment.onAppletAdded: { addApplet(applet, x, y); checkLastSpacer(); LayoutManager.save(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); checkLastSpacer(); LayoutManager.save(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } if (plasmoid.userConfiguring) { for (var i = 0; i < plasmoid.applets.length; ++i) { plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("ConfigOverlay.qml"); if (component.status === Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay:", component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { dragOverlay.destroy(); } } Plasmoid.onFormFactorChanged: containmentSizeSyncTimer.restart(); Plasmoid.onImmutableChanged: containmentSizeSyncTimer.restart(); onToolBoxChanged: { containmentSizeSyncTimer.restart(); if (startupTimer.running) { startupTimer.restart(); } } //END connections //BEGIN components Component { id: appletContainerComponent // This loader conditionally manages the BusyIndicator, it's not // loading the applet. The applet becomes a regular child item. Loader { id: container visible: false property bool animationsEnabled: true //when the applet moves caused by its resize, don't animate. //this is completely heuristic, but looks way less "jumpy" property bool movingForResize: false Layout.fillWidth: applet && applet.Layout.fillWidth Layout.onFillWidthChanged: { - if (plasmoid.formFactor != PlasmaCore.Types.Vertical) { + if (plasmoid.formFactor !== PlasmaCore.Types.Vertical) { checkLastSpacer(); } } Layout.fillHeight: applet && applet.Layout.fillHeight Layout.onFillHeightChanged: { - if (plasmoid.formFactor == PlasmaCore.Types.Vertical) { + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { checkLastSpacer(); } } Layout.minimumWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.minimumWidth > 0 ? applet.Layout.minimumWidth : root.height) : root.width) Layout.minimumHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.minimumHeight > 0 ? applet.Layout.minimumHeight : root.width) : root.height) Layout.preferredWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.preferredWidth > 0 ? applet.Layout.preferredWidth : root.height) : root.width) Layout.preferredHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.preferredHeight > 0 ? applet.Layout.preferredHeight : root.width) : root.height) Layout.maximumWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.maximumWidth > 0 ? applet.Layout.maximumWidth : (Layout.fillWidth ? root.width : root.height)) : root.height) Layout.maximumHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.maximumHeight > 0 ? applet.Layout.maximumHeight : (Layout.fillHeight ? root.height : root.width)) : root.width) property int oldX: x property int oldY: y property Item applet onAppletChanged: { if (!applet) { destroy(); } } active: applet && applet.busy sourceComponent: PlasmaComponents.BusyIndicator {} Layout.onMinimumWidthChanged: movingForResize = true; Layout.onMinimumHeightChanged: movingForResize = true; Layout.onMaximumWidthChanged: movingForResize = true; Layout.onMaximumHeightChanged: movingForResize = true; onXChanged: { if (movingForResize) { movingForResize = false; return; } if (!animationsEnabled) { startupTimer.restart(); return; } translation.x = oldX - x translation.y = oldY - y translAnim.running = true oldX = x oldY = y } onYChanged: { if (movingForResize) { movingForResize = false; return; } if (!animationsEnabled) { startupTimer.restart(); return; } translation.x = oldX - x translation.y = oldY - y translAnim.running = true oldX = x oldY = y } transform: Translate { id: translation } NumberAnimation { id: translAnim duration: units.longDuration easing.type: Easing.InOutQuad target: translation properties: "x,y" to: 0 } } } //END components //BEGIN UI elements Item { id: lastSpacer parent: currentLayout Layout.fillWidth: true Layout.fillHeight: true } Item { id: dndSpacer Layout.preferredWidth: width Layout.preferredHeight: height - width: (plasmoid.formFactor == PlasmaCore.Types.Vertical) ? currentLayout.width : theme.mSize(theme.defaultFont).width * 10 - height: (plasmoid.formFactor == PlasmaCore.Types.Vertical) ? theme.mSize(theme.defaultFont).width * 10 : currentLayout.height + width: (plasmoid.formFactor === PlasmaCore.Types.Vertical) ? currentLayout.width : theme.mSize(theme.defaultFont).width * 10 + height: (plasmoid.formFactor === PlasmaCore.Types.Vertical) ? theme.mSize(theme.defaultFont).width * 10 : currentLayout.height } // while the user is moving the applet when configuring the panel, the applet is reparented // here so it can be moved freely; previously it was reparented to "root" but this one does not // take into account the toolbox (which is left-of) the layout in right-to-left languages Item { id: moveAppletLayer anchors.fill: currentLayout } GridLayout { id: currentLayout property bool isLayoutHorizontal rowSpacing: units.smallSpacing columnSpacing: units.smallSpacing Layout.preferredWidth: { var width = 0; for (var i = 0, length = currentLayout.children.length; i < length; ++i) { var item = currentLayout.children[i]; if (item.Layout) { width += Math.max(item.Layout.minimumWidth, item.Layout.preferredWidth); } } return width; } Layout.preferredHeight: { var height = 0; for (var i = 0, length = currentLayout.children.length; i < length; ++i) { var item = currentLayout.children[i]; if (item.Layout) { height += Math.max(item.Layout.minimumHeight, item.Layout.preferredHeight); } } return height; } rows: 1 columns: 1 //when horizontal layout top-to-bottom, this way it will obey our limit of one row and actually lay out left to right flow: isHorizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight layoutDirection: Qt.application.layoutDirection } onWidthChanged: { containmentSizeSyncTimer.restart() if (startupTimer.running) { startupTimer.restart(); } } onHeightChanged: { containmentSizeSyncTimer.restart() if (startupTimer.running) { startupTimer.restart(); } } Timer { id: containmentSizeSyncTimer interval: 150 onTriggered: { dndSpacer.parent = root; currentLayout.x = (isHorizontal && toolBox && Qt.application.layoutDirection === Qt.RightToLeft && !plasmoid.immutable) ? toolBox.width : 0; currentLayout.y = 0 currentLayout.width = root.width - (isHorizontal && toolBox && !plasmoid.immutable ? toolBox.width : 0) currentLayout.height = root.height - (!isHorizontal && toolBox && !plasmoid.immutable ? toolBox.height : 0) currentLayout.isLayoutHorizontal = isHorizontal } } //FIXME: I don't see other ways at the moment a way to see when the UI is REALLY ready Timer { id: startupTimer interval: 4000 onTriggered: { for (var i = 0; i < currentLayout.children.length; ++i) { var item = currentLayout.children[i]; if (item.hasOwnProperty("animationsEnabled")) { item.animationsEnabled = true; } } } } //END UI elements } diff --git a/desktoppackage/contents/activitymanager/ActivityItem.qml b/desktoppackage/contents/activitymanager/ActivityItem.qml index 79804adbf..6938a6f3e 100644 --- a/desktoppackage/contents/activitymanager/ActivityItem.qml +++ b/desktoppackage/contents/activitymanager/ActivityItem.qml @@ -1,335 +1,335 @@ import QtQuick 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddonsComponents import org.kde.plasma.activityswitcher 1.0 as ActivitySwitcher import org.kde.activities 0.1 as Activities import org.kde.activities.settings 0.1 import "static.js" as S Item { id: root property int innerPadding : units.largeSpacing property bool current : false property bool selected : false property bool stoppable : true property alias title : title.text property alias icon : icon.source property alias hasWindows : hasWindowsIndicator.visible z : current ? 10 : selected ? 5 : 0 property string activityId : "" property string background : "" - onBackgroundChanged: if (background[0] != '#') { + onBackgroundChanged: if (background[0] !== '#') { // We have a proper wallpaper, hurroo! backgroundColor.visible = false; } else { // We have only a color backgroundColor.color = background; backgroundColor.visible = true; } signal clicked width : 200 // height : width * 1 / units.displayAspectRatio // Marco removed displayAspectRatio height : width * 9.0 / 16.0 Item { anchors { fill: parent } // Background until we get something real Rectangle { id: backgroundColor anchors.fill: parent // This is intentional - while waiting for the wallpaper, // we are showing a semi-transparent black background color: "black" opacity: root.selected ? .8 : .5 } Image { id: backgroundWallpaper anchors.fill: parent visible: !backgroundColor.visible source: "image://wallpaperthumbnail/" + background sourceSize: Qt.size(width, height) } // Title and the icon Rectangle { id: shade width: parent.height height: parent.width anchors.centerIn: parent rotation: 90 gradient: Gradient { GradientStop { position: 1.0; color: "black" } GradientStop { position: 0.0; color: "transparent" } } opacity : root.selected ? 0.5 : 1.0 } Rectangle { id: highlight visible: root.current border.width: root.current ? units.smallSpacing : 0 border.color: theme.highlightColor anchors { fill: parent // Hide the rounding error on the bottom of the rectangle bottomMargin: -1 } color: "transparent" // z: 1 } Item { id: titleBar anchors { top : parent.top left : parent.left right : parent.right leftMargin : 2 * units.smallSpacing + 2 topMargin : 2 * units.smallSpacing } Text { id: title color : "white" elide : Text.ElideRight visible : shade.visible font.bold : true anchors { top : parent.top left : parent.left right : icon.left } } Text { id: description color : "white" elide : Text.ElideRight text : model.description opacity : .6 anchors { top : title.bottom left : parent.left right : icon.left } } PlasmaCore.IconItem { id: icon width : units.iconSizes.medium height : width anchors { right : parent.right rightMargin : 2 * units.smallSpacing } } } Column { id: statsBar height: childrenRect.height + units.smallSpacing anchors { bottom : controlBar.top left : parent.left right : parent.right leftMargin : 2 * units.smallSpacing + 2 rightMargin : 2 * units.smallSpacing bottomMargin : units.smallSpacing } PlasmaCore.IconItem { id : hasWindowsIndicator source : "window-duplicate" width : 16 height : width opacity : .6 visible : false } Text { id: lastUsedDate color : "white" elide : Text.ElideRight opacity : .6 text: root.current ? i18nd("plasma_shell_org.kde.plasma.desktop", "Currently being used") : model.lastTimeUsedString } // Text { // id: stats // // color : "white" // elide : Text.ElideRight // opacity : .6 // // text: "6 documents, 2 applications" // visible: false // // anchors { // top : lastUsedDate.bottom // left : parent.left // right : parent.right // } // } } MouseArea { id: hoverArea anchors.fill : parent onClicked : root.clicked() hoverEnabled : true onEntered : S.showActivityItemActionsBar(root) Accessible.name : root.title Accessible.role : Accessible.Button Accessible.selected : root.selected Accessible.onPressAction : root.clicked() } // Controls Item { id: controlBar height: root.state == "showingControls" ? (configButton.height + 4 * units.smallSpacing) : 0 Behavior on height { NumberAnimation { duration: units.longDuration } } Behavior on opacity { NumberAnimation { duration: units.shortDuration } } clip: true anchors { bottom : parent.bottom left : parent.left right : parent.right } Rectangle { anchors { fill: parent margins: - 2 * units.smallSpacing } opacity: .75 color: theme.backgroundColor } PlasmaComponents.Button { id: configButton iconSource: "configure" tooltip: i18nd("plasma_shell_org.kde.plasma.desktop", "Configure") onClicked: ActivitySettings.configureActivity(root.activityId); anchors { left : parent.left top : parent.top leftMargin : 2 * units.smallSpacing + 2 topMargin : 2 * units.smallSpacing } } PlasmaComponents.Button { id: stopButton iconSource: "process-stop" tooltip: i18nd("plasma_shell_org.kde.plasma.desktop", "Stop activity") onClicked: ActivitySwitcher.Backend.stopActivity(activityId); anchors { right : parent.right top : parent.top rightMargin : 2 * units.smallSpacing + 2 topMargin : 2 * units.smallSpacing } } } } states: [ State { name: "plain" PropertyChanges { target: shade; visible: true } PropertyChanges { target: controlBar; opacity: 0 } }, State { name: "showingControls" PropertyChanges { target: shade; visible: true } PropertyChanges { target: controlBar; opacity: 1 } } ] transitions: [ Transition { NumberAnimation { properties : "opacity" duration : units.shortDuration } } ] } diff --git a/desktoppackage/contents/activitymanager/ActivityList.qml b/desktoppackage/contents/activitymanager/ActivityList.qml index 469b0b44e..3feb23fb9 100644 --- a/desktoppackage/contents/activitymanager/ActivityList.qml +++ b/desktoppackage/contents/activitymanager/ActivityList.qml @@ -1,209 +1,209 @@ /* vim:set foldmethod=marker: * * Copyright (C) 2014 Ivan Cukic * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * or (at your option) any later version, as published by the Free * Software Foundation * * 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. */ import QtQuick 2.2 import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.activities 0.1 as Activities import org.kde.plasma.activityswitcher 1.0 as ActivitySwitcher Flickable { id: root // contentWidth: content.width contentHeight: content.height property var model: ActivitySwitcher.Backend.runningActivitiesModel() property string filterString: "" property bool showSwitcherOnly: false property int itemsWidth: 0 property int selectedIndex: -1 function _selectRelativeToCurrent(distance) { var startingWithSelected = selectedIndex; do { selectedIndex += distance; if (selectedIndex >= activitiesList.count) { selectedIndex = 0; } if (selectedIndex < 0) { selectedIndex = activitiesList.count - 1; } // Searching for the first item that is visible, or back to the one // that we started with } while (!activitiesList.itemAt(selectedIndex).visible - && startingWithSelected != selectedIndex); + && startingWithSelected !== selectedIndex); _updateSelectedItem(); } function selectNext() { _selectRelativeToCurrent(1); } function selectPrevious() { _selectRelativeToCurrent(-1); } function _updateSelectedItem() { for (var i = 0; i < activitiesList.count; i++) { - activitiesList.itemAt(i).selected = (i == selectedIndex); + activitiesList.itemAt(i).selected = (i === selectedIndex); } } function openSelected() { var selectedItem = null; if (selectedIndex >= 0 && selectedIndex < activitiesList.count) { selectedItem = activitiesList.itemAt(selectedIndex); } else if (root.filterString != "") { // If we have only one item shown, activate it. It doesn't matter // that it is not really selected for (var i = 0; i < activitiesList.count; i++) { var item = activitiesList.itemAt(i); if (item.visible) { selectedItem = item; break; } } } - if (selectedItem != null) { + if (selectedItem !== null) { ActivitySwitcher.Backend.setCurrentActivity(selectedItem.activityId); } } Column { id: content // width: root.width - (root.width % 10) width: root.itemsWidth spacing: units.smallSpacing * 2 // Running activities Repeater { id: activitiesList model: ActivitySwitcher.Backend.runningActivitiesModel() ActivityItem { width: content.width visible : (root.filterString == "") || (title.toLowerCase().indexOf(root.filterString) != -1) activityId : model.id title : model.name icon : model.iconSource background : model.background current : model.isCurrent hasWindows : model.hasWindows innerPadding : 2 * units.smallSpacing stoppable : activitiesList.count > 1 onClicked : { ActivitySwitcher.Backend.setCurrentActivity(model.id); } } } // Stopped activities Item { // spacer width : parent.width height : units.largeSpacing } PlasmaExtras.Heading { id: stoppedActivitiesHeading text: i18nd("plasma_shell_org.kde.plasma.desktop", "Stopped activities:") level: 3 visible: !root.showSwitcherOnly && stoppedActivitiesList.count > 0 } Repeater { id: stoppedActivitiesList model: root.showSwitcherOnly ? null : ActivitySwitcher.Backend.stoppedActivitiesModel() delegate: StoppedActivityItem { id: stoppedActivityItem width: parent.width visible : (root.filterString == "") || (title.toLowerCase().indexOf(root.filterString) != -1) activityId : model.id title : model.name icon : model.iconSource innerPadding : 2 * units.smallSpacing onClicked: { ActivitySwitcher.Backend.setCurrentActivity(model.id) } } } Item { // spacer width : parent.width height : units.largeSpacing * 2 visible: stoppedActivitiesHeading.visible } add: Transition { NumberAnimation { properties: "x" from: -100 duration: units.shortDuration } } move: Transition { NumberAnimation { id: animation properties: "y" duration: units.longDuration } } } } diff --git a/desktoppackage/contents/activitymanager/ActivityManager.qml b/desktoppackage/contents/activitymanager/ActivityManager.qml index b5256beae..c57a94c04 100644 --- a/desktoppackage/contents/activitymanager/ActivityManager.qml +++ b/desktoppackage/contents/activitymanager/ActivityManager.qml @@ -1,170 +1,170 @@ /* * Copyright 2013 Marco Martin * Copyright 2014 Ivan Cukic * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library 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. */ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 import org.kde.activities 0.1 as Activities import org.kde.activities.settings 0.1 FocusScope { id: root signal closed() function parentClosed() { activityBrowser.parentClosed(); } //this is used to perfectly align the filter field and delegates property int cellWidth: theme.mSize(theme.defaultFont).width * 30 property int spacing: 2 * units.smallSpacing property bool showSwitcherOnly: false width: units.gridUnit * 16 Item { id: activityBrowser property int spacing: 2 * units.smallSpacing signal closeRequested() Keys.onPressed: { - if (event.key == Qt.Key_Escape) { + if (event.key === Qt.Key_Escape) { if (heading.searchString.length > 0) { heading.searchString = ""; } else { activityBrowser.closeRequested(); } - } else if (event.key == Qt.Key_Up) { + } else if (event.key === Qt.Key_Up) { activityList.selectPrevious(); - } else if (event.key == Qt.Key_Down) { + } else if (event.key === Qt.Key_Down) { activityList.selectNext(); - } else if (event.key == Qt.Key_Return || event.key == Qt.Key_Enter) { + } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { activityList.openSelected(); - } else if (event.key == Qt.Key_Tab) { + } else if (event.key === Qt.Key_Tab) { // console.log("TAB KEY"); } else { // console.log("OTHER KEY"); // event.accepted = false; // heading.forceActiveFocus(); } } // Rectangle { // anchors.fill : parent // opacity : .4 // color : "white" // } Heading { id: heading anchors { top: parent.top left: parent.left right: parent.right leftMargin: units.smallSpacing rightMargin: units.smallSpacing } onCloseRequested: activityBrowser.closeRequested() Component.onCompleted: focusSearch() visible: !root.showSwitcherOnly } PlasmaExtras.ScrollArea { anchors { top: heading.visible ? heading.bottom : parent.top bottom: bottomPanel.visible ? bottomPanel.top : parent.bottom left: parent.left right: parent.right topMargin: activityBrowser.spacing } ActivityList { id: activityList showSwitcherOnly: root.showSwitcherOnly filterString: heading.searchString.toLowerCase() itemsWidth: root.width - units.smallSpacing } } Item { id: bottomPanel height: newActivityButton.height + units.largeSpacing visible: !root.showSwitcherOnly anchors { bottom: parent.bottom left: parent.left right: parent.right } PlasmaComponents.ToolButton { id: newActivityButton text: i18nd("plasma_shell_org.kde.plasma.desktop", "Create activity...") iconSource: "list-add" width: parent.width onClicked: ActivitySettings.newActivity() visible: ActivitySettings.newActivityAuthorized opacity: newActivityDialog.status == Loader.Ready ? 1 - newActivityDialog.item.opacity : 1 } Loader { id: newActivityDialog z: 100 anchors.bottom: newActivityButton.bottom anchors.left: newActivityButton.left anchors.right: newActivityButton.right } } onCloseRequested: root.closed() anchors.fill: parent } } diff --git a/desktoppackage/contents/activitymanager/Heading.qml b/desktoppackage/contents/activitymanager/Heading.qml index 882ca5847..bd913e220 100644 --- a/desktoppackage/contents/activitymanager/Heading.qml +++ b/desktoppackage/contents/activitymanager/Heading.qml @@ -1,120 +1,120 @@ /* vim:set foldmethod=marker: * * Copyright (C) 2014 Ivan Cukic * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * or (at your option) any later version, as published by the Free * Software Foundation * * 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. */ import QtQuick 2.2 import QtQuick.Layouts 1.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.activities.settings 0.1 Item { id: root property alias searchString: searchText.text property bool showingSearch: false signal closeRequested function focusSearch() { searchText.forceActiveFocus() } onShowingSearchChanged: if (!showingSearch) searchText.text = "" Keys.onPressed: { - if (event.key == Qt.Key_Escape) { + if (event.key === Qt.Key_Escape) { if (root.showingSearch) { event.accepted = true; root.showingSearch = false; } } } height: childrenRect.height RowLayout { id: buttonRow anchors { top: parent.top left: parent.left right: parent.right } Item { PlasmaExtras.Title { id: heading anchors.fill: parent text: i18nd("plasma_shell_org.kde.plasma.desktop", "Activities") elide: Text.ElideRight visible: !root.showingSearch } PlasmaComponents.TextField { id: searchText anchors.fill: parent focus: true clearButtonShown: true visible: root.showingSearch placeholderText: i18nd("plasma_shell_org.kde.plasma.desktop", "Search...") onTextChanged: if (text != "") root.showingSearch = true } Layout.fillWidth: true Layout.fillHeight: true } PlasmaComponents.ToolButton { id: searchButton iconSource: "edit-find" // checkable: true // onClicked: root.closeRequested() onClicked: root.showingSearch = !root.showingSearch checked: root.showingSearch } PlasmaComponents.ToolButton { id: configureButton iconSource: "configure" onClicked: { ActivitySettings.configureActivities(); root.closeRequested(); } } PlasmaComponents.ToolButton { id: closeButton iconSource: "window-close" onClicked: root.closeRequested() } } } diff --git a/desktoppackage/contents/applet/DefaultCompactRepresentation.qml b/desktoppackage/contents/applet/DefaultCompactRepresentation.qml index 9f4cb3a48..e7292d947 100644 --- a/desktoppackage/contents/applet/DefaultCompactRepresentation.qml +++ b/desktoppackage/contents/applet/DefaultCompactRepresentation.qml @@ -1,69 +1,69 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore PlasmaCore.IconItem { id: icon - readonly property bool inPanel: (plasmoid.location == PlasmaCore.Types.TopEdge - || plasmoid.location == PlasmaCore.Types.RightEdge - || plasmoid.location == PlasmaCore.Types.BottomEdge - || plasmoid.location == PlasmaCore.Types.LeftEdge) + readonly property bool inPanel: (plasmoid.location === PlasmaCore.Types.TopEdge + || plasmoid.location === PlasmaCore.Types.RightEdge + || plasmoid.location === PlasmaCore.Types.BottomEdge + || plasmoid.location === PlasmaCore.Types.LeftEdge) Layout.minimumWidth: { switch (plasmoid.formFactor) { case PlasmaCore.Types.Vertical: return 0; case PlasmaCore.Types.Horizontal: return height; default: return units.gridUnit * 3; } } Layout.minimumHeight: { switch (plasmoid.formFactor) { case PlasmaCore.Types.Vertical: return width; case PlasmaCore.Types.Horizontal: return 0; default: return units.gridUnit * 3; } } Layout.maximumWidth: inPanel ? units.iconSizeHints.panel : -1; Layout.maximumHeight: inPanel ? units.iconSizeHints.panel : -1; source: plasmoid.icon ? plasmoid.icon : "plasma" active: mouseArea.containsMouse MouseArea { id: mouseArea property bool wasExpanded: false anchors.fill: parent hoverEnabled: true onPressed: wasExpanded = plasmoid.expanded onClicked: plasmoid.expanded = !wasExpanded } } diff --git a/desktoppackage/contents/configuration/ConfigCategoryDelegate.qml b/desktoppackage/contents/configuration/ConfigCategoryDelegate.qml index 7869b3848..256fa7c5f 100644 --- a/desktoppackage/contents/configuration/ConfigCategoryDelegate.qml +++ b/desktoppackage/contents/configuration/ConfigCategoryDelegate.qml @@ -1,149 +1,149 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.3 as QtControls import QtQuick.Window 2.2 import org.kde.kquickcontrolsaddons 2.0 import org.kde.kirigami 2.5 as Kirigami MouseArea { id: delegate //BEGIN properties implicitWidth: delegateContents.implicitWidth + 4 * units.smallSpacing implicitHeight: delegateContents.height + units.smallSpacing * 4 Layout.fillWidth: true hoverEnabled: true - property bool current: (model.kcm && pageStack.currentItem.kcm && model.kcm == pageStack.currentItem.kcm) || (model.source == pageStack.sourceFile) + property bool current: (model.kcm && pageStack.currentItem.kcm && model.kcm == pageStack.currentItem.kcm) || (model.source === pageStack.sourceFile) //END properties //BEGIN functions function openCategory() { if (current) { return; } if (typeof(categories.currentItem) !== "undefined") { pageStack.invertAnimations = (categories.currentItem.y > delegate.y); categories.currentItem = delegate; } if (model.source) { pageStack.sourceFile = model.source; } else if (model.kcm) { pageStack.sourceFile = ""; pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml"); pageStack.currentItem.kcm = model.kcm; } else { pageStack.sourceFile = ""; } pageStack.title = model.name } //END functions //BEGIN connections onPressed: { categoriesScroll.forceActiveFocus() if (current) { return; } //print("model source: " + model.source + " " + pageStack.sourceFile); if (applyButton.enabled) { messageDialog.delegate = delegate; messageDialog.open(); return; } openCategory(); } onCurrentChanged: { if (current) { categories.currentItem = delegate; } } //END connections //BEGIN UI components Rectangle { anchors.fill: parent color: Kirigami.Theme.highlightColor opacity: { // try to match Breeze style hover handling var active = categoriesScroll.activeFocus && Window.active if (current) { if (active) { return 1 } else if (delegate.containsMouse) { return 0.6 } else { return 0.3 } } else if (delegate.containsMouse) { if (active) { return 0.3 } else { return 0.1 } } return 0 } Behavior on opacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } ColumnLayout { id: delegateContents spacing: units.smallSpacing width: parent.width anchors.verticalCenter: parent.verticalCenter QIconItem { id: iconItem Layout.alignment: Qt.AlignHCenter width: units.iconSizes.medium height: width icon: model.icon state: current && categoriesScroll.activeFocus ? QIconItem.SelectedState : QIconItem.DefaultState } QtControls.Label { id: nameLabel Layout.fillWidth: true Layout.leftMargin: units.smallSpacing Layout.rightMargin: units.smallSpacing text: model.name wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter color: current && categoriesScroll.activeFocus ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor Behavior on color { ColorAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } } //END UI components } diff --git a/desktoppackage/contents/configuration/ConfigurationContainmentActions.qml b/desktoppackage/contents/configuration/ConfigurationContainmentActions.qml index b0e01acd1..2b1c0e279 100644 --- a/desktoppackage/contents/configuration/ConfigurationContainmentActions.qml +++ b/desktoppackage/contents/configuration/ConfigurationContainmentActions.qml @@ -1,170 +1,170 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.3 as QtControls import QtQuick.Layouts 1.0 Item { id: root signal configurationChanged implicitWidth: mainColumn.implicitWidth implicitHeight: mainColumn.implicitHeight property var prettyStrings: { "LeftButton": i18nd("plasma_shell_org.kde.plasma.desktop", "Left-Button"), "RightButton": i18nd("plasma_shell_org.kde.plasma.desktop", "Right-Button"), "MidButton": i18nd("plasma_shell_org.kde.plasma.desktop", "Middle-Button"), "BackButton": i18nd("plasma_shell_org.kde.plasma.desktop", "Back-Button"), "ForwardButton": i18nd("plasma_shell_org.kde.plasma.desktop", "Forward-Button"), "wheel:Vertical": i18nd("plasma_shell_org.kde.plasma.desktop", "Vertical-Scroll"), "wheel:Horizontal": i18nd("plasma_shell_org.kde.plasma.desktop", "Horizontal-Scroll"), "ShiftModifier": i18nd("plasma_shell_org.kde.plasma.desktop", "Shift"), "ControlModifier": i18nd("plasma_shell_org.kde.plasma.desktop", "Ctrl"), "AltModifier": i18nd("plasma_shell_org.kde.plasma.desktop", "Alt"), "MetaModifier": i18nd("plasma_shell_org.kde.plasma.desktop", "Meta") } function saveConfig() { configDialog.currentContainmentActionsModel.save(); } Connections { target: configDialog.currentContainmentActionsModel onConfigurationChanged: root.configurationChanged() } GridLayout { id: mainColumn flow: GridLayout.TopToBottom y: 25 width: parent.width Repeater { id: actionsRepeater model: configDialog.currentContainmentActionsModel MouseEventInputButton { Layout.column: 0 Layout.row: index Layout.fillWidth: true Layout.minimumWidth: implicitWidth defaultText: { var splitAction = model.action.split(';'); var button = splitAction[0]; var modifiers = (splitAction[1] || "").split('|').filter(function (item) { return item !== "NoModifier"; }); var parts = modifiers; modifiers.push(button); return parts.map(function (item) { return prettyStrings[item] || item; }).join(i18nc("Concatenation sign for shortcuts, e.g. Ctrl+Shift", "+")); } eventString: model.action onEventStringChanged: { configDialog.currentContainmentActionsModel.update(index, eventString, model.pluginName); } } } Repeater { model: configDialog.currentContainmentActionsModel QtControls.ComboBox { id: pluginsCombo // "index" argument of onActivated shadows the model index readonly property int pluginIndex: index Layout.fillWidth: true Layout.column: 1 Layout.row: index // both MouseEventInputButton and this ComboBox have fillWidth for a uniform layout // however, their implicit sizes is taken into account and they compete against // each other for available space. By setting an insane preferredWidth we give // ComboBox a greater share of the available space Layout.preferredWidth: 9000 model: configDialog.containmentActionConfigModel textRole: "name" property bool initialized: false Component.onCompleted: { for (var i = 0; i < configDialog.containmentActionConfigModel.count; ++i) { - if (configDialog.containmentActionConfigModel.get(i).pluginName == pluginName) { + if (configDialog.containmentActionConfigModel.get(i).pluginName === pluginName) { pluginsCombo.currentIndex = i; break; } } pluginsCombo.initialized = true; } onActivated: { if (initialized) { var newPluginName = configDialog.containmentActionConfigModel.get(index).pluginName; - if (newPluginName != pluginName) { + if (newPluginName !== pluginName) { configDialog.currentContainmentActionsModel.update(pluginIndex, action, newPluginName); } } } } } Repeater { model: configDialog.currentContainmentActionsModel RowLayout { Layout.column: 2 Layout.row: index QtControls.Button { icon.name: "configure" width: height enabled: model.hasConfigurationInterface onClicked: { configDialog.currentContainmentActionsModel.showConfiguration(index, this); } } QtControls.Button { icon.name: "dialog-information" width: height onClicked: { configDialog.currentContainmentActionsModel.showAbout(index, this); } } QtControls.Button { icon.name: "list-remove" width: height onClicked: { configDialog.currentContainmentActionsModel.remove(index); } } } } MouseEventInputButton { defaultText: i18nd("plasma_shell_org.kde.plasma.desktop", "Add Action"); onEventStringChanged: { configDialog.currentContainmentActionsModel.append(eventString, "org.kde.contextmenu"); } } } } diff --git a/desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml b/desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml index be37da232..206bb1fa7 100644 --- a/desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml +++ b/desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml @@ -1,196 +1,196 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import org.kde.plasma.configuration 2.0 import QtQuick.Controls 2.3 as QtControls import QtQuick.Layouts 1.1 import org.kde.kconfig 1.0 // for KAuthorized import org.kde.plasma.private.shell 2.0 as ShellPrivate // for WallpaperPlugin import org.kde.kirigami 2.5 as Kirigami ColumnLayout { id: root property int formAlignment: wallpaperComboBox.Kirigami.ScenePosition.x - root.Kirigami.ScenePosition.x + (units.largeSpacing/2) property string currentWallpaper: "" property string containmentPlugin: "" signal configurationChanged //BEGIN functions function saveConfig() { if (main.currentItem.saveConfig) { main.currentItem.saveConfig() } for (var key in configDialog.wallpaperConfiguration) { if (main.currentItem["cfg_"+key] !== undefined) { configDialog.wallpaperConfiguration[key] = main.currentItem["cfg_"+key] } } configDialog.currentWallpaper = root.currentWallpaper; configDialog.applyWallpaper() configDialog.containmentPlugin = root.containmentPlugin } //END functions Component.onCompleted: { for (var i = 0; i < configDialog.containmentPluginsConfigModel.count; ++i) { var data = configDialog.containmentPluginsConfigModel.get(i); - if (configDialog.containmentPlugin == data.pluginName) { + if (configDialog.containmentPlugin === data.pluginName) { pluginComboBox.currentIndex = i pluginComboBox.activated(i); break; } } for (var i = 0; i < configDialog.wallpaperConfigModel.count; ++i) { var data = configDialog.wallpaperConfigModel.get(i); - if (configDialog.currentWallpaper == data.pluginName) { + if (configDialog.currentWallpaper === data.pluginName) { wallpaperComboBox.currentIndex = i wallpaperComboBox.activated(i); break; } } } Kirigami.InlineMessage { visible: plasmoid.immutable || animating text: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout cannot be changed while widgets are locked") showCloseButton: true Layout.fillWidth: true Layout.leftMargin: Kirigami.Units.smallSpacing Layout.rightMargin: Kirigami.Units.smallSpacing } Kirigami.FormLayout { Layout.fillWidth: true QtControls.ComboBox { id: pluginComboBox Layout.preferredWidth: Math.max(implicitWidth, wallpaperComboBox.implicitWidth) Kirigami.FormData.label: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout:") enabled: !plasmoid.immutable model: configDialog.containmentPluginsConfigModel width: theme.mSize(theme.defaultFont).width * 24 textRole: "name" onActivated: { var model = configDialog.containmentPluginsConfigModel.get(currentIndex) root.containmentPlugin = model.pluginName root.configurationChanged() } } RowLayout { Layout.fillWidth: true visible: !switchContainmentWarning.visible Kirigami.FormData.label: i18nd("plasma_shell_org.kde.plasma.desktop", "Wallpaper Type:") QtControls.ComboBox { id: wallpaperComboBox Layout.preferredWidth: Math.max(implicitWidth, pluginComboBox.implicitWidth) model: configDialog.wallpaperConfigModel width: theme.mSize(theme.defaultFont).width * 24 textRole: "name" onActivated: { var model = configDialog.wallpaperConfigModel.get(currentIndex) root.currentWallpaper = model.pluginName configDialog.currentWallpaper = model.pluginName main.sourceFile = model.source root.configurationChanged() } } QtControls.Button { icon.name: "get-hot-new-stuff" text: i18nd("plasma_shell_org.kde.plasma.desktop", "Get New Plugins...") visible: KAuthorized.authorize("ghns") onClicked: wallpaperPlugin.getNewWallpaperPlugin(this) Layout.preferredHeight: wallpaperComboBox.height ShellPrivate.WallpaperPlugin { id: wallpaperPlugin } } } } ColumnLayout { id: switchContainmentWarning Layout.fillWidth: true - visible: configDialog.containmentPlugin != root.containmentPlugin + visible: configDialog.containmentPlugin !== root.containmentPlugin QtControls.Label { Layout.fillWidth: true text: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout changes must be applied before other changes can be made") wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter } QtControls.Button { Layout.alignment: Qt.AlignHCenter text: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply now") onClicked: saveConfig() } Binding { target: categoriesScroll //from parent scope AppletConfiguration property: "enabled" value: !switchContainmentWarning.visible } } Item { Layout.fillHeight: true visible: switchContainmentWarning.visible } Item { id: emptyConfig } QtControls.StackView { id: main Layout.fillHeight: true; Layout.fillWidth: true; visible: !switchContainmentWarning.visible // Bug 360862: if wallpaper has no config, sourceFile will be "" // so we wouldn't load emptyConfig and break all over the place // hence set it to some random value initially property string sourceFile: "tbd" onSourceFileChanged: { if (sourceFile) { var props = {} var wallpaperConfig = configDialog.wallpaperConfiguration for (var key in wallpaperConfig) { props["cfg_" + key] = wallpaperConfig[key] } var newItem = replace(Qt.resolvedUrl(sourceFile), props) for (var key in wallpaperConfig) { var changedSignal = newItem["cfg_" + key + "Changed"] if (changedSignal) { changedSignal.connect(root.configurationChanged) } } } else { replace(emptyConfig) } } } } diff --git a/desktoppackage/contents/configuration/PanelConfiguration.qml b/desktoppackage/contents/configuration/PanelConfiguration.qml index cf6890f01..0e11a964d 100644 --- a/desktoppackage/contents/configuration/PanelConfiguration.qml +++ b/desktoppackage/contents/configuration/PanelConfiguration.qml @@ -1,178 +1,178 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.configuration 2.0 import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import "panelconfiguration" //TODO: all of this will be done with desktop components PlasmaCore.FrameSvgItem { id: dialogRoot signal closeContextMenu //BEGIN Properties width: 640 height: 64 imagePath: "dialogs/background" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true state: { switch (panel.location) { case PlasmaCore.Types.TopEdge: return "TopEdge" case PlasmaCore.Types.LeftEdge: return "LeftEdge" case PlasmaCore.Types.RightEdge: return "RightEdge" case PlasmaCore.Types.BottomEdge: default: return "BottomEdge" } } - property bool vertical: (panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge) + property bool vertical: (panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge) //END properties //BEGIN Connections Connections { target: panel onOffsetChanged: ruler.offset = panel.offset onMinimumLengthChanged: ruler.minimumLength = panel.minimumLength onMaximumLengthChanged: ruler.maximumLength = panel.maximumLength } Connections { target: plasmoid onImmutableChanged: configDialog.close() } //END Connections //BEGIN UI components Ruler { id: ruler state: dialogRoot.state } ToolBar { id: toolBar } //END UI components //BEGIN Animations //when EdgeHandle is released animate to old panel position ParallelAnimation { id: panelResetAnimation NumberAnimation { target: panel - properties: (panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge) ? "x" : "y" + properties: (panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge) ? "x" : "y" to: { switch (panel.location) { case PlasmaCore.Types.TopEdge: return panel.screenGeometry.y + panel.distance case PlasmaCore.Types.LeftEdge: return panel.screenGeometry.x + panel.distance case PlasmaCore.Types.RightEdge: return panel.screenGeometry.x + panel.screenGeometry.width - panel.width - panel.distance case PlasmaCore.Types.BottomEdge: default: return panel.screenGeometry.y + panel.screenGeometry.height - panel.height - panel.distance } } duration: units.shortDuration * 3 } NumberAnimation { target: configDialog - properties: (panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge) ? "x" : "y" + properties: (panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge) ? "x" : "y" to: { switch (panel.location) { case PlasmaCore.Types.TopEdge: return panel.screenGeometry.y + panel.height + panel.distance case PlasmaCore.Types.LeftEdge: return panel.screenGeometry.x + panel.width + panel.distance case PlasmaCore.Types.RightEdge: return panel.screenGeometry.x + panel.screenGeometry.width - panel.width - configDialog.width - panel.distance case PlasmaCore.Types.BottomEdge: default: return panel.screenGeometry.y + panel.screenGeometry.height - panel.height - configDialog.height - panel.distance } } duration: units.shortDuration * 3 } } //END Animations //BEGIN States states: [ State { name: "TopEdge" PropertyChanges { target: dialogRoot enabledBorders: "TopBorder|BottomBorder" } PropertyChanges { target: dialogRoot implicitHeight: ruler.implicitHeight + toolBar.implicitHeight } }, State { name: "BottomEdge" PropertyChanges { target: dialogRoot enabledBorders: "TopBorder|BottomBorder" } PropertyChanges { target: dialogRoot implicitHeight: ruler.implicitHeight + toolBar.implicitHeight } }, State { name: "LeftEdge" PropertyChanges { target: dialogRoot enabledBorders: "LeftBorder|RightBorder" } PropertyChanges { target: dialogRoot implicitWidth: ruler.implicitWidth + toolBar.implicitWidth } }, State { name: "RightEdge" PropertyChanges { target: dialogRoot enabledBorders: "LeftBorder|RightBorder" } PropertyChanges { target: dialogRoot implicitWidth: ruler.implicitWidth + toolBar.implicitWidth } } ] //END States } diff --git a/desktoppackage/contents/configuration/panelconfiguration/MoreSettingsMenu.qml b/desktoppackage/contents/configuration/panelconfiguration/MoreSettingsMenu.qml index 2c919fe68..34b3cede6 100644 --- a/desktoppackage/contents/configuration/panelconfiguration/MoreSettingsMenu.qml +++ b/desktoppackage/contents/configuration/panelconfiguration/MoreSettingsMenu.qml @@ -1,157 +1,157 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.0 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.core 2.0 as PlasmaCore PlasmaCore.Dialog { id: contextMenu visualParent: settingsButton location: plasmoid.location type: PlasmaCore.Dialog.PopupMenu flags: Qt.Popup | Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus mainItem: ColumnLayout { id: menuColumn Layout.minimumWidth: menuColumn.implicitWidth Layout.minimumHeight: menuColumn.implicitHeight spacing: units.smallSpacing LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true PlasmaExtras.Heading { level: 3 text: i18nd("plasma_shell_org.kde.plasma.desktop", "Panel Alignment") } PlasmaComponents.ButtonColumn { spacing: 0 Layout.fillWidth: true PlasmaComponents.ToolButton { anchors { left: parent.left right: parent.right } text: panel.formFactor === PlasmaCore.Types.Vertical ? i18nd("plasma_shell_org.kde.plasma.desktop", "Top") : i18nd("plasma_shell_org.kde.plasma.desktop", "Left") checkable: true - checked: panel.alignment == Qt.AlignLeft + checked: panel.alignment === Qt.AlignLeft onClicked: panel.alignment = Qt.AlignLeft flat: false } PlasmaComponents.ToolButton { anchors { left: parent.left right: parent.right } text: i18nd("plasma_shell_org.kde.plasma.desktop", "Center") checkable: true - checked: panel.alignment == Qt.AlignCenter + checked: panel.alignment === Qt.AlignCenter onClicked: panel.alignment = Qt.AlignCenter flat: false } PlasmaComponents.ToolButton { anchors { left: parent.left right: parent.right } text: panel.formFactor === PlasmaCore.Types.Vertical ? i18nd("plasma_shell_org.kde.plasma.desktop", "Bottom") : i18nd("plasma_shell_org.kde.plasma.desktop", "Right") checkable: true - checked: panel.alignment == Qt.AlignRight + checked: panel.alignment === Qt.AlignRight onClicked: panel.alignment = Qt.AlignRight flat: false } } PlasmaExtras.Heading { level: 3 text: i18nd("plasma_shell_org.kde.plasma.desktop", "Visibility") } PlasmaComponents.ButtonColumn { spacing: 0 Layout.fillWidth: true Layout.minimumWidth: implicitWidth PlasmaComponents.ToolButton { width: Math.max(implicitWidth, parent.width) text: i18nd("plasma_shell_org.kde.plasma.desktop", "Always Visible") checkable: true - checked: configDialog.visibilityMode == 0 + checked: configDialog.visibilityMode === 0 onClicked: configDialog.visibilityMode = 0 flat: false } PlasmaComponents.ToolButton { width: Math.max(implicitWidth, parent.width) text: i18nd("plasma_shell_org.kde.plasma.desktop", "Auto Hide") checkable: true - checked: configDialog.visibilityMode == 1 + checked: configDialog.visibilityMode === 1 onClicked: configDialog.visibilityMode = 1 flat: false } PlasmaComponents.ToolButton { width: Math.max(implicitWidth, parent.width) text: i18nd("plasma_shell_org.kde.plasma.desktop", "Windows Can Cover") checkable: true - checked: configDialog.visibilityMode == 2 + checked: configDialog.visibilityMode === 2 onClicked: configDialog.visibilityMode = 2 flat: false } PlasmaComponents.ToolButton { width: Math.max(implicitWidth, parent.width) text: i18nd("plasma_shell_org.kde.plasma.desktop", "Windows Go Below") checkable: true - checked: configDialog.visibilityMode == 3 + checked: configDialog.visibilityMode === 3 onClicked: configDialog.visibilityMode = 3 flat: false } } PlasmaComponents.ToolButton { Layout.fillWidth: true text: i18nd("plasma_shell_org.kde.plasma.desktop", "Maximize Panel") - iconSource: panel.formFactor == PlasmaCore.Types.Vertical ? "zoom-fit-height" : "zoom-fit-width" + iconSource: panel.formFactor === PlasmaCore.Types.Vertical ? "zoom-fit-height" : "zoom-fit-width" onClicked: panel.maximize(); } PlasmaComponents.ToolButton { Layout.fillWidth: true text: i18nd("plasma_shell_org.kde.plasma.desktop", "Lock Widgets") iconSource: "document-encrypt" onClicked: { plasmoid.action("lock widgets").trigger(); configDialog.close(); } } PlasmaComponents.ToolButton { Layout.fillWidth: true text: i18nd("plasma_shell_org.kde.plasma.desktop", "Remove Panel") iconSource: "delete" onClicked: { contextMenu.visible = false; plasmoid.action("remove").trigger(); } } } function hide() { visible = false; } Component.onCompleted: { dialogRoot.closeContextMenu.connect(hide); } } diff --git a/desktoppackage/contents/configuration/panelconfiguration/Ruler.qml b/desktoppackage/contents/configuration/panelconfiguration/Ruler.qml index b2aa503d3..0f3b89a3e 100644 --- a/desktoppackage/contents/configuration/panelconfiguration/Ruler.qml +++ b/desktoppackage/contents/configuration/panelconfiguration/Ruler.qml @@ -1,431 +1,431 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.configuration 2.0 import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons PlasmaCore.FrameSvgItem { id: root //Those properties get updated by PanelConfiguration.qml whenever a value in the panel changes property alias offset: offsetHandle.value property alias minimumLength: minimumLengthHandle.value property alias maximumLength: maximumLengthHandle.value imagePath: "widgets/containment-controls" state: "BottomEdge" implicitWidth: offsetHandle.width + minimumLengthHandle.width implicitHeight: offsetHandle.height + minimumLengthHandle.height onMinimumLengthChanged: leftMinimumLengthHandle.value = minimumLength onMaximumLengthChanged: leftMaximumLengthHandle.value = maximumLength /* As offset and length have a different meaning in all alignments, the panel shifts on alignment change. * This could result in wrong panel positions (e.g. panel shifted over monitor border). * The fancy version would be a recalculation of all values, so that the panel stays at it's current position, * but this would be error prone and complicated. As the panel alignment is rarely changed, it's not worth it. * The more easy approach is just setting the panel offset to zero. This makes sure the panel has a valid position and size. */ Connections { target: panel onAlignmentChanged: offset = 0 } Component.onCompleted: { offsetHandle.value = panel.offset minimumLengthHandle.value = panel.minimumLength maximumLengthHandle.value = panel.maximumLength leftMinimumLengthHandle.value = panel.minimumLength leftMaximumLengthHandle.value = panel.maximumLength } PlasmaCore.Svg { id: containmentControlsSvg imagePath: "widgets/containment-controls" } PlasmaCore.SvgItem { id: centerMark svg: containmentControlsSvg elementId: dialogRoot.vertical ? "vertical-centerindicator" : "horizontal-centerindicator" - visible: panel.alignment == Qt.AlignCenter + visible: panel.alignment === Qt.AlignCenter width: dialogRoot.vertical ? parent.width : naturalSize.width height: dialogRoot.vertical ? naturalSize.height : parent.height anchors.centerIn: parent } SliderHandle { id: offsetHandle graphicElementName: "offsetslider" onValueChanged: panel.offset = value property int position: (dialogRoot.vertical) ? y : x /* The maximum/minimumPosition values are needed to prevent the user from moving a panel with * center alignment to the left and then drag the position handle to the left. * This would make the panel to go off the monitor: * |<- V -> | * | -> | <- | * ^move this slider to the left */ minimumPosition: { var size = dialogRoot.vertical ? height : width switch(panel.alignment){ case Qt.AlignLeft: return -size / 2 case Qt.AlignRight: return leftMaximumLengthHandle.value - size / 2 default: return panel.maximumLength / 2 - size / 2 } } //Needed for the same reason as above maximumPosition: { var size = dialogRoot.vertical ? height : width var dialogRootSize = dialogRoot.vertical ? dialogRoot.height : dialogRoot.width switch(panel.alignment){ case Qt.AlignLeft: return dialogRootSize - maximumLengthHandle.value - size / 2 case Qt.AlignRight: return dialogRootSize - size / 2 default: return dialogRootSize - panel.maximumLength / 2 - size / 2 } } } /* The maximumPosition value for the right handles and the minimumPosition value for the left handles are * needed to prevent the user from moving a panel with center alignment to the left (right) and then pull one of the * right (left) sliders to the right (left). * Because the left and right sliders are coupled, this would make the left (right) sliders to go off the monitor. * * |<- V -> | * | -> | <- | * ^move this slider to the right * * The other max/min Position values just set a minimum panel size */ SliderHandle { id: minimumLengthHandle alignment: panel.alignment | Qt.AlignLeft - visible: panel.alignment != Qt.AlignRight + visible: panel.alignment !== Qt.AlignRight offset: panel.offset graphicElementName: "minslider" onValueChanged: panel.minimumLength = value minimumPosition: offsetHandle.position + units.gridUnit * 3 maximumPosition: { var dialogRootSize = dialogRoot.vertical ? dialogRoot.height : dialogRoot.width var size = dialogRoot.vertical ? height : width - panel.alignment == Qt.AlignCenter ? Math.min(dialogRootSize - size/2, dialogRootSize + offset * 2 - size/2) : dialogRootSize - size/2 + panel.alignment === Qt.AlignCenter ? Math.min(dialogRootSize - size/2, dialogRootSize + offset * 2 - size/2) : dialogRootSize - size/2 } } SliderHandle { id: maximumLengthHandle alignment: panel.alignment | Qt.AlignLeft - visible: panel.alignment != Qt.AlignRight + visible: panel.alignment !== Qt.AlignRight offset: panel.offset graphicElementName: "maxslider" onValueChanged: panel.maximumLength = value minimumPosition: offsetHandle.position + units.gridUnit * 3 maximumPosition: { var dialogRootSize = dialogRoot.vertical ? dialogRoot.height : dialogRoot.width var size = dialogRoot.vertical ? height : width - panel.alignment == Qt.AlignCenter ? Math.min(dialogRootSize - size/2, dialogRootSize + offset * 2 - size/2) : dialogRootSize - size/2 + panel.alignment === Qt.AlignCenter ? Math.min(dialogRootSize - size/2, dialogRootSize + offset * 2 - size/2) : dialogRootSize - size/2 } } SliderHandle { id: leftMinimumLengthHandle alignment: panel.alignment | Qt.AlignRight - visible: panel.alignment != Qt.AlignLeft + visible: panel.alignment !== Qt.AlignLeft offset: panel.offset graphicElementName: "minslider" onValueChanged: panel.minimumLength = value maximumPosition: offsetHandle.position - units.gridUnit * 3 minimumPosition: { var size = dialogRoot.vertical ? height : width - panel.alignment == Qt.AlignCenter ? Math.max(-size/2, offset*2 - size/2) : -size/2 + panel.alignment === Qt.AlignCenter ? Math.max(-size/2, offset*2 - size/2) : -size/2 } } SliderHandle { id: leftMaximumLengthHandle alignment: panel.alignment | Qt.AlignRight - visible: panel.alignment != Qt.AlignLeft + visible: panel.alignment !== Qt.AlignLeft offset: panel.offset graphicElementName: "maxslider" onValueChanged: panel.maximumLength = value maximumPosition: offsetHandle.position - units.gridUnit * 3 minimumPosition: { var size = dialogRoot.vertical ? height : width - panel.alignment == Qt.AlignCenter ? Math.max(-size/2, offset*2 - size/2) : -size/2 + panel.alignment === Qt.AlignCenter ? Math.max(-size/2, offset*2 - size/2) : -size/2 } } states: [ State { name: "TopEdge" PropertyChanges { target: root prefix: "north" height: root.implicitHeight } AnchorChanges { target: root anchors { top: root.parent.top bottom: undefined left: root.parent.left right: root.parent.right } } AnchorChanges { target: offsetHandle anchors { top: undefined bottom: root.bottom left: undefined right: undefined } } AnchorChanges { target: minimumLengthHandle anchors { top: root.top bottom: undefined left: undefined right: undefined } } AnchorChanges { target: maximumLengthHandle anchors { top: undefined bottom: root.bottom left: undefined right: undefined } } AnchorChanges { target: leftMinimumLengthHandle anchors { top: root.top bottom: undefined left: undefined right: undefined } } AnchorChanges { target: leftMaximumLengthHandle anchors { top: undefined bottom: root.bottom left: undefined right: undefined } } }, State { name: "BottomEdge" PropertyChanges { target: root prefix: "south" height: root.implicitHeight } AnchorChanges { target: root anchors { top: undefined bottom: root.parent.bottom left: root.parent.left right: root.parent.right } } AnchorChanges { target: offsetHandle anchors { top: root.top bottom: undefined left: undefined right: undefined } } AnchorChanges { target: minimumLengthHandle anchors { top: undefined bottom: root.bottom left: undefined right: undefined } } AnchorChanges { target: maximumLengthHandle anchors { top: root.top bottom: undefined left: undefined right: undefined } } AnchorChanges { target: leftMinimumLengthHandle anchors { top: undefined bottom: root.bottom left: undefined right: undefined } } AnchorChanges { target: leftMaximumLengthHandle anchors { top: root.top bottom: undefined left: undefined right: undefined } } }, State { name: "LeftEdge" PropertyChanges { target: root prefix: "west" width: root.implicitWidth } AnchorChanges { target: root anchors { top: root.parent.top bottom: root.parent.bottom left: root.parent.left right: undefined } } AnchorChanges { target: offsetHandle anchors { top: undefined bottom: undefined left: undefined right: root.right } } AnchorChanges { target: minimumLengthHandle anchors { top: undefined bottom: undefined left: root.left right: undefined } } AnchorChanges { target: maximumLengthHandle anchors { top: undefined bottom: undefined left: undefined right: root.right } } AnchorChanges { target: leftMinimumLengthHandle anchors { top: undefined bottom: undefined left: root.left right: undefined } } AnchorChanges { target: leftMaximumLengthHandle anchors { top: undefined bottom: undefined left: undefined right: root.right } } }, State { name: "RightEdge" PropertyChanges { target: root prefix: "east" width: root.implicitWidth } AnchorChanges { target: root anchors { top: root.parent.top bottom: root.parent.bottom left: undefined right: root.parent.right } } AnchorChanges { target: offsetHandle anchors { top: undefined bottom: undefined left: parent.left right: undefined } } AnchorChanges { target: minimumLengthHandle anchors { top: undefined bottom: undefined left: undefined right: parent.right } } AnchorChanges { target: maximumLengthHandle anchors { top: undefined bottom: undefined left: parent.left right: undefined } } AnchorChanges { target: leftMinimumLengthHandle anchors { top: undefined bottom: undefined left: undefined right: parent.right } } AnchorChanges { target: leftMaximumLengthHandle anchors { top: undefined bottom: undefined left: parent.left right: undefined } } } ] } diff --git a/desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml b/desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml index aaad0d4ff..214ab8bff 100644 --- a/desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml +++ b/desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml @@ -1,181 +1,181 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as QQC2 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.configuration 2.0 import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons PlasmaComponents.Button { - readonly property string textLabel: panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge ? i18nd("plasma_shell_org.kde.plasma.desktop", "Width") : i18nd("plasma_shell_org.kde.plasma.desktop", "Height") + readonly property string textLabel: panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge ? i18nd("plasma_shell_org.kde.plasma.desktop", "Width") : i18nd("plasma_shell_org.kde.plasma.desktop", "Height") text: panelResizeHintTimer.running ? panel.thickness : textLabel - readonly property string sizeIcon: panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge ? "resizecol" : "resizerow" + readonly property string sizeIcon: panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge ? "resizecol" : "resizerow" iconSource: sizeIcon checkable: true checked: mel.pressed Timer { id: panelResizeHintTimer interval: 1000 } Connections { target: panel onThicknessChanged: panelResizeHintTimer.restart() } QQC2.ToolTip { id: tooltip visible: false delay: 0 timeout: 10000 contentItem: PlasmaComponents.Label { anchors.fill: parent text: i18nd("plasma_shell_org.kde.plasma.desktop", "Click and drag the button to resize the panel.") horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap color: tooltip.palette.toolTipText } KQuickControlsAddons.MouseEventListener { anchors.fill: parent onPressed: tooltip.visible = false } } KQuickControlsAddons.MouseEventListener { id: mel anchors.fill: parent - cursorShape: panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge ? Qt.SizeHorCursor : Qt.SizeVerCursor + cursorShape: panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge ? Qt.SizeHorCursor : Qt.SizeVerCursor property int startMouseX property int startMouseY onPressed: { dialogRoot.closeContextMenu(); startMouseX = mouse.x startMouseY = mouse.y tooltip.visible = true } onPositionChanged: { switch (panel.location) { case PlasmaCore.Types.TopEdge: var y = Math.min(panel.screenToFollow.geometry.y + panel.screenToFollow.geometry.height/2, mouse.screenY - mapToItem(dialogRoot, 0, startMouseY).y); var thickness = Math.max(units.gridUnit, y - panel.y); if (thickness % 2 != 0) { if (mouse.y > startMouseY) { thickness += 1; y -= 1; } else { thickness -= 1; y += 1; } } configDialog.y = y; panel.thickness = thickness; break; case PlasmaCore.Types.LeftEdge: var x = Math.min(panel.screenToFollow.geometry.x + panel.screenToFollow.geometry.width/2, mouse.screenX - mapToItem(dialogRoot, startMouseX, 0).x); var thickness = Math.max(units.gridUnit, x - panel.x); if (thickness % 2 != 0) { if (mouse.x > startMouseX) { thickness += 1; x += 1; } else { thickness -= 1; x -= 1; } } configDialog.x = x; panel.thickness = thickness; break; case PlasmaCore.Types.RightEdge: var x = Math.max(panel.screenToFollow.geometry.x + panel.screenToFollow.geometry.width/2, mouse.screenX - mapToItem(dialogRoot, startMouseX, 0).x); var thickness = Math.max(units.gridUnit, panel.screenToFollow.geometry.x + panel.screenToFollow.geometry.width - (x + configDialog.width)); if (thickness % 2 != 0) { if (mouse.x > startMouseX) { thickness -= 1; x += 1; } else { thickness += 1; x -= 1; } } configDialog.x = x; panel.thickness = thickness; break; case PlasmaCore.Types.BottomEdge: default: var y = Math.max(panel.screenToFollow.geometry.y + panel.screenToFollow.geometry.height/2, mouse.screenY - mapToItem(dialogRoot, 0, startMouseY).y); var thickness = Math.max(units.gridUnit, panel.screenToFollow.geometry.y + panel.screenToFollow.geometry.height - (y + configDialog.height)); if (thickness % 2 != 0) { if (mouse.y > startMouseY) { thickness -= 1; y += 1; } else { thickness += 1; y -= 1; } } configDialog.y = y; panel.thickness = thickness; } } property int wheelDelta: 0 onWheelMoved: { wheelDelta += wheel.delta; var deltaThickness = 0; // Magic number 120 for common "one click" // See: http://qt-project.org/doc/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop while (wheelDelta >= 120) { wheelDelta -= 120; deltaThickness += 1; } while (wheelDelta <= -120) { wheelDelta += 120; deltaThickness -= 1; } deltaThickness = deltaThickness * 2; var newThickness = Math.max(units.gridUnit, panel.thickness + deltaThickness); - if (panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge) { + if (panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge) { newThickness = Math.min(newThickness, panel.screenToFollow.geometry.width/2); } else { newThickness = Math.min(newThickness, panel.screenToFollow.geometry.height/2); } if (newThickness % 2 != 0) { newThickness -= 1; } panel.thickness = newThickness; panelResetAnimation.running = true; } } } diff --git a/desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml b/desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml index 9b194723b..6a9f00e55 100644 --- a/desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml +++ b/desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml @@ -1,282 +1,282 @@ /* * Copyright 2013 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 1.1 as QQC import QtQuick.Layouts 1.0 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.configuration 2.0 Item { id: root state: parent.state implicitWidth: Math.max(buttonsLayout.width, row.width) + units.smallSpacing * 2 implicitHeight: row.height + 20 readonly property string addWidgetsButtonText: i18nd("plasma_shell_org.kde.plasma.desktop", "Add Widgets...") readonly property string addSpacerButtonText: i18nd("plasma_shell_org.kde.plasma.desktop", "Add Spacer") readonly property string settingsButtonText: i18nd("plasma_shell_org.kde.plasma.desktop", "More Settings...") QQC.Action { shortcut: "Escape" onTriggered: { // avoid leaving the panel in an inconsistent state when escaping while dragging it // "checked" means "pressed" in this case, we abuse that property to make the button look pressed if (edgeHandle.checked || sizeHandle.checked) { return } if (contextMenuLoader.opened) { contextMenuLoader.close() } else { configDialog.close() } } } GridLayout { id: row columns: dialogRoot.vertical ? 1 : 2 rows: dialogRoot.vertical ? 2 : 1 anchors.centerIn: parent rowSpacing: units.smallSpacing columnSpacing: units.smallSpacing EdgeHandle { id: edgeHandle Layout.alignment: Qt.AlignHCenter } SizeHandle { id: sizeHandle Layout.alignment: Qt.AlignHCenter } } PlasmaComponents.Label { id: placeHolder visible: false text: addWidgetsButtonText + addSpacerButtonText + settingsButtonText } Connections { target: configDialog onVisibleChanged: { if (!configDialog.visible) { settingsButton.checked = false } } } GridLayout { id: buttonsLayout rows: 1 columns: 1 - flow: plasmoid.formFactor == PlasmaCore.Types.Horizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight + flow: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight anchors.margins: rowSpacing - property bool showText: plasmoid.formFactor == PlasmaCore.Types.Vertical || (row.x + row.width < root.width - placeHolder.width - units.iconSizes.small*4 - units.largeSpacing*5) + property bool showText: plasmoid.formFactor === PlasmaCore.Types.Vertical || (row.x + row.width < root.width - placeHolder.width - units.iconSizes.small*4 - units.largeSpacing*5) rowSpacing: units.smallSpacing columnSpacing: units.smallSpacing PlasmaComponents.Button { text: buttonsLayout.showText ? root.addWidgetsButtonText : "" tooltip: buttonsLayout.showText ? "" : root.addWidgetsButtonText iconSource: "list-add" Layout.fillWidth: true onClicked: { configDialog.close(); configDialog.showAddWidgetDialog(); } } PlasmaComponents.Button { iconSource: "distribute-horizontal-x" text: buttonsLayout.showText ? root.addSpacerButtonText : "" tooltip: buttonsLayout.showText ? "" : root.addSpacerButtonText Layout.fillWidth: true onClicked: { configDialog.addPanelSpacer(); } } PlasmaComponents.Button { id: settingsButton iconSource: "configure" text: buttonsLayout.showText ? root.settingsButtonText : "" tooltip: buttonsLayout.showText ? "" : root.settingsButtonText Layout.fillWidth: true checkable: true onCheckedChanged: { if (checked) { contextMenuLoader.open() } else { contextMenuLoader.close() } } } PlasmaComponents.ToolButton { - parent: plasmoid.formFactor == PlasmaCore.Types.Horizontal ? buttonsLayout : root - anchors.right: plasmoid.formFactor == PlasmaCore.Types.Horizontal ? undefined : parent.right + parent: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? buttonsLayout : root + anchors.right: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? undefined : parent.right iconSource: "window-close" tooltip: i18nd("plasma_shell_org.kde.plasma.desktop", "Close") onClicked: { configDialog.close() } } Loader { id: contextMenuLoader property bool opened: item && item.visible onOpenedChanged: settingsButton.checked = opened source: "MoreSettingsMenu.qml" active: false function open() { active = true item.visible = true } function close() { if (item) { item.visible = false } } } } //BEGIN States states: [ State { name: "TopEdge" PropertyChanges { target: root height: root.implicitHeight } AnchorChanges { target: root anchors { top: undefined bottom: root.parent.bottom left: root.parent.left right: root.parent.right } } AnchorChanges { target: buttonsLayout anchors { verticalCenter: root.verticalCenter top: undefined bottom: undefined left: undefined right: root.right } } PropertyChanges { target: buttonsLayout width: buttonsLayout.implicitWidth } }, State { name: "BottomEdge" PropertyChanges { target: root height: root.implicitHeight } AnchorChanges { target: root anchors { top: root.parent.top bottom: undefined left: root.parent.left right: root.parent.right } } AnchorChanges { target: buttonsLayout anchors { verticalCenter: root.verticalCenter top: undefined bottom: undefined left: undefined right: root.right } } PropertyChanges { target: buttonsLayout width: buttonsLayout.implicitWidth } }, State { name: "LeftEdge" PropertyChanges { target: root width: root.implicitWidth } AnchorChanges { target: root anchors { top: root.parent.top bottom: root.parent.bottom left: undefined right: root.parent.right } } AnchorChanges { target: buttonsLayout anchors { verticalCenter: undefined top: undefined bottom: root.bottom left: root.left right: root.right } } }, State { name: "RightEdge" PropertyChanges { target: root width: root.implicitWidth } AnchorChanges { target: root anchors { top: root.parent.top bottom: root.parent.bottom left: root.parent.left right: undefined } } AnchorChanges { target: buttonsLayout anchors { verticalCenter: undefined top: undefined bottom: root.bottom left: root.left right: root.right } } } ] //END States } diff --git a/desktoppackage/contents/explorer/AppletAlternatives.qml b/desktoppackage/contents/explorer/AppletAlternatives.qml index 83414427f..2e00624e7 100644 --- a/desktoppackage/contents/explorer/AppletAlternatives.qml +++ b/desktoppackage/contents/explorer/AppletAlternatives.qml @@ -1,192 +1,192 @@ /* * Copyright 2014 Marco Martin * * 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 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 1.0 as QtControls import QtQuick.Layouts 1.1 import QtQuick.Window 2.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.private.shell 2.0 PlasmaCore.Dialog { id: dialog visualParent: alternativesHelper.applet location: alternativesHelper.applet.location Component.onCompleted: { flags = flags | Qt.WindowStaysOnTopHint; dialog.show(); } ColumnLayout { id: root signal configurationChanged Layout.minimumWidth: units.gridUnit * 20 Layout.minimumHeight: Math.min(Screen.height - units.gridUnit * 10, heading.height + buttonsRow.height + mainList.contentHeight + units.gridUnit) LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true property string currentPlugin // we don't want a binding here, just set it to the current plugin once Component.onCompleted: currentPlugin = alternativesHelper.currentPlugin QtControls.Action { shortcut: "Escape" onTriggered: dialog.close() } QtControls.Action { shortcut: "Return" onTriggered: switchButton.clicked(null) } QtControls.Action { shortcut: "Enter" onTriggered: switchButton.clicked(null) } QtControls.Action { shortcut: "Up" onTriggered: mainList.decrementCurrentIndex() } QtControls.Action { shortcut: "Down" onTriggered: mainList.incrementCurrentIndex() } WidgetExplorer { id: widgetExplorer provides: alternativesHelper.appletProvides } PlasmaExtras.Heading { id: heading text: i18nd("plasma_shell_org.kde.plasma.desktop", "Alternative Widgets"); } // HACK for some reason initially setting the index does not work // I tried setting it in Component.onCompleted of either delegate and list // but that did not help either, hence the Timer as a last resort Timer { id: setCurrentIndexTimer property int desiredIndex: 0 interval: 0 onTriggered: mainList.currentIndex = desiredIndex } PlasmaExtras.ScrollArea { id: scrollArea Layout.fillWidth: true Layout.fillHeight: true Layout.preferredHeight: mainList.height ListView { id: mainList model: widgetExplorer.widgetsModel boundsBehavior: Flickable.StopAtBounds highlight: PlasmaComponents.Highlight { id: highlight } highlightMoveDuration : 0 highlightResizeDuration: 0 delegate: PlasmaComponents.ListItem { enabled: true onClicked: mainList.currentIndex = index Component.onCompleted: { if (model.pluginName === alternativesHelper.currentPlugin) { setCurrentIndexTimer.desiredIndex = index setCurrentIndexTimer.restart() } } Connections { target: mainList onCurrentIndexChanged: { if (mainList.currentIndex === index) { root.currentPlugin = model.pluginName } } } RowLayout { x: 2 * units.smallSpacing width: parent.width - 2 * x spacing: units.largeSpacing PlasmaCore.IconItem { Layout.preferredWidth: units.iconSizes.huge Layout.preferredHeight: units.iconSizes.huge source: model.decoration } ColumnLayout { height: parent.height Layout.fillWidth: true PlasmaExtras.Heading { level: 4 Layout.fillWidth: true text: model.name wrapMode: Text.NoWrap elide: Text.ElideRight } PlasmaComponents.Label { Layout.fillWidth: true text: model.description font.pointSize: theme.smallestFont.pointSize maximumLineCount: 2 wrapMode: Text.WordWrap elide: Text.ElideRight } } } } } } RowLayout { id: buttonsRow Layout.fillWidth: true PlasmaComponents.Button { id: switchButton - enabled: root.currentPlugin != alternativesHelper.currentPlugin + enabled: root.currentPlugin !== alternativesHelper.currentPlugin Layout.fillWidth: true text: i18nd("plasma_shell_org.kde.plasma.desktop", "Switch"); onClicked: { if (enabled) { alternativesHelper.loadAlternative(root.currentPlugin); dialog.close(); } } } PlasmaComponents.Button { id: cancelButton Layout.fillWidth: true text: i18nd("plasma_shell_org.kde.plasma.desktop", "Cancel"); onClicked: { dialog.close(); } } } } } diff --git a/desktoppackage/contents/explorer/AppletDelegate.qml b/desktoppackage/contents/explorer/AppletDelegate.qml index 411fd3799..694a4f0c9 100644 --- a/desktoppackage/contents/explorer/AppletDelegate.qml +++ b/desktoppackage/contents/explorer/AppletDelegate.qml @@ -1,234 +1,234 @@ /* * Copyright 2011 Marco Martin * Copyright 2015 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library 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. */ import QtQuick 2.4 import QtQuick.Layouts 1.1 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.draganddrop 2.0 Item { id: delegate readonly property string pluginName: model.pluginName readonly property bool pendingUninstall: pendingUninstallTimer.applets.indexOf(pluginName) > -1 width: list.cellWidth height: list.cellHeight DragArea { anchors.fill: parent supportedActions: Qt.MoveAction | Qt.LinkAction //onDragStarted: tooltipDialog.visible = false delegateImage: decoration enabled: !delegate.pendingUninstall mimeData { source: parent } Component.onCompleted: mimeData.setData("text/x-plasmoidservicename", pluginName) onDragStarted: { kwindowsystem.showingDesktop = true; main.draggingWidget = true; } onDrop: { main.draggingWidget = false; } MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true onDoubleClicked: { if (!delegate.pendingUninstall) { widgetExplorer.addApplet(pluginName) } } onEntered: list.currentIndex = index onExited: list.currentIndex = -1 } ColumnLayout { id: mainLayout spacing: units.smallSpacing anchors { left: parent.left right: parent.right //bottom: parent.bottom margins: units.smallSpacing * 2 rightMargin: units.smallSpacing * 2 // don't cram the text to the border too much top: parent.top } Item { id: iconContainer width: units.iconSizes.enormous height: width anchors.horizontalCenter: parent.horizontalCenter opacity: delegate.pendingUninstall ? 0.6 : 1 Behavior on opacity { OpacityAnimator { duration: units.longDuration easing.type: Easing.InOutQuad } } Item { id: iconWidget anchors.fill: parent PlasmaCore.IconItem { anchors.fill: parent source: model.decoration - visible: model.screenshot == "" + visible: model.screenshot === "" } Image { width: units.iconSizes.enormous height: width anchors.fill: parent fillMode: Image.PreserveAspectFit source: model.screenshot } } Item { id: badgeMask anchors.fill: parent Rectangle { x: Math.round(-units.smallSpacing * 1.5 / 2) y: x width: runningBadge.width + Math.round(units.smallSpacing * 1.5) height: width radius: height visible: running } } Rectangle { id: runningBadge width: height height: Math.round(theme.mSize(countLabel.font).height * 1.3) radius: height color: theme.highlightColor visible: running onVisibleChanged: maskShaderSource.scheduleUpdate() PlasmaComponents.Label { id: countLabel anchors.fill: parent horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter text: running } } ShaderEffect { anchors.fill: parent property var source: ShaderEffectSource { sourceItem: iconWidget hideSource: true live: false } property var mask: ShaderEffectSource { id: maskShaderSource sourceItem: badgeMask hideSource: true live: false } supportsAtlasTextures: true fragmentShader: " varying highp vec2 qt_TexCoord0; uniform highp float qt_Opacity; uniform lowp sampler2D source; uniform lowp sampler2D mask; void main() { gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0 - (texture2D(mask, qt_TexCoord0.st).a)) * qt_Opacity; } " } PlasmaComponents.ToolButton { id: uninstallButton anchors { top: parent.top right: parent.right } iconSource: delegate.pendingUninstall ? "edit-undo" : "list-remove" // we don't really "undo" anything but we'll pretend to the user that we do tooltip: delegate.pendingUninstall ? i18nd("plasma_shell_org.kde.plasma.desktop", "Undo uninstall") : i18nd("plasma_shell_org.kde.plasma.desktop", "Uninstall widget") flat: false visible: model.local onHoveredChanged: { if (hovered) { // hovering the uninstall button triggers onExited of the main mousearea list.currentIndex = index } } onClicked: { var pending = pendingUninstallTimer.applets if (delegate.pendingUninstall) { var index = pending.indexOf(pluginName) if (index > -1) { pending.splice(index, 1) } } else { pending.push(pluginName) } pendingUninstallTimer.applets = pending if (pending.length) { pendingUninstallTimer.restart() } else { pendingUninstallTimer.stop() } } } } PlasmaExtras.Heading { id: heading Layout.fillWidth: true level: 4 text: model.name elide: Text.ElideRight wrapMode: Text.WordWrap maximumLineCount: 2 lineHeight: 0.95 horizontalAlignment: Text.AlignHCenter } PlasmaComponents.Label { Layout.fillWidth: true // otherwise causes binding loop due to the way the Plasma sets the height height: implicitHeight text: model.description font.pointSize: theme.smallestFont.pointSize wrapMode: Text.WordWrap elide: Text.ElideRight maximumLineCount: heading.lineCount === 1 ? 3 : 2 horizontalAlignment: Text.AlignHCenter } } } } diff --git a/kcms/ksplash/package/contents/ui/main.qml b/kcms/ksplash/package/contents/ui/main.qml index 019f4495a..582f0b010 100644 --- a/kcms/ksplash/package/contents/ui/main.qml +++ b/kcms/ksplash/package/contents/ui/main.qml @@ -1,68 +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 choose 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" + visible: model.pluginName !== "None" iconName: "media-playback-start" tooltip: i18n("Preview Splash Screen") 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 Splash Screens...") onClicked: kcm.getNewClicked(); visible: KAuthorized.authorize("ghns") } } } diff --git a/kcms/launch/package/contents/ui/main.qml b/kcms/launch/package/contents/ui/main.qml index d7de3870f..734acca06 100644 --- a/kcms/launch/package/contents/ui/main.qml +++ b/kcms/launch/package/contents/ui/main.qml @@ -1,119 +1,119 @@ /* Copyright (c) 2017 Eike Hein 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 2.2 as QtControls import org.kde.kirigami 2.3 as Kirigami import org.kde.kcm 1.1 SimpleKCM { id: root ConfigModule.quickHelp: i18n("Launch Feedback") ConfigModule.buttons: ConfigModule.Help | ConfigModule.Defaults | ConfigModule.Apply function applyBusyCursorCurrentIndex() { - if (kcm.busyCursorCurrentIndex == 0) { + if (kcm.busyCursorCurrentIndex === 0) { busyCursorDisabled.checked = true; - } else if (kcm.busyCursorCurrentIndex == 1) { + } else if (kcm.busyCursorCurrentIndex === 1) { busyCursorStatic.checked = true; - } else if (kcm.busyCursorCurrentIndex == 2) { + } else if (kcm.busyCursorCurrentIndex === 2) { busyCursorBlinking.checked = true; - } else if (kcm.busyCursorCurrentIndex == 3) { + } else if (kcm.busyCursorCurrentIndex === 3) { busyCursorBouncing.checked = true; } } Kirigami.FormLayout { id: formLayout Connections { target: kcm onBusyCursorCurrentIndexChanged: applyBusyCursorCurrentIndex() onTaskManagerNotificationChanged: taskManagerNotification.checked = kcm.taskManagerNotification onNotificationTimeoutChanged: notificationTimeout.value = kcm.notificationTimeout } QtControls.RadioButton { id: busyCursorDisabled Kirigami.FormData.label: i18n("Cursor:") text: i18n("No Feedback") onToggled: kcm.busyCursorCurrentIndex = 0; } QtControls.RadioButton { id: busyCursorStatic text: i18n("Static") onToggled: kcm.busyCursorCurrentIndex = 1; } QtControls.RadioButton { id: busyCursorBlinking text: i18n("Blinking") onToggled: kcm.busyCursorCurrentIndex = 2; } QtControls.RadioButton { id: busyCursorBouncing text: i18n("Bouncing") onToggled: kcm.busyCursorCurrentIndex = 3; } QtControls.CheckBox { id: taskManagerNotification Kirigami.FormData.label: i18n("Task Manager:") text: i18n("Enable animation") checked: kcm.taskManagerNotification onToggled: kcm.taskManagerNotification = checked } QtControls.SpinBox { id: notificationTimeout Kirigami.FormData.label: i18n("Stop animation after:") stepSize: 1 enabled: taskManagerNotification.checked value: kcm.notificationTimeout onValueChanged: kcm.notificationTimeout = value textFromValue: function(value, locale) { return i18np("%1 sec", "%1 secs", value)} } } Component.onCompleted: applyBusyCursorCurrentIndex() } diff --git a/kcms/lookandfeel/package/contents/ui/main.qml b/kcms/lookandfeel/package/contents/ui/main.qml index afbfe1e8e..cbc45c7c1 100644 --- a/kcms/lookandfeel/package/contents/ui/main.qml +++ b/kcms/lookandfeel/package/contents/ui/main.qml @@ -1,118 +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 choose 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 != "" + 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 Look and Feel Themes...") 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" } } } } diff --git a/kcms/nightcolor/package/contents/ui/NumberField.qml b/kcms/nightcolor/package/contents/ui/NumberField.qml index a678c7cb5..857752b9c 100644 --- a/kcms/nightcolor/package/contents/ui/NumberField.qml +++ b/kcms/nightcolor/package/contents/ui/NumberField.qml @@ -1,48 +1,48 @@ /******************************************************************** Copyright 2017 Roman Gilg 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, see . *********************************************************************/ import QtQuick 2.1 import QtQuick.Controls 1.4 as Controls Controls.TextField { property double backend maximumLength: 10 horizontalAlignment: TextInput.AlignHCenter inputMethodHints: Qt.ImhFormattedNumbersOnly text: backend onBackendChanged: { text = backend; } onTextChanged: { var textFloat = parseFloat(text); - if (textFloat == undefined || isNaN(textFloat)) { + if (textFloat === undefined || isNaN(textFloat)) { return; } backend = textFloat; } onFocusChanged: { var textFloat = parseFloat(text); - if (!focus && (textFloat == undefined || isNaN(textFloat))) { + if (!focus && (textFloat === undefined || isNaN(textFloat))) { text = backend; } } } diff --git a/kcms/nightcolor/package/contents/ui/main.qml b/kcms/nightcolor/package/contents/ui/main.qml index 6dfeae871..45116aaa7 100644 --- a/kcms/nightcolor/package/contents/ui/main.qml +++ b/kcms/nightcolor/package/contents/ui/main.qml @@ -1,362 +1,362 @@ /******************************************************************** Copyright 2017 Roman Gilg 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, see . *********************************************************************/ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.4 as Controls import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.colorcorrect 0.1 as CC Item { id: root implicitHeight: units.gridUnit * 20 property int error: cA.error property bool defaultRequested: false CC.CompositorAdaptor { id: cA } CC.Geolocator { id: locator } CC.SunCalc { id: sunCalc } function calcNeedsSave() { kcm.needsSave = cA.checkStaged(); // If the user changes something manually again after // Default was triggered, only allow a normal // configuration change again: defaultRequested = false; } Connections { target: kcm onLoadRelay: cA.reloadData() onSaveRelay: defaultRequested ? cA.sendConfigurationAll() : cA.sendConfiguration(); onDefaultsRelay: { if (!cA.nightColorAvailable) { return; } activator.checked = cA.activeDefault; tempSlider.value = cA.nightTemperatureDefault; modeSwitcher.currentIndex = cA.modeDefault; // set everything else to default as well cA.latitudeFixedStaged = cA.latitudeFixedDefault; cA.longitudeFixedStaged = cA.longitudeFixedDefault; cA.morningBeginFixedStaged = cA.morningBeginFixedDefault; cA.eveningBeginFixedStaged = cA.eveningBeginFixedDefault; cA.transitionTimeStaged = cA.transitionTimeDefault; kcm.needsSave = cA.checkStagedAll(); defaultRequested = true; } } Connections { target: cA onDataUpdated: calcNeedsSave() onStagedDataReset: { activator.checked = cA.active; tempSlider.value = cA.nightTemperature; modeSwitcher.currentIndex = cA.mode; reset(); calcNeedsSave(); } } signal reset() Item { id: main width: childrenRect.width height: childrenRect.height enabled: cA.nightColorAvailable Controls.CheckBox { id: activator text: i18n("Activate Night Color") checked: cA.active onCheckedChanged: { cA.activeStaged = checked; calcNeedsSave(); } } ColumnLayout { id: mainControls anchors.top: activator.bottom anchors.topMargin: units.largeSpacing enabled: activator.checked Controls.Label { text: i18n("Night Color Temperature: ") + tempSlider.value + i18n(" K") } Controls.Slider { id: tempSlider implicitWidth: units.gridUnit * 15 minimumValue: cA.minimalTemperature maximumValue: cA.neutralTemperature value: cA.nightTemperature stepSize: 100 onValueChanged: { cA.nightTemperatureStaged = value; calcNeedsSave(); } } RowLayout { spacing: units.largeSpacing Controls.Label { text: i18n("Operation mode:") } Controls.ComboBox { id: modeSwitcher width: theme.mSize(theme.defaultFont).width * 9 model: [i18n("Automatic"), i18n("Location"), i18n("Times")] currentIndex: cA.mode onCurrentIndexChanged: { cA.modeStaged = currentIndex; advancedControlLoader.updatePage(currentIndex); calcNeedsSave(); } } } } Loader { id: advancedControlLoader anchors.top: mainControls.bottom anchors.topMargin: units.largeSpacing function updatePage(index) { sourceComponent = undefined; var page; - if (index == CC.CompositorAdaptor.ModeLocation) { + if (index === CC.CompositorAdaptor.ModeLocation) { page = manualLocationsView; - } else if (index == CC.CompositorAdaptor.ModeTimings) { + } else if (index === CC.CompositorAdaptor.ModeTimings) { page = manualTimingsView; } else { page = automaticView; } sourceComponent = page; } } Component { id: automaticView Row { spacing: units.largeSpacing Loader { sourceComponent: TimingsView { latitude: locator.latitude longitude: locator.longitude } } Loader { sourceComponent: LocationsAutoView { latitude: locator.latitude longitude: locator.longitude } } } } Component { id: manualLocationsView Row { id: manualLocationsViewRow spacing: units.largeSpacing signal change() Loader { sourceComponent: TimingsView { latitude: cA.latitudeFixedStaged longitude: cA.longitudeFixedStaged Connections { target: manualLocationsViewRow onChange: { reset(); } } } } Loader { sourceComponent: LocationsFixedView {} } } } Component { id: manualTimingsView Column { spacing: units.smallSpacing GridLayout { id: manualTimingsViewGrid columns: 3 rowSpacing: units.smallSpacing columnSpacing: units.smallSpacing enabled: activator.checked && cA.timingsEnabled Connections { target: root onReset: { mornBeginManField.backend = cA.morningBeginFixed; evenBeginManField.backend = cA.eveningBeginFixed; transTimeField.backend = cA.transitionTime; } } Controls.Label { text: i18n("Sunrise begins") Layout.alignment: Qt.AlignRight } TimeField { id: mornBeginManField backend: cA.morningBeginFixedStaged onBackendChanged: {cA.morningBeginFixedStaged = backend; calcNeedsSave(); } } Controls.Label { enabled: false text: i18n("(HH:MM)") } Controls.Label { text: i18n("Sunset begins") Layout.alignment: Qt.AlignRight } TimeField { id: evenBeginManField backend: cA.eveningBeginFixedStaged onBackendChanged: {cA.eveningBeginFixedStaged = backend; calcNeedsSave(); } } Controls.Label { enabled: false text: i18n("(HH:MM)") } Controls.Label { text: i18n("Transition duration") Layout.alignment: Qt.AlignRight } NumberField { id: transTimeField backend: cA.transitionTimeStaged onBackendChanged: {cA.transitionTimeStaged = backend; calcNeedsSave(); } inputMethodHints: Qt.ImhDigitsOnly validator: IntValidator {bottom: 1; top: 600;} // less than 12 hours (in minutes: 720) } Controls.Label { enabled: false text: i18n("(In minutes - min. 1, max. 600)") } } Controls.Label { id: manualTimingsError1 anchors.horizontalCenter: manualTimingsViewGrid.horizontalCenter visible: evenBeginManField.getNormedDate() - mornBeginManField.getNormedDate() <= 0 font.italic: true text: i18n("Error: Morning not before evening.") } Controls.Label { id: manualTimingsError2 anchors.horizontalCenter: manualTimingsViewGrid.horizontalCenter visible: { if (manualTimingsError1.visible) { return false; } var trTime = transTimeField.backend * 60 * 1000; var mor = mornBeginManField.getNormedDate(); var eve = evenBeginManField.getNormedDate(); return eve - mor <= trTime || eve - mor >= 86400000 - trTime; } font.italic: true text: i18n("Error: Transition time overlaps.") } } } } // error message as overlay Item { width: 0.8 * main.width height: 0.8 * main.height anchors.centerIn: main visible: error != CC.CompositorAdaptor.ErrorCodeSuccess Rectangle { anchors.centerIn: parent width: errorMessage.contentWidth * 1.1 height: errorMessage.contentHeight * 1.1 color: theme.backgroundColor opacity: 0.8 border { width: units.devicePixelRatio color: theme.textColor } } PlasmaExtras.Heading { id: errorMessage anchors.fill: parent level: 4 text: cA.errorText horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.Wrap textFormat: Text.PlainText } } } diff --git a/toolboxes/desktoptoolbox/contents/ui/ToolBoxButton.qml b/toolboxes/desktoptoolbox/contents/ui/ToolBoxButton.qml index 9dff34230..8d3ed4e56 100644 --- a/toolboxes/desktoptoolbox/contents/ui/ToolBoxButton.qml +++ b/toolboxes/desktoptoolbox/contents/ui/ToolBoxButton.qml @@ -1,309 +1,309 @@ /*************************************************************************** * Copyright 2012,2015 by Sebastian Kügler * * Copyright 2015 by 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) 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 . * ***************************************************************************/ import QtQuick 2.4 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.plasma.plasmoid 2.0 Item { id: toolBoxButton - property string text: main.Plasmoid.activityName == i18n("Default") ? i18n("Desktop Toolbox") : i18n("Desktop Toolbox — %1 Activity", main.Plasmoid.activityName) + property string text: main.Plasmoid.activityName === i18n("Default") ? i18n("Desktop Toolbox") : i18n("Desktop Toolbox — %1 Activity", main.Plasmoid.activityName) property bool isCorner: !buttonMouse.dragging && ((state == "topleft") || (state == "topright") || (state == "bottomright") || (state == "bottomleft")) property bool isHorizontal: (state != "left" && state != "right") rotation: switch(state) { case "left": return -90; case "right": return 90; default: return 0; } transform: Translate { x: state == "left" ? Math.round(-width/2 + height/2) : state == "right" ? + Math.round(width/2 - height/2) : 0 Behavior on x { NumberAnimation { duration: units.shortDuration * 3; easing.type: Easing.InOutExpo; } } } transformOrigin: Item.Center Behavior on rotation { NumberAnimation { duration: units.shortDuration * 3; easing.type: Easing.InOutExpo; } enabled: visible } Behavior on x { NumberAnimation { duration: units.shortDuration * 3; easing.type: Easing.InOutExpo; } enabled: visible } Behavior on y { NumberAnimation { duration: units.shortDuration * 3; easing.type: Easing.InOutExpo; } enabled: visible } clip: backgroundFrameWidthAnimation.running width: backgroundFrame.width + backgroundFrame.width % 2 height: backgroundFrame.height + backgroundFrame.height % 2 //x and y default to 0, so top left would be correct //If the position is anything else it will updated via onXChanged during initialization state: "topleft" onXChanged: stateTimer.restart() onYChanged: stateTimer.restart() Timer { id: stateTimer interval: 100 onTriggered: updateState() } function updateState() { var container = main; //print(" w: " + container.width +"x"+container.height+" : "+x+"/"+y+" tbw: " + toolBoxButton.width); var x = toolBoxButton.x - main.x; var y = toolBoxButton.y - main.y; var cornerSnap = iconWidth if (x < cornerSnap && y < cornerSnap) { toolBoxButton.state = "topleft"; } else if (container.width - x - buttonLayout.width < cornerSnap && y < cornerSnap) { toolBoxButton.state = "topright"; } else if (container.width - x - buttonLayout.width < cornerSnap && container.height - y - buttonLayout.width < cornerSnap) { toolBoxButton.state = "bottomright"; } else if (x < cornerSnap && container.height - y - buttonLayout.width < cornerSnap) { toolBoxButton.state = "bottomleft"; //top diagonal half } else if (x > (y * (container.width/container.height))) { //Top edge if (container.width - x > y ) { toolBoxButton.state = "top"; //right edge } else { //toolBoxButton.transformOrigin = Item.BottomRight toolBoxButton.state = "right"; } //bottom diagonal half } else { //Left edge if (container.height - y > x ) { //toolBoxButton.transformOrigin = Item.TopLeft toolBoxButton.state = "left"; //Bottom edge } else { toolBoxButton.state = "bottom"; } } if (!buttonMouse.pressed) { main.placeToolBox(toolBoxButton.state); } stateTimer.running = false; } PlasmaCore.FrameSvgItem { id: backgroundFrame anchors { left: parent.left top: parent.top } imagePath: "widgets/translucentbackground" opacity: buttonMouse.containsMouse || (toolBoxLoader.item && toolBoxLoader.item.visible) ? 1.0 : 0.4 width: Math.round((isCorner ? buttonLayout.height : buttonLayout.width) + margins.horizontal) height: Math.round(buttonLayout.height + margins.vertical) Behavior on width { NumberAnimation { id: backgroundFrameWidthAnimation duration: units.longDuration; easing.type: Easing.InOutQuad; } } Behavior on opacity { NumberAnimation { duration: units.longDuration; } } } Row { id: buttonLayout anchors.centerIn: parent height: Math.max(toolBoxIcon.height, fontMetrics.height) spacing: units.smallSpacing Behavior on x { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutQuad; } } PlasmaCore.SvgItem { id: toolBoxIcon svg: PlasmaCore.Svg { id: iconSvg imagePath: "widgets/configuration-icons" onRepaintNeeded: toolBoxIcon.elementId = iconSvg.hasElement("menu") ? "menu" : "configure" } elementId: iconSvg.hasElement("menu") ? "menu" : "configure" anchors.verticalCenter: parent.verticalCenter width: iconSize height: iconSize opacity: buttonMouse.containsMouse || (toolBoxLoader.item && toolBoxLoader.item.visible) ? 1 : 0.5 rotation: isHorizontal ? 0 : -90; transformOrigin: Item.Center Behavior on opacity { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutExpo; } } } PlasmaComponents.Label { id: activityName anchors.verticalCenter: parent.verticalCenter opacity: isCorner ? 0 : 1 text: toolBoxButton.text visible: opacity Behavior on opacity { //only have this animation when going from hidden -> shown enabled: activityName.opacity == 0 SequentialAnimation { //pause to allow the toolbox frame to resize //otherwise we see the text overflow the box //whilst that animates PauseAnimation { duration: units.longDuration } NumberAnimation { duration: units.shortDuration easing.type: Easing.InOutExpo } } } } FontMetrics { id: fontMetrics font: activityName.font } } MouseArea { id: buttonMouse property QtObject container: main property int pressedX property int pressedY property bool dragging: false anchors { fill: parent margins: -10 } drag { target: main.Plasmoid.immutable ? undefined : toolBoxButton minimumX: 0 maximumX: container.width - toolBoxIcon.width minimumY: 0 maximumY: container.height - toolBoxIcon.height } hoverEnabled: true onPressed: { pressedX = toolBoxButton.x pressedY = toolBoxButton.y } onPositionChanged: { if (pressed && (Math.abs(toolBoxButton.x - pressedX) > iconSize || Math.abs(toolBoxButton.y - pressedY) > iconSize)) { dragging = true; } } onClicked: { // the dialog auto-closes on losing focus main.open = !main.dialogWasVisible plasmoid.focus = true; } onReleased: { main.Plasmoid.configuration.ToolBoxButtonState = toolBoxButton.state; main.Plasmoid.configuration.ToolBoxButtonX = toolBoxButton.x; main.Plasmoid.configuration.ToolBoxButtonY = toolBoxButton.y; //print("Saved coordinates for ToolBox in config: " + toolBoxButton.x + ", " +toolBoxButton.x); if (dragging) { main.placeToolBox(); } dragging = false; stateTimer.stop(); updateState(); } onCanceled: dragging = false; } states: [ State { name: "topleft" }, State { name: "top" }, State { name: "topright" }, State { name: "right" }, State { name: "bottomright" }, State { name: "bottom" }, State { name: "bottomleft" }, State { name: "left" } ] } diff --git a/toolboxes/desktoptoolbox/contents/ui/ToolBoxRoot.qml b/toolboxes/desktoptoolbox/contents/ui/ToolBoxRoot.qml index e42e9c58e..c27229341 100644 --- a/toolboxes/desktoptoolbox/contents/ui/ToolBoxRoot.qml +++ b/toolboxes/desktoptoolbox/contents/ui/ToolBoxRoot.qml @@ -1,202 +1,202 @@ /* * Copyright 2011 Sebastian Kügler * Copyright 2011 Marco Martin * Copyright 2015 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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. */ import QtQuick 2.2 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.plasmoid 2.0 Item { id: main objectName: "org.kde.desktoptoolbox" z: 999 anchors.fill: parent Connections { target: plasmoid onAvailableScreenRegionChanged: placeToolBoxTimer.restart(); } //FIXME: this timer shouldn't exist, but unfortunately when the focus passes //from the desktop to the dialog or vice versa, the event is not atomic //and ends up with neither of those having focus, hiding the dialog when //it shouldn't Timer { id: hideDialogTimer interval: 0 //NOTE: it's checking activeFocusItem instead of active as active doesn't correctly signal its change - property bool desktopOrDialogFocus: main.Window.activeFocusItem != null || (toolBoxLoader.item && toolBoxLoader.item.activeFocusItem != null) + property bool desktopOrDialogFocus: main.Window.activeFocusItem !== null || (toolBoxLoader.item && toolBoxLoader.item.activeFocusItem !== null) onDesktopOrDialogFocusChanged: { if (!desktopOrDialogFocus) { hideDialogTimer.restart(); } } onTriggered: { if (!desktopOrDialogFocus) { open = false; } } } signal minimumWidthChanged signal minimumHeightChanged signal maximumWidthChanged signal maximumHeightChanged signal preferredWidthChanged signal preferredHeightChanged property int iconSize: units.iconSizes.small property int iconWidth: units.iconSizes.smallMedium property int iconHeight: iconWidth property bool dialogWasVisible: false property bool open: false onOpenChanged: { plasmoid.editMode = open if (open) { plasmoid.contextualActionsAboutToShow(); toolBoxLoader.active = true; toolBoxLoader.item.visible = true; } else { toolBoxLoader.item.visible = false; } } onWidthChanged: placeToolBoxTimer.restart(); onHeightChanged: placeToolBoxTimer.restart(); LayoutMirroring.enabled: (Qt.application.layoutDirection === Qt.RightToLeft) LayoutMirroring.childrenInherit: true onVisibleChanged: { if (!visible && toolBoxLoader.item) { toolBoxLoader.item.visible = false } } ToolBoxButton { id: toolBoxButton visible: false Component.onCompleted: { placeToolBox(plasmoid.configuration.ToolBoxButtonState); toolBoxButton.visible = true } } Timer { id: placeToolBoxTimer interval: 100 repeat: false running: false onTriggered: { placeToolBox(plasmoid.configuration.ToolBoxButtonState); } } Loader { id: toolBoxLoader active: false sourceComponent: PlasmaCore.Dialog { id: dialog flags: Qt.WindowStaysOnTopHint location: PlasmaCore.Types.Floating visualParent: toolBoxButton // hideOnWindowDeactivate: true mainItem: ToolBoxItem { LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true Timer { id: visibleTimer interval: 300 onTriggered: main.dialogWasVisible = dialog.visible } } onVisibleChanged: visibleTimer.restart(); } } function placeToolBox(ts) { // if nothing has been setup yet, determine default position based on layout direction if (!ts) { if (Qt.application.layoutDirection === Qt.RightToLeft) { placeToolBox("topleft"); } else { placeToolBox("topright"); } return; } var tx = Plasmoid.configuration.ToolBoxButtonX var ty = Plasmoid.configuration.ToolBoxButtonY var pos; switch (ts) { case "top": ty = main.y; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.width, toolBoxButton.height); break; case "left": tx = main.x; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.width, toolBoxButton.height); break; case "right": tx = main.width + main.x - toolBoxButton.width; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.width, toolBoxButton.height); break; case "bottom": ty = main.height + main.y - toolBoxButton.height; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.width, toolBoxButton.height); break; case "topleft": tx = main.x; ty = main.y; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.height, toolBoxButton.height); break; case "topright": tx = main.width + main.x - toolBoxButton.height; ty = main.y; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.height, toolBoxButton.height); break; case "bottomleft": tx = main.x; ty = main.height + main.y - toolBoxButton.height; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.height, toolBoxButton.height); break; case "bottomright": default: tx = main.width + main.x - toolBoxButton.height; ty = main.height + main.y - toolBoxButton.height; pos = plasmoid.adjustToAvailableScreenRegion(tx, ty, toolBoxButton.height, toolBoxButton.height); break; } //print("XXXY Setting toolbox to: " + ts + " " + tx + "x" + ty + " screen: " + main.width+ "x" + main.height+""); toolBoxButton.x = pos.x; toolBoxButton.y = pos.y; } } diff --git a/toolboxes/paneltoolbox/contents/ui/main.qml b/toolboxes/paneltoolbox/contents/ui/main.qml index 069effc71..daaca6319 100644 --- a/toolboxes/paneltoolbox/contents/ui/main.qml +++ b/toolboxes/paneltoolbox/contents/ui/main.qml @@ -1,93 +1,93 @@ /* * Copyright 2011 Sebastian Kügler * Copyright 2013 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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. */ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.plasmoid 2.0 Item { id: main width: isVertical ? units.iconSizes.medium : units.iconSizes.smallMedium + units.smallSpacing * 2 height: isVertical ? units.iconSizes.smallMedium + units.smallSpacing * 2 : units.iconSizes.medium - property bool isVertical: plasmoid.formFactor == 3 + property bool isVertical: plasmoid.formFactor === 3 opacity: plasmoid.immutable ? 0 : (mouseArea.containsMouse || plasmoid.userConfiguring ? 1 : 0.5) z: 999 Behavior on opacity { NumberAnimation { duration: units.longDuration; easing.type: Easing.InOutExpo; } } LayoutMirroring.enabled: (Qt.application.layoutDirection === Qt.RightToLeft) anchors { left: undefined top: undefined right: isVertical || !parent ? undefined : parent.right bottom: isVertical && parent ? parent.bottom : undefined verticalCenter: isVertical || !parent ? undefined : parent.verticalCenter horizontalCenter: isVertical && parent ? parent.horizontalCenter : undefined } PlasmaCore.SvgItem { id: toolBoxIcon svg: PlasmaCore.Svg { id: iconSvg imagePath: "widgets/configuration-icons" } elementId: "configure" anchors.centerIn: mouseArea width: units.iconSizes.small height: width } Connections { target: plasmoid onUserConfiguringChanged: { plasmoid.editMode = plasmoid.userConfiguring; if (plasmoid.userConfiguring) { toolTipArea.hideToolTip(); } } } MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: enabled enabled: !plasmoid.immutable onClicked: { main.Plasmoid.action("configure").trigger() } PlasmaCore.ToolTipArea { id: toolTipArea anchors.fill: parent mainText: i18nd("plasma_toolbox_org.kde.paneltoolbox", "Configure Panel...") icon: "configure" enabled: mouseArea.containsMouse } } }