2
Copyright 2007 Robert Knight <robertknight@gmail.com>
4
This library is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Library General Public
6
License as published by the Free Software Foundation; either
7
version 2 of the License, or (at your option) any later version.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public License
15
along with this library; see the file COPYING.LIB. If not, write to
16
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
Boston, MA 02110-1301, USA.
21
#include "core/recentlyusedmodel.h"
26
#include <KDesktopFile>
28
#include <KRecentDocument>
33
#include "core/recentapplications.h"
34
#include "recentadaptor.h"
36
using namespace Kickoff;
38
class RecentlyUsedModel::Private
41
Private(RecentlyUsedModel *parent, RecentType recenttype, int maxRecentApps)
43
recenttype(recenttype),
44
maxRecentApps(maxRecentApps >= 0 ? maxRecentApps : Kickoff::RecentApplications::self()->defaultMaximum()),
45
recentDocumentItem(0),
47
displayOrder(NameAfterDescription)
51
void removeExistingItem(const QString& path) {
52
if (!itemsByPath.contains(path)) {
56
QStandardItem *existingItem = itemsByPath[path];
57
kDebug() << "Removing existing item" << existingItem;
58
Q_ASSERT(existingItem->parent());
59
existingItem->parent()->removeRow(existingItem->row());
60
itemsByPath.remove(path);
63
void addRecentApplication(KService::Ptr service, bool append) {
64
// remove existing item if any
65
removeExistingItem(service->entryPath());
67
QStandardItem *appItem = StandardItemFactory::createItemForService(service, displayOrder);
68
itemsByPath.insert(service->entryPath(), appItem);
71
recentAppItem->appendRow(appItem);
73
recentAppItem->insertRow(0, appItem);
76
while (recentAppItem->rowCount() > maxRecentApps) {
77
QList<QStandardItem*> row = recentAppItem->takeRow(recentAppItem->rowCount() - 1);
79
//don't leave pending stuff in itemsByPath
81
itemsByPath.remove(row.first()->data(UrlRole).toString());
82
qDeleteAll(row.begin(), row.end());
87
void addRecentDocument(const QString& desktopPath, bool append) {
88
// remove existing item if any
89
KDesktopFile desktopFile(desktopPath);
90
KUrl documentUrl = desktopFile.readUrl();
92
removeExistingItem(documentUrl.url());
94
QStandardItem *documentItem = StandardItemFactory::createItemForUrl(desktopPath, displayOrder);
95
documentItem->setData(true, Kickoff::SubTitleMandatoryRole);
96
itemsByPath.insert(desktopPath, documentItem);
98
//kDebug() << "Document item" << documentItem << "text" << documentItem->text() << "url" << documentUrl.url();
100
recentDocumentItem->appendRow(documentItem);
102
recentDocumentItem->insertRow(0, documentItem);
106
void loadRecentDocuments()
108
// create branch for documents and add existing items
109
recentDocumentItem = new QStandardItem(i18n("Documents"));
110
const QStringList documents = KRecentDocument::recentDocuments();
111
foreach(const QString& document, documents) {
112
addRecentDocument(document, true);
115
q->appendRow(recentDocumentItem);
118
void loadRecentApplications()
120
recentAppItem = new QStandardItem(i18n("Applications"));
122
const QList<KService::Ptr> services = RecentApplications::self()->recentApplications();
123
for(int i = 0; i < maxRecentApps && i < services.count(); ++i) {
124
addRecentApplication(services[i], true);
127
q->appendRow(recentAppItem);
130
RecentlyUsedModel * const q;
131
RecentType recenttype;
134
QStandardItem *recentDocumentItem;
135
QStandardItem *recentAppItem;
136
QHash<QString, QStandardItem*> itemsByPath;
137
DisplayOrder displayOrder;
140
RecentlyUsedModel::RecentlyUsedModel(QObject *parent, RecentType recenttype, int maxRecentApps)
141
: KickoffModel(parent),
142
d(new Private(this, recenttype, maxRecentApps))
144
QDBusConnection dbus = QDBusConnection::sessionBus();
145
(void)new RecentAdaptor(this);
146
QDBusConnection::sessionBus().registerObject("/kickoff/RecentAppDoc", this);
147
dbus.connect(QString(), "/kickoff/RecentAppDoc", "org.kde.plasma", "clearRecentDocumentsAndApplications", this, SLOT(clearRecentDocumentsAndApplications()));
149
if (recenttype != DocumentsOnly) {
150
d->loadRecentApplications();
152
// listen for changes to the list of recent applications
153
connect(RecentApplications::self(), SIGNAL(applicationAdded(KService::Ptr, int)),
154
this, SLOT(recentApplicationAdded(KService::Ptr, int)));
155
connect(RecentApplications::self(), SIGNAL(applicationRemoved(KService::Ptr)),
156
this, SLOT(recentApplicationRemoved(KService::Ptr)));
157
connect(RecentApplications::self(), SIGNAL(cleared()),
158
this, SLOT(recentApplicationsCleared()));
161
if (recenttype != ApplicationsOnly) {
162
d->loadRecentDocuments();
164
// listen for changes to the list of recent documents
165
KDirWatch *recentDocWatch = new KDirWatch(this);
166
recentDocWatch->addDir(KRecentDocument::recentDocumentDirectory(), KDirWatch::WatchFiles);
167
connect(recentDocWatch, SIGNAL(created(QString)), this, SLOT(recentDocumentAdded(QString)));
168
connect(recentDocWatch, SIGNAL(deleted(QString)), this, SLOT(recentDocumentRemoved(QString)));
172
RecentlyUsedModel::~RecentlyUsedModel()
177
QVariant RecentlyUsedModel::headerData(int section, Qt::Orientation orientation, int role) const
179
if (orientation != Qt::Horizontal || section != 0) {
184
case Qt::DisplayRole:
185
if (d->recenttype == DocumentsAndApplications) {
186
return i18n("Recently Used");
187
} else if (d->recenttype == DocumentsOnly) {
188
return i18n("Recently Used Documents");
189
} else if (d->recenttype == ApplicationsOnly) {
190
return i18n("Recently Used Applications");
197
void RecentlyUsedModel::setNameDisplayOrder(DisplayOrder displayOrder)
199
if (d->displayOrder == displayOrder) {
203
d->displayOrder = displayOrder;
205
d->itemsByPath.clear();
208
if (d->recenttype != DocumentsOnly) {
209
d->loadRecentApplications();
212
if (d->recenttype != ApplicationsOnly) {
213
d->loadRecentDocuments();
217
DisplayOrder RecentlyUsedModel::nameDisplayOrder() const
219
return d->displayOrder;
222
void RecentlyUsedModel::recentDocumentAdded(const QString& path)
224
kDebug() << "Recent document added" << path;
225
d->addRecentDocument(path, false);
227
void RecentlyUsedModel::recentDocumentRemoved(const QString& path)
229
kDebug() << "Recent document removed" << path;
230
d->removeExistingItem(path);
233
void RecentlyUsedModel::recentApplicationAdded(KService::Ptr service, int)
236
d->addRecentApplication(service, false);
240
void RecentlyUsedModel::recentApplicationRemoved(KService::Ptr service)
243
d->removeExistingItem(service->entryPath());
247
void RecentlyUsedModel::recentApplicationsCleared()
249
QSet<QStandardItem*> appItems;
250
const int rows = d->recentAppItem->rowCount();
251
for (int i = 0;i < rows;i++) {
252
appItems << d->recentAppItem->child(i);
254
QMutableHashIterator<QString, QStandardItem*> iter(d->itemsByPath);
255
while (iter.hasNext()) {
257
if (appItems.contains(iter.value())) {
262
d->recentAppItem->removeRows(0, d->recentAppItem->rowCount());
265
void RecentlyUsedModel::clearRecentApplications()
267
RecentApplications::self()->clear();
269
void RecentlyUsedModel::clearRecentDocuments()
271
KRecentDocument::clear();
274
void RecentlyUsedModel::clearRecentDocumentsAndApplications()
276
clearRecentDocuments();
277
clearRecentApplications();
281
#include "recentlyusedmodel.moc"