You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
filelight/src/part/scan.cpp

205 lines
5.4 KiB

//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
//Copyright: See COPYING file that comes with this distribution
#include "debug.h"
#include "fileTree.h"
#include <kcursor.h>
#include "localLister.h"
#include <qapplication.h>
#include "remoteLister.h"
#include "scan.h"
namespace Filelight
{
bool ScanManager::s_abort = false;
uint ScanManager::s_files = 0;
ScanManager::ScanManager( QObject *parent )
: QObject( parent )
, m_thread( 0 )
, m_cache( new Chain<Directory> )
{
Filelight::LocalLister::readMounts();
}
ScanManager::~ScanManager()
{
if( m_thread ) {
debug() << "Attempting to abort scan operation...\n";
s_abort = true;
m_thread->wait();
}
delete m_cache;
//RemoteListers are QObjects and get automatically deleted
}
bool
ScanManager::running() const
{
//FIXME not complete
return m_thread && m_thread->running();
}
bool
ScanManager::start( const KURL &url )
{
//url is guarenteed clean and safe
debug() << "Scan requested for: " << url.prettyURL() << endl;
if( running() ) {
//shouldn't happen, but lets prevent mega-disasters just in case eh?
kdWarning() << "Attempted to run 2 scans concurrently!\n";
//TODO give user an error
return false;
}
s_files = 0;
s_abort = false;
if( url.protocol() == "file" )
{
const QString path = url.path( 1 );
Chain<Directory> *trees = new Chain<Directory>;
/* CHECK CACHE
* user wants: /usr/local/
* cached: /usr/
*
* user wants: /usr/
* cached: /usr/local/, /usr/include/
*/
for( Iterator<Directory> it = m_cache->iterator(); it != m_cache->end(); ++it )
{
QString cachePath = (*it)->name();
if( path.startsWith( cachePath ) ) //then whole tree already scanned
{
//find a pointer to the requested branch
debug() << "Cache-(a)hit: " << cachePath << endl;
QStringList split = QStringList::split( '/', path.mid( cachePath.length() ) );
Directory *d = *it;
Iterator<File> jt;
while( !split.isEmpty() && d != NULL ) //if NULL we have got lost so abort!!
{
jt = d->iterator();
const Link<File> *end = d->end();
QString s = split.first(); s += '/';
for( d = 0; jt != end; ++jt )
if( s == (*jt)->name() )
{
d = (Directory*)*jt;
break;
}
split.pop_front();
}
if( d )
{
delete trees;
//we found a completed tree, thus no need to scan
debug() << "Found cache-handle, generating map..\n";
//1001 indicates that this should not be cached
QCustomEvent *e = new QCustomEvent( 1001 );
e->setData( d );
QApplication::postEvent( this, e );
return true;
}
else
{
//something went wrong, we couldn't find the directory we were expecting
error() << "Didn't find " << path << " in the cache!\n";
delete it.remove(); //safest to get rid of it
break; //do a full scan
}
}
else if( cachePath.startsWith( path ) ) //then part of the requested tree is already scanned
{
debug() << "Cache-(b)hit: " << cachePath << endl;
it.transferTo( *trees );
}
}
m_url.setPath( path ); //FIXME stop switching between paths and KURLs all the time
QApplication::setOverrideCursor( KCursor::workingCursor() );
//starts listing by itself
m_thread = new Filelight::LocalLister( path, trees, this );
return true;
}
m_url = url;
QApplication::setOverrideCursor( KCursor::workingCursor() );
//will start listing straight away
QObject *o = new Filelight::RemoteLister( url, (QWidget*)parent() );
insertChild( o );
o->setName( "remote_lister" );
return true;
}
bool
ScanManager::abort()
{
s_abort = true;
delete child( "remote_lister" );
return m_thread && m_thread->running();
}
void
ScanManager::emptyCache()
{
s_abort = true;
if( m_thread && m_thread->running() )
m_thread->wait();
emit aboutToEmptyCache();
m_cache->empty();
}
void
ScanManager::customEvent( QCustomEvent *e )
{
Directory *tree = (Directory*)e->data();
if( m_thread ) {
m_thread->terminate();
m_thread->wait();
delete m_thread; //note the lister deletes itself
m_thread = 0;
}
emit completed( tree );
if( tree ) {
//we don't cache foreign stuff
//we don't recache stuff (thus only type 1000 events)
if( e->type() == 1000 && m_url.protocol() == "file" )
//TODO sanity check the cache
m_cache->append( tree );
}
else //scan failed
m_cache->empty(); //FIXME this is safe but annoying
QApplication::restoreOverrideCursor();
}
}
#include "scan.moc"