launcher from the mycroft tablet containment

This commit is contained in:
Marco Martin 2019-07-29 18:49:36 +02:00
parent 8f8a23c6ea
commit 85035dda60
5 changed files with 611 additions and 43 deletions

View file

@ -0,0 +1,144 @@
/*
* Copyright 2019 Marco Martin <mart@kde.org>
*
* 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.4
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.3 as Controls
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
Controls.Control {
id: delegate
z: dragging ? 1 : 0
property var modelData: typeof model !== "undefined" ? model : null
property bool dragging
property Controls.Control dragDelegate
Drag.active: false
Drag.hotSpot.x: delegate.width/2
Drag.hotSpot.y: delegate.height/2
Drag.mimeData: { "text/uri-list": modelData ? "file://" + modelData.ApplicationDesktopRole : "" }
Drag.dragType: Drag.Automatic
leftPadding: units.smallSpacing*2
topPadding: units.smallSpacing*2
rightPadding: units.smallSpacing*2
bottomPadding: units.smallSpacing*2
opacity: dragging ? 0.4 : 1
onDraggingChanged: {
if (dragging) {
dragDelegate.x = delegate.x
dragDelegate.y = delegate.y
dragDelegate.modelData = model;
root.reorderingApps = true;
} else {
dragDelegate.modelData = null;
root.reorderingApps = false;
}
}
contentItem: MouseArea {
drag.target: dragging ? dragDelegate : null
onClicked: {
if (modelData.ApplicationStartupNotifyRole) {
clickFedbackAnimation.target = delegate;
clickFedbackAnimation.running = true;
feedbackWindow.title = modelData.ApplicationNameRole;
feedbackWindow.state = "open";
}
plasmoid.nativeInterface.applicationListModel.runApplication(modelData.ApplicationStorageIdRole);
}
onPressAndHold: {
delegate.dragging = true;
}
onReleased: delegate.dragging = false;
onCanceled: delegate.dragging = false;
onPositionChanged: {
if (!dragging || !dragDelegate) {
return;
}
if (dragDelegate.x + dragDelegate.width < 0
|| dragDelegate.y + dragDelegate.height < 0
|| dragDelegate.x > applicationsFlow.width
|| dragDelegate.y > applicationsFlow.height) {
dragging = false;
delegate.grabToImage(function(result) {
root.externalDragStarted();
delegate.Drag.imageSource = result.url;
delegate.Drag.active = true;
})
return;
}
var newRow = Math.round(applicationsFlow.width / dragDelegate.width) * Math.floor((dragDelegate.y+dragDelegate.height/2) / dragDelegate.height) + Math.floor((dragDelegate.x+dragDelegate.width/2) / dragDelegate.width);
plasmoid.nativeInterface.applicationListModel.moveItem(modelData.index, newRow);
}
ColumnLayout {
anchors.fill: parent
spacing: 0
PlasmaCore.IconItem {
id: icon
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.fillWidth: true
Layout.preferredHeight: parent.height - root.reservedSpaceForLabel
source: modelData ? modelData.ApplicationIconRole : ""
scale: root.reorderingApps && dragDelegate && !dragging ? 0.6 : 1
Behavior on scale {
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
}
PlasmaComponents.Label {
id: label
visible: text.length > 0
Layout.fillWidth: true
Layout.fillHeight: true
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignTop
maximumLineCount: 2
elide: Text.ElideRight
text: modelData ? modelData.ApplicationNameRole : ""
font.pixelSize: theme.defaultFont.pixelSize
color: PlasmaCore.ColorScope.textColor
}
}
}
}

View file

@ -0,0 +1,102 @@
/*
* Copyright 2015 Marco Martin <notmart@gmail.com>
*
* 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 QtQuick.Window 2.2
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
Window {
id: window
property alias state: background.state
width: Screen.width
height: Screen.height
color: "transparent"
onVisibleChanged: {
if (!visible) {
background.state = "closed";
}
}
onActiveChanged: {
if (!active) {
background.state = "closed";
}
}
PlasmaCore.ColorScope {
id: background
anchors.fill: parent
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
width: window.width
height: window.height
state: "closed"
Rectangle {
anchors.fill: parent
color: background.backgroundColor
PlasmaComponents.BusyIndicator {
anchors.centerIn: parent
}
}
states: [
State {
name: "closed"
PropertyChanges {
target: background
scale: 0
}
PropertyChanges {
target: window
visible: false
}
},
State {
name: "open"
PropertyChanges {
target: background
scale: 1
}
PropertyChanges {
target: window
visible: true
}
}
]
transitions: [
Transition {
from: "closed"
SequentialAnimation {
ScriptAction {
script: window.visible = true;
}
PropertyAnimation {
target: background
duration: units.longDuration
easing.type: Easing.InOutQuad
properties: "scale"
}
}
}
]
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright 2019 Marco Martin <mart@kde.org>
*
* 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.4
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.3 as Controls
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
Controls.Control {
id: root
readonly property bool dragging: applicationsFlow.dragData
property bool reorderingApps: false
property int availableCellHeight: units.iconSizes.huge + reservedSpaceForLabel
readonly property int reservedSpaceForLabel: metrics.height
readonly property int cellWidth: applicationsFlow.width / Math.floor(applicationsFlow.width / ((availableCellHeight - reservedSpaceForLabel) + units.smallSpacing*4))
readonly property int cellHeight: availableCellHeight - topPadding
signal externalDragStarted
signal dragPositionChanged(point pos)
implicitHeight: applicationsFlow.implicitHeight + frame.margins.top + frame.margins.bottom
leftPadding: frame.margins.left
topPadding: frame.margins.top
rightPadding: frame.margins.right
bottomPadding: frame.margins.bottom
background: PlasmaCore.FrameSvgItem {
id: frame
imagePath: "widgets/background"
anchors.fill: parent
Rectangle {
y: root.cellHeight + frame.margins.top
color: theme.textColor
opacity: 0.3
height: 1
anchors {
left: parent.left
right: parent.right
leftMargin: frame.margins.left
rightMargin: frame.margins.right
}
}
}
contentItem: Item {
//NOTE: TextMetrics can't handle multi line
Controls.Label {
id: metrics
text: "M\nM"
visible: false
}
//This Delegate is the placeholder for the "drag"
//delegate (that is not actual drag and drop
Delegate {
id: dragDelegateItem
z: 999
width: root.cellWidth
height: root.cellHeight
onYChanged: dragPositionChanged(Qt.point(x, y))
visible: modelData !== null
}
Flow {
id: applicationsFlow
anchors.fill: parent
spacing: 0
property var dragData
property int startContentYDrag
property bool viewHasBeenDragged
NumberAnimation {
id: scrollAnim
target: applicationsFlow
properties: "contentY"
duration: units.longDuration
easing.type: Easing.InOutQuad
}
move: Transition {
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
properties: "x,y"
}
}
Repeater {
model: plasmoid.nativeInterface.applicationListModel
delegate: Delegate {
width: root.cellWidth
height: root.cellHeight
dragDelegate: dragDelegateItem
}
}
}
}
}

View file

@ -0,0 +1,182 @@
/*
* Copyright 2019 Marco Martin <mart@kde.org>
*
* 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.4
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.3 as Controls
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
MouseArea {
id: root
property alias availableCellHeight: launcherGrid.availableCellHeight
property alias contentY: mainFlickable.contentY
property alias contentHeight: mainFlickable.contentHeight
property alias topMargin: mainFlickable.topMargin
property int leftPadding
property int rightPadding
signal movementEnded
signal externalDragStarted
drag.filterChildren: true
onClicked: closeAnim.restart()
//BEGIN functions
//Autoscroll related functions
function scrollUp() {
autoScrollTimer.scrollDown = false;
autoScrollTimer.running = true;
scrollUpIndicator.opacity = 1;
scrollDownIndicator.opacity = 0;
}
function scrollDown() {
autoScrollTimer.scrollDown = true;
autoScrollTimer.running = true;
scrollUpIndicator.opacity = 0;
scrollDownIndicator.opacity = 1;
}
function stopScroll() {
autoScrollTimer.running = false;
scrollUpIndicator.opacity = 0;
scrollDownIndicator.opacity = 0;
}
//END functions
Timer {
id: autoScrollTimer
property bool scrollDown: true
repeat: true
interval: 1500
onTriggered: {
//reordering launcher icons
if (launcherGrid.reorderingApps) {
scrollAnim.to = scrollDown ?
//Scroll down
Math.min(mainFlickable.contentItem.height - root.height, mainFlickable.contentY + root.height/2) :
//Scroll up
Math.max(0, mainFlickable.contentY - root.height/2);
} else {
stopScroll();
}
scrollAnim.running = true;
}
}
NumberAnimation {
id: scrollAnim
target: mainFlickable
property: "contentY"
duration: units.longDuration
easing.type: Easing.InOutQuad
}
PlasmaCore.Svg {
id: arrowsSvg
imagePath: "widgets/arrows"
}
PlasmaCore.SvgItem {
id: scrollUpIndicator
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 300
}
z: 2
opacity: 0
svg: arrowsSvg
elementId: "up-arrow"
width: units.iconSizes.large
height: width
Behavior on opacity {
OpacityAnimator {
duration: 1000
easing.type: Easing.InOutQuad
}
}
}
PlasmaCore.SvgItem {
id: scrollDownIndicator
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: units.gridUnit * 2
}
z: 2
opacity: 0
svg: arrowsSvg
elementId: "down-arrow"
width: units.iconSizes.large
height: width
Behavior on opacity {
OpacityAnimator {
duration: 1000
easing.type: Easing.InOutQuad
}
}
}
Flickable {
id: mainFlickable
anchors{
fill: parent
leftMargin: root.leftPadding
rightMargin: root.rightPadding
}
contentWidth: width
contentHeight: launcherGrid.height
onMovementEnded: root.movementEnded();
onFlickEnded: root.movementEnded();
LauncherGrid {
id: launcherGrid
width: parent.width
onExternalDragStarted: root.externalDragStarted()
onDragPositionChanged: {
pos = mapToItem(root, pos.x, pos.y);
if (pos.y < root.height /3) {
scrollUp();
} else if (pos.y > root.height / 3 * 2) {
scrollDown();
} else {
stopScroll();
}
}
}
}
PlasmaComponents.ScrollBar {
anchors {
top: parent.top
right: parent.right
bottom: parent.bottom
topMargin: Math.max(0, -mainFlickable.contentY) + units.smallSpacing*2
rightMargin: root.rightPadding + units.smallSpacing * 2
}
interactive: false
flickableItem: mainFlickable
}
}

View file

@ -26,6 +26,8 @@ import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.draganddrop 2.0 as DragDrop import org.kde.draganddrop 2.0 as DragDrop
import "launcher" as Launcher
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
Item { Item {
@ -68,67 +70,78 @@ Item {
Text { Text {
text:"Edit Mode" text:"Edit Mode"
color: "white" color: "white"
visible: appletsLayout.editMode visible: plasmoid.editMode
} }
Connections { Connections {
target: plasmoid target: plasmoid
onEditModeChanged: appletsLayout.editMode = plasmoid.editMode onEditModeChanged: {
appletsLayout.editMode = plasmoid.editMode
if (plasmoid.editMode) {
menuRepeater.freeLayout();
} else {
menuRepeater.relayout();
}
}
} }
ContainmentLayoutManager.AppletsLayout { Flickable {
id: appletsLayout
anchors.fill: parent anchors.fill: parent
configKey: width > height ? "ItemGeometries" : "ItemGeometriesVertical" contentWidth: width
containment: plasmoid contentHeight: appletsLayout.height
editModeCondition: plasmoid.immutable interactive: !plasmoid.editMode
? ContainmentLayoutManager.AppletsLayout.Manual
: ContainmentLayoutManager.AppletsLayout.AfterPressAndHold
// Sets the containment in edit mode when we go in edit mode as well ContainmentLayoutManager.AppletsLayout {
onEditModeChanged: plasmoid.editMode = editMode id: appletsLayout
width: parent.width
height: 500 + launcher.height
configKey: width > height ? "ItemGeometries" : "ItemGeometriesVertical"
containment: plasmoid
editModeCondition: plasmoid.immutable
? ContainmentLayoutManager.AppletsLayout.Manual
: ContainmentLayoutManager.AppletsLayout.AfterPressAndHold
minimumItemWidth: units.gridUnit * 3 // Sets the containment in edit mode when we go in edit mode as well
minimumItemHeight: minimumItemWidth onEditModeChanged: plasmoid.editMode = editMode
defaultItemWidth: units.gridUnit * 6 minimumItemWidth: units.gridUnit * 3
defaultItemHeight: defaultItemWidth minimumItemHeight: minimumItemWidth
cellWidth: units.iconSizes.small defaultItemWidth: units.gridUnit * 6
cellHeight: cellWidth defaultItemHeight: defaultItemWidth
acceptsAppletCallback: function(applet, x, y) { cellWidth: units.iconSizes.small
print("Applet: "+applet+" "+x+" "+y) cellHeight: cellWidth
return true;
}
appletContainerComponent: ContainmentLayoutManager.BasicAppletContainer { acceptsAppletCallback: function(applet, x, y) {
id: appletContainer print("Applet: "+applet+" "+x+" "+y)
configOverlayComponent: ConfigOverlay {} return true;
} }
placeHolder: ContainmentLayoutManager.PlaceHolder {} appletContainerComponent: ContainmentLayoutManager.BasicAppletContainer {
id: appletContainer
configOverlayComponent: ConfigOverlay {}
onEditModeChanged: {
if (editMode) {
plasmoid.editMode = true;
}
}
}
Repeater { placeHolder: ContainmentLayoutManager.PlaceHolder {}
model: 3
ContainmentLayoutManager.ItemContainer {
id: extraIcon
key: "Icon-" + modelData
preferredLayoutDirection: editMode ? ContainmentLayoutManager.AppletsLayout.Closest : ContainmentLayoutManager.AppletsLayout.TopToBottom
x: 16
y: 16
implicitWidth: 48
implicitHeight: 48
editModeCondition: ContainmentLayoutManager.ItemContainer.AfterPress
Rectangle { Launcher.LauncherGrid {
anchors.fill: parent id: launcher
color: extraIcon.focus ? "green" : "red" anchors {
radius: width left: parent.left
opacity: extraIcon.editMode ? 0.6 : 1 right: parent.right
bottom: parent.bottom
} }
} }
} }
} }
Controls.Button {
text: "load"
onClicked: menuRepeater.model = plasmoid.nativeInterface.applicationListModel
}
} }
} }