prototype for a new homescreen containment

This commit is contained in:
Marco Martin 2019-07-29 14:46:12 +02:00
parent 9d8b2f8daf
commit 8f8a23c6ea
12 changed files with 945 additions and 0 deletions

View file

@ -1,4 +1,5 @@
add_subdirectory(panel)
add_subdirectory(homescreen)
add_subdirectory(homescreen2)
add_subdirectory(taskpanel)

View file

@ -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)

View file

@ -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

View file

@ -0,0 +1,273 @@
/*
* Copyright (C) 2014 Antonis Tsiapaliokas <antonis.tsiapaliokas@kde.org>
*
* 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 <QByteArray>
#include <QModelIndex>
#include <QProcess>
// KDE
#include <KPluginInfo>
#include <KService>
#include <KServiceGroup>
#include <KServiceTypeTrader>
#include <KSharedConfig>
#include <KSycoca>
#include <KSycocaEntry>
#include <KShell>
#include <KIOWidgets/KRun>
#include <QDebug>
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<int, QByteArray> ApplicationListModel::roleNames() const
{
QHash<int, QByteArray> 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<int, ApplicationData> orderedList;
QList<ApplicationData> 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<KServiceGroup* >(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<KServiceGroup* >(entry.data()));
subGroupList << serviceGroup;
} else if (entry->property("Exec").isValid()) {
KService::Ptr service(static_cast<KService* >(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<QUrl>(), 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();
}

View file

@ -0,0 +1,90 @@
/*
* Copyright (C) 2014 Antonis Tsiapaliokas <antonis.tsiapaliokas@kde.org>
*
* 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 <QObject>
#include <QAbstractListModel>
#include <QList>
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<int, QByteArray> 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<ApplicationData> m_applicationList;
QStringList m_appOrder;
QHash<QString, int> m_appPositions;
};
#endif // APPLICATIONLISTMODEL_H

View file

@ -0,0 +1,44 @@
/***************************************************************************
* Copyright (C) 2015 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 02110-1301 USA . *
***************************************************************************/
#include "homescreen.h"
#include "applicationlistmodel.h"
#include <QtQml>
#include <QDebug>
HomeScreen::HomeScreen(QObject *parent, const QVariantList &args)
: Plasma::Containment(parent, args)
{
qmlRegisterType<ApplicationListModel>();
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"

View file

@ -0,0 +1,45 @@
/***************************************************************************
* Copyright (C) 2015 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 02110-1301 USA . *
***************************************************************************/
#ifndef HOMESCREEN_H
#define HOMESCREEN_H
#include <Plasma/Containment>
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

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="General">
<entry name="ItemsGeometries" type="String" hidden="true">
<label>Encoded geometries of items (resource categories).</label>
</entry>
<entry name="VerticalItemsGeometries" type="String" hidden="true">
<label>Encoded geometries of items, vertical screen (resource categories).</label>
</entry>
</group>
</kcfg>

View file

@ -0,0 +1,148 @@
/*
* Copyright 2011 Marco Martin <mart@kde.org>
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
*
* 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;
}
}
}

View file

@ -0,0 +1,129 @@
/*
* 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 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
}
}
}
}
}
}

View file

@ -0,0 +1,134 @@
/*
* 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 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
}
}
}
}
}
}

View file

@ -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