diff --git a/src/shell/qmlpackages/desktop/contents/explorer/AppletDelegate.qml b/src/shell/qmlpackages/desktop/contents/explorer/AppletDelegate.qml new file mode 100644 index 000000000..5c015c6d0 --- /dev/null +++ b/src/shell/qmlpackages/desktop/contents/explorer/AppletDelegate.qml @@ -0,0 +1,195 @@ +/* + * Copyright 2011 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 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 1.1 +import org.kde.plasma.components 0.1 as PlasmaComponents +import org.kde.plasma.core 0.1 as PlasmaCore +import org.kde.draganddrop 1.0 +import org.kde.qtextracomponents 0.1 + +PlasmaCore.FrameSvgItem { + id: background + width: list.delegateWidth + height: list.delegateHeight + + property variant icon: decoration + property string title: name + property string description: model.description + property string author: model.author + property string email: model.email + property string license: model.license + property string pluginName: model.pluginName + property bool local: model.local + + ListView.onRemove: SequentialAnimation { + PropertyAction { + target: background + property: "ListView.delayRemove" + value: true + } + NumberAnimation { + target: background + property: widgetExplorer.orientation == Qt.Horizontal ? "y" : "x" + to: widgetExplorer.orientation == Qt.Horizontal ? list.delegateHeight : list.delegateWidth + duration: 150 + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: background + property: widgetExplorer.orientation == Qt.Horizontal ? "y" : "x" + to: widgetExplorer.orientation == Qt.Horizontal ? list.delegateHeight : list.delegateWidth + duration: 150 + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: background + property: widgetExplorer.orientation == Qt.Horizontal ? "width" : "height" + from: widgetExplorer.orientation == Qt.Horizontal ? list.delegateWidth : list.delegateHeight + to: 0 + duration: 150 + easing.type: Easing.InOutQuad + } + PropertyAction { + target: background + property: "ListView.delayRemove" + value: false + } + } + + ListView.onAdd: SequentialAnimation { + PropertyAction { + target: background + property: "y" + value: widgetExplorer.orientation == Qt.Horizontal ? -list.delegateHeight : -list.delegateWidth + } + NumberAnimation { + target: background + property: widgetExplorer.orientation == Qt.Horizontal ? "width" : "height" + from: 0 + to: widgetExplorer.orientation == Qt.Horizontal ? list.delegateWidth : list.delegateHeight + duration: 150 + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: background + property: widgetExplorer.orientation == Qt.Horizontal ? "y" : "x" + to: 0 + duration: 150 + easing.type: Easing.InOutQuad + } + } + + + imagePath: "widgets/viewitem" + prefix: "normal" + + DragArea { + anchors.fill: parent + supportedActions: Qt.MoveAction | Qt.LinkAction + onDragStarted: tooltipDialog.visible = false + delegateImage: background.icon + mimeData { + source: parent + } + Component.onCompleted: mimeData.setData("text/x-plasmoidservicename", pluginName) + + QIconItem { + id: iconWidget + anchors.verticalCenter: parent.verticalCenter + x: y + width: theme.hugeIconSize + height: width + icon: background.icon + } + Column { + anchors { + left: iconWidget.right + right: parent.right + verticalCenter: parent.verticalCenter + + leftMargin: background.margins.left + rightMargin: background.margins.right + } + + PlasmaComponents.Label { + id: titleText + text: title + font { + weight: Font.Bold + pointSize: theme.smallestFont.pointSize + } + anchors { + left: parent.left + right: parent.right + } + height: paintedHeight + wrapMode: Text.WordWrap + //go with nowrap only if there is a single word too long + onPaintedWidthChanged: { + wrapTimer.restart() + } + Timer { + id: wrapTimer + interval: 200 + onTriggered: { + //give it some pixels of tolerance + if (titleText.paintedWidth > titleText.width + 3) { + titleText.wrapMode = Text.NoWrap + titleText.elide = Text.ElideRight + } else { + titleText.wrapMode = Text.WordWrap + titleText.elide = Text.ElideNone + } + } + } + } + PlasmaComponents.Label { + text: description + font.pointSize: theme.smallestFont.pointSize + anchors { + left: parent.left + right: parent.right + } + elide: Text.ElideRight + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignTop + maximumLineCount: 3 + } + } + QIconItem { + icon: running ? "dialog-ok-apply" : undefined + visible: running + width: theme.smallIconSize + height: width + anchors { + right: parent.right + bottom: parent.bottom + rightMargin: background.margins.right + bottomMargin: background.margins.bottom + } + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + onDoubleClicked: widgetExplorer.addApplet(pluginName) + onEntered: tooltipDialog.appletDelegate = background + onExited: tooltipDialog.appletDelegate = null + } + } +} diff --git a/src/shell/qmlpackages/desktop/contents/explorer/SimpleWidgetExplorer.qml b/src/shell/qmlpackages/desktop/contents/explorer/SimpleWidgetExplorer.qml new file mode 100644 index 000000000..a261ef3ac --- /dev/null +++ b/src/shell/qmlpackages/desktop/contents/explorer/SimpleWidgetExplorer.qml @@ -0,0 +1,51 @@ +/* + * Copyright 2013 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 2.010-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 + + +Rectangle { + id: root + color: "pink" + width: 400 + height: 800 + + ListView { + anchors.fill: parent + model: widgetExplorer.widgetsModel + header: PlasmaExtras.Title { text: "Add Widgets" } + delegate: Item { + width: parent.width + height: 48 + Text { text: "Applet: " + pluginName } + + MouseArea { + anchors.fill: parent + onClicked: widgetExplorer.addApplet(pluginName) + } + } + } + + Component.onCompleted: { + print("WidgetExplorer QML loaded"); + print(" found " + widgetExplorer.widgetsModel.count + " widgets"); + } +} diff --git a/src/shell/qmlpackages/desktop/contents/explorer/Tooltip.qml b/src/shell/qmlpackages/desktop/contents/explorer/Tooltip.qml new file mode 100644 index 000000000..3ee4efa37 --- /dev/null +++ b/src/shell/qmlpackages/desktop/contents/explorer/Tooltip.qml @@ -0,0 +1,142 @@ +/* + * Copyright 2011 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 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 1.1 +import org.kde.plasma.components 0.1 as PlasmaComponents +import org.kde.plasma.core 0.1 as PlasmaCore +import org.kde.qtextracomponents 0.1 + +MouseArea { + id: main + + hoverEnabled: true + onEntered: toolTipHideTimer.running = false + onExited: toolTipHideTimer.running = true + + width: childrenRect.width + height: 200 + + property variant icon + property string title + property string description + property string author + property string email + property string license + property string pluginName + property bool local + + onClicked: tooltipDialog.visible = false + Connections { + target: tooltipDialog + onAppletDelegateChanged: { + if (!tooltipDialog.appletDelegate) { + return + } + icon = tooltipDialog.appletDelegate.icon + title = tooltipDialog.appletDelegate.title + description = tooltipDialog.appletDelegate.description + author = tooltipDialog.appletDelegate.author + email = tooltipDialog.appletDelegate.email + license = tooltipDialog.appletDelegate.license + pluginName = tooltipDialog.appletDelegate.pluginName + local = tooltipDialog.appletDelegate.local + } + } + QIconItem { + id: tooltipIconWidget + anchors.left: parent.left + anchors.top: parent.top + width: theme.hugeIconSize + height: width + icon: main.icon + } + Column { + id: nameColumn + spacing: 8 + anchors { + left: tooltipIconWidget.right + leftMargin: 8 + top: parent.top + right: parent.right + } + + PlasmaComponents.Label { + text: title + font.bold:true + anchors.left: parent.left + anchors.right: parent.right + height: paintedHeight + wrapMode: Text.Wrap + } + PlasmaComponents.Label { + text: description + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.Wrap + } + } + Grid { + anchors.top: tooltipIconWidget.bottom + anchors.topMargin: 16 + anchors.bottom: uninstallButton.top + anchors.bottomMargin: 4 + rows: 3 + columns: 2 + spacing: 4 + PlasmaComponents.Label { + text: i18n("License:") + } + PlasmaComponents.Label { + id: licenseText + text: license + wrapMode: Text.Wrap + } + PlasmaComponents.Label { + text: i18n("Author:") + } + PlasmaComponents.Label { + text: author + wrapMode: Text.Wrap + } + PlasmaComponents.Label { + text: i18n("Email:") + } + PlasmaComponents.Label { + text: email + } + } + + PlasmaComponents.Button { + id: uninstallButton + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + } + opacity: local ? 1 : 0 + Behavior on opacity { + NumberAnimation { duration: 250 } + } + iconSource: "application-exit" + text: i18n("Uninstall") + onClicked: { + widgetExplorer.uninstall(pluginName) + tooltipDialog.visible = false + } + } +} diff --git a/src/shell/qmlpackages/desktop/contents/explorer/WidgetExplorer.qml b/src/shell/qmlpackages/desktop/contents/explorer/WidgetExplorer.qml index a261ef3ac..0b081b652 100644 --- a/src/shell/qmlpackages/desktop/contents/explorer/WidgetExplorer.qml +++ b/src/shell/qmlpackages/desktop/contents/explorer/WidgetExplorer.qml @@ -1,51 +1,367 @@ /* - * Copyright 2013 Sebastian Kügler + * Copyright 2011 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 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. + * 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. + * 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 QtQuick 1.1 +import org.kde.plasma.components 0.1 as PlasmaComponents +import org.kde.plasma.core 0.1 as PlasmaCore +import org.kde.qtextracomponents 0.1 +Item { + id: main -Rectangle { - id: root - color: "pink" - width: 400 - height: 800 + //this is used to perfectly align the filter field and delegates + property int cellWidth: theme.defaultFont.mSize.width * 20 - ListView { - anchors.fill: parent - model: widgetExplorer.widgetsModel - header: PlasmaExtras.Title { text: "Add Widgets" } - delegate: Item { - width: parent.width - height: 48 - Text { text: "Applet: " + pluginName } + property int minimumWidth: cellWidth + ( + widgetExplorer.orientation == Qt.Horizontal + ? 0 + : (scrollBar.width + 4 * 2) // 4 * 2 == left and right margins + ) + property int minimumHeight: topBar.height + list.delegateHeight + (widgetExplorer.orientation == Qt.Horizontal ? scrollBar.height : 0) + 4 - MouseArea { - anchors.fill: parent - onClicked: widgetExplorer.addApplet(pluginName) + property Item getWidgetsButton + property Item categoryButton + + PlasmaComponents.ContextMenu { + id: categoriesDialog + visualParent: main.categoryButton + } + Repeater { + parent: categoriesDialog + model: widgetExplorer.filterModel + delegate: PlasmaComponents.MenuItem { + text: display + separator: model["separator"] + onClicked: { + list.contentX = 0 + list.contentY = 0 + var item = widgetExplorer.filterModel.get(index) + + widgetExplorer.widgetsModel.filterType = item.filterType + widgetExplorer.widgetsModel.filterQuery = item.filterData + main.categoryButton.text = item.display + } + Component.onCompleted: { + parent = categoriesDialog } } } - Component.onCompleted: { - print("WidgetExplorer QML loaded"); - print(" found " + widgetExplorer.widgetsModel.count + " widgets"); + PlasmaComponents.ContextMenu { + id: getWidgetsDialog + visualParent: main.getWidgetsButton + } + Repeater { + parent: getWidgetsDialog + model: widgetExplorer.widgetsMenuActions + delegate: PlasmaComponents.MenuItem { + icon: modelData.icon + text: modelData.text + separator: modelData.separator + onClicked: modelData.trigger() + Component.onCompleted: { + parent = getWidgetsDialog + } + } + } + + PlasmaCore.Dialog { + id: tooltipDialog + property Item appletDelegate + + Component.onCompleted: { + tooltipDialog.setAttribute(Qt.WA_X11NetWmWindowTypeToolTip, true) + tooltipDialog.windowFlags = Qt.Window|Qt.WindowStaysOnTopHint|Qt.X11BypassWindowManagerHint + } + + onAppletDelegateChanged: { + if (!appletDelegate) { + toolTipHideTimer.restart() + toolTipShowTimer.running = false + } else if (tooltipDialog.visible) { + var point = main.tooltipPosition() + tooltipDialog.x = point.x + tooltipDialog.y = point.y + } else { + toolTipShowTimer.restart() + toolTipHideTimer.running = false + } + } + mainItem: Tooltip { id: tooltipWidget } + Behavior on x { + enabled: widgetExplorer.orientation == Qt.Horizontal + NumberAnimation { duration: 250 } + } + Behavior on y { + enabled: widgetExplorer.orientation == Qt.Vertical + NumberAnimation { duration: 250 } + } + } + Timer { + id: toolTipShowTimer + interval: 500 + repeat: false + onTriggered: { + var point = main.tooltipPosition() + tooltipDialog.x = point.x + tooltipDialog.y = point.y + tooltipDialog.visible = true + } + } + Timer { + id: toolTipHideTimer + interval: 1000 + repeat: false + onTriggered: tooltipDialog.visible = false + } + function tooltipPosition() { + return widgetExplorer.tooltipPosition(tooltipDialog.appletDelegate, tooltipDialog.width, tooltipDialog.height); + } + + Loader { + id: topBar + property Item categoryButton + + sourceComponent: (widgetExplorer.orientation == Qt.Horizontal) ? horizontalTopBarComponent : verticalTopBarComponent + height: item.height + 2 + anchors { + top: parent.top + left: parent.left + right: parent.right + + topMargin: widgetExplorer.orientation == Qt.Horizontal ? 4 : 0 + leftMargin: 4 + } + } + + Component { + id: horizontalTopBarComponent + + Item { + anchors { + top: parent.top + left: parent.left + right: parent.right + } + height: filterField.height + Row { + spacing: 5 + anchors { + left: parent.left + leftMargin: 2 + } + PlasmaComponents.TextField { + id: filterField + width: list.width / Math.floor(list.width / cellWidth) - 4 + clearButtonShown: true + placeholderText: i18n("Enter search term...") + onTextChanged: { + list.contentX = 0 + list.contentY = 0 + widgetExplorer.widgetsModel.searchTerm = text + } + Component.onCompleted: forceActiveFocus() + } + PlasmaComponents.Button { + id: categoryButton + text: i18n("Categories") + onClicked: categoriesDialog.open() + } + } + Row { + anchors.right: parent.right + spacing: 5 + PlasmaComponents.Button { + id: getWidgetsButton + iconSource: "get-hot-new-stuff" + text: i18n("Get new widgets") + onClicked: getWidgetsDialog.open() + } + + Repeater { + model: widgetExplorer.extraActions.length + PlasmaComponents.Button { + iconSource: widgetExplorer.extraActions[modelData].icon + text: widgetExplorer.extraActions[modelData].text + onClicked: { + widgetExplorer.extraActions[modelData].trigger() + } + } + } + PlasmaComponents.ToolButton { + iconSource: "window-close" + onClicked: widgetExplorer.closeClicked() + } + } + Component.onCompleted: { + main.getWidgetsButton = getWidgetsButton + main.categoryButton = categoryButton + } + } + } + + Component { + id: verticalTopBarComponent + + Column { + anchors.top: parent.top + anchors.left:parent.left + anchors.right: parent.right + spacing: 4 + + PlasmaComponents.ToolButton { + anchors.right: parent.right + iconSource: "window-close" + onClicked: widgetExplorer.closeClicked() + } + PlasmaComponents.TextField { + anchors { + left: parent.left + right: parent.right + } + clearButtonShown: true + placeholderText: i18n("Enter search term...") + onTextChanged: { + list.contentX = 0 + list.contentY = 0 + widgetExplorer.widgetsModel.searchTerm = text + } + Component.onCompleted: forceActiveFocus() + } + PlasmaComponents.Button { + anchors { + left: parent.left + right: parent.right + } + id: categoryButton + text: i18n("Categories") + onClicked: categoriesDialog.open() + } + Component.onCompleted: { + main.categoryButton = categoryButton + } + } + } + + MouseEventListener { + id: listParent + anchors { + top: topBar.bottom + left: parent.left + right: widgetExplorer.orientation == Qt.Horizontal + ? parent.right + : (scrollBar.visible ? scrollBar.left : parent.right) + bottom: widgetExplorer.orientation == Qt.Horizontal ? scrollBar.top : bottomBar.top + leftMargin: 4 + bottomMargin: 4 + } + onWheelMoved: { + //use this only if the wheel orientation is vertical and the list orientation is horizontal, otherwise will be the list itself managing the wheel + if (wheel.orientation == Qt.Vertical && list.orientation == ListView.Horizontal) { + var delta = wheel.delta > 0 ? 20 : -20 + list.contentX = Math.min(Math.max(0, list.contentWidth - list.width), + Math.max(0, list.contentX - delta)) + } + } + ListView { + id: list + + property int delegateWidth: (widgetExplorer.orientation == Qt.Horizontal) ? (list.width / Math.floor(list.width / cellWidth)) : list.width + property int delegateHeight: theme.defaultFont.mSize.height * 7 - 4 + + anchors.fill: parent + + orientation: widgetExplorer.orientation == Qt.Horizontal ? ListView.Horizontal : ListView.vertical + snapMode: ListView.SnapToItem + model: widgetExplorer.widgetsModel + + clip: widgetExplorer.orientation == Qt.Vertical + + delegate: AppletDelegate {} + } + + } + PlasmaComponents.ScrollBar { + id: scrollBar + orientation: widgetExplorer.orientation == Qt.Horizontal ? ListView.Horizontal : ListView.Vertical + anchors { + top: widgetExplorer.orientation == Qt.Horizontal ? undefined : listParent.top + bottom: widgetExplorer.orientation == Qt.Horizontal ? parent.bottom : bottomBar.top + left: widgetExplorer.orientation == Qt.Horizontal ? parent.left : undefined + right: parent.right + } + flickableItem: list + } + + Loader { + id: bottomBar + + sourceComponent: (widgetExplorer.orientation == Qt.Horizontal) ? undefined : verticalBottomBarComponent + height: item.height + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + leftMargin: 4 + } + } + + Component { + id: verticalBottomBarComponent + Column { + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + + spacing: 4 + + PlasmaComponents.Button { + anchors { + left: parent.left + right: parent.right + } + id: getWidgetsButton + iconSource: "get-hot-new-stuff" + text: i18n("Get new widgets") + onClicked: getWidgetsDialog.open() + } + + Repeater { + model: widgetExplorer.extraActions.length + PlasmaComponents.Button { + anchors { + left: parent.left + right: parent.right + } + iconSource: widgetExplorer.extraActions[modelData].icon + text: widgetExplorer.extraActions[modelData].text + onClicked: { + widgetExplorer.extraActions[modelData].trigger() + } + } + } + + Component.onCompleted: { + main.getWidgetsButton = getWidgetsButton + } + } } }