diff --git a/applets/quicklaunch/package/contents/ui/main.qml b/applets/quicklaunch/package/contents/ui/main.qml index 0777306cb..7c7241e09 100644 --- a/applets/quicklaunch/package/contents/ui/main.qml +++ b/applets/quicklaunch/package/contents/ui/main.qml @@ -1,293 +1,292 @@ /* * Copyright 2015 David Rosca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see */ import QtQuick 2.2 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.draganddrop 2.0 as DragAndDrop import org.kde.plasma.private.quicklaunch 1.0 import "layout.js" as LayoutManager Item { id: root readonly property int maxSectionCount: plasmoid.configuration.maxSectionCount readonly property bool showLauncherNames : plasmoid.configuration.showLauncherNames readonly property bool enablePopup : plasmoid.configuration.enablePopup readonly property string title : plasmoid.formFactor == PlasmaCore.Types.Planar ? plasmoid.configuration.title : "" readonly property bool vertical : plasmoid.formFactor == PlasmaCore.Types.Vertical || (plasmoid.formFactor == PlasmaCore.Types.Planar && height > width) readonly property bool horizontal : plasmoid.formFactor == PlasmaCore.Types.Horizontal property bool dragging : false Layout.minimumWidth: LayoutManager.minimumWidth() Layout.minimumHeight: LayoutManager.minimumHeight() Layout.preferredWidth: LayoutManager.preferredWidth() Layout.preferredHeight: LayoutManager.preferredHeight() Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Plasmoid.backgroundHints: PlasmaCore.Types.DefaultBackground | PlasmaCore.Types.ConfigurableBackground DragAndDrop.DropArea { anchors.fill: parent preventStealing: true enabled: !plasmoid.immutable onDragEnter: { if (event.mimeData.hasUrls) { dragging = true; } else { event.ignore(); } } onDragMove: { var index = grid.indexAt(event.x, event.y); if (isInternalDrop(event)) { launcherModel.moveUrl(event.mimeData.source.itemIndex, index); } else { launcherModel.showDropMarker(index); } popup.visible = root.childAt(event.x, event.y) == popupArrow; } onDragLeave: { dragging = false; launcherModel.clearDropMarker(); } onDrop: { dragging = false; launcherModel.clearDropMarker(); if (isInternalDrop(event)) { event.accept(Qt.IgnoreAction); saveConfiguration(); } else { var index = grid.indexAt(event.x, event.y); launcherModel.insertUrls(index == -1 ? launcherModel.count : index, event.mimeData.urls); event.accept(event.proposedAction); } } } PlasmaComponents.Label { id: titleLabel anchors { top: parent.top left: parent.left right: parent.right } height: theme.mSize(theme.defaultFont).height horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignTop elide: Text.ElideMiddle text: title } Item { id: launcher anchors { top: title.length ? titleLabel.bottom : parent.top left: parent.left right: !vertical && popupArrow.visible ? popupArrow.left : parent.right bottom: vertical && popupArrow.visible ? popupArrow.top : parent.bottom } GridView { id: grid anchors.fill: parent interactive: false flow: horizontal ? GridView.FlowTopToBottom : GridView.FlowLeftToRight cellWidth: LayoutManager.preferredCellWidth() cellHeight: LayoutManager.preferredCellHeight() visible: count model: UrlModel { id: launcherModel } delegate: IconItem { } } PlasmaCore.IconItem { id: defaultIcon anchors.fill: parent source: "fork" visible: !grid.visible PlasmaCore.ToolTipArea { anchors.fill: parent - icon: "fork" mainText: i18n("Quicklaunch") subText: i18nc("@info", "Add launchers by Drag and Drop or by using the context menu.") } } } PlasmaCore.Dialog { id: popup type: PlasmaCore.Dialog.PopupMenu flags: Qt.WindowStaysOnTopHint hideOnWindowDeactivate: true location: plasmoid.location visualParent: vertical ? popupArrow : root mainItem: Popup { } } PlasmaCore.ToolTipArea { id: popupArrow visible: enablePopup anchors { top: vertical ? undefined : parent.top right: parent.right bottom: parent.bottom } subText: popup.visible ? i18n("Hide icons") : i18n("Show hidden icons") MouseArea { id: arrowMouseArea anchors.fill: parent onClicked: { popup.visible = !popup.visible } PlasmaCore.Svg { id: arrowSvg imagePath: "widgets/arrows" } PlasmaCore.SvgItem { id: arrow anchors.centerIn: parent width: Math.min(parent.width, parent.height) height: width rotation: popup.visible ? 180 : 0 Behavior on rotation { RotationAnimation { duration: units.shortDuration * 3 } } svg: arrowSvg elementId: { if (plasmoid.location == PlasmaCore.Types.TopEdge) { return "down-arrow"; } else if (plasmoid.location == PlasmaCore.Types.LeftEdge) { return "right-arrow"; } else if (plasmoid.location == PlasmaCore.Types.RightEdge) { return "left-arrow"; } else if (vertical) { return "right-arrow"; } else { return "up-arrow"; } } } } } Logic { id: logic onLauncherAdded: { var m = isPopup ? popup.mainItem.popupModel : launcherModel; m.appendUrl(url); } onLauncherEdited: { var m = isPopup ? popup.mainItem.popupModel : launcherModel; m.changeUrl(index, url); } } // States to fix binding loop with enabled popup states: [ State { name: "normal" when: !vertical PropertyChanges { target: popupArrow width: units.iconSizes.smallMedium height: root.height } }, State { name: "vertical" when: vertical PropertyChanges { target: popupArrow width: root.width height: units.iconSizes.smallMedium } } ] Connections { target: plasmoid.configuration onLauncherUrlsChanged: { launcherModel.urlsChanged.disconnect(saveConfiguration); launcherModel.setUrls(plasmoid.configuration.launcherUrls); launcherModel.urlsChanged.connect(saveConfiguration); } } Component.onCompleted: { launcherModel.setUrls(plasmoid.configuration.launcherUrls); launcherModel.urlsChanged.connect(saveConfiguration); plasmoid.setAction("addLauncher", i18nc("@action", "Add Launcher..."), "list-add"); } function action_addLauncher() { logic.addLauncher(); } function saveConfiguration() { if (!dragging) { plasmoid.configuration.launcherUrls = launcherModel.urls(); } } function isInternalDrop(event) { return event.mimeData.source && event.mimeData.source.GridView && event.mimeData.source.GridView.view == grid; } } diff --git a/applets/quickshare/plasmoid/contents/ui/main.qml b/applets/quickshare/plasmoid/contents/ui/main.qml index b64893e3b..0d2c9f617 100644 --- a/applets/quickshare/plasmoid/contents/ui/main.qml +++ b/applets/quickshare/plasmoid/contents/ui/main.qml @@ -1,331 +1,326 @@ /*************************************************************************** * Copyright (C) 2013 by Aleix Pol Gonzalez * * * * 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.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 QtExtra import QtQuick.Layouts 1.1 import org.kde.plasma.private.purpose 1.0 DropArea { id: root Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation 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: units.iconSizes.small Layout.minimumHeight: Layout.minimumWidth Layout.maximumWidth: inPanel ? units.iconSizeHints.panel : -1 Layout.maximumHeight: inPanel ? units.iconSizeHints.panel : -1 property string url: "" property string errorMessage: "" property var pasteUrls: [] property int nextPaste: 0 function firstMimeType(formats) { for (var v in formats) { var curr = formats[v]; if (curr == "text/uri-list") { return { name: "text/uri-list" }; } else { var mime = mimeDb.mimeTypeForName(curr); if (mime.hasOwnProperty("iconName")) { return mime; } } } return {}; } function urlsMimetype(urls) { return mimeDb.mimeTypeForUrl(urls[0]); } function filenameFromUrl(url) { var parts = url.split("/"); return parts[parts.length - 1]; } function objectToArray(object) { var array = []; for(var v in object) { // toString() here too because sometimes the contents are non-string (eg QUrl) array.push(object[v].toString()); } return array; } onEntered: { root.state = "idle"; var mimetype; if (drag.hasUrls) { mimetype = urlsMimetype(objectToArray(drag.urls)); } else { mimetype = firstMimeType(drag.formats); } icon.source = mimetype.iconName; drag.accepted = true } onExited: { icon.source = "edit-paste" } QtExtra.Clipboard { id: clipboard } QtExtra.MimeDatabase { id: mimeDb } function resetActions() { for(var v in root.pasteUrls) { plasmoid.setAction(v, root.pasteUrls[v], ""); } } ContentTracker { id: contentTracker } function activate() { if (root.state == "configuration") { root.state = "idle"; } else if (contentTracker.uri) { var mime = contentTracker.mimeType; if (!mime) { mime = mimeDb.mimeTypeForUrl(contentTracker.uri).name; } sendData([contentTracker.uri], mime); } else { action_paste(); } } MouseArea { anchors.fill: parent onClicked: { activate(); } } Plasmoid.onActivated: { activate(); } ShowUrlDialog { id: showUrl location: plasmoid.location visualParent: parent onCopyUrl: { clipboard.content = showUrl.url; } } function copyUrl(url) { if (plasmoid.configuration.copyAutomatically) clipboard.content = url; else { showUrl.url = url showUrl.visible = true } } ShareDialog { id: shareDialog location: plasmoid.location inputData: { urls: [] } visualParent: parent onRunningChanged: { if (running) { root.state = "sending" } } onFinished: { if (error==0 && output.url !== "") { console.assert(output.url !== undefined); var resultUrl = output.url; console.log("Received url", resultUrl) if (resultUrl) { root.url = resultUrl; copyUrl(resultUrl) root.pasteUrls.push(resultUrl); while (plasmoid.configuration.historySize <= root.pasteUrls.length && root.pasteUrls.length !== 0) { root.pasteUrls.shift(); } } resetActions(); } shareDialog.visible = false; root.state = error===0 ? "success" : "failure"; root.errorMessage = message; } onWindowDeactivated: { if (!running) root.state = "idle"; } } function sendBase64Data(base64data, mimetype) { // Awesome KIO magic <3 var url = "data:"+mimetype+";base64,"+base64data; sendData([url], mimetype); } function sendData(urls, mimetype) { shareDialog.inputData = { "urls": urls, "mimeType": mimetype } root.state = "configuration" } onDropped: { if (drop.hasUrls) { var urls = objectToArray(drop.urls); sendData(urls, urlsMimetype(urls).name); } else { var mimetype = firstMimeType(drop.formats).name; var data = drop.getDataAsArrayBuffer(mimetype); sendBase64Data(PurposeHelper.variantToBase64(data), mimetype); } drop.accepted = true; } Component.onCompleted: { plasmoid.setAction("paste", i18nc("@action", "Paste"), "edit-paste"); plasmoid.setActionSeparator("pastes"); } function actionTriggered(actionName) { var index = parseInt(actionName); if (index) Qt.openUrlExternally(pasteUrls[actionName]); } function action_paste() { if (clipboard.formats.length < 1) { // empty clipboard! return; // do nothing (there's the tooltip!) } if (clipboard.formats.indexOf("text/uri-list")>=0) { var urls = objectToArray(clipboard.contentFormat("text/uri-list")) sendData(urls, urlsMimetype(urls).name); } else { var mimetype = firstMimeType(clipboard.formats).name; sendBase64Data(PurposeHelper.variantToBase64(clipboard.contentFormat(mimetype)), mimetype); } } PlasmaCore.ToolTipArea { id: tooltipArea anchors.fill: parent location: plasmoid.location active: true mainText: i18n("Share") subText: i18n("Drop text or an image onto me to upload it to an online service.") } PlasmaCore.IconItem { id: icon anchors.fill: parent } PlasmaComponents.BusyIndicator { id: busy anchors.fill: parent visible: false } Rectangle { border { color: theme.textColor width: root.containsDrag ? 5 : 1 } color: theme.backgroundColor radius: Math.max(parent.width, parent.height)/10 anchors.fill: parent opacity: root.containsDrag || tooltipArea.containsMouse ? .3 : 0 Behavior on opacity { NumberAnimation { duration: 100 } } } Timer { id: idleTimer running: false interval: 5000 onTriggered: root.state = "idle" } state: "idle" states: [ State { name: "idle" PropertyChanges { target: icon; source: "emblem-shared-symbolic" } - PropertyChanges { target: tooltipArea; icon: "emblem-shared-symbolic" } PropertyChanges { target: tooltipArea; mainText: i18n("Share") } PropertyChanges { target: tooltipArea; subText: contentTracker.uri ? i18n("Upload %1 to an online service", contentTracker.title ? contentTracker.title : filenameFromUrl(contentTracker.uri)) : i18n("Drop text or an image onto me to upload it to an online service.") } }, State { name: "configuration" PropertyChanges { target: icon; source: "configure" } - PropertyChanges { target: tooltipArea; icon: "edit-paste" } PropertyChanges { target: shareDialog; visible: true } }, State { name: "sending" PropertyChanges { target: icon; visible: false } PropertyChanges { target: busy; visible: true } PropertyChanges { target: busy; running: true } - PropertyChanges { target: tooltipArea; icon: "view-history" } PropertyChanges { target: tooltipArea; mainText: i18n("Sending...") } PropertyChanges { target: tooltipArea; subText: i18n("Please wait") } }, State { name: "success" PropertyChanges { target: icon; source: "dialog-ok" } PropertyChanges { target: idleTimer; running: true } - PropertyChanges { target: tooltipArea; icon: "dialog-ok" } PropertyChanges { target: tooltipArea; mainText: i18n("Successfully uploaded") } PropertyChanges { target: tooltipArea; subText: root.url ? i18n("%1", root.url) : "" } }, State { name: "failure" PropertyChanges { target: icon; source: "dialog-cancel" } PropertyChanges { target: idleTimer; running: true } - PropertyChanges { target: tooltipArea; icon: icon.source } PropertyChanges { target: tooltipArea; mainText: i18n("Error during upload.") } PropertyChanges { target: tooltipArea; subText: (root.errorMessage=="" ? i18n("Please, try again.") : root.errorMessage) } } ] }