Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Moving files to Recycle Bin is slow.
Forum Updated to NodeBB v4.3 + New Features

Moving files to Recycle Bin is slow.

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 3 Posters 3.4k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    samdol
    wrote on last edited by
    #1

    Hi,

    I tried to move files to recycle bin in windows 7. But Qt does not provide
    platform independent method to do that. I found that I could use the following
    snippet to send files to recycle bin.

    bool MainWindow::moveToTrash( QString fn ){
        QFileInfo fileinfo( fn );
        if( !fileinfo.exists() ){
            QMessageBox::warning(this,tr("Failed") ,tr("No %1 exists").arg(fn));
            return false;
         //   throw OdtCore::Exception( "File doesnt exists, cant move to trash" );
        }
        WCHAR from[ MAX_PATH ];
        memset( from, 0, sizeof( from ));
        int l = fileinfo.absoluteFilePath().toWCharArray( from );
        Q_ASSERT( 0 <= l && l < MAX_PATH );
        from[ l ] = '\0';
    
        SHFILEOPSTRUCT fileop;
        memset( &fileop, 0, sizeof( fileop ) );
        fileop.wFunc = FO_DELETE;
        fileop.pFrom = from;
        fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
    
    
    //SHFileOperationW
       int rv = SHFileOperationW( &fileop ); //Takes 20 ~ 70 ms which is 90% of deleting process. 5 times slower than just deleting.
        if( 0 != rv ){
            //qDebug() << rv << QString::number( rv ).toInt( 0, 8 );
            QMessageBox::warning(this,tr("Failed") ,tr("Could not move %1 to trash.").arg(fn));
           // throw OdtCore::Exception( "move to trash failed" );
            return false;
        }
    
        return true;
    }
    

    It works but very slow. Deleting 2000 files by explorer takes less than 30 seconds. In contrast, using SHFileOperationW() takes 4 or 5 minutes to delete the same 2000 files which is intollerable. Is it a normal performance or can I improve the performance with other methods?

    raven-worxR 1 Reply Last reply
    0
    • S samdol

      Hi,

      I tried to move files to recycle bin in windows 7. But Qt does not provide
      platform independent method to do that. I found that I could use the following
      snippet to send files to recycle bin.

      bool MainWindow::moveToTrash( QString fn ){
          QFileInfo fileinfo( fn );
          if( !fileinfo.exists() ){
              QMessageBox::warning(this,tr("Failed") ,tr("No %1 exists").arg(fn));
              return false;
           //   throw OdtCore::Exception( "File doesnt exists, cant move to trash" );
          }
          WCHAR from[ MAX_PATH ];
          memset( from, 0, sizeof( from ));
          int l = fileinfo.absoluteFilePath().toWCharArray( from );
          Q_ASSERT( 0 <= l && l < MAX_PATH );
          from[ l ] = '\0';
      
          SHFILEOPSTRUCT fileop;
          memset( &fileop, 0, sizeof( fileop ) );
          fileop.wFunc = FO_DELETE;
          fileop.pFrom = from;
          fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
      
      
      //SHFileOperationW
         int rv = SHFileOperationW( &fileop ); //Takes 20 ~ 70 ms which is 90% of deleting process. 5 times slower than just deleting.
          if( 0 != rv ){
              //qDebug() << rv << QString::number( rv ).toInt( 0, 8 );
              QMessageBox::warning(this,tr("Failed") ,tr("Could not move %1 to trash.").arg(fn));
             // throw OdtCore::Exception( "move to trash failed" );
              return false;
          }
      
          return true;
      }
      

      It works but very slow. Deleting 2000 files by explorer takes less than 30 seconds. In contrast, using SHFileOperationW() takes 4 or 5 minutes to delete the same 2000 files which is intollerable. Is it a normal performance or can I improve the performance with other methods?

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @samdol said in Moving files to Recycle Bin is slow.:
      what first comes to my mind is that you are using QFileInfo for each file. QFileInfo is rather expensive and should be avoided in your case if anyhow possible.

      Also you are testing in release mode right?

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      S 1 Reply Last reply
      2
      • raven-worxR raven-worx

        @samdol said in Moving files to Recycle Bin is slow.:
        what first comes to my mind is that you are using QFileInfo for each file. QFileInfo is rather expensive and should be avoided in your case if anyhow possible.

        Also you are testing in release mode right?

        S Offline
        S Offline
        samdol
        wrote on last edited by samdol
        #3

        @raven-worx
        Thanks, but when I run benchmark test, QFileInfo did not take much time compare to SHFileOperationW() which takes 90 percent of processing time for deleting files. It took 30~ 70 miliseconds for each file which is quite slow compare to direct delete. And Yes, I tested in release mode.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi,

          After a quicklook about SHFileOperationW, it seems you're not the only experimenting this problem. It is however a Windows API specific issue and nothing Qt can do anything about.

          Taking a look at the documentation of SHFILEOPSTRUCT, it seems that the pFrom string can contain a list of files so you may gain time by building the list of all the files you want to delete and make only one call to SHFileOperationW.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          S 1 Reply Last reply
          8
          • SGaistS SGaist

            Hi,

            After a quicklook about SHFileOperationW, it seems you're not the only experimenting this problem. It is however a Windows API specific issue and nothing Qt can do anything about.

            Taking a look at the documentation of SHFILEOPSTRUCT, it seems that the pFrom string can contain a list of files so you may gain time by building the list of all the files you want to delete and make only one call to SHFileOperationW.

            S Offline
            S Offline
            samdol
            wrote on last edited by samdol
            #5

            @SGaist

            Thank you for the advise. As you suggested, I attempt to put multiple deleting files on SHFileOperationW.
            Doc says I need to put 0s between filenames, I created Qstring with 0s between
            filenames. Then converted to WcharArray and finally put 0 at the end.
            But when I run this code, it puts only file1.jpg to recyclebin. And file2.jpg
            did not move.

            bool moveToTrash( QString filenames ){
                WCHAR from[ MAX_PATH ];
                memset( from, 0, sizeof( from ));
                int l = filenames.toWCharArray( from );
                Q_ASSERT( 0 <= l && l < MAX_PATH );
                from[ l ] = '\0';
            
                SHFILEOPSTRUCT fileop;
                memset( &fileop, 0, sizeof( fileop ) );
                fileop.wFunc = FO_DELETE;
                fileop.pFrom = from;
                fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
            
            //SHFileOperationW
               int rv = SHFileOperationW( &fileop ); //Takes 20 ~ 70 ms which is 90% of deleting process. 5 times slower than just deleting.
                if( 0 != rv ){
                    return false;
                }
                return true;
            }
            
            
            
            
            int main(int argc, char *argv[])
            {
                QApplication a(argc, argv);
                QString filenames=QString("D:/folder/file1.jpg\0D:/folder/file2.jpg");
                moveToTrash(filenames);
                return a.exec();
            }
            
            raven-worxR 1 Reply Last reply
            0
            • S samdol

              @SGaist

              Thank you for the advise. As you suggested, I attempt to put multiple deleting files on SHFileOperationW.
              Doc says I need to put 0s between filenames, I created Qstring with 0s between
              filenames. Then converted to WcharArray and finally put 0 at the end.
              But when I run this code, it puts only file1.jpg to recyclebin. And file2.jpg
              did not move.

              bool moveToTrash( QString filenames ){
                  WCHAR from[ MAX_PATH ];
                  memset( from, 0, sizeof( from ));
                  int l = filenames.toWCharArray( from );
                  Q_ASSERT( 0 <= l && l < MAX_PATH );
                  from[ l ] = '\0';
              
                  SHFILEOPSTRUCT fileop;
                  memset( &fileop, 0, sizeof( fileop ) );
                  fileop.wFunc = FO_DELETE;
                  fileop.pFrom = from;
                  fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
              
              //SHFileOperationW
                 int rv = SHFileOperationW( &fileop ); //Takes 20 ~ 70 ms which is 90% of deleting process. 5 times slower than just deleting.
                  if( 0 != rv ){
                      return false;
                  }
                  return true;
              }
              
              
              
              
              int main(int argc, char *argv[])
              {
                  QApplication a(argc, argv);
                  QString filenames=QString("D:/folder/file1.jpg\0D:/folder/file2.jpg");
                  moveToTrash(filenames);
                  return a.exec();
              }
              
              raven-worxR Offline
              raven-worxR Offline
              raven-worx
              Moderators
              wrote on last edited by
              #6

              @samdol said in Moving files to Recycle Bin is slow.:

              QString filenames=QString("D:/folder/file1.jpg\0D:/folder/file2.jpg");

              don't go the long way with QString. I think QString only creates the string until it finds the \0 character.
              Pass a QStringList to your moveToTrash() method and create the string for the WinAPI call just before calling it.

              --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
              If you have a question please use the forum so others can benefit from the solution in the future

              1 Reply Last reply
              1
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                You can use a QByteArray to create your long list of files as, like @raven-worx, QString represent a zero terminated string.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                S 1 Reply Last reply
                1
                • SGaistS SGaist

                  You can use a QByteArray to create your long list of files as, like @raven-worx, QString represent a zero terminated string.

                  S Offline
                  S Offline
                  samdol
                  wrote on last edited by
                  #8

                  @SGaist

                  In the following code, I tried to send QStringList of deleting files to
                  moveToTrash(). And used QByteArray to add '\0's between filenames. But when I compile, it says,
                  cannot convert 'char*' to 'WCHAR{aka wchar_t*}' in initialization.
                  cannot convert 'WCHAR* {aka wchar_t*} to 'char*' for argument '1' to 'char*
                  strcpy(char*, const char*)'
                  I also tried to do ba.toWCharArray(from), but I could not find such function
                  for QByteArray.

                  bool moveToTrash( QStringList filename_list ){
                      QByteArray ba;
                      for(int i=0;i<filename_list.size();i++){
                          ba.append(filename_list.at(i));
                          ba.append('\0');
                      }
                      ba.append('\0');
                  
                      WCHAR* from = new char[ba.size()]; <-- Error
                      strcpy(from, ba.data()); <-- Error
                  
                      SHFILEOPSTRUCT fileop;
                      memset( &fileop, 0, sizeof( fileop ) );
                     // fileop.hwnd = NULL;
                      fileop.wFunc = FO_DELETE;
                      fileop.pFrom = from;
                      fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
                  
                     int rv = SHFileOperationW( &fileop );
                     if( 0 != rv ){
                          return false;
                      }
                      return true;
                  }
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication a(argc, argv);
                      QStringList filename_list;
                      filename_list<<"D:/folder/file1.jpg"<<"D:/folder/file2.jpg";
                      moveToTrash(filename_list);
                      return a.exec();
                  }
                  
                  S 1 Reply Last reply
                  0
                  • S samdol

                    @SGaist

                    In the following code, I tried to send QStringList of deleting files to
                    moveToTrash(). And used QByteArray to add '\0's between filenames. But when I compile, it says,
                    cannot convert 'char*' to 'WCHAR{aka wchar_t*}' in initialization.
                    cannot convert 'WCHAR* {aka wchar_t*} to 'char*' for argument '1' to 'char*
                    strcpy(char*, const char*)'
                    I also tried to do ba.toWCharArray(from), but I could not find such function
                    for QByteArray.

                    bool moveToTrash( QStringList filename_list ){
                        QByteArray ba;
                        for(int i=0;i<filename_list.size();i++){
                            ba.append(filename_list.at(i));
                            ba.append('\0');
                        }
                        ba.append('\0');
                    
                        WCHAR* from = new char[ba.size()]; <-- Error
                        strcpy(from, ba.data()); <-- Error
                    
                        SHFILEOPSTRUCT fileop;
                        memset( &fileop, 0, sizeof( fileop ) );
                       // fileop.hwnd = NULL;
                        fileop.wFunc = FO_DELETE;
                        fileop.pFrom = from;
                        fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
                    
                       int rv = SHFileOperationW( &fileop );
                       if( 0 != rv ){
                            return false;
                        }
                        return true;
                    }
                    
                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                        QStringList filename_list;
                        filename_list<<"D:/folder/file1.jpg"<<"D:/folder/file2.jpg";
                        moveToTrash(filename_list);
                        return a.exec();
                    }
                    
                    S Offline
                    S Offline
                    samdol
                    wrote on last edited by
                    #9

                    @samdol
                    I also tried the following approach. Manually adding '\0's between files. It seems it should work. but it moves a file to trach only when I delete one file. If I try to delete more than one file, it does not do anything.

                    bool moveToTrash( QStringList filename_list ){
                    
                        WCHAR* from= new WCHAR[ 999999 ];
                        int l=filename_list.at(0).toWCharArray( from );
                        from[l]='\0';
                    
                        int i;
                        for( i=1;i<filename_list.size();i++){
                            WCHAR* from_tmp = new WCHAR[ filename_list.at(i).size() ];
                            l += filename_list.at(i).toWCharArray( from_tmp );
                            wcscat (from, from_tmp);
                            from[l+i]='\0';
                    
                        }
                        from[l+i+1]='\0';
                    
                        SHFILEOPSTRUCT fileop;
                        memset( &fileop, 0, sizeof( fileop ) );
                        fileop.wFunc = FO_DELETE;
                        fileop.pFrom = from;
                        fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
                    
                       int rv = SHFileOperationW( &fileop ); //Takes 20 ~ 70 ms which is 90% of deleting process. 5 times slower than just deleting.
                    
                        return true;
                    }
                    
                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved