Results 1 to 6 of 6

Thread: Recursive directory scan with abort function in a non blocking manner

  1. #1
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Wiki edits
    5

    Default Recursive directory scan with abort function in a non blocking manner

    Hi,

    this is the task: Scan a folder recursive for - lets say - png files and give their addresses back in a QStringList. Furthermore the count of the found images should be displayed in a label or whatever during the scan. And of course the gui is not allowed to freeze and you should be able to abort the scan.

    And the solution is ... ? Or better asked, what is the best, easiest and best-performance solution?

    Right now I have a simple subclasses thread and do like:
    Qt Code:
    1. class ThreadReadDir : public QThread
    2. {
    3. Q_OBJECT
    4. public:
    5. explicit ThreadReadDir(QObject* parent = 0)
    6. : QThread(parent)
    7. {
    8. m_stopped = false;
    9. }
    10.  
    11. void stop()
    12. {
    13. m_stopped = true;
    14. }
    15.  
    16. void readDir(QDir dir)
    17. {
    18. m_dir = dir;
    19. if (!m_stopped)
    20. start();
    21. }
    22.  
    23. void run()
    24. {
    25. readDir_private(m_dir);
    26. }
    27.  
    28. QStringList files() const
    29. {
    30. return m_files;
    31. }
    32.  
    33. Q_SIGNALS:
    34. void currentFileCountChanged(int);
    35.  
    36. private:
    37. QStringList m_files;
    38. QDir m_dir;
    39. bool m_stopped;
    40.  
    41. void readDir_private(QDir dir)
    42. {
    43. if (m_stopped)
    44. return;
    45. QStringList files = dir.entryList(QStringList() << "*.png", QDir::Files, QDir::Name);
    46. for (int i = 0; i < files.count(); ++i)
    47. m_files << dir.absolutePath() + QDir::separator() + files.value(i);
    48. Q_EMIT currentFileCountChanged(m_files.count());
    49.  
    50. if (m_stopped)
    51. return;
    52. QStringList directories = dir.entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
    53. for (int i = 0; i < directories.count(); ++i)
    54. {
    55. if (m_stopped)
    56. return;
    57. readDir_private(dir.absolutePath() + QDir::separator() + directories.at(i));
    58. }
    59. }
    60. };
    To copy to clipboard, switch view to plain text mode 
    With
    Qt Code:
    1. // Constructor
    2. ThreadReadDir* m_filethread = new ThreadReadDir(this);
    3. QObject::connect(m_filethread, SIGNAL(currentFileCountChanged(int)), this, SLOT(setFileCount(int)));
    4.  
    5. // After scan request
    6. m_filethread->readDir(QDir(/*...*/));
    7.  
    8. //
    9. void XXX::setFileCount(int cnt)
    10. {
    11. ui->statRead->setText(QString("%1 Files").arg(cnt));
    12. }
    13.  
    14. //
    15. void XXX::OnAbortRequest()
    16. {
    17. m_filethread->stop();
    18. m_filethread->wait();
    19. }
    To copy to clipboard, switch view to plain text mode 

    It works, but it is a hell of work for such a simple request and therefore I wonder if there is a easier and better to maintain way to achieve that. QtConcurrent::run would be fine if one could cancel it.


    Thanks for sharing your thoughts,

    Lykurg

  2. #2
    Join Date
    Jul 2009
    Location
    Enschede, Netherlands
    Posts
    462
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanked 69 Times in 67 Posts

    Default Re: Recursive directory scan with abort function in a non blocking manner

    The QtConcurrent::map*() functions are cancellable through the QFuture object they return. Maybe it's possible to mock something up using that? (it would probably be a little hackish though )
    Horse sense is the thing that keeps horses from betting on people. --W.C. Fields

    Ask Smart Questions

  3. #3
    Join Date
    Jun 2010
    Posts
    142
    Qt products
    Qt4
    Platforms
    Unix/X11
    Thanks
    11
    Thanked 4 Times in 3 Posts

    Default Re: Recursive directory scan with abort function in a non blocking manner

    Not sure if this is relavent, but the file extension is NOT a certain way to tell the type of a file. For example i use Linux, and file extensions have no meaning to it. The only real reason for them is for the user to tell the file type easily, and because *some* programs pay attention to them.

    Unlike in Windows, in Linux I can call a PNG file "image.jpg" and it will work just fine, because *nix and most *nix programs look at the contents of the file, not the extension.

    Qt Code:
    1. michael@michael-desktop ~ $ file image.jpg
    2. image.jpg: JPEG image data, JFIF standard 1.01
    3. michael@michael-desktop ~ $ mv image.jpg image.png
    4. michael@michael-desktop ~ $ file image.png
    5. image.png: JPEG image data, JFIF standard 1.01
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jul 2010
    Posts
    21
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanked 5 Times in 5 Posts

    Default Re: Recursive directory scan with abort function in a non blocking manner

    I'd probably go with QThread as well. Something like
    Qt Code:
    1. class Scanner : public QThread
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. explicit Scanner(const QDir &dir, QObject *parent = 0)
    7. : iterator(dir, QDirIterator::Subdirectories), QThread(parent), stopped(false)
    8. {
    9. }
    10.  
    11. void run()
    12. {
    13. while(!stopped && iterator.hasNext()) {
    14. QString entry(iterator.next());
    15. if(QFileInfo(entry).suffix().toLower() == "png") {
    16. fileList << entry;
    17. emit fileCountChanged(fileList.count());
    18. }
    19. }
    20. }
    21.  
    22. QStringList files() const
    23. {
    24. return fileList;
    25. }
    26.  
    27. public slots:
    28. void stop()
    29. {
    30. stopped = true;
    31. }
    32.  
    33. signals:
    34. void fileCountChanged(int);
    35.  
    36. private:
    37. QDirIterator iterator;
    38. QStringList fileList;
    39. bool stopped;
    40. };
    To copy to clipboard, switch view to plain text mode 
    Then simply start(), stop() and wait(), as in the original code snippet above.

  5. #5
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Wiki edits
    5

    Default Re: Recursive directory scan with abort function in a non blocking manner

    Oh, I love Qt! And I should probably look more often in the docs, also for working solutions since I wasn't aware of QDirIterator. This will save me doing the recursive function. Nice! Thanks for pointing that out. (One small improvement if somebody want use it later: since the iterator uses a QFileInfo internal better use that (QDirIterator::fileInfo) instead of creating a second one.)

    @franz: the map* functions are nice but personal I find them hard to maintain (especial in that case). A capsuled Thread is also easier to reuse.
    @MTK358: The suffixes are of course meaningless. If you want be sure that it is really a png or any other file you have to do "deeper" tests.


    And one follow up: Did you normally subclass QThread or use QObject::moveToThread()? (I am just curious how others did it.)

  6. #6
    Join Date
    Jun 2010
    Posts
    142
    Qt products
    Qt4
    Platforms
    Unix/X11
    Thanks
    11
    Thanked 4 Times in 3 Posts

    Default Re: Recursive directory scan with abort function in a non blocking manner

    Quote Originally Posted by Lykurg View Post
    The suffixes are of course meaningless. If you want be sure that it is really a png or any other file you have to do "deeper" tests.
    Yes, sure. If I would make a simple example I would just have it search for *.png, too. Anyway, if it matters, in Wikipedia it says that a PNG file should always begin with:

    Qt Code:
    1. 89 50 4E 47 0D 0A 1A 0A
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. [QtNetwork] LAN GameServer Port Scan ... how to?
    By BrainB0ne in forum Qt Programming
    Replies: 0
    Last Post: 4th December 2009, 22:42
  2. how to abort a function taking to long to process
    By john_god in forum General Programming
    Replies: 5
    Last Post: 30th April 2009, 02:06
  3. Vista - Scan System Hardware?
    By JimDaniel in forum Qt Programming
    Replies: 1
    Last Post: 10th March 2008, 19:07
  4. Read Data in formated manner
    By rajeshs in forum Qt Programming
    Replies: 1
    Last Post: 1st January 2008, 13:28
  5. how to recursive a directory in qt?
    By deweyjew in forum Qt Programming
    Replies: 5
    Last Post: 7th November 2006, 10:06

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.