diff --git a/containments/CMakeLists.txt b/containments/CMakeLists.txt index a1915629..fd2ddeab 100644 --- a/containments/CMakeLists.txt +++ b/containments/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(panel) add_subdirectory(homescreen) +add_subdirectory(homescreen2) add_subdirectory(taskpanel) diff --git a/containments/homescreen2/CMakeLists.txt b/containments/homescreen2/CMakeLists.txt new file mode 100644 index 00000000..487849d6 --- /dev/null +++ b/containments/homescreen2/CMakeLists.txt @@ -0,0 +1,23 @@ +set(homescreen_SRCS + homescreen.cpp + applicationlistmodel.cpp +) + +add_library(plasma_containment_phone_homescreen2 MODULE ${homescreen_SRCS}) + +kcoreaddons_desktop_to_json(plasma_containment_phone_homescreen2 package/metadata.desktop) + +target_link_libraries(plasma_containment_phone_homescreen2 + Qt5::Gui + KF5::Plasma + Qt5::Qml + KF5::I18n + KF5::Service + KF5::KIOWidgets + ) + + +install(TARGETS plasma_containment_phone_homescreen2 DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/applets) + +plasma_install_package(package org.kde.phone.homescreen2) + diff --git a/containments/homescreen2/Messages.sh b/containments/homescreen2/Messages.sh new file mode 100755 index 00000000..c0782d94 --- /dev/null +++ b/containments/homescreen2/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_org.kde.phone.homescreen.pot +rm -f rc.cpp diff --git a/containments/homescreen2/applicationlistmodel.cpp b/containments/homescreen2/applicationlistmodel.cpp new file mode 100644 index 00000000..b3e06c71 --- /dev/null +++ b/containments/homescreen2/applicationlistmodel.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2014 Antonis Tsiapaliokas + * + * 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. + */ + +// Self +#include "applicationlistmodel.h" + +// Qt +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ApplicationListModel::ApplicationListModel(QObject *parent) + : QAbstractListModel(parent) +{ + //can't use the new syntax as this signal is overloaded + connect(KSycoca::self(), SIGNAL(databaseChanged(const QStringList &)), + this, SLOT(sycocaDbChanged(const QStringList &))); +} + +ApplicationListModel::~ApplicationListModel() += default; + +QHash ApplicationListModel::roleNames() const +{ + QHash roleNames; + roleNames[ApplicationNameRole] = "ApplicationNameRole"; + roleNames[ApplicationIconRole] = "ApplicationIconRole"; + roleNames[ApplicationStorageIdRole] = "ApplicationStorageIdRole"; + roleNames[ApplicationEntryPathRole] = "ApplicationEntryPathRole"; + roleNames[ApplicationOriginalRowRole] = "ApplicationOriginalRowRole"; + + return roleNames; +} + +void ApplicationListModel::sycocaDbChanged(const QStringList &changes) +{ + if (!changes.contains("apps") && !changes.contains("xdgdata-apps")) { + return; + } + + m_applicationList.clear(); + + loadApplications(); +} + +bool appNameLessThan(const ApplicationData &a1, const ApplicationData &a2) +{ + return a1.name.toLower() < a2.name.toLower(); +} + +void ApplicationListModel::loadApplications() +{ + auto cfg = KSharedConfig::openConfig("applications-blacklistrc"); + auto blgroup = KConfigGroup(cfg, QStringLiteral("Applications")); + + // This is only temporary to get a clue what those apps' desktop files are called + // I'll remove it once I've done a blacklist + QStringList bl; + + QStringList blacklist = blgroup.readEntry("blacklist", QStringList()); + + + beginResetModel(); + + m_applicationList.clear(); + + KServiceGroup::Ptr group = KServiceGroup::root(); + if (!group || !group->isValid()) return; + KServiceGroup::List subGroupList = group->entries(true); + + QMap orderedList; + QList unorderedList; + + // Iterate over all entries in the group + while (!subGroupList.isEmpty()) { + KSycocaEntry::Ptr groupEntry = subGroupList.first(); + subGroupList.pop_front(); + + if (groupEntry->isType(KST_KServiceGroup)) { + KServiceGroup::Ptr serviceGroup(static_cast(groupEntry.data())); + + if (!serviceGroup->noDisplay()) { + KServiceGroup::List entryGroupList = serviceGroup->entries(true); + + for(KServiceGroup::List::ConstIterator it = entryGroupList.constBegin(); it != entryGroupList.constEnd(); it++) { + KSycocaEntry::Ptr entry = (*it); + + if (entry->isType(KST_KServiceGroup)) { + KServiceGroup::Ptr serviceGroup(static_cast(entry.data())); + subGroupList << serviceGroup; + + } else if (entry->property("Exec").isValid()) { + KService::Ptr service(static_cast(entry.data())); + + qDebug() << " desktopEntryName: " << service->desktopEntryName(); + + if (service->isApplication() && + !blacklist.contains(service->desktopEntryName()) && + service->showOnCurrentPlatform() && + !service->property("Terminal", QVariant::Bool).toBool()) { + + bl << service->desktopEntryName(); + + ApplicationData data; + data.name = service->name(); + data.icon = service->icon(); + data.storageId = service->storageId(); + data.entryPath = service->exec(); + + auto it = m_appPositions.constFind(service->storageId()); + if (it != m_appPositions.constEnd()) { + orderedList[*it] = data; + } else { + unorderedList << data; + } + } + } + } + } + } + } + + blgroup.writeEntry("allapps", bl); + blgroup.writeEntry("blacklist", blacklist); + cfg->sync(); + + std::sort(unorderedList.begin(), unorderedList.end(), appNameLessThan); + m_applicationList << orderedList.values(); + m_applicationList << unorderedList; + + endResetModel(); + emit countChanged(); +} + +QVariant ApplicationListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + switch (role) { + case Qt::DisplayRole: + case ApplicationNameRole: + return m_applicationList.at(index.row()).name; + case ApplicationIconRole: + return m_applicationList.at(index.row()).icon; + case ApplicationStorageIdRole: + return m_applicationList.at(index.row()).storageId; + case ApplicationEntryPathRole: + return m_applicationList.at(index.row()).entryPath; + case ApplicationOriginalRowRole: + return index.row(); + + default: + return QVariant(); + } +} + +Qt::ItemFlags ApplicationListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return nullptr; + return Qt::ItemIsDragEnabled|QAbstractItemModel::flags(index); +} + +int ApplicationListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + + return m_applicationList.count(); +} + +void ApplicationListModel::moveRow(const QModelIndex& /* sourceParent */, int sourceRow, const QModelIndex& /* destinationParent */, int destinationChild) +{ + moveItem(sourceRow, destinationChild); +} + +Q_INVOKABLE void ApplicationListModel::moveItem(int row, int destination) +{ + if (row < 0 || destination < 0 || row >= m_applicationList.length() || + destination >= m_applicationList.length() || row == destination) { + return; + } + if (destination > row) { + ++destination; + } + + beginMoveRows(QModelIndex(), row, row, QModelIndex(), destination); + if (destination > row) { + ApplicationData data = m_applicationList.at(row); + m_applicationList.insert(destination, data); + m_applicationList.takeAt(row); + } else { + ApplicationData data = m_applicationList.takeAt(row); + m_applicationList.insert(destination, data); + } + + + m_appOrder.clear(); + m_appPositions.clear(); + int i = 0; + for (auto app : m_applicationList) { + m_appOrder << app.storageId; + m_appPositions[app.storageId] = i; + ++i; + } + + + emit appOrderChanged(); + endMoveRows(); +} + +void ApplicationListModel::runApplication(const QString &storageId) +{ + if (storageId.isEmpty()) { + return; + } + + KService::Ptr service = KService::serviceByStorageId(storageId); + + KRun::runService(*service, QList(), nullptr); +} + +QStringList ApplicationListModel::appOrder() const +{ + return m_appOrder; +} + +void ApplicationListModel::setAppOrder(const QStringList &order) +{ + if (m_appOrder == order) { + return; + } + + m_appOrder = order; + m_appPositions.clear(); + int i = 0; + for (auto app : m_appOrder) { + m_appPositions[app] = i; + ++i; + } + emit appOrderChanged(); +} diff --git a/containments/homescreen2/applicationlistmodel.h b/containments/homescreen2/applicationlistmodel.h new file mode 100644 index 00000000..ddf65bf5 --- /dev/null +++ b/containments/homescreen2/applicationlistmodel.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2014 Antonis Tsiapaliokas + * + * 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. + */ + +#ifndef APPLICATIONLISTMODEL_H +#define APPLICATIONLISTMODEL_H + +// Qt +#include +#include +#include + +class QString; + +struct ApplicationData { + QString name; + QString icon; + QString storageId; + QString entryPath; +}; + +class ApplicationListModel : public QAbstractListModel { + Q_OBJECT + + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(QStringList appOrder READ appOrder WRITE setAppOrder NOTIFY appOrderChanged) + +public: + ApplicationListModel(QObject *parent = nullptr); + ~ApplicationListModel() override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + + void moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild); + + int count() { return m_applicationList.count(); } + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + + Qt::ItemFlags flags(const QModelIndex &index) const override; + + QHash roleNames() const Q_DECL_OVERRIDE; + + enum Roles { + ApplicationNameRole = Qt::UserRole + 1, + ApplicationIconRole = Qt::UserRole + 2, + ApplicationStorageIdRole = Qt::UserRole + 3, + ApplicationEntryPathRole = Qt::UserRole + 4, + ApplicationOriginalRowRole = Qt::UserRole + 6 + }; + + QStringList appOrder() const; + void setAppOrder(const QStringList &order); + + Q_INVOKABLE void moveItem(int row, int order); + + Q_INVOKABLE void runApplication(const QString &storageId); + + Q_INVOKABLE void loadApplications(); + +public Q_SLOTS: + void sycocaDbChanged(const QStringList &change); + +Q_SIGNALS: + void countChanged(); + void appOrderChanged(); + +private: + QList m_applicationList; + + QStringList m_appOrder; + QHash m_appPositions; +}; + +#endif // APPLICATIONLISTMODEL_H diff --git a/containments/homescreen2/homescreen.cpp b/containments/homescreen2/homescreen.cpp new file mode 100644 index 00000000..452667e4 --- /dev/null +++ b/containments/homescreen2/homescreen.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2015 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 02110-1301 USA . * + ***************************************************************************/ + +#include "homescreen.h" +#include "applicationlistmodel.h" + +#include +#include + +HomeScreen::HomeScreen(QObject *parent, const QVariantList &args) + : Plasma::Containment(parent, args) +{ + qmlRegisterType(); + m_applicationListModel = new ApplicationListModel(this); + setHasConfigurationInterface(true); +} + +HomeScreen::~HomeScreen() += default; + +ApplicationListModel *HomeScreen::applicationListModel() +{ + return m_applicationListModel; +} + +K_EXPORT_PLASMA_APPLET_WITH_JSON(homescreen, HomeScreen, "metadata.json") + +#include "homescreen.moc" diff --git a/containments/homescreen2/homescreen.h b/containments/homescreen2/homescreen.h new file mode 100644 index 00000000..6a7bbf18 --- /dev/null +++ b/containments/homescreen2/homescreen.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2015 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 02110-1301 USA . * + ***************************************************************************/ + +#ifndef HOMESCREEN_H +#define HOMESCREEN_H + + +#include + +class ApplicationListModel; + +class HomeScreen : public Plasma::Containment +{ + Q_OBJECT + Q_PROPERTY(ApplicationListModel *applicationListModel READ applicationListModel CONSTANT) + +public: + HomeScreen( QObject *parent, const QVariantList &args ); + ~HomeScreen() override; + + ApplicationListModel *applicationListModel(); + +private: + ApplicationListModel *m_applicationListModel; + +}; + +#endif diff --git a/containments/homescreen2/package/contents/config/main.xml b/containments/homescreen2/package/contents/config/main.xml new file mode 100644 index 00000000..d35a3081 --- /dev/null +++ b/containments/homescreen2/package/contents/config/main.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/containments/homescreen2/package/contents/ui/ActionButton.qml b/containments/homescreen2/package/contents/ui/ActionButton.qml new file mode 100644 index 00000000..a468bc44 --- /dev/null +++ b/containments/homescreen2/package/contents/ui/ActionButton.qml @@ -0,0 +1,148 @@ +/* + * Copyright 2011 Marco Martin + * Copyright 2013 Sebastian Kügler + * + * 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 + +PlasmaCore.ToolTipArea { + id: button + + location: PlasmaCore.Types.LeftEdge + mainText: action !== undefined ? action.text : "" + mainItem: toolTipDelegate + + //API + property PlasmaCore.Svg svg + property alias elementId: icon.elementId + property QtObject action + property bool backgroundVisible: false + property int iconSize: 32 + property int pressedOffset: 1 + property bool checked: false + property bool toggle: false + property string text + signal clicked + + implicitWidth: buttonRow.implicitWidth + implicitHeight: buttonRow.implicitHeight + + opacity: action==undefined||action.enabled?1:0.6 + + Behavior on opacity { + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + + onCheckedChanged: { + if (checked) { + buttonItem.elementId = "pressed" + shadowItem.opacity = 0 + } else { + buttonItem.elementId = "normal" + shadowItem.opacity = 1 + } + } + + PlasmaCore.Svg { + id: buttonSvg + imagePath: "widgets/actionbutton" + } + + PlasmaCore.SvgItem { + id: shadowItem + svg: buttonSvg + elementId: "shadow" + width: iconSize+13//button.backgroundVisible?iconSize+8:iconSize + height: width + visible: button.backgroundVisible + } + + Row { + id: buttonRow + + Item { + width: buttonItem.visible?buttonItem.width:iconSize + height: buttonItem.visible?buttonItem.height:iconSize + + PlasmaCore.SvgItem { + id: buttonItem + svg: buttonSvg + elementId: "normal" + width: shadowItem.width + height: shadowItem.height + visible: backgroundVisible + } + + PlasmaCore.SvgItem { + id: icon + width: iconSize + height: iconSize + svg: button.svg + anchors.centerIn: parent + } + } + + Text { + id: actionText + text: button.text + style: Text.Outline + color: theme.textColor + styleColor: Qt.rgba(1,1,1,0.4) + anchors.verticalCenter: parent.verticalCenter + } + } + + MouseArea { + anchors.fill: parent + anchors.leftMargin: -10 + anchors.topMargin: -10 + anchors.rightMargin: -10 + anchors.bottomMargin: -10 + preventStealing: true + onPressed: { + buttonItem.elementId = "pressed" + shadowItem.opacity = 0; + button.x = button.x + button.pressedOffset; + button.y = button.y + button.pressedOffset; + } + onReleased: { + if (button.checked || !button.toggle) { + buttonItem.elementId = "normal" + shadowItem.opacity = 1 + button.checked = false + } else { + button.checked = true + } + button.x = button.x - button.pressedOffset; + button.y = button.y - button.pressedOffset; + } + onClicked: { + if (action) { + action.trigger() + } else { + button.clicked() + } + appletContainer.editMode = false; + } + } +} diff --git a/containments/homescreen2/package/contents/ui/ConfigOverlay.qml b/containments/homescreen2/package/contents/ui/ConfigOverlay.qml new file mode 100644 index 00000000..ce717b53 --- /dev/null +++ b/containments/homescreen2/package/contents/ui/ConfigOverlay.qml @@ -0,0 +1,129 @@ +/* + * Copyright 2019 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.12 +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 3.0 as PlasmaComponents + +import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager + +ContainmentLayoutManager.ConfigOverlayWithHandles { + id: overlay + + readonly property int iconSize: units.iconSizes.small + PlasmaCore.Svg { + id: configIconsSvg + imagePath: "widgets/configuration-icons" + } + + PlasmaComponents.Label { + id: toolTipDelegate + + width: contentWidth + height: undefined + + property Item toolTip + + text: (toolTip != null) ? toolTip.mainText : "" + } + + SequentialAnimation { + id: removeAnim + NumberAnimation { + target: overlay.itemContainer + property: "scale" + from: 1 + to: 0 + duration: units.longDuration + easing.type: Easing.InOutQuad + } + ScriptAction { + script: { + appletContainer.applet.action("remove").trigger(); + appletContainer.editMode = false; + } + } + } + PlasmaCore.FrameSvgItem { + id: frame + anchors.centerIn: parent + + width: layout.implicitWidth + margins.left + margins.right + height: layout.implicitHeight + margins.top + margins.bottom + imagePath: "widgets/background" + + RowLayout { + id: layout + spacing: units.largeSpacing + anchors { + fill: parent + topMargin: parent.margins.top + leftMargin: parent.margins.left + bottomMargin: parent.margins.bottom + rightMargin: parent.margins.right + } + + ActionButton { + svg: configIconsSvg + elementId: "configure" + iconSize: overlay.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 { + id: closeButton + svg: configIconsSvg + elementId: "delete" + mainText: i18n("Remove") + iconSize: overlay.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 overlay.itemContainer, we just + // emit a signal here to avoid the applet-gets-removed-before-we- + // can-animate it race condition. + onClicked: { + removeAnim.restart(); + } + Component.onCompleted: { + var a = applet.action("remove"); + if (a && typeof(a) != "undefined") { + a.enabled = true + } + } + } + } + } +} + diff --git a/containments/homescreen2/package/contents/ui/main.qml b/containments/homescreen2/package/contents/ui/main.qml new file mode 100644 index 00000000..5253437b --- /dev/null +++ b/containments/homescreen2/package/contents/ui/main.qml @@ -0,0 +1,134 @@ +/* + * Copyright 2019 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.12 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.2 as Controls +import QtGraphicalEffects 1.0 + +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.draganddrop 2.0 as DragDrop + +import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager + +Item { + id: root + width: 640 + height: 480 + + property Item toolBox + + DragDrop.DropArea { + anchors.fill: parent + + //TODO type safety? + property Item appletsArea + onDragEnter: { + event.accept(event.proposedAction); + } + onDragMove: { + appletsLayout.showPlaceHolderAt( + Qt.rect(event.x - appletsLayout.defaultItemWidth / 2, + event.y - appletsLayout.defaultItemHeight / 2, + appletsLayout.defaultItemWidth, + appletsLayout.defaultItemHeight) + ); + } + + onDragLeave: { + appletsLayout.hidePlaceHolder(); + } + + preventStealing: true + + onDrop: { + plasmoid.processMimeData(event.mimeData, + event.x - appletsLayout.placeHolder.width / 2, event.y - appletsLayout.placeHolder.height / 2); + event.accept(event.proposedAction); + appletsLayout.hidePlaceHolder(); + } + +Text { + text:"Edit Mode" + color: "white" + visible: appletsLayout.editMode +} + Connections { + target: plasmoid + onEditModeChanged: appletsLayout.editMode = plasmoid.editMode + } + + ContainmentLayoutManager.AppletsLayout { + id: appletsLayout + anchors.fill: parent + configKey: width > height ? "ItemGeometries" : "ItemGeometriesVertical" + containment: plasmoid + editModeCondition: plasmoid.immutable + ? ContainmentLayoutManager.AppletsLayout.Manual + : ContainmentLayoutManager.AppletsLayout.AfterPressAndHold + + // Sets the containment in edit mode when we go in edit mode as well + onEditModeChanged: plasmoid.editMode = editMode + + minimumItemWidth: units.gridUnit * 3 + minimumItemHeight: minimumItemWidth + + defaultItemWidth: units.gridUnit * 6 + defaultItemHeight: defaultItemWidth + + cellWidth: units.iconSizes.small + cellHeight: cellWidth + + acceptsAppletCallback: function(applet, x, y) { + print("Applet: "+applet+" "+x+" "+y) + return true; + } + + appletContainerComponent: ContainmentLayoutManager.BasicAppletContainer { + id: appletContainer + configOverlayComponent: ConfigOverlay {} + } + + placeHolder: ContainmentLayoutManager.PlaceHolder {} + + Repeater { + 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 { + anchors.fill: parent + color: extraIcon.focus ? "green" : "red" + radius: width + opacity: extraIcon.editMode ? 0.6 : 1 + } + } + } + } + } +} diff --git a/containments/homescreen2/package/metadata.desktop b/containments/homescreen2/package/metadata.desktop new file mode 100644 index 00000000..cc05cf69 --- /dev/null +++ b/containments/homescreen2/package/metadata.desktop @@ -0,0 +1,37 @@ +[Desktop Entry] +Encoding=UTF-8 +Keywords= +Name=Phone Homescreen +Name[ca]=Pantalla d'inici del telèfon +Name[ca@valencia]=Pantalla d'inici del telèfon +Name[cs]=Domácí obrazovka telefonu +Name[en_GB]=Phone Homescreen +Name[es]=Pantalla de inicio del teléfono +Name[fi]=Phonen aloitusnäyttö +Name[fr]=Page d'accueil du téléphone +Name[gl]=Pantalla de inicio do teléfono +Name[it]=Schermata home del telefono +Name[ko]=전화 홈 화면 +Name[nl]=Standaardscherm van de telefoon +Name[nn]=Heimebilete for telefon +Name[pl]=Ekran domowy telefonu +Name[pt]=Ecrã Inicial +Name[sv]=Telefonens hemskärm +Name[tr]=Telefon Ana Ekranı +Name[uk]=Домашня сторінка телефону +Name[x-test]=xxPhone Homescreenxx +Name[zh_CN]=手机主屏幕 +Name[zh_TW]=手機的主畫面 +Type=Service + +X-KDE-ServiceTypes=Plasma/Applet,Plasma/Containment +X-Plasma-API=declarativeappletscript +X-KDE-Library=plasma_containment_phone_homescreen2 +X-KDE-PluginInfo-Author=Marco Martin +X-KDE-PluginInfo-Category=Containments +X-KDE-PluginInfo-Email=mart@kde.org +X-KDE-PluginInfo-License=GPLv2+ +X-KDE-PluginInfo-Name=org.kde.phone.homescreen2 +X-KDE-PluginInfo-Version= +X-KDE-PluginInfo-Website= +X-Plasma-MainScript=ui/main.qml