File indexing completed on 2024-12-15 04:14:22

0001 /*
0002  * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) version 3, or any
0008  * later version accepted by the membership of KDE e.V. (or its
0009  * successor approved by the membership of KDE e.V.), which shall
0010  * act as a proxy defined in Section 6 of version 3 of the license.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0019  *
0020  */
0021 
0022 #include "FilesystemContentLister.h"
0023 
0024 #include <KFileMetaData/UserMetaData>
0025 
0026 #include <QCoreApplication>
0027 #include <QDateTime>
0028 #include <QDirIterator>
0029 #include <QMimeDatabase>
0030 #include <QTimer>
0031 #include <QVariantHash>
0032 #include <QThreadPool>
0033 #include <QRunnable>
0034 
0035 #include "ContentQuery.h"
0036 
0037 class FileSystemSearcher : public QObject, public QRunnable
0038 {
0039     Q_OBJECT
0040 public:
0041     FileSystemSearcher(ContentQuery* query) : QObject() { m_query = query; }
0042 
0043     void run() override
0044     {
0045         QMimeDatabase mimeDb;
0046 
0047         auto locations = m_query->locations();
0048         if(locations.isEmpty())
0049             locations.append(QDir::homePath());
0050 
0051         for(const auto& location : locations)
0052         {
0053             QDirIterator it(location, QDirIterator::Subdirectories);
0054             while (it.hasNext())
0055             {
0056                 auto filePath = it.next();
0057 
0058                 if(it.fileInfo().isDir())
0059                     continue;
0060 
0061                 if(!m_query->mimeTypes().isEmpty()) {
0062                     QString mimeType = mimeDb.mimeTypeForFile(filePath).name();
0063                     if(!m_query->mimeTypes().contains(mimeType))
0064                         continue;
0065                 }
0066 
0067                 auto metadata = ContentListerBase::metaDataForFile(filePath);
0068 
0069                 emit fileFound(filePath, metadata);
0070             }
0071         }
0072 
0073         emit finished(this);
0074     }
0075 
0076 Q_SIGNALS:
0077     void fileFound(const QString& path, const QVariantMap& metaData);
0078     void finished(FileSystemSearcher* searcher);
0079 
0080 private:
0081     ContentQuery* m_query;
0082 };
0083 
0084 class FilesystemContentLister::Private
0085 {
0086 public:
0087     Private() { }
0088 
0089     QList<FileSystemSearcher*> runnables;
0090 };
0091 
0092 FilesystemContentLister::FilesystemContentLister(QObject* parent)
0093     : ContentListerBase(parent)
0094     , d(new Private)
0095 {
0096 
0097 }
0098 
0099 FilesystemContentLister::~FilesystemContentLister()
0100 {
0101     QThreadPool::globalInstance()->waitForDone();
0102     delete d;
0103 }
0104 
0105 void FilesystemContentLister::startSearch(const QList<ContentQuery*>& queries)
0106 {
0107     for(const auto& query : queries)
0108     {
0109         auto runnable = new FileSystemSearcher{query};
0110         connect(runnable, &FileSystemSearcher::fileFound, this, &FilesystemContentLister::fileFound);
0111         connect(runnable, &FileSystemSearcher::finished, this, &FilesystemContentLister::queryFinished);
0112 
0113         d->runnables.append(runnable);
0114     }
0115 
0116     if(!d->runnables.isEmpty())
0117         QThreadPool::globalInstance()->start(d->runnables.first());
0118 }
0119 
0120 void FilesystemContentLister::queryFinished(QRunnable* runnable)
0121 {
0122     d->runnables.removeAll(static_cast<FileSystemSearcher*>(runnable));
0123 
0124     if(!d->runnables.isEmpty())
0125     {
0126         QThreadPool::globalInstance()->start(d->runnables.first());
0127     }
0128     else
0129     {
0130         emit searchCompleted();
0131     }
0132 }
0133 
0134 // This needs to be included since we define a QObject subclass here in the C++ file.
0135 #include "FilesystemContentLister.moc"