diff --git a/applets/kicker/plugin/computermodel.cpp b/applets/kicker/plugin/computermodel.cpp index b45d6899a..41ea6b55e 100644 --- a/applets/kicker/plugin/computermodel.cpp +++ b/applets/kicker/plugin/computermodel.cpp @@ -1,302 +1,304 @@ /*************************************************************************** * Copyright (C) 2007 Kevin Ottens * * Copyright (C) 2015 by Eike Hein * * * * 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 "computermodel.h" #include "actionlist.h" #include "favoritesmodel.h" #include #include #include #include #include #include #include #include "krunner_interface.h" FilteredPlacesModel::FilteredPlacesModel(QObject *parent) : QSortFilterProxyModel(parent) , m_placesModel(new KFilePlacesModel(this)) { setSourceModel(m_placesModel); sort(0); } FilteredPlacesModel::~FilteredPlacesModel() { } QUrl FilteredPlacesModel::url(const QModelIndex &index) const { return m_placesModel->url(mapToSource(index)); } bool FilteredPlacesModel::isDevice(const QModelIndex &index) const { return m_placesModel->isDevice(mapToSource(index)); } Solid::Device FilteredPlacesModel::deviceForIndex(const QModelIndex &index) const { return m_placesModel->deviceForIndex(mapToSource(index)); } bool FilteredPlacesModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { const QModelIndex index = m_placesModel->index(sourceRow, 0, sourceParent); return !m_placesModel->isHidden(index) && !m_placesModel->data(index, KFilePlacesModel::FixedDeviceRole).toBool(); } bool FilteredPlacesModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { bool lDevice = m_placesModel->isDevice(left); bool rDevice = m_placesModel->isDevice(right); if (lDevice && !rDevice) { return false; } else if (!lDevice && rDevice) { return true; } return (left.row() < right.row()); } RunCommandModel::RunCommandModel(QObject *parent) : AbstractModel(parent) { } RunCommandModel::~RunCommandModel() { } QString RunCommandModel::description() const { return QString(); } QVariant RunCommandModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (role == Qt::DisplayRole) { return i18n("Run Command..."); } else if (role == Qt::DecorationRole) { return QIcon::fromTheme(QStringLiteral("system-run")); } else if (role == Kicker::DescriptionRole) { return i18n("Run a command or a search query"); } else if (role == Kicker::GroupRole) { return i18n("Applications"); } return QVariant(); } int RunCommandModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : (KAuthorized::authorize(QStringLiteral("run_command")) ? 1 : 0); } Q_INVOKABLE bool RunCommandModel::trigger(int row, const QString &actionId, const QVariant &argument) { Q_UNUSED(actionId) Q_UNUSED(argument) if (row == 0 && KAuthorized::authorize(QStringLiteral("run_command"))) { org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); krunner.display(); return true; } return false; } ComputerModel::ComputerModel(QObject *parent) : ForwardingModel(parent) , m_concatProxy(new KConcatenateRowsProxyModel(this)) , m_runCommandModel(new RunCommandModel(this)) , m_systemAppsModel(new FavoritesModel(this)) , m_filteredPlacesModel(new FilteredPlacesModel(this)) , m_appNameFormat(AppEntry::NameOnly) , m_appletInterface(nullptr) { connect(m_systemAppsModel, &FavoritesModel::favoritesChanged, this, &ComputerModel::systemApplicationsChanged); m_concatProxy->addSourceModel(m_runCommandModel); m_concatProxy->addSourceModel(m_systemAppsModel); m_concatProxy->addSourceModel(m_filteredPlacesModel); setSourceModel(m_concatProxy); } ComputerModel::~ComputerModel() { } QString ComputerModel::description() const { return i18n("Computer"); } int ComputerModel::appNameFormat() const { return m_appNameFormat; } void ComputerModel::setAppNameFormat(int format) { if (m_appNameFormat != (AppEntry::NameFormat)format) { m_appNameFormat = (AppEntry::NameFormat)format; m_systemAppsModel->refresh(); emit appNameFormatChanged(); } } QObject *ComputerModel::appletInterface() const { return m_appletInterface; } void ComputerModel::setAppletInterface(QObject *appletInterface) { if (m_appletInterface != appletInterface) { m_appletInterface = appletInterface; emit appletInterfaceChanged(); } } QStringList ComputerModel::systemApplications() const { return m_systemAppsModel->favorites(); } void ComputerModel::setSystemApplications(const QStringList &apps) { m_systemAppsModel->setFavorites(apps); } QVariant ComputerModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } const QModelIndex sourceIndex = m_concatProxy->mapToSource(m_concatProxy->index(index.row(), index.column())); bool isPlace = (sourceIndex.model() == m_filteredPlacesModel); if (isPlace) { if (role == Kicker::DescriptionRole) { if (m_filteredPlacesModel->isDevice(sourceIndex)) { Solid::Device device = m_filteredPlacesModel->deviceForIndex(sourceIndex); Solid::StorageAccess *access = device.as(); if (access) { return access->filePath(); + } else { + return QString(); } } else { const QUrl &url = m_filteredPlacesModel->url(sourceIndex); return url.toString(QUrl::PreferLocalFile); } } else if (role == Kicker::FavoriteIdRole) { if (!m_filteredPlacesModel->isDevice(sourceIndex)) { return m_filteredPlacesModel->url(sourceIndex); } } else if (role == Kicker::UrlRole) { return m_filteredPlacesModel->url(sourceIndex); } else if (role == Kicker::GroupRole) { if (m_filteredPlacesModel->isDevice(sourceIndex)) { return i18n("Removable Storage"); } else { return i18n("Places"); } } else if (role == Qt::DisplayRole || role == Qt::DecorationRole) { return sourceIndex.data(role); } } else if (role == Kicker::GroupRole) { return i18n("Applications"); } else { return sourceIndex.data(role); } return QVariant(); } bool ComputerModel::trigger(int row, const QString &actionId, const QVariant &argument) { const QModelIndex sourceIndex = m_concatProxy->mapToSource(m_concatProxy->index(row, 0)); if (sourceIndex.model() == m_filteredPlacesModel) { const QUrl &url = m_filteredPlacesModel->url(sourceIndex); if (url.isValid()) { new KRun(url, 0); return true; } Solid::Device device = m_filteredPlacesModel->deviceForIndex(sourceIndex); Solid::StorageAccess *access = device.as(); if (access && !access->isAccessible()) { connect(access, &Solid::StorageAccess::setupDone, this, &ComputerModel::onSetupDone); access->setup(); return true; } } else { AbstractModel *model = nullptr; if (sourceIndex.model() == m_systemAppsModel) { model = m_systemAppsModel; } else { model = m_runCommandModel; } return model->trigger(sourceIndex.row(), actionId, argument); } return false; } void ComputerModel::onSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi) { Q_UNUSED(errorData); if (error != Solid::NoError) { return; } Solid::Device device(udi); Solid::StorageAccess *access = device.as(); Q_ASSERT(access); new KRun(QUrl::fromLocalFile(access->filePath()), 0); } diff --git a/applets/kicker/plugin/recentcontactsmodel.cpp b/applets/kicker/plugin/recentcontactsmodel.cpp index 1d2c9f54e..9d5a48618 100644 --- a/applets/kicker/plugin/recentcontactsmodel.cpp +++ b/applets/kicker/plugin/recentcontactsmodel.cpp @@ -1,244 +1,246 @@ /*************************************************************************** * Copyright (C) 2012 by Aurélien Gâteau * * Copyright (C) 2014-2015 by Eike Hein * * * * 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 "recentcontactsmodel.h" #include "actionlist.h" #include "contactentry.h" #include #include #include #include #include //FIXME TODO: Pretty include in KPeople broken. #include #include namespace KAStats = KActivities::Stats; using namespace KAStats; using namespace KAStats::Terms; RecentContactsModel::RecentContactsModel(QObject *parent) : ForwardingModel(parent) { refresh(); } RecentContactsModel::~RecentContactsModel() { } QString RecentContactsModel::description() const { return i18n("Contacts"); } QVariant RecentContactsModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } QString id = sourceModel()->data(index, ResultModel::ResourceRole).toString(); KPeople::PersonData *data = 0; if (m_idToData.contains(id)) { data = m_idToData[id]; } if (!data) { const_cast(this)->insertPersonData(id, index.row()); return QVariant(); } if (role == Qt::DisplayRole) { return data->name(); } else if (role == Qt::DecorationRole) { return data->presenceIconName(); } else if (role == Kicker::FavoriteIdRole) { return id; } else if (role == Kicker::HasActionListRole) { return true; } else if (role == Kicker::ActionListRole) { QVariantList actionList ; const QVariantMap &forgetAction = Kicker::createActionItem(i18n("Forget Contact"), "forget"); actionList << forgetAction; const QVariantMap &forgetAllAction = Kicker::createActionItem(i18n("Forget All Contacts"), "forgetAll"); actionList << forgetAllAction; actionList << Kicker::createSeparatorActionItem(); actionList << Kicker::createActionItem(i18n("Show Contact Information..."), "showContactInfo"); return actionList; + } else if (role == Kicker::DescriptionRole) { + return QString(); } return QVariant(); } bool RecentContactsModel::trigger(int row, const QString &actionId, const QVariant &argument) { Q_UNUSED(argument) bool withinBounds = row >= 0 && row < rowCount(); if (actionId.isEmpty() && withinBounds) { QString id = sourceModel()->data(sourceModel()->index(row, 0), ResultModel::ResourceRole).toString(); const QList actionList = KPeople::actionsForPerson(id, this); if (!actionList.isEmpty()) { QAction *chat = 0; foreach (QAction *action, actionList) { const QVariant &actionType = action->property("actionType"); if (!actionType.isNull() && actionType.toInt() == KPeople::ActionType::TextChatAction) { chat = action; } } if (chat) { chat->trigger(); return true; } } return false; } else if (actionId == "showContactInfo" && withinBounds) { ContactEntry::showPersonDetailsDialog(sourceModel()->data(sourceModel()->index(row, 0), ResultModel::ResourceRole).toString()); } else if (actionId == "forget" && withinBounds) { if (sourceModel()) { ResultModel *resultModel = static_cast(sourceModel()); resultModel->forgetResource(row); } return false; } else if (actionId == "forgetAll") { if (sourceModel()) { ResultModel *resultModel = static_cast(sourceModel()); resultModel->forgetAllResources(); } return false; } return false; } bool RecentContactsModel::hasActions() const { return rowCount(); } QVariantList RecentContactsModel::actions() const { QVariantList actionList; if (rowCount()) { actionList << Kicker::createActionItem(i18n("Forget All Contacts"), "forgetAll"); } return actionList; } void RecentContactsModel::refresh() { QObject *oldModel = sourceModel(); auto query = UsedResources | RecentlyUsedFirst | Agent("KTp") | Type::any() | Activity::current() | Url::startsWith("ktp") | Limit(15); ResultModel *model = new ResultModel(query); QModelIndex index; if (model->canFetchMore(index)) { model->fetchMore(index); } // FIXME TODO: Don't wipe entire cache on transactions. connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(buildCache()), Qt::UniqueConnection); connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(buildCache()), Qt::UniqueConnection); connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(buildCache()), Qt::UniqueConnection); connect(model, SIGNAL(modelReset()), this, SLOT(buildCache()), Qt::UniqueConnection); setSourceModel(model); buildCache(); delete oldModel; } void RecentContactsModel::buildCache() { qDeleteAll(m_idToData.values()); m_idToData.clear(); m_dataToRow.clear(); QString id; for(int i = 0; i < sourceModel()->rowCount(); ++i) { id = sourceModel()->data(sourceModel()->index(i, 0), ResultModel::ResourceRole).toString(); if (!m_idToData.contains(id)) { insertPersonData(id, i); } } } void RecentContactsModel::insertPersonData(const QString& id, int row) { KPeople::PersonData *data = new KPeople::PersonData(id); m_idToData[id] = data; m_dataToRow[data] = row; connect(data, SIGNAL(dataChanged()), this, SLOT(personDataChanged())); } void RecentContactsModel::personDataChanged() { KPeople::PersonData *data = static_cast(sender()); if (m_dataToRow.contains(data)) { int row = m_dataToRow[data]; QModelIndex idx = sourceModel()->index(row, 0); emit dataChanged(idx, idx); } }