Search code examples
c++qtmemoryqfileqfiledialog

How to check the available free space of a selected drive in Qt?


I am using Qt5.6.2 in Windows 7.My Goal is to save a CustomDatafile to a selected drive (mostly a Pen drive or local drive or network drive).

So before saving the file I would like to check the available memory and write access of the selected path.

From this thread I came to know about QStorageInfo class. So I wrote the below function.

bool ImportExport::checkWriteAccessAndEnoughDriveSpace(const QString &path,QString &error)
{
   error = QString();
   int fileSizeMB = 100;//for testing purpose I am comparing with 100 MB. correct solution is to compare with size of the file.
   qDebug() << "path to QStorage: " <<path;
   QStorageInfo storage(path);
   //QStorageInfo storage = QStorageInfo::root();
   qDebug() << "export root path: " <<storage.rootPath();
   qDebug() << "volume name:" << storage.name();
   qDebug() << "fileSystemType:" << storage.fileSystemType();
   qDebug() << "size:" << storage.bytesTotal()/1000/1000 << "MB";
   qDebug() << "availableSize:" << storage.bytesAvailable()/1000/1000 << "MB";

   if (storage.isValid() && storage.isReady()) {
      if (!storage.isReadOnly()) {
         // check enough memory
         int MBavailable = storage.bytesAvailable()/1000/1000;
         if(MBavailable > fileSizeMB){
            return true;
         }else{
            error = tr("Not enough disk space, available disk space is only : ") + QString::number(MBavailable);
            return false;
         }
      }else{
         error = tr("No permission to write to current folder ");
         qDebug() << error; // how to set this message as toolTip on the fileDialog
         return false;
      }
   }else{
      error = tr("Selected drive validity: ")+ QString::number(storage.isValid()) +tr("or storage availability: ") +QString::number(storage.isReady());
      qDebug() << error; // how to set this message as toolTip
      return false;
   }
}

This is the debug output:

path to QStorage:  "D:/Aluminium Demo DMU105mB.cba"
export root path:  ""
volume name: ""
fileSystemType: ""
size: 0 MB
availableSize: 0 MB
"Selected drive validity: 0or storage availability: 0"

As you can see the QStorageInfo is always giving me 0 size, drive not ready. No matter what ever the drive i select the result is always the same. Can anybody point out the error? any solution for my problem? Thank you in advance.

Edit 1: if I hardcode the QStorage contructor

QStorageInfo storage("D:"); Then Everything works fine. If I give the path QStorageInfo storage("D:\Application Cube DMU65mB.cba");

Then it doesn't work. The user can select any drive (local drive or removable drive). On selecting the folder I get the path from the QDialog (code is not shown here). So I think if I can get only the Drive infromation from the path then my problem is solved I guess. Now, How can I get only the drive name? I can do by parsing the path which I got from the QDialog but any better solution? Thanks

Edit 2: I have changed the contructor to QStorageInfo storage(path);. Then it works for Local Drives but if the user selects Removable Drive (Pen drive), it doesn't work. Anyone has idea why it is not working for Pen Drive? Thanks.


Solution

  • The problem is with the path given to the constructor of QStorageInfo class. If the path includes the file name then it will NOT work. The following works:

       QFileInfo info(fullPath);
       QString path = info.path();
       QStorageInfo storage(path);
    

    Note: Fullpath contains the filename whereas the path doesn't.

    Then comes the next problem QStorageInfo::isReadOnly() gives you false even though you have write access. This doesn't work due to Windows-NFTS file System. So the trick is to check if you can sucecssfully create a temp file.

      if (storage.isValid() && storage.isReady()) {
          //check write permission
          QString filename(path+"dummyTempJob.job"); //temp file, a workaround to check write access because QFileInfo isWritable and storage.isReadOnly() doesn't work for windows NTFS system
          QFile file(filename);
          if(file.open(QIODevice::WriteOnly)){
              file.remove();//delete the temp file
              checkWriteAccess = true;
          }else{
             error = QObject::tr("No write permissions to %1.").arg(path);
             qCritical()<< error;
          }
       }else{
          error = QObject::tr("Drive %1 is not available.").arg(storage.rootPath());
          qCritical() << error << QStringLiteral(" valid = %1, ready = %2").arg(storage.isValid()).arg(storage.isReady());
       }