Back to index

scribus-ng  1.3.4.dfsg+svn20071115
filesearch.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 #include "filesearch.h"
00008 #include "filesearch.moc"
00009 #include <qtimer.h>
00010 #include <qregexp.h>
00011 
00012 
00013 enum FileSearchStatus
00014 {
00015        Status_NotStarted,
00016        Status_Running,
00017        Status_Cancelled,
00018        Status_Failed,
00019        Status_Finished,
00020 };
00021 
00022 
00023 FileSearch::FileSearch(QObject* parent, const QString & fileName,const QString & searchBase, int depthLimit, bool caseSensitive) :
00024        DeferredTask(parent),
00025        m_searchBase(searchBase.isNull() ? QDir::homeDirPath() : searchBase),
00026        m_fileName(fileName),
00027        m_depth(0),
00028        m_maxdepth(depthLimit)
00029 {
00030        m_caseSensitive = caseSensitive;
00031 #ifdef _WIN32
00032        // it has no meaning to set case sensitiveness on win
00033        m_caseSensitive = false;
00034 #endif
00035        DeferredTask::init();
00036        m_dir.setPath(m_searchBase);
00037        Q_ASSERT(m_dir.exists());
00038        // Give ourselves a useful name for object browsers, etc.
00039        setName(QString("FileSearch for \"%1\"").arg(m_searchBase).local8Bit());
00040 }
00041 
00042 FileSearch::~FileSearch()
00043 {
00044        DeferredTask::cleanup();
00045 }
00046 
00047 const QStringList & FileSearch::matchingFiles() const
00048 {
00049        return m_matchingFiles;
00050 }
00051 
00052 int FileSearch::foundCount() const
00053 {
00054        return m_matchingFiles.count();
00055 }
00056 
00057 const QString & FileSearch::fileName() const
00058 {
00059        return m_fileName;
00060 }
00061 
00062 const QDir & FileSearch::currentDir() const
00063 {
00064        return m_dir;
00065 }
00066 
00067 void FileSearch::start()
00068 {
00069        // Push the list of subdirs for the starting dir onto the stack
00070        pushStack();
00071        // and add the current directory's files to the list
00072        addCurrentDirFiles();
00073        DeferredTask::start();
00074 }
00075 
00076 void FileSearch::next()
00077 {
00078        // We start off in a directory that has just been examined.
00079        // A list of the names of directories in this directory is at the top of
00080        // m_tree, and m_iter points to the first directory name in that list. The
00081        // files in this directory have already been checked to see if they match,
00082        // and added to the list of matches if they do.
00083        // We need to select the directory to step into, and search its contents.
00084 
00085        // skip '.', '..'
00086        while ( *(m_iter.top()) == "." || *(m_iter.top()) == ".." )
00087               ++m_iter.top();
00088 
00089        if ( (m_iter.top() == m_tree.top().end()) || (m_depth == m_maxdepth) )
00090        {
00091               // We're at the end of the list of subdirectory names in this directory,
00092               // or we've hit the maximum depth we're allowed to search to.
00093               // Move up to the previous directory.
00094               m_iter.pop();
00095               m_tree.pop();
00096               m_dir.cdUp();
00097               m_depth--;
00098               // Check if we've run out of tree and should finish up
00099               if (m_depth < 0)
00100               {
00101                      // We've run out of tree, so we're all done. Kill the timer and
00102                      // tell our owner we've finished.
00103                      Q_ASSERT(m_iter.count() == 0);
00104                      Q_ASSERT(m_tree.count() == 0);
00105                      DeferredTask::done();
00106                      emit searchComplete(m_matchingFiles, m_fileName);
00107               }
00108               else
00109               {
00110                      // As an optimisation, call next() to do a short recursion back to the
00111                      // next subdir we actually need to search, so we don't have to wait for
00112                      // the timer to get around to firing for this trivial step. We're not
00113                      // putting anything on the stack so this should be pretty safe.
00114                      next();
00115               }
00116        }
00117        else
00118        {
00119               // There are still subdirectories to search. Select the next one and step
00120               // into it, incrementing the iterator for the current dir in the process.
00121               m_dir.cd(*(m_iter.top()));
00122               ++m_iter.top();
00123               m_depth++;
00124               pushStack();
00125               addCurrentDirFiles();
00126        }
00127 }
00128 
00129 void FileSearch::pushStack()
00130 {
00131        m_tree.push(m_dir.entryList(QDir::Dirs|QDir::NoSymLinks));
00132        m_iter.push(m_tree.top().begin());
00133 }
00134 
00135 void FileSearch::addCurrentDirFiles()
00136 {
00137        const QFileInfoList *filist = m_dir.entryInfoList(m_caseSensitive ? m_fileName : "*", QDir::Files);
00138        QFileInfoListIterator it( *filist );
00139        QFileInfo *fi;
00140        // Search files in this dir
00141        if (m_caseSensitive)
00142        {
00143               while ( ( fi = it.current() ) != 0 )
00144               {
00145                      ++it;
00146                      m_matchingFiles.push_back(fi->absFilePath());
00147               }
00148        }
00149        else
00150        {
00151               // unix only, resp. no meaning in windows
00152               QRegExp r(m_fileName, false, true);
00153               while ( ( fi = it.current() ) != 0 )
00154               {
00155                      ++it;
00156                      if (r.exactMatch(fi->fileName()))
00157                             m_matchingFiles.push_back(fi->absFilePath());
00158               }
00159        }
00160 }