diff --git a/src/engine/idutils.h b/src/engine/idutils.h index e1d513ff..40007101 100644 --- a/src/engine/idutils.h +++ b/src/engine/idutils.h @@ -1,117 +1,127 @@ /* * This file is part of the KDE Baloo Project * Copyright (C) 2015 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 . * */ #ifndef BALOO_ID_UTILS_ #define BALOO_ID_UTILS_ #include #include #ifdef Q_OS_WIN # include #endif namespace Baloo { inline quint64 devIdAndInodeToId(quint32 devId, quint32 inode) { quint32 arr[2]; arr[0] = devId; arr[1] = inode; return *(reinterpret_cast(arr)); } /** * Convert the QT_STATBUF into a 64 bit unique identifier for the file. * This identifier is combination of the device id and inode number. */ inline quint64 statBufToId(const QT_STATBUF& stBuf) { - // We're loosing 32 bits of info, so this could potentially break + // We're losing 32 bits of info, so this could potentially break // on file systems with really large inode and device ids return devIdAndInodeToId(static_cast(stBuf.st_dev), static_cast(stBuf.st_ino)); } -inline quint64 filePathToId(const QByteArray& filePath) +inline int filePathToStat(const QByteArray& filePath, QT_STATBUF& statBuf) { - QT_STATBUF statBuf; #ifndef Q_OS_WIN - if (QT_LSTAT(filePath.constData(), &statBuf) != 0) { - return 0; - } + return QT_LSTAT(filePath.constData(), &statBuf); #else - if (QT_STAT(filePath.constData(), &statBuf) != 0) { - return 0; - } - if (QFileInfo(filePath).isSymLink()) { - if (QT_STAT(QFileInfo(filePath).symLinkTarget().toUtf8().constData(), &statBuf) != 0) { - return 0; - } + const int ret = QT_STAT(filePath.constData(), &statBuf) + if (ret == 0 && QFileInfo(filePath).isSymLink()) { + return QT_STAT(QFileInfo(filePath).symLinkTarget().toUtf8().constData(), &statBuf) + } else { + return ret; } #endif - return statBufToId(statBuf); +} + +inline QT_STATBUF filePathToStat(const QByteArray& filePath) +{ + QT_STATBUF statBuf; + const int ret = filePathToStat(filePath, statBuf); + //TODO: if (ret != 0) qDebug() ? + Q_UNUSED(ret) + return statBuf; +} + +inline quint64 filePathToId(const QByteArray& filePath) +{ + QT_STATBUF statBuf; + const int ret = filePathToStat(filePath, statBuf); + return ret ? 0 : statBufToId(statBuf); } inline quint32 idToInode(quint64 id) { quint32* arr = reinterpret_cast(&id); return arr[1]; } inline quint32 idToDeviceId(quint64 id) { quint32* arr = reinterpret_cast(&id); return arr[0]; } template inline void sortedIdInsert(T& vec, const V& id) { /** * search with normal < */ const auto i(std::lower_bound(vec.begin(), vec.end(), id)); /** * end reached or element found smaller? * => insert new element! */ if (i == vec.end() || (id != *i)) vec.insert(i, id); } template inline void sortedIdRemove(T& vec, const V& id) { const int idx = vec.indexOf(id); if (idx >= 0) { vec.remove(idx); } } } #endif diff --git a/src/file/basicindexingjob.cpp b/src/file/basicindexingjob.cpp index 54e0cd1e..3ea73208 100644 --- a/src/file/basicindexingjob.cpp +++ b/src/file/basicindexingjob.cpp @@ -1,220 +1,220 @@ /* * This file is part of the KDE Baloo Project * Copyright (C) 2013-2015 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 "basicindexingjob.h" #include "termgenerator.h" #include "idutils.h" #include "baloodebug.h" #include #include #include #include #include using namespace Baloo; BasicIndexingJob::BasicIndexingJob(const QString& filePath, const QString& mimetype, IndexingLevel level) : m_filePath(filePath) , m_mimetype(mimetype) , m_indexingLevel(level) { } BasicIndexingJob::~BasicIndexingJob() { } bool BasicIndexingJob::index() { const QByteArray url = QFile::encodeName(m_filePath); QT_STATBUF statBuf; - if (QT_LSTAT(url.data(), &statBuf) != 0) { + if (filePathToStat(url, statBuf) != 0) { return false; } Document doc; doc.setId(statBufToId(statBuf)); doc.setUrl(url); QString fileName = url.mid(url.lastIndexOf('/') + 1); TermGenerator tg(&doc); tg.indexFileNameText(fileName, 1000); tg.indexFileNameText(fileName, QByteArray("F")); tg.indexText(m_mimetype, QByteArray("M")); // Time doc.setMTime(statBuf.st_mtime); doc.setCTime(statBuf.st_ctime); // Types QVector tList = typesForMimeType(m_mimetype); for (KFileMetaData::Type::Type type : tList) { QByteArray num = QByteArray::number(static_cast(type)); doc.addBoolTerm(QByteArray("T") + num); } if (S_ISDIR(statBuf.st_mode)) { static const QByteArray type = QByteArray("T") + QByteArray::number(static_cast(KFileMetaData::Type::Folder)); doc.addBoolTerm(type); // For folders we do not need to go through file indexing, so we do not set contentIndexing } else if (m_indexingLevel == MarkForContentIndexing) { doc.setContentIndexing(true); } indexXAttr(m_filePath, doc); m_doc = doc; return true; } bool BasicIndexingJob::indexXAttr(const QString& url, Document& doc) { KFileMetaData::UserMetaData userMetaData(url); TermGenerator tg(&doc); QStringList tags = userMetaData.tags(); for (const QString& tag : tags) { tg.indexXattrText(tag, QByteArray("TA")); doc.addXattrBoolTerm(QByteArray("TAG-") + tag.toUtf8()); } int rating = userMetaData.rating(); if (rating) { doc.addXattrBoolTerm(QByteArray("R") + QByteArray::number(rating)); } QString comment = userMetaData.userComment(); if (!comment.isEmpty()) { tg.indexXattrText(comment, QByteArray("C")); } return (!tags.isEmpty() || rating || !comment.isEmpty()); } QVector BasicIndexingJob::typesForMimeType(const QString& mimeType) { using namespace KFileMetaData; QVector types; // Basic types if (mimeType.startsWith(QLatin1String("audio/"))) types << Type::Audio; if (mimeType.startsWith(QLatin1String("video/"))) types << Type::Video; if (mimeType.startsWith(QLatin1String("image/"))) types << Type::Image; if (mimeType.startsWith(QLatin1String("text/"))) types << Type::Text; if (mimeType.contains(QLatin1String("document"))) types << Type::Document; if (mimeType.contains(QLatin1String("powerpoint"))) { types << Type::Presentation; types << Type::Document; } if (mimeType.contains(QLatin1String("excel"))) { types << Type::Spreadsheet; types << Type::Document; } static QMultiHash typeMapper = { {"text/plain", Type::Document}, // MS Office {"application/msword", Type::Document}, {"application/x-scribus", Type::Document}, {"application/vnd.ms-powerpoint", Type::Document}, {"application/vnd.ms-powerpoint", Type::Presentation}, {"application/vnd.ms-excel", Type::Document}, {"application/vnd.ms-excel", Type::Spreadsheet}, // Office 2007 {"application/vnd.openxmlformats-officedocument.wordprocessingml.document", Type::Document}, {"application/vnd.openxmlformats-officedocument.presentationml.presentation", Type::Document}, {"application/vnd.openxmlformats-officedocument.presentationml.presentation", Type::Presentation}, {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Type::Document}, {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Type::Spreadsheet}, // Open Document Formats - http://en.wikipedia.org/wiki/OpenDocument_technical_specification {"application/vnd.oasis.opendocument.text", Type::Document}, {"application/vnd.oasis.opendocument.presentation", Type::Document}, {"application/vnd.oasis.opendocument.presentation", Type::Presentation}, {"application/vnd.oasis.opendocument.spreadsheet", Type::Document}, {"application/vnd.oasis.opendocument.spreadsheet", Type::Spreadsheet}, {"application/pdf", Type::Document}, {"application/postscript", Type::Document}, {"application/x-dvi", Type::Document}, {"application/rtf", Type::Document}, // EBooks {"application/epub+zip", Type::Document}, {"application/x-mobipocket-ebook", Type::Document}, // Archives - http://en.wikipedia.org/wiki/List_of_archive_formats {"application/x-tar", Type::Archive}, {"application/x-bzip2", Type::Archive}, {"application/x-gzip", Type::Archive}, {"application/x-lzip", Type::Archive}, {"application/x-lzma", Type::Archive}, {"application/x-lzop", Type::Archive}, {"application/x-compress", Type::Archive}, {"application/x-7z-compressed", Type::Archive}, {"application/x-ace-compressed", Type::Archive}, {"application/x-astrotite-afa", Type::Archive}, {"application/x-alz-compressed", Type::Archive}, {"application/vnd.android.package-archive", Type::Archive}, {"application/x-arj", Type::Archive}, {"application/vnd.ms-cab-compressed", Type::Archive}, {"application/x-cfs-compressed", Type::Archive}, {"application/x-dar", Type::Archive}, {"application/x-lzh", Type::Archive}, {"application/x-lzx", Type::Archive}, {"application/x-rar-compressed", Type::Archive}, {"application/x-stuffit", Type::Archive}, {"application/x-stuffitx", Type::Archive}, {"application/x-gtar", Type::Archive}, {"application/zip", Type::Archive}, {"image/svg+xml", Type::Image}, // WPS office {"application/wps-office.doc", Type::Document}, {"application/wps-office.xls", Type::Document}, {"application/wps-office.xls", Type::Spreadsheet}, {"application/wps-office.pot", Type::Document}, {"application/wps-office.pot", Type::Presentation}, {"application/wps-office.wps", Type::Document}, {"application/wps-office.docx", Type::Document}, {"application/wps-office.xlsx", Type::Document}, {"application/wps-office.xlsx", Type::Spreadsheet}, {"application/wps-office.pptx", Type::Document}, {"application/wps-office.pptx", Type::Presentation}, // Other {"text/markdown", Type::Document}, {"image/vnd.djvu+multipage", Type::Document}, {"application/x-lyx", Type::Document} }; types << typeMapper.values(mimeType).toVector(); return types; } diff --git a/src/file/fileinfo.cpp b/src/file/fileinfo.cpp index 6bab4a79..ebbc2c8c 100644 --- a/src/file/fileinfo.cpp +++ b/src/file/fileinfo.cpp @@ -1,40 +1,41 @@ /* * This file is part of the KDE Baloo Project * Copyright (C) 2015 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 "fileinfo.h" +#include "idutils.h" using namespace Baloo; FileInfo::FileInfo(const QByteArray& filePath) : m_filePath(filePath) , m_exists(true) { Q_ASSERT(!filePath.endsWith('/')); - if (QT_LSTAT(filePath.data(), &m_statBuf) != 0) { + if (filePathToStat(filePath, m_statBuf) != 0) { m_exists = false; - memset(&m_statBuf, 0, sizeof(QT_STATBUF)); + memset(&m_statBuf, 0, sizeof(m_statBuf)); } } bool FileInfo::isHidden() const { int pos = m_filePath.lastIndexOf('/'); return m_filePath[pos + 1] == '.'; } diff --git a/src/kioslaves/search/kio_search.cpp b/src/kioslaves/search/kio_search.cpp index 7c22d13a..54246f10 100644 --- a/src/kioslaves/search/kio_search.cpp +++ b/src/kioslaves/search/kio_search.cpp @@ -1,147 +1,149 @@ /* Copyright (C) 2008-2010 by Sebastian Trueg Copyright (C) 2012-2014 by Vishesh Handa 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, 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 "kio_search.h" #include "query.h" #include "resultiterator.h" +#include "idutils.h" #include #include #include #include #include #include #include using namespace Baloo; namespace { KIO::UDSEntry statSearchFolder(const QUrl& url) { KIO::UDSEntry uds; uds.insert(KIO::UDSEntry::UDS_ACCESS, 0700); uds.insert(KIO::UDSEntry::UDS_USER, KUser().loginName()); uds.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); uds.insert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); uds.insert(KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES, QStringLiteral("baloo")); uds.insert(KIO::UDSEntry::UDS_DISPLAY_TYPE, i18n("Search Folder")); uds.insert(KIO::UDSEntry::UDS_URL, url.url()); QUrlQuery query(url); QString title = query.queryItemValue(QStringLiteral("title"), QUrl::FullyDecoded); if (!title.isEmpty()) { uds.insert(KIO::UDSEntry::UDS_NAME, title); uds.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, title); } return uds; } } SearchProtocol::SearchProtocol(const QByteArray& poolSocket, const QByteArray& appSocket) : KIO::SlaveBase("baloosearch", poolSocket, appSocket) { } SearchProtocol::~SearchProtocol() { } void SearchProtocol::listDir(const QUrl& url) { Query q; QUrlQuery urlQuery(url); if (urlQuery.hasQueryItem(QStringLiteral("json"))) { QString jsonString = urlQuery.queryItemValue(QStringLiteral("json"), QUrl::FullyDecoded); q = Query::fromJSON(jsonString.toUtf8()); } else if (urlQuery.hasQueryItem(QStringLiteral("query"))) { QString queryString = urlQuery.queryItemValue(QStringLiteral("query"), QUrl::FullyDecoded); q.setSearchString(queryString); } q.setSortingOption(Query::SortNone); ResultIterator it = q.exec(); while (it.next()) { KIO::UDSEntry uds; const QString filePath(it.filePath()); // Code from kdelibs/kioslaves/file.cpp QT_STATBUF statBuf; - if (QT_LSTAT(QFile::encodeName(filePath).data(), &statBuf) == 0) { + const QByteArray ba = QFile::encodeName(filePath); + if (filePathToStat(ba, statBuf) == 0) { uds.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, statBuf.st_mtime); uds.insert(KIO::UDSEntry::UDS_ACCESS_TIME, statBuf.st_atime); uds.insert(KIO::UDSEntry::UDS_SIZE, statBuf.st_size); uds.insert(KIO::UDSEntry::UDS_USER, statBuf.st_uid); uds.insert(KIO::UDSEntry::UDS_GROUP, statBuf.st_gid); mode_t type = statBuf.st_mode & S_IFMT; mode_t access = statBuf.st_mode & 07777; uds.insert(KIO::UDSEntry::UDS_FILE_TYPE, type); uds.insert(KIO::UDSEntry::UDS_ACCESS, access); } else { continue; } QUrl url = QUrl::fromLocalFile(filePath); uds.insert(KIO::UDSEntry::UDS_NAME, url.fileName()); uds.insert(KIO::UDSEntry::UDS_URL, url.url()); uds.insert(KIO::UDSEntry::UDS_LOCAL_PATH, filePath); listEntry(uds); } finished(); } void SearchProtocol::mimetype(const QUrl&) { mimeType(QStringLiteral("inode/directory")); finished(); } void SearchProtocol::stat(const QUrl& url) { statEntry(statSearchFolder(url)); finished(); } extern "C" { Q_DECL_EXPORT int kdemain(int argc, char** argv) { QCoreApplication app(argc, argv); app.setApplicationName(QStringLiteral("kio_baloosearch")); Baloo::SearchProtocol slave(argv[2], argv[3]); slave.dispatchLoop(); return 0; } } diff --git a/src/kioslaves/timeline/kio_timeline.cpp b/src/kioslaves/timeline/kio_timeline.cpp index aa3f0633..acc820b0 100644 --- a/src/kioslaves/timeline/kio_timeline.cpp +++ b/src/kioslaves/timeline/kio_timeline.cpp @@ -1,266 +1,268 @@ /* Copyright 2009-2010 Sebastian Trueg Copyright 2013 Vishesh Handa 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) 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 14 of version 3 of the license. 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, see . */ #include "kio_timeline.h" #include "timelinetools.h" #include "query.h" #include "resultiterator.h" +#include "idutils.h" #include #include #include #include #include #include using namespace Baloo; namespace { KIO::UDSEntry createFolderUDSEntry(const QString& name, const QString& displayName, const QDate& date) { KIO::UDSEntry uds; QDateTime dt(date, QTime(0, 0, 0)); uds.insert(KIO::UDSEntry::UDS_NAME, name); uds.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, displayName); uds.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); uds.insert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); uds.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, dt.toTime_t()); uds.insert(KIO::UDSEntry::UDS_CREATION_TIME, dt.toTime_t()); uds.insert(KIO::UDSEntry::UDS_ACCESS, 0700); uds.insert(KIO::UDSEntry::UDS_USER, KUser().loginName()); return uds; } KIO::UDSEntry createMonthUDSEntry(int month, int year) { QString dateString = QDate(year, month, 1).toString( i18nc("Month and year used in a tree above the actual days. " "Have a look at http://doc.qt.io/qt-5/qdate.html#toString " "to see which variables you can use and ask kde-i18n-doc@kde.org if you have " "problems understanding how to translate this", "MMMM yyyy")); return createFolderUDSEntry(QDate(year, month, 1).toString(QStringLiteral("yyyy-MM")), dateString, QDate(year, month, 1)); } KIO::UDSEntry createDayUDSEntry(const QDate& date) { KIO::UDSEntry uds = createFolderUDSEntry(date.toString(QStringLiteral("yyyy-MM-dd")), KFormat().formatRelativeDate(date, QLocale::LongFormat), date); return uds; } KIO::UDSEntry createFileUDSEntry(const QString& filePath) { KIO::UDSEntry uds; // Code from kdelibs/kioslaves/file.cpp QT_STATBUF statBuf; - if( QT_LSTAT(QFile::encodeName(filePath).data(), &statBuf) == 0) { + const QByteArray url = QFile::encodeName(filePath); + if (filePathToStat(url, statBuf) == 0) { uds.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, statBuf.st_mtime); uds.insert(KIO::UDSEntry::UDS_ACCESS_TIME, statBuf.st_atime); uds.insert(KIO::UDSEntry::UDS_SIZE, statBuf.st_size); uds.insert(KIO::UDSEntry::UDS_USER, statBuf.st_uid); uds.insert(KIO::UDSEntry::UDS_GROUP, statBuf.st_gid); mode_t type = statBuf.st_mode & S_IFMT; mode_t access = statBuf.st_mode & 07777; uds.insert(KIO::UDSEntry::UDS_FILE_TYPE, type); uds.insert(KIO::UDSEntry::UDS_ACCESS, access); QUrl fileUrl = QUrl::fromLocalFile(filePath); uds.insert(KIO::UDSEntry::UDS_URL, fileUrl.url()); uds.insert(KIO::UDSEntry::UDS_NAME, fileUrl.fileName()); } return uds; } } TimelineProtocol::TimelineProtocol(const QByteArray& poolSocket, const QByteArray& appSocket) : KIO::SlaveBase("timeline", poolSocket, appSocket) { } TimelineProtocol::~TimelineProtocol() { } void TimelineProtocol::listDir(const QUrl& url) { switch (parseTimelineUrl(url, &m_date, &m_filename)) { case RootFolder: listEntry(createFolderUDSEntry(QStringLiteral("today"), i18n("Today"), QDate::currentDate())); listEntry(createFolderUDSEntry(QStringLiteral("calendar"), i18n("Calendar"), QDate::currentDate())); finished(); break; case CalendarFolder: listThisYearsMonths(); // TODO: add entry for previous years finished(); break; case MonthFolder: listDays(m_date.month(), m_date.year()); finished(); break; case DayFolder: { Query query; query.setDateFilter(m_date.year(), m_date.month(), m_date.day()); query.setSortingOption(Query::SortNone); ResultIterator it = query.exec(); while (it.next()) { KIO::UDSEntry uds = createFileUDSEntry(it.filePath()); if (uds.count()) listEntry(uds); } finished(); break; } case NoFolder: error(KIO::ERR_DOES_NOT_EXIST, url.toString()); break; } } void TimelineProtocol::mimetype(const QUrl& url) { switch (parseTimelineUrl(url, &m_date, &m_filename)) { case RootFolder: case CalendarFolder: case MonthFolder: case DayFolder: mimetype(QUrl(QLatin1String("inode/directory"))); break; case NoFolder: error(KIO::ERR_DOES_NOT_EXIST, url.toString()); break; } } void TimelineProtocol::stat(const QUrl& url) { switch (parseTimelineUrl(url, &m_date, &m_filename)) { case RootFolder: { KIO::UDSEntry uds; uds.insert(KIO::UDSEntry::UDS_NAME, QStringLiteral("/")); uds.insert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("nepomuk")); uds.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); uds.insert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); statEntry(uds); finished(); break; } case CalendarFolder: statEntry(createFolderUDSEntry(QStringLiteral("calendar"), i18n("Calendar"), QDate::currentDate())); finished(); break; case MonthFolder: statEntry(createMonthUDSEntry(m_date.month(), m_date.year())); finished(); break; case DayFolder: if (m_filename.isEmpty()) { statEntry(createDayUDSEntry(m_date)); finished(); } break; case NoFolder: error(KIO::ERR_DOES_NOT_EXIST, url.toString()); break; } } void TimelineProtocol::listDays(int month, int year) { const int days = QDate(year, month, 1).daysInMonth(); for (int day = 1; day <= days; ++day) { QDate date(year, month, day); if (date <= QDate::currentDate() && filesInDate(date)) { listEntry(createDayUDSEntry(date)); } } } bool TimelineProtocol::filesInDate(const QDate& date) { Query query; query.setLimit(1); query.setDateFilter(date.year(), date.month(), date.day()); query.setSortingOption(Query::SortNone); ResultIterator it = query.exec(); return it.next(); } void TimelineProtocol::listThisYearsMonths() { Query query; query.setLimit(1); query.setSortingOption(Query::SortNone); int year = QDate::currentDate().year(); int currentMonth = QDate::currentDate().month(); for (int month = 1; month <= currentMonth; ++month) { query.setDateFilter(year, month); ResultIterator it = query.exec(); if (it.next()) { listEntry(createMonthUDSEntry(month, year)); } } } extern "C" { Q_DECL_EXPORT int kdemain(int argc, char** argv) { QCoreApplication app(argc, argv); app.setApplicationName(QStringLiteral("kio_timeline")); Baloo::TimelineProtocol slave(argv[2], argv[3]); slave.dispatchLoop(); return 0; } }