~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to plasma/desktop/applets/kickoff/core/recentlyusedmodel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright 2007 Robert Knight <robertknight@gmail.com>
 
3
 
 
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.
 
8
 
 
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.
 
13
 
 
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.
 
18
*/
 
19
 
 
20
// Own
 
21
#include "core/recentlyusedmodel.h"
 
22
 
 
23
// Qt
 
24
 
 
25
// KDE
 
26
#include <KDesktopFile>
 
27
#include <KDirWatch>
 
28
#include <KRecentDocument>
 
29
#include <KUrl>
 
30
#include <KDebug>
 
31
 
 
32
// Local
 
33
#include "core/recentapplications.h"
 
34
#include "recentadaptor.h"
 
35
 
 
36
using namespace Kickoff;
 
37
 
 
38
class RecentlyUsedModel::Private
 
39
{
 
40
public:
 
41
    Private(RecentlyUsedModel *parent, RecentType recenttype, int maxRecentApps)
 
42
            : q(parent),
 
43
              recenttype(recenttype),
 
44
              maxRecentApps(maxRecentApps >= 0 ? maxRecentApps : Kickoff::RecentApplications::self()->defaultMaximum()),
 
45
              recentDocumentItem(0),
 
46
              recentAppItem(0),
 
47
              displayOrder(NameAfterDescription)
 
48
    {
 
49
    }
 
50
 
 
51
    void removeExistingItem(const QString& path) {
 
52
        if (!itemsByPath.contains(path)) {
 
53
            return;
 
54
        }
 
55
 
 
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);
 
61
    }
 
62
 
 
63
    void addRecentApplication(KService::Ptr service, bool append) {
 
64
        // remove existing item if any
 
65
        removeExistingItem(service->entryPath());
 
66
 
 
67
        QStandardItem *appItem = StandardItemFactory::createItemForService(service, displayOrder);
 
68
        itemsByPath.insert(service->entryPath(), appItem);
 
69
 
 
70
        if (append) {
 
71
            recentAppItem->appendRow(appItem);
 
72
        } else {
 
73
            recentAppItem->insertRow(0, appItem);
 
74
        }
 
75
 
 
76
        while (recentAppItem->rowCount() > maxRecentApps) {
 
77
            QList<QStandardItem*> row = recentAppItem->takeRow(recentAppItem->rowCount() - 1);
 
78
 
 
79
            //don't leave pending stuff in itemsByPath
 
80
            if (!row.isEmpty()) {
 
81
                itemsByPath.remove(row.first()->data(UrlRole).toString());
 
82
                qDeleteAll(row.begin(), row.end());
 
83
            }
 
84
        }
 
85
    }
 
86
 
 
87
    void addRecentDocument(const QString& desktopPath, bool append) {
 
88
        // remove existing item if any
 
89
        KDesktopFile desktopFile(desktopPath);
 
90
        KUrl documentUrl = desktopFile.readUrl();
 
91
 
 
92
        removeExistingItem(documentUrl.url());
 
93
 
 
94
        QStandardItem *documentItem = StandardItemFactory::createItemForUrl(desktopPath, displayOrder);
 
95
        documentItem->setData(true, Kickoff::SubTitleMandatoryRole);
 
96
        itemsByPath.insert(desktopPath, documentItem);
 
97
 
 
98
        //kDebug() << "Document item" << documentItem << "text" << documentItem->text() << "url" << documentUrl.url();
 
99
        if (append) {
 
100
            recentDocumentItem->appendRow(documentItem);
 
101
        } else {
 
102
            recentDocumentItem->insertRow(0, documentItem);
 
103
        }
 
104
    }
 
105
 
 
106
    void loadRecentDocuments()
 
107
    {
 
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);
 
113
        }
 
114
 
 
115
        q->appendRow(recentDocumentItem);
 
116
    }
 
117
 
 
118
    void loadRecentApplications()
 
119
    {
 
120
        recentAppItem = new QStandardItem(i18n("Applications"));
 
121
 
 
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);
 
125
        }
 
126
 
 
127
        q->appendRow(recentAppItem);
 
128
    }
 
129
 
 
130
    RecentlyUsedModel * const q;
 
131
    RecentType recenttype;
 
132
    int maxRecentApps;
 
133
 
 
134
    QStandardItem *recentDocumentItem;
 
135
    QStandardItem *recentAppItem;
 
136
    QHash<QString, QStandardItem*> itemsByPath;
 
137
    DisplayOrder displayOrder;
 
138
};
 
139
 
 
140
RecentlyUsedModel::RecentlyUsedModel(QObject *parent, RecentType recenttype, int maxRecentApps)
 
141
        : KickoffModel(parent),
 
142
          d(new Private(this, recenttype, maxRecentApps))
 
143
{
 
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()));
 
148
 
 
149
    if (recenttype != DocumentsOnly) {
 
150
        d->loadRecentApplications();
 
151
 
 
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()));
 
159
    }
 
160
 
 
161
    if (recenttype != ApplicationsOnly) {
 
162
        d->loadRecentDocuments();
 
163
 
 
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)));
 
169
    }
 
170
}
 
171
 
 
172
RecentlyUsedModel::~RecentlyUsedModel()
 
173
{
 
174
    delete d;
 
175
}
 
176
 
 
177
QVariant RecentlyUsedModel::headerData(int section, Qt::Orientation orientation, int role) const
 
178
{
 
179
    if (orientation != Qt::Horizontal || section != 0) {
 
180
        return QVariant();
 
181
    }
 
182
 
 
183
    switch (role) {
 
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");
 
191
        }
 
192
    default:
 
193
        return QVariant();
 
194
    }
 
195
}
 
196
 
 
197
void RecentlyUsedModel::setNameDisplayOrder(DisplayOrder displayOrder) 
 
198
{
 
199
    if (d->displayOrder == displayOrder) {
 
200
        return;
 
201
    }
 
202
 
 
203
    d->displayOrder = displayOrder;
 
204
 
 
205
    d->itemsByPath.clear();
 
206
    clear();
 
207
 
 
208
    if (d->recenttype != DocumentsOnly) {
 
209
        d->loadRecentApplications();
 
210
    }
 
211
 
 
212
    if (d->recenttype != ApplicationsOnly) {
 
213
        d->loadRecentDocuments();
 
214
    }
 
215
}
 
216
 
 
217
DisplayOrder RecentlyUsedModel::nameDisplayOrder() const
 
218
{
 
219
   return d->displayOrder;
 
220
}
 
221
 
 
222
void RecentlyUsedModel::recentDocumentAdded(const QString& path)
 
223
{
 
224
    kDebug() << "Recent document added" << path;
 
225
    d->addRecentDocument(path, false);
 
226
}
 
227
void RecentlyUsedModel::recentDocumentRemoved(const QString& path)
 
228
{
 
229
    kDebug() << "Recent document removed" << path;
 
230
    d->removeExistingItem(path);
 
231
}
 
232
 
 
233
void RecentlyUsedModel::recentApplicationAdded(KService::Ptr service, int)
 
234
{
 
235
    if (service) {
 
236
        d->addRecentApplication(service, false);
 
237
    }
 
238
}
 
239
 
 
240
void RecentlyUsedModel::recentApplicationRemoved(KService::Ptr service)
 
241
{
 
242
    if (service) {
 
243
        d->removeExistingItem(service->entryPath());
 
244
    }
 
245
}
 
246
 
 
247
void RecentlyUsedModel::recentApplicationsCleared()
 
248
{
 
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);
 
253
    }
 
254
    QMutableHashIterator<QString, QStandardItem*> iter(d->itemsByPath);
 
255
    while (iter.hasNext()) {
 
256
        iter.next();
 
257
        if (appItems.contains(iter.value())) {
 
258
            iter.remove();
 
259
        }
 
260
    }
 
261
 
 
262
    d->recentAppItem->removeRows(0, d->recentAppItem->rowCount());
 
263
}
 
264
 
 
265
void RecentlyUsedModel::clearRecentApplications()
 
266
{
 
267
    RecentApplications::self()->clear();
 
268
}
 
269
void RecentlyUsedModel::clearRecentDocuments()
 
270
{
 
271
    KRecentDocument::clear();
 
272
}
 
273
 
 
274
void RecentlyUsedModel::clearRecentDocumentsAndApplications()
 
275
{
 
276
    clearRecentDocuments();
 
277
    clearRecentApplications();
 
278
}
 
279
 
 
280
 
 
281
#include "recentlyusedmodel.moc"
 
282