mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-27 14:33:08 +00:00
prototype for a new homescreen containment
This commit is contained in:
parent
9d8b2f8daf
commit
8f8a23c6ea
12 changed files with 945 additions and 0 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
add_subdirectory(panel)
|
add_subdirectory(panel)
|
||||||
add_subdirectory(homescreen)
|
add_subdirectory(homescreen)
|
||||||
|
add_subdirectory(homescreen2)
|
||||||
add_subdirectory(taskpanel)
|
add_subdirectory(taskpanel)
|
||||||
|
|
|
||||||
23
containments/homescreen2/CMakeLists.txt
Normal file
23
containments/homescreen2/CMakeLists.txt
Normal 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)
|
||||||
|
|
||||||
4
containments/homescreen2/Messages.sh
Executable file
4
containments/homescreen2/Messages.sh
Executable 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
|
||||||
273
containments/homescreen2/applicationlistmodel.cpp
Normal file
273
containments/homescreen2/applicationlistmodel.cpp
Normal 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();
|
||||||
|
}
|
||||||
90
containments/homescreen2/applicationlistmodel.h
Normal file
90
containments/homescreen2/applicationlistmodel.h
Normal 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
|
||||||
44
containments/homescreen2/homescreen.cpp
Normal file
44
containments/homescreen2/homescreen.cpp
Normal 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"
|
||||||
45
containments/homescreen2/homescreen.h
Normal file
45
containments/homescreen2/homescreen.h
Normal 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
|
||||||
17
containments/homescreen2/package/contents/config/main.xml
Normal file
17
containments/homescreen2/package/contents/config/main.xml
Normal 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>
|
||||||
148
containments/homescreen2/package/contents/ui/ActionButton.qml
Normal file
148
containments/homescreen2/package/contents/ui/ActionButton.qml
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
containments/homescreen2/package/contents/ui/ConfigOverlay.qml
Normal file
129
containments/homescreen2/package/contents/ui/ConfigOverlay.qml
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
134
containments/homescreen2/package/contents/ui/main.qml
Normal file
134
containments/homescreen2/package/contents/ui/main.qml
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
containments/homescreen2/package/metadata.desktop
Normal file
37
containments/homescreen2/package/metadata.desktop
Normal 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
|
||||||
Loading…
Reference in a new issue