Skip to content

Class QArchive::Extractor

Antony jr edited this page Dec 16, 2017 · 30 revisions

The Extractor Takes care of extraction of archives with the help of libarchive.
This class runs on a seperate thread to avoid blocking by libarchive.

Table of Contents

Class Anatomy

Constructors

Extractor(QObject *parent = NULL)
Extractor(const QString&) Simply add a single archive , any format Most likely will be used for 7zip.
Extractor(const QStringList&) Add all archives from the QStringList in order.
Extractor(const QString& , const QString&) Add a single archive and set the destination path.
Extractor(const QStringList& , const QString&) Add all archive from the QStringList and set the destination path.

Methods

void addArchive(const QString&) Add a archive to the queue.
void addArchive(const QStringList&) Add a set of archives to the queue.
void removeArchive(const QString&) Remove's a archive from the queue matching the QString.
void setDestination(const QString&) set the Destination of the extracted files.

Slots

void start(void) Starts or resumes the extractor. (Inherited from QThread)
Stoping and Terminating Refer QtDocs for information on stoping QThread.

Signals

void finished() Emitted when all extraction job is done.
void extracting(const QString&) Emitted with the filename beign extracted.
void extracted(const QString&) Emitted with the filename that has been extracted.
void status(const QString& ,const QString&) Emitted with archive(1) and filename(2) beign writen.
void error(short , const QString&) Emitted when something goes wrong! This does provide the filename.

Usage

The Extractor Class is inherited from QThread and thus it runs in a seperate thread , this
prevents libarchive from blocking your main thread.

Just three steps to extract any file that is supported by libarchvie

Note: examples can be found in the examples tree of this repo.

Step #1:
Construct the Extractor Class!

 #include "QArchive.hpp"
   ...
   ...
 int main(int argc , char** argv){
  QCoreApplication app(argc , argv);
     ...
  QArchive::Extractor Archive("test.7z");
     ...
  return app.exec();
 }

Step #2: Connect Your Callbacks!

 // emitted when all extraction is finished 
 QObject::connect(&Archive , &QArchive::Extractor::finished , [&](){
          qDebug() << "Finished all extraction!";
          app.quit();
 });

Step #3: Start the extraction! This does not block your main thread.

 Archive.start();
 qDebug() << "Its Non-Blocking!";

Handling error's

Take a look at QArchive error codes here

These error codes are passed to error signal by the Extractor with the corresponding filename,
So all you have to do is to connect your callback to this signal and use the error codes to find the
type of error you are dealing with.

Like this

// emitted when something goes wrong
QObject::connect(&e , &QArchive::Extractor::error , [&](short code , QString file){
     switch(code){
       case QArchive::ARCHIVE_READ_ERROR:
              qDebug() << "unable to find archive :: " << file;
              app.quit();
              break;
       case QArchive::ARCHIVE_QUALITY_ERROR:
              qDebug() << "bad archive! :: " << file;
              app.quit();
              break;
       case QArchive::ARCHIVE_UNCAUGHT_ERROR:
              qDebug() << "fatal error. :: " << file;
              app.quit();
              break;
       default:
              qDebug() << "unknown error. :: " << file;
              app.quit();
              break;
  }
});

Destination Path

Setting destination path will make QArchive extract the files to the directory user mentioned , its
simply as extract to.
You can set the destination path from the constructor or later by a Method , The default
output path is the programs working directory

Through Constructor

QArchive::Extractor Archiver("ArchiveName.7z" , "OutputDirectory");

Through Method

QArchive::Extractor Archiver("ArchiveName.7z");
Archiver.setDestination("OutputDirectory");

A Universal Extractor with QArchive

universal_extractor.pro

TEMPLATE = app
TARGET = extraction
LIBS += -larchive
INCLUDEPATH += . /path/to/QArchive-header /path/to/libarchive-headers
DEFINES += QT_DEPRECATED_WARNINGS
QT += core

SOURCES += main.cpp
HEADERS += path/to/QArchive.hpp

main.cpp

#include <QCoreApplication>
#include <QDebug>
#include "QArchive.hpp"

int main(int argc , char** argv)
{
   QCoreApplication app(argc , argv);
   /*
    * 1.Construct
    */
   if(argc == 1){ return -1; } 
   QArchive::Extractor e(QString(argv[1]));


   /*
    * 2.Connect Callbacks
   */

   // emitted when all extraction is finished 
   QObject::connect(&e , &QArchive::Extractor::finished , [&](){
   qDebug() << "Finished all extraction!";
   app.quit();
   });

   QObject::connect(&e , &QArchive::Extractor::extracting , [&](QString file){
   qDebug() << "Extracting:: " << file;
   });

   // emitted when a file is extracted
   QObject::connect(&e , &QArchive::Extractor::extracted , [&](QString file){
   qDebug() << "Extracted:: " << file;
   });
   // emitted when something goes wrong
   QObject::connect(&e , &QArchive::Extractor::error , [&](short code , QString file){
    switch(code){
     case QArchive::ARCHIVE_READ_ERROR:
      qDebug() << "unable to find archive :: " << file;
      app.quit();
      break;
    case QArchive::ARCHIVE_QUALITY_ERROR:
     qDebug() << "bad archive! :: " << file;
     app.quit();
     break;
    case QArchive::ARCHIVE_UNCAUGHT_ERROR:
     qDebug() << "fatal error. :: " << file;
     app.quit();
     break;
    default:
     qDebug() << "unknown error. :: " << file;
     app.quit();
     break;
   }
  });

  /*
   * 3.Start extraction!
   */
  e.start();
  qDebug() << "Its Non-Blocking!";
  return app.exec();
}

Compiling with QMake

 $ mkdir build
 $ cd build
 $ qmake ../universal_extractor.pro
 $ make -j4