File indexing completed on 2024-04-14 04:52:51

0001 /* This file is part of FSView.
0002     SPDX-FileCopyrightText: 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only
0005 */
0006 
0007 /*
0008  * Classes for breadth-first search in local filesystem
0009  */
0010 
0011 #ifndef KONQ_PLUGIN_SCAN_H
0012 #define KONQ_PLUGIN_SCAN_H
0013 
0014 #include <QFile>
0015 #include <QVector>
0016 #include <kio/global.h>
0017 
0018 class ScanDir;
0019 class ScanFile;
0020 
0021 class ScanItem
0022 {
0023 public:
0024     ScanItem(const QString &p, ScanDir *d)
0025     {
0026         absPath = p;
0027         dir = d;
0028     }
0029 
0030     QString absPath;
0031     ScanDir *dir;
0032 };
0033 
0034 typedef QList<ScanItem *> ScanItemList;
0035 
0036 /**
0037  * Listener for events from directory scanning.
0038  *
0039  * You can register a listener for the ScanManager to get
0040  * all scan events and a listener for every ScanDir for
0041  * directory specific scan events.
0042  *
0043  * sizeChanged is called when a scan of a subdirectory
0044  * finished.
0045  */
0046 class ScanListener
0047 {
0048 public:
0049     virtual ~ScanListener() {}
0050     virtual void scanStarted(ScanDir *) {}
0051     virtual void sizeChanged(ScanDir *) {}
0052     virtual void scanFinished(ScanDir *) {}
0053     // destroyed events are not delivered to listeners of ScanManager
0054     virtual void destroyed(ScanDir *) {}
0055     virtual void destroyed(ScanFile *) {}
0056 };
0057 
0058 /**
0059  * ScanManager
0060  *
0061  * Start/Stop/Restart Scans. Example:
0062  *
0063  *   ScanManager m("/opt");
0064  *   m.startScan();
0065  *   while(m.scan());
0066  */
0067 class ScanManager
0068 {
0069 public:
0070     ScanManager();
0071     ScanManager(const QString &path);
0072     ~ScanManager();
0073 
0074     /** Set the top path for scanning
0075      * The ScanDir object created gets attribute data.
0076      */
0077     ScanDir *setTop(const QString &path, int data = 0);
0078     ScanDir *top()
0079     {
0080         return _topDir;
0081     }
0082 
0083     bool scanRunning();
0084     int scanLength() const
0085     {
0086         return _list.count();
0087     }
0088 
0089     /**
0090      * Starts the scan. Stop previous scan if running.
0091      * For the actual scan to happen, you have to call
0092      * scan() periodically.
0093      *
0094      * If from !=0, restart scan at given position; from must
0095      * be from the previous scan of this manager.
0096      */
0097     void startScan(ScanDir *from = nullptr);
0098 
0099     /** Stop a current running scan.
0100      * Make all directories to finish their scan.
0101      */
0102     void stopScan();
0103 
0104     /**
0105      * Scan first directory from todo list.
0106      * Directories added to the todo list are attributed with data.
0107      * Returns the number of new subdirectories created for scanning.
0108      */
0109     int scan(int data);
0110 
0111     /* set listener to get a callbacks from this ScanDir */
0112     void setListener(ScanListener *);
0113     ScanListener *listener()
0114     {
0115         return _listener;
0116     }
0117 
0118 private:
0119     ScanItemList _list;
0120     ScanDir *_topDir;
0121     ScanListener *_listener;
0122 };
0123 
0124 class ScanFile
0125 {
0126 public:
0127     ScanFile();
0128     ScanFile(const QString &n, KIO::fileoffset_t s);
0129     ~ScanFile();
0130 
0131     const QString &name()
0132     {
0133         return _name;
0134     }
0135     KIO::fileoffset_t size()
0136     {
0137         return _size;
0138     }
0139 
0140     /* set listener to get callbacks from this ScanDir */
0141     void setListener(ScanListener *l)
0142     {
0143         _listener = l;
0144     }
0145     ScanListener *listener()
0146     {
0147         return _listener;
0148     }
0149 
0150 private:
0151     QString _name;
0152     KIO::fileoffset_t _size;
0153     ScanListener *_listener;
0154 };
0155 
0156 typedef QVector<ScanFile> ScanFileVector;
0157 typedef QVector<ScanDir> ScanDirVector;
0158 
0159 /**
0160  * A directory to scan.
0161  * You can attribute a directory to scan with a
0162  * integer data attribute.
0163  */
0164 class ScanDir
0165 {
0166 public:
0167     ScanDir();
0168     ScanDir(const QString &n, ScanManager *m,
0169             ScanDir *p = nullptr, int data = 0);
0170     ~ScanDir();
0171 
0172     /* Get items of this directory
0173      * and append subdirectories to todo list.
0174      *
0175      * Directories added to the todo list are attributed with data.
0176      * Returns the number of new subdirectories created for scanning.
0177      */
0178     int scan(ScanItem *si, ScanItemList &list, int data);
0179 
0180     /* clear scan objects below */
0181     void clear();
0182 
0183     /*
0184      * Setup for child rescan
0185      */
0186     void setupChildRescan();
0187 
0188     /* Absolute path. Warning: Slow, loops to top parent. */
0189     QString path();
0190 
0191     /* get integer data attribute */
0192     int data()
0193     {
0194         return _data;
0195     }
0196     void setData(int d)
0197     {
0198         _data = d;
0199     }
0200 
0201     ScanFileVector &files()
0202     {
0203         return _files;
0204     }
0205     ScanDirVector &dirs()
0206     {
0207         return _dirs;
0208     }
0209     const QString &name()
0210     {
0211         return _name;
0212     }
0213     KIO::fileoffset_t size()
0214     {
0215         update();
0216         return _size;
0217     }
0218     unsigned int fileCount()
0219     {
0220         update();
0221         return _fileCount;
0222     }
0223     unsigned int dirCount()
0224     {
0225         update();
0226         return _dirCount;
0227     }
0228     ScanDir *parent()
0229     {
0230         return _parent;
0231     }
0232     bool scanStarted()
0233     {
0234         return (_dirsFinished >= 0);
0235     }
0236     bool scanFinished()
0237     {
0238         return (_dirsFinished == _dirs.count());
0239     }
0240     bool scanRunning()
0241     {
0242         return scanStarted() && !scanFinished();
0243     }
0244 
0245     /* set listener to get a callbacks from this ScanDir */
0246     void setListener(ScanListener *);
0247     ScanListener *listener()
0248     {
0249         return _listener;
0250     }
0251     ScanManager *manager()
0252     {
0253         return _manager;
0254     }
0255 
0256     /* force current scan to be finished */
0257     void finish();
0258 
0259 private:
0260     void update();
0261     bool isForbiddenDir(QString &);
0262 
0263     /* this propagates file count and size to upper dirs */
0264     void subScanFinished();
0265     void callScanStarted();
0266     void callSizeChanged();
0267     void callScanFinished();
0268 
0269     ScanFileVector _files;
0270     ScanDirVector _dirs;
0271 
0272     QString _name;
0273     bool _dirty; /* needs a call to update() */
0274     KIO::fileoffset_t _size, _fileSize;
0275     unsigned int _fileCount, _dirCount;
0276     int _dirsFinished, _data;
0277     ScanDir *_parent;
0278     ScanListener *_listener;
0279     ScanManager *_manager;
0280 };
0281 
0282 #endif // KONQ_PLUGIN_SCAN_H