diff --git a/src/lib/filemonitor.cpp b/src/lib/filemonitor.cpp index 1b07540c..f1fc9151 100644 --- a/src/lib/filemonitor.cpp +++ b/src/lib/filemonitor.cpp @@ -1,87 +1,87 @@ /* * * Copyright (C) 2013 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "filemonitor.h" #include #include #include #include using namespace Baloo; class FileMonitor::Private { public: QSet m_files; }; FileMonitor::FileMonitor(QObject* parent) : QObject(parent) , d(new Private) { QDBusConnection con = QDBusConnection::sessionBus(); con.connect(QString(), QStringLiteral("/files"), QStringLiteral("org.kde"), QStringLiteral("changed"), this, SLOT(slotFileMetaDataChanged(QStringList))); } FileMonitor::~FileMonitor() { delete d; } void FileMonitor::addFile(const QString& fileUrl) { QString f = fileUrl; if (f.endsWith(QLatin1Char('/'))) f = f.mid(0, f.length()-1); d->m_files.insert(f); } void FileMonitor::addFile(const QUrl& url) { const QString localFile = url.toLocalFile(); - if (localFile.size()) + if (!localFile.isEmpty()) addFile(localFile); } void FileMonitor::setFiles(const QStringList& fileList) { d->m_files = fileList.toSet(); } QStringList FileMonitor::files() const { return QStringList(d->m_files.toList()); } void FileMonitor::clear() { d->m_files.clear(); } void FileMonitor::slotFileMetaDataChanged(const QStringList& fileUrls) { Q_FOREACH (const QString& url, fileUrls) { if (d->m_files.contains(url)) { Q_EMIT fileMetaDataChanged(url); } } } diff --git a/src/lib/query.cpp b/src/lib/query.cpp index ee0ff190..981e8782 100644 --- a/src/lib/query.cpp +++ b/src/lib/query.cpp @@ -1,352 +1,352 @@ /* * This file is part of the KDE Baloo Project * Copyright (C) 2013 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #include "query.h" #include "term.h" #include "advancedqueryparser.h" #include "searchstore.h" #include #include #include #include #include #include #include using namespace Baloo; const int defaultLimit = -1; class Baloo::Query::Private { public: Private() { m_limit = defaultLimit; m_offset = 0; m_yearFilter = 0; m_monthFilter = 0; m_dayFilter = 0; m_sortingOption = SortAuto; } Term m_term; QStringList m_types; QString m_searchString; int m_limit; uint m_offset; int m_yearFilter; int m_monthFilter; int m_dayFilter; SortingOption m_sortingOption; QString m_includeFolder; }; Query::Query() : d(new Private) { } Query::Query(const Query& rhs) : d(new Private(*rhs.d)) { } Query::~Query() { delete d; } void Query::addType(const QString& type) { d->m_types << type.split(QLatin1Char('/'), QString::SkipEmptyParts); } void Query::addTypes(const QStringList& typeList) { Q_FOREACH (const QString& type, typeList) { addType(type); } } void Query::setType(const QString& type) { d->m_types.clear(); addType(type); } void Query::setTypes(const QStringList& types) { d->m_types = types; } QStringList Query::types() const { return d->m_types; } QString Query::searchString() const { return d->m_searchString; } void Query::setSearchString(const QString& str) { d->m_searchString = str; AdvancedQueryParser parser; d->m_term = parser.parse(str); } uint Query::limit() const { return d->m_limit; } void Query::setLimit(uint limit) { d->m_limit = limit; } uint Query::offset() const { return d->m_offset; } void Query::setOffset(uint offset) { d->m_offset = offset; } void Query::setDateFilter(int year, int month, int day) { d->m_yearFilter = year; d->m_monthFilter = month; d->m_dayFilter = day; } int Query::yearFilter() const { return d->m_yearFilter; } int Query::monthFilter() const { return d->m_monthFilter; } int Query::dayFilter() const { return d->m_dayFilter; } void Query::setSortingOption(Query::SortingOption option) { d->m_sortingOption = option; } Query::SortingOption Query::sortingOption() const { return d->m_sortingOption; } QString Query::includeFolder() const { return d->m_includeFolder; } void Query::setIncludeFolder(const QString& folder) { d->m_includeFolder = folder; } ResultIterator Query::exec() { Term term(d->m_term); if (!d->m_types.isEmpty()) { for (const QString& type : qAsConst(d->m_types)) { term = term && Term(QStringLiteral("type"), type); } } if (!d->m_includeFolder.isEmpty()) { term = term && Term(QStringLiteral("includefolder"), d->m_includeFolder); } if (d->m_yearFilter || d->m_monthFilter || d->m_dayFilter) { QByteArray ba = QByteArray::number(d->m_yearFilter); if (d->m_monthFilter < 10) ba += '0'; ba += QByteArray::number(d->m_monthFilter); if (d->m_dayFilter < 10) ba += '0'; ba += QByteArray::number(d->m_dayFilter); term = term && Term(QStringLiteral("modified"), ba, Term::Equal); } SearchStore searchStore; QStringList result = searchStore.exec(term, d->m_offset, d->m_limit, d->m_sortingOption == SortAuto); return ResultIterator(result); } QByteArray Query::toJSON() { QVariantMap map; if (!d->m_types.isEmpty()) map[QStringLiteral("type")] = d->m_types; if (d->m_limit != defaultLimit) map[QStringLiteral("limit")] = d->m_limit; if (d->m_offset) map[QStringLiteral("offset")] = d->m_offset; if (!d->m_searchString.isEmpty()) map[QStringLiteral("searchString")] = d->m_searchString; if (d->m_term.isValid()) map[QStringLiteral("term")] = QVariant(d->m_term.toVariantMap()); if (d->m_yearFilter >= 0) map[QStringLiteral("yearFilter")] = d->m_yearFilter; if (d->m_monthFilter >= 0) map[QStringLiteral("monthFilter")] = d->m_monthFilter; if (d->m_dayFilter >= 0) map[QStringLiteral("dayFilter")] = d->m_dayFilter; if (d->m_sortingOption != SortAuto) map[QStringLiteral("sortingOption")] = static_cast(d->m_sortingOption); if (!d->m_includeFolder.isEmpty()) map[QStringLiteral("includeFolder")] = d->m_includeFolder; QJsonObject jo = QJsonObject::fromVariantMap(map); QJsonDocument jdoc; jdoc.setObject(jo); return jdoc.toJson(); } // static Query Query::fromJSON(const QByteArray& arr) { QJsonDocument jdoc = QJsonDocument::fromJson(arr); const QVariantMap map = jdoc.object().toVariantMap(); Query query; query.d->m_types = map[QStringLiteral("type")].toStringList(); if (map.contains(QStringLiteral("limit"))) query.d->m_limit = map[QStringLiteral("limit")].toUInt(); else query.d->m_limit = defaultLimit; query.d->m_offset = map[QStringLiteral("offset")].toUInt(); query.d->m_searchString = map[QStringLiteral("searchString")].toString(); query.d->m_term = Term::fromVariantMap(map[QStringLiteral("term")].toMap()); if (map.contains(QStringLiteral("yearFilter"))) query.d->m_yearFilter = map[QStringLiteral("yearFilter")].toInt(); if (map.contains(QStringLiteral("monthFilter"))) query.d->m_monthFilter = map[QStringLiteral("monthFilter")].toInt(); if (map.contains(QStringLiteral("dayFilter"))) query.d->m_dayFilter = map[QStringLiteral("dayFilter")].toInt(); if (map.contains(QStringLiteral("sortingOption"))) { int option = map.value(QStringLiteral("sortingOption")).toInt(); query.d->m_sortingOption = static_cast(option); } if (map.contains(QStringLiteral("includeFolder"))) { query.d->m_includeFolder = map.value(QStringLiteral("includeFolder")).toString(); } return query; } QUrl Query::toSearchUrl(const QString& title) { QUrl url; url.setScheme(QStringLiteral("baloosearch")); QUrlQuery urlQuery; urlQuery.addQueryItem(QStringLiteral("json"), QString::fromUtf8(toJSON())); - if (title.size()) + if (!title.isEmpty()) urlQuery.addQueryItem(QStringLiteral("title"), title); url.setQuery(urlQuery); return url; } Query Query::fromSearchUrl(const QUrl& url) { if (url.scheme() != QLatin1String("baloosearch")) return Query(); QUrlQuery urlQuery(url); QString jsonString = urlQuery.queryItemValue(QStringLiteral("json"), QUrl::FullyDecoded); return Query::fromJSON(jsonString.toUtf8()); } QString Query::titleFromQueryUrl(const QUrl& url) { QUrlQuery urlQuery(url); return urlQuery.queryItemValue(QStringLiteral("title"), QUrl::FullyDecoded); } bool Query::operator==(const Query& rhs) const { if (rhs.d->m_limit != d->m_limit || rhs.d->m_offset != d->m_offset || rhs.d->m_dayFilter != d->m_dayFilter || rhs.d->m_monthFilter != d->m_monthFilter || rhs.d->m_yearFilter != d->m_yearFilter || rhs.d->m_includeFolder != d->m_includeFolder || rhs.d->m_searchString != d->m_searchString || rhs.d->m_sortingOption != d->m_sortingOption) { return false; } if (rhs.d->m_types.size() != d->m_types.size()) return false; Q_FOREACH (const QString& type, rhs.d->m_types) { if (!d->m_types.contains(type)) return false; } return d->m_term == rhs.d->m_term; } bool Query::operator!=(const Query& rhs) const { return !(*this == rhs); } Query& Query::operator=(const Query& rhs) { *d = *rhs.d; return *this; } diff --git a/src/lib/term.cpp b/src/lib/term.cpp index 0a828c3a..7b76bf84 100644 --- a/src/lib/term.cpp +++ b/src/lib/term.cpp @@ -1,470 +1,470 @@ /* * This file is part of the KDE Baloo Project * Copyright (C) 2013 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #include "term.h" #include #include using namespace Baloo; class Baloo::Term::Private { public: Operation m_op; Comparator m_comp; QString m_property; QVariant m_value; bool m_isNegated; QList m_subTerms; QVariantHash m_userData; Private() { m_op = None; m_comp = Auto; m_isNegated = false; } }; Term::Term() : d(new Private) { } Term::Term(const Term& t) : d(new Private(*t.d)) { } Term::Term(const QString& property) : d(new Private) { d->m_property = property; } Term::Term(const QString& property, const QVariant& value, Term::Comparator c) : d(new Private) { d->m_property = property; d->m_value = value; if (c == Auto) { if (value.type() == QVariant::String) d->m_comp = Contains; else if (value.type() == QVariant::DateTime) d->m_comp = Contains; else d->m_comp = Equal; } else { d->m_comp = c; } } /* Term::Term(const QString& property, const QVariant& start, const QVariant& end) : d(new Private) { d->m_property = property; d->m_op = Range; // FIXME: How to save range queries? } */ Term::Term(Term::Operation op) : d(new Private) { d->m_op = op; } Term::Term(Term::Operation op, const Term& t) : d(new Private) { d->m_op = op; d->m_subTerms << t; } Term::Term(Term::Operation op, const QList& t) : d(new Private) { d->m_op = op; d->m_subTerms = t; } Term::Term(const Term& lhs, Term::Operation op, const Term& rhs) : d(new Private) { d->m_op = op; if (lhs.operation() == op) { d->m_subTerms << lhs.subTerms(); } else { d->m_subTerms << lhs; } if (rhs.operation() == op) { d->m_subTerms << rhs.subTerms(); } else { d->m_subTerms << rhs; } } Term::~Term() { delete d; } bool Term::isValid() const { // Terms with an operator but no subterms are still valid if (d->m_op != Term::None) { return true; } if (d->m_comp == Term::Auto) { return false; } return true; } void Term::setNegation(bool isNegated) { d->m_isNegated = isNegated; } bool Term::isNegated() const { return d->m_isNegated; } bool Term::negated() const { return d->m_isNegated; } void Term::addSubTerm(const Term& term) { d->m_subTerms << term; } void Term::setSubTerms(const QList& terms) { d->m_subTerms = terms; } Term Term::subTerm() const { - if (d->m_subTerms.size()) + if (!d->m_subTerms.isEmpty()) return d->m_subTerms.first(); return Term(); } QList Term::subTerms() const { return d->m_subTerms; } void Term::setOperation(Term::Operation op) { d->m_op = op; } Term::Operation Term::operation() const { return d->m_op; } bool Term::empty() const { return isEmpty(); } bool Term::isEmpty() const { return d->m_property.isEmpty() && d->m_value.isNull() && d->m_subTerms.isEmpty(); } QString Term::property() const { return d->m_property; } void Term::setProperty(const QString& property) { d->m_property = property; } void Term::setValue(const QVariant& value) { d->m_value = value; } QVariant Term::value() const { return d->m_value; } Term::Comparator Term::comparator() const { return d->m_comp; } void Term::setComparator(Term::Comparator c) { d->m_comp = c; } void Term::setUserData(const QString& name, const QVariant& value) { d->m_userData.insert(name, value); } QVariant Term::userData(const QString& name) const { return d->m_userData.value(name); } QVariantMap Term::toVariantMap() const { QVariantMap map; if (d->m_op != None) { QVariantList variantList; Q_FOREACH (const Term& term, d->m_subTerms) { variantList << QVariant(term.toVariantMap()); } if (d->m_op == And) map[QStringLiteral("$and")] = variantList; else map[QStringLiteral("$or")] = variantList; return map; } QString op; switch (d->m_comp) { case Equal: map[d->m_property] = d->m_value; return map; case Contains: op = QStringLiteral("$ct"); break; case Greater: op = QStringLiteral("$gt"); break; case GreaterEqual: op = QStringLiteral("$gte"); break; case Less: op = QStringLiteral("$lt"); break; case LessEqual: op = QStringLiteral("$lte"); break; case Auto: Q_ASSERT(0); } QVariantMap m; m[op] = d->m_value; map[d->m_property] = QVariant(m); return map; } namespace { // QJson does not recognize QDate/QDateTime parameters. We try to guess // and see if they can be converted into date/datetime. QVariant tryConvert(const QVariant& var) { if (var.canConvert(QVariant::DateTime)) { QDateTime dt = var.toDateTime(); if (!dt.isValid()) return var; if (!var.toString().contains(QLatin1String("T"))) { return QVariant(var.toDate()); } return dt; } return var; } } Term Term::fromVariantMap(const QVariantMap& map) { if (map.size() != 1) return Term(); Term term; QString andOrString; if (map.contains(QStringLiteral("$and"))) { andOrString = QStringLiteral("$and"); term.setOperation(And); } else if (map.contains(QStringLiteral("$or"))) { andOrString = QStringLiteral("$or"); term.setOperation(Or); } - if (andOrString.size()) { + if (!andOrString.isEmpty()) { QList subTerms; QVariantList list = map[andOrString].toList(); Q_FOREACH (const QVariant& var, list) subTerms << Term::fromVariantMap(var.toMap()); term.setSubTerms(subTerms); return term; } QString prop = map.cbegin().key(); term.setProperty(prop); QVariant value = map.value(prop); if (value.type() == QVariant::Map) { QVariantMap mapVal = value.toMap(); if (mapVal.size() != 1) return term; QString op = mapVal.cbegin().key(); Term::Comparator com; if (op == QLatin1String("$ct")) com = Contains; else if (op == QLatin1String("$gt")) com = Greater; else if (op == QLatin1String("$gte")) com = GreaterEqual; else if (op == QLatin1String("$lt")) com = Less; else if (op == QLatin1String("$lte")) com = LessEqual; else return term; term.setComparator(com); term.setValue(tryConvert(mapVal.value(op))); return term; } term.setComparator(Equal); term.setValue(tryConvert(value)); return term; } bool Term::operator==(const Term& rhs) const { if (d->m_op != rhs.d->m_op || d->m_comp != rhs.d->m_comp || d->m_isNegated != rhs.d->m_isNegated || d->m_property != rhs.d->m_property || d->m_value != rhs.d->m_value) { return false; } if (d->m_subTerms.size() != rhs.d->m_subTerms.size()) return false; if (d->m_subTerms.isEmpty()) return true; Q_FOREACH (const Term& t, d->m_subTerms) { if (!rhs.d->m_subTerms.contains(t)) return false; } return true; } Term& Term::operator=(const Term& rhs) { *d = *rhs.d; return *this; } namespace { QString comparatorToString(Baloo::Term::Comparator c) { switch (c) { case Baloo::Term::Auto: return QStringLiteral("Auto"); case Baloo::Term::Equal: return QStringLiteral("="); case Baloo::Term::Contains: return QStringLiteral(":"); case Baloo::Term::Less: return QStringLiteral("<"); case Baloo::Term::LessEqual: return QStringLiteral("<="); case Baloo::Term::Greater: return QStringLiteral(">"); case Baloo::Term::GreaterEqual: return QStringLiteral(">="); } return QString(); } QString operationToString(Baloo::Term::Operation op) { switch (op) { case Baloo::Term::None: return QStringLiteral("NONE"); case Baloo::Term::And: return QStringLiteral("AND"); case Baloo::Term::Or: return QStringLiteral("OR"); } return QString(); } } QDebug operator <<(QDebug d, const Baloo::Term& t) { if (t.subTerms().isEmpty()) { d << QStringLiteral("(%1 %2 %3 (%4))").arg(t.property(), comparatorToString(t.comparator()), t.value().toString(), QString::fromLatin1(t.value().typeName())).toUtf8().constData(); } else { d << "[" << operationToString(t.operation()).toUtf8().constData(); const auto subTerms = t.subTerms(); for (const Term& term : subTerms) { d << term; } d << "]"; } return d; }