Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 1018b86e authored by Marco Martin's avatar Marco Martin

prototype of kactivity-based most used modules entries

Summary:
use kactivities to track the most used modules (kcmshell will need to as well)
and present them in the start page as 5 big icons

Test Plan:
empty kactivities db, show default set, after some usage, the most used modules come
on top

Reviewers: #plasma, #vdg

Subscribers: davidedmundson, abetts, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D6061
parent 04b7489c
......@@ -35,6 +35,8 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
DocTools
Package
Declarative
Activities
ActivitiesStats
OPTIONAL_COMPONENTS
KHtml
QUIET
......
......@@ -30,6 +30,7 @@ target_link_libraries( systemsettingsview
KF5::KIOWidgets
KF5::Service
KF5::IconThemes
KF5::Activities
)
set_target_properties( systemsettingsview PROPERTIES SOVERSION 3 )
......
......@@ -43,6 +43,8 @@
#include <kauthobjectdecorator.h>
#include <KIconLoader>
#include <KActivities/ResourceInstance>
#include "MenuItem.h"
class ModuleView::Private {
......@@ -341,6 +343,13 @@ void ModuleView::activeModuleChanged(KPageWidgetItem * current, KPageWidgetItem
}
// We need to get the state of the now active module
stateChanged();
KCModuleProxy * activeModule = d->mPages.value( d->mPageWidget->currentPage() );
if (activeModule) {
KActivities::ResourceInstance::notifyAccessed(QUrl("kcm:" + activeModule->moduleInfo().service()->storageId()),
"org.kde.systemsettings");
qWarning()<<QUrl("kcm:" + activeModule->moduleInfo().service()->storageId());
}
}
void ModuleView::stateChanged()
......
......@@ -17,6 +17,7 @@ target_link_libraries(systemsettings_sidebar_mode systemsettingsview
KF5::XmlGui
KF5::Package
KF5::Declarative
KF5::ActivitiesStats
Qt5::Qml
Qt5::Quick
Qt5::QuickWidgets
......
......@@ -33,6 +33,7 @@
#include <QAction>
#include <KAboutData>
#include <KCModuleInfo>
#include <KStandardAction>
#include <KLocalizedString>
#include <KIconLoader>
......@@ -51,6 +52,15 @@
#include <QLabel>
#include <QDebug>
#include <KActivities/Stats/ResultModel>
#include <KActivities/Stats/ResultSet>
#include <KActivities/Stats/Terms>
namespace KAStats = KActivities::Stats;
using namespace KAStats;
using namespace KAStats::Terms;
K_PLUGIN_FACTORY( SidebarModeFactory, registerPlugin<SidebarMode>(); )
class SubcategoryModel : public QStandardItemModel
......@@ -86,6 +96,105 @@ private:
QAbstractItemModel *m_parentModel;
};
class MostUsedModel : public QSortFilterProxyModel
{
public:
MostUsedModel(QObject *parent = 0)
: QSortFilterProxyModel (parent)
{
sort(0, Qt::DescendingOrder);
setSortRole(ResultModel::ScoreRole);
setDynamicSortFilter(true);
//prepare default items
m_defaultModel = new QStandardItemModel(this);
QStandardItem *item = new QStandardItem();
item->setData(QUrl(QStringLiteral("kcm:kcm_lookandfeel.desktop")), ResultModel::ResourceRole);
m_defaultModel->appendRow(item);
item = new QStandardItem();
item->setData(QUrl(QStringLiteral("kcm:user_manager.desktop")), ResultModel::ResourceRole);
m_defaultModel->appendRow(item);
item = new QStandardItem();
item->setData(QUrl(QStringLiteral("kcm:screenlocker.desktop")), ResultModel::ResourceRole);
m_defaultModel->appendRow(item);
item = new QStandardItem();
item->setData(QUrl(QStringLiteral("kcm:powerdevilprofilesconfig.desktop")), ResultModel::ResourceRole);
m_defaultModel->appendRow(item);
item = new QStandardItem();
item->setData(QUrl(QStringLiteral("kcm:kcm_kscreen.desktop")), ResultModel::ResourceRole);
m_defaultModel->appendRow(item);
}
void setResultModel(ResultModel *model)
{
if (m_resultModel == model) {
return;
}
auto updateModel = [this]() {
if (m_resultModel->rowCount() >= 5) {
setSourceModel(m_resultModel);
} else {
setSourceModel(m_defaultModel);
}
};
m_resultModel = model;
connect(m_resultModel, &QAbstractItemModel::rowsInserted, this, updateModel);
connect(m_resultModel, &QAbstractItemModel::rowsRemoved, this, updateModel);
updateModel();
}
QHash<int, QByteArray> roleNames() const
{
QHash<int, QByteArray> roleNames;
roleNames.insert(Qt::DisplayRole, "display");
roleNames.insert(Qt::DecorationRole, "decoration");
roleNames.insert(ResultModel::ScoreRole, "score");
return roleNames;
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
{
MenuItem *mi;
const QModelIndex &mappedIndex = mapToSource(index);
const QString desktopName = sourceModel()->data(mappedIndex, ResultModel::ResourceRole).toUrl().path();
if (m_menuItems.contains(desktopName)) {
mi = m_menuItems.value(desktopName);
} else {
mi = new MenuItem(false, nullptr);
const_cast<MostUsedModel *>(this)->m_menuItems.insert(desktopName, mi);
KService::Ptr service = KService::serviceByStorageId(desktopName);
if (!service || !service->isValid()) {
return QVariant();
}
mi->setService(service);
}
switch (role) {
case Qt::UserRole:
return QVariant::fromValue(mi);
case Qt::DisplayRole:
return mi->service()->name();
case Qt::DecorationRole:
return mi->service()->icon();
case ResultModel::ScoreRole:
return sourceModel()->data(mappedIndex, ResultModel::ScoreRole).toInt();
default:
return QVariant();
}
}
private:
QHash<QString, MenuItem *> m_menuItems;
QStandardItemModel *m_defaultModel;
ResultModel *m_resultModel;
};
class SidebarMode::Private {
public:
Private()
......@@ -104,6 +213,7 @@ public:
QQuickWidget * quickWidget;
KPackage::Package package;
SubcategoryModel * subCategoryModel;
MostUsedModel * mostUsedModel;
QWidget * mainWidget;
QQuickWidget * placeHolderWidget;
QHBoxLayout * mainLayout;
......@@ -163,6 +273,11 @@ QAbstractItemModel * SidebarMode::subCategoryModel() const
return d->subCategoryModel;
}
QAbstractItemModel * SidebarMode::mostUsedModel() const
{
return d->mostUsedModel;
}
QList<QAbstractItemView*> SidebarMode::views() const
{
QList<QAbstractItemView*> list;
......@@ -183,6 +298,8 @@ void SidebarMode::initEvent()
d->proxyModel->setFilterHighlightsEntries( false );
connect( d->proxyModel, &MenuProxyModel::filterRegExpChanged, this, &SidebarMode::activeCategoryChanged );
d->mostUsedModel = new MostUsedModel( this );
d->subCategoryModel = new SubcategoryModel( d->proxyModel, this );
d->mainWidget = new QWidget();
d->mainWidget->installEventFilter(this);
......@@ -219,6 +336,13 @@ void SidebarMode::hideToolTip()
d->toolTipManager->hideToolTip();
}
Q_INVOKABLE void SidebarMode::loadMostUsed(int index)
{
const QModelIndex idx = d->mostUsedModel->index(index, 0);
d->moduleView->closeModules();
d->moduleView->loadModule( idx );
}
void SidebarMode::changeModule( const QModelIndex& activeModule )
{
d->moduleView->closeModules();
......@@ -334,6 +458,8 @@ void SidebarMode::initWidget()
d->mainLayout->addWidget( d->moduleView );
d->mainLayout->addWidget( d->placeHolderWidget );
emit changeToolBarItems(BaseMode::NoItems);
d->mostUsedModel->setResultModel(new ResultModel( AllResources | Agent("org.kde.systemsettings") | HighScoredFirst | Limit(5), this));
}
bool SidebarMode::eventFilter(QObject* watched, QEvent* event)
......
......@@ -34,6 +34,7 @@ class SidebarMode : public BaseMode
Q_PROPERTY(QAbstractItemModel *categoryModel READ categoryModel CONSTANT)
Q_PROPERTY(QAbstractItemModel *subCategoryModel READ subCategoryModel CONSTANT)
Q_PROPERTY(QAbstractItemModel *mostUsedModel READ mostUsedModel CONSTANT)
Q_PROPERTY(int activeCategory READ activeCategory WRITE setActiveCategory NOTIFY activeCategoryChanged)
Q_PROPERTY(int activeSubCategory READ activeSubCategory WRITE setActiveSubCategory NOTIFY activeSubCategoryChanged)
Q_PROPERTY(int width READ width NOTIFY widthChanged)
......@@ -49,6 +50,7 @@ public:
ModuleView * moduleView() const Q_DECL_OVERRIDE;
QAbstractItemModel *categoryModel() const;
QAbstractItemModel *subCategoryModel() const;
QAbstractItemModel *mostUsedModel() const;
int activeCategory() const;
void setActiveCategory(int cat);
......@@ -61,6 +63,7 @@ public:
Q_INVOKABLE void triggerGlobalAction(const QString &name);
Q_INVOKABLE void requestToolTip(int index, const QRectF &rect);
Q_INVOKABLE void hideToolTip();
Q_INVOKABLE void loadMostUsed(int index);
protected:
QList<QAbstractItemView*> views() const Q_DECL_OVERRIDE;
......
/*
Copyright (c) 2017 Marco Martin <mart@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library 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 library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import org.kde.kirigami 2.1 as Kirigami
MouseArea {
property alias icon: iconItem.source
property alias text: label.text
property string module
implicitWidth: column.implicitWidth
implicitHeight: column.implicitHeight
cursorShape: Qt.PointingHandCursor
Layout.fillWidth: true
onClicked: systemsettings.loadMostUsed(index);
ColumnLayout {
id: column
anchors.centerIn: parent
Kirigami.Icon {
id: iconItem
Layout.alignment: Qt.AlignHCenter
width: Kirigami.Units.iconSizes.huge
height: width
}
Kirigami.Label {
Layout.alignment: Qt.AlignHCenter
id: label
}
}
}
......@@ -21,16 +21,14 @@ import QtQuick.Layouts 1.1
import org.kde.kirigami 2.1 as Kirigami
Rectangle {
id: root
color: Kirigami.Theme.backgroundColor
ColumnLayout {
anchors {
top: parent.top
bottom: parent.bottom
bottom: separator.top
bottomMargin: Kirigami.Units.largeSpacing
horizontalCenter: parent.horizontalCenter
}
Item {
Layout.fillHeight: true
}
Kirigami.Icon {
Layout.alignment: Qt.AlignHCenter
source: "systemsettings"
......@@ -40,10 +38,38 @@ Rectangle {
}
Kirigami.Label {
Layout.alignment: Qt.AlignHCenter
text: i18n("Select an item from the list to see the available options")
text: i18n("System settings")
}
Item {
Layout.fillHeight: true
}
Kirigami.Separator {
id: separator
anchors.centerIn: parent
width: parent.width * 0.8
}
ColumnLayout {
anchors {
top: separator.bottom
topMargin: Kirigami.Units.largeSpacing
horizontalCenter: parent.horizontalCenter
}
width: parent.width * 0.8
Kirigami.Heading {
Layout.alignment: Qt.AlignHCenter
level: 3
text: i18n("Frequently used:")
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
spacing: Kirigami.Units.largeSpacing
Repeater {
model: systemsettings.mostUsedModel
delegate: IntroIcon {
icon: model.decoration
text: model.display
}
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment