File indexing completed on 2024-05-05 04:48:50

0001 /****************************************************************************************
0002  * Copyright (c) 2010-2013 Ralf Engels <ralf-engels@gmx.de>                             *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef ABSTRACT_DIRECTORY_WATCHER_H
0018 #define ABSTRACT_DIRECTORY_WATCHER_H
0019 
0020 #include "amarok_export.h"
0021 #include "GenericScanManager.h"
0022 
0023 #include <QObject>
0024 #include <QSet>
0025 #include <QMutex>
0026 #include <QWaitCondition>
0027 
0028 #include <ThreadWeaver/Job>
0029 
0030 #include <QUrl>
0031 
0032 class QTimer;
0033 class KDirWatch;
0034 
0035 /** The AbstractDirectoryWatcher is a helper object that watches a set of
0036     directories for a collection and starts an incremental scan as soon
0037     as something changes.
0038 
0039     You need to implement the collectionFolders method.
0040 
0041     Use the Watcher like this:
0042     ThreadWeaver::Queue::instance()->enqueue( ScanDirectoryWatcherJob( this ) );
0043 
0044     Note: When Amarok is started we wait a minute (so that the scanner does not slow down
0045     the application startup) and then we do a full incremental scan.
0046     After that we use KDirWatch to track directory changes.
0047     KDirWatch will not track changes to symbolic links!
0048 
0049     Note: The watcher needs to be a separate job because the KDirWatcher might need a long
0050     time adding recursive directories.
0051     This will prevent the directory adding from blocking the UI.
0052 */
0053 class AMAROK_EXPORT AbstractDirectoryWatcher : public QObject, public ThreadWeaver::Job
0054 {
0055     Q_OBJECT
0056 
0057     public:
0058         AbstractDirectoryWatcher();
0059 
0060         void run(ThreadWeaver::JobPointer self = QSharedPointer<ThreadWeaver::Job>(), ThreadWeaver::Thread *thread = nullptr) override;
0061         void requestAbort() override;
0062 
0063         /** Pauses the emitting of the scan signal */
0064         void setBlockScanning( bool block );
0065 
0066     Q_SIGNALS:
0067         /** Requests the scanner to do an incremental scan.
0068          *  The incremental scan will check for new files or sub-folders.
0069          *  @param directories The directories to scan or and empty string if every
0070          *  collection folder should be checked for changes.
0071          *  @param type The type of the scan.
0072          */
0073         void requestScan( QList<QUrl> directories, GenericScanManager::ScanType type );
0074         /** This signal is emitted when this job is being processed by a thread. */
0075         void started(ThreadWeaver::JobPointer);
0076         /** This signal is emitted when the job has been finished (no matter if it succeeded or not). */
0077         void done(ThreadWeaver::JobPointer);
0078         /** This job has failed.
0079          * This signal is emitted when success() returns false after the job is executed. */
0080         void failed(ThreadWeaver::JobPointer);
0081 
0082     protected Q_SLOTS:
0083         void delayTimeout();
0084         void delayedScan( const QString& path );
0085 
0086     protected:
0087         virtual QList<QString> collectionFolders() = 0;
0088 
0089         /** Adds the given directory to the list of directories for the next scan.  */
0090         void addDirToList( const QString &directory );
0091 
0092         void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override;
0093         void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override;
0094 
0095         QTimer* m_delayedScanTimer;
0096         KDirWatch *m_watcher;
0097 
0098         /** Mutex for the wait condition */
0099         QMutex m_mutex;
0100         QWaitCondition m_waitCondition;
0101 
0102         QMutex m_dirsMutex;
0103         QSet<QUrl> m_scanDirsRequested;
0104 
0105         bool m_aborted;
0106         bool m_blocked;
0107 };
0108 
0109 #endif