Results 1 to 6 of 6

Thread: QFileSystemWatcher - Issue Removing Files

  1. #1
    Join Date
    May 2017
    Posts
    6
    Thanked 1 Time in 1 Post

    Default QFileSystemWatcher - Issue Removing Files

    I wanted to remove all files from a QFileSystemWatcher so I wrote this:

    Qt Code:
    1. if (fsWatcher.files().isEmpty() == false)
    2. fsWatcher.removePaths(fsWatcher.files());
    To copy to clipboard, switch view to plain text mode 
    However, I found it didn't work, and checking the QStringList returned by removePaths() I found it was failing for every single file, so no files were ever being removed from the watcher list.

    Since removePaths() wasn't working I thought I'd try the removePath() method with the code:

    Qt Code:
    1. if (fsWatcher.files().isEmpty() == false)
    2. {
    3. QStringList fileList = fsWatcher.files();
    4. QStringList::const_iterator filePath;
    5. for (filePath = fileList.constBegin() ; filePath != fileList.constEnd() ; ++filePath)
    6. if (fsWatcher.removePath(*filePath) == false)
    7. qDebug() << "Failed to remove file: " << *filePath;
    8. }
    To copy to clipboard, switch view to plain text mode 
    This too didn't work, and it failed for every file.

    To investigate the matter further I wrote this program:

    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QFileSystemWatcher>
    3. #include <QDir>
    4. #include <QDebug>
    5.  
    6. void AddFiles(QDir & dirReader, QFileSystemWatcher & fsWatcher);
    7. void RemoveFilesQDir(QDir & dirReader, QFileSystemWatcher & fsWatcher);
    8. void RemoveFilesQFSW(QFileSystemWatcher & fsWatcher);
    9.  
    10.  
    11. int main()
    12. {
    13. QDir dirReader("G:/TestFiles/Test");
    14. QFileSystemWatcher fsWatcher;
    15.  
    16. qDebug() << "Remove using RemoveFilesQDir()";
    17. AddFiles(dirReader, fsWatcher);
    18. RemoveFilesQDir(dirReader, fsWatcher);
    19.  
    20. qDebug() << "\nRemove using RemoveFilesQFSW()";
    21. AddFiles(dirReader, fsWatcher);
    22. RemoveFilesQFSW(fsWatcher);
    23.  
    24. return 0;
    25. }
    26.  
    27.  
    28. void AddFiles(QDir & dirReader, QFileSystemWatcher & fsWatcher)
    29. {
    30. QFileInfoList fileList = dirReader.entryInfoList();
    31. QFileInfoList::const_iterator file;
    32. for (file = fileList.constBegin() ; file != fileList.constEnd() ; ++file)
    33. {
    34. if (file->isFile())
    35. {
    36. if (fsWatcher.addPath(file->filePath()))
    37. qDebug() << "Add Success\t" << file->filePath();
    38. else
    39. qDebug() << "Add Fail\t" << file->filePath();
    40. }
    41. }
    42. }
    43.  
    44. void RemoveFilesQDir(QDir & dirReader, QFileSystemWatcher & fsWatcher)
    45. {
    46. QFileInfoList fileList = dirReader.entryInfoList();
    47. QFileInfoList::const_iterator file;
    48. for (file = fileList.constBegin() ; file != fileList.constEnd() ; ++file)
    49. {
    50. if (file->isFile())
    51. {
    52. if (fsWatcher.removePath(file->filePath()))
    53. qDebug() << "Remove Success\t" << file->filePath();
    54. else
    55. qDebug() << "Remove Fail\t" << file->filePath();
    56. }
    57. }
    58. }
    59.  
    60.  
    61. void RemoveFilesQFSW(QFileSystemWatcher & fsWatcher)
    62. {
    63. if (fsWatcher.files().isEmpty() == false)
    64. {
    65. QStringList fileList = fsWatcher.files();
    66. QStringList::const_iterator file;
    67. for (file = fileList.constBegin() ; file != fileList.constEnd() ; ++file)
    68. {
    69. if (fsWatcher.removePath(*file) == false)
    70. qDebug() << "Remove Successful\t" << *file;
    71. else
    72. qDebug() << "Remove Fail\t" << *file;
    73. }
    74. }
    75. }
    To copy to clipboard, switch view to plain text mode 
    The output from the program is this:

    Qt Code:
    1. Remove using RemoveFilesQDir()
    2. Add Success "G:/TestFiles/Test/Test 01.txt"
    3. Add Success "G:/TestFiles/Test/Test 02.txt"
    4. Add Success "G:/TestFiles/Test/Test 03.txt"
    5. Remove Success "G:/TestFiles/Test/Test 01.txt"
    6. Remove Success "G:/TestFiles/Test/Test 02.txt"
    7. Remove Success "G:/TestFiles/Test/Test 03.txt"
    8.  
    9. Remove using RemoveFilesQFSW()
    10. Add Success "G:/TestFiles/Test/Test 01.txt"
    11. Add Success "G:/TestFiles/Test/Test 02.txt"
    12. Add Success "G:/TestFiles/Test/Test 03.txt"
    13. Remove Fail "G:/TestFiles/Test/Test 01.txt"
    14. Remove Fail "G:/TestFiles/Test/Test 02.txt"
    15. Remove Fail "G:/TestFiles/Test/Test 03.txt"
    16. Press <RETURN> to close this window...
    To copy to clipboard, switch view to plain text mode 
    So, removing the files using the file paths from the QDir::entryInfoList() works fine, but removing the files using the paths returned by QFileSystemWatcher::files() fails, even though the file paths are identical in both cases.

    I was just wondering if somebody could explain why removing files using the paths returned by QFileSystemWatcher::files() fails?

    Also, since the below code doesn't work, what's the fastest way to clear all the files from a QFileSystemWatcher?

    Qt Code:
    1. if (fsWatcher.files().isEmpty() == false)
    2. fsWatcher.removePaths(fsWatcher.files());
    To copy to clipboard, switch view to plain text mode 
    Thanks a lot.

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemWatcher - Issue Removing Files

    What on earth are you trying to do with this code?

    Qt Code:
    1. if (fsWatcher.removePath(*file) == false)
    2. qDebug() << "Remove Successful\t" << *file;
    3. else
    4. qDebug() << "Remove Fail\t" << *file;
    To copy to clipboard, switch view to plain text mode 

    In the first place, entries in a QStringList are QString instances, not QString *, so the argument in the first line should be "file", not "*file".
    Second, your logic is backwards. The if statement says, "If you can't remove the file (removePath() returned false), then report Remove Successful".

    QFileSystemWatcher::addPath() will add the file to its list of things to watch only if the file exists. Because of the way you have constructed your tests, you are passing in a list of files obtained from QDir, which guarantees these are real files. So of course your "RemoveFilesQDir" works because you've added valid files to its list in "AddDir" and you are calling removePath() with the correct argument.

    QFileSystemWatcher::removePath() will remove the file from the list of watched files, but if the file doesn't exist, then it can return false. But your logic is upside down anyway in RemoveFilesQFSW..

    I don't know why your removePaths() code doesn't work.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    May 2017
    Posts
    6
    Thanked 1 Time in 1 Post

    Default Re: QFileSystemWatcher - Issue Removing Files

    Sorry, I was a bit out of it when I wrote that example after spending the day trying to work out what was going wrong.

    Anyway, I've spent another day and I think I've found the problem. It seems that if you add a directory, and then add some files in that directory, you can successfully remove the files, but any attempt to remove the directory fails. If you do things the other way around and add the files first, you can successfully remove the directory, but any attempts to remove the files fail.

    I'm once again a bit delirious (need to get to bed) but let me try and write an example. Here I add the directory first and then the files, then try to remove them:

    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QFileSystemWatcher>
    3. #include <QDebug>
    4.  
    5. void RemoveItems(QFileSystemWatcher & fsWatcher, char* desc, QStringList Items);
    6.  
    7. int main()
    8. {
    9. QFileSystemWatcher fsWatcher;
    10.  
    11. fsWatcher.addPath("G:/TestFiles/Test1");
    12. fsWatcher.addPath("G:/TestFiles/Test1/File 1-1.txt");
    13. fsWatcher.addPath("G:/TestFiles/Test1/File 1-2.txt");
    14. fsWatcher.addPath("G:/TestFiles/Test1/File 1-3.txt");
    15.  
    16. RemoveItems(fsWatcher, "Files", fsWatcher.files());
    17. RemoveItems(fsWatcher, "Directories", fsWatcher.directories());
    18.  
    19. fsWatcher.addPath("G:/TestFiles/Test2");
    20. fsWatcher.addPath("G:/TestFiles/Test2/File 2-1.txt");
    21. fsWatcher.addPath("G:/TestFiles/Test2/File 2-2.txt");
    22. fsWatcher.addPath("G:/TestFiles/Test2/File 2-3.txt");
    23.  
    24. RemoveItems(fsWatcher, "Files", fsWatcher.files());
    25. RemoveItems(fsWatcher, "Directories", fsWatcher.directories());
    26.  
    27. return 0;
    28. }
    29.  
    30. void RemoveItems(QFileSystemWatcher & fsWatcher, char* desc, QStringList itemList)
    31. {
    32. printf("Removing %d %s\n", itemList.size(), desc);
    33. QStringList failList = fsWatcher.removePaths(itemList);
    34.  
    35. if (failList.isEmpty())
    36. {
    37. printf("%s removed successfully\n", desc);
    38. }
    39. else
    40. {
    41. QStringList::const_iterator item;
    42. for (item = failList.constBegin() ; item != failList.constEnd() ; ++item)
    43. printf("Remove fail - %s\n", item->toLatin1().data());
    44. }
    45. printf("\n");
    46. }
    To copy to clipboard, switch view to plain text mode 
    As you can see in the output, attempts to remove the directories fail:

    Qt Code:
    1. Removing 3 Files
    2. Files removed successfully
    3.  
    4. Removing 1 Directories
    5. Remove fail - G:/TestFiles/Test1
    6.  
    7. Removing 3 Files
    8. Files removed successfully
    9.  
    10. Removing 2 Directories
    11. Remove fail - G:/TestFiles/Test1
    12. Remove fail - G:/TestFiles/Test2
    To copy to clipboard, switch view to plain text mode 
    Below I've changed the main() function to first add the files then the directory:

    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QFileSystemWatcher>
    3. #include <QDebug>
    4.  
    5. void RemoveItems(QFileSystemWatcher & fsWatcher, char* desc, QStringList Items);
    6.  
    7. int main()
    8. {
    9. QFileSystemWatcher fsWatcher;
    10.  
    11. fsWatcher.addPath("G:/TestFiles/Test1/File 1-1.txt");
    12. fsWatcher.addPath("G:/TestFiles/Test1/File 1-2.txt");
    13. fsWatcher.addPath("G:/TestFiles/Test1/File 1-3.txt");
    14. fsWatcher.addPath("G:/TestFiles/Test1");
    15.  
    16. RemoveItems(fsWatcher, "Files", fsWatcher.files());
    17. RemoveItems(fsWatcher, "Directories", fsWatcher.directories());
    18.  
    19. fsWatcher.addPath("G:/TestFiles/Test2/File 2-1.txt");
    20. fsWatcher.addPath("G:/TestFiles/Test2/File 2-2.txt");
    21. fsWatcher.addPath("G:/TestFiles/Test2/File 2-3.txt");
    22. fsWatcher.addPath("G:/TestFiles/Test2");
    23.  
    24. RemoveItems(fsWatcher, "Files", fsWatcher.files());
    25. RemoveItems(fsWatcher, "Directories", fsWatcher.directories());
    26.  
    27. return 0;
    28. }
    29.  
    30. void RemoveItems(QFileSystemWatcher & fsWatcher, char* desc, QStringList itemList)
    31. {
    32. printf("Removing %d %s\n", itemList.size(), desc);
    33. QStringList failList = fsWatcher.removePaths(itemList);
    34.  
    35. if (failList.isEmpty())
    36. {
    37. printf("%s removed successfully\n", desc);
    38. }
    39. else
    40. {
    41. QStringList::const_iterator item;
    42. for (item = failList.constBegin() ; item != failList.constEnd() ; ++item)
    43. printf("Remove fail - %s\n", item->toLatin1().data());
    44. }
    45. printf("\n");
    46. }
    To copy to clipboard, switch view to plain text mode 
    Now attempts to remove the files fail:

    Qt Code:
    1. Removing 3 Files
    2. Remove fail - G:/TestFiles/Test1/File 1-1.txt
    3. Remove fail - G:/TestFiles/Test1/File 1-2.txt
    4. Remove fail - G:/TestFiles/Test1/File 1-3.txt
    5.  
    6. Removing 1 Directories
    7. Directories removed successfully
    8.  
    9. Removing 6 Files
    10. Remove fail - G:/TestFiles/Test1/File 1-1.txt
    11. Remove fail - G:/TestFiles/Test1/File 1-2.txt
    12. Remove fail - G:/TestFiles/Test1/File 1-3.txt
    13. Remove fail - G:/TestFiles/Test2/File 2-1.txt
    14. Remove fail - G:/TestFiles/Test2/File 2-2.txt
    15. Remove fail - G:/TestFiles/Test2/File 2-3.txt
    16.  
    17. Removing 1 Directories
    18. Directories removed successfully
    19.  
    20. Press <RETURN> to close this window...
    To copy to clipboard, switch view to plain text mode 
    Hopefully those examples make sense this time

    I'm not sure if this is a bug with QFileSystemWatcher or if I'm misunderstanding something. Anyway, I best take a shower and get to bed and I'll look into this more tomorrow morning.

  4. #4
    Join Date
    May 2017
    Posts
    6
    Thanked 1 Time in 1 Post

    Default Re: QFileSystemWatcher - Issue Removing Files

    Unless I'm missing something, this does appear to be a bug in QFileSystemWatcher. It appears that the only solution is to have two QFileSystemWatcher - one for files and another for directories. If you do things that way it works fine.

    Here's the program from the previous post modified to use two QFileSystemWatchers:

    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QFileSystemWatcher>
    3. #include <QDebug>
    4.  
    5. void RemoveItems(QFileSystemWatcher & fsWatcher, char* desc, QStringList Items);
    6.  
    7. int main()
    8. {
    9. QFileSystemWatcher fsWatcherDir;
    10. QFileSystemWatcher fsWatcherFile;
    11.  
    12. fsWatcherDir.addPath("G:/TestFiles/Test1");
    13. fsWatcherFile.addPath("G:/TestFiles/Test1/File 1-1.txt");
    14. fsWatcherFile.addPath("G:/TestFiles/Test1/File 1-2.txt");
    15. fsWatcherFile.addPath("G:/TestFiles/Test1/File 1-3.txt");
    16.  
    17. RemoveItems(fsWatcherFile, "Files", fsWatcherFile.files());
    18. RemoveItems(fsWatcherDir, "Directories", fsWatcherDir.directories());
    19.  
    20. fsWatcherDir.addPath("G:/TestFiles/Test2");
    21. fsWatcherFile.addPath("G:/TestFiles/Test2/File 2-1.txt");
    22. fsWatcherFile.addPath("G:/TestFiles/Test2/File 2-2.txt");
    23. fsWatcherFile.addPath("G:/TestFiles/Test2/File 2-3.txt");
    24.  
    25. RemoveItems(fsWatcherFile, "Files", fsWatcherFile.files());
    26. RemoveItems(fsWatcherDir, "Directories", fsWatcherDir.directories());
    27.  
    28. return 0;
    29. }
    30.  
    31. void RemoveItems(QFileSystemWatcher & fsWatcher, char* desc, QStringList itemList)
    32. {
    33. printf("Removing %d %s\n", itemList.size(), desc);
    34. QStringList failList = fsWatcher.removePaths(itemList);
    35.  
    36. if (failList.isEmpty())
    37. {
    38. printf("%s removed successfully\n", desc);
    39. }
    40. else
    41. {
    42. QStringList::const_iterator item;
    43. for (item = failList.constBegin() ; item != failList.constEnd() ; ++item)
    44. printf("Remove fail - %s\n", item->toLatin1().data());
    45. }
    46. printf("\n");
    47. }
    To copy to clipboard, switch view to plain text mode 
    And the output:

    Qt Code:
    1. Removing 3 Files
    2. Files removed successfully
    3.  
    4. Removing 1 Directories
    5. Directories removed successfully
    6.  
    7. Removing 3 Files
    8. Files removed successfully
    9.  
    10. Removing 1 Directories
    11. Directories removed successfully
    To copy to clipboard, switch view to plain text mode 
    I'd be grateful if somebody could clarify if this is a misunderstanding on my part or a bug that needs reporting.

    Thanks.

  5. The following user says thank you to Escot for this useful post:

    d_stranz (18th June 2017)

  6. #5
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemWatcher - Issue Removing Files

    Nice work in testing this. I have no idea if this is a bug or not.

    A further test would be to see if you still get change events on the directories even after you have tried (and failed) to remove them from the QFSW. If you do, then I would definitely classify that as a bug.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. #6
    Join Date
    May 2017
    Posts
    6
    Thanked 1 Time in 1 Post

    Default Re: QFileSystemWatcher - Issue Removing Files

    After a failed attempt to remove a file from the watcher it does stop sending fileChanged() signals for the file. The problem is that if you need to add that file back to the QFileSystemWatcher the addPath() operation files.

    This can be a significant issue, for example in my program:

    User visits directory - all files get added to watcher and fileChanged() signals work correctly.
    User leaves directory - program attempts to remove files for watcher, but removePath() operation fails for all files.
    User returns to directory - program attempts to add files again to watcher, but addPath() operation fails. Program will therefore not received fileChanged() signals so will fail to work correctly.

    This is actually how I noticed the issue to begin with. The program wasn't receiving fileChanged() signals when it should so I checked the QFileSystemWatcher files() list and found the files were there, so I was confused. I later noticed there were other files on the list that shouldn't have been there and that's when I found out that removePath() was failing.

Similar Threads

  1. Issue in playing animated webp files using QMovie
    By sumarka in forum Qt Programming
    Replies: 0
    Last Post: 19th May 2016, 08:13
  2. [SOLVED] Issue Using external files with QSettings
    By Arkahik in forum Qt Programming
    Replies: 6
    Last Post: 13th April 2016, 16:37
  3. Replies: 2
    Last Post: 13th March 2015, 08:59
  4. Removing locked attribute on Mac locked files?
    By gfunk in forum Qt Programming
    Replies: 1
    Last Post: 26th October 2007, 22:40
  5. Replies: 5
    Last Post: 22nd September 2006, 08:04

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
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.