summaryrefslogtreecommitdiffstats
path: root/konq-plugins/fsview/scan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'konq-plugins/fsview/scan.cpp')
-rw-r--r--konq-plugins/fsview/scan.cpp362
1 files changed, 362 insertions, 0 deletions
diff --git a/konq-plugins/fsview/scan.cpp b/konq-plugins/fsview/scan.cpp
new file mode 100644
index 0000000..ed691e3
--- /dev/null
+++ b/konq-plugins/fsview/scan.cpp
@@ -0,0 +1,362 @@
+/* This file is part of FSView.
+ Copyright (C) 2002, 2003 Josef Weidendorfer <[email protected]>
+
+ KCachegrind 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qdir.h>
+#include <qstringlist.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+
+#include "scan.h"
+#include "inode.h"
+
+
+// ScanManager
+
+ScanManager::ScanManager()
+{
+ _topDir = 0;
+ _listener = 0;
+}
+
+ScanManager::ScanManager(const QString& path)
+{
+ _topDir = 0;
+ _listener = 0;
+ setTop(path);
+}
+
+ScanManager::~ScanManager()
+{
+ stopScan();
+ if (_topDir) delete _topDir;
+}
+
+void ScanManager::setListener(ScanListener* l)
+{
+ _listener = l;
+}
+
+ScanDir* ScanManager::setTop(const QString& path, int data)
+{
+ stopScan();
+ if (_topDir) {
+ delete _topDir;
+ _topDir = 0;
+ }
+ if (!path.isEmpty()) {
+ _topDir = new ScanDir(path, this, 0, data);
+ }
+ return _topDir;
+}
+
+bool ScanManager::scanRunning()
+{
+ if (!_topDir) return false;
+
+ return _topDir->scanRunning();
+}
+
+void ScanManager::startScan(ScanDir* from)
+{
+ if (!_topDir) return;
+ if (!from) from = _topDir;
+
+ if (scanRunning()) stopScan();
+
+ from->clear();
+ if (from->parent())
+ from->parent()->setupChildRescan();
+
+ _list.append(new ScanItem(from->path(),from));
+}
+
+void ScanManager::stopScan()
+{
+ if (!_topDir) return;
+
+ if (0) kdDebug(90100) << "ScanManager::stopScan, scanLength "
+ << _list.count() << endl;
+
+ ScanItem* si;
+ while( (si=_list.take(0))!=0 ) {
+ si->dir->finish();
+ delete si;
+ }
+}
+
+int ScanManager::scan(int data)
+{
+ ScanItem* si = _list.take(0);
+ if (!si) return false;
+
+ int newCount = si->dir->scan(si, _list, data);
+ delete si;
+
+ return newCount;
+}
+
+
+// ScanFile
+
+ScanFile::ScanFile()
+{
+ _size = 0;
+ _listener = 0;
+}
+
+ScanFile::ScanFile(const QString& n, KIO::fileoffset_t s)
+{
+ _name = n;
+ _size = s;
+ _listener = 0;
+}
+
+ScanFile::~ScanFile()
+{
+ if (_listener) _listener->destroyed(this);
+}
+
+// ScanDir
+
+ScanDir::ScanDir()
+{
+ _dirty = true;
+ _dirsFinished = -1; /* scan not started */
+
+ _parent = 0;
+ _manager = 0;
+ _listener = 0;
+ _data = 0;
+}
+
+ScanDir::ScanDir(const QString& n, ScanManager* m,
+ ScanDir* p, int data)
+ : _name(n)
+{
+ _dirty = true;
+ _dirsFinished = -1; /* scan not started */
+
+ _parent = p;
+ _manager = m;
+ _listener = 0;
+ _data = data;
+}
+
+ScanDir::~ScanDir()
+{
+ if (_listener) _listener->destroyed(this);
+}
+
+void ScanDir::setListener(ScanListener* l)
+{
+ _listener = l;
+}
+
+QString ScanDir::path()
+{
+ if (_parent) {
+ QString p = _parent->path();
+ if (!p.endsWith("/")) p += "/";
+ return p + _name;
+ }
+
+ return _name;
+}
+
+void ScanDir::clear()
+{
+ _dirty = true;
+ _dirsFinished = -1; /* scan not started */
+
+ _files.clear();
+ _dirs.clear();
+}
+
+void ScanDir::update()
+{
+ if (!_dirty) return;
+ _dirty = false;
+
+ _fileCount = 0;
+ _dirCount = 0;
+ _size = 0;
+
+ if (_dirsFinished == -1) return;
+
+ if (_files.count()>0) {
+ _fileCount += _files.count();
+ _size = _fileSize;
+ }
+ if (_dirs.count()>0) {
+ _dirCount += _dirs.count();
+ ScanDirVector::iterator it;
+ for( it = _dirs.begin(); it != _dirs.end(); ++it ) {
+ (*it).update();
+ _fileCount += (*it)._fileCount;
+ _dirCount += (*it)._dirCount;
+ _size += (*it)._size;
+ }
+ }
+}
+
+int ScanDir::scan(ScanItem* si, ScanItemList& list, int data)
+{
+ clear();
+ _dirsFinished = 0;
+ _fileSize = 0;
+ _dirty = true;
+
+ KURL u;
+ u.setPath(si->absPath);
+ if (!kapp->authorizeURLAction("list", KURL(), u)) {
+ if (_parent)
+ _parent->subScanFinished();
+
+ return 0;
+ }
+
+ QDir d(si->absPath);
+ QStringList fileList = d.entryList( QDir::Files |
+ QDir::Hidden | QDir::NoSymLinks );
+
+ if (fileList.count()>0) {
+ KDE_struct_stat buff;
+
+ _files.reserve(fileList.count());
+
+ QStringList::Iterator it;
+ for (it = fileList.begin(); it != fileList.end(); ++it ) {
+ KDE_lstat( QFile::encodeName(si->absPath + "/" + (*it)), &buff );
+ _files.append( ScanFile(*it, buff.st_size) );
+ _fileSize += buff.st_size;
+ }
+ }
+
+ QStringList dirList = d.entryList( QDir::Dirs |
+ QDir::Hidden | QDir::NoSymLinks );
+
+ if (dirList.count()>2) {
+ _dirs.reserve(dirList.count()-2);
+
+ QStringList::Iterator it;
+ for (it = dirList.begin(); it != dirList.end(); ++it ) {
+ if ( ((*it) == "..") || ((*it) == ".") ) continue;
+ _dirs.append( ScanDir(*it, _manager, this, data) );
+ list.append( new ScanItem( si->absPath + "/" + (*it),
+ &(_dirs.last()) ));
+ }
+ _dirCount += _dirs.count();
+ }
+
+ callScanStarted();
+ callSizeChanged();
+
+ if (_dirs.count() == 0) {
+ callScanFinished();
+
+ if (_parent)
+ _parent->subScanFinished();
+ }
+
+ return _dirs.count();
+}
+
+void ScanDir::subScanFinished()
+{
+ _dirsFinished++;
+ callSizeChanged();
+
+ if (0) kdDebug(90100) << "ScanDir::subScanFinished [" << path()
+ << "]: " << _dirsFinished << "/" << _dirs.count() << endl;
+
+
+
+ if (_dirsFinished < (int)_dirs.count()) return;
+
+ /* all subdirs read */
+ callScanFinished();
+
+ if (_parent)
+ _parent->subScanFinished();
+}
+
+void ScanDir::finish()
+{
+ if (scanRunning()) {
+ _dirsFinished = (int)_dirs.count();
+ callScanFinished();
+ }
+
+ if (_parent)
+ _parent->finish();
+}
+
+void ScanDir::setupChildRescan()
+{
+ if (_dirs.count() == 0) return;
+
+ _dirsFinished = 0;
+ ScanDirVector::iterator it;
+ for( it = _dirs.begin(); it != _dirs.end(); ++it )
+ if ((*it).scanFinished()) _dirsFinished++;
+
+ if (_parent &&
+ (_dirsFinished < (int)_dirs.count()) )
+ _parent->setupChildRescan();
+
+ callScanStarted();
+}
+
+void ScanDir::callScanStarted()
+{
+ if (0) kdDebug(90100) << "ScanDir:Started [" << path()
+ << "]: size " << size() << ", files " << fileCount() << endl;
+
+ ScanListener* mListener = _manager ? _manager->listener() : 0;
+
+ if (_listener) _listener->scanStarted(this);
+ if (mListener) mListener->scanStarted(this);
+}
+
+void ScanDir::callSizeChanged()
+{
+ if (0) kdDebug(90100) << ". [" << path()
+ << "]: size " << size() << ", files " << fileCount() << endl;
+
+ _dirty = true;
+
+ if (_parent) _parent->callSizeChanged();
+
+ ScanListener* mListener = _manager ? _manager->listener() : 0;
+
+ if (_listener) _listener->sizeChanged(this);
+ if (mListener) mListener->sizeChanged(this);
+}
+
+void ScanDir::callScanFinished()
+{
+ if (0) kdDebug(90100) << "ScanDir:Finished [" << path()
+ << "]: size " << size() << ", files " << fileCount() << endl;
+
+ ScanListener* mListener = _manager ? _manager->listener() : 0;
+
+ if (_listener) _listener->scanFinished(this);
+ if (mListener) mListener->scanFinished(this);
+}
+