PDA

View Full Version : unpacking rar files



mentalmushroom
10th March 2011, 08:03
Hello. Does qt provide some means for unpacking rar files? Using command line tools isn't a good way, because I need it to be platform-independent and while unpacking I need to receive some information about the unrarring process such as progress indication, volume changing for multipart archives etc.

squidge
10th March 2011, 11:57
I know rarlabs produce Unrar.dll for Windows, maybe they produce similar library for Linux/etc?

mentalmushroom
10th March 2011, 13:33
Yes, unrar.dll is for windows and they also provide portable sources. I hope they are really portable for Linux and Mac. I thought maybe Qt already has some functionality for that purpose.

tanderson
10th March 2011, 22:27
I have successfully used QProcess to use unrar on linux and mac. I believe it will work on windows also, but I haven't tested it.


/************************************************** **********************
Copyright 2009 Thomas Anderson

This file is part of QBinNews.

QBinNews is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

QBinNews is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with QBinNews. If not, see <http://www.gnu.org/licenses/>.
************************************************** ************************/

#include "qunrarthread.h"
#include <QDebug>

QUnrar::QUnrar() : scanCount(0)
{
unrarProcess = new QProcess(this);
connect (unrarProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutputSlot()));
connect (unrarProcess, SIGNAL(readyReadStandardError()), this, SLOT(readErrorSlot()));
connect(unrarProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(finished(int,QProcess::ExitStatus)));
}

void QUnrar::beginUnrarSlot(QSharedPointer<UnrarJob> job)
{
scanCount=0;
currentJob = job;
//-o+ tells unrar to automatically overwrite.
//-p- tells unrar to not prompt for password. Not sure what the outcome will be. think is will probably just end maybe with error?
QStringList parameters;
QString basePath(job->basePath + "/extracted");
parameters << "e" << "-o+" << "-p-" << job->rarPath << basePath;
qDebug() << "unrar launch: " << job->rarPath;

// QDir temp(job->basePath);
unrarProcess->setWorkingDirectory(job->basePath);
unrarProcess->start(QString("unrar"), parameters);
if (!unrarProcess->waitForStarted(500000))
qDebug() << "process didn't start in QUnrar::beginUnrarSlot";
if (logFile.isOpen())
logFile.close();
logFile.setFileName(job->basePath + "/unrarOut.txt");
logFile.open(QIODevice::WriteOnly);
}

void QUnrar::finished(int exitCode, QProcess::ExitStatus exitStatus)
{
logFile.close();
// qDebug() << "inside QUnrar::finished. exitCode is "<< exitCode << " exitStatus is " << exitStatus;
emit endUnrarSignal(currentJob);
currentJob.clear();
}

void QUnrar::readOutputSlot()
{
while (unrarProcess->canReadLine())
{
QByteArray line(unrarProcess->readLine());
// qDebug() << line;
if ((!line.contains('%')) && (!line.trimmed().isEmpty()))
{
line = line.trimmed();
logFile.write(line);
logFile.write("\n");
if (line.contains("Extracting from"))
scanCount++;
//update progress
int PercentComplete;
double WorkPercent;
WorkPercent = scanCount/(double)currentJob->rarCount;
WorkPercent *= 100;
PercentComplete = WorkPercent;
emit UpdateProgressSignal(currentJob->jobId, PercentComplete);
}
}
}

void QUnrar::readErrorSlot()
{
qDebug() << "error doing unrar";
qDebug() << unrarProcess->readAllStandardError();
if (unrarProcess->state() == QProcess::Running)
{
qDebug() << "attempting to terminate qunrarprocess.";
unrarProcess->terminate();
}
}

/////////////////////////////////////

QUnrarThread::QUnrarThread() : QThread(), unrarTest(false)
{
}

void QUnrarThread::run()
{
QUnrar theUnrar;
QUnrar *unrarPointer = &theUnrar;// i did this so the intellisense would show me the sigs and slots.
connect(this, SIGNAL(beginUnrarSignal(QSharedPointer<UnrarJob>)), unrarPointer,
SLOT(beginUnrarSlot(QSharedPointer<UnrarJob>)));
connect(unrarPointer, SIGNAL(endUnrarSignal(QSharedPointer<UnrarJob>)), this,
SLOT(endUnrarSlot(QSharedPointer<UnrarJob>)));
connect(unrarPointer, SIGNAL(UpdateProgressSignal(int,int)), this, SIGNAL(UpdateProgressSignal(int,int)));

exec();
}


void QUnrarThread::addUnrarSlot(QSharedPointer<UnrarJob> job)
{
unrarQueue.enqueue(*job);
sendJob();
}

void QUnrarThread::endUnrarSlot(QSharedPointer<UnrarJob> job)
{
unrarTest = false;
emit unrarDoneSignal(job);
sendJob();
}

void QUnrarThread::sendJob()
{
if (unrarQueue.isEmpty())
return;
if (unrarTest == false)
{
QSharedPointer<UnrarJob> tempJob = QSharedPointer<UnrarJob>(new UnrarJob());
*tempJob = unrarQueue.dequeue();
unrarTest = true;
emit beginUnrarSignal(tempJob);
}
}

mentalmushroom
11th March 2011, 06:34
ok, thank you

continuata
23rd May 2012, 15:26
Hi Tanderson, is there any chance you could provide the rest of the code? (Headers and UnrarJob class etc.)