Commit b1a80710 authored by Marco Martin's avatar Marco Martin
Browse files

remove model duplication

we really need a single model and instance.

the 3 different menus are just proxymodels on top of it
parent 291cf113
......@@ -27,10 +27,11 @@ import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.kquickcontrolsaddons 2.0
import org.kde.private.biglauncher 1.0 as Launcher
import org.kde.kirigami 2.11 as Kirigami
import org.kde.kitemmodels 1.0 as KItemModels
import "delegates" as Delegates
import org.kde.mycroft.bigscreen 1.0 as BigScreen
import org.kde.private.biglauncher 1.0
FocusScope {
anchors {
......@@ -61,7 +62,14 @@ FocusScope {
BigScreen.TileView {
id: gridView
title: i18n("Voice Apps")
model: plasmoid.nativeInterface.voiceAppListModel
model: KItemModels.KSortFilterProxyModel {
sourceModel: plasmoid.nativeInterface.applicationListModel
filterRole: "ApplicationCategoriesRole"
filterRowCallback: function(source_row, source_parent) {
return sourceModel.data(sourceModel.index(source_row, 0, source_parent), ApplicationListModel.ApplicationCategoriesRole).indexOf("VoiceApp") !== -1;
}
}
currentIndex: 0
focus: true
onActiveFocusChanged: if (activeFocus) launcherHomeColumn.currentSection = gridView
......@@ -77,7 +85,15 @@ FocusScope {
BigScreen.TileView {
id: gridView2
title: i18n("Applications")
model: plasmoid.nativeInterface.applicationListModel
model: KItemModels.KSortFilterProxyModel {
sourceModel: plasmoid.nativeInterface.applicationListModel
filterRole: "ApplicationCategoriesRole"
filterRowCallback: function(source_row, source_parent) {
var cats = sourceModel.data(sourceModel.index(source_row, 0, source_parent), ApplicationListModel.ApplicationCategoriesRole);
return cats.indexOf("Game") === -1 && cats.indexOf("VoiceApp") === -1;
}
}
currentIndex: 0
focus: false
onActiveFocusChanged: if (activeFocus) launcherHomeColumn.currentSection = gridView2
......@@ -93,7 +109,14 @@ FocusScope {
BigScreen.TileView {
id: gridView3
title: i18n("Games")
model: plasmoid.nativeInterface.gamesAppListModel
model: KItemModels.KSortFilterProxyModel {
sourceModel: plasmoid.nativeInterface.applicationListModel
filterRole: "ApplicationCategoriesRole"
filterRowCallback: function(source_row, source_parent) {
return sourceModel.data(sourceModel.index(source_row, 0, source_parent), ApplicationListModel.ApplicationCategoriesRole).indexOf("Game") !== -1;
}
}
currentIndex: 0
focus: false
onActiveFocusChanged: if (activeFocus) launcherHomeColumn.currentSection = gridView2
......
......@@ -28,7 +28,8 @@ BigScreen.IconDelegate {
onClicked: {
feedbackWindow.open(modelData.ApplicationNameRole, modelData.ApplicationIconRole);
ListView.view.model.runApplication(modelData.ApplicationStorageIdRole)
ListView.view.model.moveItem(index, 0);
plasmoid.nativeInterface.applicationListModel.runApplication(modelData.ApplicationStorageIdRole)
plasmoid.nativeInterface.applicationListModel.moveItem(modelData.ApplicationOriginalRowRole, 0);
ListView.view.currentIndex = 0
}
}
......@@ -27,7 +27,8 @@ BigScreen.IconDelegate {
text: modelData ? modelData.ApplicationNameRole : ""
onClicked: {
plasmoid.nativeInterface.voiceAppListModel.runApplication(modelData.ApplicationStorageIdRole)
plasmoid.nativeInterface.voiceAppListModel.moveItem(index, 0);
plasmoid.nativeInterface.applicationListModel.runApplication(modelData.ApplicationStorageIdRole)
plasmoid.nativeInterface.applicationListModel.moveItem(modelData.ApplicationOriginalRowRole, 0);
ListView.view.currentIndex = 0
}
}
......@@ -5,9 +5,7 @@ add_definitions(-DTRANSLATION_DOMAIN=\"biglauncherhomescreen\")
set(biglauncherhomescreen_SRCS
biglauncherhomescreen.cpp
biglauncher_dbus.cpp
applicationlistmodel.cpp
voiceapplistmodel.cpp
gamesapplistmodel.cpp)
applicationlistmodel.cpp)
add_library(plasma_containment_biglauncherhomescreen MODULE ${biglauncherhomescreen_SRCS})
......
......@@ -54,6 +54,7 @@ QHash<int, QByteArray> ApplicationListModel::roleNames() const
roleNames[ApplicationNameRole] = "ApplicationNameRole";
roleNames[ApplicationCommentRole] = "ApplicationCommentRole";
roleNames[ApplicationIconRole] = "ApplicationIconRole";
roleNames[ApplicationCategoriesRole] = "ApplicationCategoriesRole";
roleNames[ApplicationStorageIdRole] = "ApplicationStorageIdRole";
roleNames[ApplicationEntryPathRole] = "ApplicationEntryPathRole";
roleNames[ApplicationDesktopRole] = "ApplicationDesktopRole";
......@@ -120,7 +121,7 @@ void ApplicationListModel::loadApplications()
KServiceGroup::Ptr serviceGroup(static_cast<KServiceGroup* >(entry.data()));
subGroupList << serviceGroup;
} else if (entry->property("Exec").isValid() && entry->property("Categories") != "VoiceApp" && !entry->property("Categories").toStringList().contains("Game")) {
} else if (entry->property("Exec").isValid()) {
qDebug() << entry->property("Categories");
KService::Ptr service(static_cast<KService* >(entry.data()));
qDebug() << " desktopEntryName: " << service->desktopEntryName();
......@@ -141,6 +142,7 @@ void ApplicationListModel::loadApplications()
data.name = service->name();
data.comment = service->comment();
data.icon = service->icon();
data.categories = service->categories();
data.storageId = service->storageId();
data.entryPath = service->exec();
data.desktopPath = service->entryPath();
......@@ -185,6 +187,8 @@ QVariant ApplicationListModel::data(const QModelIndex &index, int role) const
return m_applicationList.at(index.row()).comment;
case ApplicationIconRole:
return m_applicationList.at(index.row()).icon;
case ApplicationCategoriesRole:
return m_applicationList.at(index.row()).categories;
case ApplicationStorageIdRole:
return m_applicationList.at(index.row()).storageId;
case ApplicationEntryPathRole:
......@@ -271,7 +275,7 @@ void ApplicationListModel::runApplication(const QString &storageId)
KService::Ptr service = KService::serviceByStorageId(storageId);
KRun::runService(*service, QList<QUrl>(), nullptr);
KRun::runApplication(*service, QList<QUrl>(), nullptr);
}
QStringList ApplicationListModel::appOrder() const
......
......@@ -31,6 +31,7 @@ struct ApplicationData {
QString name;
QString comment;
QString icon;
QStringList categories;
QString storageId;
QString entryPath;
QString desktopPath;
......@@ -63,12 +64,14 @@ public:
ApplicationNameRole = Qt::UserRole + 1,
ApplicationCommentRole,
ApplicationIconRole,
ApplicationCategoriesRole,
ApplicationStorageIdRole,
ApplicationEntryPathRole,
ApplicationDesktopRole,
ApplicationStartupNotifyRole,
ApplicationOriginalRowRole
};
Q_ENUM(Roles)
QStringList appOrder() const;
void setAppOrder(const QStringList &order);
......
......@@ -20,8 +20,6 @@
#include "biglauncherhomescreen.h"
#include "biglauncher_dbus.h"
#include "applicationlistmodel.h"
#include "voiceapplistmodel.h"
#include "gamesapplistmodel.h"
#include <QDebug>
#include <QProcess>
......@@ -32,14 +30,10 @@ HomeScreen::HomeScreen(QObject *parent, const QVariantList &args)
{
const QByteArray uri("org.kde.private.biglauncher");
qmlRegisterUncreatableType<ApplicationListModel>(uri, 1, 0, "ApplicationListModel", QStringLiteral("Cannot create an item of type ApplicationListModel"));
qmlRegisterUncreatableType<VoiceAppListModel>(uri, 1, 0, "VoiceAppListModel", QStringLiteral("Cannot create an item of type VoiceAppListModel"));
qmlRegisterUncreatableType<GamesAppListModel>(uri, 1, 0, "GamesAppListModel", QStringLiteral("Cannot create an item of type GamesAppListModel"));
//setHasConfigurationInterface(true);
auto bigLauncherDbusAdapterInterface = new BigLauncherDbusAdapterInterface(this);
m_applicationListModel = new ApplicationListModel(this);
m_voiceAppListModel = new VoiceAppListModel(this);
m_gamesAppListModel = new GamesAppListModel(this);
}
HomeScreen::~HomeScreen()
......@@ -50,16 +44,6 @@ ApplicationListModel *HomeScreen::applicationListModel() const
return m_applicationListModel;
}
VoiceAppListModel *HomeScreen::voiceAppListModel() const
{
return m_voiceAppListModel;
}
GamesAppListModel *HomeScreen::gamesAppListModel() const
{
return m_gamesAppListModel;
}
void HomeScreen::executeCommand(const QString &command)
{
qWarning()<<"Executing"<<command;
......
......@@ -24,31 +24,23 @@
#include <Plasma/Containment>
class ApplicationListModel;
class VoiceAppListModel;
class GamesAppListModel;
class HomeScreen : public Plasma::Containment
{
Q_OBJECT
Q_PROPERTY(ApplicationListModel *applicationListModel READ applicationListModel CONSTANT)
Q_PROPERTY(VoiceAppListModel *voiceAppListModel READ voiceAppListModel CONSTANT)
Q_PROPERTY(GamesAppListModel *gamesAppListModel READ gamesAppListModel CONSTANT)
public:
HomeScreen( QObject *parent, const QVariantList &args );
~HomeScreen() override;
ApplicationListModel *applicationListModel() const;
VoiceAppListModel *voiceAppListModel() const;
GamesAppListModel *gamesAppListModel() const;
public Q_SLOTS:
void executeCommand(const QString &command);
private:
ApplicationListModel *m_applicationListModel;
VoiceAppListModel *m_voiceAppListModel;
GamesAppListModel *m_gamesAppListModel;
};
/*
* 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 "gamesapplistmodel.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>
GamesAppListModel::GamesAppListModel(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 &)));
}
GamesAppListModel::~GamesAppListModel()
= default;
QHash<int, QByteArray> GamesAppListModel::roleNames() const
{
QHash<int, QByteArray> roleNames;
roleNames[ApplicationNameRole] = "ApplicationNameRole";
roleNames[ApplicationIconRole] = "ApplicationIconRole";
roleNames[ApplicationStorageIdRole] = "ApplicationStorageIdRole";
roleNames[ApplicationEntryPathRole] = "ApplicationEntryPathRole";
roleNames[ApplicationDesktopRole] = "ApplicationDesktopRole";
roleNames[ApplicationStartupNotifyRole] = "ApplicationStartupNotifyRole";
roleNames[ApplicationOriginalRowRole] = "ApplicationOriginalRowRole";
return roleNames;
}
void GamesAppListModel::sycocaDbChanged(const QStringList &changes)
{
if (!changes.contains("apps") && !changes.contains("xdgdata-apps")) {
return;
}
m_applicationList.clear();
loadApplications();
}
bool appNameLessThan(const GapplicationData &a1, const GapplicationData &a2)
{
return a1.name.toLower() < a2.name.toLower();
}
void GamesAppListModel::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, GapplicationData> orderedList;
QList<GapplicationData> 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("Categories").toStringList().contains("Game")) {
qDebug() << entry->property("Categories").toStringList();
KService::Ptr service(static_cast<KService* >(entry.data()));
qDebug() << " desktopEntryName: " << service->desktopEntryName();
//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();
GapplicationData data;
data.name = service->name();
data.icon = service->icon();
data.storageId = service->storageId();
data.entryPath = service->exec();
data.desktopPath = service->entryPath();
data.startupNotify = service->property("StartupNotify").toBool();
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 GamesAppListModel::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 ApplicationDesktopRole:
return m_applicationList.at(index.row()).desktopPath;
case ApplicationStartupNotifyRole:
return m_applicationList.at(index.row()).startupNotify;
case ApplicationOriginalRowRole:
return index.row();
default:
return QVariant();
}
}
Qt::ItemFlags GamesAppListModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return nullptr;
return Qt::ItemIsDragEnabled|QAbstractItemModel::flags(index);
}
int GamesAppListModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_applicationList.count();
}
void GamesAppListModel::moveRow(const QModelIndex& /* sourceParent */, int sourceRow, const QModelIndex& /* destinationParent */, int destinationChild)
{
moveItem(sourceRow, destinationChild);
}
Q_INVOKABLE void GamesAppListModel::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) {
GapplicationData data = m_applicationList.at(row);
m_applicationList.insert(destination, data);
m_applicationList.takeAt(row);
} else {
GapplicationData 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 GamesAppListModel::runApplication(const QString &storageId)
{
if (storageId.isEmpty()) {
return;
}
KService::Ptr service = KService::serviceByStorageId(storageId);
KRun::runService(*service, QList<QUrl>(), nullptr);
}
QStringList GamesAppListModel::appOrder() const
{
return m_appOrder;
}
void GamesAppListModel::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();
}
/*
* 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 GAMEAPPLISTMODEL_H
#define GAMEAPPLISTMODEL_H
// Qt
#include <QObject>
#include <QAbstractListModel>
#include <QList>
class QString;
struct GapplicationData {
QString name;
QString icon;
QString storageId;
QString entryPath;
QString desktopPath;
bool startupNotify = true;
};
class GamesAppListModel : public QAbstractListModel {
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(QStringList appOrder READ appOrder WRITE setAppOrder NOTIFY appOrderChanged)
public:
GamesAppListModel(QObject *parent = nullptr);
~GamesAppListModel() 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,
ApplicationStorageIdRole,
ApplicationEntryPathRole,
ApplicationDesktopRole,
ApplicationStartupNotifyRole,
ApplicationOriginalRowRole