~ubuntu-branches/ubuntu/raring/plasma-mobile/raring-proposed

« back to all changes in this revision

Viewing changes to components/metadatamodel/metadatatimelinemodel.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2012-07-17 12:04:43 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120717120443-q3ig9u2fnltx67yg
Tags: 2.0+git2012071701-0ubuntu1
* New upstream snapshot
* Remove build-dep on kde-runtime-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright 2011 Marco Martin <notmart@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
#include "metadatatimelinemodel.h"
 
21
 
 
22
 
 
23
#include <KDebug>
 
24
#include <KMimeType>
 
25
#include <KCalendarSystem>
 
26
 
 
27
#include <soprano/vocabulary.h>
 
28
 
 
29
#include <Nepomuk/File>
 
30
#include <Nepomuk/Query/AndTerm>
 
31
#include <Nepomuk/Query/ResourceTerm>
 
32
#include <Nepomuk/Tag>
 
33
#include <Nepomuk/Variant>
 
34
#include <nepomuk/comparisonterm.h>
 
35
#include <nepomuk/literalterm.h>
 
36
#include <nepomuk/queryparser.h>
 
37
#include <nepomuk/resourcetypeterm.h>
 
38
#include <nepomuk/standardqueries.h>
 
39
 
 
40
#include <nepomuk/nfo.h>
 
41
#include <nepomuk/nie.h>
 
42
 
 
43
#include "kao.h"
 
44
 
 
45
 
 
46
MetadataTimelineModel::MetadataTimelineModel(QObject *parent)
 
47
    : AbstractMetadataModel(parent),
 
48
      m_queryClient(0),
 
49
      m_totalCount(0)
 
50
{
 
51
    QHash<int, QByteArray> roleNames;
 
52
    roleNames[LabelRole] = "label";
 
53
    roleNames[YearRole] = "year";
 
54
    roleNames[MonthRole] = "month";
 
55
    roleNames[DayRole] = "day";
 
56
    roleNames[CountRole] = "count";
 
57
    setRoleNames(roleNames);
 
58
    askRefresh();
 
59
}
 
60
 
 
61
MetadataTimelineModel::~MetadataTimelineModel()
 
62
{
 
63
}
 
64
 
 
65
 
 
66
void MetadataTimelineModel::setLevel(MetadataTimelineModel::Level level)
 
67
{
 
68
    if (m_level == level) {
 
69
        return;
 
70
    }
 
71
 
 
72
    m_level = level;
 
73
    askRefresh();
 
74
    emit levelChanged();
 
75
}
 
76
 
 
77
MetadataTimelineModel::Level MetadataTimelineModel::level() const
 
78
{
 
79
    return m_level;
 
80
}
 
81
 
 
82
 
 
83
QString MetadataTimelineModel::description() const
 
84
{
 
85
    if (m_results.isEmpty()) {
 
86
        return QString();
 
87
    }
 
88
 
 
89
    //TODO: manage cases where start and enddate cover more than one year/month
 
90
    switch (m_level) {
 
91
    case Year:
 
92
        return i18n("All years");
 
93
    case Month:
 
94
        return KGlobal::locale()->calendar()->yearString(startDate(), KCalendarSystem::LongFormat);
 
95
    case Day:
 
96
    default:
 
97
        return i18nc("Month and year, such as March 2007", "%1 %2", KGlobal::locale()->calendar()->monthName(startDate(), KCalendarSystem::LongName), KGlobal::locale()->calendar()->yearString(startDate(), KCalendarSystem::LongFormat));
 
98
    }
 
99
}
 
100
 
 
101
 
 
102
void MetadataTimelineModel::doQuery()
 
103
{
 
104
    QDeclarativePropertyMap *parameters = qobject_cast<QDeclarativePropertyMap *>(extraParameters());
 
105
 
 
106
    m_totalCount = 0;
 
107
 
 
108
    setRunning(true);
 
109
    QString monthQuery;
 
110
    QString dayQuery;
 
111
 
 
112
    if (m_level >= Month) {
 
113
        monthQuery = "bif:month(?label)";
 
114
    } else {
 
115
        monthQuery = '0';
 
116
    }
 
117
    if (m_level >= Day) {
 
118
        dayQuery = "bif:dayofmonth(?label)";
 
119
    } else {
 
120
        dayQuery = '0';
 
121
    }
 
122
 
 
123
    QString query = QString("select distinct bif:year(?label) as ?year %1 as ?month %2 as ?day count(*) as ?count where { ?r nie:lastModified ?label  ").arg(monthQuery).arg(dayQuery);
 
124
 
 
125
 
 
126
    if (!resourceType().isEmpty()) {
 
127
        QString type = resourceType();
 
128
        bool negation = false;
 
129
        if (type.startsWith('!')) {
 
130
            type = type.remove(0, 1);
 
131
            negation = true;
 
132
        }
 
133
        if (negation) {
 
134
            query += " . FILTER(!bif:exists((select (1) where { ?r rdf:type " + type + " . }))) ";
 
135
        } else {
 
136
            query += " . ?r rdf:type " + type;
 
137
        }
 
138
 
 
139
        if (type != "nfo:Bookmark") {
 
140
            //FIXME: remove bookmarks if not explicitly asked for
 
141
            query += " . FILTER(!bif:exists((select (1) where { ?r a <http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Bookmark> . }))) ";
 
142
        }
 
143
    }
 
144
 
 
145
    if (!mimeTypeStrings().isEmpty()) {
 
146
        query += " { ";
 
147
        bool first = true;
 
148
        foreach (QString type, mimeTypeStrings()) {
 
149
            bool negation = false;
 
150
            if (!first) {
 
151
                query += " UNION ";
 
152
            }
 
153
            first = false;
 
154
            if (type.startsWith('!')) {
 
155
                type = type.remove(0, 1);
 
156
                negation = true;
 
157
            }
 
158
            if (negation) {
 
159
                query += " { . FILTER(!bif:exists((select (1) where { ?r nie:mimeType \"" + type + "\"^^<http://www.w3.org/2001/XMLSchema#string> . }))) } ";
 
160
            } else {
 
161
                query += " { ?r nie:mimeType \"" + type + "\"^^<http://www.w3.org/2001/XMLSchema#string> . } ";
 
162
            }
 
163
        }
 
164
        query += " } ";
 
165
    }
 
166
 
 
167
    if (parameters && parameters->size() > 0) {
 
168
        foreach (const QString &key, parameters->keys()) {
 
169
            QString parameter = parameters->value(key).toString();
 
170
            bool negation = false;
 
171
            if (parameter.startsWith('!')) {
 
172
                parameter = parameter.remove(0, 1);
 
173
                negation = true;
 
174
            }
 
175
 
 
176
            if (negation) {
 
177
                query += " . FILTER(!bif:exists((select (1) where { ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) . }))) ";
 
178
            } else {
 
179
                query += " . ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) ";
 
180
            }
 
181
        }
 
182
    }
 
183
 
 
184
    if (!activityId().isEmpty()) {
 
185
        QString activity = activityId();
 
186
        bool negation = false;
 
187
        if (activity.startsWith('!')) {
 
188
            activity = activity.remove(0, 1);
 
189
            negation = true;
 
190
        }
 
191
        Nepomuk::Resource acRes(activity, Nepomuk::Vocabulary::KAO::Activity());
 
192
 
 
193
        if (negation) {
 
194
            query +=  ". FILTER(!bif:exists((select (1) where { <" + acRes.resourceUri().toString() + "> <http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isRelated> ?r . }))) ";
 
195
        } else {
 
196
            query +=  " . <" + acRes.resourceUri().toString() + "> nao:isRelated ?r ";
 
197
        }
 
198
    }
 
199
 
 
200
    //this is an AND set of tags.. should be allowed OR as well?
 
201
    foreach (const QString &tag, tagStrings()) {
 
202
        QString individualTag = tag;
 
203
        bool negation = false;
 
204
 
 
205
        if (individualTag.startsWith('!')) {
 
206
            individualTag = individualTag.remove(0, 1);
 
207
            negation = true;
 
208
        }
 
209
 
 
210
        if (negation) {
 
211
            query += ". FILTER(!bif:exists((select (1) where { ?r nao:hasTag ?tagSet \
 
212
                    . ?tagSet ?tagLabel ?tag \
 
213
                    . ?tagLabel <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#label> \
 
214
                    . FILTER(bif:contains(?tag, \"'"+individualTag+"'\"))}))) ";
 
215
        } else {
 
216
            query += ". ?r nao:hasTag ?tagSet \
 
217
                    . ?tagSet ?tagLabel ?tag \
 
218
                    . ?tagLabel <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#label> \
 
219
                    . FILTER(bif:contains(?tag, \"'"+individualTag+"'\")) ";
 
220
        }
 
221
    }
 
222
 
 
223
    if (startDate().isValid() || endDate().isValid()) {
 
224
        if (startDate().isValid()) {
 
225
            query += ". ?r <http://www.semanticdesktop.org/ontologies/2007/01/19/nie#lastModified> ?v2 . FILTER(?v2>\"" + startDate().toString(Qt::ISODate) + "\"^^<http://www.w3.org/2001/XMLSchema#dateTime>) ";
 
226
        }
 
227
        if (endDate().isValid()) {
 
228
            query += ". ?r <http://www.semanticdesktop.org/ontologies/2007/01/19/nie#lastModified> ?v2 . FILTER(?v2<\"" + endDate().toString(Qt::ISODate) + "\"^^<http://www.w3.org/2001/XMLSchema#dateTime>) ";
 
229
        }
 
230
    }
 
231
 
 
232
    if (minimumRating() > 0) {
 
233
        query += " . ?r nao:numericRating ?rating filter (?rating >=" + QString::number(minimumRating()) + ") ";
 
234
    }
 
235
 
 
236
    if (maximumRating() > 0) {
 
237
        query += " . ?r nao:numericRating ?rating filter (?rating <=" + QString::number(maximumRating()) + ") ";
 
238
    }
 
239
 
 
240
    //user visibility is too slow
 
241
    //query +=  " . FILTER(bif:exists((select (1) where { ?r a [ <http://www.semanticdesktop.org/ontologies/2007/08/15/nao#userVisible> \"true\"^^<http://www.w3.org/2001/XMLSchema#boolean> ] . }))) }";
 
242
    query += "}";
 
243
 
 
244
    //Group by construction
 
245
    query += " group by bif:year(?label) ";
 
246
    if (m_level >= Month) {
 
247
        query += " bif:month(?label) ";
 
248
    }
 
249
    if (m_level >= Day) {
 
250
        query += " bif:dayofmonth(?label) ";
 
251
    }
 
252
    query += " order by ?year ?month ?day ";
 
253
 
 
254
    kDebug() << "Performing the Sparql query" << query;
 
255
 
 
256
    beginResetModel();
 
257
    m_results.clear();
 
258
    endResetModel();
 
259
    emit countChanged();
 
260
    emit totalCountChanged();
 
261
    emit descriptionChanged();
 
262
 
 
263
    if (m_queryClient) {
 
264
        m_queryClient->close();
 
265
    }
 
266
    delete m_queryClient;
 
267
    m_queryClient = new Nepomuk::Query::QueryServiceClient(this);
 
268
 
 
269
    connect(m_queryClient, SIGNAL(newEntries(QList<Nepomuk::Query::Result>)),
 
270
            this, SLOT(newEntries(QList<Nepomuk::Query::Result>)));
 
271
    connect(m_queryClient, SIGNAL(entriesRemoved(QList<QUrl>)),
 
272
            this, SLOT(entriesRemoved(QList<QUrl>)));
 
273
    connect(m_queryClient, SIGNAL(finishedListing()), this, SLOT(finishedListing()));
 
274
 
 
275
    m_queryClient->sparqlQuery(query);
 
276
}
 
277
 
 
278
void MetadataTimelineModel::newEntries(const QList< Nepomuk::Query::Result > &entries)
 
279
{
 
280
    QVector<QHash<Roles, int> > results;
 
281
    QVariantList categories;
 
282
    foreach (const Nepomuk::Query::Result &res, entries) {
 
283
        QString label;
 
284
        int count = res.additionalBinding(QLatin1String("count")).variant().toInt();
 
285
        int year = res.additionalBinding(QLatin1String("year")).variant().toInt();
 
286
        int month = res.additionalBinding(QLatin1String("month")).variant().toInt();
 
287
        int day = res.additionalBinding(QLatin1String("day")).variant().toInt();
 
288
 
 
289
        QHash<Roles, int> resHash;
 
290
        resHash[YearRole] = year;
 
291
        resHash[MonthRole] = month;
 
292
        resHash[DayRole] = day;
 
293
        resHash[CountRole] = count;
 
294
 
 
295
        m_totalCount += count;
 
296
        results << resHash;
 
297
    }
 
298
 
 
299
    if (results.count() > 0) {
 
300
        beginInsertRows(QModelIndex(), m_results.count(), m_results.count()+results.count());
 
301
        m_results << results;
 
302
        m_categories << categories;
 
303
        endInsertRows();
 
304
        emit countChanged();
 
305
        emit totalCountChanged();
 
306
        emit descriptionChanged();
 
307
    }
 
308
}
 
309
 
 
310
void MetadataTimelineModel::entriesRemoved(const QList<QUrl> &urls)
 
311
{
 
312
    //FIXME: we don't have urls here
 
313
    return;
 
314
 
 
315
    emit countChanged();
 
316
    emit totalCountChanged();
 
317
}
 
318
 
 
319
void MetadataTimelineModel::finishedListing()
 
320
{
 
321
    setRunning(false);
 
322
}
 
323
 
 
324
 
 
325
 
 
326
QVariant MetadataTimelineModel::data(const QModelIndex &index, int role) const
 
327
{
 
328
    if (!index.isValid() || index.column() != 0 ||
 
329
        index.row() < 0 || index.row() >= m_results.count()){
 
330
        return QVariant();
 
331
    }
 
332
 
 
333
    const QHash<Roles, int> row = m_results[index.row()];
 
334
 
 
335
    if (role == LabelRole) {
 
336
        switch(m_level) {
 
337
        case Year:
 
338
            return row.value(YearRole);
 
339
        case Month:
 
340
            return KGlobal::locale()->calendar()->monthName(row.value(MonthRole),  row.value(YearRole), KCalendarSystem::LongName);
 
341
        case Day:
 
342
        default:
 
343
            return row.value(DayRole);
 
344
        }
 
345
    }
 
346
    return row.value((Roles)role);
 
347
}
 
348
 
 
349
#include "metadatatimelinemodel.moc"