diff --git a/applets/windowstrip/windowstrip.cpp b/applets/windowstrip/windowstrip.cpp index 41080fae..7290f8ab 100644 --- a/applets/windowstrip/windowstrip.cpp +++ b/applets/windowstrip/windowstrip.cpp @@ -1,173 +1,173 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * 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 "windowstrip.h" #include #include #include #include #include #include #include #include #include #include #include #include #include WindowStrip::WindowStrip(QGraphicsWidget *parent) : Plasma::DeclarativeWidget(parent) { // Run the frameupdater once every 20 msec, // so KWin gets in the ideal case updated // rects for every frame m_frameUpdater.setInterval(20); // The frameController is used to stop updating the // frame after a timeout after the animation has stopped m_updateController.setSingleShot(true); m_updateController.setInterval(200); connect(&m_frameUpdater, SIGNAL(timeout()), SLOT(updateFrame())); connect(&m_updateController, SIGNAL(timeout()), &m_frameUpdater, SLOT(stop())); // allow the QML to know the name of the shell to compare against the window. if (QDeclarativeContext *context = engine()->rootContext()) { context->setContextProperty("shellName", KGlobal::mainComponent().aboutData()->appName()); } //setThumbnailRects("Tokamak 5"); setQmlPath(KStandardDirs::locate("data", "plasma/plasmoids/org.kde.windowstrip/WindowStrip.qml")); m_windowFlicker = rootObject()->findChild("windowFlicker"); if (m_windowFlicker) { connect(m_windowFlicker, SIGNAL(childrenPositionsChanged()), this, SLOT(scrollChanged())); connect(m_windowFlicker, SIGNAL(contentXChanged()), this, SLOT(scrollChanged())); } scrollChanged(); } WindowStrip::~WindowStrip() { hideThumbnails(); } void WindowStrip::init() { QList< WId > windows = KWindowSystem::windows(); // use this once the kdelibs branch export-mru-window-list is merged to master //QList< WId > windows = KWindowSystem::mostRecentlyUsedOrder(); } void WindowStrip::showThumbnails() { QList translatedWindows; - foreach (QRect windowRect, m_windows.values()) { + foreach (const QRect &windowRect, m_windows) { translatedWindows << windowRect.translated(m_windowsOffset); } Plasma::WindowEffects::showWindowThumbnails(m_desktop, m_windows.keys(), translatedWindows); //kDebug() << "/// all shown" << m_windows.keys() << translatedWindows; } void WindowStrip::hideThumbnails() { Plasma::WindowEffects::showWindowThumbnails(m_desktop); kDebug() << "/// all hidden "; } void WindowStrip::scrollChanged() { //kDebug() << "elapsed: " << m_time.elapsed(); if (m_time.elapsed() < 50) { //kDebug() << "skipping"; //return; } // the view has changed, update the windows, // start the updating timer, and start the controller // to kill the updater after a while updateFrame(); updateWindows(); m_updateController.start(); m_frameUpdater.start(); } void WindowStrip::updateWindows() { if (!m_windowFlicker) { return; } QVariant dataX = m_windowFlicker->property("contentX"); QVariant dataY = m_windowFlicker->property("contentY"); //kWarning()<<"new X"<(parentItem())->view(); if (view) { m_desktop = view->effectiveWinId(); } else { m_desktop = 0; } m_windowsOffset = -QPoint(dataX.value(), dataY.value()); showThumbnails(); //kDebug() << "duration: " << m_time.elapsed(); //m_timer.restart(); } void WindowStrip::updateFrame() { if (!m_windowFlicker) { return; } QVariant data = m_windowFlicker->property("childrenPositions"); QList thumbnailsInfo = data.value >(); //kDebug() << "window positions" << thumbnailsInfo; QPoint offset; QGraphicsView *v = static_cast(parentItem())->view(); if (v) { offset = v->mapFromScene(m_windowFlicker->mapToScene(0,0)); } m_windows.clear(); - foreach (QVariant windowData, thumbnailsInfo) { + foreach (const QVariant &windowData, thumbnailsInfo) { const QVariantMap windowInfo = windowData.value(); WId winId = (WId)windowInfo["winId"].value().toInt(); m_windows[winId] = QRect(windowInfo["x"].value()+offset.x(), windowInfo["y"].value()+offset.y(), windowInfo["width"].value(), windowInfo["height"].value()); } update(); } #include "windowstrip.moc" diff --git a/applications/webbrowser/src/completionmodel.cpp b/applications/webbrowser/src/completionmodel.cpp index 6c91e789..b359f287 100644 --- a/applications/webbrowser/src/completionmodel.cpp +++ b/applications/webbrowser/src/completionmodel.cpp @@ -1,207 +1,207 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * 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 . * ***************************************************************************/ //#define KDE_DEPRECATED 1 #include "completionmodel.h" #include "completionitem.h" #include "history.h" // Nepomuk #include #include //#include #include #include "bookmark.h" #include //#include #include #include //#include #include #include #include #include #include #include "kdebug.h" class CompletionModelPrivate { public: QList items; QList filteredItems; Nepomuk::Query::Query query; Nepomuk::Query::QueryServiceClient* queryClient; History* history; QString filter; bool isPopulated; }; CompletionModel::CompletionModel(QObject *parent) : QObject(parent) { d = new CompletionModelPrivate; d->isPopulated = false; d->history = new History(this); connect(d->history, SIGNAL(dataChanged()), this, SIGNAL(dataChanged())); } CompletionModel::~CompletionModel() { delete d; } History* CompletionModel::history() { return d->history; } QList CompletionModel::items() { QList l; l.append(d->history->items()); l.append(d->items); return l; } QList CompletionModel::filteredBookmarks() { return filteredItems(d->items); } QList CompletionModel::filteredHistory() { return filteredItems(d->history->items()); } QList CompletionModel::filteredItems(const QList &l) { //QList l; //l.append(d->history->items()); //l.append(d->items); if (d->filter.isEmpty()) { return l; } d->filteredItems.clear(); QList filteredItems; foreach(QObject* it, l) { CompletionItem* ci = qobject_cast(it); if (ci) { // Matching, pretty basic right now if (ci->name().contains(d->filter, Qt::CaseInsensitive)) { filteredItems.append(ci); } else if (ci->url().contains(d->filter, Qt::CaseInsensitive)) { filteredItems.append(ci); } } } return filteredItems; } void CompletionModel::setFilter(const QString &filter) { d->filter = filter; //kDebug() << "OOO FIlter set to " << filter; emit dataChanged(); } void CompletionModel::populate() { //kDebug() << "populating model..."; if (!d->isPopulated) { d->isPopulated = true; d->history->loadHistory(); loadBookmarks(); } } void CompletionModel::loadBookmarks() { if (!Nepomuk::Query::QueryServiceClient::serviceAvailable()) { return; } kDebug() << "Loading bookmarks..."; Nepomuk::Types::Class bookmarkClass(Nepomuk::Bookmark::resourceTypeUri()); Nepomuk::Query::ResourceTypeTerm rtt(bookmarkClass); d->query.setTerm(rtt); d->queryClient = new Nepomuk::Query::QueryServiceClient(this); connect(d->queryClient, SIGNAL(finishedListing()), this, SLOT(finishedListing())); connect(d->queryClient, SIGNAL(newEntries(QList)), this, SLOT(newEntries(QList))); connect(d->queryClient, SIGNAL(entriesRemoved(QList)), this, SLOT(entriesRemoved(QList))); d->query.setLimit(64); d->queryClient->query(d->query); } void CompletionModel::finishedListing() { //kDebug() << "Done listing."; } void CompletionModel::newEntries(const QList< Nepomuk::Query::Result >& entries) { - foreach (Nepomuk::Query::Result res, entries) { + foreach (const Nepomuk::Query::Result &res, entries) { //kDebug() << "Result!!!" << res.resource().genericLabel() << res.resource().type(); CompletionItem* item = new CompletionItem(this); item->setResource(res.resource()); d->items.append(item); } emit dataChanged(); } void CompletionModel::entriesRemoved(const QList< QUrl >& urls) { // not efficient but I do think users will have thousands of bookmarks to make this cause any lag. // Also in the common case urls.size() == 1, so there will be only one iteration through the // bookmarks list. QMutableListIterator i(d->items); foreach (const QUrl &u, urls) { while (i.hasNext()) { CompletionItem * cItem = static_cast(i.next()); if (cItem && cItem->resourceUri() == u) { //kDebug() << "Removing" << u << cItem->url(); i.remove(); cItem->deleteLater(); break; } } i.toFront(); } emit dataChanged(); } #include "completionmodel.moc" diff --git a/components/metadatamodel/metadatacloudmodel.cpp b/components/metadatamodel/metadatacloudmodel.cpp index 71273f46..56323523 100644 --- a/components/metadatamodel/metadatacloudmodel.cpp +++ b/components/metadatamodel/metadatacloudmodel.cpp @@ -1,361 +1,361 @@ /* Copyright 2011 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. */ #include "metadatacloudmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MetadataCloudModel::MetadataCloudModel(QObject *parent) : AbstractMetadataModel(parent), m_queryClient(0) { QHash roleNames; roleNames[Label] = "label"; roleNames[Count] = "count"; setRoleNames(roleNames); } MetadataCloudModel::~MetadataCloudModel() { } void MetadataCloudModel::setCloudCategory(QString category) { if (m_cloudCategory == category) { return; } m_cloudCategory = category; askRefresh(); emit cloudCategoryChanged(); } QString MetadataCloudModel::cloudCategory() const { return m_cloudCategory; } QVariantList MetadataCloudModel::categories() const { return m_categories; } void MetadataCloudModel::setAllowedCategories(const QVariantList &whitelist) { QSet set = variantToStringList(whitelist).toSet(); if (set == m_allowedCategories) { return; } m_allowedCategories = set; emit allowedCategoriesChanged(); } QVariantList MetadataCloudModel::allowedCategories() const { return stringToVariantList(m_allowedCategories.values()); } void MetadataCloudModel::doQuery() { QDeclarativePropertyMap *parameters = qobject_cast(extraParameters()); //check if really all properties to build the query are null if (m_cloudCategory.isEmpty()) { return; } setStatus(Waiting); QString query = "select distinct ?label count(*) as ?count where { "; if (m_cloudCategory == "kao:Activity") { query += " ?activity nao:isRelated ?r . ?activity rdf:type kao:Activity . ?activity kao:activityIdentifier ?label "; } else { query += " ?r " + m_cloudCategory + " ?label"; } if (!resourceType().isEmpty()) { QString type = resourceType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r rdf:type " + type + " . }))) "; } else { query += " . ?r rdf:type " + type; } if (type != "nfo:Bookmark") { //FIXME: remove bookmarks if not explicitly asked for query += " . FILTER(!bif:exists((select (1) where { ?r a . }))) "; } } if (!mimeType().isEmpty()) { QString type = mimeType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) . }))) "; } else { query += " . ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) "; } } if (parameters && parameters->size() > 0) { foreach (const QString &key, parameters->keys()) { QString parameter = parameters->value(key).toString(); bool negation = false; if (parameter.startsWith('!')) { parameter = parameter.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) . }))) "; } else { query += " . ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) "; } } } if (!activityId().isEmpty()) { QString activity = activityId(); bool negation = false; if (activity.startsWith('!')) { activity = activity.remove(0, 1); negation = true; } Nepomuk::Resource acRes(activity, Nepomuk::Vocabulary::KAO::Activity()); if (negation) { query += ". FILTER(!bif:exists((select (1) where { <" + acRes.resourceUri().toString() + "> ?r . }))) "; } else { query += " . <" + acRes.resourceUri().toString() + "> nao:isRelated ?r "; } } //this is an AND set of tags.. should be allowed OR as well? foreach (const QString &tag, tagStrings()) { QString individualTag = tag; bool negation = false; if (individualTag.startsWith('!')) { individualTag = individualTag.remove(0, 1); negation = true; } if (negation) { query += ". FILTER(!bif:exists((select (1) where { ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\"))}))) "; } else { query += ". ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\")) "; } } if (startDate().isValid() || endDate().isValid()) { if (startDate().isValid()) { query += " . { \ ?r ?v2 . FILTER(?v2>\"" + startDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?r ?v3 . FILTER(?v3>\"" + startDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?v4 ?r .\ ?v4 ?v5 .\ FILTER(?v5>\"" + startDate().toString(Qt::ISODate) + "\"^^) . \ }"; } if (endDate().isValid()) { query += " . { \ ?r ?v2 . FILTER(?v2<\"" + endDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?r ?v3 . FILTER(?v3<\"" + endDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?v4 ?r .\ ?v4 ?v5 .\ FILTER(?v5<\"" + endDate().toString(Qt::ISODate) + "\"^^) . \ }"; } } if (minimumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating >=" + QString::number(minimumRating()) + ") "; } if (maximumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating <=" + QString::number(maximumRating()) + ") "; } //Exclude who doesn't have url query += " . FILTER(bif:exists((select (1) where { ?r nie:url ?h . }))) "; query += " . ?r ?v1 . FILTER(?v1>0) . } group by ?label order by ?label"; kDebug() << "Performing the Sparql query" << query; beginResetModel(); m_results.clear(); endResetModel(); emit countChanged(); delete m_queryClient; m_queryClient = new Nepomuk::Query::QueryServiceClient(this); connect(m_queryClient, SIGNAL(newEntries(const QList &)), this, SLOT(newEntries(const QList &))); connect(m_queryClient, SIGNAL(entriesRemoved(const QList &)), this, SLOT(entriesRemoved(const QList &))); connect(m_queryClient, SIGNAL(finishedListing()), this, SLOT(finishedListing())); m_queryClient->sparqlQuery(query); } void MetadataCloudModel::newEntries(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); QVector > results; QVariantList categories; - foreach (Nepomuk::Query::Result res, entries) { + foreach (const Nepomuk::Query::Result &res, entries) { QString label; int count = res.additionalBinding(QLatin1String("count")).variant().toInt(); QVariant rawLabel = res.additionalBinding(QLatin1String("label")).variant(); if (rawLabel.canConvert()) { label = rawLabel.value().className(); } else if (!rawLabel.value().scheme().isEmpty()) { const QUrl url = rawLabel.value(); if (url.scheme() == "nepomuk") { label = Nepomuk::Resource(url).genericLabel(); //TODO: it should convert from ontology url to short form nfo:Document } else { label = propertyShortName(url); } } else if (rawLabel.canConvert()) { label = rawLabel.toString(); } else if (rawLabel.canConvert()) { label = QString::number(rawLabel.toInt()); } else { continue; } if (label.isEmpty() || !(m_allowedCategories.isEmpty() || m_allowedCategories.contains(label))) { continue; } results << QPair(label, count); categories << label; } if (results.count() > 0) { beginInsertRows(QModelIndex(), m_results.count(), m_results.count()+results.count()-1); m_results << results; m_categories << categories; endInsertRows(); emit countChanged(); emit categoriesChanged(); } } void MetadataCloudModel::entriesRemoved(const QList &urls) { //FIXME: optimize kDebug()<= 0) { beginRemoveRows(QModelIndex(), index, index); m_results.remove(index); endRemoveRows(); } } emit countChanged(); } void MetadataCloudModel::finishedListing() { setStatus(Idle); } QVariant MetadataCloudModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= m_results.count()){ return QVariant(); } const QPair row = m_results[index.row()]; switch (role) { case Label: return row.first; case Count: return row.second; default: return QVariant(); } } #include "metadatacloudmodel.moc" diff --git a/components/metadatamodel/metadatamodel.cpp b/components/metadatamodel/metadatamodel.cpp index c0763ff8..f04fded6 100644 --- a/components/metadatamodel/metadatamodel.cpp +++ b/components/metadatamodel/metadatamodel.cpp @@ -1,910 +1,910 @@ /* Copyright 2011 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. */ #include "metadatamodel.h" #include "resourcewatcher.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kao.h" using namespace Nepomuk::Vocabulary; using namespace Soprano::Vocabulary; MetadataModel::MetadataModel(QObject *parent) : AbstractMetadataModel(parent), m_runningClients(0), m_countQueryClient(0), m_limit(0), m_pageSize(30), m_scoreResources(false), m_thumbnailSize(180, 120), m_thumbnailerPlugins(new QStringList(KIO::PreviewJob::availablePlugins())) { m_newEntriesTimer = new QTimer(this); m_newEntriesTimer->setSingleShot(true); connect(m_newEntriesTimer, SIGNAL(timeout()), this, SLOT(newEntriesDelayed())); m_previewTimer = new QTimer(this); m_previewTimer->setSingleShot(true); connect(m_previewTimer, SIGNAL(timeout()), this, SLOT(delayedPreview())); //using the same cache of the engine, they index both by url m_imageCache = new KImageCache("plasma_engine_preview", 10485760); m_watcher = new Nepomuk::ResourceWatcher(this); m_watcher->addProperty(NAO::numericRating()); connect(m_watcher, SIGNAL(propertyAdded(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)), this, SLOT(propertyChanged(Nepomuk::Resource, Nepomuk::Types::Property, QVariant))); QHash roleNames; roleNames[Qt::DisplayRole] = "display"; roleNames[Qt::DecorationRole] = "decoration"; roleNames[Label] = "label"; roleNames[Description] = "description"; roleNames[Types] = "types"; roleNames[ClassName] = "className"; roleNames[GenericClassName] = "genericClassName"; roleNames[HasSymbol] = "hasSymbol"; roleNames[Icon] = "icon"; roleNames[Thumbnail] = "thumbnail"; roleNames[IsFile] = "isFile"; roleNames[Exists] = "exists"; roleNames[Rating] = "rating"; roleNames[NumericRating] = "numericRating"; roleNames[Symbols] = "symbols"; roleNames[ResourceUri] = "resourceUri"; roleNames[ResourceType] = "resourceType"; roleNames[MimeType] = "mimeType"; roleNames[Url] = "url"; roleNames[Topics] = "topics"; roleNames[TopicsNames] = "topicsNames"; roleNames[Tags] = "tags"; roleNames[TagsNames] = "tagsNames"; setRoleNames(roleNames); } MetadataModel::~MetadataModel() { delete m_imageCache; } void MetadataModel::setQuery(const Nepomuk::Query::Query &query) { m_query = query; if (Nepomuk::Query::QueryServiceClient::serviceAvailable()) { askRefresh(); } } Nepomuk::Query::Query MetadataModel::query() const { return m_query; } void MetadataModel::setQueryString(const QString &query) { if (query == m_queryString || query == "nepomuk") { return; } m_queryString = query; askRefresh(); emit queryStringChanged(); } QString MetadataModel::queryString() const { return m_queryString; } void MetadataModel::setLimit(int limit) { if (limit == m_limit) { return; } m_limit = limit; askRefresh(); emit limitChanged(); } int MetadataModel::limit() const { return m_limit; } void MetadataModel::setScoreResources(bool score) { if (m_scoreResources == score) { return; } m_scoreResources = score; askRefresh(); emit scoreResourcesChanged(); } bool MetadataModel::scoreResources() const { return m_scoreResources; } void MetadataModel::setLazyLoading(bool lazy) { //lazy loading depends from the page zise, that is not directly user controllable if (lazy == (m_pageSize > 0)) { return; } //TODO: a way to control this? maybe from the available memory? m_pageSize = lazy ? 30 : -1; askRefresh(); emit lazyLoadingChanged(); } bool MetadataModel::lazyLoading() const { return (m_pageSize > 0); } void MetadataModel::setSortBy(const QVariantList &sortBy) { QStringList stringList = variantToStringList(sortBy); if (m_sortBy == stringList) { return; } m_sortBy = stringList; askRefresh(); emit sortByChanged(); } QVariantList MetadataModel::sortBy() const { return stringToVariantList(m_sortBy); } void MetadataModel::setSortOrder(Qt::SortOrder sortOrder) { if (m_sortOrder == sortOrder) { return; } m_sortOrder = sortOrder; askRefresh(); emit sortOrderChanged(); } Qt::SortOrder MetadataModel::sortOrder() const { return m_sortOrder; } int MetadataModel::find(const QString &resourceUri) { int index = -1; int i = 0; Nepomuk::Resource resToFind = Nepomuk::Resource::fromResourceUri(resourceUri); foreach (const Nepomuk::Resource &res, m_resources) { if (res == resToFind) { index = i; break; } ++i; } return index; } void MetadataModel::doQuery() { QDeclarativePropertyMap *parameters = qobject_cast(extraParameters()); //check if really all properties to build the query are null if (m_queryString.isEmpty() && resourceType().isEmpty() && mimeType().isEmpty() && activityId().isEmpty() && tagStrings().size() == 0 && !startDate().isValid() && !endDate().isValid() && minimumRating() <= 0 && maximumRating() <= 0 && parameters->size() == 0) { return; } setStatus(Waiting); m_query = Nepomuk::Query::Query(); m_query.setQueryFlags(Nepomuk::Query::Query::WithoutFullTextExcerpt); Nepomuk::Query::AndTerm rootTerm; if (!m_queryString.isEmpty()) { rootTerm.addSubTerm(Nepomuk::Query::QueryParser::parseQuery(m_queryString).term()); } if (!resourceType().isEmpty()) { //FIXME: more elegant QString type = resourceType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(Nepomuk::Query::ResourceTypeTerm(propertyUrl(type)))); } else { rootTerm.addSubTerm(Nepomuk::Query::ResourceTypeTerm(propertyUrl(type))); if (type != "nfo:Bookmark") { //FIXME: remove bookmarks if not explicitly asked for rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(Nepomuk::Query::ResourceTypeTerm(propertyUrl("nfo:Bookmark")))); } } } if (!mimeType().isEmpty()) { QString type = mimeType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } Nepomuk::Query::ComparisonTerm term(Nepomuk::Vocabulary::NIE::mimeType(), Nepomuk::Query::LiteralTerm(type)); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } if (parameters && parameters->size() > 0) { foreach (const QString &key, parameters->keys()) { QString parameter = parameters->value(key).toString(); bool negation = false; if (parameter.startsWith('!')) { parameter = parameter.remove(0, 1); negation = true; } //FIXME: Contains should work, but doesn't match for file names Nepomuk::Query::ComparisonTerm term(propertyUrl(key), Nepomuk::Query::LiteralTerm(parameter)); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } } if (!activityId().isEmpty()) { QString activity = activityId(); bool negation = false; if (activity.startsWith('!')) { activity = activity.remove(0, 1); negation = true; } kDebug() << "Asking for resources of activity" << activityId(); Nepomuk::Resource acRes(activity, Nepomuk::Vocabulary::KAO::Activity()); Nepomuk::Query::ComparisonTerm term(Soprano::Vocabulary::NAO::isRelated(), Nepomuk::Query::ResourceTerm(acRes)); term.setInverted(true); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } foreach (const QString &tag, tagStrings()) { QString individualTag = tag; bool negation = false; if (individualTag.startsWith('!')) { individualTag = individualTag.remove(0, 1); negation = true; } Nepomuk::Query::ComparisonTerm term( Soprano::Vocabulary::NAO::hasTag(), Nepomuk::Query::ResourceTerm(Nepomuk::Tag(individualTag))); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } if (startDate().isValid() || endDate().isValid()) { rootTerm.addSubTerm(Nepomuk::Query::dateRangeQuery(startDate(), endDate()).term()); } if (minimumRating() > 0) { const Nepomuk::Query::LiteralTerm ratingTerm(minimumRating()); Nepomuk::Query::ComparisonTerm term = Nepomuk::Types::Property(propertyUrl("nao:numericRating")) > ratingTerm; rootTerm.addSubTerm(term); } if (maximumRating() > 0) { const Nepomuk::Query::LiteralTerm ratingTerm(maximumRating()); Nepomuk::Query::ComparisonTerm term = Nepomuk::Types::Property(propertyUrl("nao:numericRating")) < ratingTerm; rootTerm.addSubTerm(term); } if (m_scoreResources) { QString activity = activityId(); if (activity.startsWith('!')) { activity = activity.remove(0, 1); } Nepomuk::Query::ComparisonTerm term = Nepomuk::Query::ComparisonTerm(propertyUrl("kao:targettedResource"), Nepomuk::Query::Term()); term.setVariableName("c"); term.setInverted(true); Nepomuk::Query::AndTerm andTerm = Nepomuk::Query::AndTerm(); Nepomuk::Query::ResourceTypeTerm typeTerm(KAO::ResourceScoreCache()); andTerm.addSubTerm(typeTerm); if (!activity.isEmpty()) { Nepomuk::Query::ComparisonTerm usedActivityTerm(propertyUrl("kao:usedActivity"), Nepomuk::Query::ResourceTerm(Nepomuk::Resource(activity, Nepomuk::Vocabulary::KAO::Activity())) ); andTerm.addSubTerm(usedActivityTerm); } Nepomuk::Query::ComparisonTerm cachedScoreTerm(propertyUrl("kao:cachedScore"), Nepomuk::Query::Term()); cachedScoreTerm.setVariableName("score"); cachedScoreTerm.setSortWeight(1, Qt::DescendingOrder); andTerm.addSubTerm(cachedScoreTerm); term.setSubTerm(andTerm); rootTerm.addSubTerm(term); } //bind directly some properties, to avoid calling hyper inefficient resource::property { m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NIE::url())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NAO::hasSymbol())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NIE::mimeType())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NAO::description())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(Xesam::description())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(RDFS::comment())); } int weight = m_sortBy.length() + 1; foreach (const QString &sortProperty, m_sortBy) { Nepomuk::Query::ComparisonTerm sortTerm(propertyUrl(sortProperty), Nepomuk::Query::Term()); sortTerm.setSortWeight(weight, m_sortOrder); rootTerm.addSubTerm(sortTerm); --weight; } m_query.setTerm(rootTerm); kDebug()<<"Sparql query:"< &)), this, SLOT(countQueryResult(const QList &))); if (m_limit > 0) { m_query.setLimit(m_limit); } m_countQueryClient->sparqlQuery(m_query.toSparqlQuery(Nepomuk::Query::Query::CreateCountQuery)); //if page size is invalid, fetch all if (m_pageSize < 1) { fetchResultsPage(0); } } void MetadataModel::fetchResultsPage(int page) { Nepomuk::Query::QueryServiceClient *client = new Nepomuk::Query::QueryServiceClient(this); m_queryClients[page] = client; m_pagesForClient[client] = page; m_validIndexForPage[page] = 0; Nepomuk::Query::Query pageQuery(m_query); if (m_pageSize > 0) { pageQuery.setOffset(m_pageSize*page); pageQuery.setLimit(m_pageSize); } client->query(pageQuery); connect(client, SIGNAL(newEntries(const QList &)), this, SLOT(newEntries(const QList &))); connect(client, SIGNAL(entriesRemoved(const QList &)), this, SLOT(entriesRemoved(const QList &))); connect(client, SIGNAL(finishedListing()), this, SLOT(finishedListing())); m_queryClientsHistory << client; ++m_runningClients; } void MetadataModel::countQueryResult(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); //this should be always 1 - foreach (Nepomuk::Query::Result res, entries) { + foreach (const Nepomuk::Query::Result &res, entries) { int count = res.additionalBinding(QLatin1String("cnt")).variant().toInt(); if (count < m_resources.size()) { beginRemoveRows(QModelIndex(), count-1, m_resources.size()-1); m_resources.resize(count); endRemoveRows(); } else if (count > m_resources.size()) { beginInsertRows(QModelIndex(), m_resources.size(), count-1); m_resources.resize(count); endInsertRows(); } } } void MetadataModel::newEntries(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); const int page = m_pagesForClient.value(qobject_cast(sender())); - foreach (Nepomuk::Query::Result res, entries) { + foreach (const Nepomuk::Query::Result &res, entries) { //kDebug() << "Result!!!" << res.resource().genericLabel() << res.resource().type(); //kDebug() << "Result label:" << res.genericLabel(); Nepomuk::Resource resource = res.resource(); if (res.requestProperties().value(propertyUrl("nie:url")).toString().isEmpty()) { continue; } m_resourcesToInsert[page] << resource; //pre-popuplating of the cache to avoid accessing properties directly //label is a bit too complex to take from query m_cachedResources[resource][Label] = resource.genericLabel(); QString description = res.requestProperties().value(NAO::description()).toString(); if (description.isEmpty()) { description = res.requestProperties().value(Xesam::description()).toString(); } if (description.isEmpty()) { description = res.requestProperties().value(RDFS::comment()).toString(); } if (!description.isEmpty()) { m_cachedResources[resource][Description] = description; } m_cachedResources[resource][Url] = res.requestProperties().value(propertyUrl("nie:url")).toString(); QStringList types; foreach (const QUrl &u, resource.types()) { types << u.toString(); } m_cachedResources[resource][Types] = types; Soprano::Node symbol = res.requestProperties().value(NAO::hasSymbol()); if (!symbol.toString().isEmpty()) { m_cachedResources[resource][Icon] = symbol.toString(); } else { m_cachedResources[resource][Icon] = KMimeType::iconNameForUrl(m_cachedResources[resource][Url].toString()); } //those seems to not be possible avoiding to access the resource m_cachedResources[resource][ClassName] = resource.className(); m_cachedResources[resource][ResourceType] = resource.resourceType(); m_cachedResources[resource][IsFile] = resource.isFile(); m_cachedResources[resource][HasSymbol] = res.requestProperties().value(NAO::hasSymbol()).toString(); m_cachedResources[resource][MimeType] = res.requestProperties().value(NIE::mimeType()).toString(); //FIXME: The most complicated of all, this should really be simplified { //FIXME: a more elegant way is needed QString genericClassName = m_cachedResources.value(resource).value(ClassName).toString(); //FIXME: most bookmarks are Document too, so Bookmark wins if (m_cachedResources.value(resource).value(Label).value >().contains(NFO::Bookmark())) { m_cachedResources[resource][GenericClassName] = "Bookmark"; } else { Nepomuk::Types::Class resClass(resource.resourceType()); - foreach (Nepomuk::Types::Class parentClass, resClass.parentClasses()) { + foreach (const Nepomuk::Types::Class &parentClass, resClass.parentClasses()) { const QString label = parentClass.label(); if (label == "Document" || label == "Audio" || label == "Video" || label == "Image" || label == "Contact") { genericClassName = label; break; //two cases where the class is 2 levels behind the level of generalization we want } else if (parentClass.label() == "RasterImage") { genericClassName = "Image"; } else if (parentClass.label() == "TextDocument") { genericClassName = "Document"; } } m_cachedResources[resource][GenericClassName] = genericClassName; } } } if (!m_newEntriesTimer->isActive() && !m_resourcesToInsert[page].isEmpty()) { m_newEntriesTimer->start(200); } } void MetadataModel::newEntriesDelayed() { if (m_resourcesToInsert.isEmpty()) { return; } m_elapsedTime.start(); QHash >::const_iterator i; for (i = m_resourcesToInsert.constBegin(); i != m_resourcesToInsert.constEnd(); ++i) { const QList resourcesToInsert = i.value(); m_watcher->stop(); int pageStart = 0; if (m_pageSize > 0) { pageStart = i.key() * m_pageSize; } int startOffset = m_validIndexForPage.value(i.key()); int offset = startOffset; //if new result arrive on an already running query, they may arrive before countQueryResult if (m_resources.size() < pageStart + startOffset + 1) { beginInsertRows(QModelIndex(), m_resources.size(), pageStart + startOffset); m_resources.resize(pageStart + startOffset + 1); endInsertRows(); } //this happens only when m_validIndexForPage has been invalidate by row removal if (!m_validIndexForPage.contains(i.key()) && m_resources[pageStart + startOffset].isValid()) { while (startOffset < m_resources.size() && m_resources[pageStart + startOffset].isValid()) { ++startOffset; ++offset; } } - foreach (Nepomuk::Resource res, resourcesToInsert) { + foreach (const Nepomuk::Resource &res, resourcesToInsert) { //kDebug() << "Result!!!" << res.genericLabel() << res.type(); //kDebug() << "Page:" << i.key() << "Index:"<< pageStart + offset; m_uriToResourceIndex[res.resourceUri()] = pageStart + offset; //there can be new results before the count query gets updated if (pageStart + offset < m_resources.size()) { m_resources[pageStart + offset] = res; m_watcher->addResource(res); ++offset; } else { beginInsertRows(QModelIndex(), m_resources.size(), pageStart + offset); m_resources.resize(pageStart + offset + 1); m_resources[pageStart + offset] = res; m_watcher->addResource(res); ++offset; endInsertRows(); } } m_validIndexForPage[i.key()] = offset; m_watcher->start(); emit dataChanged(createIndex(pageStart + startOffset, 0), createIndex(pageStart + startOffset + resourcesToInsert.count()-1, 0)); } kDebug() << "Elapsed time populating the model" << m_elapsedTime.elapsed(); m_resourcesToInsert.clear(); } void MetadataModel::propertyChanged(Nepomuk::Resource res, Nepomuk::Types::Property prop, QVariant val) { Q_UNUSED(prop) Q_UNUSED(val) const int index = m_uriToResourceIndex.value(res.resourceUri()); if (index >= 0) { emit dataChanged(createIndex(index, 0, 0), createIndex(index, 0, 0)); } } void MetadataModel::entriesRemoved(const QList &urls) { int prevIndex = -100; //pack all the stuff to remove in groups, to emit the least possible signals //this assumes urls are in the same order they arrived ion the results //it's a map because we want to remove values from the vector in inverted order to keep indexes valid trough the remove loop QMap toRemove; foreach (const QUrl &url, urls) { const int index = m_uriToResourceIndex.value(url); if (index == prevIndex + 1) { toRemove[prevIndex]++; } else { toRemove[index] = 1; } prevIndex = index; } //all the page indexes may be invalid now m_validIndexForPage.clear(); QMap::const_iterator i = toRemove.constEnd(); while (i != toRemove.constBegin()) { --i; beginRemoveRows(QModelIndex(), i.key(), i.key()+i.value()-1); m_resources.remove(i.key(), i.value()); endRemoveRows(); } //another loop, we don't depend to m_uriToResourceIndex in data(), but we take this doublesafety foreach (const QUrl &url, urls) { m_uriToResourceIndex.remove(url); } //FIXME: this loop makes all the optimizations useless, get rid either of it or the optimizations for (int i = 0; i < m_resources.count(); ++i) { m_uriToResourceIndex[m_resources[i].resourceUri()] = i; } emit countChanged(); } void MetadataModel::finishedListing() { --m_runningClients; if (m_runningClients <= 0) { setStatus(Idle); if (m_queryClientsHistory.count() > 10) { for (int i = 0; i < m_queryClientsHistory.count() - 10; ++i) { Nepomuk::Query::QueryServiceClient *client = m_queryClientsHistory.first(); m_queryClientsHistory.pop_front(); int page = m_pagesForClient.value(client); m_queryClients.remove(page); m_pagesForClient.remove(client); delete client; } } } } QVariant MetadataModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= m_resources.count()){ return QVariant(); } const Nepomuk::Resource &resource = m_resources[index.row()]; if (!resource.isValid() && m_pageSize > 0 && !m_queryClients.contains(floor(index.row()/m_pageSize))) { //HACK const_cast(this)->fetchResultsPage(floor(index.row()/m_pageSize)); return QVariant(); //m_pageSize <= 0, means fetch all } else if (!resource.isValid() && !m_queryClients.contains(0)) { //HACK const_cast(this)->fetchResultsPage(0); return QVariant(); } else if (!resource.isValid()) { return QVariant(); } //We're lucky: was cached if (m_cachedResources.value(resource).contains(role)) { return m_cachedResources.value(resource).value(role); } switch (role) { case Qt::DisplayRole: case Label: return m_cachedResources.value(resource).value(Label); case Qt::DecorationRole: return KIcon(m_cachedResources.value(resource).value(Icon).toString()); case HasSymbol: case Icon: return m_cachedResources.value(resource).value(Icon).toString(); case Thumbnail: { KUrl url(m_cachedResources.value(resource).value(Url).toString()); if (m_cachedResources.value(resource).value(IsFile).toBool() && url.isLocalFile()) { QImage preview = QImage(m_thumbnailSize, QImage::Format_ARGB32_Premultiplied); if (m_imageCache->findImage(url.prettyUrl(), &preview)) { return preview; } m_previewTimer->start(100); const_cast(this)->m_filesToPreview[url] = QPersistentModelIndex(index); } return QVariant(); } case Exists: return resource.exists(); case Rating: return resource.rating(); case NumericRating: return resource.property(NAO::numericRating()).toString(); case Symbols: return resource.symbols(); case ResourceUri: return resource.resourceUri(); case Topics: { QStringList topics; foreach (const Nepomuk::Resource &u, resource.topics()) { topics << u.resourceUri().toString(); } return topics; } case TopicsNames: { QStringList topicNames; foreach (const Nepomuk::Resource &u, resource.topics()) { topicNames << u.genericLabel(); } return topicNames; } case Tags: { QStringList tags; foreach (const Nepomuk::Tag &tag, resource.tags()) { tags << tag.resourceUri().toString(); } return tags; } case TagsNames: { QStringList tagNames; foreach (const Nepomuk::Tag &tag, resource.tags()) { tagNames << tag.genericLabel(); } return tagNames; } default: return QVariant(); } } void MetadataModel::delayedPreview() { QHash::const_iterator i = m_filesToPreview.constBegin(); KFileItemList list; while (i != m_filesToPreview.constEnd()) { KUrl file = i.key(); QPersistentModelIndex index = i.value(); if (!m_previewJobs.contains(file) && file.isValid()) { list.append(KFileItem(file, QString(), 0)); m_previewJobs.insert(file, QPersistentModelIndex(index)); } ++i; } if (list.size() > 0) { KIO::PreviewJob* job = KIO::filePreview(list, m_thumbnailSize, m_thumbnailerPlugins); //job->setIgnoreMaximumSize(true); kDebug() << "Created job" << job; connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), this, SLOT(showPreview(const KFileItem&, const QPixmap&))); connect(job, SIGNAL(failed(const KFileItem&)), this, SLOT(previewFailed(const KFileItem&))); } m_filesToPreview.clear(); } void MetadataModel::showPreview(const KFileItem &item, const QPixmap &preview) { QPersistentModelIndex index = m_previewJobs.value(item.url()); m_previewJobs.remove(item.url()); if (!index.isValid()) { return; } m_imageCache->insertImage(item.url().prettyUrl(), preview.toImage()); //kDebug() << "preview size:" << preview.size(); emit dataChanged(index, index); } void MetadataModel::previewFailed(const KFileItem &item) { m_previewJobs.remove(item.url()); } // Just signal QSortFilterProxyModel to do the real sorting. void MetadataModel::sort(int column, Qt::SortOrder order) { Q_UNUSED(column); Q_UNUSED(order); beginResetModel(); endResetModel(); } void MetadataModel::setThumbnailSize(const QSize& size) { m_thumbnailSize = size; emit thumbnailSizeChanged(); } QSize MetadataModel::thumbnailSize() const { return m_thumbnailSize; } #include "metadatamodel.moc" diff --git a/components/metadatamodel/metadatatimelinemodel.cpp b/components/metadatamodel/metadatatimelinemodel.cpp index bfa7a775..643ae396 100644 --- a/components/metadatamodel/metadatatimelinemodel.cpp +++ b/components/metadatamodel/metadatatimelinemodel.cpp @@ -1,340 +1,340 @@ /* Copyright 2011 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. */ #include "metadatatimelinemodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kao.h" MetadataTimelineModel::MetadataTimelineModel(QObject *parent) : AbstractMetadataModel(parent), m_queryClient(0), m_totalCount(0) { QHash roleNames; roleNames[LabelRole] = "label"; roleNames[YearRole] = "year"; roleNames[MonthRole] = "month"; roleNames[DayRole] = "day"; roleNames[CountRole] = "count"; setRoleNames(roleNames); askRefresh(); } MetadataTimelineModel::~MetadataTimelineModel() { } void MetadataTimelineModel::setLevel(MetadataTimelineModel::Level level) { if (m_level == level) { return; } m_level = level; askRefresh(); emit levelChanged(); } MetadataTimelineModel::Level MetadataTimelineModel::level() const { return m_level; } QString MetadataTimelineModel::description() const { if (m_results.isEmpty()) { return QString(); } //TODO: manage cases where start and enddate cover more than one year/month switch (m_level) { case Year: return i18n("All years"); case Month: return KGlobal::locale()->calendar()->yearString(startDate(), KCalendarSystem::LongFormat); case Day: default: 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)); } } void MetadataTimelineModel::doQuery() { QDeclarativePropertyMap *parameters = qobject_cast(extraParameters()); m_totalCount = 0; setStatus(Waiting); QString monthQuery; QString dayQuery; if (m_level >= Month) { monthQuery = "bif:month(?label)"; } else { monthQuery = '0'; } if (m_level >= Day) { dayQuery = "bif:dayofmonth(?label)"; } else { dayQuery = '0'; } 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); if (!resourceType().isEmpty()) { QString type = resourceType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r rdf:type " + type + " . }))) "; } else { query += " . ?r rdf:type " + type; } if (type != "nfo:Bookmark") { //FIXME: remove bookmarks if not explicitly asked for query += " . FILTER(!bif:exists((select (1) where { ?r a . }))) "; } } if (!mimeType().isEmpty()) { QString type = mimeType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) . }))) "; } else { query += " . ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) "; } } if (parameters && parameters->size() > 0) { foreach (const QString &key, parameters->keys()) { QString parameter = parameters->value(key).toString(); bool negation = false; if (parameter.startsWith('!')) { parameter = parameter.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) . }))) "; } else { query += " . ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) "; } } } if (!activityId().isEmpty()) { QString activity = activityId(); bool negation = false; if (activity.startsWith('!')) { activity = activity.remove(0, 1); negation = true; } Nepomuk::Resource acRes(activity, Nepomuk::Vocabulary::KAO::Activity()); if (negation) { query += ". FILTER(!bif:exists((select (1) where { <" + acRes.resourceUri().toString() + "> ?r . }))) "; } else { query += " . <" + acRes.resourceUri().toString() + "> nao:isRelated ?r "; } } //this is an AND set of tags.. should be allowed OR as well? foreach (const QString &tag, tagStrings()) { QString individualTag = tag; bool negation = false; if (individualTag.startsWith('!')) { individualTag = individualTag.remove(0, 1); negation = true; } if (negation) { query += ". FILTER(!bif:exists((select (1) where { ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\"))}))) "; } else { query += ". ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\")) "; } } if (startDate().isValid() || endDate().isValid()) { if (startDate().isValid()) { query += ". ?r ?v2 . FILTER(?v2>\"" + startDate().toString(Qt::ISODate) + "\"^^) "; } if (endDate().isValid()) { query += ". ?r ?v2 . FILTER(?v2<\"" + endDate().toString(Qt::ISODate) + "\"^^) "; } } if (minimumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating >=" + QString::number(minimumRating()) + ") "; } if (maximumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating <=" + QString::number(maximumRating()) + ") "; } query += " . ?r ?v1 . FILTER(?v1>0) . } "; //Group by construction query += " group by bif:year(?label) "; if (m_level >= Month) { query += " bif:month(?label) "; } if (m_level >= Day) { query += " bif:dayofmonth(?label) "; } query += " order by ?year ?month ?day "; kDebug() << "Performing the Sparql query" << query; beginResetModel(); m_results.clear(); endResetModel(); emit countChanged(); emit totalCountChanged(); emit descriptionChanged(); if (m_queryClient) { m_queryClient->close(); } delete m_queryClient; m_queryClient = new Nepomuk::Query::QueryServiceClient(this); connect(m_queryClient, SIGNAL(newEntries(const QList &)), this, SLOT(newEntries(const QList &))); connect(m_queryClient, SIGNAL(entriesRemoved(const QList &)), this, SLOT(entriesRemoved(const QList &))); connect(m_queryClient, SIGNAL(finishedListing()), this, SLOT(finishedListing())); m_queryClient->sparqlQuery(query); } void MetadataTimelineModel::newEntries(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); QVector > results; QVariantList categories; - foreach (Nepomuk::Query::Result res, entries) { + foreach (const Nepomuk::Query::Result &res, entries) { QString label; int count = res.additionalBinding(QLatin1String("count")).variant().toInt(); int year = res.additionalBinding(QLatin1String("year")).variant().toInt(); int month = res.additionalBinding(QLatin1String("month")).variant().toInt(); int day = res.additionalBinding(QLatin1String("day")).variant().toInt(); QHash resHash; resHash[YearRole] = year; resHash[MonthRole] = month; resHash[DayRole] = day; resHash[CountRole] = count; m_totalCount += count; results << resHash; } if (results.count() > 0) { beginInsertRows(QModelIndex(), m_results.count(), m_results.count()+results.count()); m_results << results; m_categories << categories; endInsertRows(); emit countChanged(); emit totalCountChanged(); emit descriptionChanged(); } } void MetadataTimelineModel::entriesRemoved(const QList &urls) { //FIXME: we don't have urls here return; emit countChanged(); emit totalCountChanged(); } void MetadataTimelineModel::finishedListing() { setStatus(Idle); } QVariant MetadataTimelineModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= m_results.count()){ return QVariant(); } const QHash row = m_results[index.row()]; if (role == LabelRole) { switch(m_level) { case Year: return row.value(YearRole); case Month: return KGlobal::locale()->calendar()->monthName(row.value(MonthRole), row.value(YearRole), KCalendarSystem::LongName); case Day: default: return row.value(DayRole); } } return row.value((Roles)role); } #include "metadatatimelinemodel.moc" diff --git a/components/mobilecomponents/categorizedproxymodel.cpp b/components/mobilecomponents/categorizedproxymodel.cpp index af9e2bf9..65e6dd79 100644 --- a/components/mobilecomponents/categorizedproxymodel.cpp +++ b/components/mobilecomponents/categorizedproxymodel.cpp @@ -1,238 +1,238 @@ /* Copyright 2011 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. */ #include "categorizedproxymodel.h" #include #include CategorizedProxyModel::CategorizedProxyModel(QObject *parent) : QSortFilterProxyModel(parent), m_categoryRoleInt(Qt::UserRole) { m_fillCategoriesTimer = new QTimer(this); m_fillCategoriesTimer->setSingleShot(true); connect(m_fillCategoriesTimer, SIGNAL(timeout()), this, SLOT(fillCategories())); } CategorizedProxyModel::~CategorizedProxyModel() { } void CategorizedProxyModel::setCategoryRole(const QString &role) { if (role == m_categoryRoleString) { return; } m_categoryRoleString = role; m_fillCategoriesTimer->start(0); } QString CategorizedProxyModel::categoryRole() const { return m_categoryRoleString; } void CategorizedProxyModel::setCurrentCategory(const QString &category) { if (m_currentCategory == category) { return; } m_currentCategory = category; beginResetModel(); endResetModel(); } QString CategorizedProxyModel::currentCategory() const { return m_currentCategory; } QStringList CategorizedProxyModel::categories() const { return m_categories; } void CategorizedProxyModel::setModel(QObject *source) { QAbstractItemModel *model = qobject_cast(source); if (!model) { return; } m_fillCategoriesTimer->start(0); // TODO disconnect old model connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(slotInsertRows(QModelIndex, int, int)), Qt::QueuedConnection); connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), SLOT(slotRemoveRows(QModelIndex, int, int))); connect(model, SIGNAL(modelReset()), this, SLOT(fillCategories()), Qt::QueuedConnection); setRoleNames(model->roleNames()); setSourceModel(model); } QObject *CategorizedProxyModel::model() const { return sourceModel(); } int CategorizedProxyModel::rowCount(const QModelIndex &parent) const { //if it's a root it's a category if (parent.parent() != QModelIndex()) { return 0; } return m_categoryHash.value(m_currentCategory); } QVariant CategorizedProxyModel::data(const QModelIndex &index, int role) const { if (index.row() < 0) { return QVariant(); } int offset = 0; - foreach (QString cat, m_categories) { + foreach (const QString &cat, m_categories) { if (cat == m_currentCategory) { break; } offset += m_categoryHash.value(cat); } return QSortFilterProxyModel::data(CategorizedProxyModel::index(index.row()+offset, index.column()), role); } void CategorizedProxyModel::fillCategories() { QAbstractItemModel *model = QSortFilterProxyModel::sourceModel(); if (!model) { return; } setRoleNames(model->roleNames()); QHash names = model->roleNames(); QHash::const_iterator i; for (i = names.constBegin(); i != names.constEnd(); ++i) { if (i.value() == m_categoryRoleString) { m_categoryRoleInt = i.key(); } } setSortRole(m_categoryRoleInt); sort(0); QHash categoryHash; QStringList categories; for (int i = 0; i <= model->rowCount(); i++) { QString category = model->data(model->index(i, 0), m_categoryRoleInt).toString(); if (category.isEmpty()) { continue; } if (categoryHash.contains(category)) { ++categoryHash[category]; } else { categoryHash[category] = 1; categories.append(category); qSort(categories.begin(), categories.end()); } } if (categoryHash != m_categoryHash) { beginResetModel(); m_categoryHash = categoryHash; m_categories = categories; endResetModel(); emit categoriesChanged(); } } void CategorizedProxyModel::slotInsertRows(const QModelIndex& sourceIndex, int begin, int end) { QAbstractItemModel *model = QSortFilterProxyModel::sourceModel(); if (!model) { return; } setRoleNames(model->roleNames()); sort(0); bool changed = false; for (int i = begin; i <= end; i++) { QString category = model->data(model->index(i, 0), m_categoryRoleInt).toString(); if (category.isEmpty()) { continue; } if (m_categoryHash.contains(category)) { ++m_categoryHash[category]; } else { m_categoryHash[category] = 1; m_categories.append(category); qSort(m_categories.begin(), m_categories.end()); changed = true; } } if (changed) { emit categoriesChanged(); } } void CategorizedProxyModel::slotRemoveRows(const QModelIndex& sourceIndex, int begin, int end) { QAbstractItemModel *model = QSortFilterProxyModel::sourceModel(); if (!model) { return; } bool changed = false; for (int i = begin; i <= end; i++) { QString category = model->data(model->index(i, 0), m_categoryRoleInt).toString(); if (m_categoryHash.contains(category)) { if (m_categoryHash.value(category) <= 1) { m_categoryHash.remove(category); m_categories.removeAll(category); changed = true; } else { --m_categoryHash[category]; } } } if (changed) { emit categoriesChanged(); } } #include "categorizedproxymodel.moc" diff --git a/dataengines/apps/appsource.cpp b/dataengines/apps/appsource.cpp index 9fe1e4c3..34b8c29b 100644 --- a/dataengines/apps/appsource.cpp +++ b/dataengines/apps/appsource.cpp @@ -1,108 +1,108 @@ /* * Copyright 2009 Chani Armitage * Copyright 2011 Marco Martin * * This program 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 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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 "appsource.h" #include #include #include AppSource::AppSource(const QString &name, QObject *parent) : Plasma::DataContainer(parent) { setObjectName(name); QStringList names = name.split(':'); if (names.length() == 2) { m_categories = names.last().split('|'); } KSharedConfigPtr ptr = KSharedConfig::openConfig("active-blacklistrc"); KConfigGroup config = KConfigGroup(ptr, "blacklist"); m_blackList = config.readEntry("apps", QStringList()); populate(); connect(KSycoca::self(), SIGNAL(databaseChanged(QStringList)), this, SLOT(sycocaChanged(QStringList))); } AppSource::~AppSource() { } void AppSource::sycocaChanged(const QStringList &changes) { if (changes.contains("apps") || changes.contains("xdgdata-apps")) { populate(); } } void AppSource::populate() { QString query = "exist Exec"; if (!m_categories.isEmpty()) { query += " and ("; bool first = true; foreach (const QString &category, m_categories) { if (!first) { query += " or "; } first = false; query += QString(" (exist Categories and '%1' ~subin Categories)").arg(category); } query += ')'; } //openSUSE: exclude YaST modules from the list query += " and (not (exist Categories and 'X-SuSE-YaST' in Categories))"; // Filter out blacklisted apps as to not show too much crap - foreach (const QString appName, m_blackList) { + foreach (const QString &appName, m_blackList) { query += QString(" and (DesktopEntryName != '%1' )").arg(appName); } //kWarning()<query("Application", query); removeAllData(); Plasma::DataEngine::Data data; foreach (const KService::Ptr &service, services) { if (service->noDisplay()) { continue; } QString description; if (!service->genericName().isEmpty() && service->genericName() != service->name()) { description = service->genericName(); } else if (!service->comment().isEmpty()) { description = service->comment(); } data["iconName"] = service->icon(); data["name"] = service->name(); data["genericName"] = service->genericName(); data["description"] = description; data["storageId"] = service->storageId(); data["entryPath"] = service->entryPath(); setData(service->storageId(), data); } checkForUpdate(); } #include "appsource.moc" diff --git a/dataengines/metadata/resourcecontainer.cpp b/dataengines/metadata/resourcecontainer.cpp index dfe739dc..00656167 100644 --- a/dataengines/metadata/resourcecontainer.cpp +++ b/dataengines/metadata/resourcecontainer.cpp @@ -1,263 +1,263 @@ /* Copyright 2011 Marco Martin Copyright 2011 Sebastian Kügler This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. */ #include "resourcecontainer.h" #include "resourcewatcher.h" #include #include #include #include #include #include ResourceContainer::ResourceContainer(QObject *parent) : Plasma::DataContainer(parent) { m_watcher = new Nepomuk::ResourceWatcher(this); m_watcher->addProperty(QUrl("http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating")); connect(m_watcher, SIGNAL(propertyAdded(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)), this, SLOT(propertyChanged(Nepomuk::Resource, Nepomuk::Types::Property, QVariant))); } ResourceContainer::~ResourceContainer() { } void ResourceContainer::propertyChanged(Nepomuk::Resource res, Nepomuk::Types::Property prop, QVariant val) { if (res != m_resource) { return; } setData(prop.name(), val); checkForUpdate(); } void ResourceContainer::setResource(Nepomuk::Resource resource) { if (m_resource == resource) { return; } m_resource = resource; //update the resource watcher { m_watcher->stop(); QList resources; resources << resource; m_watcher->setResources(resources); m_watcher->start(); } QString desc = resource.genericDescription(); if (desc.isEmpty()) { desc = resource.className(); } QString label = resource.genericLabel(); if (label.isEmpty()) { label = "Empty label."; } setData("label", label); setData("description", desc); // Types QStringList _types; foreach (const QUrl &u, resource.types()) { _types << u.toString(); } setData("types", _types); Nepomuk::Types::Class resClass(resource.resourceType()); //FIXME: a more elegant way is needed setData("genericClassName", resource.className()); - foreach (Nepomuk::Types::Class parentClass, resClass.parentClasses()) { + foreach (const Nepomuk::Types::Class &parentClass, resClass.parentClasses()) { if (parentClass.label() == "Document" || parentClass.label() == "Audio" || parentClass.label() == "Video" || parentClass.label() == "Image" || parentClass.label() == "Contact") { setData("genericClassName", parentClass.label()); break; //two cases where the class is 2 levels behind the level of generalization we want } else if (parentClass.label() == "RasterImage") { setData("genericClassName", "Image"); } else if (parentClass.label() == "TextDocument") { setData("genericClassName", "Document"); } } QString _icon = resource.genericIcon(); if (_icon.isEmpty() && resource.isFile()) { KUrl url = resource.toFile().url(); if (!url.isEmpty()) { _icon = KMimeType::iconNameForUrl(url); } } if (_icon.isEmpty()) { // use resource types to find a suitable icon. //TODO _icon = icon(QStringList(resource.className())); //kDebug() << "symbol" << _icon; } if (_icon.split(',').count() > 1) { kDebug() << "More than one icon!" << _icon; _icon = _icon.split(',').last(); } setData("icon", _icon); setData("hasSymbol", _icon); setData("isFile", resource.isFile()); setData("exists", resource.exists()); setData("rating", resource.rating()); setData("symbols", resource.symbols()); setData("className", resource.className()); setData("resourceUri", resource.resourceUri()); setData("resourceType", resource.resourceType()); setData("query", objectName()); if (resource.isFile() && resource.toFile().url().isLocalFile()) { setData("url", resource.toFile().url().prettyUrl()); } // Topics QStringList _topics, _topicNames; foreach (const Nepomuk::Resource &u, resource.topics()) { _topics << u.resourceUri().toString(); _topicNames << u.genericLabel(); } setData("topics", _topics); setData("topicNames", _topicNames); // Tags QStringList _tags, _tagNames; foreach (const Nepomuk::Tag &tag, resource.tags()) { _tags << tag.resourceUri().toString(); _tagNames << tag.genericLabel(); } setData("tags", _tags); setData("tagNames", _tagNames); // Related QStringList _relateds; foreach (const Nepomuk::Resource &res, resource.isRelateds()) { _relateds << res.resourceUri().toString(); } setData("relateds", _relateds); // Dynamic properties QStringList _properties; QHash props = resource.properties(); foreach(const QUrl &propertyUrl, props.keys()) { QStringList _l = propertyUrl.toString().split('#'); if (_l.count() > 1) { QString key = _l[1]; _properties << key; //QString from = dynamic_cast(); if (resource.property(propertyUrl).variant().canConvert(QVariant::List)) { QVariantList tl = resource.property(propertyUrl).variant().toList(); - foreach (QVariant vu, tl) { + foreach (const QVariant &vu, tl) { //kDebug() << vu.toString().startsWith("nepomuk:") << vu.toString().startsWith("akonadi:") << vu.toString(); if (vu.canConvert(QVariant::Url) && (vu.toString().startsWith("nepomuk:") || vu.toString().startsWith("akonadi:"))) { kDebug() << "HHH This is a list.!!!" << key << vu.toString(); } } } //kDebug() << " ... " << key << propertyUrl << resource.property(propertyUrl).variant(); if (key != "plainTextMessageContent" && !data().contains(key)) { setData(key, resource.property(propertyUrl).variant()); } // More properties } else { kWarning() << "Could not parse ontology URL, missing '#':" << propertyUrl.toString(); } } setData("properties", _properties); checkForUpdate(); } QString ResourceContainer::icon(const QStringList &types) { if (!m_icons.size()) { // Add fallback icons here from generic to specific // The list of types is also sorted in this way, so // we're returning the most specific icon, even with // the hardcoded mapping. // Files //m_icons["FileDataObject"] = QString("audio-x-generic"); // Audio m_icons["Audio"] = QString("audio-x-generic"); m_icons["MusicPiece"] = QString("audio-x-generic"); // Images m_icons["Image"] = QString("image-x-generic"); m_icons["RasterImage"] = QString("image-x-generic"); m_icons["Email"] = QString("internet-mail"); m_icons["Document"] = QString("kword"); m_icons["PersonContact"] = QString("x-office-contact"); // Filesystem m_icons["Website"] = QString("text-html"); // ... add some more // Filesystem m_icons["Bookmark"] = QString("bookmarks"); m_icons["BookmarksFolder"] = QString("bookmarks-organize"); m_icons["FileDataObject"] = QString("unknown"); m_icons["TextDocument"] = QString("text-enriched"); } // keep searching until the most specific icon is found QString _icon = "nepomuk"; foreach(const QString &t, types) { QString shortType = t.split('#').last(); if (shortType.isEmpty()) { shortType = t; } if (m_icons.keys().contains(shortType)) { _icon = m_icons[shortType]; //kDebug() << "found icon for type" << shortType << _icon; } } return _icon; } #include "resourcecontainer.moc"